/** START DEFINE BLOCK for jupyterlab@0.15.1/jupyterlab/build/main.js **/
jupyter.define('jupyterlab@0.15.1/jupyterlab/build/main.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var es6_promise_1 = __jupyter_require__('es6-promise@^3.2.1/dist/es6-promise.js');
	var application_1 = __jupyter_require__('jupyterlab@0.15.1/lib/application/index.js');
	__jupyter_require__('font-awesome@4.6.3/css/font-awesome.min.css');
	__jupyter_require__('jupyterlab@0.15.1/lib/default-theme/index.css');
	es6_promise_1.polyfill();
	/* tslint:disable */
	var mods = [
	    __jupyter_require__('jupyterlab@0.15.1/lib/about/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/application/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/clipboard/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/codemirror/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/commandlinker/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/console/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/csvwidget/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/docmanager/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/editorwidget/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/faq/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/help/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/imagewidget/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/inspector/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/landing/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/launcher/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/mainmenu/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/markdownwidget/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/notebook/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/rendermime/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/running/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/services/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/shortcuts/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/statedb/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/terminal/plugin.js'),
	    __jupyter_require__('jupyterlab@0.15.1/lib/tooltip/plugin.js')
	];
	/* tslint:enable */
	/**
	 * Create an application object.
	 *
	 * @param loader - The module loader for the application.
	 *
	 * @returns A new application object.
	 */
	function createLab(loader) {
	    var lab = new application_1.JupyterLab({
	        loader: loader,
	        gitDescription: ("v0.15.1"),
	        namespace: 'jupyterlab',
	        version: __jupyter_require__('jupyterlab@0.15.1/package.json').version
	    });
	    lab.registerPluginModules(mods);
	    return lab;
	}
	exports.createLab = createLab;
	
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/jupyterlab/build/main.js **/


/** START DEFINE BLOCK for es6-promise@3.2.1/dist/es6-promise.js **/
jupyter.define('es6-promise@3.2.1/dist/es6-promise.js', function (module, exports, __jupyter_require__) {
	var require;var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(process, global, module) {/*!
	 * @overview es6-promise - a tiny implementation of Promises/A+.
	 * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
	 * @license   Licensed under MIT license
	 *            See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
	 * @version   3.2.1
	 */
	
	(function() {
	    "use strict";
	    function lib$es6$promise$utils$$objectOrFunction(x) {
	      return typeof x === 'function' || (typeof x === 'object' && x !== null);
	    }
	
	    function lib$es6$promise$utils$$isFunction(x) {
	      return typeof x === 'function';
	    }
	
	    function lib$es6$promise$utils$$isMaybeThenable(x) {
	      return typeof x === 'object' && x !== null;
	    }
	
	    var lib$es6$promise$utils$$_isArray;
	    if (!Array.isArray) {
	      lib$es6$promise$utils$$_isArray = function (x) {
	        return Object.prototype.toString.call(x) === '[object Array]';
	      };
	    } else {
	      lib$es6$promise$utils$$_isArray = Array.isArray;
	    }
	
	    var lib$es6$promise$utils$$isArray = lib$es6$promise$utils$$_isArray;
	    var lib$es6$promise$asap$$len = 0;
	    var lib$es6$promise$asap$$vertxNext;
	    var lib$es6$promise$asap$$customSchedulerFn;
	
	    var lib$es6$promise$asap$$asap = function asap(callback, arg) {
	      lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len] = callback;
	      lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len + 1] = arg;
	      lib$es6$promise$asap$$len += 2;
	      if (lib$es6$promise$asap$$len === 2) {
	        // If len is 2, that means that we need to schedule an async flush.
	        // If additional callbacks are queued before the queue is flushed, they
	        // will be processed by this flush that we are scheduling.
	        if (lib$es6$promise$asap$$customSchedulerFn) {
	          lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush);
	        } else {
	          lib$es6$promise$asap$$scheduleFlush();
	        }
	      }
	    }
	
	    function lib$es6$promise$asap$$setScheduler(scheduleFn) {
	      lib$es6$promise$asap$$customSchedulerFn = scheduleFn;
	    }
	
	    function lib$es6$promise$asap$$setAsap(asapFn) {
	      lib$es6$promise$asap$$asap = asapFn;
	    }
	
	    var lib$es6$promise$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined;
	    var lib$es6$promise$asap$$browserGlobal = lib$es6$promise$asap$$browserWindow || {};
	    var lib$es6$promise$asap$$BrowserMutationObserver = lib$es6$promise$asap$$browserGlobal.MutationObserver || lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver;
	    var lib$es6$promise$asap$$isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
	
	    // test for web worker but not in IE10
	    var lib$es6$promise$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&
	      typeof importScripts !== 'undefined' &&
	      typeof MessageChannel !== 'undefined';
	
	    // node
	    function lib$es6$promise$asap$$useNextTick() {
	      // node version 0.10.x displays a deprecation warning when nextTick is used recursively
	      // see https://github.com/cujojs/when/issues/410 for details
	      return function() {
	        process.nextTick(lib$es6$promise$asap$$flush);
	      };
	    }
	
	    // vertx
	    function lib$es6$promise$asap$$useVertxTimer() {
	      return function() {
	        lib$es6$promise$asap$$vertxNext(lib$es6$promise$asap$$flush);
	      };
	    }
	
	    function lib$es6$promise$asap$$useMutationObserver() {
	      var iterations = 0;
	      var observer = new lib$es6$promise$asap$$BrowserMutationObserver(lib$es6$promise$asap$$flush);
	      var node = document.createTextNode('');
	      observer.observe(node, { characterData: true });
	
	      return function() {
	        node.data = (iterations = ++iterations % 2);
	      };
	    }
	
	    // web worker
	    function lib$es6$promise$asap$$useMessageChannel() {
	      var channel = new MessageChannel();
	      channel.port1.onmessage = lib$es6$promise$asap$$flush;
	      return function () {
	        channel.port2.postMessage(0);
	      };
	    }
	
	    function lib$es6$promise$asap$$useSetTimeout() {
	      return function() {
	        setTimeout(lib$es6$promise$asap$$flush, 1);
	      };
	    }
	
	    var lib$es6$promise$asap$$queue = new Array(1000);
	    function lib$es6$promise$asap$$flush() {
	      for (var i = 0; i < lib$es6$promise$asap$$len; i+=2) {
	        var callback = lib$es6$promise$asap$$queue[i];
	        var arg = lib$es6$promise$asap$$queue[i+1];
	
	        callback(arg);
	
	        lib$es6$promise$asap$$queue[i] = undefined;
	        lib$es6$promise$asap$$queue[i+1] = undefined;
	      }
	
	      lib$es6$promise$asap$$len = 0;
	    }
	
	    function lib$es6$promise$asap$$attemptVertx() {
	      try {
	        var r = require;
	        var vertx = __jupyter_require__('__ignored__');
	        lib$es6$promise$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext;
	        return lib$es6$promise$asap$$useVertxTimer();
	      } catch(e) {
	        return lib$es6$promise$asap$$useSetTimeout();
	      }
	    }
	
	    var lib$es6$promise$asap$$scheduleFlush;
	    // Decide what async method to use to triggering processing of queued callbacks:
	    if (lib$es6$promise$asap$$isNode) {
	      lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useNextTick();
	    } else if (lib$es6$promise$asap$$BrowserMutationObserver) {
	      lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMutationObserver();
	    } else if (lib$es6$promise$asap$$isWorker) {
	      lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMessageChannel();
	    } else if (lib$es6$promise$asap$$browserWindow === undefined && "function" === 'function') {
	      lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$attemptVertx();
	    } else {
	      lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useSetTimeout();
	    }
	    function lib$es6$promise$then$$then(onFulfillment, onRejection) {
	      var parent = this;
	
	      var child = new this.constructor(lib$es6$promise$$internal$$noop);
	
	      if (child[lib$es6$promise$$internal$$PROMISE_ID] === undefined) {
	        lib$es6$promise$$internal$$makePromise(child);
	      }
	
	      var state = parent._state;
	
	      if (state) {
	        var callback = arguments[state - 1];
	        lib$es6$promise$asap$$asap(function(){
	          lib$es6$promise$$internal$$invokeCallback(state, child, callback, parent._result);
	        });
	      } else {
	        lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection);
	      }
	
	      return child;
	    }
	    var lib$es6$promise$then$$default = lib$es6$promise$then$$then;
	    function lib$es6$promise$promise$resolve$$resolve(object) {
	      /*jshint validthis:true */
	      var Constructor = this;
	
	      if (object && typeof object === 'object' && object.constructor === Constructor) {
	        return object;
	      }
	
	      var promise = new Constructor(lib$es6$promise$$internal$$noop);
	      lib$es6$promise$$internal$$resolve(promise, object);
	      return promise;
	    }
	    var lib$es6$promise$promise$resolve$$default = lib$es6$promise$promise$resolve$$resolve;
	    var lib$es6$promise$$internal$$PROMISE_ID = Math.random().toString(36).substring(16);
	
	    function lib$es6$promise$$internal$$noop() {}
	
	    var lib$es6$promise$$internal$$PENDING   = void 0;
	    var lib$es6$promise$$internal$$FULFILLED = 1;
	    var lib$es6$promise$$internal$$REJECTED  = 2;
	
	    var lib$es6$promise$$internal$$GET_THEN_ERROR = new lib$es6$promise$$internal$$ErrorObject();
	
	    function lib$es6$promise$$internal$$selfFulfillment() {
	      return new TypeError("You cannot resolve a promise with itself");
	    }
	
	    function lib$es6$promise$$internal$$cannotReturnOwn() {
	      return new TypeError('A promises callback cannot return that same promise.');
	    }
	
	    function lib$es6$promise$$internal$$getThen(promise) {
	      try {
	        return promise.then;
	      } catch(error) {
	        lib$es6$promise$$internal$$GET_THEN_ERROR.error = error;
	        return lib$es6$promise$$internal$$GET_THEN_ERROR;
	      }
	    }
	
	    function lib$es6$promise$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) {
	      try {
	        then.call(value, fulfillmentHandler, rejectionHandler);
	      } catch(e) {
	        return e;
	      }
	    }
	
	    function lib$es6$promise$$internal$$handleForeignThenable(promise, thenable, then) {
	       lib$es6$promise$asap$$asap(function(promise) {
	        var sealed = false;
	        var error = lib$es6$promise$$internal$$tryThen(then, thenable, function(value) {
	          if (sealed) { return; }
	          sealed = true;
	          if (thenable !== value) {
	            lib$es6$promise$$internal$$resolve(promise, value);
	          } else {
	            lib$es6$promise$$internal$$fulfill(promise, value);
	          }
	        }, function(reason) {
	          if (sealed) { return; }
	          sealed = true;
	
	          lib$es6$promise$$internal$$reject(promise, reason);
	        }, 'Settle: ' + (promise._label || ' unknown promise'));
	
	        if (!sealed && error) {
	          sealed = true;
	          lib$es6$promise$$internal$$reject(promise, error);
	        }
	      }, promise);
	    }
	
	    function lib$es6$promise$$internal$$handleOwnThenable(promise, thenable) {
	      if (thenable._state === lib$es6$promise$$internal$$FULFILLED) {
	        lib$es6$promise$$internal$$fulfill(promise, thenable._result);
	      } else if (thenable._state === lib$es6$promise$$internal$$REJECTED) {
	        lib$es6$promise$$internal$$reject(promise, thenable._result);
	      } else {
	        lib$es6$promise$$internal$$subscribe(thenable, undefined, function(value) {
	          lib$es6$promise$$internal$$resolve(promise, value);
	        }, function(reason) {
	          lib$es6$promise$$internal$$reject(promise, reason);
	        });
	      }
	    }
	
	    function lib$es6$promise$$internal$$handleMaybeThenable(promise, maybeThenable, then) {
	      if (maybeThenable.constructor === promise.constructor &&
	          then === lib$es6$promise$then$$default &&
	          constructor.resolve === lib$es6$promise$promise$resolve$$default) {
	        lib$es6$promise$$internal$$handleOwnThenable(promise, maybeThenable);
	      } else {
	        if (then === lib$es6$promise$$internal$$GET_THEN_ERROR) {
	          lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$GET_THEN_ERROR.error);
	        } else if (then === undefined) {
	          lib$es6$promise$$internal$$fulfill(promise, maybeThenable);
	        } else if (lib$es6$promise$utils$$isFunction(then)) {
	          lib$es6$promise$$internal$$handleForeignThenable(promise, maybeThenable, then);
	        } else {
	          lib$es6$promise$$internal$$fulfill(promise, maybeThenable);
	        }
	      }
	    }
	
	    function lib$es6$promise$$internal$$resolve(promise, value) {
	      if (promise === value) {
	        lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$selfFulfillment());
	      } else if (lib$es6$promise$utils$$objectOrFunction(value)) {
	        lib$es6$promise$$internal$$handleMaybeThenable(promise, value, lib$es6$promise$$internal$$getThen(value));
	      } else {
	        lib$es6$promise$$internal$$fulfill(promise, value);
	      }
	    }
	
	    function lib$es6$promise$$internal$$publishRejection(promise) {
	      if (promise._onerror) {
	        promise._onerror(promise._result);
	      }
	
	      lib$es6$promise$$internal$$publish(promise);
	    }
	
	    function lib$es6$promise$$internal$$fulfill(promise, value) {
	      if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }
	
	      promise._result = value;
	      promise._state = lib$es6$promise$$internal$$FULFILLED;
	
	      if (promise._subscribers.length !== 0) {
	        lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, promise);
	      }
	    }
	
	    function lib$es6$promise$$internal$$reject(promise, reason) {
	      if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }
	      promise._state = lib$es6$promise$$internal$$REJECTED;
	      promise._result = reason;
	
	      lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publishRejection, promise);
	    }
	
	    function lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection) {
	      var subscribers = parent._subscribers;
	      var length = subscribers.length;
	
	      parent._onerror = null;
	
	      subscribers[length] = child;
	      subscribers[length + lib$es6$promise$$internal$$FULFILLED] = onFulfillment;
	      subscribers[length + lib$es6$promise$$internal$$REJECTED]  = onRejection;
	
	      if (length === 0 && parent._state) {
	        lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, parent);
	      }
	    }
	
	    function lib$es6$promise$$internal$$publish(promise) {
	      var subscribers = promise._subscribers;
	      var settled = promise._state;
	
	      if (subscribers.length === 0) { return; }
	
	      var child, callback, detail = promise._result;
	
	      for (var i = 0; i < subscribers.length; i += 3) {
	        child = subscribers[i];
	        callback = subscribers[i + settled];
	
	        if (child) {
	          lib$es6$promise$$internal$$invokeCallback(settled, child, callback, detail);
	        } else {
	          callback(detail);
	        }
	      }
	
	      promise._subscribers.length = 0;
	    }
	
	    function lib$es6$promise$$internal$$ErrorObject() {
	      this.error = null;
	    }
	
	    var lib$es6$promise$$internal$$TRY_CATCH_ERROR = new lib$es6$promise$$internal$$ErrorObject();
	
	    function lib$es6$promise$$internal$$tryCatch(callback, detail) {
	      try {
	        return callback(detail);
	      } catch(e) {
	        lib$es6$promise$$internal$$TRY_CATCH_ERROR.error = e;
	        return lib$es6$promise$$internal$$TRY_CATCH_ERROR;
	      }
	    }
	
	    function lib$es6$promise$$internal$$invokeCallback(settled, promise, callback, detail) {
	      var hasCallback = lib$es6$promise$utils$$isFunction(callback),
	          value, error, succeeded, failed;
	
	      if (hasCallback) {
	        value = lib$es6$promise$$internal$$tryCatch(callback, detail);
	
	        if (value === lib$es6$promise$$internal$$TRY_CATCH_ERROR) {
	          failed = true;
	          error = value.error;
	          value = null;
	        } else {
	          succeeded = true;
	        }
	
	        if (promise === value) {
	          lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$cannotReturnOwn());
	          return;
	        }
	
	      } else {
	        value = detail;
	        succeeded = true;
	      }
	
	      if (promise._state !== lib$es6$promise$$internal$$PENDING) {
	        // noop
	      } else if (hasCallback && succeeded) {
	        lib$es6$promise$$internal$$resolve(promise, value);
	      } else if (failed) {
	        lib$es6$promise$$internal$$reject(promise, error);
	      } else if (settled === lib$es6$promise$$internal$$FULFILLED) {
	        lib$es6$promise$$internal$$fulfill(promise, value);
	      } else if (settled === lib$es6$promise$$internal$$REJECTED) {
	        lib$es6$promise$$internal$$reject(promise, value);
	      }
	    }
	
	    function lib$es6$promise$$internal$$initializePromise(promise, resolver) {
	      try {
	        resolver(function resolvePromise(value){
	          lib$es6$promise$$internal$$resolve(promise, value);
	        }, function rejectPromise(reason) {
	          lib$es6$promise$$internal$$reject(promise, reason);
	        });
	      } catch(e) {
	        lib$es6$promise$$internal$$reject(promise, e);
	      }
	    }
	
	    var lib$es6$promise$$internal$$id = 0;
	    function lib$es6$promise$$internal$$nextId() {
	      return lib$es6$promise$$internal$$id++;
	    }
	
	    function lib$es6$promise$$internal$$makePromise(promise) {
	      promise[lib$es6$promise$$internal$$PROMISE_ID] = lib$es6$promise$$internal$$id++;
	      promise._state = undefined;
	      promise._result = undefined;
	      promise._subscribers = [];
	    }
	
	    function lib$es6$promise$promise$all$$all(entries) {
	      return new lib$es6$promise$enumerator$$default(this, entries).promise;
	    }
	    var lib$es6$promise$promise$all$$default = lib$es6$promise$promise$all$$all;
	    function lib$es6$promise$promise$race$$race(entries) {
	      /*jshint validthis:true */
	      var Constructor = this;
	
	      if (!lib$es6$promise$utils$$isArray(entries)) {
	        return new Constructor(function(resolve, reject) {
	          reject(new TypeError('You must pass an array to race.'));
	        });
	      } else {
	        return new Constructor(function(resolve, reject) {
	          var length = entries.length;
	          for (var i = 0; i < length; i++) {
	            Constructor.resolve(entries[i]).then(resolve, reject);
	          }
	        });
	      }
	    }
	    var lib$es6$promise$promise$race$$default = lib$es6$promise$promise$race$$race;
	    function lib$es6$promise$promise$reject$$reject(reason) {
	      /*jshint validthis:true */
	      var Constructor = this;
	      var promise = new Constructor(lib$es6$promise$$internal$$noop);
	      lib$es6$promise$$internal$$reject(promise, reason);
	      return promise;
	    }
	    var lib$es6$promise$promise$reject$$default = lib$es6$promise$promise$reject$$reject;
	
	
	    function lib$es6$promise$promise$$needsResolver() {
	      throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
	    }
	
	    function lib$es6$promise$promise$$needsNew() {
	      throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
	    }
	
	    var lib$es6$promise$promise$$default = lib$es6$promise$promise$$Promise;
	    /**
	      Promise objects represent the eventual result of an asynchronous operation. The
	      primary way of interacting with a promise is through its `then` method, which
	      registers callbacks to receive either a promise's eventual value or the reason
	      why the promise cannot be fulfilled.
	
	      Terminology
	      -----------
	
	      - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
	      - `thenable` is an object or function that defines a `then` method.
	      - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
	      - `exception` is a value that is thrown using the throw statement.
	      - `reason` is a value that indicates why a promise was rejected.
	      - `settled` the final resting state of a promise, fulfilled or rejected.
	
	      A promise can be in one of three states: pending, fulfilled, or rejected.
	
	      Promises that are fulfilled have a fulfillment value and are in the fulfilled
	      state.  Promises that are rejected have a rejection reason and are in the
	      rejected state.  A fulfillment value is never a thenable.
	
	      Promises can also be said to *resolve* a value.  If this value is also a
	      promise, then the original promise's settled state will match the value's
	      settled state.  So a promise that *resolves* a promise that rejects will
	      itself reject, and a promise that *resolves* a promise that fulfills will
	      itself fulfill.
	
	
	      Basic Usage:
	      ------------
	
	      ```js
	      var promise = new Promise(function(resolve, reject) {
	        // on success
	        resolve(value);
	
	        // on failure
	        reject(reason);
	      });
	
	      promise.then(function(value) {
	        // on fulfillment
	      }, function(reason) {
	        // on rejection
	      });
	      ```
	
	      Advanced Usage:
	      ---------------
	
	      Promises shine when abstracting away asynchronous interactions such as
	      `XMLHttpRequest`s.
	
	      ```js
	      function getJSON(url) {
	        return new Promise(function(resolve, reject){
	          var xhr = new XMLHttpRequest();
	
	          xhr.open('GET', url);
	          xhr.onreadystatechange = handler;
	          xhr.responseType = 'json';
	          xhr.setRequestHeader('Accept', 'application/json');
	          xhr.send();
	
	          function handler() {
	            if (this.readyState === this.DONE) {
	              if (this.status === 200) {
	                resolve(this.response);
	              } else {
	                reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
	              }
	            }
	          };
	        });
	      }
	
	      getJSON('/posts.json').then(function(json) {
	        // on fulfillment
	      }, function(reason) {
	        // on rejection
	      });
	      ```
	
	      Unlike callbacks, promises are great composable primitives.
	
	      ```js
	      Promise.all([
	        getJSON('/posts'),
	        getJSON('/comments')
	      ]).then(function(values){
	        values[0] // => postsJSON
	        values[1] // => commentsJSON
	
	        return values;
	      });
	      ```
	
	      @class Promise
	      @param {function} resolver
	      Useful for tooling.
	      @constructor
	    */
	    function lib$es6$promise$promise$$Promise(resolver) {
	      this[lib$es6$promise$$internal$$PROMISE_ID] = lib$es6$promise$$internal$$nextId();
	      this._result = this._state = undefined;
	      this._subscribers = [];
	
	      if (lib$es6$promise$$internal$$noop !== resolver) {
	        typeof resolver !== 'function' && lib$es6$promise$promise$$needsResolver();
	        this instanceof lib$es6$promise$promise$$Promise ? lib$es6$promise$$internal$$initializePromise(this, resolver) : lib$es6$promise$promise$$needsNew();
	      }
	    }
	
	    lib$es6$promise$promise$$Promise.all = lib$es6$promise$promise$all$$default;
	    lib$es6$promise$promise$$Promise.race = lib$es6$promise$promise$race$$default;
	    lib$es6$promise$promise$$Promise.resolve = lib$es6$promise$promise$resolve$$default;
	    lib$es6$promise$promise$$Promise.reject = lib$es6$promise$promise$reject$$default;
	    lib$es6$promise$promise$$Promise._setScheduler = lib$es6$promise$asap$$setScheduler;
	    lib$es6$promise$promise$$Promise._setAsap = lib$es6$promise$asap$$setAsap;
	    lib$es6$promise$promise$$Promise._asap = lib$es6$promise$asap$$asap;
	
	    lib$es6$promise$promise$$Promise.prototype = {
	      constructor: lib$es6$promise$promise$$Promise,
	
	    /**
	      The primary way of interacting with a promise is through its `then` method,
	      which registers callbacks to receive either a promise's eventual value or the
	      reason why the promise cannot be fulfilled.
	
	      ```js
	      findUser().then(function(user){
	        // user is available
	      }, function(reason){
	        // user is unavailable, and you are given the reason why
	      });
	      ```
	
	      Chaining
	      --------
	
	      The return value of `then` is itself a promise.  This second, 'downstream'
	      promise is resolved with the return value of the first promise's fulfillment
	      or rejection handler, or rejected if the handler throws an exception.
	
	      ```js
	      findUser().then(function (user) {
	        return user.name;
	      }, function (reason) {
	        return 'default name';
	      }).then(function (userName) {
	        // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
	        // will be `'default name'`
	      });
	
	      findUser().then(function (user) {
	        throw new Error('Found user, but still unhappy');
	      }, function (reason) {
	        throw new Error('`findUser` rejected and we're unhappy');
	      }).then(function (value) {
	        // never reached
	      }, function (reason) {
	        // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
	        // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
	      });
	      ```
	      If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
	
	      ```js
	      findUser().then(function (user) {
	        throw new PedagogicalException('Upstream error');
	      }).then(function (value) {
	        // never reached
	      }).then(function (value) {
	        // never reached
	      }, function (reason) {
	        // The `PedgagocialException` is propagated all the way down to here
	      });
	      ```
	
	      Assimilation
	      ------------
	
	      Sometimes the value you want to propagate to a downstream promise can only be
	      retrieved asynchronously. This can be achieved by returning a promise in the
	      fulfillment or rejection handler. The downstream promise will then be pending
	      until the returned promise is settled. This is called *assimilation*.
	
	      ```js
	      findUser().then(function (user) {
	        return findCommentsByAuthor(user);
	      }).then(function (comments) {
	        // The user's comments are now available
	      });
	      ```
	
	      If the assimliated promise rejects, then the downstream promise will also reject.
	
	      ```js
	      findUser().then(function (user) {
	        return findCommentsByAuthor(user);
	      }).then(function (comments) {
	        // If `findCommentsByAuthor` fulfills, we'll have the value here
	      }, function (reason) {
	        // If `findCommentsByAuthor` rejects, we'll have the reason here
	      });
	      ```
	
	      Simple Example
	      --------------
	
	      Synchronous Example
	
	      ```javascript
	      var result;
	
	      try {
	        result = findResult();
	        // success
	      } catch(reason) {
	        // failure
	      }
	      ```
	
	      Errback Example
	
	      ```js
	      findResult(function(result, err){
	        if (err) {
	          // failure
	        } else {
	          // success
	        }
	      });
	      ```
	
	      Promise Example;
	
	      ```javascript
	      findResult().then(function(result){
	        // success
	      }, function(reason){
	        // failure
	      });
	      ```
	
	      Advanced Example
	      --------------
	
	      Synchronous Example
	
	      ```javascript
	      var author, books;
	
	      try {
	        author = findAuthor();
	        books  = findBooksByAuthor(author);
	        // success
	      } catch(reason) {
	        // failure
	      }
	      ```
	
	      Errback Example
	
	      ```js
	
	      function foundBooks(books) {
	
	      }
	
	      function failure(reason) {
	
	      }
	
	      findAuthor(function(author, err){
	        if (err) {
	          failure(err);
	          // failure
	        } else {
	          try {
	            findBoooksByAuthor(author, function(books, err) {
	              if (err) {
	                failure(err);
	              } else {
	                try {
	                  foundBooks(books);
	                } catch(reason) {
	                  failure(reason);
	                }
	              }
	            });
	          } catch(error) {
	            failure(err);
	          }
	          // success
	        }
	      });
	      ```
	
	      Promise Example;
	
	      ```javascript
	      findAuthor().
	        then(findBooksByAuthor).
	        then(function(books){
	          // found books
	      }).catch(function(reason){
	        // something went wrong
	      });
	      ```
	
	      @method then
	      @param {Function} onFulfilled
	      @param {Function} onRejected
	      Useful for tooling.
	      @return {Promise}
	    */
	      then: lib$es6$promise$then$$default,
	
	    /**
	      `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
	      as the catch block of a try/catch statement.
	
	      ```js
	      function findAuthor(){
	        throw new Error('couldn't find that author');
	      }
	
	      // synchronous
	      try {
	        findAuthor();
	      } catch(reason) {
	        // something went wrong
	      }
	
	      // async with promises
	      findAuthor().catch(function(reason){
	        // something went wrong
	      });
	      ```
	
	      @method catch
	      @param {Function} onRejection
	      Useful for tooling.
	      @return {Promise}
	    */
	      'catch': function(onRejection) {
	        return this.then(null, onRejection);
	      }
	    };
	    var lib$es6$promise$enumerator$$default = lib$es6$promise$enumerator$$Enumerator;
	    function lib$es6$promise$enumerator$$Enumerator(Constructor, input) {
	      this._instanceConstructor = Constructor;
	      this.promise = new Constructor(lib$es6$promise$$internal$$noop);
	
	      if (!this.promise[lib$es6$promise$$internal$$PROMISE_ID]) {
	        lib$es6$promise$$internal$$makePromise(this.promise);
	      }
	
	      if (lib$es6$promise$utils$$isArray(input)) {
	        this._input     = input;
	        this.length     = input.length;
	        this._remaining = input.length;
	
	        this._result = new Array(this.length);
	
	        if (this.length === 0) {
	          lib$es6$promise$$internal$$fulfill(this.promise, this._result);
	        } else {
	          this.length = this.length || 0;
	          this._enumerate();
	          if (this._remaining === 0) {
	            lib$es6$promise$$internal$$fulfill(this.promise, this._result);
	          }
	        }
	      } else {
	        lib$es6$promise$$internal$$reject(this.promise, lib$es6$promise$enumerator$$validationError());
	      }
	    }
	
	    function lib$es6$promise$enumerator$$validationError() {
	      return new Error('Array Methods must be provided an Array');
	    }
	
	    lib$es6$promise$enumerator$$Enumerator.prototype._enumerate = function() {
	      var length  = this.length;
	      var input   = this._input;
	
	      for (var i = 0; this._state === lib$es6$promise$$internal$$PENDING && i < length; i++) {
	        this._eachEntry(input[i], i);
	      }
	    };
	
	    lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) {
	      var c = this._instanceConstructor;
	      var resolve = c.resolve;
	
	      if (resolve === lib$es6$promise$promise$resolve$$default) {
	        var then = lib$es6$promise$$internal$$getThen(entry);
	
	        if (then === lib$es6$promise$then$$default &&
	            entry._state !== lib$es6$promise$$internal$$PENDING) {
	          this._settledAt(entry._state, i, entry._result);
	        } else if (typeof then !== 'function') {
	          this._remaining--;
	          this._result[i] = entry;
	        } else if (c === lib$es6$promise$promise$$default) {
	          var promise = new c(lib$es6$promise$$internal$$noop);
	          lib$es6$promise$$internal$$handleMaybeThenable(promise, entry, then);
	          this._willSettleAt(promise, i);
	        } else {
	          this._willSettleAt(new c(function(resolve) { resolve(entry); }), i);
	        }
	      } else {
	        this._willSettleAt(resolve(entry), i);
	      }
	    };
	
	    lib$es6$promise$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) {
	      var promise = this.promise;
	
	      if (promise._state === lib$es6$promise$$internal$$PENDING) {
	        this._remaining--;
	
	        if (state === lib$es6$promise$$internal$$REJECTED) {
	          lib$es6$promise$$internal$$reject(promise, value);
	        } else {
	          this._result[i] = value;
	        }
	      }
	
	      if (this._remaining === 0) {
	        lib$es6$promise$$internal$$fulfill(promise, this._result);
	      }
	    };
	
	    lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) {
	      var enumerator = this;
	
	      lib$es6$promise$$internal$$subscribe(promise, undefined, function(value) {
	        enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED, i, value);
	      }, function(reason) {
	        enumerator._settledAt(lib$es6$promise$$internal$$REJECTED, i, reason);
	      });
	    };
	    function lib$es6$promise$polyfill$$polyfill() {
	      var local;
	
	      if (typeof global !== 'undefined') {
	          local = global;
	      } else if (typeof self !== 'undefined') {
	          local = self;
	      } else {
	          try {
	              local = Function('return this')();
	          } catch (e) {
	              throw new Error('polyfill failed because global object is unavailable in this environment');
	          }
	      }
	
	      var P = local.Promise;
	
	      if (P && Object.prototype.toString.call(P.resolve()) === '[object Promise]' && !P.cast) {
	        return;
	      }
	
	      local.Promise = lib$es6$promise$promise$$default;
	    }
	    var lib$es6$promise$polyfill$$default = lib$es6$promise$polyfill$$polyfill;
	
	    var lib$es6$promise$umd$$ES6Promise = {
	      'Promise': lib$es6$promise$promise$$default,
	      'polyfill': lib$es6$promise$polyfill$$default
	    };
	
	    /* global define:true module:true window: true */
	    if ("function" === 'function' && __jupyter_require__('webpack@1.14.0/buildin/amd-define.js')['amd']) {
	      !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { return lib$es6$promise$umd$$ES6Promise; }.call(exports, __jupyter_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	    } else if (typeof module !== 'undefined' && module['exports']) {
	      module['exports'] = lib$es6$promise$umd$$ES6Promise;
	    } else if (typeof this !== 'undefined') {
	      this['ES6Promise'] = lib$es6$promise$umd$$ES6Promise;
	    }
	
	    lib$es6$promise$polyfill$$default();
	}).call(this);
	
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('process@0.11.9/browser.js'), (function() { return this; }()), __jupyter_require__('webpack@1.14.0/buildin/module.js')(module)))
})
/** END DEFINE BLOCK for es6-promise@3.2.1/dist/es6-promise.js **/


/** START DEFINE BLOCK for process@0.11.9/browser.js **/
jupyter.define('process@0.11.9/browser.js', function (module, exports, __jupyter_require__) {
	// shim for using process in browser
	var process = module.exports = {};
	
	// cached from whatever global is present so that test runners that stub it
	// don't break things.  But we need to wrap it in a try catch in case it is
	// wrapped in strict mode code which doesn't define any globals.  It's inside a
	// function because try/catches deoptimize in certain engines.
	
	var cachedSetTimeout;
	var cachedClearTimeout;
	
	function defaultSetTimout() {
	    throw new Error('setTimeout has not been defined');
	}
	function defaultClearTimeout () {
	    throw new Error('clearTimeout has not been defined');
	}
	(function () {
	    try {
	        if (typeof setTimeout === 'function') {
	            cachedSetTimeout = setTimeout;
	        } else {
	            cachedSetTimeout = defaultSetTimout;
	        }
	    } catch (e) {
	        cachedSetTimeout = defaultSetTimout;
	    }
	    try {
	        if (typeof clearTimeout === 'function') {
	            cachedClearTimeout = clearTimeout;
	        } else {
	            cachedClearTimeout = defaultClearTimeout;
	        }
	    } catch (e) {
	        cachedClearTimeout = defaultClearTimeout;
	    }
	} ())
	function runTimeout(fun) {
	    if (cachedSetTimeout === setTimeout) {
	        //normal enviroments in sane situations
	        return setTimeout(fun, 0);
	    }
	    // if setTimeout wasn't available but was latter defined
	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
	        cachedSetTimeout = setTimeout;
	        return setTimeout(fun, 0);
	    }
	    try {
	        // when when somebody has screwed with setTimeout but no I.E. maddness
	        return cachedSetTimeout(fun, 0);
	    } catch(e){
	        try {
	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
	            return cachedSetTimeout.call(null, fun, 0);
	        } catch(e){
	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
	            return cachedSetTimeout.call(this, fun, 0);
	        }
	    }
	
	
	}
	function runClearTimeout(marker) {
	    if (cachedClearTimeout === clearTimeout) {
	        //normal enviroments in sane situations
	        return clearTimeout(marker);
	    }
	    // if clearTimeout wasn't available but was latter defined
	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
	        cachedClearTimeout = clearTimeout;
	        return clearTimeout(marker);
	    }
	    try {
	        // when when somebody has screwed with setTimeout but no I.E. maddness
	        return cachedClearTimeout(marker);
	    } catch (e){
	        try {
	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
	            return cachedClearTimeout.call(null, marker);
	        } catch (e){
	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
	            return cachedClearTimeout.call(this, marker);
	        }
	    }
	
	
	
	}
	var queue = [];
	var draining = false;
	var currentQueue;
	var queueIndex = -1;
	
	function cleanUpNextTick() {
	    if (!draining || !currentQueue) {
	        return;
	    }
	    draining = false;
	    if (currentQueue.length) {
	        queue = currentQueue.concat(queue);
	    } else {
	        queueIndex = -1;
	    }
	    if (queue.length) {
	        drainQueue();
	    }
	}
	
	function drainQueue() {
	    if (draining) {
	        return;
	    }
	    var timeout = runTimeout(cleanUpNextTick);
	    draining = true;
	
	    var len = queue.length;
	    while(len) {
	        currentQueue = queue;
	        queue = [];
	        while (++queueIndex < len) {
	            if (currentQueue) {
	                currentQueue[queueIndex].run();
	            }
	        }
	        queueIndex = -1;
	        len = queue.length;
	    }
	    currentQueue = null;
	    draining = false;
	    runClearTimeout(timeout);
	}
	
	process.nextTick = function (fun) {
	    var args = new Array(arguments.length - 1);
	    if (arguments.length > 1) {
	        for (var i = 1; i < arguments.length; i++) {
	            args[i - 1] = arguments[i];
	        }
	    }
	    queue.push(new Item(fun, args));
	    if (queue.length === 1 && !draining) {
	        runTimeout(drainQueue);
	    }
	};
	
	// v8 likes predictible objects
	function Item(fun, array) {
	    this.fun = fun;
	    this.array = array;
	}
	Item.prototype.run = function () {
	    this.fun.apply(null, this.array);
	};
	process.title = 'browser';
	process.browser = true;
	process.env = {};
	process.argv = [];
	process.version = ''; // empty string to avoid regexp issues
	process.versions = {};
	
	function noop() {}
	
	process.on = noop;
	process.addListener = noop;
	process.once = noop;
	process.off = noop;
	process.removeListener = noop;
	process.removeAllListeners = noop;
	process.emit = noop;
	
	process.binding = function (name) {
	    throw new Error('process.binding is not supported');
	};
	
	process.cwd = function () { return '/' };
	process.chdir = function (dir) {
	    throw new Error('process.chdir is not supported');
	};
	process.umask = function() { return 0; };
	
})
/** END DEFINE BLOCK for process@0.11.9/browser.js **/


/** START DEFINE BLOCK for webpack@1.14.0/buildin/module.js **/
jupyter.define('webpack@1.14.0/buildin/module.js', function (module, exports, __jupyter_require__) {
	module.exports = function(module) {
		if(!module.webpackPolyfill) {
			module.deprecate = function() {};
			module.paths = [];
			// module.parent = undefined by default
			module.children = [];
			module.webpackPolyfill = 1;
		}
		return module;
	}
	
})
/** END DEFINE BLOCK for webpack@1.14.0/buildin/module.js **/


/** START DEFINE BLOCK for __ignored__ **/
jupyter.define('__ignored__', function (module, exports, __jupyter_require__) {
	/* (ignored) */
})
/** END DEFINE BLOCK for __ignored__ **/


/** START DEFINE BLOCK for webpack@1.14.0/buildin/amd-define.js **/
jupyter.define('webpack@1.14.0/buildin/amd-define.js', function (module, exports, __jupyter_require__) {
	module.exports = function() { throw new Error("define cannot be used indirect"); };
	
})
/** END DEFINE BLOCK for webpack@1.14.0/buildin/amd-define.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/application/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/application/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var application_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/application.js');
	var shell_1 = __jupyter_require__('jupyterlab@0.15.1/lib/application/shell.js');
	var loader_1 = __jupyter_require__('jupyterlab@0.15.1/lib/application/loader.js');
	exports.ModuleLoader = loader_1.ModuleLoader;
	var shell_2 = __jupyter_require__('jupyterlab@0.15.1/lib/application/shell.js');
	exports.ApplicationShell = shell_2.ApplicationShell;
	/**
	 * The command IDs used by the application plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.closeAll = 'main-jupyterlab:close-all';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	/**
	 * JupyterLab is the main application class. It is instantiated once and shared.
	 */
	var JupyterLab = (function (_super) {
	    __extends(JupyterLab, _super);
	    /**
	     * Construct a new JupyterLab object.
	     */
	    function JupyterLab(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this);
	        this._isStarted = false;
	        this._startedDelegate = new services_1.utils.PromiseDelegate();
	        this._info = {
	            gitDescription: options.gitDescription || 'unknown',
	            namespace: options.namespace || 'jupyterlab',
	            version: options.version || 'unknown'
	        };
	        this._loader = options.loader || null;
	    }
	    Object.defineProperty(JupyterLab.prototype, "info", {
	        /**
	         * The information about the application.
	         */
	        get: function () {
	            return this._info;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(JupyterLab.prototype, "loader", {
	        /**
	         * The module loader used by the application.
	         */
	        get: function () {
	            return this._loader;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(JupyterLab.prototype, "restored", {
	        /**
	         * Promise that resolves when state is restored, returning layout description.
	         *
	         * #### Notes
	         * This is just a reference to `shell.restored`.
	         */
	        get: function () {
	            return this.shell.restored;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(JupyterLab.prototype, "started", {
	        /**
	         * A promise that resolves when the JupyterLab application is started.
	         */
	        get: function () {
	            return this._startedDelegate.promise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Start the JupyterLab application.
	     */
	    JupyterLab.prototype.start = function (options) {
	        var _this = this;
	        if (options === void 0) { options = {}; }
	        if (this._isStarted) {
	            return Promise.resolve(void 0);
	        }
	        this._isStarted = true;
	        return _super.prototype.start.call(this, options).then(function () {
	            _this._startedDelegate.resolve(void 0);
	        });
	    };
	    /**
	     * Register plugins from a plugin module.
	     *
	     * @param mod - The plugin module to register.
	     */
	    JupyterLab.prototype.registerPluginModule = function (mod) {
	        var _this = this;
	        var data = mod.default;
	        if (!Array.isArray(data)) {
	            data = [data];
	        }
	        data.forEach(function (item) { _this.registerPlugin(item); });
	    };
	    /**
	     * Register the plugins from multiple plugin modules.
	     *
	     * @param mods - The plugin modules to register.
	     */
	    JupyterLab.prototype.registerPluginModules = function (mods) {
	        var _this = this;
	        mods.forEach(function (mod) { _this.registerPluginModule(mod); });
	    };
	    /**
	     * Create the application shell for the JupyterLab application.
	     */
	    JupyterLab.prototype.createShell = function () {
	        return new shell_1.ApplicationShell();
	    };
	    return JupyterLab;
	}(application_1.Application));
	exports.JupyterLab = JupyterLab;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/application/index.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/index.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/config/index.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/contents/index.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/index.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/manager.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/nbformat.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/session/index.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/terminal/index.js'));
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	exports.utils = utils;
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/index.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/config/index.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/config/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	/**
	 * The url for the config service.
	 */
	var SERVICE_CONFIG_URL = 'api/config';
	/**
	 * The namespace for ConfigSection statics.
	 */
	var ConfigSection;
	(function (ConfigSection) {
	    /**
	     * Create a config section.
	     *
	     * @returns A Promise that is fulfilled with the config section is loaded.
	     */
	    function create(options) {
	        var section = new DefaultConfigSection(options);
	        return section.load().then(function () {
	            return section;
	        });
	    }
	    ConfigSection.create = create;
	})(ConfigSection = exports.ConfigSection || (exports.ConfigSection = {}));
	/**
	 * Implementation of the Configurable data section.
	 */
	var DefaultConfigSection = (function () {
	    /**
	     * Construct a new config section.
	     */
	    function DefaultConfigSection(options) {
	        this._url = 'unknown';
	        this._data = null;
	        this._ajaxSettings = null;
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        this.ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        this._url = utils.urlPathJoin(baseUrl, SERVICE_CONFIG_URL, encodeURIComponent(options.name));
	    }
	    Object.defineProperty(DefaultConfigSection.prototype, "ajaxSettings", {
	        /**
	         * Get a copy of the default ajax settings for the section.
	         */
	        get: function () {
	            return utils.copy(this._ajaxSettings);
	        },
	        /**
	         * Set the default ajax settings for the section.
	         */
	        set: function (value) {
	            this._ajaxSettings = utils.copy(value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultConfigSection.prototype, "data", {
	        /**
	         * Get the data for this section.
	         */
	        get: function () {
	            return this._data;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Load the initial data for this section.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/config).
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     */
	    DefaultConfigSection.prototype.load = function () {
	        var _this = this;
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'GET';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(this._url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            _this._data = success.data;
	        });
	    };
	    /**
	     * Modify the stored config values.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/config).
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     *
	     * Updates the local data immediately, sends the change to the server,
	     * and updates the local data with the response, and fulfils the promise
	     * with that data.
	     */
	    DefaultConfigSection.prototype.update = function (newdata) {
	        var _this = this;
	        this._data = utils.extend(this._data, newdata);
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'PATCH';
	        ajaxSettings.data = JSON.stringify(newdata);
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.contentType = 'application/json';
	        return utils.ajaxRequest(this._url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            _this._data = success.data;
	            return _this._data;
	        });
	    };
	    return DefaultConfigSection;
	}());
	/**
	 * Configurable object with defaults.
	 */
	var ConfigWithDefaults = (function () {
	    /**
	     * Create a new config with defaults.
	     */
	    function ConfigWithDefaults(options) {
	        this._section = null;
	        this._defaults = null;
	        this._className = '';
	        this._section = options.section;
	        this._defaults = options.defaults || {};
	        this._className = options.className || '';
	    }
	    /**
	     * Get data from the config section or fall back to defaults.
	     */
	    ConfigWithDefaults.prototype.get = function (key) {
	        var data = this._classData();
	        return key in data ? data[key] : this._defaults[key];
	    };
	    /**
	     * Set a config value.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/config).
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     *
	     * Sends the update to the server, and changes our local copy of the data
	     * immediately.
	     */
	    ConfigWithDefaults.prototype.set = function (key, value) {
	        var d = {};
	        d[key] = value;
	        if (this._className) {
	            var d2 = {};
	            d2[this._className] = d;
	            return this._section.update(d2);
	        }
	        else {
	            return this._section.update(d);
	        }
	    };
	    /**
	     * Get data from the Section with our classname, if available.
	     *
	     * #### Notes
	     * If we have no classname, get all of the data in the Section
	     */
	    ConfigWithDefaults.prototype._classData = function () {
	        var data = this._section.data;
	        if (this._className && this._className in data) {
	            return data[this._className];
	        }
	        return data;
	    };
	    return ConfigWithDefaults;
	}());
	exports.ConfigWithDefaults = ConfigWithDefaults;
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/config/index.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/utils.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/utils.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(process) {// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	'use strict';
	var minimist = __jupyter_require__('minimist@^1.2.0/index.js');
	var url = __jupyter_require__('url@^0.11.0/url.js');
	var urljoin = __jupyter_require__('url-join@^1.1.0/lib/url-join.js');
	/**
	 * Copy the contents of one object to another, recursively.
	 *
	 * From [stackoverflow](http://stackoverflow.com/a/12317051).
	 */
	function extend(target, source) {
	    target = target || {};
	    for (var prop in source) {
	        if (typeof source[prop] === 'object') {
	            target[prop] = extend(target[prop], source[prop]);
	        }
	        else {
	            target[prop] = source[prop];
	        }
	    }
	    return target;
	}
	exports.extend = extend;
	/**
	 * Get a deep copy of a JSON object.
	 */
	function copy(object) {
	    return JSON.parse(JSON.stringify(object));
	}
	exports.copy = copy;
	/**
	 * Get a random 32 character hex string (not a formal UUID)
	 */
	function uuid() {
	    var s = [];
	    var hexDigits = '0123456789abcdef';
	    var nChars = hexDigits.length;
	    for (var i = 0; i < 32; i++) {
	        s[i] = hexDigits.charAt(Math.floor(Math.random() * nChars));
	    }
	    return s.join('');
	}
	exports.uuid = uuid;
	/**
	 * Parse a url into a URL object.
	 *
	 * @param urlString - The URL string to parse.
	 *
	 * @param parseQueryString - If `true`, the query property will always be set
	 *   to an object returned by the `querystring` module's `parse()` method.
	 *   If `false`, the `query` property on the returned URL object will be an
	 *   unparsed, undecoded string. Defaults to `false`.
	 *
	 * @param slashedDenoteHost - If `true`, the first token after the literal
	 *   string `//` and preceeding the next `/` will be interpreted as the `host`.
	 *   For instance, given `//foo/bar`, the result would be
	 *   `{host: 'foo', pathname: '/bar'}` rather than `{pathname: '//foo/bar'}`.
	 *   Defaults to `false`.
	 *
	 * @returns A URL object.
	 */
	function urlParse(urlStr, parseQueryString, slashesDenoteHost) {
	    return url.parse(urlStr, parseQueryString, slashesDenoteHost);
	}
	exports.urlParse = urlParse;
	/**
	 * Resolve a url.
	 *
	 * Take a base URL, and a href URL, and resolve them as a browser would for
	 * an anchor tag.
	 */
	function urlResolve(from, to) {
	    return url.resolve(from, to);
	}
	exports.urlResolve = urlResolve;
	/**
	 * Join a sequence of url components and normalizes as in node `path.join`.
	 */
	function urlPathJoin() {
	    var parts = [];
	    for (var _i = 0; _i < arguments.length; _i++) {
	        parts[_i - 0] = arguments[_i];
	    }
	    return urljoin.apply(void 0, parts);
	}
	exports.urlPathJoin = urlPathJoin;
	/**
	 * Encode the components of a multi-segment url.
	 *
	 * #### Notes
	 * Preserves the `'/'` separators.
	 * Should not include the base url, since all parts are escaped.
	 */
	function urlEncodeParts(uri) {
	    // Normalize and join, split, encode, then join.
	    uri = urljoin(uri);
	    var parts = uri.split('/').map(encodeURIComponent);
	    return urljoin.apply(void 0, parts);
	}
	exports.urlEncodeParts = urlEncodeParts;
	/**
	 * Return a serialized object string suitable for a query.
	 *
	 * From [stackoverflow](http://stackoverflow.com/a/30707423).
	 */
	function jsonToQueryString(json) {
	    return '?' + Object.keys(json).map(function (key) {
	        return encodeURIComponent(key) + '=' + encodeURIComponent(String(json[key]));
	    }).join('&');
	}
	exports.jsonToQueryString = jsonToQueryString;
	function _getCookie(name) {
	    // from tornado docs: http://www.tornadoweb.org/en/stable/guide/security.html
	    var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
	    return r ? r[1] : void 0;
	}
	/**
	 * Asynchronous XMLHTTPRequest handler.
	 *
	 * @param url - The url to request.
	 *
	 * @param settings - The settings to apply to the request and response.
	 *
	 * #### Notes
	 * Based on this [example](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest).
	 */
	function ajaxRequest(url, ajaxSettings) {
	    var method = ajaxSettings.method || 'GET';
	    // Ensure that requests have applied data.
	    if (!ajaxSettings.data) {
	        ajaxSettings.data = '{}';
	        ajaxSettings.contentType = 'application/json';
	    }
	    var user = ajaxSettings.user || '';
	    var password = ajaxSettings.password || '';
	    var headers = ajaxSettings.requestHeaders || {};
	    if (!ajaxSettings.cache) {
	        // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache.
	        url += ((/\?/).test(url) ? '&' : '?') + (new Date()).getTime();
	    }
	    return new Promise(function (resolve, reject) {
	        var xhr = new XMLHttpRequest();
	        xhr.open(method, url, true, user, password);
	        if (ajaxSettings.contentType !== void 0) {
	            xhr.setRequestHeader('Content-Type', ajaxSettings.contentType);
	        }
	        if (ajaxSettings.timeout !== void 0) {
	            xhr.timeout = ajaxSettings.timeout;
	        }
	        if (!!ajaxSettings.withCredentials) {
	            xhr.withCredentials = true;
	        }
	        // Try to add the xsrf token if there is no existing authorization.
	        var token = headers['Authorization'];
	        if (!token && typeof document !== 'undefined' && document.cookie) {
	            var xsrfToken = _getCookie('_xsrf');
	            if (xsrfToken !== void 0) {
	                xhr.setRequestHeader('X-XSRFToken', xsrfToken);
	            }
	        }
	        for (var prop in headers) {
	            xhr.setRequestHeader(prop, headers[prop]);
	        }
	        xhr.onload = function (event) {
	            if (xhr.status >= 300) {
	                reject({ event: event, xhr: xhr, ajaxSettings: ajaxSettings, throwError: xhr.statusText });
	            }
	            var data = xhr.responseText;
	            try {
	                data = JSON.parse(data);
	            }
	            catch (err) {
	            }
	            resolve({ xhr: xhr, ajaxSettings: ajaxSettings, data: data, event: event });
	        };
	        xhr.onabort = function (event) {
	            reject({ xhr: xhr, event: event, ajaxSettings: ajaxSettings });
	        };
	        xhr.onerror = function (event) {
	            reject({ xhr: xhr, event: event, ajaxSettings: ajaxSettings });
	        };
	        xhr.ontimeout = function (ev) {
	            reject({ xhr: xhr, event: event, ajaxSettings: ajaxSettings });
	        };
	        if (ajaxSettings.data) {
	            xhr.send(ajaxSettings.data);
	        }
	        else {
	            xhr.send();
	        }
	    });
	}
	exports.ajaxRequest = ajaxRequest;
	/**
	 * Create an ajax error from an ajax success.
	 *
	 * @param success - The original success object.
	 *
	 * @param throwError - The optional new error name.  If not given
	 *  we use "Invalid Status: <xhr.status>"
	 */
	function makeAjaxError(success, throwError) {
	    var xhr = success.xhr;
	    var ajaxSettings = success.ajaxSettings;
	    var event = success.event;
	    throwError = throwError || "Invalid Status: " + xhr.status;
	    return Promise.reject({ xhr: xhr, ajaxSettings: ajaxSettings, event: event, throwError: throwError });
	}
	exports.makeAjaxError = makeAjaxError;
	/**
	 * Try to load an object from a module or a registry.
	 *
	 * Try to load an object from a module asynchronously if a module
	 * is specified, otherwise tries to load an object from the global
	 * registry, if the global registry is provided.
	 */
	function loadObject(name, moduleName, registry) {
	    return new Promise(function (resolve, reject) {
	        // Try loading the view module using require.js
	        if (moduleName) {
	            if (typeof requirejs === 'undefined') {
	                throw new Error('requirejs not found');
	            }
	            requirejs([moduleName], function (mod) {
	                if (mod[name] === void 0) {
	                    var msg = "Object '" + name + "' not found in module '" + moduleName + "'";
	                    reject(new Error(msg));
	                }
	                else {
	                    resolve(mod[name]);
	                }
	            }, reject);
	        }
	        else {
	            if (registry && registry[name]) {
	                resolve(registry[name]);
	            }
	            else {
	                reject(new Error("Object '" + name + "' not found in registry"));
	            }
	        }
	    });
	}
	exports.loadObject = loadObject;
	;
	/**
	 * A Promise that can be resolved or rejected by another object.
	 */
	var PromiseDelegate = (function () {
	    /**
	     * Construct a new Promise delegate.
	     */
	    function PromiseDelegate() {
	        var _this = this;
	        this._promise = new Promise(function (resolve, reject) {
	            _this._resolve = resolve;
	            _this._reject = reject;
	        });
	    }
	    Object.defineProperty(PromiseDelegate.prototype, "promise", {
	        /**
	         * Get the underlying Promise.
	         */
	        get: function () {
	            return this._promise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Resolve the underlying Promise with an optional value or another Promise.
	     */
	    PromiseDelegate.prototype.resolve = function (value) {
	        // Note: according to the Promise spec, and the `this` context for resolve
	        // and reject are ignored
	        this._resolve(value);
	    };
	    /**
	     * Reject the underlying Promise with an optional reason.
	     */
	    PromiseDelegate.prototype.reject = function (reason) {
	        // Note: according to the Promise spec, the `this` context for resolve
	        // and reject are ignored
	        this._reject(reason);
	    };
	    return PromiseDelegate;
	}());
	exports.PromiseDelegate = PromiseDelegate;
	/**
	 * Global config data for the Jupyter application.
	 */
	var configData = null;
	/**
	 *  Make an object fully immutable by freezing each object in it.
	 */
	function deepFreeze(obj) {
	    // Freeze properties before freezing self
	    Object.getOwnPropertyNames(obj).forEach(function (name) {
	        var prop = obj[name];
	        // Freeze prop if it is an object
	        if (typeof prop === 'object' && prop !== null && !Object.isFrozen(prop)) {
	            deepFreeze(prop);
	        }
	    });
	    // Freeze self
	    return Object.freeze(obj);
	}
	/**
	 * Get global configuration data for the Jupyter application.
	 *
	 * @param name - The name of the configuration option.
	 *
	 * @returns The config value or `undefined` if not found.
	 *
	 * #### Notes
	 * For browser based applications, it is assumed that the page HTML
	 * includes a script tag with the id `jupyter-config-data` containing the
	 * configuration as valid JSON.
	 */
	function getConfigOption(name) {
	    if (configData) {
	        return configData[name];
	    }
	    if (typeof document === 'undefined') {
	        configData = minimist(process.argv.slice(2));
	    }
	    else {
	        var el = document.getElementById('jupyter-config-data');
	        if (el) {
	            configData = JSON.parse(el.textContent);
	        }
	        else {
	            configData = {};
	        }
	    }
	    configData = deepFreeze(configData);
	    return configData[name];
	}
	exports.getConfigOption = getConfigOption;
	/**
	 * Get the base URL for a Jupyter application.
	 */
	function getBaseUrl() {
	    var baseUrl = getConfigOption('baseUrl');
	    if (!baseUrl || baseUrl === '/') {
	        baseUrl = (typeof location === 'undefined' ?
	            'http://localhost:8888/' : location.origin + '/');
	    }
	    return baseUrl;
	}
	exports.getBaseUrl = getBaseUrl;
	/**
	 * Get the base websocket URL for a Jupyter application.
	 */
	function getWsUrl(baseUrl) {
	    var wsUrl = getConfigOption('wsUrl');
	    if (!wsUrl) {
	        baseUrl = baseUrl || getBaseUrl();
	        if (baseUrl.indexOf('http') !== 0) {
	            if (typeof location !== 'undefined') {
	                baseUrl = urlPathJoin(location.origin, baseUrl);
	            }
	            else {
	                baseUrl = urlPathJoin('http://localhost:8888/', baseUrl);
	            }
	        }
	        wsUrl = 'ws' + baseUrl.slice(4);
	    }
	    return wsUrl;
	}
	exports.getWsUrl = getWsUrl;
	/**
	 * Add token to ajaxSettings.requestHeaders if defined.
	 * Always returns a copy of ajaxSettings, and a dict.
	 */
	function ajaxSettingsWithToken(ajaxSettings, token) {
	    if (!ajaxSettings) {
	        ajaxSettings = {};
	    }
	    else {
	        ajaxSettings = copy(ajaxSettings);
	    }
	    if (!token) {
	        token = getConfigOption('token');
	    }
	    if (!token || token == '') {
	        return ajaxSettings;
	    }
	    if (!ajaxSettings.requestHeaders) {
	        ajaxSettings.requestHeaders = {};
	    }
	    ajaxSettings.requestHeaders['Authorization'] = "token " + token;
	    return ajaxSettings;
	}
	exports.ajaxSettingsWithToken = ajaxSettingsWithToken;
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('process@0.11.9/browser.js')))
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/utils.js **/


/** START DEFINE BLOCK for minimist@1.2.0/index.js **/
jupyter.define('minimist@1.2.0/index.js', function (module, exports, __jupyter_require__) {
	module.exports = function (args, opts) {
	    if (!opts) opts = {};
	    
	    var flags = { bools : {}, strings : {}, unknownFn: null };
	
	    if (typeof opts['unknown'] === 'function') {
	        flags.unknownFn = opts['unknown'];
	    }
	
	    if (typeof opts['boolean'] === 'boolean' && opts['boolean']) {
	      flags.allBools = true;
	    } else {
	      [].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
	          flags.bools[key] = true;
	      });
	    }
	    
	    var aliases = {};
	    Object.keys(opts.alias || {}).forEach(function (key) {
	        aliases[key] = [].concat(opts.alias[key]);
	        aliases[key].forEach(function (x) {
	            aliases[x] = [key].concat(aliases[key].filter(function (y) {
	                return x !== y;
	            }));
	        });
	    });
	
	    [].concat(opts.string).filter(Boolean).forEach(function (key) {
	        flags.strings[key] = true;
	        if (aliases[key]) {
	            flags.strings[aliases[key]] = true;
	        }
	     });
	
	    var defaults = opts['default'] || {};
	    
	    var argv = { _ : [] };
	    Object.keys(flags.bools).forEach(function (key) {
	        setArg(key, defaults[key] === undefined ? false : defaults[key]);
	    });
	    
	    var notFlags = [];
	
	    if (args.indexOf('--') !== -1) {
	        notFlags = args.slice(args.indexOf('--')+1);
	        args = args.slice(0, args.indexOf('--'));
	    }
	
	    function argDefined(key, arg) {
	        return (flags.allBools && /^--[^=]+$/.test(arg)) ||
	            flags.strings[key] || flags.bools[key] || aliases[key];
	    }
	
	    function setArg (key, val, arg) {
	        if (arg && flags.unknownFn && !argDefined(key, arg)) {
	            if (flags.unknownFn(arg) === false) return;
	        }
	
	        var value = !flags.strings[key] && isNumber(val)
	            ? Number(val) : val
	        ;
	        setKey(argv, key.split('.'), value);
	        
	        (aliases[key] || []).forEach(function (x) {
	            setKey(argv, x.split('.'), value);
	        });
	    }
	
	    function setKey (obj, keys, value) {
	        var o = obj;
	        keys.slice(0,-1).forEach(function (key) {
	            if (o[key] === undefined) o[key] = {};
	            o = o[key];
	        });
	
	        var key = keys[keys.length - 1];
	        if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') {
	            o[key] = value;
	        }
	        else if (Array.isArray(o[key])) {
	            o[key].push(value);
	        }
	        else {
	            o[key] = [ o[key], value ];
	        }
	    }
	    
	    function aliasIsBoolean(key) {
	      return aliases[key].some(function (x) {
	          return flags.bools[x];
	      });
	    }
	
	    for (var i = 0; i < args.length; i++) {
	        var arg = args[i];
	        
	        if (/^--.+=/.test(arg)) {
	            // Using [\s\S] instead of . because js doesn't support the
	            // 'dotall' regex modifier. See:
	            // http://stackoverflow.com/a/1068308/13216
	            var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
	            var key = m[1];
	            var value = m[2];
	            if (flags.bools[key]) {
	                value = value !== 'false';
	            }
	            setArg(key, value, arg);
	        }
	        else if (/^--no-.+/.test(arg)) {
	            var key = arg.match(/^--no-(.+)/)[1];
	            setArg(key, false, arg);
	        }
	        else if (/^--.+/.test(arg)) {
	            var key = arg.match(/^--(.+)/)[1];
	            var next = args[i + 1];
	            if (next !== undefined && !/^-/.test(next)
	            && !flags.bools[key]
	            && !flags.allBools
	            && (aliases[key] ? !aliasIsBoolean(key) : true)) {
	                setArg(key, next, arg);
	                i++;
	            }
	            else if (/^(true|false)$/.test(next)) {
	                setArg(key, next === 'true', arg);
	                i++;
	            }
	            else {
	                setArg(key, flags.strings[key] ? '' : true, arg);
	            }
	        }
	        else if (/^-[^-]+/.test(arg)) {
	            var letters = arg.slice(1,-1).split('');
	            
	            var broken = false;
	            for (var j = 0; j < letters.length; j++) {
	                var next = arg.slice(j+2);
	                
	                if (next === '-') {
	                    setArg(letters[j], next, arg)
	                    continue;
	                }
	                
	                if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) {
	                    setArg(letters[j], next.split('=')[1], arg);
	                    broken = true;
	                    break;
	                }
	                
	                if (/[A-Za-z]/.test(letters[j])
	                && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
	                    setArg(letters[j], next, arg);
	                    broken = true;
	                    break;
	                }
	                
	                if (letters[j+1] && letters[j+1].match(/\W/)) {
	                    setArg(letters[j], arg.slice(j+2), arg);
	                    broken = true;
	                    break;
	                }
	                else {
	                    setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg);
	                }
	            }
	            
	            var key = arg.slice(-1)[0];
	            if (!broken && key !== '-') {
	                if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
	                && !flags.bools[key]
	                && (aliases[key] ? !aliasIsBoolean(key) : true)) {
	                    setArg(key, args[i+1], arg);
	                    i++;
	                }
	                else if (args[i+1] && /true|false/.test(args[i+1])) {
	                    setArg(key, args[i+1] === 'true', arg);
	                    i++;
	                }
	                else {
	                    setArg(key, flags.strings[key] ? '' : true, arg);
	                }
	            }
	        }
	        else {
	            if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
	                argv._.push(
	                    flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
	                );
	            }
	            if (opts.stopEarly) {
	                argv._.push.apply(argv._, args.slice(i + 1));
	                break;
	            }
	        }
	    }
	    
	    Object.keys(defaults).forEach(function (key) {
	        if (!hasKey(argv, key.split('.'))) {
	            setKey(argv, key.split('.'), defaults[key]);
	            
	            (aliases[key] || []).forEach(function (x) {
	                setKey(argv, x.split('.'), defaults[key]);
	            });
	        }
	    });
	    
	    if (opts['--']) {
	        argv['--'] = new Array();
	        notFlags.forEach(function(key) {
	            argv['--'].push(key);
	        });
	    }
	    else {
	        notFlags.forEach(function(key) {
	            argv._.push(key);
	        });
	    }
	
	    return argv;
	};
	
	function hasKey (obj, keys) {
	    var o = obj;
	    keys.slice(0,-1).forEach(function (key) {
	        o = (o[key] || {});
	    });
	
	    var key = keys[keys.length - 1];
	    return key in o;
	}
	
	function isNumber (x) {
	    if (typeof x === 'number') return true;
	    if (/^0x[0-9a-f]+$/i.test(x)) return true;
	    return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
	}
	
	
})
/** END DEFINE BLOCK for minimist@1.2.0/index.js **/


/** START DEFINE BLOCK for url@0.11.0/url.js **/
jupyter.define('url@0.11.0/url.js', function (module, exports, __jupyter_require__) {
	// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.
	
	'use strict';
	
	var punycode = __jupyter_require__('punycode@1.3.2/punycode.js');
	var util = __jupyter_require__('url@0.11.0/util.js');
	
	exports.parse = urlParse;
	exports.resolve = urlResolve;
	exports.resolveObject = urlResolveObject;
	exports.format = urlFormat;
	
	exports.Url = Url;
	
	function Url() {
	  this.protocol = null;
	  this.slashes = null;
	  this.auth = null;
	  this.host = null;
	  this.port = null;
	  this.hostname = null;
	  this.hash = null;
	  this.search = null;
	  this.query = null;
	  this.pathname = null;
	  this.path = null;
	  this.href = null;
	}
	
	// Reference: RFC 3986, RFC 1808, RFC 2396
	
	// define these here so at least they only have to be
	// compiled once on the first module load.
	var protocolPattern = /^([a-z0-9.+-]+:)/i,
	    portPattern = /:[0-9]*$/,
	
	    // Special case for a simple path URL
	    simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
	
	    // RFC 2396: characters reserved for delimiting URLs.
	    // We actually just auto-escape these.
	    delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
	
	    // RFC 2396: characters not allowed for various reasons.
	    unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
	
	    // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
	    autoEscape = ['\''].concat(unwise),
	    // Characters that are never ever allowed in a hostname.
	    // Note that any invalid chars are also handled, but these
	    // are the ones that are *expected* to be seen, so we fast-path
	    // them.
	    nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
	    hostEndingChars = ['/', '?', '#'],
	    hostnameMaxLen = 255,
	    hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
	    hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
	    // protocols that can allow "unsafe" and "unwise" chars.
	    unsafeProtocol = {
	      'javascript': true,
	      'javascript:': true
	    },
	    // protocols that never have a hostname.
	    hostlessProtocol = {
	      'javascript': true,
	      'javascript:': true
	    },
	    // protocols that always contain a // bit.
	    slashedProtocol = {
	      'http': true,
	      'https': true,
	      'ftp': true,
	      'gopher': true,
	      'file': true,
	      'http:': true,
	      'https:': true,
	      'ftp:': true,
	      'gopher:': true,
	      'file:': true
	    },
	    querystring = __jupyter_require__('querystring@0.2.0/index.js');
	
	function urlParse(url, parseQueryString, slashesDenoteHost) {
	  if (url && util.isObject(url) && url instanceof Url) return url;
	
	  var u = new Url;
	  u.parse(url, parseQueryString, slashesDenoteHost);
	  return u;
	}
	
	Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
	  if (!util.isString(url)) {
	    throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
	  }
	
	  // Copy chrome, IE, opera backslash-handling behavior.
	  // Back slashes before the query string get converted to forward slashes
	  // See: https://code.google.com/p/chromium/issues/detail?id=25916
	  var queryIndex = url.indexOf('?'),
	      splitter =
	          (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
	      uSplit = url.split(splitter),
	      slashRegex = /\\/g;
	  uSplit[0] = uSplit[0].replace(slashRegex, '/');
	  url = uSplit.join(splitter);
	
	  var rest = url;
	
	  // trim before proceeding.
	  // This is to support parse stuff like "  http://foo.com  \n"
	  rest = rest.trim();
	
	  if (!slashesDenoteHost && url.split('#').length === 1) {
	    // Try fast path regexp
	    var simplePath = simplePathPattern.exec(rest);
	    if (simplePath) {
	      this.path = rest;
	      this.href = rest;
	      this.pathname = simplePath[1];
	      if (simplePath[2]) {
	        this.search = simplePath[2];
	        if (parseQueryString) {
	          this.query = querystring.parse(this.search.substr(1));
	        } else {
	          this.query = this.search.substr(1);
	        }
	      } else if (parseQueryString) {
	        this.search = '';
	        this.query = {};
	      }
	      return this;
	    }
	  }
	
	  var proto = protocolPattern.exec(rest);
	  if (proto) {
	    proto = proto[0];
	    var lowerProto = proto.toLowerCase();
	    this.protocol = lowerProto;
	    rest = rest.substr(proto.length);
	  }
	
	  // figure out if it's got a host
	  // user@server is *always* interpreted as a hostname, and url
	  // resolution will treat //foo/bar as host=foo,path=bar because that's
	  // how the browser resolves relative URLs.
	  if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
	    var slashes = rest.substr(0, 2) === '//';
	    if (slashes && !(proto && hostlessProtocol[proto])) {
	      rest = rest.substr(2);
	      this.slashes = true;
	    }
	  }
	
	  if (!hostlessProtocol[proto] &&
	      (slashes || (proto && !slashedProtocol[proto]))) {
	
	    // there's a hostname.
	    // the first instance of /, ?, ;, or # ends the host.
	    //
	    // If there is an @ in the hostname, then non-host chars *are* allowed
	    // to the left of the last @ sign, unless some host-ending character
	    // comes *before* the @-sign.
	    // URLs are obnoxious.
	    //
	    // ex:
	    // http://a@b@c/ => user:a@b host:c
	    // http://a@b?@c => user:a host:c path:/?@c
	
	    // v0.12 TODO(isaacs): This is not quite how Chrome does things.
	    // Review our test case against browsers more comprehensively.
	
	    // find the first instance of any hostEndingChars
	    var hostEnd = -1;
	    for (var i = 0; i < hostEndingChars.length; i++) {
	      var hec = rest.indexOf(hostEndingChars[i]);
	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
	        hostEnd = hec;
	    }
	
	    // at this point, either we have an explicit point where the
	    // auth portion cannot go past, or the last @ char is the decider.
	    var auth, atSign;
	    if (hostEnd === -1) {
	      // atSign can be anywhere.
	      atSign = rest.lastIndexOf('@');
	    } else {
	      // atSign must be in auth portion.
	      // http://a@b/c@d => host:b auth:a path:/c@d
	      atSign = rest.lastIndexOf('@', hostEnd);
	    }
	
	    // Now we have a portion which is definitely the auth.
	    // Pull that off.
	    if (atSign !== -1) {
	      auth = rest.slice(0, atSign);
	      rest = rest.slice(atSign + 1);
	      this.auth = decodeURIComponent(auth);
	    }
	
	    // the host is the remaining to the left of the first non-host char
	    hostEnd = -1;
	    for (var i = 0; i < nonHostChars.length; i++) {
	      var hec = rest.indexOf(nonHostChars[i]);
	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
	        hostEnd = hec;
	    }
	    // if we still have not hit it, then the entire thing is a host.
	    if (hostEnd === -1)
	      hostEnd = rest.length;
	
	    this.host = rest.slice(0, hostEnd);
	    rest = rest.slice(hostEnd);
	
	    // pull out port.
	    this.parseHost();
	
	    // we've indicated that there is a hostname,
	    // so even if it's empty, it has to be present.
	    this.hostname = this.hostname || '';
	
	    // if hostname begins with [ and ends with ]
	    // assume that it's an IPv6 address.
	    var ipv6Hostname = this.hostname[0] === '[' &&
	        this.hostname[this.hostname.length - 1] === ']';
	
	    // validate a little.
	    if (!ipv6Hostname) {
	      var hostparts = this.hostname.split(/\./);
	      for (var i = 0, l = hostparts.length; i < l; i++) {
	        var part = hostparts[i];
	        if (!part) continue;
	        if (!part.match(hostnamePartPattern)) {
	          var newpart = '';
	          for (var j = 0, k = part.length; j < k; j++) {
	            if (part.charCodeAt(j) > 127) {
	              // we replace non-ASCII char with a temporary placeholder
	              // we need this to make sure size of hostname is not
	              // broken by replacing non-ASCII by nothing
	              newpart += 'x';
	            } else {
	              newpart += part[j];
	            }
	          }
	          // we test again with ASCII char only
	          if (!newpart.match(hostnamePartPattern)) {
	            var validParts = hostparts.slice(0, i);
	            var notHost = hostparts.slice(i + 1);
	            var bit = part.match(hostnamePartStart);
	            if (bit) {
	              validParts.push(bit[1]);
	              notHost.unshift(bit[2]);
	            }
	            if (notHost.length) {
	              rest = '/' + notHost.join('.') + rest;
	            }
	            this.hostname = validParts.join('.');
	            break;
	          }
	        }
	      }
	    }
	
	    if (this.hostname.length > hostnameMaxLen) {
	      this.hostname = '';
	    } else {
	      // hostnames are always lower case.
	      this.hostname = this.hostname.toLowerCase();
	    }
	
	    if (!ipv6Hostname) {
	      // IDNA Support: Returns a punycoded representation of "domain".
	      // It only converts parts of the domain name that
	      // have non-ASCII characters, i.e. it doesn't matter if
	      // you call it with a domain that already is ASCII-only.
	      this.hostname = punycode.toASCII(this.hostname);
	    }
	
	    var p = this.port ? ':' + this.port : '';
	    var h = this.hostname || '';
	    this.host = h + p;
	    this.href += this.host;
	
	    // strip [ and ] from the hostname
	    // the host field still retains them, though
	    if (ipv6Hostname) {
	      this.hostname = this.hostname.substr(1, this.hostname.length - 2);
	      if (rest[0] !== '/') {
	        rest = '/' + rest;
	      }
	    }
	  }
	
	  // now rest is set to the post-host stuff.
	  // chop off any delim chars.
	  if (!unsafeProtocol[lowerProto]) {
	
	    // First, make 100% sure that any "autoEscape" chars get
	    // escaped, even if encodeURIComponent doesn't think they
	    // need to be.
	    for (var i = 0, l = autoEscape.length; i < l; i++) {
	      var ae = autoEscape[i];
	      if (rest.indexOf(ae) === -1)
	        continue;
	      var esc = encodeURIComponent(ae);
	      if (esc === ae) {
	        esc = escape(ae);
	      }
	      rest = rest.split(ae).join(esc);
	    }
	  }
	
	
	  // chop off from the tail first.
	  var hash = rest.indexOf('#');
	  if (hash !== -1) {
	    // got a fragment string.
	    this.hash = rest.substr(hash);
	    rest = rest.slice(0, hash);
	  }
	  var qm = rest.indexOf('?');
	  if (qm !== -1) {
	    this.search = rest.substr(qm);
	    this.query = rest.substr(qm + 1);
	    if (parseQueryString) {
	      this.query = querystring.parse(this.query);
	    }
	    rest = rest.slice(0, qm);
	  } else if (parseQueryString) {
	    // no query string, but parseQueryString still requested
	    this.search = '';
	    this.query = {};
	  }
	  if (rest) this.pathname = rest;
	  if (slashedProtocol[lowerProto] &&
	      this.hostname && !this.pathname) {
	    this.pathname = '/';
	  }
	
	  //to support http.request
	  if (this.pathname || this.search) {
	    var p = this.pathname || '';
	    var s = this.search || '';
	    this.path = p + s;
	  }
	
	  // finally, reconstruct the href based on what has been validated.
	  this.href = this.format();
	  return this;
	};
	
	// format a parsed object into a url string
	function urlFormat(obj) {
	  // ensure it's an object, and not a string url.
	  // If it's an obj, this is a no-op.
	  // this way, you can call url_format() on strings
	  // to clean up potentially wonky urls.
	  if (util.isString(obj)) obj = urlParse(obj);
	  if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
	  return obj.format();
	}
	
	Url.prototype.format = function() {
	  var auth = this.auth || '';
	  if (auth) {
	    auth = encodeURIComponent(auth);
	    auth = auth.replace(/%3A/i, ':');
	    auth += '@';
	  }
	
	  var protocol = this.protocol || '',
	      pathname = this.pathname || '',
	      hash = this.hash || '',
	      host = false,
	      query = '';
	
	  if (this.host) {
	    host = auth + this.host;
	  } else if (this.hostname) {
	    host = auth + (this.hostname.indexOf(':') === -1 ?
	        this.hostname :
	        '[' + this.hostname + ']');
	    if (this.port) {
	      host += ':' + this.port;
	    }
	  }
	
	  if (this.query &&
	      util.isObject(this.query) &&
	      Object.keys(this.query).length) {
	    query = querystring.stringify(this.query);
	  }
	
	  var search = this.search || (query && ('?' + query)) || '';
	
	  if (protocol && protocol.substr(-1) !== ':') protocol += ':';
	
	  // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
	  // unless they had them to begin with.
	  if (this.slashes ||
	      (!protocol || slashedProtocol[protocol]) && host !== false) {
	    host = '//' + (host || '');
	    if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
	  } else if (!host) {
	    host = '';
	  }
	
	  if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
	  if (search && search.charAt(0) !== '?') search = '?' + search;
	
	  pathname = pathname.replace(/[?#]/g, function(match) {
	    return encodeURIComponent(match);
	  });
	  search = search.replace('#', '%23');
	
	  return protocol + host + pathname + search + hash;
	};
	
	function urlResolve(source, relative) {
	  return urlParse(source, false, true).resolve(relative);
	}
	
	Url.prototype.resolve = function(relative) {
	  return this.resolveObject(urlParse(relative, false, true)).format();
	};
	
	function urlResolveObject(source, relative) {
	  if (!source) return relative;
	  return urlParse(source, false, true).resolveObject(relative);
	}
	
	Url.prototype.resolveObject = function(relative) {
	  if (util.isString(relative)) {
	    var rel = new Url();
	    rel.parse(relative, false, true);
	    relative = rel;
	  }
	
	  var result = new Url();
	  var tkeys = Object.keys(this);
	  for (var tk = 0; tk < tkeys.length; tk++) {
	    var tkey = tkeys[tk];
	    result[tkey] = this[tkey];
	  }
	
	  // hash is always overridden, no matter what.
	  // even href="" will remove it.
	  result.hash = relative.hash;
	
	  // if the relative url is empty, then there's nothing left to do here.
	  if (relative.href === '') {
	    result.href = result.format();
	    return result;
	  }
	
	  // hrefs like //foo/bar always cut to the protocol.
	  if (relative.slashes && !relative.protocol) {
	    // take everything except the protocol from relative
	    var rkeys = Object.keys(relative);
	    for (var rk = 0; rk < rkeys.length; rk++) {
	      var rkey = rkeys[rk];
	      if (rkey !== 'protocol')
	        result[rkey] = relative[rkey];
	    }
	
	    //urlParse appends trailing / to urls like http://www.example.com
	    if (slashedProtocol[result.protocol] &&
	        result.hostname && !result.pathname) {
	      result.path = result.pathname = '/';
	    }
	
	    result.href = result.format();
	    return result;
	  }
	
	  if (relative.protocol && relative.protocol !== result.protocol) {
	    // if it's a known url protocol, then changing
	    // the protocol does weird things
	    // first, if it's not file:, then we MUST have a host,
	    // and if there was a path
	    // to begin with, then we MUST have a path.
	    // if it is file:, then the host is dropped,
	    // because that's known to be hostless.
	    // anything else is assumed to be absolute.
	    if (!slashedProtocol[relative.protocol]) {
	      var keys = Object.keys(relative);
	      for (var v = 0; v < keys.length; v++) {
	        var k = keys[v];
	        result[k] = relative[k];
	      }
	      result.href = result.format();
	      return result;
	    }
	
	    result.protocol = relative.protocol;
	    if (!relative.host && !hostlessProtocol[relative.protocol]) {
	      var relPath = (relative.pathname || '').split('/');
	      while (relPath.length && !(relative.host = relPath.shift()));
	      if (!relative.host) relative.host = '';
	      if (!relative.hostname) relative.hostname = '';
	      if (relPath[0] !== '') relPath.unshift('');
	      if (relPath.length < 2) relPath.unshift('');
	      result.pathname = relPath.join('/');
	    } else {
	      result.pathname = relative.pathname;
	    }
	    result.search = relative.search;
	    result.query = relative.query;
	    result.host = relative.host || '';
	    result.auth = relative.auth;
	    result.hostname = relative.hostname || relative.host;
	    result.port = relative.port;
	    // to support http.request
	    if (result.pathname || result.search) {
	      var p = result.pathname || '';
	      var s = result.search || '';
	      result.path = p + s;
	    }
	    result.slashes = result.slashes || relative.slashes;
	    result.href = result.format();
	    return result;
	  }
	
	  var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
	      isRelAbs = (
	          relative.host ||
	          relative.pathname && relative.pathname.charAt(0) === '/'
	      ),
	      mustEndAbs = (isRelAbs || isSourceAbs ||
	                    (result.host && relative.pathname)),
	      removeAllDots = mustEndAbs,
	      srcPath = result.pathname && result.pathname.split('/') || [],
	      relPath = relative.pathname && relative.pathname.split('/') || [],
	      psychotic = result.protocol && !slashedProtocol[result.protocol];
	
	  // if the url is a non-slashed url, then relative
	  // links like ../.. should be able
	  // to crawl up to the hostname, as well.  This is strange.
	  // result.protocol has already been set by now.
	  // Later on, put the first path part into the host field.
	  if (psychotic) {
	    result.hostname = '';
	    result.port = null;
	    if (result.host) {
	      if (srcPath[0] === '') srcPath[0] = result.host;
	      else srcPath.unshift(result.host);
	    }
	    result.host = '';
	    if (relative.protocol) {
	      relative.hostname = null;
	      relative.port = null;
	      if (relative.host) {
	        if (relPath[0] === '') relPath[0] = relative.host;
	        else relPath.unshift(relative.host);
	      }
	      relative.host = null;
	    }
	    mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
	  }
	
	  if (isRelAbs) {
	    // it's absolute.
	    result.host = (relative.host || relative.host === '') ?
	                  relative.host : result.host;
	    result.hostname = (relative.hostname || relative.hostname === '') ?
	                      relative.hostname : result.hostname;
	    result.search = relative.search;
	    result.query = relative.query;
	    srcPath = relPath;
	    // fall through to the dot-handling below.
	  } else if (relPath.length) {
	    // it's relative
	    // throw away the existing file, and take the new path instead.
	    if (!srcPath) srcPath = [];
	    srcPath.pop();
	    srcPath = srcPath.concat(relPath);
	    result.search = relative.search;
	    result.query = relative.query;
	  } else if (!util.isNullOrUndefined(relative.search)) {
	    // just pull out the search.
	    // like href='?foo'.
	    // Put this after the other two cases because it simplifies the booleans
	    if (psychotic) {
	      result.hostname = result.host = srcPath.shift();
	      //occationaly the auth can get stuck only in host
	      //this especially happens in cases like
	      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
	      var authInHost = result.host && result.host.indexOf('@') > 0 ?
	                       result.host.split('@') : false;
	      if (authInHost) {
	        result.auth = authInHost.shift();
	        result.host = result.hostname = authInHost.shift();
	      }
	    }
	    result.search = relative.search;
	    result.query = relative.query;
	    //to support http.request
	    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
	      result.path = (result.pathname ? result.pathname : '') +
	                    (result.search ? result.search : '');
	    }
	    result.href = result.format();
	    return result;
	  }
	
	  if (!srcPath.length) {
	    // no path at all.  easy.
	    // we've already handled the other stuff above.
	    result.pathname = null;
	    //to support http.request
	    if (result.search) {
	      result.path = '/' + result.search;
	    } else {
	      result.path = null;
	    }
	    result.href = result.format();
	    return result;
	  }
	
	  // if a url ENDs in . or .., then it must get a trailing slash.
	  // however, if it ends in anything else non-slashy,
	  // then it must NOT get a trailing slash.
	  var last = srcPath.slice(-1)[0];
	  var hasTrailingSlash = (
	      (result.host || relative.host || srcPath.length > 1) &&
	      (last === '.' || last === '..') || last === '');
	
	  // strip single dots, resolve double dots to parent dir
	  // if the path tries to go above the root, `up` ends up > 0
	  var up = 0;
	  for (var i = srcPath.length; i >= 0; i--) {
	    last = srcPath[i];
	    if (last === '.') {
	      srcPath.splice(i, 1);
	    } else if (last === '..') {
	      srcPath.splice(i, 1);
	      up++;
	    } else if (up) {
	      srcPath.splice(i, 1);
	      up--;
	    }
	  }
	
	  // if the path is allowed to go above the root, restore leading ..s
	  if (!mustEndAbs && !removeAllDots) {
	    for (; up--; up) {
	      srcPath.unshift('..');
	    }
	  }
	
	  if (mustEndAbs && srcPath[0] !== '' &&
	      (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
	    srcPath.unshift('');
	  }
	
	  if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
	    srcPath.push('');
	  }
	
	  var isAbsolute = srcPath[0] === '' ||
	      (srcPath[0] && srcPath[0].charAt(0) === '/');
	
	  // put the host back
	  if (psychotic) {
	    result.hostname = result.host = isAbsolute ? '' :
	                                    srcPath.length ? srcPath.shift() : '';
	    //occationaly the auth can get stuck only in host
	    //this especially happens in cases like
	    //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
	    var authInHost = result.host && result.host.indexOf('@') > 0 ?
	                     result.host.split('@') : false;
	    if (authInHost) {
	      result.auth = authInHost.shift();
	      result.host = result.hostname = authInHost.shift();
	    }
	  }
	
	  mustEndAbs = mustEndAbs || (result.host && srcPath.length);
	
	  if (mustEndAbs && !isAbsolute) {
	    srcPath.unshift('');
	  }
	
	  if (!srcPath.length) {
	    result.pathname = null;
	    result.path = null;
	  } else {
	    result.pathname = srcPath.join('/');
	  }
	
	  //to support request.http
	  if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
	    result.path = (result.pathname ? result.pathname : '') +
	                  (result.search ? result.search : '');
	  }
	  result.auth = relative.auth || result.auth;
	  result.slashes = result.slashes || relative.slashes;
	  result.href = result.format();
	  return result;
	};
	
	Url.prototype.parseHost = function() {
	  var host = this.host;
	  var port = portPattern.exec(host);
	  if (port) {
	    port = port[0];
	    if (port !== ':') {
	      this.port = port.substr(1);
	    }
	    host = host.substr(0, host.length - port.length);
	  }
	  if (host) this.hostname = host;
	};
	
})
/** END DEFINE BLOCK for url@0.11.0/url.js **/


/** START DEFINE BLOCK for punycode@1.3.2/punycode.js **/
jupyter.define('punycode@1.3.2/punycode.js', function (module, exports, __jupyter_require__) {
	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
	;(function(root) {
	
		/** Detect free variables */
		var freeExports = typeof exports == 'object' && exports &&
			!exports.nodeType && exports;
		var freeModule = typeof module == 'object' && module &&
			!module.nodeType && module;
		var freeGlobal = typeof global == 'object' && global;
		if (
			freeGlobal.global === freeGlobal ||
			freeGlobal.window === freeGlobal ||
			freeGlobal.self === freeGlobal
		) {
			root = freeGlobal;
		}
	
		/**
		 * The `punycode` object.
		 * @name punycode
		 * @type Object
		 */
		var punycode,
	
		/** Highest positive signed 32-bit float value */
		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
	
		/** Bootstring parameters */
		base = 36,
		tMin = 1,
		tMax = 26,
		skew = 38,
		damp = 700,
		initialBias = 72,
		initialN = 128, // 0x80
		delimiter = '-', // '\x2D'
	
		/** Regular expressions */
		regexPunycode = /^xn--/,
		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
	
		/** Error messages */
		errors = {
			'overflow': 'Overflow: input needs wider integers to process',
			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
			'invalid-input': 'Invalid input'
		},
	
		/** Convenience shortcuts */
		baseMinusTMin = base - tMin,
		floor = Math.floor,
		stringFromCharCode = String.fromCharCode,
	
		/** Temporary variable */
		key;
	
		/*--------------------------------------------------------------------------*/
	
		/**
		 * A generic error utility function.
		 * @private
		 * @param {String} type The error type.
		 * @returns {Error} Throws a `RangeError` with the applicable error message.
		 */
		function error(type) {
			throw RangeError(errors[type]);
		}
	
		/**
		 * A generic `Array#map` utility function.
		 * @private
		 * @param {Array} array The array to iterate over.
		 * @param {Function} callback The function that gets called for every array
		 * item.
		 * @returns {Array} A new array of values returned by the callback function.
		 */
		function map(array, fn) {
			var length = array.length;
			var result = [];
			while (length--) {
				result[length] = fn(array[length]);
			}
			return result;
		}
	
		/**
		 * A simple `Array#map`-like wrapper to work with domain name strings or email
		 * addresses.
		 * @private
		 * @param {String} domain The domain name or email address.
		 * @param {Function} callback The function that gets called for every
		 * character.
		 * @returns {Array} A new string of characters returned by the callback
		 * function.
		 */
		function mapDomain(string, fn) {
			var parts = string.split('@');
			var result = '';
			if (parts.length > 1) {
				// In email addresses, only the domain name should be punycoded. Leave
				// the local part (i.e. everything up to `@`) intact.
				result = parts[0] + '@';
				string = parts[1];
			}
			// Avoid `split(regex)` for IE8 compatibility. See #17.
			string = string.replace(regexSeparators, '\x2E');
			var labels = string.split('.');
			var encoded = map(labels, fn).join('.');
			return result + encoded;
		}
	
		/**
		 * Creates an array containing the numeric code points of each Unicode
		 * character in the string. While JavaScript uses UCS-2 internally,
		 * this function will convert a pair of surrogate halves (each of which
		 * UCS-2 exposes as separate characters) into a single code point,
		 * matching UTF-16.
		 * @see `punycode.ucs2.encode`
		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
		 * @memberOf punycode.ucs2
		 * @name decode
		 * @param {String} string The Unicode input string (UCS-2).
		 * @returns {Array} The new array of code points.
		 */
		function ucs2decode(string) {
			var output = [],
			    counter = 0,
			    length = string.length,
			    value,
			    extra;
			while (counter < length) {
				value = string.charCodeAt(counter++);
				if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
					// high surrogate, and there is a next character
					extra = string.charCodeAt(counter++);
					if ((extra & 0xFC00) == 0xDC00) { // low surrogate
						output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
					} else {
						// unmatched surrogate; only append this code unit, in case the next
						// code unit is the high surrogate of a surrogate pair
						output.push(value);
						counter--;
					}
				} else {
					output.push(value);
				}
			}
			return output;
		}
	
		/**
		 * Creates a string based on an array of numeric code points.
		 * @see `punycode.ucs2.decode`
		 * @memberOf punycode.ucs2
		 * @name encode
		 * @param {Array} codePoints The array of numeric code points.
		 * @returns {String} The new Unicode string (UCS-2).
		 */
		function ucs2encode(array) {
			return map(array, function(value) {
				var output = '';
				if (value > 0xFFFF) {
					value -= 0x10000;
					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
					value = 0xDC00 | value & 0x3FF;
				}
				output += stringFromCharCode(value);
				return output;
			}).join('');
		}
	
		/**
		 * Converts a basic code point into a digit/integer.
		 * @see `digitToBasic()`
		 * @private
		 * @param {Number} codePoint The basic numeric code point value.
		 * @returns {Number} The numeric value of a basic code point (for use in
		 * representing integers) in the range `0` to `base - 1`, or `base` if
		 * the code point does not represent a value.
		 */
		function basicToDigit(codePoint) {
			if (codePoint - 48 < 10) {
				return codePoint - 22;
			}
			if (codePoint - 65 < 26) {
				return codePoint - 65;
			}
			if (codePoint - 97 < 26) {
				return codePoint - 97;
			}
			return base;
		}
	
		/**
		 * Converts a digit/integer into a basic code point.
		 * @see `basicToDigit()`
		 * @private
		 * @param {Number} digit The numeric value of a basic code point.
		 * @returns {Number} The basic code point whose value (when used for
		 * representing integers) is `digit`, which needs to be in the range
		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
		 * used; else, the lowercase form is used. The behavior is undefined
		 * if `flag` is non-zero and `digit` has no uppercase form.
		 */
		function digitToBasic(digit, flag) {
			//  0..25 map to ASCII a..z or A..Z
			// 26..35 map to ASCII 0..9
			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
		}
	
		/**
		 * Bias adaptation function as per section 3.4 of RFC 3492.
		 * http://tools.ietf.org/html/rfc3492#section-3.4
		 * @private
		 */
		function adapt(delta, numPoints, firstTime) {
			var k = 0;
			delta = firstTime ? floor(delta / damp) : delta >> 1;
			delta += floor(delta / numPoints);
			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
				delta = floor(delta / baseMinusTMin);
			}
			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
		}
	
		/**
		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
		 * symbols.
		 * @memberOf punycode
		 * @param {String} input The Punycode string of ASCII-only symbols.
		 * @returns {String} The resulting string of Unicode symbols.
		 */
		function decode(input) {
			// Don't use UCS-2
			var output = [],
			    inputLength = input.length,
			    out,
			    i = 0,
			    n = initialN,
			    bias = initialBias,
			    basic,
			    j,
			    index,
			    oldi,
			    w,
			    k,
			    digit,
			    t,
			    /** Cached calculation results */
			    baseMinusT;
	
			// Handle the basic code points: let `basic` be the number of input code
			// points before the last delimiter, or `0` if there is none, then copy
			// the first basic code points to the output.
	
			basic = input.lastIndexOf(delimiter);
			if (basic < 0) {
				basic = 0;
			}
	
			for (j = 0; j < basic; ++j) {
				// if it's not a basic code point
				if (input.charCodeAt(j) >= 0x80) {
					error('not-basic');
				}
				output.push(input.charCodeAt(j));
			}
	
			// Main decoding loop: start just after the last delimiter if any basic code
			// points were copied; start at the beginning otherwise.
	
			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
	
				// `index` is the index of the next character to be consumed.
				// Decode a generalized variable-length integer into `delta`,
				// which gets added to `i`. The overflow checking is easier
				// if we increase `i` as we go, then subtract off its starting
				// value at the end to obtain `delta`.
				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
	
					if (index >= inputLength) {
						error('invalid-input');
					}
	
					digit = basicToDigit(input.charCodeAt(index++));
	
					if (digit >= base || digit > floor((maxInt - i) / w)) {
						error('overflow');
					}
	
					i += digit * w;
					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
	
					if (digit < t) {
						break;
					}
	
					baseMinusT = base - t;
					if (w > floor(maxInt / baseMinusT)) {
						error('overflow');
					}
	
					w *= baseMinusT;
	
				}
	
				out = output.length + 1;
				bias = adapt(i - oldi, out, oldi == 0);
	
				// `i` was supposed to wrap around from `out` to `0`,
				// incrementing `n` each time, so we'll fix that now:
				if (floor(i / out) > maxInt - n) {
					error('overflow');
				}
	
				n += floor(i / out);
				i %= out;
	
				// Insert `n` at position `i` of the output
				output.splice(i++, 0, n);
	
			}
	
			return ucs2encode(output);
		}
	
		/**
		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
		 * Punycode string of ASCII-only symbols.
		 * @memberOf punycode
		 * @param {String} input The string of Unicode symbols.
		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
		 */
		function encode(input) {
			var n,
			    delta,
			    handledCPCount,
			    basicLength,
			    bias,
			    j,
			    m,
			    q,
			    k,
			    t,
			    currentValue,
			    output = [],
			    /** `inputLength` will hold the number of code points in `input`. */
			    inputLength,
			    /** Cached calculation results */
			    handledCPCountPlusOne,
			    baseMinusT,
			    qMinusT;
	
			// Convert the input in UCS-2 to Unicode
			input = ucs2decode(input);
	
			// Cache the length
			inputLength = input.length;
	
			// Initialize the state
			n = initialN;
			delta = 0;
			bias = initialBias;
	
			// Handle the basic code points
			for (j = 0; j < inputLength; ++j) {
				currentValue = input[j];
				if (currentValue < 0x80) {
					output.push(stringFromCharCode(currentValue));
				}
			}
	
			handledCPCount = basicLength = output.length;
	
			// `handledCPCount` is the number of code points that have been handled;
			// `basicLength` is the number of basic code points.
	
			// Finish the basic string - if it is not empty - with a delimiter
			if (basicLength) {
				output.push(delimiter);
			}
	
			// Main encoding loop:
			while (handledCPCount < inputLength) {
	
				// All non-basic code points < n have been handled already. Find the next
				// larger one:
				for (m = maxInt, j = 0; j < inputLength; ++j) {
					currentValue = input[j];
					if (currentValue >= n && currentValue < m) {
						m = currentValue;
					}
				}
	
				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
				// but guard against overflow
				handledCPCountPlusOne = handledCPCount + 1;
				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
					error('overflow');
				}
	
				delta += (m - n) * handledCPCountPlusOne;
				n = m;
	
				for (j = 0; j < inputLength; ++j) {
					currentValue = input[j];
	
					if (currentValue < n && ++delta > maxInt) {
						error('overflow');
					}
	
					if (currentValue == n) {
						// Represent delta as a generalized variable-length integer
						for (q = delta, k = base; /* no condition */; k += base) {
							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
							if (q < t) {
								break;
							}
							qMinusT = q - t;
							baseMinusT = base - t;
							output.push(
								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
							);
							q = floor(qMinusT / baseMinusT);
						}
	
						output.push(stringFromCharCode(digitToBasic(q, 0)));
						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
						delta = 0;
						++handledCPCount;
					}
				}
	
				++delta;
				++n;
	
			}
			return output.join('');
		}
	
		/**
		 * Converts a Punycode string representing a domain name or an email address
		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
		 * it doesn't matter if you call it on a string that has already been
		 * converted to Unicode.
		 * @memberOf punycode
		 * @param {String} input The Punycoded domain name or email address to
		 * convert to Unicode.
		 * @returns {String} The Unicode representation of the given Punycode
		 * string.
		 */
		function toUnicode(input) {
			return mapDomain(input, function(string) {
				return regexPunycode.test(string)
					? decode(string.slice(4).toLowerCase())
					: string;
			});
		}
	
		/**
		 * Converts a Unicode string representing a domain name or an email address to
		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
		 * i.e. it doesn't matter if you call it with a domain that's already in
		 * ASCII.
		 * @memberOf punycode
		 * @param {String} input The domain name or email address to convert, as a
		 * Unicode string.
		 * @returns {String} The Punycode representation of the given domain name or
		 * email address.
		 */
		function toASCII(input) {
			return mapDomain(input, function(string) {
				return regexNonASCII.test(string)
					? 'xn--' + encode(string)
					: string;
			});
		}
	
		/*--------------------------------------------------------------------------*/
	
		/** Define the public API */
		punycode = {
			/**
			 * A string representing the current Punycode.js version number.
			 * @memberOf punycode
			 * @type String
			 */
			'version': '1.3.2',
			/**
			 * An object of methods to convert from JavaScript's internal character
			 * representation (UCS-2) to Unicode code points, and back.
			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
			 * @memberOf punycode
			 * @type Object
			 */
			'ucs2': {
				'decode': ucs2decode,
				'encode': ucs2encode
			},
			'decode': decode,
			'encode': encode,
			'toASCII': toASCII,
			'toUnicode': toUnicode
		};
	
		/** Expose `punycode` */
		// Some AMD build optimizers, like r.js, check for specific condition patterns
		// like the following:
		if (
			true
		) {
			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
				return punycode;
			}.call(exports, __jupyter_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
		} else if (freeExports && freeModule) {
			if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
				freeModule.exports = punycode;
			} else { // in Narwhal or RingoJS v0.7.0-
				for (key in punycode) {
					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
				}
			}
		} else { // in Rhino or a web browser
			root.punycode = punycode;
		}
	
	}(this));
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('webpack@1.14.0/buildin/module.js')(module), (function() { return this; }())))
})
/** END DEFINE BLOCK for punycode@1.3.2/punycode.js **/


/** START DEFINE BLOCK for url@0.11.0/util.js **/
jupyter.define('url@0.11.0/util.js', function (module, exports, __jupyter_require__) {
	'use strict';
	
	module.exports = {
	  isString: function(arg) {
	    return typeof(arg) === 'string';
	  },
	  isObject: function(arg) {
	    return typeof(arg) === 'object' && arg !== null;
	  },
	  isNull: function(arg) {
	    return arg === null;
	  },
	  isNullOrUndefined: function(arg) {
	    return arg == null;
	  }
	};
	
})
/** END DEFINE BLOCK for url@0.11.0/util.js **/


/** START DEFINE BLOCK for querystring@0.2.0/index.js **/
jupyter.define('querystring@0.2.0/index.js', function (module, exports, __jupyter_require__) {
	'use strict';
	
	exports.decode = exports.parse = __jupyter_require__('querystring@0.2.0/decode.js');
	exports.encode = exports.stringify = __jupyter_require__('querystring@0.2.0/encode.js');
	
})
/** END DEFINE BLOCK for querystring@0.2.0/index.js **/


/** START DEFINE BLOCK for querystring@0.2.0/decode.js **/
jupyter.define('querystring@0.2.0/decode.js', function (module, exports, __jupyter_require__) {
	// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.
	
	'use strict';
	
	// If obj.hasOwnProperty has been overridden, then calling
	// obj.hasOwnProperty(prop) will break.
	// See: https://github.com/joyent/node/issues/1707
	function hasOwnProperty(obj, prop) {
	  return Object.prototype.hasOwnProperty.call(obj, prop);
	}
	
	module.exports = function(qs, sep, eq, options) {
	  sep = sep || '&';
	  eq = eq || '=';
	  var obj = {};
	
	  if (typeof qs !== 'string' || qs.length === 0) {
	    return obj;
	  }
	
	  var regexp = /\+/g;
	  qs = qs.split(sep);
	
	  var maxKeys = 1000;
	  if (options && typeof options.maxKeys === 'number') {
	    maxKeys = options.maxKeys;
	  }
	
	  var len = qs.length;
	  // maxKeys <= 0 means that we should not limit keys count
	  if (maxKeys > 0 && len > maxKeys) {
	    len = maxKeys;
	  }
	
	  for (var i = 0; i < len; ++i) {
	    var x = qs[i].replace(regexp, '%20'),
	        idx = x.indexOf(eq),
	        kstr, vstr, k, v;
	
	    if (idx >= 0) {
	      kstr = x.substr(0, idx);
	      vstr = x.substr(idx + 1);
	    } else {
	      kstr = x;
	      vstr = '';
	    }
	
	    k = decodeURIComponent(kstr);
	    v = decodeURIComponent(vstr);
	
	    if (!hasOwnProperty(obj, k)) {
	      obj[k] = v;
	    } else if (Array.isArray(obj[k])) {
	      obj[k].push(v);
	    } else {
	      obj[k] = [obj[k], v];
	    }
	  }
	
	  return obj;
	};
	
})
/** END DEFINE BLOCK for querystring@0.2.0/decode.js **/


/** START DEFINE BLOCK for querystring@0.2.0/encode.js **/
jupyter.define('querystring@0.2.0/encode.js', function (module, exports, __jupyter_require__) {
	// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.
	
	'use strict';
	
	var stringifyPrimitive = function(v) {
	  switch (typeof v) {
	    case 'string':
	      return v;
	
	    case 'boolean':
	      return v ? 'true' : 'false';
	
	    case 'number':
	      return isFinite(v) ? v : '';
	
	    default:
	      return '';
	  }
	};
	
	module.exports = function(obj, sep, eq, name) {
	  sep = sep || '&';
	  eq = eq || '=';
	  if (obj === null) {
	    obj = undefined;
	  }
	
	  if (typeof obj === 'object') {
	    return Object.keys(obj).map(function(k) {
	      var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
	      if (Array.isArray(obj[k])) {
	        return obj[k].map(function(v) {
	          return ks + encodeURIComponent(stringifyPrimitive(v));
	        }).join(sep);
	      } else {
	        return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
	      }
	    }).join(sep);
	
	  }
	
	  if (!name) return '';
	  return encodeURIComponent(stringifyPrimitive(name)) + eq +
	         encodeURIComponent(stringifyPrimitive(obj));
	};
	
})
/** END DEFINE BLOCK for querystring@0.2.0/encode.js **/


/** START DEFINE BLOCK for url-join@1.1.0/lib/url-join.js **/
jupyter.define('url-join@1.1.0/lib/url-join.js', function (module, exports, __jupyter_require__) {
	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (name, context, definition) {
	  if (typeof module !== 'undefined' && module.exports) module.exports = definition();
	  else if (true) !(__WEBPACK_AMD_DEFINE_FACTORY__ = (definition), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __jupyter_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	  else context[name] = definition();
	})('urljoin', this, function () {
	
	  function normalize (str, options) {
	
	    // make sure protocol is followed by two slashes
	    str = str.replace(/:\//g, '://');
	
	    // remove consecutive slashes
	    str = str.replace(/([^:\s])\/+/g, '$1/');
	
	    // remove trailing slash before parameters or hash
	    str = str.replace(/\/(\?|&|#[^!])/g, '$1');
	
	    // replace ? in parameters with &
	    str = str.replace(/(\?.+)\?/g, '$1&');
	
	    return str;
	  }
	
	  return function () {
	    var input = arguments;
	    var options = {};
	
	    if (typeof arguments[0] === 'object') {
	      // new syntax with array and options
	      input = arguments[0];
	      options = arguments[1] || {};
	    }
	
	    var joined = [].slice.call(input, 0).join('/');
	    return normalize(joined, options);
	  };
	
	});
	
})
/** END DEFINE BLOCK for url-join@1.1.0/lib/url-join.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/contents/index.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/contents/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var posix = __jupyter_require__('path-posix@^1.0.0/index.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	var validate = __jupyter_require__('@jupyterlab/services@0.36.1/lib/contents/validate.js');
	/**
	 * The url for the contents service.
	 */
	var SERVICE_CONTENTS_URL = 'api/contents';
	/**
	 * The url for the file access.
	 */
	var FILES_URL = 'files';
	/**
	 * A contents manager that passes file operations to the server.
	 *
	 * This includes checkpointing with the normal file operations.
	 */
	var ContentsManager = (function () {
	    /**
	     * Construct a new contents manager object.
	     *
	     * @param options - The options used to initialize the object.
	     */
	    function ContentsManager(options) {
	        if (options === void 0) { options = {}; }
	        this._baseUrl = '';
	        this._isDisposed = false;
	        this._ajaxSettings = null;
	        this._baseUrl = options.baseUrl || utils.getBaseUrl();
	        this._ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	    }
	    Object.defineProperty(ContentsManager.prototype, "isDisposed", {
	        /**
	         * Test whether the manager has been disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the manager.
	     */
	    ContentsManager.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        signaling_1.clearSignalData(this);
	    };
	    Object.defineProperty(ContentsManager.prototype, "baseUrl", {
	        /**
	         * Get the base url of the manager.
	         */
	        get: function () {
	            return this._baseUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ContentsManager.prototype, "ajaxSettings", {
	        /**
	         * Get a copy of the default ajax settings for the contents manager.
	         */
	        get: function () {
	            return utils.copy(this._ajaxSettings);
	        },
	        /**
	         * Set the default ajax settings for the contents manager.
	         */
	        set: function (value) {
	            this._ajaxSettings = utils.copy(value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Get a file or directory.
	     *
	     * @param path: The path to the file.
	     *
	     * @param options: The options used to fetch the file.
	     *
	     * @returns A promise which resolves with the file content.
	     *
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
	     */
	    ContentsManager.prototype.get = function (path, options) {
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'GET';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        var url = this._getUrl(path);
	        if (options) {
	            // The notebook type cannot take an format option.
	            if (options.type === 'notebook') {
	                delete options['format'];
	            }
	            var params = utils.copy(options);
	            params.content = options.content ? '1' : '0';
	            url += utils.jsonToQueryString(params);
	        }
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            try {
	                validate.validateContentsModel(success.data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            return success.data;
	        });
	    };
	    /**
	     * Get an encoded download url given a file path.
	     *
	     * @param path - An absolute POSIX file path on the server.
	     *
	     * #### Notes
	     * It is expected that the path contains no relative paths,
	     * use [[ContentsManager.getAbsolutePath]] to get an absolute
	     * path if necessary.
	     */
	    ContentsManager.prototype.getDownloadUrl = function (path) {
	        return Promise.resolve(utils.urlPathJoin(this._baseUrl, FILES_URL, utils.urlEncodeParts(path)));
	    };
	    /**
	     * Create a new untitled file or directory in the specified directory path.
	     *
	     * @param options: The options used to create the file.
	     *
	     * @returns A promise which resolves with the created file content when the
	     *    file is created.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
	     */
	    ContentsManager.prototype.newUntitled = function (options) {
	        var _this = this;
	        if (options === void 0) { options = {}; }
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'POST';
	        ajaxSettings.contentType = 'application/json';
	        ajaxSettings.dataType = 'json';
	        if (options) {
	            if (options.ext) {
	                options.ext = ContentsManager.normalizeExtension(options.ext);
	            }
	            ajaxSettings.data = JSON.stringify(options);
	        }
	        var url = this._getUrl(options.path || '');
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 201) {
	                return utils.makeAjaxError(success);
	            }
	            var data = success.data;
	            try {
	                validate.validateContentsModel(data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            _this.fileChanged.emit({
	                type: 'new',
	                oldValue: null,
	                newValue: data
	            });
	            return data;
	        });
	    };
	    /**
	     * Delete a file.
	     *
	     * @param path - The path to the file.
	     *
	     * @returns A promise which resolves when the file is deleted.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents).
	     */
	    ContentsManager.prototype.delete = function (path) {
	        var _this = this;
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'DELETE';
	        ajaxSettings.dataType = 'json';
	        var url = this._getUrl(path);
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 204) {
	                return utils.makeAjaxError(success);
	            }
	            _this.fileChanged.emit({
	                type: 'delete',
	                oldValue: { path: path },
	                newValue: null
	            });
	        }, function (error) {
	            // Translate certain errors to more specific ones.
	            // TODO: update IPEP27 to specify errors more precisely, so
	            // that error types can be detected here with certainty.
	            if (error.xhr.status === 400) {
	                var err = JSON.parse(error.xhr.response);
	                if (err.message) {
	                    error.throwError = err.message;
	                }
	            }
	            return Promise.reject(error);
	        });
	    };
	    /**
	     * Rename a file or directory.
	     *
	     * @param path - The original file path.
	     *
	     * @param newPath - The new file path.
	     *
	     * @returns A promise which resolves with the new file contents model when
	     *   the file is renamed.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
	     */
	    ContentsManager.prototype.rename = function (path, newPath) {
	        var _this = this;
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'PATCH';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.contentType = 'application/json';
	        ajaxSettings.data = JSON.stringify({ path: newPath });
	        var url = this._getUrl(path);
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            var data = success.data;
	            try {
	                validate.validateContentsModel(data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            _this.fileChanged.emit({
	                type: 'rename',
	                oldValue: { path: path },
	                newValue: data
	            });
	            return data;
	        });
	    };
	    /**
	     * Save a file.
	     *
	     * @param path - The desired file path.
	     *
	     * @param options - Optional overrides to the model.
	     *
	     * @returns A promise which resolves with the file content model when the
	     *   file is saved.
	     *
	     * #### Notes
	     * Ensure that `model.content` is populated for the file.
	     *
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
	     */
	    ContentsManager.prototype.save = function (path, options) {
	        var _this = this;
	        if (options === void 0) { options = {}; }
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'PUT';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.data = JSON.stringify(options);
	        ajaxSettings.contentType = 'application/json';
	        ajaxSettings.cache = false;
	        var url = this._getUrl(path);
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            // will return 200 for an existing file and 201 for a new file
	            if (success.xhr.status !== 200 && success.xhr.status !== 201) {
	                return utils.makeAjaxError(success);
	            }
	            var data = success.data;
	            try {
	                validate.validateContentsModel(data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            _this.fileChanged.emit({
	                type: 'save',
	                oldValue: null,
	                newValue: data
	            });
	            return data;
	        });
	    };
	    /**
	     * Copy a file into a given directory.
	     *
	     * @param path - The original file path.
	     *
	     * @param toDir - The destination directory path.
	     *
	     * @returns A promise which resolves with the new contents model when the
	     *  file is copied.
	     *
	     * #### Notes
	     * The server will select the name of the copied file.
	     *
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
	     */
	    ContentsManager.prototype.copy = function (fromFile, toDir) {
	        var _this = this;
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'POST';
	        ajaxSettings.data = JSON.stringify({ copy_from: fromFile });
	        ajaxSettings.contentType = 'application/json';
	        ajaxSettings.dataType = 'json';
	        var url = this._getUrl(toDir);
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 201) {
	                return utils.makeAjaxError(success);
	            }
	            var data = success.data;
	            try {
	                validate.validateContentsModel(data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            _this.fileChanged.emit({
	                type: 'new',
	                oldValue: null,
	                newValue: data
	            });
	            return data;
	        });
	    };
	    /**
	     * Create a checkpoint for a file.
	     *
	     * @param path - The path of the file.
	     *
	     * @returns A promise which resolves with the new checkpoint model when the
	     *   checkpoint is created.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
	     */
	    ContentsManager.prototype.createCheckpoint = function (path) {
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'POST';
	        ajaxSettings.dataType = 'json';
	        var url = this._getUrl(path, 'checkpoints');
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 201) {
	                return utils.makeAjaxError(success);
	            }
	            try {
	                validate.validateCheckpointModel(success.data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            return success.data;
	        });
	    };
	    /**
	     * List available checkpoints for a file.
	     *
	     * @param path - The path of the file.
	     *
	     * @returns A promise which resolves with a list of checkpoint models for
	     *    the file.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
	     */
	    ContentsManager.prototype.listCheckpoints = function (path) {
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'GET';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        var url = this._getUrl(path, 'checkpoints');
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            if (!Array.isArray(success.data)) {
	                return utils.makeAjaxError(success, 'Invalid Checkpoint list');
	            }
	            for (var i = 0; i < success.data.length; i++) {
	                try {
	                    validate.validateCheckpointModel(success.data[i]);
	                }
	                catch (err) {
	                    return utils.makeAjaxError(success, err.message);
	                }
	            }
	            return success.data;
	        });
	    };
	    /**
	     * Restore a file to a known checkpoint state.
	     *
	     * @param path - The path of the file.
	     *
	     * @param checkpointID - The id of the checkpoint to restore.
	     *
	     * @returns A promise which resolves when the checkpoint is restored.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents).
	     */
	    ContentsManager.prototype.restoreCheckpoint = function (path, checkpointID) {
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'POST';
	        ajaxSettings.dataType = 'json';
	        var url = this._getUrl(path, 'checkpoints', checkpointID);
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 204) {
	                return utils.makeAjaxError(success);
	            }
	        });
	    };
	    /**
	     * Delete a checkpoint for a file.
	     *
	     * @param path - The path of the file.
	     *
	     * @param checkpointID - The id of the checkpoint to delete.
	     *
	     * @returns A promise which resolves when the checkpoint is deleted.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents).
	     */
	    ContentsManager.prototype.deleteCheckpoint = function (path, checkpointID) {
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'DELETE';
	        ajaxSettings.dataType = 'json';
	        var url = this._getUrl(path, 'checkpoints', checkpointID);
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 204) {
	                return utils.makeAjaxError(success);
	            }
	        });
	    };
	    /**
	     * Get a REST url for a file given a path.
	     */
	    ContentsManager.prototype._getUrl = function () {
	        var args = [];
	        for (var _i = 0; _i < arguments.length; _i++) {
	            args[_i - 0] = arguments[_i];
	        }
	        var parts = args.map(function (path) { return utils.urlEncodeParts(path); });
	        return utils.urlPathJoin.apply(utils, [this._baseUrl, SERVICE_CONTENTS_URL].concat(parts));
	    };
	    return ContentsManager;
	}());
	exports.ContentsManager = ContentsManager;
	// Define the signals for the `ContentsManager` class.
	signaling_1.defineSignal(ContentsManager.prototype, 'fileChanged');
	/**
	 * A namespace for ContentsManager statics.
	 */
	var ContentsManager;
	(function (ContentsManager) {
	    /**
	     * Get the absolute POSIX path to a file on the server.
	     *
	     * @param relativePath - The relative POSIX path to the file.
	     *
	     * @param cwd - The optional POSIX current working directory.  The default is
	     *  an empty string.
	     *
	     * #### Notes
	     * Absolute path in this context is equivalent to a POSIX path without
	     * the initial `'/'` because IPEP 27 paths denote `''` as the root.
	     * If the resulting path is not contained within the server root,
	     * returns `null`, since it cannot be served.
	     */
	    function getAbsolutePath(relativePath, cwd) {
	        if (cwd === void 0) { cwd = ''; }
	        // Bail if it looks like a url.
	        var urlObj = utils.urlParse(relativePath);
	        if (urlObj.protocol) {
	            return relativePath;
	        }
	        var norm = posix.normalize(posix.join(cwd, relativePath));
	        if (norm.indexOf('../') === 0) {
	            return null;
	        }
	        return posix.resolve('/', cwd, relativePath).slice(1);
	    }
	    ContentsManager.getAbsolutePath = getAbsolutePath;
	    /**
	     * Get the last portion of a path, similar to the Unix basename command.
	     */
	    function basename(path, ext) {
	        return posix.basename(path, ext);
	    }
	    ContentsManager.basename = basename;
	    /**
	     * Get the directory name of a path, similar to the Unix dirname command.
	     */
	    function dirname(path) {
	        return posix.dirname(path);
	    }
	    ContentsManager.dirname = dirname;
	    /**
	     * Get the extension of the path.
	     *
	     * #### Notes
	     * The extension is the string from the last occurance of the `.`
	     * character to end of string in the last portion of the path.
	     * If there is no `.` in the last portion of the path, or if the first
	     * character of the basename of path [[basename]] is `.`, then an
	     * empty string is returned.
	     */
	    function extname(path) {
	        return posix.extname(path);
	    }
	    ContentsManager.extname = extname;
	    /**
	     * Normalize a file extension to be of the type `'.foo'`.
	     *
	     * Adds a leading dot if not present and converts to lower case.
	     */
	    function normalizeExtension(extension) {
	        if (extension.length > 0 && extension.indexOf('.') !== 0) {
	            extension = "." + extension;
	        }
	        return extension;
	    }
	    ContentsManager.normalizeExtension = normalizeExtension;
	})(ContentsManager = exports.ContentsManager || (exports.ContentsManager = {}));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/contents/index.js **/


/** START DEFINE BLOCK for path-posix@1.0.0/index.js **/
jupyter.define('path-posix@1.0.0/index.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.
	
	'use strict';
	var util = __jupyter_require__('util@0.10.3/util.js');
	var isString = function (x) {
	  return typeof x === 'string';
	};
	
	
	// resolves . and .. elements in a path array with directory names there
	// must be no slashes or device names (c:\) in the array
	// (so also no leading and trailing slashes - it does not distinguish
	// relative and absolute paths)
	function normalizeArray(parts, allowAboveRoot) {
	  var res = [];
	  for (var i = 0; i < parts.length; i++) {
	    var p = parts[i];
	
	    // ignore empty parts
	    if (!p || p === '.')
	      continue;
	
	    if (p === '..') {
	      if (res.length && res[res.length - 1] !== '..') {
	        res.pop();
	      } else if (allowAboveRoot) {
	        res.push('..');
	      }
	    } else {
	      res.push(p);
	    }
	  }
	
	  return res;
	}
	
	// Split a filename into [root, dir, basename, ext], unix version
	// 'root' is just a slash, or nothing.
	var splitPathRe =
	    /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
	var posix = {};
	
	
	function posixSplitPath(filename) {
	  return splitPathRe.exec(filename).slice(1);
	}
	
	
	// path.resolve([from ...], to)
	// posix version
	posix.resolve = function() {
	  var resolvedPath = '',
	      resolvedAbsolute = false;
	
	  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
	    var path = (i >= 0) ? arguments[i] : process.cwd();
	
	    // Skip empty and invalid entries
	    if (!isString(path)) {
	      throw new TypeError('Arguments to path.resolve must be strings');
	    } else if (!path) {
	      continue;
	    }
	
	    resolvedPath = path + '/' + resolvedPath;
	    resolvedAbsolute = path.charAt(0) === '/';
	  }
	
	  // At this point the path should be resolved to a full absolute path, but
	  // handle relative paths to be safe (might happen when process.cwd() fails)
	
	  // Normalize the path
	  resolvedPath = normalizeArray(resolvedPath.split('/'),
	                                !resolvedAbsolute).join('/');
	
	  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
	};
	
	// path.normalize(path)
	// posix version
	posix.normalize = function(path) {
	  var isAbsolute = posix.isAbsolute(path),
	      trailingSlash = path.substr(-1) === '/';
	
	  // Normalize the path
	  path = normalizeArray(path.split('/'), !isAbsolute).join('/');
	
	  if (!path && !isAbsolute) {
	    path = '.';
	  }
	  if (path && trailingSlash) {
	    path += '/';
	  }
	
	  return (isAbsolute ? '/' : '') + path;
	};
	
	// posix version
	posix.isAbsolute = function(path) {
	  return path.charAt(0) === '/';
	};
	
	// posix version
	posix.join = function() {
	  var path = '';
	  for (var i = 0; i < arguments.length; i++) {
	    var segment = arguments[i];
	    if (!isString(segment)) {
	      throw new TypeError('Arguments to path.join must be strings');
	    }
	    if (segment) {
	      if (!path) {
	        path += segment;
	      } else {
	        path += '/' + segment;
	      }
	    }
	  }
	  return posix.normalize(path);
	};
	
	
	// path.relative(from, to)
	// posix version
	posix.relative = function(from, to) {
	  from = posix.resolve(from).substr(1);
	  to = posix.resolve(to).substr(1);
	
	  function trim(arr) {
	    var start = 0;
	    for (; start < arr.length; start++) {
	      if (arr[start] !== '') break;
	    }
	
	    var end = arr.length - 1;
	    for (; end >= 0; end--) {
	      if (arr[end] !== '') break;
	    }
	
	    if (start > end) return [];
	    return arr.slice(start, end + 1);
	  }
	
	  var fromParts = trim(from.split('/'));
	  var toParts = trim(to.split('/'));
	
	  var length = Math.min(fromParts.length, toParts.length);
	  var samePartsLength = length;
	  for (var i = 0; i < length; i++) {
	    if (fromParts[i] !== toParts[i]) {
	      samePartsLength = i;
	      break;
	    }
	  }
	
	  var outputParts = [];
	  for (var i = samePartsLength; i < fromParts.length; i++) {
	    outputParts.push('..');
	  }
	
	  outputParts = outputParts.concat(toParts.slice(samePartsLength));
	
	  return outputParts.join('/');
	};
	
	
	posix._makeLong = function(path) {
	  return path;
	};
	
	
	posix.dirname = function(path) {
	  var result = posixSplitPath(path),
	      root = result[0],
	      dir = result[1];
	
	  if (!root && !dir) {
	    // No dirname whatsoever
	    return '.';
	  }
	
	  if (dir) {
	    // It has a dirname, strip trailing slash
	    dir = dir.substr(0, dir.length - 1);
	  }
	
	  return root + dir;
	};
	
	
	posix.basename = function(path, ext) {
	  var f = posixSplitPath(path)[2];
	  // TODO: make this comparison case-insensitive on windows?
	  if (ext && f.substr(-1 * ext.length) === ext) {
	    f = f.substr(0, f.length - ext.length);
	  }
	  return f;
	};
	
	
	posix.extname = function(path) {
	  return posixSplitPath(path)[3];
	};
	
	
	posix.format = function(pathObject) {
	  if (!util.isObject(pathObject)) {
	    throw new TypeError(
	        "Parameter 'pathObject' must be an object, not " + typeof pathObject
	    );
	  }
	
	  var root = pathObject.root || '';
	
	  if (!isString(root)) {
	    throw new TypeError(
	        "'pathObject.root' must be a string or undefined, not " +
	        typeof pathObject.root
	    );
	  }
	
	  var dir = pathObject.dir ? pathObject.dir + posix.sep : '';
	  var base = pathObject.base || '';
	  return dir + base;
	};
	
	
	posix.parse = function(pathString) {
	  if (!isString(pathString)) {
	    throw new TypeError(
	        "Parameter 'pathString' must be a string, not " + typeof pathString
	    );
	  }
	  var allParts = posixSplitPath(pathString);
	  if (!allParts || allParts.length !== 4) {
	    throw new TypeError("Invalid path '" + pathString + "'");
	  }
	  allParts[1] = allParts[1] || '';
	  allParts[2] = allParts[2] || '';
	  allParts[3] = allParts[3] || '';
	
	  return {
	    root: allParts[0],
	    dir: allParts[0] + allParts[1].slice(0, allParts[1].length - 1),
	    base: allParts[2],
	    ext: allParts[3],
	    name: allParts[2].slice(0, allParts[2].length - allParts[3].length)
	  };
	};
	
	
	posix.sep = '/';
	posix.delimiter = ':';
	
	  module.exports = posix;
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('process@0.11.9/browser.js')))
})
/** END DEFINE BLOCK for path-posix@1.0.0/index.js **/


/** START DEFINE BLOCK for util@0.10.3/util.js **/
jupyter.define('util@0.10.3/util.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.
	
	var formatRegExp = /%[sdj%]/g;
	exports.format = function(f) {
	  if (!isString(f)) {
	    var objects = [];
	    for (var i = 0; i < arguments.length; i++) {
	      objects.push(inspect(arguments[i]));
	    }
	    return objects.join(' ');
	  }
	
	  var i = 1;
	  var args = arguments;
	  var len = args.length;
	  var str = String(f).replace(formatRegExp, function(x) {
	    if (x === '%%') return '%';
	    if (i >= len) return x;
	    switch (x) {
	      case '%s': return String(args[i++]);
	      case '%d': return Number(args[i++]);
	      case '%j':
	        try {
	          return JSON.stringify(args[i++]);
	        } catch (_) {
	          return '[Circular]';
	        }
	      default:
	        return x;
	    }
	  });
	  for (var x = args[i]; i < len; x = args[++i]) {
	    if (isNull(x) || !isObject(x)) {
	      str += ' ' + x;
	    } else {
	      str += ' ' + inspect(x);
	    }
	  }
	  return str;
	};
	
	
	// Mark that a method should not be used.
	// Returns a modified function which warns once by default.
	// If --no-deprecation is set, then it is a no-op.
	exports.deprecate = function(fn, msg) {
	  // Allow for deprecating things in the process of starting up.
	  if (isUndefined(global.process)) {
	    return function() {
	      return exports.deprecate(fn, msg).apply(this, arguments);
	    };
	  }
	
	  if (process.noDeprecation === true) {
	    return fn;
	  }
	
	  var warned = false;
	  function deprecated() {
	    if (!warned) {
	      if (process.throwDeprecation) {
	        throw new Error(msg);
	      } else if (process.traceDeprecation) {
	        console.trace(msg);
	      } else {
	        console.error(msg);
	      }
	      warned = true;
	    }
	    return fn.apply(this, arguments);
	  }
	
	  return deprecated;
	};
	
	
	var debugs = {};
	var debugEnviron;
	exports.debuglog = function(set) {
	  if (isUndefined(debugEnviron))
	    debugEnviron = ({"GIT_DESCRIPTION":"v0.15.1"}).NODE_DEBUG || '';
	  set = set.toUpperCase();
	  if (!debugs[set]) {
	    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
	      var pid = process.pid;
	      debugs[set] = function() {
	        var msg = exports.format.apply(exports, arguments);
	        console.error('%s %d: %s', set, pid, msg);
	      };
	    } else {
	      debugs[set] = function() {};
	    }
	  }
	  return debugs[set];
	};
	
	
	/**
	 * Echos the value of a value. Trys to print the value out
	 * in the best way possible given the different types.
	 *
	 * @param {Object} obj The object to print out.
	 * @param {Object} opts Optional options object that alters the output.
	 */
	/* legacy: obj, showHidden, depth, colors*/
	function inspect(obj, opts) {
	  // default options
	  var ctx = {
	    seen: [],
	    stylize: stylizeNoColor
	  };
	  // legacy...
	  if (arguments.length >= 3) ctx.depth = arguments[2];
	  if (arguments.length >= 4) ctx.colors = arguments[3];
	  if (isBoolean(opts)) {
	    // legacy...
	    ctx.showHidden = opts;
	  } else if (opts) {
	    // got an "options" object
	    exports._extend(ctx, opts);
	  }
	  // set default options
	  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
	  if (isUndefined(ctx.depth)) ctx.depth = 2;
	  if (isUndefined(ctx.colors)) ctx.colors = false;
	  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
	  if (ctx.colors) ctx.stylize = stylizeWithColor;
	  return formatValue(ctx, obj, ctx.depth);
	}
	exports.inspect = inspect;
	
	
	// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
	inspect.colors = {
	  'bold' : [1, 22],
	  'italic' : [3, 23],
	  'underline' : [4, 24],
	  'inverse' : [7, 27],
	  'white' : [37, 39],
	  'grey' : [90, 39],
	  'black' : [30, 39],
	  'blue' : [34, 39],
	  'cyan' : [36, 39],
	  'green' : [32, 39],
	  'magenta' : [35, 39],
	  'red' : [31, 39],
	  'yellow' : [33, 39]
	};
	
	// Don't use 'blue' not visible on cmd.exe
	inspect.styles = {
	  'special': 'cyan',
	  'number': 'yellow',
	  'boolean': 'yellow',
	  'undefined': 'grey',
	  'null': 'bold',
	  'string': 'green',
	  'date': 'magenta',
	  // "name": intentionally not styling
	  'regexp': 'red'
	};
	
	
	function stylizeWithColor(str, styleType) {
	  var style = inspect.styles[styleType];
	
	  if (style) {
	    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
	           '\u001b[' + inspect.colors[style][1] + 'm';
	  } else {
	    return str;
	  }
	}
	
	
	function stylizeNoColor(str, styleType) {
	  return str;
	}
	
	
	function arrayToHash(array) {
	  var hash = {};
	
	  array.forEach(function(val, idx) {
	    hash[val] = true;
	  });
	
	  return hash;
	}
	
	
	function formatValue(ctx, value, recurseTimes) {
	  // Provide a hook for user-specified inspect functions.
	  // Check that value is an object with an inspect function on it
	  if (ctx.customInspect &&
	      value &&
	      isFunction(value.inspect) &&
	      // Filter out the util module, it's inspect function is special
	      value.inspect !== exports.inspect &&
	      // Also filter out any prototype objects using the circular check.
	      !(value.constructor && value.constructor.prototype === value)) {
	    var ret = value.inspect(recurseTimes, ctx);
	    if (!isString(ret)) {
	      ret = formatValue(ctx, ret, recurseTimes);
	    }
	    return ret;
	  }
	
	  // Primitive types cannot have properties
	  var primitive = formatPrimitive(ctx, value);
	  if (primitive) {
	    return primitive;
	  }
	
	  // Look up the keys of the object.
	  var keys = Object.keys(value);
	  var visibleKeys = arrayToHash(keys);
	
	  if (ctx.showHidden) {
	    keys = Object.getOwnPropertyNames(value);
	  }
	
	  // IE doesn't make error fields non-enumerable
	  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
	  if (isError(value)
	      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
	    return formatError(value);
	  }
	
	  // Some type of object without properties can be shortcutted.
	  if (keys.length === 0) {
	    if (isFunction(value)) {
	      var name = value.name ? ': ' + value.name : '';
	      return ctx.stylize('[Function' + name + ']', 'special');
	    }
	    if (isRegExp(value)) {
	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
	    }
	    if (isDate(value)) {
	      return ctx.stylize(Date.prototype.toString.call(value), 'date');
	    }
	    if (isError(value)) {
	      return formatError(value);
	    }
	  }
	
	  var base = '', array = false, braces = ['{', '}'];
	
	  // Make Array say that they are Array
	  if (isArray(value)) {
	    array = true;
	    braces = ['[', ']'];
	  }
	
	  // Make functions say that they are functions
	  if (isFunction(value)) {
	    var n = value.name ? ': ' + value.name : '';
	    base = ' [Function' + n + ']';
	  }
	
	  // Make RegExps say that they are RegExps
	  if (isRegExp(value)) {
	    base = ' ' + RegExp.prototype.toString.call(value);
	  }
	
	  // Make dates with properties first say the date
	  if (isDate(value)) {
	    base = ' ' + Date.prototype.toUTCString.call(value);
	  }
	
	  // Make error with message first say the error
	  if (isError(value)) {
	    base = ' ' + formatError(value);
	  }
	
	  if (keys.length === 0 && (!array || value.length == 0)) {
	    return braces[0] + base + braces[1];
	  }
	
	  if (recurseTimes < 0) {
	    if (isRegExp(value)) {
	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
	    } else {
	      return ctx.stylize('[Object]', 'special');
	    }
	  }
	
	  ctx.seen.push(value);
	
	  var output;
	  if (array) {
	    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
	  } else {
	    output = keys.map(function(key) {
	      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
	    });
	  }
	
	  ctx.seen.pop();
	
	  return reduceToSingleString(output, base, braces);
	}
	
	
	function formatPrimitive(ctx, value) {
	  if (isUndefined(value))
	    return ctx.stylize('undefined', 'undefined');
	  if (isString(value)) {
	    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
	                                             .replace(/'/g, "\\'")
	                                             .replace(/\\"/g, '"') + '\'';
	    return ctx.stylize(simple, 'string');
	  }
	  if (isNumber(value))
	    return ctx.stylize('' + value, 'number');
	  if (isBoolean(value))
	    return ctx.stylize('' + value, 'boolean');
	  // For some reason typeof null is "object", so special case here.
	  if (isNull(value))
	    return ctx.stylize('null', 'null');
	}
	
	
	function formatError(value) {
	  return '[' + Error.prototype.toString.call(value) + ']';
	}
	
	
	function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
	  var output = [];
	  for (var i = 0, l = value.length; i < l; ++i) {
	    if (hasOwnProperty(value, String(i))) {
	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
	          String(i), true));
	    } else {
	      output.push('');
	    }
	  }
	  keys.forEach(function(key) {
	    if (!key.match(/^\d+$/)) {
	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
	          key, true));
	    }
	  });
	  return output;
	}
	
	
	function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
	  var name, str, desc;
	  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
	  if (desc.get) {
	    if (desc.set) {
	      str = ctx.stylize('[Getter/Setter]', 'special');
	    } else {
	      str = ctx.stylize('[Getter]', 'special');
	    }
	  } else {
	    if (desc.set) {
	      str = ctx.stylize('[Setter]', 'special');
	    }
	  }
	  if (!hasOwnProperty(visibleKeys, key)) {
	    name = '[' + key + ']';
	  }
	  if (!str) {
	    if (ctx.seen.indexOf(desc.value) < 0) {
	      if (isNull(recurseTimes)) {
	        str = formatValue(ctx, desc.value, null);
	      } else {
	        str = formatValue(ctx, desc.value, recurseTimes - 1);
	      }
	      if (str.indexOf('\n') > -1) {
	        if (array) {
	          str = str.split('\n').map(function(line) {
	            return '  ' + line;
	          }).join('\n').substr(2);
	        } else {
	          str = '\n' + str.split('\n').map(function(line) {
	            return '   ' + line;
	          }).join('\n');
	        }
	      }
	    } else {
	      str = ctx.stylize('[Circular]', 'special');
	    }
	  }
	  if (isUndefined(name)) {
	    if (array && key.match(/^\d+$/)) {
	      return str;
	    }
	    name = JSON.stringify('' + key);
	    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
	      name = name.substr(1, name.length - 2);
	      name = ctx.stylize(name, 'name');
	    } else {
	      name = name.replace(/'/g, "\\'")
	                 .replace(/\\"/g, '"')
	                 .replace(/(^"|"$)/g, "'");
	      name = ctx.stylize(name, 'string');
	    }
	  }
	
	  return name + ': ' + str;
	}
	
	
	function reduceToSingleString(output, base, braces) {
	  var numLinesEst = 0;
	  var length = output.reduce(function(prev, cur) {
	    numLinesEst++;
	    if (cur.indexOf('\n') >= 0) numLinesEst++;
	    return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
	  }, 0);
	
	  if (length > 60) {
	    return braces[0] +
	           (base === '' ? '' : base + '\n ') +
	           ' ' +
	           output.join(',\n  ') +
	           ' ' +
	           braces[1];
	  }
	
	  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
	}
	
	
	// NOTE: These type checking functions intentionally don't use `instanceof`
	// because it is fragile and can be easily faked with `Object.create()`.
	function isArray(ar) {
	  return Array.isArray(ar);
	}
	exports.isArray = isArray;
	
	function isBoolean(arg) {
	  return typeof arg === 'boolean';
	}
	exports.isBoolean = isBoolean;
	
	function isNull(arg) {
	  return arg === null;
	}
	exports.isNull = isNull;
	
	function isNullOrUndefined(arg) {
	  return arg == null;
	}
	exports.isNullOrUndefined = isNullOrUndefined;
	
	function isNumber(arg) {
	  return typeof arg === 'number';
	}
	exports.isNumber = isNumber;
	
	function isString(arg) {
	  return typeof arg === 'string';
	}
	exports.isString = isString;
	
	function isSymbol(arg) {
	  return typeof arg === 'symbol';
	}
	exports.isSymbol = isSymbol;
	
	function isUndefined(arg) {
	  return arg === void 0;
	}
	exports.isUndefined = isUndefined;
	
	function isRegExp(re) {
	  return isObject(re) && objectToString(re) === '[object RegExp]';
	}
	exports.isRegExp = isRegExp;
	
	function isObject(arg) {
	  return typeof arg === 'object' && arg !== null;
	}
	exports.isObject = isObject;
	
	function isDate(d) {
	  return isObject(d) && objectToString(d) === '[object Date]';
	}
	exports.isDate = isDate;
	
	function isError(e) {
	  return isObject(e) &&
	      (objectToString(e) === '[object Error]' || e instanceof Error);
	}
	exports.isError = isError;
	
	function isFunction(arg) {
	  return typeof arg === 'function';
	}
	exports.isFunction = isFunction;
	
	function isPrimitive(arg) {
	  return arg === null ||
	         typeof arg === 'boolean' ||
	         typeof arg === 'number' ||
	         typeof arg === 'string' ||
	         typeof arg === 'symbol' ||  // ES6 symbol
	         typeof arg === 'undefined';
	}
	exports.isPrimitive = isPrimitive;
	
	exports.isBuffer = __jupyter_require__('util@0.10.3/support/isBufferBrowser.js');
	
	function objectToString(o) {
	  return Object.prototype.toString.call(o);
	}
	
	
	function pad(n) {
	  return n < 10 ? '0' + n.toString(10) : n.toString(10);
	}
	
	
	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
	              'Oct', 'Nov', 'Dec'];
	
	// 26 Feb 16:19:34
	function timestamp() {
	  var d = new Date();
	  var time = [pad(d.getHours()),
	              pad(d.getMinutes()),
	              pad(d.getSeconds())].join(':');
	  return [d.getDate(), months[d.getMonth()], time].join(' ');
	}
	
	
	// log is just a thin wrapper to console.log that prepends a timestamp
	exports.log = function() {
	  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
	};
	
	
	/**
	 * Inherit the prototype methods from one constructor into another.
	 *
	 * The Function.prototype.inherits from lang.js rewritten as a standalone
	 * function (not on Function.prototype). NOTE: If this file is to be loaded
	 * during bootstrapping this function needs to be rewritten using some native
	 * functions as prototype setup using normal JavaScript does not work as
	 * expected during bootstrapping (see mirror.js in r114903).
	 *
	 * @param {function} ctor Constructor function which needs to inherit the
	 *     prototype.
	 * @param {function} superCtor Constructor function to inherit prototype from.
	 */
	exports.inherits = __jupyter_require__('inherits@2.0.1/inherits_browser.js');
	
	exports._extend = function(origin, add) {
	  // Don't do anything if add isn't an object
	  if (!add || !isObject(add)) return origin;
	
	  var keys = Object.keys(add);
	  var i = keys.length;
	  while (i--) {
	    origin[keys[i]] = add[keys[i]];
	  }
	  return origin;
	};
	
	function hasOwnProperty(obj, prop) {
	  return Object.prototype.hasOwnProperty.call(obj, prop);
	}
	
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __jupyter_require__('process@0.11.9/browser.js')))
})
/** END DEFINE BLOCK for util@0.10.3/util.js **/


/** START DEFINE BLOCK for util@0.10.3/support/isBufferBrowser.js **/
jupyter.define('util@0.10.3/support/isBufferBrowser.js', function (module, exports, __jupyter_require__) {
	module.exports = function isBuffer(arg) {
	  return arg && typeof arg === 'object'
	    && typeof arg.copy === 'function'
	    && typeof arg.fill === 'function'
	    && typeof arg.readUInt8 === 'function';
	}
})
/** END DEFINE BLOCK for util@0.10.3/support/isBufferBrowser.js **/


/** START DEFINE BLOCK for inherits@2.0.1/inherits_browser.js **/
jupyter.define('inherits@2.0.1/inherits_browser.js', function (module, exports, __jupyter_require__) {
	if (typeof Object.create === 'function') {
	  // implementation from standard node.js 'util' module
	  module.exports = function inherits(ctor, superCtor) {
	    ctor.super_ = superCtor
	    ctor.prototype = Object.create(superCtor.prototype, {
	      constructor: {
	        value: ctor,
	        enumerable: false,
	        writable: true,
	        configurable: true
	      }
	    });
	  };
	} else {
	  // old school shim for old browsers
	  module.exports = function inherits(ctor, superCtor) {
	    ctor.super_ = superCtor
	    var TempCtor = function () {}
	    TempCtor.prototype = superCtor.prototype
	    ctor.prototype = new TempCtor()
	    ctor.prototype.constructor = ctor
	  }
	}
	
})
/** END DEFINE BLOCK for inherits@2.0.1/inherits_browser.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/core/signaling.js **/
jupyter.define('phosphor@0.7.0/lib/core/signaling.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(setImmediate) {/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * Define a signal property on a prototype object.
	 *
	 * @param target - The prototype for the class of interest.
	 *
	 * @param name - The name of the signal property.
	 *
	 * #### Notes
	 * The defined signal property is read-only.
	 *
	 * #### Example
	 * ```typescript
	 * class SomeClass {
	 *   valueChanged: ISignal<SomeClass, number>;
	 * }
	 *
	 * defineSignal(SomeClass.prototype, 'valueChanged');
	 */
	function defineSignal(target, name) {
	    var token = Object.freeze({});
	    Object.defineProperty(target, name, {
	        get: function () { return new Signal(this, token); }
	    });
	}
	exports.defineSignal = defineSignal;
	/**
	 * Remove all connections where the given object is the sender.
	 *
	 * @param sender - The sender object of interest.
	 *
	 * #### Example
	 * ```typescript
	 * disconnectSender(someObject);
	 * ```
	 */
	function disconnectSender(sender) {
	    // If there are no receivers, there is nothing to do.
	    var receiverList = senderData.get(sender);
	    if (receiverList === void 0) {
	        return;
	    }
	    // Clear the connections and schedule a cleanup of the
	    // receiver's corresponding list of sender connections.
	    for (var i = 0, n = receiverList.length; i < n; ++i) {
	        var conn = receiverList[i];
	        var senderList = receiverData.get(conn.thisArg || conn.slot);
	        scheduleCleanup(senderList);
	        conn.token = null;
	    }
	    // Schedule a cleanup of the receiver list.
	    scheduleCleanup(receiverList);
	}
	exports.disconnectSender = disconnectSender;
	/**
	 * Remove all connections where the given object is the receiver.
	 *
	 * @param receiver - The receiver object of interest.
	 *
	 * #### Notes
	 * If a `thisArg` is provided when connecting a signal, that object
	 * is considered the receiver. Otherwise, the `callback` is used as
	 * the receiver.
	 *
	 * #### Example
	 * ```typescript
	 * // disconnect a regular object receiver
	 * disconnectReceiver(myObject);
	 *
	 * // disconnect a plain callback receiver
	 * disconnectReceiver(myCallback);
	 * ```
	 */
	function disconnectReceiver(receiver) {
	    // If there are no senders, there is nothing to do.
	    var senderList = receiverData.get(receiver);
	    if (senderList === void 0) {
	        return;
	    }
	    // Clear the connections and schedule a cleanup of the
	    // senders's corresponding list of receiver connections.
	    for (var i = 0, n = senderList.length; i < n; ++i) {
	        var conn = senderList[i];
	        var receiverList = senderData.get(conn.sender);
	        scheduleCleanup(receiverList);
	        conn.token = null;
	    }
	    // Schedule a cleanup of the sender list.
	    scheduleCleanup(senderList);
	}
	exports.disconnectReceiver = disconnectReceiver;
	/**
	 * Clear all signal data associated with the given object.
	 *
	 * @param obj - The object for which the signal data should be cleared.
	 *
	 * #### Notes
	 * This removes all signal connections where the object is used as
	 * either the sender or the receiver.
	 *
	 * #### Example
	 * ```typescript
	 * clearSignalData(someObject);
	 * ```
	 */
	function clearSignalData(obj) {
	    disconnectSender(obj);
	    disconnectReceiver(obj);
	}
	exports.clearSignalData = clearSignalData;
	/**
	 * A concrete implementation of `ISignal`.
	 */
	var Signal = (function () {
	    /**
	     * Construct a new signal.
	     *
	     * @param sender - The object which owns the signal.
	     *
	     * @param token - The unique token identifying the signal.
	     */
	    function Signal(sender, token) {
	        this._sender = sender;
	        this._token = token;
	    }
	    /**
	     * Connect a slot to the signal.
	     *
	     * @param slot - The slot to invoke when the signal is emitted.
	     *
	     * @param thisArg - The `this` context for the slot. If provided,
	     *   this must be a non-primitive object.
	     *
	     * @returns `true` if the connection succeeds, `false` otherwise.
	     */
	    Signal.prototype.connect = function (slot, thisArg) {
	        return connect(this._sender, this._token, slot, thisArg);
	    };
	    /**
	     * Disconnect a slot from the signal.
	     *
	     * @param slot - The slot to disconnect from the signal.
	     *
	     * @param thisArg - The `this` context for the slot. If provided,
	     *   this must be a non-primitive object.
	     *
	     * @returns `true` if the connection is removed, `false` otherwise.
	     */
	    Signal.prototype.disconnect = function (slot, thisArg) {
	        return disconnect(this._sender, this._token, slot, thisArg);
	    };
	    /**
	     * Emit the signal and invoke the connected slots.
	     *
	     * @param args - The args to pass to the connected slots.
	     */
	    Signal.prototype.emit = function (args) {
	        emit(this._sender, this._token, args);
	    };
	    return Signal;
	}());
	/**
	 * A weak mapping of sender to list of receiver connections.
	 */
	var senderData = new WeakMap();
	/**
	 * A weak mapping of receiver to list of sender connections.
	 */
	var receiverData = new WeakMap();
	/**
	 * A set of connection lists which are pending cleanup.
	 */
	var dirtySet = new Set();
	/**
	 * A local reference to an event loop callback.
	 */
	var defer = (function () {
	    var ok = typeof requestAnimationFrame === 'function';
	    return ok ? requestAnimationFrame : setImmediate;
	})();
	/**
	 * Connect a slot to a signal.
	 *
	 * @param sender - The object emitting the signal.
	 *
	 * @param token - The unique token for the signal.
	 *
	 * @param slot - The slot to connect to the signal.
	 *
	 * @param thisArg - The `this` context for the slot.
	 *
	 * @returns `true` if the connection succeeds, `false` otherwise.
	 *
	 * #### Notes
	 * Signal connections are unique. If a connection already exists for
	 * the given `slot` and `thisArg`, this function returns `false`.
	 *
	 * A newly connected slot will not be invoked until the next time the
	 * signal is emitted, even if the slot is connected while the signal
	 * is dispatching.
	 */
	function connect(sender, token, slot, thisArg) {
	    // Coerce a `null` thisArg to `undefined`.
	    thisArg = thisArg || void 0;
	    // Ensure the sender's receiver list is created.
	    var receiverList = senderData.get(sender);
	    if (receiverList === void 0) {
	        receiverList = [];
	        senderData.set(sender, receiverList);
	    }
	    // Bail if a matching connection already exists.
	    if (findConnection(receiverList, token, slot, thisArg) !== null) {
	        return false;
	    }
	    // Ensure the receiver's sender list is created.
	    var receiver = thisArg || slot;
	    var senderList = receiverData.get(receiver);
	    if (senderList === void 0) {
	        senderList = [];
	        receiverData.set(receiver, senderList);
	    }
	    // Create a new connection and add it to the end of each list.
	    var connection = { sender: sender, token: token, slot: slot, thisArg: thisArg };
	    receiverList.push(connection);
	    senderList.push(connection);
	    // Indicate a successful connection.
	    return true;
	}
	/**
	 * Disconnect a slot from a signal.
	 *
	 * @param sender - The object emitting the signal.
	 *
	 * @param token - The unique token for the signal.
	 *
	 * @param slot - The slot to disconnect from the signal.
	 *
	 * @param thisArg - The `this` context for the slot.
	 *
	 * @returns `true` if the connection is removed, `false` otherwise.
	 *
	 * #### Notes
	 * If no connection exists for the given `slot` and `thisArg`, this
	 * function returns `false`.
	 *
	 * A disconnected slot will no longer be invoked, even if the slot
	 * is disconnected while the signal is dispatching.
	 */
	function disconnect(sender, token, slot, thisArg) {
	    // Coerce a `null` thisArg to `undefined`.
	    thisArg = thisArg || void 0;
	    // Lookup the list of receivers, and bail if none exist.
	    var receiverList = senderData.get(sender);
	    if (receiverList === void 0) {
	        return false;
	    }
	    // Bail if no matching connection exits.
	    var conn = findConnection(receiverList, token, slot, thisArg);
	    if (conn === null) {
	        return false;
	    }
	    // Lookup the list of senders, which is now known to exist.
	    var senderList = receiverData.get(thisArg || slot);
	    // Clear the connection and schedule list cleanup.
	    conn.token = null;
	    scheduleCleanup(receiverList);
	    scheduleCleanup(senderList);
	    // Indicate a successful disconnection.
	    return true;
	}
	/**
	 * Emit a signal and invoke the connected slots.
	 *
	 * @param sender - The object emitting the signal.
	 *
	 * @param token - The unique token for the signal.
	 *
	 * @param args - The args to pass to the connected slots.
	 *
	 * #### Notes
	 * Connected slots are invoked synchronously, in the order in which
	 * they are connected.
	 *
	 * Exceptions thrown by connected slots will be caught and logged.
	 */
	function emit(sender, token, args) {
	    // If there are no receivers, there is nothing to do.
	    var receiverList = senderData.get(sender);
	    if (receiverList === void 0) {
	        return;
	    }
	    // Invoke the connections which match the given token.
	    for (var i = 0, n = receiverList.length; i < n; ++i) {
	        var conn = receiverList[i];
	        if (conn.token === token) {
	            invokeSlot(conn, args);
	        }
	    }
	}
	/**
	 * Safely invoke a non-empty connection.
	 *
	 * @param conn - The connection of interest
	 *
	 * @param args - The arguments to pass to the slot.
	 *
	 * #### Notes
	 * Any exception thrown by the slot will be caught and logged.
	 */
	function invokeSlot(conn, args) {
	    try {
	        conn.slot.call(conn.thisArg, conn.sender, args);
	    }
	    catch (err) {
	        console.error(err);
	    }
	}
	/**
	 * Find a connection which matches the given parameters.
	 *
	 * @param list - The list of connections to search.
	 *
	 * @param token - The unique token for the signal.
	 *
	 * @param slot - The slot of interest.
	 *
	 * @param thisArg - The `this` context for the slot.
	 *
	 * @returns The first connection which matches the supplied parameters,
	 *   or null if no matching connection is found.
	 */
	function findConnection(list, token, slot, thisArg) {
	    for (var i = 0, n = list.length; i < n; ++i) {
	        var conn = list[i];
	        if (conn.token === token &&
	            conn.slot === slot &&
	            conn.thisArg === thisArg) {
	            return conn;
	        }
	    }
	    return null;
	}
	/**
	 * Schedule a cleanup of a connection list.
	 *
	 * @param list - The list of connections to cleanup.
	 *
	 * #### Notes
	 * This will add the list to the dirty set and schedule a deferred
	 * cleanup of the list contents. On cleanup, any connection with a
	 * null token will be removed from the array.
	 */
	function scheduleCleanup(list) {
	    if (dirtySet.size === 0) {
	        defer(cleanupDirtySet);
	    }
	    dirtySet.add(list);
	}
	/**
	 * Cleanup the connection lists in the dirty set.
	 *
	 * #### Notes
	 * This function should only be invoked asynchronously, when the stack
	 * frame is guaranteed to not be on the path of a signal dispatch.
	 */
	function cleanupDirtySet() {
	    dirtySet.forEach(cleanupList);
	    dirtySet.clear();
	}
	/**
	 * Cleanup the dirty connections in a connection list.
	 *
	 * @param list - The list of connection to cleanup.
	 *
	 * #### Notes
	 * This will remove any connection with a null token from the list,
	 * while retaining the relative order of the other connections.
	 *
	 * This function should only be invoked asynchronously, when the stack
	 * frame is guaranteed to not be on the path of a signal dispatch.
	 */
	function cleanupList(list) {
	    var count = 0;
	    for (var i = 0, n = list.length; i < n; ++i) {
	        var conn = list[i];
	        if (conn.token === null) {
	            count++;
	        }
	        else {
	            list[i - count] = conn;
	        }
	    }
	    list.length -= count;
	}
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('timers-browserify@2.0.2/main.js').setImmediate))
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/core/signaling.js **/


/** START DEFINE BLOCK for timers-browserify@2.0.2/main.js **/
jupyter.define('timers-browserify@2.0.2/main.js', function (module, exports, __jupyter_require__) {
	var apply = Function.prototype.apply;
	
	// DOM APIs, for completeness
	
	exports.setTimeout = function() {
	  return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
	};
	exports.setInterval = function() {
	  return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
	};
	exports.clearTimeout =
	exports.clearInterval = function(timeout) {
	  if (timeout) {
	    timeout.close();
	  }
	};
	
	function Timeout(id, clearFn) {
	  this._id = id;
	  this._clearFn = clearFn;
	}
	Timeout.prototype.unref = Timeout.prototype.ref = function() {};
	Timeout.prototype.close = function() {
	  this._clearFn.call(window, this._id);
	};
	
	// Does not start the time, just sets up the members needed.
	exports.enroll = function(item, msecs) {
	  clearTimeout(item._idleTimeoutId);
	  item._idleTimeout = msecs;
	};
	
	exports.unenroll = function(item) {
	  clearTimeout(item._idleTimeoutId);
	  item._idleTimeout = -1;
	};
	
	exports._unrefActive = exports.active = function(item) {
	  clearTimeout(item._idleTimeoutId);
	
	  var msecs = item._idleTimeout;
	  if (msecs >= 0) {
	    item._idleTimeoutId = setTimeout(function onTimeout() {
	      if (item._onTimeout)
	        item._onTimeout();
	    }, msecs);
	  }
	};
	
	// setimmediate attaches itself to the global object
	__jupyter_require__('setimmediate@^1.0.4/setImmediate.js');
	exports.setImmediate = setImmediate;
	exports.clearImmediate = clearImmediate;
	
})
/** END DEFINE BLOCK for timers-browserify@2.0.2/main.js **/


/** START DEFINE BLOCK for setimmediate@1.0.5/setImmediate.js **/
jupyter.define('setimmediate@1.0.5/setImmediate.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) {
	    "use strict";
	
	    if (global.setImmediate) {
	        return;
	    }
	
	    var nextHandle = 1; // Spec says greater than zero
	    var tasksByHandle = {};
	    var currentlyRunningATask = false;
	    var doc = global.document;
	    var registerImmediate;
	
	    function setImmediate(callback) {
	      // Callback can either be a function or a string
	      if (typeof callback !== "function") {
	        callback = new Function("" + callback);
	      }
	      // Copy function arguments
	      var args = new Array(arguments.length - 1);
	      for (var i = 0; i < args.length; i++) {
	          args[i] = arguments[i + 1];
	      }
	      // Store and register the task
	      var task = { callback: callback, args: args };
	      tasksByHandle[nextHandle] = task;
	      registerImmediate(nextHandle);
	      return nextHandle++;
	    }
	
	    function clearImmediate(handle) {
	        delete tasksByHandle[handle];
	    }
	
	    function run(task) {
	        var callback = task.callback;
	        var args = task.args;
	        switch (args.length) {
	        case 0:
	            callback();
	            break;
	        case 1:
	            callback(args[0]);
	            break;
	        case 2:
	            callback(args[0], args[1]);
	            break;
	        case 3:
	            callback(args[0], args[1], args[2]);
	            break;
	        default:
	            callback.apply(undefined, args);
	            break;
	        }
	    }
	
	    function runIfPresent(handle) {
	        // From the spec: "Wait until any invocations of this algorithm started before this one have completed."
	        // So if we're currently running a task, we'll need to delay this invocation.
	        if (currentlyRunningATask) {
	            // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
	            // "too much recursion" error.
	            setTimeout(runIfPresent, 0, handle);
	        } else {
	            var task = tasksByHandle[handle];
	            if (task) {
	                currentlyRunningATask = true;
	                try {
	                    run(task);
	                } finally {
	                    clearImmediate(handle);
	                    currentlyRunningATask = false;
	                }
	            }
	        }
	    }
	
	    function installNextTickImplementation() {
	        registerImmediate = function(handle) {
	            process.nextTick(function () { runIfPresent(handle); });
	        };
	    }
	
	    function canUsePostMessage() {
	        // The test against `importScripts` prevents this implementation from being installed inside a web worker,
	        // where `global.postMessage` means something completely different and can't be used for this purpose.
	        if (global.postMessage && !global.importScripts) {
	            var postMessageIsAsynchronous = true;
	            var oldOnMessage = global.onmessage;
	            global.onmessage = function() {
	                postMessageIsAsynchronous = false;
	            };
	            global.postMessage("", "*");
	            global.onmessage = oldOnMessage;
	            return postMessageIsAsynchronous;
	        }
	    }
	
	    function installPostMessageImplementation() {
	        // Installs an event handler on `global` for the `message` event: see
	        // * https://developer.mozilla.org/en/DOM/window.postMessage
	        // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
	
	        var messagePrefix = "setImmediate$" + Math.random() + "$";
	        var onGlobalMessage = function(event) {
	            if (event.source === global &&
	                typeof event.data === "string" &&
	                event.data.indexOf(messagePrefix) === 0) {
	                runIfPresent(+event.data.slice(messagePrefix.length));
	            }
	        };
	
	        if (global.addEventListener) {
	            global.addEventListener("message", onGlobalMessage, false);
	        } else {
	            global.attachEvent("onmessage", onGlobalMessage);
	        }
	
	        registerImmediate = function(handle) {
	            global.postMessage(messagePrefix + handle, "*");
	        };
	    }
	
	    function installMessageChannelImplementation() {
	        var channel = new MessageChannel();
	        channel.port1.onmessage = function(event) {
	            var handle = event.data;
	            runIfPresent(handle);
	        };
	
	        registerImmediate = function(handle) {
	            channel.port2.postMessage(handle);
	        };
	    }
	
	    function installReadyStateChangeImplementation() {
	        var html = doc.documentElement;
	        registerImmediate = function(handle) {
	            // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
	            // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
	            var script = doc.createElement("script");
	            script.onreadystatechange = function () {
	                runIfPresent(handle);
	                script.onreadystatechange = null;
	                html.removeChild(script);
	                script = null;
	            };
	            html.appendChild(script);
	        };
	    }
	
	    function installSetTimeoutImplementation() {
	        registerImmediate = function(handle) {
	            setTimeout(runIfPresent, 0, handle);
	        };
	    }
	
	    // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
	    var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
	    attachTo = attachTo && attachTo.setTimeout ? attachTo : global;
	
	    // Don't get fooled by e.g. browserify environments.
	    if ({}.toString.call(global.process) === "[object process]") {
	        // For Node.js before 0.9
	        installNextTickImplementation();
	
	    } else if (canUsePostMessage()) {
	        // For non-IE10 modern browsers
	        installPostMessageImplementation();
	
	    } else if (global.MessageChannel) {
	        // For web workers, where supported
	        installMessageChannelImplementation();
	
	    } else if (doc && "onreadystatechange" in doc.createElement("script")) {
	        // For IE 6–8
	        installReadyStateChangeImplementation();
	
	    } else {
	        // For older browsers
	        installSetTimeoutImplementation();
	    }
	
	    attachTo.setImmediate = setImmediate;
	    attachTo.clearImmediate = clearImmediate;
	}(typeof self === "undefined" ? typeof global === "undefined" ? this : global : self));
	
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __jupyter_require__('process@0.11.9/browser.js')))
})
/** END DEFINE BLOCK for setimmediate@1.0.5/setImmediate.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/contents/validate.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/contents/validate.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * Validate a property as being on an object, and optionally
	 * of a given type.
	 */
	function validateProperty(object, name, typeName) {
	    if (!object.hasOwnProperty(name)) {
	        throw Error("Missing property '" + name + "'");
	    }
	    if (typeName !== void 0) {
	        var valid = true;
	        var value = object[name];
	        switch (typeName) {
	            case 'array':
	                valid = Array.isArray(value);
	                break;
	            case 'object':
	                valid = typeof value !== 'undefined';
	                break;
	            default:
	                valid = typeof value === typeName;
	        }
	        if (!valid) {
	            throw new Error("Property '" + name + "' is not of type '" + typeName);
	        }
	    }
	}
	/**
	 * Validate an `Contents.IModel` object.
	 */
	function validateContentsModel(model) {
	    validateProperty(model, 'name', 'string');
	    validateProperty(model, 'path', 'string');
	    validateProperty(model, 'type', 'string');
	    validateProperty(model, 'created', 'string');
	    validateProperty(model, 'last_modified', 'string');
	    validateProperty(model, 'mimetype', 'object');
	    validateProperty(model, 'content', 'object');
	    validateProperty(model, 'format', 'object');
	}
	exports.validateContentsModel = validateContentsModel;
	/**
	 * Validate an `Contents.ICheckpointModel` object.
	 */
	function validateCheckpointModel(model) {
	    validateProperty(model, 'id', 'string');
	    validateProperty(model, 'last_modified', 'string');
	}
	exports.validateCheckpointModel = validateCheckpointModel;
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/contents/validate.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/index.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/kernel/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	'use strict';
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/kernel.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/manager.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/messages.js'));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/index.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/kernel.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/kernel/kernel.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var default_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/default.js');
	/**
	 * A namespace for kernel types, interfaces, and type checker functions.
	 */
	var Kernel;
	(function (Kernel) {
	    /**
	     * Find a kernel by id.
	     *
	     * #### Notes
	     * If the kernel was already started via `startNewKernel`, we return its
	     * `Kernel.IModel`.
	     *
	     * Otherwise, if `options` are given, we attempt to find to the existing
	     * kernel.
	     * The promise is fulfilled when the kernel is found,
	     * otherwise the promise is rejected.
	     */
	    function findById(id, options) {
	        return default_1.DefaultKernel.findById(id, options);
	    }
	    Kernel.findById = findById;
	    /**
	     * Fetch all of the kernel specs.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernelspecs).
	     */
	    function getSpecs(options) {
	        if (options === void 0) { options = {}; }
	        return default_1.DefaultKernel.getSpecs(options);
	    }
	    Kernel.getSpecs = getSpecs;
	    /**
	     * Fetch the running kernels.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernels) and validates the response model.
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     */
	    function listRunning(options) {
	        if (options === void 0) { options = {}; }
	        return default_1.DefaultKernel.listRunning(options);
	    }
	    Kernel.listRunning = listRunning;
	    /**
	     * Start a new kernel.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernels) and validates the response model.
	     *
	     * If no options are given or the kernel name is not given, the
	     * default kernel will by started by the server.
	     *
	     * Wraps the result in a Kernel object. The promise is fulfilled
	     * when the kernel is started by the server, otherwise the promise is rejected.
	     */
	    function startNew(options) {
	        options = options || {};
	        return default_1.DefaultKernel.startNew(options);
	    }
	    Kernel.startNew = startNew;
	    /**
	     * Connect to a running kernel.
	     *
	     * #### Notes
	     * If the kernel was already started via `startNewKernel`, the existing
	     * Kernel object info is used to create another instance.
	     *
	     * Otherwise, if `options` are given, we attempt to connect to the existing
	     * kernel found by calling `listRunningKernels`.
	     * The promise is fulfilled when the kernel is running on the server,
	     * otherwise the promise is rejected.
	     *
	     * If the kernel was not already started and no `options` are given,
	     * the promise is rejected.
	     */
	    function connectTo(id, options) {
	        return default_1.DefaultKernel.connectTo(id, options);
	    }
	    Kernel.connectTo = connectTo;
	    /**
	     * Shut down a kernel by id.
	     */
	    function shutdown(id, options) {
	        if (options === void 0) { options = {}; }
	        return default_1.DefaultKernel.shutdown(id, options);
	    }
	    Kernel.shutdown = shutdown;
	})(Kernel = exports.Kernel || (exports.Kernel = {}));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/kernel.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/default.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/kernel/default.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var comm_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/comm.js');
	var messages_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/messages.js');
	var future_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/future.js');
	var serialize = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/serialize.js');
	var validate = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/validate.js');
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	/**
	 * The url for the kernel service.
	 */
	var KERNEL_SERVICE_URL = 'api/kernels';
	/**
	 * The url for the kernelspec service.
	 */
	var KERNELSPEC_SERVICE_URL = 'api/kernelspecs';
	/**
	 * Implementation of the Kernel object
	 */
	var DefaultKernel = (function () {
	    /**
	     * Construct a kernel object.
	     */
	    function DefaultKernel(options, id) {
	        this._id = '';
	        this._token = '';
	        this._name = '';
	        this._baseUrl = '';
	        this._wsUrl = '';
	        this._status = 'unknown';
	        this._clientId = '';
	        this._ws = null;
	        this._username = '';
	        this._ajaxSettings = '{}';
	        this._reconnectLimit = 7;
	        this._reconnectAttempt = 0;
	        this._isReady = false;
	        this._futures = null;
	        this._commPromises = null;
	        this._comms = null;
	        this._targetRegistry = Object.create(null);
	        this._info = null;
	        this._pendingMessages = [];
	        this._connectionPromise = null;
	        this._specPromise = null;
	        this._name = options.name;
	        this._id = id;
	        this._baseUrl = options.baseUrl || utils.getBaseUrl();
	        this._wsUrl = options.wsUrl || utils.getWsUrl(this._baseUrl);
	        this._ajaxSettings = JSON.stringify(utils.ajaxSettingsWithToken(options.ajaxSettings, options.token));
	        this._token = options.token || utils.getConfigOption('token');
	        this._clientId = options.clientId || utils.uuid();
	        this._username = options.username || '';
	        this._futures = new Map();
	        this._commPromises = new Map();
	        this._comms = new Map();
	        this._createSocket();
	        Private.runningKernels.pushBack(this);
	    }
	    Object.defineProperty(DefaultKernel.prototype, "id", {
	        /**
	         * The id of the server-side kernel.
	         */
	        get: function () {
	            return this._id;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "name", {
	        /**
	         * The name of the server-side kernel.
	         */
	        get: function () {
	            return this._name;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "model", {
	        /**
	         * Get the model associated with the kernel.
	         */
	        get: function () {
	            return { name: this.name, id: this.id };
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "username", {
	        /**
	         * The client username.
	         */
	        get: function () {
	            return this._username;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "clientId", {
	        /**
	         * The client unique id.
	         */
	        get: function () {
	            return this._clientId;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "status", {
	        /**
	         * The current status of the kernel.
	         */
	        get: function () {
	            return this._status;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "baseUrl", {
	        /**
	         * The base url of the kernel.
	         */
	        get: function () {
	            return this._baseUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "ajaxSettings", {
	        /**
	         * Get a copy of the default ajax settings for the kernel.
	         */
	        get: function () {
	            return JSON.parse(this._ajaxSettings);
	        },
	        /**
	         * Set the default ajax settings for the kernel.
	         */
	        set: function (value) {
	            this._ajaxSettings = JSON.stringify(value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "isDisposed", {
	        /**
	         * Test whether the kernel has been disposed.
	         */
	        get: function () {
	            return this._futures === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "info", {
	        /**
	         * The cached kernel info.
	         *
	         * #### Notes
	         * This value will be null until the kernel is ready.
	         */
	        get: function () {
	            return this._info;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "isReady", {
	        /**
	         * Test whether the kernel is ready.
	         */
	        get: function () {
	            return this._isReady;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultKernel.prototype, "ready", {
	        /**
	         * A promise that is fulfilled when the kernel is ready.
	         */
	        get: function () {
	            return this._connectionPromise.promise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Get the kernel spec.
	     *
	     * @returns A promise that resolves with the kernel spec.
	     */
	    DefaultKernel.prototype.getSpec = function () {
	        var _this = this;
	        if (this._specPromise) {
	            return this._specPromise;
	        }
	        var options = {
	            baseUrl: this._baseUrl,
	            ajaxSettings: this.ajaxSettings
	        };
	        this._specPromise = Private.findSpecs(options).then(function (specs) {
	            return specs.kernelspecs[_this._name];
	        });
	        return this._specPromise;
	    };
	    /**
	     * Clone the current kernel with a new clientId.
	     */
	    DefaultKernel.prototype.clone = function () {
	        var options = {
	            baseUrl: this._baseUrl,
	            wsUrl: this._wsUrl,
	            name: this._name,
	            username: this._username,
	            token: this._token,
	            ajaxSettings: this.ajaxSettings
	        };
	        return new DefaultKernel(options, this._id);
	    };
	    /**
	     * Dispose of the resources held by the kernel.
	     */
	    DefaultKernel.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._status = 'dead';
	        if (this._ws !== null) {
	            this._ws.close();
	        }
	        this._ws = null;
	        this._futures.forEach(function (future, key) {
	            future.dispose();
	        });
	        this._comms.forEach(function (comm, key) {
	            comm.dispose();
	        });
	        this._futures = null;
	        this._commPromises = null;
	        this._comms = null;
	        this._targetRegistry = null;
	        Private.runningKernels.remove(this);
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Send a shell message to the kernel.
	     *
	     * #### Notes
	     * Send a message to the kernel's shell channel, yielding a future object
	     * for accepting replies.
	     *
	     * If `expectReply` is given and `true`, the future is disposed when both a
	     * shell reply and an idle status message are received. If `expectReply`
	     * is not given or is `false`, the future is resolved when an idle status
	     * message is received.
	     * If `disposeOnDone` is not given or is `true`, the Future is disposed at this point.
	     * If `disposeOnDone` is given and `false`, it is up to the caller to dispose of the Future.
	     *
	     * All replies are validated as valid kernel messages.
	     *
	     * If the kernel status is `dead`, this will throw an error.
	     */
	    DefaultKernel.prototype.sendShellMessage = function (msg, expectReply, disposeOnDone) {
	        var _this = this;
	        if (expectReply === void 0) { expectReply = false; }
	        if (disposeOnDone === void 0) { disposeOnDone = true; }
	        if (this.status === 'dead') {
	            throw new Error('Kernel is dead');
	        }
	        if (!this._isReady) {
	            this._pendingMessages.push(msg);
	        }
	        else {
	            this._ws.send(serialize.serialize(msg));
	        }
	        var future = new future_1.KernelFutureHandler(function () {
	            _this._futures.delete(msg.header.msg_id);
	        }, msg, expectReply, disposeOnDone);
	        this._futures.set(msg.header.msg_id, future);
	        return future;
	    };
	    /**
	     * Interrupt a kernel.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernels).
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     *
	     * It is assumed that the API call does not mutate the kernel id or name.
	     *
	     * The promise will be rejected if the kernel status is `Dead` or if the
	     * request fails or the response is invalid.
	     */
	    DefaultKernel.prototype.interrupt = function () {
	        return Private.interruptKernel(this, this._baseUrl, this.ajaxSettings);
	    };
	    /**
	     * Restart a kernel.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernels) and validates the response model.
	     *
	     * Any existing Future or Comm objects are cleared.
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     *
	     * It is assumed that the API call does not mutate the kernel id or name.
	     *
	     * The promise will be rejected if the request fails or the response is
	     * invalid.
	     */
	    DefaultKernel.prototype.restart = function () {
	        this._clearState();
	        this._updateStatus('restarting');
	        return Private.restartKernel(this, this._baseUrl, this.ajaxSettings);
	    };
	    /**
	     * Reconnect to a disconnected kernel.
	     *
	     * #### Notes
	     * Used when the websocket connection to the kernel is lost.
	     */
	    DefaultKernel.prototype.reconnect = function () {
	        this._isReady = false;
	        if (this._ws !== null) {
	            // Clear the websocket event handlers and the socket itself.
	            this._ws.onopen = null;
	            this._ws.onclose = null;
	            this._ws.onerror = null;
	            this._ws.onmessage = null;
	            this._ws.close();
	            this._ws = null;
	        }
	        this._updateStatus('reconnecting');
	        this._createSocket();
	        return this._connectionPromise.promise;
	    };
	    /**
	     * Shutdown a kernel.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernels).
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     *
	     * On a valid response, closes the websocket and disposes of the kernel
	     * object, and fulfills the promise.
	     *
	     * The promise will be rejected if the kernel status is `Dead` or if the
	     * request fails or the response is invalid.
	     */
	    DefaultKernel.prototype.shutdown = function () {
	        if (this.status === 'dead') {
	            return Promise.reject(new Error('Kernel is dead'));
	        }
	        this._clearState();
	        return Private.shutdownKernel(this.id, this._baseUrl, this.ajaxSettings);
	    };
	    /**
	     * Send a `kernel_info_request` message.
	     *
	     * #### Notes
	     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#kernel-info).
	     *
	     * Fulfills with the `kernel_info_response` content when the shell reply is
	     * received and validated.
	     */
	    DefaultKernel.prototype.requestKernelInfo = function () {
	        var _this = this;
	        var options = {
	            msgType: 'kernel_info_request',
	            channel: 'shell',
	            username: this._username,
	            session: this._clientId
	        };
	        var msg = messages_1.KernelMessage.createShellMessage(options);
	        return Private.handleShellMessage(this, msg).then(function (reply) {
	            _this._info = reply.content;
	            return reply;
	        });
	    };
	    /**
	     * Send a `complete_request` message.
	     *
	     * #### Notes
	     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#completion).
	     *
	     * Fulfills with the `complete_reply` content when the shell reply is
	     * received and validated.
	     */
	    DefaultKernel.prototype.requestComplete = function (content) {
	        var options = {
	            msgType: 'complete_request',
	            channel: 'shell',
	            username: this._username,
	            session: this._clientId
	        };
	        var msg = messages_1.KernelMessage.createShellMessage(options, content);
	        return Private.handleShellMessage(this, msg);
	    };
	    /**
	     * Send an `inspect_request` message.
	     *
	     * #### Notes
	     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#introspection).
	     *
	     * Fulfills with the `inspect_reply` content when the shell reply is
	     * received and validated.
	     */
	    DefaultKernel.prototype.requestInspect = function (content) {
	        var options = {
	            msgType: 'inspect_request',
	            channel: 'shell',
	            username: this._username,
	            session: this._clientId
	        };
	        var msg = messages_1.KernelMessage.createShellMessage(options, content);
	        return Private.handleShellMessage(this, msg);
	    };
	    /**
	     * Send a `history_request` message.
	     *
	     * #### Notes
	     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#history).
	     *
	     * Fulfills with the `history_reply` content when the shell reply is
	     * received and validated.
	     */
	    DefaultKernel.prototype.requestHistory = function (content) {
	        var options = {
	            msgType: 'history_request',
	            channel: 'shell',
	            username: this._username,
	            session: this._clientId
	        };
	        var msg = messages_1.KernelMessage.createShellMessage(options, content);
	        return Private.handleShellMessage(this, msg);
	    };
	    /**
	     * Send an `execute_request` message.
	     *
	     * #### Notes
	     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#execute).
	     *
	     * Future `onReply` is called with the `execute_reply` content when the
	     * shell reply is received and validated. The future will resolve when
	     * this message is received and the `idle` iopub status is received.
	     * The future will also be disposed at this point unless `disposeOnDone`
	     * is specified and `false`, in which case it is up to the caller to dispose
	     * of the future.
	     *
	     * **See also:** [[IExecuteReply]]
	     */
	    DefaultKernel.prototype.requestExecute = function (content, disposeOnDone) {
	        if (disposeOnDone === void 0) { disposeOnDone = true; }
	        var options = {
	            msgType: 'execute_request',
	            channel: 'shell',
	            username: this._username,
	            session: this._clientId
	        };
	        var defaults = {
	            silent: false,
	            store_history: true,
	            user_expressions: {},
	            allow_stdin: true,
	            stop_on_error: false
	        };
	        content = utils.extend(defaults, content);
	        var msg = messages_1.KernelMessage.createShellMessage(options, content);
	        return this.sendShellMessage(msg, true, disposeOnDone);
	    };
	    /**
	     * Send an `is_complete_request` message.
	     *
	     * #### Notes
	     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#code-completeness).
	     *
	     * Fulfills with the `is_complete_response` content when the shell reply is
	     * received and validated.
	     */
	    DefaultKernel.prototype.requestIsComplete = function (content) {
	        var options = {
	            msgType: 'is_complete_request',
	            channel: 'shell',
	            username: this._username,
	            session: this._clientId
	        };
	        var msg = messages_1.KernelMessage.createShellMessage(options, content);
	        return Private.handleShellMessage(this, msg);
	    };
	    /**
	     * Send a `comm_info_request` message.
	     *
	     * #### Notes
	     * Fulfills with the `comm_info_reply` content when the shell reply is
	     * received and validated.
	     */
	    DefaultKernel.prototype.requestCommInfo = function (content) {
	        var options = {
	            msgType: 'comm_info_request',
	            channel: 'shell',
	            username: this._username,
	            session: this._clientId
	        };
	        var msg = messages_1.KernelMessage.createShellMessage(options, content);
	        return Private.handleShellMessage(this, msg);
	    };
	    /**
	     * Send an `input_reply` message.
	     *
	     * #### Notes
	     * See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#messages-on-the-stdin-router-dealer-sockets).
	     */
	    DefaultKernel.prototype.sendInputReply = function (content) {
	        if (this.status === 'dead') {
	            throw new Error('Kernel is dead');
	        }
	        var options = {
	            msgType: 'input_reply',
	            channel: 'stdin',
	            username: this._username,
	            session: this._clientId
	        };
	        var msg = messages_1.KernelMessage.createMessage(options, content);
	        if (!this._isReady) {
	            this._pendingMessages.push(msg);
	        }
	        else {
	            this._ws.send(serialize.serialize(msg));
	        }
	    };
	    /**
	     * Register an IOPub message hook.
	     *
	     * @param msg_id - The parent_header message id the hook will intercept.
	     *
	     * @param hook - The callback invoked for the message.
	     *
	     * @returns A disposable used to unregister the message hook.
	     *
	     * #### Notes
	     * The IOPub hook system allows you to preempt the handlers for IOPub messages with a
	     * given parent_header message id. The most recently registered hook is run first.
	     * If the hook returns false, any later hooks and the future's onIOPub handler will not run.
	     * If a hook throws an error, the error is logged to the console and the next hook is run.
	     * If a hook is registered during the hook processing, it won't run until the next message.
	     * If a hook is disposed during the hook processing, it will be deactivated immediately.
	     *
	     * See also [[IFuture.registerMessageHook]].
	     */
	    DefaultKernel.prototype.registerMessageHook = function (msgId, hook) {
	        var _this = this;
	        var future = this._futures && this._futures.get(msgId);
	        if (future) {
	            future.registerMessageHook(hook);
	        }
	        return new disposable_1.DisposableDelegate(function () {
	            future = _this._futures && _this._futures.get(msgId);
	            if (future) {
	                future.removeMessageHook(hook);
	            }
	        });
	    };
	    /**
	     * Register a comm target handler.
	     *
	     * @param targetName - The name of the comm target.
	     *
	     * @param callback - The callback invoked for a comm open message.
	     *
	     * @returns A disposable used to unregister the comm target.
	     *
	     * #### Notes
	     * Only one comm target can be registered at a time, an existing
	     * callback will be overidden.  A registered comm target handler will take
	     * precedence over a comm which specifies a `target_module`.
	     */
	    DefaultKernel.prototype.registerCommTarget = function (targetName, callback) {
	        var _this = this;
	        this._targetRegistry[targetName] = callback;
	        return new disposable_1.DisposableDelegate(function () {
	            if (!_this.isDisposed) {
	                delete _this._targetRegistry[targetName];
	            }
	        });
	    };
	    /**
	     * Connect to a comm, or create a new one.
	     *
	     * #### Notes
	     * If a client-side comm already exists, it is returned.
	     */
	    DefaultKernel.prototype.connectToComm = function (targetName, commId) {
	        var _this = this;
	        if (commId === void 0) {
	            commId = utils.uuid();
	        }
	        var comm = this._comms.get(commId);
	        if (!comm) {
	            comm = new comm_1.CommHandler(targetName, commId, this, function () { _this._unregisterComm(commId); });
	            this._comms.set(commId, comm);
	        }
	        return comm;
	    };
	    /**
	     * Create the kernel websocket connection and add socket status handlers.
	     */
	    DefaultKernel.prototype._createSocket = function () {
	        var _this = this;
	        var partialUrl = utils.urlPathJoin(this._wsUrl, KERNEL_SERVICE_URL, encodeURIComponent(this._id));
	        // Strip any authentication from the display string.
	        var parsed = utils.urlParse(partialUrl);
	        var display = partialUrl.replace(parsed.auth, '');
	        var url = utils.urlPathJoin(partialUrl, 'channels?session_id=' + encodeURIComponent(this._clientId));
	        // if token authentication is in use
	        if (this._token !== '') {
	            url = url + ("&token=" + encodeURIComponent(this._token));
	        }
	        console.log('Starting websocket', display);
	        this._connectionPromise = new utils.PromiseDelegate();
	        this._ws = new WebSocket(url);
	        // Ensure incoming binary messages are not Blobs
	        this._ws.binaryType = 'arraybuffer';
	        this._ws.onmessage = function (evt) { _this._onWSMessage(evt); };
	        this._ws.onopen = function (evt) { _this._onWSOpen(evt); };
	        this._ws.onclose = function (evt) { _this._onWSClose(evt); };
	        this._ws.onerror = function (evt) { _this._onWSClose(evt); };
	    };
	    /**
	     * Handle a websocket open event.
	     */
	    DefaultKernel.prototype._onWSOpen = function (evt) {
	        var _this = this;
	        this._reconnectAttempt = 0;
	        // Allow the message to get through.
	        this._isReady = true;
	        // Get the kernel info, signaling that the kernel is ready.
	        this.requestKernelInfo().then(function () {
	            _this._connectionPromise.resolve(void 0);
	        }).catch(function (err) {
	            _this._connectionPromise.reject(err);
	        });
	        this._isReady = false;
	    };
	    /**
	     * Handle a websocket message, validating and routing appropriately.
	     */
	    DefaultKernel.prototype._onWSMessage = function (evt) {
	        if (this.status === 'dead') {
	            // If the socket is being closed, ignore any messages
	            return;
	        }
	        var msg = serialize.deserialize(evt.data);
	        try {
	            validate.validateMessage(msg);
	        }
	        catch (error) {
	            console.error("Invalid message: " + error.message);
	            return;
	        }
	        if (msg.parent_header) {
	            var parentHeader = msg.parent_header;
	            var future = this._futures && this._futures.get(parentHeader.msg_id);
	            if (future) {
	                future.handleMsg(msg);
	            }
	            else {
	                // If the message was sent by us and was not iopub, it is orphaned.
	                var owned = parentHeader.session === this.clientId;
	                if (msg.channel !== 'iopub' && owned) {
	                    this.unhandledMessage.emit(msg);
	                }
	            }
	        }
	        if (msg.channel === 'iopub') {
	            switch (msg.header.msg_type) {
	                case 'status':
	                    this._updateStatus(msg.content.execution_state);
	                    break;
	                case 'comm_open':
	                    this._handleCommOpen(msg);
	                    break;
	                case 'comm_msg':
	                    this._handleCommMsg(msg);
	                    break;
	                case 'comm_close':
	                    this._handleCommClose(msg);
	                    break;
	            }
	            this.iopubMessage.emit(msg);
	        }
	    };
	    /**
	     * Handle a websocket close event.
	     */
	    DefaultKernel.prototype._onWSClose = function (evt) {
	        if (this.status === 'dead') {
	            return;
	        }
	        // Clear the websocket event handlers and the socket itself.
	        this._ws.onclose = null;
	        this._ws.onerror = null;
	        this._ws = null;
	        if (this._reconnectAttempt < this._reconnectLimit) {
	            this._updateStatus('reconnecting');
	            var timeout = Math.pow(2, this._reconnectAttempt);
	            console.error('Connection lost, reconnecting in ' + timeout + ' seconds.');
	            setTimeout(this._createSocket.bind(this), 1e3 * timeout);
	            this._reconnectAttempt += 1;
	        }
	        else {
	            this._updateStatus('dead');
	            this._connectionPromise.reject(new Error('Could not establish connection'));
	        }
	    };
	    /**
	     * Handle status iopub messages from the kernel.
	     */
	    DefaultKernel.prototype._updateStatus = function (status) {
	        switch (status) {
	            case 'starting':
	            case 'idle':
	            case 'busy':
	                this._isReady = true;
	                break;
	            case 'restarting':
	            case 'reconnecting':
	            case 'dead':
	                this._isReady = false;
	                break;
	            default:
	                console.error('invalid kernel status:', status);
	                return;
	        }
	        if (status !== this._status) {
	            this._status = status;
	            Private.logKernelStatus(this);
	            this.statusChanged.emit(status);
	            if (status === 'dead') {
	                this.dispose();
	            }
	        }
	        if (this._isReady) {
	            this._sendPending();
	        }
	    };
	    /**
	     * Send pending messages to the kernel.
	     */
	    DefaultKernel.prototype._sendPending = function () {
	        // We shift the message off the queue
	        // after the message is sent so that if there is an exception,
	        // the message is still pending.
	        while (this._pendingMessages.length > 0) {
	            var msg = serialize.serialize(this._pendingMessages[0]);
	            this._ws.send(msg);
	            this._pendingMessages.shift();
	        }
	    };
	    /**
	     * Clear the internal state.
	     */
	    DefaultKernel.prototype._clearState = function () {
	        this._isReady = false;
	        this._pendingMessages = [];
	        this._futures.forEach(function (future, key) {
	            future.dispose();
	        });
	        this._comms.forEach(function (comm, key) {
	            comm.dispose();
	        });
	        this._futures = new Map();
	        this._commPromises = new Map();
	        this._comms = new Map();
	    };
	    /**
	     * Handle a `comm_open` kernel message.
	     */
	    DefaultKernel.prototype._handleCommOpen = function (msg) {
	        var _this = this;
	        var content = msg.content;
	        var promise = utils.loadObject(content.target_name, content.target_module, this._targetRegistry).then(function (target) {
	            var comm = new comm_1.CommHandler(content.target_name, content.comm_id, _this, function () { _this._unregisterComm(content.comm_id); });
	            var response;
	            try {
	                response = target(comm, msg);
	            }
	            catch (e) {
	                comm.close();
	                console.error('Exception opening new comm');
	                throw (e);
	            }
	            return Promise.resolve(response).then(function () {
	                _this._commPromises.delete(comm.commId);
	                _this._comms.set(comm.commId, comm);
	                return comm;
	            });
	        });
	        this._commPromises.set(content.comm_id, promise);
	    };
	    /**
	     * Handle 'comm_close' kernel message.
	     */
	    DefaultKernel.prototype._handleCommClose = function (msg) {
	        var _this = this;
	        var content = msg.content;
	        var promise = this._commPromises.get(content.comm_id);
	        if (!promise) {
	            var comm = this._comms.get(content.comm_id);
	            if (!comm) {
	                console.error('Comm not found for comm id ' + content.comm_id);
	                return;
	            }
	            promise = Promise.resolve(comm);
	        }
	        promise.then(function (comm) {
	            _this._unregisterComm(comm.commId);
	            try {
	                var onClose = comm.onClose;
	                if (onClose) {
	                    onClose(msg);
	                }
	                comm.dispose();
	            }
	            catch (e) {
	                console.error('Exception closing comm: ', e, e.stack, msg);
	            }
	        });
	    };
	    /**
	     * Handle a 'comm_msg' kernel message.
	     */
	    DefaultKernel.prototype._handleCommMsg = function (msg) {
	        var content = msg.content;
	        var promise = this._commPromises.get(content.comm_id);
	        if (!promise) {
	            var comm = this._comms.get(content.comm_id);
	            if (!comm) {
	                // We do have a registered comm for this comm id, ignore.
	                return;
	            }
	            else {
	                var onMsg = comm.onMsg;
	                if (onMsg) {
	                    onMsg(msg);
	                }
	            }
	        }
	        else {
	            promise.then(function (comm) {
	                try {
	                    var onMsg = comm.onMsg;
	                    if (onMsg) {
	                        onMsg(msg);
	                    }
	                }
	                catch (e) {
	                    console.error('Exception handling comm msg: ', e, e.stack, msg);
	                }
	                return comm;
	            });
	        }
	    };
	    /**
	     * Unregister a comm instance.
	     */
	    DefaultKernel.prototype._unregisterComm = function (commId) {
	        this._comms.delete(commId);
	        this._commPromises.delete(commId);
	    };
	    return DefaultKernel;
	}());
	exports.DefaultKernel = DefaultKernel;
	// Define the signals for the `DefaultKernel` class.
	signaling_1.defineSignal(DefaultKernel.prototype, 'terminated');
	signaling_1.defineSignal(DefaultKernel.prototype, 'statusChanged');
	signaling_1.defineSignal(DefaultKernel.prototype, 'iopubMessage');
	signaling_1.defineSignal(DefaultKernel.prototype, 'unhandledMessage');
	/**
	 * The namespace for `DefaultKernel` statics.
	 */
	var DefaultKernel;
	(function (DefaultKernel) {
	    /**
	     * Find a kernel by id.
	     *
	     * #### Notes
	     * If the kernel was already started via `startNewKernel`, we return its
	     * `Kernel.IModel`.
	     *
	     * Otherwise, if `options` are given, we attempt to find the existing
	     * kernel.
	     * The promise is fulfilled when the kernel is found,
	     * otherwise the promise is rejected.
	     */
	    function findById(id, options) {
	        return Private.findById(id, options);
	    }
	    DefaultKernel.findById = findById;
	    /**
	     * Fetch all of the kernel specs.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernelspecs).
	     */
	    function getSpecs(options) {
	        if (options === void 0) { options = {}; }
	        return Private.getSpecs(options);
	    }
	    DefaultKernel.getSpecs = getSpecs;
	    /**
	     * Fetch the running kernels.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernels) and validates the response model.
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     */
	    function listRunning(options) {
	        if (options === void 0) { options = {}; }
	        return Private.listRunning(options);
	    }
	    DefaultKernel.listRunning = listRunning;
	    /**
	     * Start a new kernel.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernels) and validates the response model.
	     *
	     * If no options are given or the kernel name is not given, the
	     * default kernel will by started by the server.
	     *
	     * Wraps the result in a Kernel object. The promise is fulfilled
	     * when the kernel is started by the server, otherwise the promise is rejected.
	     */
	    function startNew(options) {
	        options = options || {};
	        return Private.startNew(options);
	    }
	    DefaultKernel.startNew = startNew;
	    /**
	     * Connect to a running kernel.
	     *
	     * #### Notes
	     * If the kernel was already started via `startNewKernel`, the existing
	     * Kernel object info is used to create another instance.
	     *
	     * Otherwise, if `options` are given, we attempt to connect to the existing
	     * kernel found by calling `listRunningKernels`.
	     * The promise is fulfilled when the kernel is running on the server,
	     * otherwise the promise is rejected.
	     *
	     * If the kernel was not already started and no `options` are given,
	     * the promise is rejected.
	     */
	    function connectTo(id, options) {
	        return Private.connectTo(id, options);
	    }
	    DefaultKernel.connectTo = connectTo;
	    /**
	     * Shut down a kernel by id.
	     */
	    function shutdown(id, options) {
	        if (options === void 0) { options = {}; }
	        return Private.shutdown(id, options);
	    }
	    DefaultKernel.shutdown = shutdown;
	})(DefaultKernel = exports.DefaultKernel || (exports.DefaultKernel = {}));
	/**
	 * A private namespace for the Kernel.
	 */
	var Private;
	(function (Private) {
	    /**
	     * A module private store for running kernels.
	     */
	    Private.runningKernels = new vector_1.Vector();
	    /**
	     * A module private store of kernel specs by base url.
	     */
	    Private.specs = Object.create(null);
	    /**
	     * Find a kernel by id.
	     */
	    function findById(id, options) {
	        var kernel = searching_1.find(Private.runningKernels, function (value) {
	            return (value.id === id);
	        });
	        if (kernel) {
	            return Promise.resolve(kernel.model);
	        }
	        return getKernelModel(id, options).catch(function () {
	            throw new Error("No running kernel with id: " + id);
	        });
	    }
	    Private.findById = findById;
	    /**
	     * Get the cached kernel specs or fetch them.
	     */
	    function findSpecs(options) {
	        var promise = Private.specs[options.baseUrl];
	        if (promise) {
	            return promise;
	        }
	        return getSpecs(options);
	    }
	    Private.findSpecs = findSpecs;
	    /**
	     * Fetch all of the kernel specs.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernelspecs).
	     */
	    function getSpecs(options) {
	        if (options === void 0) { options = {}; }
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var url = utils.urlPathJoin(baseUrl, KERNELSPEC_SERVICE_URL);
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'GET';
	        ajaxSettings.dataType = 'json';
	        var promise = utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            try {
	                return validate.validateSpecModels(success.data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	        });
	        Private.specs[baseUrl] = promise;
	        return promise;
	    }
	    Private.getSpecs = getSpecs;
	    /**
	     * Fetch the running kernels.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/kernels) and validates the response model.
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     */
	    function listRunning(options) {
	        if (options === void 0) { options = {}; }
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var url = utils.urlPathJoin(baseUrl, KERNEL_SERVICE_URL);
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'GET';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            if (!Array.isArray(success.data)) {
	                return utils.makeAjaxError(success, 'Invalid kernel list');
	            }
	            for (var i = 0; i < success.data.length; i++) {
	                try {
	                    validate.validateModel(success.data[i]);
	                }
	                catch (err) {
	                    return utils.makeAjaxError(success, err.message);
	                }
	            }
	            return updateRunningKernels(success.data);
	        }, onKernelError);
	    }
	    Private.listRunning = listRunning;
	    /**
	     * Update the running kernels based on new data from the server.
	     */
	    function updateRunningKernels(kernels) {
	        iteration_1.each(Private.runningKernels, function (kernel) {
	            var updated = searching_1.find(kernels, function (model) {
	                if (kernel.id === model.id) {
	                    return true;
	                }
	            });
	            // If kernel is no longer running on disk, emit dead signal.
	            if (!updated && kernel.status !== 'dead') {
	                kernel.terminated.emit(void 0);
	                kernel.dispose();
	            }
	        });
	        return kernels;
	    }
	    Private.updateRunningKernels = updateRunningKernels;
	    /**
	     * Start a new kernel.
	     */
	    function startNew(options) {
	        options = options || {};
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var url = utils.urlPathJoin(baseUrl, KERNEL_SERVICE_URL);
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'POST';
	        ajaxSettings.data = JSON.stringify({ name: options.name });
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.contentType = 'application/json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 201) {
	                return utils.makeAjaxError(success);
	            }
	            validate.validateModel(success.data);
	            options = utils.copy(options);
	            options.name = success.data.name;
	            return new DefaultKernel(options, success.data.id);
	        }, onKernelError);
	    }
	    Private.startNew = startNew;
	    /**
	     * Connect to a running kernel.
	     *
	     * #### Notes
	     * If the kernel was already started via `startNewKernel`, the existing
	     * Kernel object info is used to create another instance.
	     *
	     * Otherwise, if `options` are given, we attempt to connect to the existing
	     * kernel found by calling `listRunningKernels`.
	     * The promise is fulfilled when the kernel is running on the server,
	     * otherwise the promise is rejected.
	     *
	     * If the kernel was not already started and no `options` are given,
	     * the promise is rejected.
	     */
	    function connectTo(id, options) {
	        var kernel = searching_1.find(Private.runningKernels, function (value) {
	            return value.id === id;
	        });
	        if (kernel) {
	            return Promise.resolve(kernel.clone());
	        }
	        return getKernelModel(id, options).then(function (model) {
	            options = utils.copy(options);
	            options.name = model.name;
	            return new DefaultKernel(options, id);
	        }).catch(function () {
	            throw new Error("No running kernel with id: " + id);
	        });
	    }
	    Private.connectTo = connectTo;
	    /**
	     * Shut down a kernel by id.
	     */
	    function shutdown(id, options) {
	        if (options === void 0) { options = {}; }
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        return shutdownKernel(id, baseUrl, ajaxSettings);
	    }
	    Private.shutdown = shutdown;
	    /**
	     * Restart a kernel.
	     */
	    function restartKernel(kernel, baseUrl, ajaxSettings) {
	        if (kernel.status === 'dead') {
	            return Promise.reject(new Error('Kernel is dead'));
	        }
	        var url = utils.urlPathJoin(baseUrl, KERNEL_SERVICE_URL, encodeURIComponent(kernel.id), 'restart');
	        ajaxSettings = ajaxSettings || {};
	        ajaxSettings.method = 'POST';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            try {
	                validate.validateModel(success.data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	        }, onKernelError);
	    }
	    Private.restartKernel = restartKernel;
	    /**
	     * Interrupt a kernel.
	     */
	    function interruptKernel(kernel, baseUrl, ajaxSettings) {
	        if (kernel.status === 'dead') {
	            return Promise.reject(new Error('Kernel is dead'));
	        }
	        var url = utils.urlPathJoin(baseUrl, KERNEL_SERVICE_URL, encodeURIComponent(kernel.id), 'interrupt');
	        ajaxSettings = ajaxSettings || {};
	        ajaxSettings.method = 'POST';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 204) {
	                return utils.makeAjaxError(success);
	            }
	        }, onKernelError);
	    }
	    Private.interruptKernel = interruptKernel;
	    /**
	     * Delete a kernel.
	     */
	    function shutdownKernel(id, baseUrl, ajaxSettings) {
	        var url = utils.urlPathJoin(baseUrl, KERNEL_SERVICE_URL, encodeURIComponent(id));
	        ajaxSettings = ajaxSettings || {};
	        ajaxSettings.method = 'DELETE';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 204) {
	                return utils.makeAjaxError(success);
	            }
	            killKernels(id);
	        }, function (error) {
	            if (error.xhr.status === 404) {
	                var response = JSON.parse(error.xhr.responseText);
	                console.warn(response['message']);
	                killKernels(id);
	            }
	            else {
	                return onKernelError(error);
	            }
	        });
	    }
	    Private.shutdownKernel = shutdownKernel;
	    /**
	     * Kill the kernels by id.
	     */
	    function killKernels(id) {
	        iteration_1.each(iteration_1.toArray(Private.runningKernels), function (kernel) {
	            if (kernel.id === id) {
	                kernel.terminated.emit(void 0);
	                kernel.dispose();
	            }
	        });
	    }
	    /**
	     * Get a full kernel model from the server by kernel id string.
	     */
	    function getKernelModel(id, options) {
	        options = options || {};
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var url = utils.urlPathJoin(baseUrl, KERNEL_SERVICE_URL, encodeURIComponent(id));
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'GET';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            var data = success.data;
	            try {
	                validate.validateModel(data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            return data;
	        }, Private.onKernelError);
	    }
	    Private.getKernelModel = getKernelModel;
	    /**
	     * Log the current kernel status.
	     */
	    function logKernelStatus(kernel) {
	        switch (kernel.status) {
	            case 'idle':
	            case 'busy':
	            case 'unknown':
	                return;
	            default:
	                console.log("Kernel: " + kernel.status + " (" + kernel.id + ")");
	                break;
	        }
	    }
	    Private.logKernelStatus = logKernelStatus;
	    /**
	     * Handle an error on a kernel Ajax call.
	     */
	    function onKernelError(error) {
	        var text = (error.throwError ||
	            error.xhr.statusText ||
	            error.xhr.responseText);
	        var msg = "API request failed: " + text;
	        console.error(msg);
	        return Promise.reject(error);
	    }
	    Private.onKernelError = onKernelError;
	    /**
	     * Send a kernel message to the kernel and resolve the reply message.
	     */
	    function handleShellMessage(kernel, msg) {
	        var future;
	        try {
	            future = kernel.sendShellMessage(msg, true);
	        }
	        catch (e) {
	            return Promise.reject(e);
	        }
	        return new Promise(function (resolve, reject) {
	            future.onReply = function (reply) {
	                resolve(reply);
	            };
	        });
	    }
	    Private.handleShellMessage = handleShellMessage;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/default.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/iteration.js **/
jupyter.define('phosphor@0.7.0/lib/algorithm/iteration.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * Create an iterator for an iterable or array-like object.
	 *
	 * @param object - The iterable or array-like object of interest.
	 *
	 * @returns A new iterator for the given object.
	 *
	 * #### Notes
	 * This function allows iteration algorithms to operate on user-defined
	 * iterable types and builtin array-like objects in a uniform fashion.
	 */
	function iter(object) {
	    var it;
	    if (typeof object.iter === 'function') {
	        it = object.iter();
	    }
	    else {
	        it = new ArrayIterator(object, 0);
	    }
	    return it;
	}
	exports.iter = iter;
	/**
	 * Create an array from an iterable of values.
	 *
	 * @param object - The iterable or array-like object of interest.
	 *
	 * @returns A new array of values from the given object.
	 */
	function toArray(object) {
	    var value;
	    var result = [];
	    var it = iter(object);
	    while ((value = it.next()) !== void 0) {
	        result[result.length] = value;
	    }
	    return result;
	}
	exports.toArray = toArray;
	/**
	 * Create an empty iterator.
	 *
	 * @returns A new iterator which yields nothing.
	 */
	function empty() {
	    return new EmptyIterator();
	}
	exports.empty = empty;
	/**
	 * An iterator which is always empty.
	 */
	var EmptyIterator = (function () {
	    /**
	     * Construct a new empty iterator.
	     */
	    function EmptyIterator() {
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    EmptyIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the current iterator.
	     *
	     * @returns A new independent clone of the current iterator.
	     */
	    EmptyIterator.prototype.clone = function () {
	        return new EmptyIterator();
	    };
	    /**
	     * Get the next value from the iterator.
	     *
	     * @returns Always `undefined`.
	     */
	    EmptyIterator.prototype.next = function () {
	        return void 0;
	    };
	    return EmptyIterator;
	}());
	exports.EmptyIterator = EmptyIterator;
	/**
	 * An iterator for an array-like object.
	 *
	 * #### Notes
	 * This iterator can be used for any builtin JS array-like object.
	 */
	var ArrayIterator = (function () {
	    /**
	     * Construct a new array iterator.
	     *
	     * @param source - The array-like object of interest.
	     *
	     * @param start - The starting index for iteration.
	     */
	    function ArrayIterator(source, start) {
	        this._source = source;
	        this._index = start;
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    ArrayIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the current iterator.
	     *
	     * @returns A new independent clone of the current iterator.
	     *
	     * #### Notes
	     * The source array is shared among clones.
	     */
	    ArrayIterator.prototype.clone = function () {
	        return new ArrayIterator(this._source, this._index);
	    };
	    /**
	     * Get the next value from the source array.
	     *
	     * @returns The next value from the source array, or `undefined`
	     *   if the iterator is exhausted.
	     */
	    ArrayIterator.prototype.next = function () {
	        if (this._index >= this._source.length) {
	            return void 0;
	        }
	        return this._source[this._index++];
	    };
	    return ArrayIterator;
	}());
	exports.ArrayIterator = ArrayIterator;
	/**
	 * Invoke a function for each value in an iterable.
	 *
	 * @param object - The iterable or array-like object of interest.
	 *
	 * @param fn - The callback function to invoke for each value.
	 *
	 * #### Notes
	 * Iteration cannot be terminated early.
	 */
	function each(object, fn) {
	    var value;
	    var it = iter(object);
	    while ((value = it.next()) !== void 0) {
	        fn(value);
	    }
	}
	exports.each = each;
	/**
	 * Test whether all values in an iterable satisfy a predicate.
	 *
	 * @param object - The iterable or array-like object of interest.
	 *
	 * @param fn - The predicate function to invoke for each value.
	 *
	 * @returns `true` if all values pass the test, `false` otherwise.
	 *
	 * #### Notes
	 * Iteration terminates on the first `false` predicate result.
	 */
	function every(object, fn) {
	    var value;
	    var it = iter(object);
	    while ((value = it.next()) !== void 0) {
	        if (!fn(value)) {
	            return false;
	        }
	    }
	    return true;
	}
	exports.every = every;
	/**
	 * Test whether any value in an iterable satisfies a predicate.
	 *
	 * @param object - The iterable or array-like object of interest.
	 *
	 * @param fn - The predicate function to invoke for each value.
	 *
	 * @returns `true` if any value passes the test, `false` otherwise.
	 *
	 * #### Notes
	 * Iteration terminates on the first `true` predicate result.
	 */
	function some(object, fn) {
	    var value;
	    var it = iter(object);
	    while ((value = it.next()) !== void 0) {
	        if (fn(value)) {
	            return true;
	        }
	    }
	    return false;
	}
	exports.some = some;
	function reduce(object, fn, initial) {
	    // Setup the iterator and fetch the first value.
	    var it = iter(object);
	    var first = it.next();
	    // An empty iterator and no initial value is an error.
	    if (first === void 0 && initial === void 0) {
	        throw new TypeError('Reduce of empty iterable with no initial value.');
	    }
	    // If the iterator is empty, return the initial value.
	    if (first === void 0) {
	        return initial;
	    }
	    // If the iterator has a single item and no initial value, the
	    // reducer is not invoked and the first item is the return value.
	    var second = it.next();
	    if (second === void 0 && initial === void 0) {
	        return first;
	    }
	    // If iterator has a single item and an initial value is provided,
	    // the reducer is invoked and that result is the return value.
	    if (second === void 0) {
	        return fn(initial, first);
	    }
	    // Setup the initial accumulator value.
	    var accumulator;
	    if (initial === void 0) {
	        accumulator = fn(first, second);
	    }
	    else {
	        accumulator = fn(fn(initial, first), second);
	    }
	    // Iterate the rest of the values, updating the accumulator.
	    var next;
	    while ((next = it.next()) !== void 0) {
	        accumulator = fn(accumulator, next);
	    }
	    // Return the final accumulated value.
	    return accumulator;
	}
	exports.reduce = reduce;
	/**
	 * Filter an iterable for values which pass a test.
	 *
	 * @param object - The iterable or array-like object of interest.
	 *
	 * @param fn - The predicate function to invoke for each value.
	 *
	 * @returns An iterator which yields the values which pass the test.
	 */
	function filter(object, fn) {
	    return new FilterIterator(iter(object), fn);
	}
	exports.filter = filter;
	/**
	 * An iterator which yields values which pass a test.
	 */
	var FilterIterator = (function () {
	    /**
	     * Construct a new filter iterator.
	     *
	     * @param source - The iterator of values of interest.
	     *
	     * @param fn - The predicate function to invoke for each value in
	     *   the iterator. It returns whether the value passes the test.
	     */
	    function FilterIterator(source, fn) {
	        this._source = source;
	        this._fn = fn;
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    FilterIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the current iterator.
	     *
	     * @returns A new independent clone of the current iterator.
	     *
	     * #### Notes
	     * The source iterator must be cloneable.
	     *
	     * The predicate function is shared among clones.
	     */
	    FilterIterator.prototype.clone = function () {
	        return new FilterIterator(this._source.clone(), this._fn);
	    };
	    /**
	     * Get the next value which passes the test.
	     *
	     * @returns The next value from the source iterator which passes
	     *   the predicate, or `undefined` if the iterator is exhausted.
	     */
	    FilterIterator.prototype.next = function () {
	        var value;
	        var fn = this._fn;
	        var it = this._source;
	        while ((value = it.next()) !== void 0) {
	            if (fn(value)) {
	                return value;
	            }
	        }
	        return void 0;
	    };
	    return FilterIterator;
	}());
	exports.FilterIterator = FilterIterator;
	/**
	 * Transform the values of an iterable with a mapping function.
	 *
	 * @param object - The iterable or array-like object of interest.
	 *
	 * @param fn - The mapping function to invoke for each value.
	 *
	 * @returns An iterator which yields the transformed values.
	 */
	function map(object, fn) {
	    return new MapIterator(iter(object), fn);
	}
	exports.map = map;
	/**
	 * An iterator which transforms values using a mapping function.
	 */
	var MapIterator = (function () {
	    /**
	     * Construct a new map iterator.
	     *
	     * @param source - The iterator of values of interest.
	     *
	     * @param fn - The mapping function to invoke for each value in the
	     *   iterator. It returns the transformed value.
	     */
	    function MapIterator(source, fn) {
	        this._source = source;
	        this._fn = fn;
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    MapIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the current iterator.
	     *
	     * @returns A new independent clone of the current iterator.
	     *
	     * #### Notes
	     * The source iterator must be cloneable.
	     *
	     * The mapping function is shared among clones.
	     */
	    MapIterator.prototype.clone = function () {
	        return new MapIterator(this._source.clone(), this._fn);
	    };
	    /**
	     * Get the next mapped value from the source iterator.
	     *
	     * @returns The next value from the source iterator transformed
	     *   by the mapper, or `undefined` if the iterator is exhausted.
	     */
	    MapIterator.prototype.next = function () {
	        var value = this._source.next();
	        if (value === void 0) {
	            return void 0;
	        }
	        return this._fn.call(void 0, value);
	    };
	    return MapIterator;
	}());
	exports.MapIterator = MapIterator;
	/**
	 * Attach an incremental index to an iterable.
	 *
	 * @param object - The iterable or array-like object of interest.
	 *
	 * @param start - The initial value of the index. The default is zero.
	 *
	 * @returns An iterator which yields `[index, value]` tuples.
	 */
	function enumerate(object, start) {
	    if (start === void 0) { start = 0; }
	    return new EnumerateIterator(iter(object), start);
	}
	exports.enumerate = enumerate;
	/**
	 * An iterator which attaches an incremental index to a source.
	 */
	var EnumerateIterator = (function () {
	    /**
	     * Construct a new enumerate iterator.
	     *
	     * @param source - The iterator of values of interest.
	     *
	     * @param start - The initial value of the index.
	     */
	    function EnumerateIterator(source, start) {
	        this._source = source;
	        this._index = start;
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    EnumerateIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the enumerate iterator.
	     *
	     * @returns A new iterator starting with the current value.
	     *
	     * #### Notes
	     * The source iterator must be cloneable.
	     */
	    EnumerateIterator.prototype.clone = function () {
	        return new EnumerateIterator(this._source.clone(), this._index);
	    };
	    /**
	     * Get the next value from the enumeration.
	     *
	     * @returns The next value from the enumeration, or `undefined` if
	     *   the iterator is exhausted.
	     */
	    EnumerateIterator.prototype.next = function () {
	        var value = this._source.next();
	        if (value === void 0) {
	            return void 0;
	        }
	        return [this._index++, value];
	    };
	    return EnumerateIterator;
	}());
	exports.EnumerateIterator = EnumerateIterator;
	/**
	 * Create an iterator which yields a value a single time.
	 *
	 * @param value - The value to wrap in an iterator.
	 *
	 * @returns A new iterator which yields the value a single time.
	 */
	function once(value) {
	    return new RepeatIterator(value, 1);
	}
	exports.once = once;
	/**
	 * Create an iterator which repeats a value a number of times.
	 *
	 * @param value - The value to repeat.
	 *
	 * @param count - The number of times to repeat the value.
	 *
	 * @returns A new iterator which repeats the specified value.
	 */
	function repeat(value, count) {
	    return new RepeatIterator(value, count);
	}
	exports.repeat = repeat;
	/**
	 * An iterator which repeats a value a specified number of times.
	 */
	var RepeatIterator = (function () {
	    /**
	     * Construct a new repeat iterator.
	     *
	     * @param value - The value to repeat.
	     *
	     * @param count - The number of times to repeat the value.
	     */
	    function RepeatIterator(value, count) {
	        this._value = value;
	        this._count = count;
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    RepeatIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the repeat iterator.
	     *
	     * @returns A new iterator starting with the current value.
	     */
	    RepeatIterator.prototype.clone = function () {
	        return new RepeatIterator(this._value, this._count);
	    };
	    /**
	     * Get the next value from the iterator.
	     *
	     * @returns The next value from the iterator, or `undefined` if
	     *   the iterator is exhausted.
	     */
	    RepeatIterator.prototype.next = function () {
	        if (this._count <= 0) {
	            return void 0;
	        }
	        this._count--;
	        return this._value;
	    };
	    return RepeatIterator;
	}());
	exports.RepeatIterator = RepeatIterator;
	/**
	 * Chain together several iterables.
	 *
	 * @param objects - The iterables or array-like objects of interest.
	 *
	 * @returns An iterator which yields the values of the given iterables
	 *   in the order in which they are supplied.
	 */
	function chain() {
	    var objects = [];
	    for (var _i = 0; _i < arguments.length; _i++) {
	        objects[_i - 0] = arguments[_i];
	    }
	    return new ChainIterator(map(objects, iter));
	}
	exports.chain = chain;
	/**
	 * An iterator which chains together several iterators.
	 */
	var ChainIterator = (function () {
	    /**
	     * Construct a new chain iterator.
	     *
	     * @param source - The iterator of iterators of interest.
	     */
	    function ChainIterator(source) {
	        this._cloned = false;
	        this._source = source;
	        this._active = void 0;
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    ChainIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the chain iterator.
	     *
	     * @returns A new iterator starting with the current value.
	     *
	     * #### Notes
	     * The source iterators must be cloneable.
	     */
	    ChainIterator.prototype.clone = function () {
	        var result = new ChainIterator(this._source.clone());
	        result._active = this._active && this._active.clone();
	        result._cloned = true;
	        this._cloned = true;
	        return result;
	    };
	    /**
	     * Get the next value from the iterator.
	     *
	     * @returns The next value from the iterator, or `undefined` when
	     *   all source iterators are exhausted.
	     */
	    ChainIterator.prototype.next = function () {
	        if (this._active === void 0) {
	            this._active = this._source.next();
	            if (this._active === void 0) {
	                return void 0;
	            }
	            if (this._cloned) {
	                this._active = this._active.clone();
	            }
	        }
	        var value = this._active.next();
	        if (value !== void 0) {
	            return value;
	        }
	        this._active = void 0;
	        return this.next();
	    };
	    return ChainIterator;
	}());
	exports.ChainIterator = ChainIterator;
	/**
	 * Iterate several iterables in lockstep.
	 *
	 * @param objects - The iterables or array-like objects of interest.
	 *
	 * @returns An iterator which yields successive tuples of values where
	 *   each value is taken in turn from the provided iterables. It will
	 *   be as long as the shortest provided iterable.
	 */
	function zip() {
	    var objects = [];
	    for (var _i = 0; _i < arguments.length; _i++) {
	        objects[_i - 0] = arguments[_i];
	    }
	    return new ZipIterator(objects.map(iter));
	}
	exports.zip = zip;
	/**
	 * An iterator which iterates several sources in lockstep.
	 */
	var ZipIterator = (function () {
	    /**
	     * Construct a new zip iterator.
	     *
	     * @param source - The iterators of interest.
	     */
	    function ZipIterator(source) {
	        this._source = source;
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    ZipIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the zip iterator.
	     *
	     * @returns A new iterator starting with the current value.
	     *
	     * #### Notes
	     * The source iterators must be cloneable.
	     */
	    ZipIterator.prototype.clone = function () {
	        return new ZipIterator(this._source.map(function (it) { return it.clone(); }));
	    };
	    /**
	     * Get the next zipped value from the iterator.
	     *
	     * @returns The next zipped value from the iterator, or `undefined`
	     *   when the first source iterator is exhausted.
	     */
	    ZipIterator.prototype.next = function () {
	        var iters = this._source;
	        var result = new Array(iters.length);
	        for (var i = 0, n = iters.length; i < n; ++i) {
	            var value = iters[i].next();
	            if (value === void 0) {
	                return void 0;
	            }
	            result[i] = value;
	        }
	        return result;
	    };
	    return ZipIterator;
	}());
	exports.ZipIterator = ZipIterator;
	/**
	 * Iterate over an iterable using a stepped increment.
	 *
	 * @param object - The iterable or array-like object of interest.
	 *
	 * @param step - The distance to step on each iteration. A value
	 *   of less than `1` will behave the same as a value of `1`.
	 *
	 * @returns An iterator which traverses the iterable step-wise.
	 */
	function stride(object, step) {
	    return new StrideIterator(iter(object), step);
	}
	exports.stride = stride;
	/**
	 * An iterator which traverses a source iterator step-wise.
	 */
	var StrideIterator = (function () {
	    /**
	     * Construct a new stride iterator.
	     *
	     * @param source - The iterator of values of interest.
	     *
	     * @param step - The distance to step on each iteration. A value
	     *   of less than `1` will behave the same as a value of `1`.
	     */
	    function StrideIterator(source, step) {
	        this._source = source;
	        this._step = step;
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    StrideIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the stride iterator.
	     *
	     * @returns A new iterator starting with the current value.
	     *
	     * #### Notes
	     * The source iterator must be cloneable.
	     */
	    StrideIterator.prototype.clone = function () {
	        return new StrideIterator(this._source.clone(), this._step);
	    };
	    /**
	     * Get the next stepped value from the iterator.
	     *
	     * @returns The next stepped value from the iterator, or `undefined`
	     *   when the source iterator is exhausted.
	     */
	    StrideIterator.prototype.next = function () {
	        var value = this._source.next();
	        if (value === void 0) {
	            return void 0;
	        }
	        var step = this._step;
	        while (--step > 0) {
	            this._source.next();
	        }
	        return value;
	    };
	    return StrideIterator;
	}());
	exports.StrideIterator = StrideIterator;
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/iteration.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/searching.js **/
jupyter.define('phosphor@0.7.0/lib/algorithm/searching.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	var sequence_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/sequence.js');
	/**
	 * Find the first value in an iterable which matches a predicate.
	 *
	 * @param object - The iterable or array-like object to search.
	 *
	 * @param fn - The predicate function to apply to the values.
	 *
	 * @returns The first matching value, or `undefined` if no matching
	 *   value is found.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Example
	 * ```typescript
	 * import { find } from 'phosphor/lib/algorithm/searching';
	 *
	 * interface IAnimal { species: string, name: string };
	 *
	 * function isCat(value: IAnimal): boolean {
	 *   return value.species === 'cat';
	 * }
	 *
	 * let data: IAnimal[] = [
	 *   { species: 'dog', name: 'spot' },
	 *   { species: 'cat', name: 'fluffy' },
	 *   { species: 'alligator', name: 'pocho' },
	 * ];
	 *
	 * find(data, isCat).name;  // 'fluffy'
	 * ```
	 */
	function find(object, fn) {
	    var value;
	    var it = iteration_1.iter(object);
	    while ((value = it.next()) !== void 0) {
	        if (fn(value)) {
	            return value;
	        }
	    }
	    return void 0;
	}
	exports.find = find;
	/**
	 * Test whether an iterable contains a specific value.
	 *
	 * @param object - The iterable or array-like object to search.
	 *
	 * @param value - The value to search for in the iterable. Values
	 *   are compared using strict `===` equality.
	 *
	 * @returns `true` if the value is found, `false` otherwise.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Example
	 * ```typescript
	 * import { contains } from 'phosphor/lib/algorithm/searching';
	 *
	 * let data: number[] = [5, 7, 0, -2, 9];
	 *
	 * contains(data, -2);  // true
	 * contains(data, 3);   // false
	 * ```
	 */
	function contains(object, value) {
	    var temp;
	    var it = iteration_1.iter(object);
	    while ((temp = it.next()) !== void 0) {
	        if (temp === value) {
	            return true;
	        }
	    }
	    return false;
	}
	exports.contains = contains;
	/**
	 * Find the minimum value in an iterable.
	 *
	 * @param object - The iterable or array-like object to search.
	 *
	 * @param fn - The 3-way comparison function to apply to the values.
	 *   It should return `< 0` if the first value is less than the second.
	 *   `0` if the values are equivalent, or `> 0` if the first value is
	 *   greater than the second.
	 *
	 * @returns The minimum value in the iterable. If multiple values are
	 *   equivalent to the minimum, the left-most value is returned. If
	 *   the iterable is empty, this returns `undefined`.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Example
	 * ```typescript
	 * import { min } from 'phosphor/lib/algorithm/searching';
	 *
	 * function numberCmp(a: number, b: number): number {
	 *   return a - b;
	 * }
	 *
	 * min([7, 4, 0, 3, 9, 4], numberCmp);  // 0
	 * ```
	 */
	function min(object, fn) {
	    var it = iteration_1.iter(object);
	    var result = it.next();
	    if (result === void 0) {
	        return void 0;
	    }
	    var value;
	    while ((value = it.next()) !== void 0) {
	        if (fn(value, result) < 0) {
	            result = value;
	        }
	    }
	    return result;
	}
	exports.min = min;
	/**
	 * Find the maximum value in an iterable.
	 *
	 * @param object - The iterable or array-like object to search.
	 *
	 * @param fn - The 3-way comparison function to apply to the values.
	 *   It should return `< 0` if the first value is less than the second.
	 *   `0` if the values are equivalent, or `> 0` if the first value is
	 *   greater than the second.
	 *
	 * @returns The maximum value in the iterable. If multiple values are
	 *   equivalent to the maximum, the left-most value is returned. If
	 *   the iterable is empty, this returns `undefined`.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Example
	 * ```typescript
	 * import { max } from 'phosphor/lib/algorithm/searching';
	 *
	 * function numberCmp(a: number, b: number): number {
	 *   return a - b;
	 * }
	 *
	 * max([7, 4, 0, 3, 9, 4], numberCmp);  // 9
	 * ```
	 */
	function max(object, fn) {
	    var it = iteration_1.iter(object);
	    var result = it.next();
	    if (result === void 0) {
	        return void 0;
	    }
	    var value;
	    while ((value = it.next()) !== void 0) {
	        if (fn(value, result) > 0) {
	            result = value;
	        }
	    }
	    return result;
	}
	exports.max = max;
	/**
	 * Find the index of the first occurrence of a value in a sequence.
	 *
	 * @param object - The sequence or array-like object to search.
	 *
	 * @param value - The value to locate in the sequence. Values are
	 *   compared using strict `===` equality.
	 *
	 * @param fromIndex - The starting index of the search. The default
	 *   value is `0`.
	 *
	 * @returns The index of the first occurrence of the value, or `-1`
	 *   if the value is not found.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Undefined Behavior
	 * A `fromIndex` which is non-integral or `< 0`.
	 *
	 * #### Example
	 * ```typescript
	 * import { indexOf } from 'phosphor/lib/algorithm/searching';
	 *
	 * let data = ['one', 'two', 'three', 'four', 'one'];
	 * indexOf(data, 'red');     // -1
	 * indexOf(data, 'one');     // 0
	 * indexOf(data, 'one', 1);  // 4
	 * indexOf(data, 'two', 2);  // -1
	 * ```
	 */
	function indexOf(object, value, fromIndex) {
	    var length = object.length;
	    if (length === 0) {
	        return -1;
	    }
	    var start;
	    if (fromIndex === void 0) {
	        start = 0;
	    }
	    else {
	        start = fromIndex;
	    }
	    var seq = sequence_1.asSequence(object);
	    for (var i = start; i < length; ++i) {
	        if (seq.at(i) === value) {
	            return i;
	        }
	    }
	    return -1;
	}
	exports.indexOf = indexOf;
	/**
	 * Find the index of the last occurrence of a value in a sequence.
	 *
	 * @param object - The sequence or array-like object to search.
	 *
	 * @param value - The value to locate in the sequence. Values are
	 *   compared using strict `===` equality.
	 *
	 * @param fromIndex - The starting index of the search. The default
	 *   value is `length - 1`.
	 *
	 * @returns The index of the last occurrence of the value, or `-1`
	 *   if the value is not found.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Undefined Behavior
	 * A `fromIndex` which is non-integral or `>= length`.
	 *
	 * #### Example
	 * ```typescript
	 * import { lastIndexOf } from 'phosphor/lib/algorithm/searching';
	 *
	 * let data = ['one', 'two', 'three', 'four', 'one'];
	 * lastIndexOf(data, 'red');     // -1
	 * lastIndexOf(data, 'one');     // 4
	 * lastIndexOf(data, 'one', 1);  // 0
	 * lastIndexOf(data, 'two', 2);  // 1
	 * ```
	 */
	function lastIndexOf(object, value, fromIndex) {
	    var length = object.length;
	    if (length === 0) {
	        return -1;
	    }
	    var start;
	    if (fromIndex === void 0) {
	        start = length - 1;
	    }
	    else {
	        start = fromIndex;
	    }
	    var seq = sequence_1.asSequence(object);
	    for (var i = start; i >= 0; --i) {
	        if (seq.at(i) === value) {
	            return i;
	        }
	    }
	    return -1;
	}
	exports.lastIndexOf = lastIndexOf;
	/**
	 * Find the index of the first value which matches a predicate.
	 *
	 * @param object - The sequence or array-like object to search.
	 *
	 * @param fn - The predicate function to apply to the values.
	 *
	 * @param fromIndex - The starting index of the search. The default
	 *   value is `0`.
	 *
	 * @returns The index of the first matching value, or `-1` if no
	 *   matching value is found.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Undefined Behavior
	 * A `fromIndex` which is non-integral or `< 0`.
	 *
	 * Modifying the length of the sequence while searching.
	 *
	 * #### Example
	 * ```typescript
	 * import { findIndex } from 'phosphor/lib/algorithm/searching';
	 *
	 * function isEven(value: number): boolean {
	 *   return value % 2 === 0;
	 * }
	 *
	 * let data = [1, 2, 3, 4, 3, 2, 1];
	 * findIndex(data, isEven);     // 1
	 * findIndex(data, isEven, 4);  // 5
	 * findIndex(data, isEven, 6);  // -1
	 * ```
	 */
	function findIndex(object, fn, fromIndex) {
	    var length = object.length;
	    if (length === 0) {
	        return -1;
	    }
	    var start;
	    if (fromIndex === void 0) {
	        start = 0;
	    }
	    else {
	        start = fromIndex;
	    }
	    var seq = sequence_1.asSequence(object);
	    for (var i = start; i < length; ++i) {
	        if (fn(seq.at(i), i)) {
	            return i;
	        }
	    }
	    return -1;
	}
	exports.findIndex = findIndex;
	/**
	 * Find the index of the last value which matches a predicate.
	 *
	 * @param object - The sequence or array-like object to search.
	 *
	 * @param fn - The predicate function to apply to the values.
	 *
	 * @param fromIndex - The starting index of the search. The default
	 *   value is `length - 1`.
	 *
	 * @returns The index of the last matching value, or `-1` if no
	 *   matching value is found.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Undefined Behavior
	 * A `fromIndex` which is non-integral or `>= length`.
	 *
	 * Modifying the length of the sequence while searching.
	 *
	 * #### Example
	 * ```typescript
	 * import { findLastIndex } from 'phosphor/lib/algorithm/searching';
	 *
	 * function isEven(value: number): boolean {
	 *   return value % 2 === 0;
	 * }
	 *
	 * let data = [1, 2, 3, 4, 3, 2, 1];
	 * findLastIndex(data, isEven);     // 5
	 * findLastIndex(data, isEven, 4);  // 3
	 * findLastIndex(data, isEven, 0);  // -1
	 * ```
	 */
	function findLastIndex(object, fn, fromIndex) {
	    var length = object.length;
	    if (length === 0) {
	        return -1;
	    }
	    var start;
	    if (fromIndex === void 0) {
	        start = length - 1;
	    }
	    else {
	        start = fromIndex;
	    }
	    var seq = sequence_1.asSequence(object);
	    for (var i = start; i >= 0; --i) {
	        if (fn(seq.at(i), i)) {
	            return i;
	        }
	    }
	    return -1;
	}
	exports.findLastIndex = findLastIndex;
	/**
	 * Find the index of the first element which compares `>=` to a value.
	 *
	 * @param sequence - The sequence or array-like object to search.
	 *   It must be sorted in ascending order.
	 *
	 * @param value - The value to locate in the sequence.
	 *
	 * @param fn - The 3-way comparison function to apply to the values.
	 *   It should return `< 0` if an element is less than a value, `0` if
	 *   an element is equal to a value, or `> 0` if an element is greater
	 *   than a value.
	 *
	 * @returns The index of the first element which compares `>=` to the
	 *   value, or `length` if there is no such element.
	 *
	 * #### Complexity
	 * Logarithmic.
	 *
	 * #### Undefined Behavior
	 * A sequence which is not sorted in ascending order.
	 *
	 * Modifying the length of the sequence while searching.
	 *
	 * #### Example
	 * ```typescript
	 * import { lowerBound } from 'phosphor/lib/algorithm/searching';
	 *
	 * function numberCmp(a: number, b: number): number {
	 *   return a - b;
	 * }
	 *
	 * let data = [0, 3, 4, 7, 7, 9];
	 * lowerBound(data, 0, numberCmp);   // 0
	 * lowerBound(data, 6, numberCmp);   // 3
	 * lowerBound(data, 7, numberCmp);   // 3
	 * lowerBound(data, -1, numberCmp);  // 0
	 * lowerBound(data, 10, numberCmp);  // 6
	 * ```
	 */
	function lowerBound(object, value, fn) {
	    var n = object.length;
	    if (n === 0) {
	        return 0;
	    }
	    var begin = 0;
	    var half;
	    var middle;
	    var seq = sequence_1.asSequence(object);
	    while (n > 0) {
	        half = n / 2 | 0;
	        middle = begin + half;
	        if (fn(seq.at(middle), value) < 0) {
	            begin = middle + 1;
	            n -= half + 1;
	        }
	        else {
	            n = half;
	        }
	    }
	    return begin;
	}
	exports.lowerBound = lowerBound;
	/**
	 * Find the index of the first element which compares `>` than a value.
	 *
	 * @param sequence - The sequence or array-like object to search.
	 *   It must be sorted in ascending order.
	 *
	 * @param value - The value to locate in the sequence.
	 *
	 * @param fn - The 3-way comparison function to apply to the values.
	 *   It should return `< 0` if an element is less than a value, `0` if
	 *   an element is equal to a value, or `> 0` if an element is greater
	 *   than a value.
	 *
	 * @returns The index of the first element which compares `>` than the
	 *   value, or `length` if there is no such element.
	 *
	 * #### Complexity
	 * Logarithmic.
	 *
	 * #### Undefined Behavior
	 * A sequence which is not sorted in ascending order.
	 *
	 * Modifying the length of the sequence while searching.
	 *
	 * #### Example
	 * ```typescript
	 * import { upperBound } from 'phosphor/lib/algorithm/searching';
	 *
	 * function numberCmp(a: number, b: number): number {
	 *   return a - b;
	 * }
	 *
	 * let data = [0, 3, 4, 7, 7, 9];
	 * upperBound(data, 0, numberCmp);   // 1
	 * upperBound(data, 6, numberCmp);   // 3
	 * upperBound(data, 7, numberCmp);   // 5
	 * upperBound(data, -1, numberCmp);  // 0
	 * upperBound(data, 10, numberCmp);  // 6
	 * ```
	 */
	function upperBound(object, value, fn) {
	    var n = object.length;
	    if (n === 0) {
	        return 0;
	    }
	    var begin = 0;
	    var half;
	    var middle;
	    var seq = sequence_1.asSequence(object);
	    while (n > 0) {
	        half = n / 2 | 0;
	        middle = begin + half;
	        if (fn(seq.at(middle), value) > 0) {
	            n = half;
	        }
	        else {
	            begin = middle + 1;
	            n -= half + 1;
	        }
	    }
	    return begin;
	}
	exports.upperBound = upperBound;
	/**
	 * A namespace which holds string searching functionality.
	 */
	var StringSearch;
	(function (StringSearch) {
	    /**
	     * Compute the sum-of-squares match for the given search text.
	     *
	     * @param sourceText - The text which should be searched.
	     *
	     * @param queryText - The query text to locate in the source text.
	     *
	     * @returns The match result object, or `null` if there is no match.
	     *
	     * #### Complexity
	     * Linear on `sourceText`.
	     *
	     * #### Notes
	     * This scoring algorithm uses a sum-of-squares approach to determine
	     * the score. In order for there to be a match, all of the characters
	     * in `queryText` **must** appear in `sourceText` in order. The index
	     * of each matching character is squared and added to the score. This
	     * means that early and consecutive character matches are preferred.
	     *
	     * The character match is performed with strict equality. It is case
	     * sensitive and does not ignore whitespace. If those behaviors are
	     * required, the text should be transformed before scoring.
	     */
	    function sumOfSquares(sourceText, queryText) {
	        var score = 0;
	        var indices = new Array(queryText.length);
	        for (var i = 0, j = 0, n = queryText.length; i < n; ++i, ++j) {
	            j = sourceText.indexOf(queryText[i], j);
	            if (j === -1) {
	                return null;
	            }
	            indices[i] = j;
	            score += j * j;
	        }
	        return { score: score, indices: indices };
	    }
	    StringSearch.sumOfSquares = sumOfSquares;
	    /**
	     * Highlight the matched characters of a source string.
	     *
	     * @param source - The text which should be highlighted.
	     *
	     * @param indices - The indices of the matched characters. They must
	     *   appear in increasing order and must be in bounds of the source.
	     *
	     * @returns A string with interpolated `<mark>` tags.
	     */
	    function highlight(sourceText, indices) {
	        var k = 0;
	        var last = 0;
	        var result = '';
	        var n = indices.length;
	        while (k < n) {
	            var i = indices[k];
	            var j = indices[k];
	            while (++k < n && indices[k] === j + 1) {
	                j++;
	            }
	            var head = sourceText.slice(last, i);
	            var chunk = sourceText.slice(i, j + 1);
	            result += head + "<mark>" + chunk + "</mark>";
	            last = j + 1;
	        }
	        return result + sourceText.slice(last);
	    }
	    StringSearch.highlight = highlight;
	})(StringSearch = exports.StringSearch || (exports.StringSearch = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/searching.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/sequence.js **/
jupyter.define('phosphor@0.7.0/lib/algorithm/sequence.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	/**
	 * Cast a sequence or array-like object to a sequence.
	 *
	 * @param object - The sequence or array-like object of interest.
	 *
	 * @returns A sequence for the given object.
	 *
	 * #### Notes
	 * This function allows sequence algorithms to operate on user-defined
	 * sequence types and builtin array-like objects in a uniform fashion.
	 */
	function asSequence(object) {
	    var seq;
	    if (typeof object.at === 'function') {
	        seq = object;
	    }
	    else {
	        seq = new ArraySequence(object);
	    }
	    return seq;
	}
	exports.asSequence = asSequence;
	/**
	 * Cast a mutable sequence or array-like object to a mutable sequence.
	 *
	 * @param object - The sequence or array-like object of interest.
	 *
	 * @returns A mutable sequence for the given object.
	 *
	 * #### Notes
	 * This function allows sequence algorithms to operate on user-defined
	 * sequence types and builtin array-like objects in a uniform fashion.
	 */
	function asMutableSequence(object) {
	    var seq;
	    if (typeof object.set === 'function') {
	        seq = object;
	    }
	    else {
	        seq = new MutableArraySequence(object);
	    }
	    return seq;
	}
	exports.asMutableSequence = asMutableSequence;
	/**
	 * A sequence for an array-like object.
	 *
	 * #### Notes
	 * This sequence can be used for any builtin JS array-like object.
	 */
	var ArraySequence = (function () {
	    /**
	     * Construct a new array sequence.
	     *
	     * @param source - The array-like object of interest.
	     */
	    function ArraySequence(source) {
	        this._source = source;
	    }
	    Object.defineProperty(ArraySequence.prototype, "length", {
	        /**
	         * The length of the sequence.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._source.length;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A new iterator which traverses the object's values.
	     */
	    ArraySequence.prototype.iter = function () {
	        return new iteration_1.ArrayIterator(this._source, 0);
	    };
	    /**
	     * Get the value at the specified index.
	     *
	     * @param index - The positive integer index of interest.
	     *
	     * @returns The value at the specified index.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral or out of range.
	     */
	    ArraySequence.prototype.at = function (index) {
	        return this._source[index];
	    };
	    return ArraySequence;
	}());
	exports.ArraySequence = ArraySequence;
	/**
	 * A sequence for a mutable array-like object.
	 *
	 * #### Notes
	 * This sequence can be used for any builtin JS array-like object.
	 */
	var MutableArraySequence = (function (_super) {
	    __extends(MutableArraySequence, _super);
	    function MutableArraySequence() {
	        _super.apply(this, arguments);
	    }
	    /**
	     * Set the value at the specified index.
	     *
	     * @param index - The positive integer index of interest.
	     *
	     * @param value - The value to set at the specified index.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral or out of range.
	     */
	    MutableArraySequence.prototype.set = function (index, value) {
	        this._source[index] = value;
	    };
	    return MutableArraySequence;
	}(ArraySequence));
	exports.MutableArraySequence = MutableArraySequence;
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/sequence.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/collections/vector.js **/
jupyter.define('phosphor@0.7.0/lib/collections/vector.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	/**
	 * A generic vector data structure.
	 */
	var Vector = (function () {
	    /**
	     * Construct a new vector.
	     *
	     * @param values - The initial values for the vector.
	     */
	    function Vector(values) {
	        var _this = this;
	        this._array = [];
	        if (values)
	            iteration_1.each(values, function (value) { _this.pushBack(value); });
	    }
	    Object.defineProperty(Vector.prototype, "isEmpty", {
	        /**
	         * Test whether the vector is empty.
	         *
	         * @returns `true` if the vector is empty, `false` otherwise.
	         *
	         * #### Notes
	         * This is a read-only property.
	         *
	         * #### Complexity
	         * Constant.
	         *
	         * #### Iterator Validity
	         * No changes.
	         */
	        get: function () {
	            return this._array.length === 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Vector.prototype, "length", {
	        /**
	         * Get the length of the vector.
	         *
	         * @return The number of values in the vector.
	         *
	         * #### Notes
	         * This is a read-only property.
	         *
	         * #### Complexity
	         * Constant.
	         *
	         * #### Iterator Validity
	         * No changes.
	         */
	        get: function () {
	            return this._array.length;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Vector.prototype, "front", {
	        /**
	         * Get the value at the front of the vector.
	         *
	         * @returns The value at the front of the vector, or `undefined` if
	         *   the vector is empty.
	         *
	         * #### Notes
	         * This is a read-only property.
	         *
	         * #### Complexity
	         * Constant.
	         *
	         * #### Iterator Validity
	         * No changes.
	         */
	        get: function () {
	            return this._array[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Vector.prototype, "back", {
	        /**
	         * Get the value at the back of the vector.
	         *
	         * @returns The value at the back of the vector, or `undefined` if
	         *   the vector is empty.
	         *
	         * #### Notes
	         * This is a read-only property.
	         *
	         * #### Complexity
	         * Constant.
	         *
	         * #### Iterator Validity
	         * No changes.
	         */
	        get: function () {
	            return this._array[this._array.length - 1];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over the values in the vector.
	     *
	     * @returns A new iterator starting at the front of the vector.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * No changes.
	     */
	    Vector.prototype.iter = function () {
	        return new iteration_1.ArrayIterator(this._array, 0);
	    };
	    /**
	     * Get the value at the specified index.
	     *
	     * @param index - The positive integer index of interest.
	     *
	     * @returns The value at the specified index.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * No changes.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral or out of range.
	     */
	    Vector.prototype.at = function (index) {
	        return this._array[index];
	    };
	    /**
	     * Set the value at the specified index.
	     *
	     * @param index - The positive integer index of interest.
	     *
	     * @param value - The value to set at the specified index.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * No changes.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral or out of range.
	     */
	    Vector.prototype.set = function (index, value) {
	        this._array[index] = value;
	    };
	    /**
	     * Add a value to the back of the vector.
	     *
	     * @param value - The value to add to the back of the vector.
	     *
	     * @returns The new length of the vector.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * No changes.
	     */
	    Vector.prototype.pushBack = function (value) {
	        return this._array.push(value);
	    };
	    /**
	     * Remove and return the value at the back of the vector.
	     *
	     * @returns The value at the back of the vector, or `undefined` if
	     *   the vector is empty.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * Iterators pointing at the removed value are invalidated.
	     */
	    Vector.prototype.popBack = function () {
	        return this._array.pop();
	    };
	    /**
	     * Insert a value into the vector at a specific index.
	     *
	     * @param index - The index at which to insert the value.
	     *
	     * @param value - The value to set at the specified index.
	     *
	     * @returns The new length of the vector.
	     *
	     * #### Complexity
	     * Linear.
	     *
	     * #### Iterator Validity
	     * No changes.
	     *
	     * #### Notes
	     * The `index` will be clamped to the bounds of the vector.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral.
	     */
	    Vector.prototype.insert = function (index, value) {
	        var array = this._array;
	        var n = array.length;
	        index = Math.max(0, Math.min(index, n));
	        for (var i = n; i > index; --i) {
	            array[i] = array[i - 1];
	        }
	        array[index] = value;
	        return n + 1;
	    };
	    /**
	     * Remove the first occurrence of a value from the vector.
	     *
	     * @param value - The value of interest.
	     *
	     * @returns The index of the removed value, or `-1` if the value
	     *   is not contained in the vector.
	     *
	     * #### Complexity
	     * Linear.
	     *
	     * #### Iterator Validity
	     * Iterators pointing at the removed value and beyond are invalidated.
	     *
	     * #### Notes
	     * Comparison is performed using strict `===` equality.
	     */
	    Vector.prototype.remove = function (value) {
	        var index = this._array.indexOf(value);
	        if (index !== -1)
	            this.removeAt(index);
	        return index;
	    };
	    /**
	     * Remove and return the value at a specific index.
	     *
	     * @param index - The index of the value of interest.
	     *
	     * @returns The value at the specified index, or `undefined` if the
	     *   index is out of range.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * Iterators pointing at the removed value and beyond are invalidated.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral.
	     */
	    Vector.prototype.removeAt = function (index) {
	        var array = this._array;
	        var n = array.length;
	        if (index < 0 || index >= n) {
	            return void 0;
	        }
	        var value = array[index];
	        for (var i = index + 1; i < n; ++i) {
	            array[i - 1] = array[i];
	        }
	        array.length = n - 1;
	        return value;
	    };
	    /**
	     * Remove all values from the vector.
	     *
	     * #### Complexity
	     * Linear.
	     *
	     * #### Iterator Validity
	     * All current iterators are invalidated.
	     */
	    Vector.prototype.clear = function () {
	        this._array.length = 0;
	    };
	    /**
	     * Swap the contents of the vector with the contents of another.
	     *
	     * @param other - The other vector holding the contents to swap.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * All current iterators remain valid, but will now point to the
	     * contents of the other vector involved in the swap.
	     */
	    Vector.prototype.swap = function (other) {
	        var array = other._array;
	        other._array = this._array;
	        this._array = array;
	    };
	    return Vector;
	}());
	exports.Vector = Vector;
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/collections/vector.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/core/disposable.js **/
jupyter.define('phosphor@0.7.0/lib/core/disposable.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	/**
	 * A disposable object which delegates to a callback function.
	 */
	var DisposableDelegate = (function () {
	    /**
	     * Construct a new disposable delegate.
	     *
	     * @param callback - The function to invoke on dispose.
	     */
	    function DisposableDelegate(callback) {
	        this._callback = callback || null;
	    }
	    Object.defineProperty(DisposableDelegate.prototype, "isDisposed", {
	        /**
	         * Test whether the delegate has been disposed.
	         *
	         * #### Notes
	         * This is a read-only property which is always safe to access.
	         */
	        get: function () {
	            return this._callback === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the delegate and invoke the callback function.
	     *
	     * #### Notes
	     * All calls to this method after the first will be a no-op.
	     */
	    DisposableDelegate.prototype.dispose = function () {
	        if (this._callback === null) {
	            return;
	        }
	        var callback = this._callback;
	        this._callback = null;
	        callback();
	    };
	    return DisposableDelegate;
	}());
	exports.DisposableDelegate = DisposableDelegate;
	/**
	 * An object which manages a collection of disposable items.
	 */
	var DisposableSet = (function () {
	    /**
	     * Construct a new disposable set.
	     *
	     * @param items - The initial disposable items.
	     */
	    function DisposableSet(items) {
	        var _this = this;
	        this._set = new Set();
	        if (items)
	            iteration_1.each(items, function (item) { _this._set.add(item); });
	    }
	    Object.defineProperty(DisposableSet.prototype, "isDisposed", {
	        /**
	         * Test whether the set has been disposed.
	         *
	         * #### Notes
	         * This is a read-only property which is always safe to access.
	         */
	        get: function () {
	            return this._set === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the set and the disposable items it contains.
	     *
	     * #### Notes
	     * Items are disposed in the order they are added to the set.
	     *
	     * It is unsafe to use the set after it has been disposed.
	     *
	     * All calls to this method after the first will be a no-op.
	     */
	    DisposableSet.prototype.dispose = function () {
	        if (this._set === null) {
	            return;
	        }
	        var set = this._set;
	        this._set = null;
	        set.forEach(function (item) { item.dispose(); });
	    };
	    /**
	     * Add a disposable item to the set.
	     *
	     * @param item - The disposable item to add to the set. If the item
	     *   is already contained in the set, this is a no-op.
	     *
	     * @throws An error if the set has been disposed.
	     */
	    DisposableSet.prototype.add = function (item) {
	        if (this._set === null) {
	            throw new Error('Object is disposed');
	        }
	        this._set.add(item);
	    };
	    /**
	     * Remove a disposable item from the set.
	     *
	     * @param item - The disposable item to remove from the set. If the
	     *   item does not exist in the set, this is a no-op.
	     *
	     * @throws An error if the set has been disposed.
	     */
	    DisposableSet.prototype.remove = function (item) {
	        if (this._set === null) {
	            throw new Error('Object is disposed');
	        }
	        this._set.delete(item);
	    };
	    /**
	     * Remove all disposable items from the set.
	     *
	     * @throws An error if the set has been disposed.
	     */
	    DisposableSet.prototype.clear = function () {
	        if (this._set === null) {
	            throw new Error('Object is disposed');
	        }
	        this._set.clear();
	    };
	    return DisposableSet;
	}());
	exports.DisposableSet = DisposableSet;
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/core/disposable.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/comm.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/kernel/comm.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var messages_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/messages.js');
	/**
	 * Comm channel handler.
	 */
	var CommHandler = (function (_super) {
	    __extends(CommHandler, _super);
	    /**
	     * Construct a new comm channel.
	     */
	    function CommHandler(target, id, kernel, disposeCb) {
	        _super.call(this, disposeCb);
	        this._target = '';
	        this._id = '';
	        this._kernel = null;
	        this._onClose = null;
	        this._onMsg = null;
	        this._id = id;
	        this._target = target;
	        this._kernel = kernel;
	    }
	    Object.defineProperty(CommHandler.prototype, "commId", {
	        /**
	         * The unique id for the comm channel.
	         */
	        get: function () {
	            return this._id;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommHandler.prototype, "targetName", {
	        /**
	         * The target name for the comm channel.
	         */
	        get: function () {
	            return this._target;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommHandler.prototype, "onClose", {
	        /**
	         * Get the callback for a comm close event.
	         *
	         * #### Notes
	         * This is called when the comm is closed from either the server or
	         * client.
	         *
	         * **See also:** [[ICommClose]], [[close]]
	         */
	        get: function () {
	            return this._onClose;
	        },
	        /**
	         * Set the callback for a comm close event.
	         *
	         * #### Notes
	         * This is called when the comm is closed from either the server or
	         * client.
	         *
	         * **See also:** [[close]]
	         */
	        set: function (cb) {
	            this._onClose = cb;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommHandler.prototype, "onMsg", {
	        /**
	         * Get the callback for a comm message received event.
	         */
	        get: function () {
	            return this._onMsg;
	        },
	        /**
	         * Set the callback for a comm message received event.
	         */
	        set: function (cb) {
	            this._onMsg = cb;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommHandler.prototype, "isDisposed", {
	        /**
	         * Test whether the comm has been disposed.
	         */
	        get: function () {
	            return (this._kernel === null);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Open a comm with optional data and metadata.
	     *
	     * #### Notes
	     * This sends a `comm_open` message to the server.
	     *
	     * **See also:** [[ICommOpen]]
	     */
	    CommHandler.prototype.open = function (data, metadata) {
	        if (this.isDisposed || this._kernel.isDisposed) {
	            return;
	        }
	        var options = {
	            msgType: 'comm_open',
	            channel: 'shell',
	            username: this._kernel.username,
	            session: this._kernel.clientId
	        };
	        var content = {
	            comm_id: this._id,
	            target_name: this._target,
	            data: data || {}
	        };
	        var msg = messages_1.KernelMessage.createShellMessage(options, content, metadata);
	        return this._kernel.sendShellMessage(msg, false, true);
	    };
	    /**
	     * Send a `comm_msg` message to the kernel.
	     *
	     * #### Notes
	     * This is a no-op if the comm has been closed.
	     *
	     * **See also:** [[ICommMsg]]
	     */
	    CommHandler.prototype.send = function (data, metadata, buffers, disposeOnDone) {
	        if (buffers === void 0) { buffers = []; }
	        if (disposeOnDone === void 0) { disposeOnDone = true; }
	        if (this.isDisposed || this._kernel.isDisposed) {
	            return;
	        }
	        var options = {
	            msgType: 'comm_msg',
	            channel: 'shell',
	            username: this._kernel.username,
	            session: this._kernel.clientId
	        };
	        var content = {
	            comm_id: this._id,
	            data: data
	        };
	        var msg = messages_1.KernelMessage.createShellMessage(options, content, metadata, buffers);
	        return this._kernel.sendShellMessage(msg, false, true);
	    };
	    /**
	     * Close the comm.
	     *
	     * #### Notes
	     * This will send a `comm_close` message to the kernel, and call the
	     * `onClose` callback if set.
	     *
	     * This is a no-op if the comm is already closed.
	     *
	     * **See also:** [[ICommClose]], [[onClose]]
	     */
	    CommHandler.prototype.close = function (data, metadata) {
	        if (this.isDisposed || this._kernel.isDisposed) {
	            return;
	        }
	        var options = {
	            msgType: 'comm_msg',
	            channel: 'shell',
	            username: this._kernel.username,
	            session: this._kernel.clientId
	        };
	        var content = {
	            comm_id: this._id,
	            data: data || {}
	        };
	        var msg = messages_1.KernelMessage.createShellMessage(options, content, metadata);
	        var future = this._kernel.sendShellMessage(msg, false, true);
	        options.channel = 'iopub';
	        var ioMsg = messages_1.KernelMessage.createMessage(options, content, metadata);
	        var onClose = this._onClose;
	        if (onClose) {
	            onClose(ioMsg);
	        }
	        this.dispose();
	        return future;
	    };
	    /**
	     * Dispose of the resources held by the comm.
	     */
	    CommHandler.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._onClose = null;
	        this._onMsg = null;
	        this._kernel = null;
	        _super.prototype.dispose.call(this);
	    };
	    return CommHandler;
	}(disposable_1.DisposableDelegate));
	exports.CommHandler = CommHandler;
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/comm.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/messages.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/kernel/messages.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	/**
	 * A namespace for kernel messages.
	 */
	var KernelMessage;
	(function (KernelMessage) {
	    /**
	     * Create a well-formed kernel message.
	     */
	    function createMessage(options, content, metadata, buffers) {
	        if (content === void 0) { content = {}; }
	        if (metadata === void 0) { metadata = {}; }
	        if (buffers === void 0) { buffers = []; }
	        return {
	            header: {
	                username: options.username || '',
	                version: '5.0',
	                session: options.session,
	                msg_id: options.msgId || utils.uuid(),
	                msg_type: options.msgType
	            },
	            parent_header: {},
	            channel: options.channel,
	            content: content,
	            metadata: metadata,
	            buffers: buffers
	        };
	    }
	    KernelMessage.createMessage = createMessage;
	    /**
	     * Create a well-formed kernel shell message.
	     */
	    function createShellMessage(options, content, metadata, buffers) {
	        if (content === void 0) { content = {}; }
	        if (metadata === void 0) { metadata = {}; }
	        if (buffers === void 0) { buffers = []; }
	        var msg = createMessage(options, content, metadata, buffers);
	        return msg;
	    }
	    KernelMessage.createShellMessage = createShellMessage;
	    /**
	     * Test whether a kernel message is a `'stream'` message.
	     */
	    function isStreamMsg(msg) {
	        return msg.header.msg_type === 'stream';
	    }
	    KernelMessage.isStreamMsg = isStreamMsg;
	    /**
	     * Test whether a kernel message is an `'display_data'` message.
	     */
	    function isDisplayDataMsg(msg) {
	        return msg.header.msg_type === 'display_data';
	    }
	    KernelMessage.isDisplayDataMsg = isDisplayDataMsg;
	    /**
	     * Test whether a kernel message is an `'execute_input'` message.
	     */
	    function isExecuteInputMsg(msg) {
	        return msg.header.msg_type === 'execute_input';
	    }
	    KernelMessage.isExecuteInputMsg = isExecuteInputMsg;
	    /**
	     * Test whether a kernel message is an `'execute_result'` message.
	     */
	    function isExecuteResultMsg(msg) {
	        return msg.header.msg_type === 'execute_result';
	    }
	    KernelMessage.isExecuteResultMsg = isExecuteResultMsg;
	    /**
	     * Test whether a kernel message is an `'error'` message.
	     */
	    function isErrorMsg(msg) {
	        return msg.header.msg_type === 'error';
	    }
	    KernelMessage.isErrorMsg = isErrorMsg;
	    /**
	     * Test whether a kernel message is a `'status'` message.
	     */
	    function isStatusMsg(msg) {
	        return msg.header.msg_type === 'status';
	    }
	    KernelMessage.isStatusMsg = isStatusMsg;
	    /**
	     * Test whether a kernel message is a `'clear_output'` message.
	     */
	    function isClearOutputMsg(msg) {
	        return msg.header.msg_type === 'clear_output';
	    }
	    KernelMessage.isClearOutputMsg = isClearOutputMsg;
	    /**
	     * Test whether a kernel message is a `'comm_open'` message.
	     */
	    function isCommOpenMsg(msg) {
	        return msg.header.msg_type === 'comm_open';
	    }
	    KernelMessage.isCommOpenMsg = isCommOpenMsg;
	    /**
	     * Test whether a kernel message is a `'comm_close'` message.
	     */
	    function isCommCloseMsg(msg) {
	        return msg.header.msg_type === 'comm_close';
	    }
	    KernelMessage.isCommCloseMsg = isCommCloseMsg;
	    /**
	     * Test whether a kernel message is a `'comm_msg'` message.
	     */
	    function isCommMsgMsg(msg) {
	        return msg.header.msg_type === 'comm_msg';
	    }
	    KernelMessage.isCommMsgMsg = isCommMsgMsg;
	    ;
	    /**
	     * Test whether a kernel message is an `'input_request'` message.
	     */
	    function isInputRequestMsg(msg) {
	        return msg.header.msg_type === 'input_request';
	    }
	    KernelMessage.isInputRequestMsg = isInputRequestMsg;
	})(KernelMessage = exports.KernelMessage || (exports.KernelMessage = {}));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/messages.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/future.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/kernel/future.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(setImmediate) {// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var messages_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/messages.js');
	/**
	 * Implementation of a kernel future.
	 */
	var KernelFutureHandler = (function (_super) {
	    __extends(KernelFutureHandler, _super);
	    /**
	     * Construct a new KernelFutureHandler.
	     */
	    function KernelFutureHandler(cb, msg, expectShell, disposeOnDone) {
	        _super.call(this, cb);
	        this._msg = null;
	        this._status = 0;
	        this._stdin = null;
	        this._iopub = null;
	        this._reply = null;
	        this._done = null;
	        this._hooks = new Private.HookList();
	        this._disposeOnDone = true;
	        this._msg = msg;
	        if (!expectShell) {
	            this._setFlag(Private.KernelFutureFlag.GotReply);
	        }
	        this._disposeOnDone = disposeOnDone;
	    }
	    Object.defineProperty(KernelFutureHandler.prototype, "msg", {
	        /**
	         * Get the original outgoing message.
	         */
	        get: function () {
	            return this._msg;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelFutureHandler.prototype, "isDone", {
	        /**
	         * Check for message done state.
	         */
	        get: function () {
	            return this._testFlag(Private.KernelFutureFlag.IsDone);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelFutureHandler.prototype, "onReply", {
	        /**
	         * Get the reply handler.
	         */
	        get: function () {
	            return this._reply;
	        },
	        /**
	         * Set the reply handler.
	         */
	        set: function (cb) {
	            this._reply = cb;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelFutureHandler.prototype, "onIOPub", {
	        /**
	         * Get the iopub handler.
	         */
	        get: function () {
	            return this._iopub;
	        },
	        /**
	         * Set the iopub handler.
	         */
	        set: function (cb) {
	            this._iopub = cb;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelFutureHandler.prototype, "onDone", {
	        /**
	         * Get the done handler.
	         */
	        get: function () {
	            return this._done;
	        },
	        /**
	         * Set the done handler.
	         */
	        set: function (cb) {
	            this._done = cb;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelFutureHandler.prototype, "onStdin", {
	        /**
	         * Get the stdin handler.
	         */
	        get: function () {
	            return this._stdin;
	        },
	        /**
	         * Set the stdin handler.
	         */
	        set: function (cb) {
	            this._stdin = cb;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Register hook for IOPub messages.
	     *
	     * @param hook - The callback invoked for an IOPub message.
	     *
	     * #### Notes
	     * The IOPub hook system allows you to preempt the handlers for IOPub messages handled
	     * by the future. The most recently registered hook is run first.
	     * If the hook returns false, any later hooks and the future's onIOPub handler will not run.
	     * If a hook throws an error, the error is logged to the console and the next hook is run.
	     * If a hook is registered during the hook processing, it won't run until the next message.
	     * If a hook is removed during the hook processing, it will be deactivated immediately.
	     */
	    KernelFutureHandler.prototype.registerMessageHook = function (hook) {
	        this._hooks.add(hook);
	    };
	    /**
	     * Remove a hook for IOPub messages.
	     *
	     * @param hook - The hook to remove.
	     *
	     * #### Notes
	     * If a hook is removed during the hook processing, it will be deactivated immediately.
	     */
	    KernelFutureHandler.prototype.removeMessageHook = function (hook) {
	        if (this.isDisposed) {
	            return;
	        }
	        this._hooks.remove(hook);
	    };
	    /**
	     * Dispose and unregister the future.
	     */
	    KernelFutureHandler.prototype.dispose = function () {
	        this._stdin = null;
	        this._iopub = null;
	        this._reply = null;
	        this._done = null;
	        this._msg = null;
	        if (this._hooks) {
	            this._hooks.dispose();
	        }
	        this._hooks = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle an incoming kernel message.
	     */
	    KernelFutureHandler.prototype.handleMsg = function (msg) {
	        switch (msg.channel) {
	            case 'shell':
	                this._handleReply(msg);
	                break;
	            case 'stdin':
	                this._handleStdin(msg);
	                break;
	            case 'iopub':
	                this._handleIOPub(msg);
	                break;
	        }
	    };
	    KernelFutureHandler.prototype._handleReply = function (msg) {
	        var reply = this._reply;
	        if (reply) {
	            reply(msg);
	        }
	        this._setFlag(Private.KernelFutureFlag.GotReply);
	        if (this._testFlag(Private.KernelFutureFlag.GotIdle)) {
	            this._handleDone();
	        }
	    };
	    KernelFutureHandler.prototype._handleStdin = function (msg) {
	        var stdin = this._stdin;
	        if (stdin) {
	            stdin(msg);
	        }
	    };
	    KernelFutureHandler.prototype._handleIOPub = function (msg) {
	        var process = this._hooks.process(msg);
	        var iopub = this._iopub;
	        if (process && iopub) {
	            iopub(msg);
	        }
	        if (messages_1.KernelMessage.isStatusMsg(msg) &&
	            msg.content.execution_state === 'idle') {
	            this._setFlag(Private.KernelFutureFlag.GotIdle);
	            if (this._testFlag(Private.KernelFutureFlag.GotReply)) {
	                this._handleDone();
	            }
	        }
	    };
	    KernelFutureHandler.prototype._handleDone = function () {
	        if (this.isDone) {
	            return;
	        }
	        this._setFlag(Private.KernelFutureFlag.IsDone);
	        var done = this._done;
	        if (done)
	            done();
	        this._done = null;
	        if (this._disposeOnDone) {
	            this.dispose();
	        }
	    };
	    /**
	     * Test whether the given future flag is set.
	     */
	    KernelFutureHandler.prototype._testFlag = function (flag) {
	        return (this._status & flag) !== 0;
	    };
	    /**
	     * Set the given future flag.
	     */
	    KernelFutureHandler.prototype._setFlag = function (flag) {
	        this._status |= flag;
	    };
	    return KernelFutureHandler;
	}(disposable_1.DisposableDelegate));
	exports.KernelFutureHandler = KernelFutureHandler;
	var Private;
	(function (Private) {
	    /**
	     * A polyfill for a function to run code outside of the current execution context.
	     */
	    var defer = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setImmediate;
	    var HookList = (function () {
	        function HookList() {
	            this._hooks = [];
	        }
	        /**
	         * Register a hook.
	         *
	         * @param hook - The callback to register.
	         */
	        HookList.prototype.add = function (hook) {
	            this.remove(hook);
	            this._hooks.push(hook);
	        };
	        /**
	         * Remove a hook.
	         *
	         * @param hook - The callback to remove.
	         */
	        HookList.prototype.remove = function (hook) {
	            if (this.isDisposed) {
	                return;
	            }
	            var index = this._hooks.indexOf(hook);
	            if (index >= 0) {
	                this._hooks[index] = null;
	                this._scheduleCompact();
	            }
	        };
	        /**
	         * Process a message through the hooks.
	         *
	         * #### Notes
	         * The most recently registered hook is run first.
	         * If the hook returns false, any later hooks will not run.
	         * If a hook throws an error, the error is logged to the console and the next hook is run.
	         * If a hook is registered during the hook processing, it won't run until the next message.
	         * If a hook is removed during the hook processing, it will be deactivated immediately.
	         */
	        HookList.prototype.process = function (msg) {
	            var continueHandling;
	            // most recently-added hook is called first
	            for (var i = this._hooks.length - 1; i >= 0; i--) {
	                var hook = this._hooks[i];
	                if (hook === null) {
	                    continue;
	                }
	                try {
	                    continueHandling = hook(msg);
	                }
	                catch (err) {
	                    continueHandling = true;
	                    console.error(err);
	                }
	                if (continueHandling === false) {
	                    return false;
	                }
	            }
	            return true;
	        };
	        Object.defineProperty(HookList.prototype, "isDisposed", {
	            /**
	             * Test whether the HookList has been disposed.
	             */
	            get: function () {
	                return (this._hooks === null);
	            },
	            enumerable: true,
	            configurable: true
	        });
	        /**
	         * Dispose the hook list.
	         */
	        HookList.prototype.dispose = function () {
	            this._hooks = null;
	        };
	        /**
	         * Schedule a cleanup of the list, removing any hooks that have been nulled out.
	         */
	        HookList.prototype._scheduleCompact = function () {
	            var _this = this;
	            if (!this._cleanupScheduled) {
	                this._cleanupScheduled = true;
	                defer(function () {
	                    _this._cleanupScheduled = false;
	                    _this._compact();
	                });
	            }
	        };
	        /**
	         * Compact the list, removing any nulls.
	         */
	        HookList.prototype._compact = function () {
	            if (this.isDisposed) {
	                return;
	            }
	            var numNulls = 0;
	            for (var i = 0, len = this._hooks.length; i < len; i++) {
	                var hook = this._hooks[i];
	                if (this._hooks[i] === null) {
	                    numNulls++;
	                }
	                else {
	                    this._hooks[i - numNulls] = hook;
	                }
	            }
	            this._hooks.length -= numNulls;
	        };
	        return HookList;
	    }());
	    Private.HookList = HookList;
	    /**
	     * Bit flags for the kernel future state.
	     */
	    (function (KernelFutureFlag) {
	        KernelFutureFlag[KernelFutureFlag["GotReply"] = 1] = "GotReply";
	        KernelFutureFlag[KernelFutureFlag["GotIdle"] = 2] = "GotIdle";
	        KernelFutureFlag[KernelFutureFlag["IsDone"] = 4] = "IsDone";
	        KernelFutureFlag[KernelFutureFlag["DisposeOnDone"] = 8] = "DisposeOnDone";
	    })(Private.KernelFutureFlag || (Private.KernelFutureFlag = {}));
	    var KernelFutureFlag = Private.KernelFutureFlag;
	})(Private || (Private = {}));
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('timers-browserify@2.0.2/main.js').setImmediate))
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/future.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/serialize.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/kernel/serialize.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * Deserialize and return the unpacked message.
	 *
	 * #### Notes
	 * Handles JSON blob strings and binary messages.
	 */
	function deserialize(data) {
	    var value;
	    if (typeof data === 'string') {
	        value = JSON.parse(data);
	    }
	    else {
	        value = deserializeBinary(data);
	    }
	    return value;
	}
	exports.deserialize = deserialize;
	/**
	 * Serialize a kernel message for transport.
	 *
	 * #### Notes
	 * If there is binary content, an `ArrayBuffer` is returned,
	 * otherwise the message is converted to a JSON string.
	 */
	function serialize(msg) {
	    var value;
	    if (msg.buffers && msg.buffers.length) {
	        value = serializeBinary(msg);
	    }
	    else {
	        value = JSON.stringify(msg);
	    }
	    return value;
	}
	exports.serialize = serialize;
	/**
	 * Deserialize a binary message to a Kernel Message.
	 */
	function deserializeBinary(buf) {
	    var data = new DataView(buf);
	    // read the header: 1 + nbufs 32b integers
	    var nbufs = data.getUint32(0);
	    var offsets = [];
	    if (nbufs < 2) {
	        throw new Error('Invalid incoming Kernel Message');
	    }
	    for (var i = 1; i <= nbufs; i++) {
	        offsets.push(data.getUint32(i * 4));
	    }
	    var jsonBytes = new Uint8Array(buf.slice(offsets[0], offsets[1]));
	    var msg = JSON.parse((new TextDecoder('utf8')).decode(jsonBytes));
	    // the remaining chunks are stored as DataViews in msg.buffers
	    msg.buffers = [];
	    for (var i = 1; i < nbufs; i++) {
	        var start = offsets[i];
	        var stop = offsets[i + 1] || buf.byteLength;
	        msg.buffers.push(new DataView(buf.slice(start, stop)));
	    }
	    return msg;
	}
	/**
	 * Implement the binary serialization protocol.
	 *
	 * Serialize Kernel message to ArrayBuffer.
	 */
	function serializeBinary(msg) {
	    var offsets = [];
	    var buffers = [];
	    var encoder = new TextEncoder('utf8');
	    var jsonUtf8 = encoder.encode(JSON.stringify(msg, replaceBuffers));
	    buffers.push(jsonUtf8.buffer);
	    for (var i = 0; i < msg.buffers.length; i++) {
	        // msg.buffers elements could be either views or ArrayBuffers
	        // buffers elements are ArrayBuffers
	        var b = msg.buffers[i];
	        buffers.push(b instanceof ArrayBuffer ? b : b.buffer);
	    }
	    var nbufs = buffers.length;
	    offsets.push(4 * (nbufs + 1));
	    for (var i = 0; i + 1 < buffers.length; i++) {
	        offsets.push(offsets[offsets.length - 1] + buffers[i].byteLength);
	    }
	    var msgBuf = new Uint8Array(offsets[offsets.length - 1] + buffers[buffers.length - 1].byteLength);
	    // use DataView.setUint32 for network byte-order
	    var view = new DataView(msgBuf.buffer);
	    // write nbufs to first 4 bytes
	    view.setUint32(0, nbufs);
	    // write offsets to next 4 * nbufs bytes
	    for (var i = 0; i < offsets.length; i++) {
	        view.setUint32(4 * (i + 1), offsets[i]);
	    }
	    // write all the buffers at their respective offsets
	    for (var i = 0; i < buffers.length; i++) {
	        msgBuf.set(new Uint8Array(buffers[i]), offsets[i]);
	    }
	    return msgBuf.buffer;
	}
	/**
	 * Filter `"buffers"` key for `JSON.stringify`.
	 */
	function replaceBuffers(key, value) {
	    if (key === 'buffers') {
	        return undefined;
	    }
	    return value;
	}
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/serialize.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/validate.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/kernel/validate.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * Required fields for `IKernelHeader`.
	 */
	var HEADER_FIELDS = ['username', 'version', 'session', 'msg_id', 'msg_type'];
	/**
	 * Requred fields and types for contents of various types of `kernel.IMessage`
	 * messages on the iopub channel.
	 */
	var IOPUB_CONTENT_FIELDS = {
	    stream: { name: 'string', text: 'string' },
	    display_data: { data: 'object', metadata: 'object' },
	    execute_input: { code: 'string', execution_count: 'number' },
	    execute_result: { execution_count: 'number', data: 'object',
	        metadata: 'object' },
	    error: { ename: 'string', evalue: 'string', traceback: 'object' },
	    status: { execution_state: 'string' },
	    clear_output: { wait: 'boolean' },
	    comm_open: { comm_id: 'string', target_name: 'string', data: 'object' },
	    comm_msg: { comm_id: 'string', data: 'object' },
	    comm_close: { comm_id: 'string' },
	    shutdown_reply: { restart: 'boolean' } // Emitted by the IPython kernel.
	};
	/**
	 * Validate a property as being on an object, and optionally
	 * of a given type.
	 */
	function validateProperty(object, name, typeName) {
	    if (!object.hasOwnProperty(name)) {
	        throw Error("Missing property '" + name + "'");
	    }
	    if (typeName !== void 0) {
	        var valid = true;
	        var value = object[name];
	        switch (typeName) {
	            case 'array':
	                valid = Array.isArray(value);
	                break;
	            case 'object':
	                valid = typeof value !== 'undefined';
	                break;
	            default:
	                valid = typeof value === typeName;
	        }
	        if (!valid) {
	            throw new Error("Property '" + name + "' is not of type '" + typeName);
	        }
	    }
	}
	/**
	 * Validate the header of a kernel message.
	 */
	function validateHeader(header) {
	    for (var i = 0; i < HEADER_FIELDS.length; i++) {
	        validateProperty(header, HEADER_FIELDS[i], 'string');
	    }
	}
	/**
	 * Validate a kernel message object.
	 */
	function validateMessage(msg) {
	    validateProperty(msg, 'metadata', 'object');
	    validateProperty(msg, 'content', 'object');
	    validateProperty(msg, 'channel', 'string');
	    validateHeader(msg.header);
	    if (msg.channel === 'iopub') {
	        validateIOPubContent(msg);
	    }
	}
	exports.validateMessage = validateMessage;
	/**
	 * Validate content an kernel message on the iopub channel.
	 */
	function validateIOPubContent(msg) {
	    if (msg.channel === 'iopub') {
	        var fields = IOPUB_CONTENT_FIELDS[msg.header.msg_type];
	        if (fields === void 0) {
	            throw Error("Invalid Kernel message: iopub message type " + msg.header.msg_type + " not recognized");
	        }
	        var names = Object.keys(fields);
	        var content = msg.content;
	        for (var i = 0; i < names.length; i++) {
	            validateProperty(content, names[i], fields[names[i]]);
	        }
	    }
	}
	/**
	 * Validate a `Kernel.IModel` object.
	 */
	function validateModel(model) {
	    validateProperty(model, 'name', 'string');
	    validateProperty(model, 'id', 'string');
	}
	exports.validateModel = validateModel;
	/**
	 * Validate a server kernelspec model to a client side model.
	 */
	function validateSpecModel(data) {
	    var spec = data.spec;
	    if (!spec) {
	        throw new Error('Invalid kernel spec');
	    }
	    validateProperty(data, 'name', 'string');
	    validateProperty(data, 'resources', 'object');
	    validateProperty(spec, 'language', 'string');
	    validateProperty(spec, 'display_name', 'string');
	    validateProperty(spec, 'argv', 'array');
	    return {
	        name: data.name,
	        resources: data.resources,
	        language: spec.language,
	        display_name: spec.display_name,
	        argv: spec.argv
	    };
	}
	exports.validateSpecModel = validateSpecModel;
	/**
	 * Validate a `Kernel.ISpecModels` object.
	 */
	function validateSpecModels(data) {
	    if (!data.hasOwnProperty('kernelspecs')) {
	        throw new Error('No kernelspecs found');
	    }
	    var keys = Object.keys(data.kernelspecs);
	    var kernelspecs = Object.create(null);
	    var defaultSpec = data.default;
	    for (var i = 0; i < keys.length; i++) {
	        var ks = data.kernelspecs[keys[i]];
	        try {
	            kernelspecs[keys[i]] = validateSpecModel(ks);
	        }
	        catch (err) {
	            // Remove the errant kernel spec.
	            console.warn("Removing errant kernel spec: " + keys[i]);
	        }
	    }
	    keys = Object.keys(kernelspecs);
	    if (!keys.length) {
	        throw new Error('No valid kernelspecs found');
	    }
	    if (!defaultSpec || typeof defaultSpec !== 'string' ||
	        !(defaultSpec in kernelspecs)) {
	        defaultSpec = keys[0];
	        console.warn("Default kernel not found, using '" + keys[0] + "'");
	    }
	    return {
	        default: defaultSpec,
	        kernelspecs: kernelspecs,
	    };
	}
	exports.validateSpecModels = validateSpecModels;
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/validate.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/manager.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/kernel/manager.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var json_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/json.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	var kernel_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/kernel.js');
	/**
	 * An implementation of a kernel manager.
	 */
	var KernelManager = (function () {
	    /**
	     * Construct a new kernel manager.
	     *
	     * @param options - The default options for kernel.
	     */
	    function KernelManager(options) {
	        var _this = this;
	        if (options === void 0) { options = {}; }
	        this._baseUrl = '';
	        this._wsUrl = '';
	        this._token = '';
	        this._ajaxSettings = '';
	        this._running = [];
	        this._specs = null;
	        this._isDisposed = false;
	        this._runningTimer = -1;
	        this._specsTimer = -1;
	        this._isReady = false;
	        this._baseUrl = options.baseUrl || utils.getBaseUrl();
	        this._wsUrl = options.wsUrl || utils.getWsUrl(this._baseUrl);
	        this._token = options.token || utils.getConfigOption('token');
	        this._ajaxSettings = JSON.stringify(utils.ajaxSettingsWithToken(options.ajaxSettings, options.token));
	        // Initialize internal data.
	        this._readyPromise = this._refreshSpecs().then(function () {
	            return _this._refreshRunning();
	        });
	        // Set up polling.
	        this._runningTimer = setInterval(function () {
	            _this._refreshRunning();
	        }, 10000);
	        this._specsTimer = setInterval(function () {
	            _this._refreshSpecs();
	        }, 61000);
	    }
	    Object.defineProperty(KernelManager.prototype, "isDisposed", {
	        /**
	         * Test whether the terminal manager is disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the manager.
	     */
	    KernelManager.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        clearInterval(this._runningTimer);
	        clearInterval(this._specsTimer);
	        signaling_1.clearSignalData(this);
	        this._specs = null;
	        this._running = [];
	    };
	    Object.defineProperty(KernelManager.prototype, "baseUrl", {
	        /**
	         * Get the base url of the manager.
	         */
	        get: function () {
	            return this._baseUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelManager.prototype, "wsUrl", {
	        /**
	         * Get the ws url of the manager.
	         */
	        get: function () {
	            return this._wsUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelManager.prototype, "ajaxSettings", {
	        /**
	         * The default ajax settings for the manager.
	         */
	        get: function () {
	            return JSON.parse(this._ajaxSettings);
	        },
	        /**
	         * Set the default ajax settings for the manager.
	         */
	        set: function (value) {
	            this._ajaxSettings = JSON.stringify(value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelManager.prototype, "specs", {
	        /**
	         * Get the most recently fetched kernel specs.
	         */
	        get: function () {
	            return this._specs;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelManager.prototype, "isReady", {
	        /**
	         * Test whether the manager is ready.
	         */
	        get: function () {
	            return this._isReady;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(KernelManager.prototype, "ready", {
	        /**
	         * A promise that fulfills when the manager is ready.
	         */
	        get: function () {
	            return this._readyPromise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over the most recent running kernels.
	     *
	     * @returns A new iterator over the running kernels.
	     */
	    KernelManager.prototype.running = function () {
	        return iteration_1.iter(this._running);
	    };
	    /**
	     * Force a refresh of the specs from the server.
	     *
	     * @returns A promise that resolves when the specs are fetched.
	     *
	     * #### Notes
	     * This is intended to be called only in response to a user action,
	     * since the manager maintains its internal state.
	     */
	    KernelManager.prototype.refreshSpecs = function () {
	        return this._refreshSpecs();
	    };
	    /**
	     * Force a refresh of the running kernels.
	     *
	     * @returns A promise that with the list of running sessions.
	     *
	     * #### Notes
	     * This is not typically meant to be called by the user, since the
	     * manager maintains its own internal state.
	     */
	    KernelManager.prototype.refreshRunning = function () {
	        return this._refreshRunning();
	    };
	    /**
	     * Start a new kernel.  See also [[startNewKernel]].
	     *
	     * @param options - Overrides for the default options.
	     */
	    KernelManager.prototype.startNew = function (options) {
	        var _this = this;
	        return kernel_1.Kernel.startNew(this._getOptions(options)).then(function (kernel) {
	            _this._onStarted(kernel);
	            return kernel;
	        });
	    };
	    /**
	     * Find a kernel by id.
	     *
	     * @param options - Overrides for the default options.
	     */
	    KernelManager.prototype.findById = function (id, options) {
	        return kernel_1.Kernel.findById(id, this._getOptions(options));
	    };
	    /**
	     * Connect to a running kernel.  See also [[connectToKernel]].
	     *
	     * @param options - Overrides for the default options.
	     */
	    KernelManager.prototype.connectTo = function (id, options) {
	        var _this = this;
	        return kernel_1.Kernel.connectTo(id, this._getOptions(options)).then(function (kernel) {
	            _this._onStarted(kernel);
	            return kernel;
	        });
	    };
	    /**
	     * Shut down a kernel by id.
	     *
	     * @param options - Overrides for the default options.
	     *
	     * #### Notes
	     * This will emit [[runningChanged]] if the running kernels list
	     * changes.
	     */
	    KernelManager.prototype.shutdown = function (id, options) {
	        var _this = this;
	        return kernel_1.Kernel.shutdown(id, this._getOptions(options)).then(function () {
	            _this._onTerminated(id);
	        });
	    };
	    /**
	     * Handle a kernel terminating.
	     */
	    KernelManager.prototype._onTerminated = function (id) {
	        var index = searching_1.findIndex(this._running, function (value) { return value.id === id; });
	        if (index !== -1) {
	            this._running.splice(index, 1);
	            this.runningChanged.emit(this._running.slice());
	        }
	    };
	    /**
	     * Handle a kernel starting.
	     */
	    KernelManager.prototype._onStarted = function (kernel) {
	        var _this = this;
	        var id = kernel.id;
	        var index = searching_1.findIndex(this._running, function (value) { return value.id === id; });
	        if (index === -1) {
	            this._running.push(kernel.model);
	            this.runningChanged.emit(this._running.slice());
	        }
	        kernel.terminated.connect(function () {
	            _this._onTerminated(id);
	        });
	    };
	    /**
	     * Refresh the specs.
	     */
	    KernelManager.prototype._refreshSpecs = function () {
	        var _this = this;
	        var options = {
	            baseUrl: this._baseUrl,
	            token: this._token,
	            ajaxSettings: this.ajaxSettings
	        };
	        return kernel_1.Kernel.getSpecs(options).then(function (specs) {
	            if (!json_1.deepEqual(specs, _this._specs)) {
	                _this._specs = specs;
	                _this.specsChanged.emit(specs);
	            }
	        });
	    };
	    /**
	     * Refresh the running sessions.
	     */
	    KernelManager.prototype._refreshRunning = function () {
	        var _this = this;
	        return kernel_1.Kernel.listRunning(this._getOptions({})).then(function (running) {
	            _this._isReady = true;
	            if (!json_1.deepEqual(running, _this._running)) {
	                _this._running = running.slice();
	                _this.runningChanged.emit(running);
	            }
	        });
	    };
	    /**
	     * Get optionally overidden options.
	     */
	    KernelManager.prototype._getOptions = function (options) {
	        if (options === void 0) { options = {}; }
	        options.baseUrl = this._baseUrl;
	        options.wsUrl = this._wsUrl;
	        options.token = this._token;
	        options.ajaxSettings = options.ajaxSettings || this.ajaxSettings;
	        return options;
	    };
	    return KernelManager;
	}());
	exports.KernelManager = KernelManager;
	// Define the signal for the `KernelManager` class.
	signaling_1.defineSignal(KernelManager.prototype, 'specsChanged');
	signaling_1.defineSignal(KernelManager.prototype, 'runningChanged');
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/kernel/manager.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/json.js **/
jupyter.define('phosphor@0.7.0/lib/algorithm/json.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * Test whether a JSON value is a primitive.
	 *
	 * @param value - The JSON value of interest.
	 *
	 * @returns `true` if the value is a primitive or `null`,
	 *   `false` otherwise.
	 */
	function isPrimitive(value) {
	    return (value === null ||
	        typeof value === 'boolean' ||
	        typeof value === 'number' ||
	        typeof value === 'string');
	}
	exports.isPrimitive = isPrimitive;
	/**
	 * Test whether a JSON value is an array.
	 *
	 * @param value - The JSON value of interest.
	 *
	 * @returns `true` if the value is a an array, `false` otherwise.
	 */
	function isArray(value) {
	    return Array.isArray(value);
	}
	exports.isArray = isArray;
	/**
	 * Test whether a JSON value is an object.
	 *
	 * @param value - The JSON value of interest.
	 *
	 * @returns `true` if the value is a an object, `false` otherwise.
	 */
	function isObject(value) {
	    return !isPrimitive(value) && !isArray(value);
	}
	exports.isObject = isObject;
	/**
	 * Compare two JSON values for deep equality.
	 *
	 * @param first - The first JSON value of interest.
	 *
	 * @param second - The second JSON value of interest.
	 *
	 * @returns `true` if the values are equivalent, `false` otherwise.
	 */
	function deepEqual(first, second) {
	    // Check referential and primitive equality first.
	    if (first === second) {
	        return true;
	    }
	    // If one is a primitive, the `===` check ruled out the other.
	    if (isPrimitive(first) || isPrimitive(second)) {
	        return false;
	    }
	    // Bail if either is `undefined`.
	    if (!first || !second) {
	        return false;
	    }
	    // Test whether they are arrays.
	    var a1 = isArray(first);
	    var a2 = isArray(second);
	    // Bail if the types are different.
	    if (a1 !== a2) {
	        return false;
	    }
	    // If they are both arrays, compare them.
	    if (a1 && a2) {
	        return Private.arrayEqual(first, second);
	    }
	    // At this point, they must both be objects.
	    return Private.objectEqual(first, second);
	}
	exports.deepEqual = deepEqual;
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Compare two JSON arrays for deep equality.
	     */
	    function arrayEqual(first, second) {
	        // Test the arrays for equal length.
	        if (first.length !== second.length) {
	            return false;
	        }
	        // Compare the values for equality.
	        for (var i = 0, n = first.length; i < n; ++i) {
	            if (!deepEqual(first[i], second[i])) {
	                return false;
	            }
	        }
	        // At this point, the arrays are equal.
	        return true;
	    }
	    Private.arrayEqual = arrayEqual;
	    /**
	     * Compare two JSON objects for deep equality.
	     */
	    function objectEqual(first, second) {
	        // Get the keys for each object.
	        var k1 = Object.keys(first);
	        var k2 = Object.keys(second);
	        // Test the keys for equal length.
	        if (k1.length !== k2.length) {
	            return false;
	        }
	        // Sort the keys for equivalent order.
	        k1.sort();
	        k2.sort();
	        // Compare the keys for equality.
	        for (var i = 0, n = k1.length; i < n; ++i) {
	            if (k1[i] !== k2[i]) {
	                return false;
	            }
	        }
	        // Compare the values for equality.
	        for (var i = 0, n = k1.length; i < n; ++i) {
	            if (!deepEqual(first[k1[i]], second[k1[i]])) {
	                return false;
	            }
	        }
	        // At this point, the objects are equal.
	        return true;
	    }
	    Private.objectEqual = objectEqual;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/json.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/manager.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/manager.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var contents_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/contents/index.js');
	var session_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/session/index.js');
	var terminal_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/terminal/index.js');
	var utils_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	/**
	 * A Jupyter services manager.
	 */
	var ServiceManager = (function () {
	    /**
	     * Construct a new services provider.
	     */
	    function ServiceManager(options) {
	        var _this = this;
	        this._sessionManager = null;
	        this._contentsManager = null;
	        this._terminalManager = null;
	        this._isDisposed = false;
	        options = options || {};
	        options.wsUrl = options.wsUrl || utils_1.getWsUrl();
	        options.baseUrl = options.baseUrl || utils_1.getBaseUrl();
	        options.ajaxSettings = utils_1.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        this._sessionManager = new session_1.SessionManager(options);
	        this._contentsManager = new contents_1.ContentsManager(options);
	        this._terminalManager = new terminal_1.TerminalManager(options);
	        this._sessionManager.specsChanged.connect(function (sender, specs) {
	            _this.specsChanged.emit(specs);
	        });
	        this._readyPromise = this._sessionManager.ready.then(function () {
	            if (_this._terminalManager.isAvailable()) {
	                return _this._terminalManager.ready;
	            }
	        });
	    }
	    Object.defineProperty(ServiceManager.prototype, "isDisposed", {
	        /**
	         * Test whether the terminal manager is disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the manager.
	     */
	    ServiceManager.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        signaling_1.clearSignalData(this);
	        this._sessionManager.dispose();
	        this._contentsManager.dispose();
	        this._sessionManager.dispose();
	    };
	    Object.defineProperty(ServiceManager.prototype, "specs", {
	        /**
	         * The kernel spec models.
	         */
	        get: function () {
	            return this._sessionManager.specs;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ServiceManager.prototype, "baseUrl", {
	        /**
	         * Get the base url of the server.
	         */
	        get: function () {
	            return this._sessionManager.baseUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ServiceManager.prototype, "sessions", {
	        /**
	         * Get the session manager instance.
	         */
	        get: function () {
	            return this._sessionManager;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ServiceManager.prototype, "contents", {
	        /**
	         * Get the contents manager instance.
	         */
	        get: function () {
	            return this._contentsManager;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ServiceManager.prototype, "terminals", {
	        /**
	         * Get the terminal manager instance.
	         */
	        get: function () {
	            return this._terminalManager;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ServiceManager.prototype, "isReady", {
	        /**
	         * Test whether the manager is ready.
	         */
	        get: function () {
	            return this._sessionManager.isReady || this._terminalManager.isReady;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ServiceManager.prototype, "ready", {
	        /**
	         * A promise that fulfills when the manager is ready.
	         */
	        get: function () {
	            return this._readyPromise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return ServiceManager;
	}());
	exports.ServiceManager = ServiceManager;
	// Define the signals for the `ServiceManager` class.
	signaling_1.defineSignal(ServiceManager.prototype, 'specsChanged');
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/manager.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/index.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/session/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/session/manager.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/session/session.js'));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/index.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/manager.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/session/manager.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var json_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/json.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var kernel_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/index.js');
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	var session_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/session/session.js');
	/**
	 * An implementation of a session manager.
	 */
	var SessionManager = (function () {
	    /**
	     * Construct a new session manager.
	     *
	     * @param options - The default options for each session.
	     */
	    function SessionManager(options) {
	        var _this = this;
	        if (options === void 0) { options = {}; }
	        this._baseUrl = '';
	        this._wsUrl = '';
	        this._ajaxSettings = '';
	        this._isDisposed = false;
	        this._running = [];
	        this._specs = null;
	        this._runningTimer = -1;
	        this._specsTimer = -1;
	        this._baseUrl = options.baseUrl || utils.getBaseUrl();
	        this._wsUrl = options.wsUrl || utils.getWsUrl(this._baseUrl);
	        this._ajaxSettings = JSON.stringify(options.ajaxSettings || {});
	        // Initialize internal data.
	        this._readyPromise = this._refreshSpecs().then(function () {
	            return _this._refreshRunning();
	        });
	        // Set up polling.
	        this._runningTimer = setInterval(function () {
	            _this._refreshRunning();
	        }, 10000);
	        this._specsTimer = setInterval(function () {
	            _this._refreshSpecs();
	        }, 61000);
	    }
	    Object.defineProperty(SessionManager.prototype, "isDisposed", {
	        /**
	         * Test whether the terminal manager is disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the manager.
	     */
	    SessionManager.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        clearInterval(this._runningTimer);
	        clearInterval(this._specsTimer);
	        signaling_1.clearSignalData(this);
	        this._running = [];
	    };
	    Object.defineProperty(SessionManager.prototype, "baseUrl", {
	        /**
	         * The base url of the manager.
	         */
	        get: function () {
	            return this._baseUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SessionManager.prototype, "wsUrl", {
	        /**
	         * The base ws url of the manager.
	         */
	        get: function () {
	            return this._wsUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SessionManager.prototype, "ajaxSettings", {
	        /**
	         * The default ajax settings for the manager.
	         */
	        get: function () {
	            return JSON.parse(this._ajaxSettings);
	        },
	        /**
	         * Set the default ajax settings for the manager.
	         */
	        set: function (value) {
	            this._ajaxSettings = JSON.stringify(value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SessionManager.prototype, "specs", {
	        /**
	         * Get the most recently fetched kernel specs.
	         */
	        get: function () {
	            return this._specs;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SessionManager.prototype, "isReady", {
	        /**
	         * Test whether the manager is ready.
	         */
	        get: function () {
	            return this._specs !== null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SessionManager.prototype, "ready", {
	        /**
	         * A promise that fulfills when the manager is ready.
	         */
	        get: function () {
	            return this._readyPromise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over the most recent running sessions.
	     *
	     * @returns A new iterator over the running sessions.
	     */
	    SessionManager.prototype.running = function () {
	        return iteration_1.iter(this._running);
	    };
	    /**
	     * Force a refresh of the specs from the server.
	     *
	     * @returns A promise that resolves when the specs are fetched.
	     *
	     * #### Notes
	     * This is intended to be called only in response to a user action,
	     * since the manager maintains its internal state.
	     */
	    SessionManager.prototype.refreshSpecs = function () {
	        return this._refreshSpecs();
	    };
	    /**
	     * Force a refresh of the running sessions.
	     *
	     * @returns A promise that with the list of running sessions.
	     *
	     * #### Notes
	     * This is not typically meant to be called by the user, since the
	     * manager maintains its own internal state.
	     */
	    SessionManager.prototype.refreshRunning = function () {
	        return this._refreshRunning();
	    };
	    /**
	     * Start a new session.  See also [[startNewSession]].
	     *
	     * @param options - Overrides for the default options, must include a
	     *   `'path'`.
	     */
	    SessionManager.prototype.startNew = function (options) {
	        var _this = this;
	        return session_1.Session.startNew(this._getOptions(options)).then(function (session) {
	            _this._onStarted(session);
	            return session;
	        });
	    };
	    /**
	     * Find a session by id.
	     */
	    SessionManager.prototype.findById = function (id, options) {
	        return session_1.Session.findById(id, this._getOptions(options));
	    };
	    /**
	     * Find a session by path.
	     */
	    SessionManager.prototype.findByPath = function (path, options) {
	        return session_1.Session.findByPath(path, this._getOptions(options));
	    };
	    /*
	     * Connect to a running session.  See also [[connectToSession]].
	     */
	    SessionManager.prototype.connectTo = function (id, options) {
	        var _this = this;
	        return session_1.Session.connectTo(id, this._getOptions(options)).then(function (session) {
	            _this._onStarted(session);
	            return session;
	        });
	    };
	    /**
	     * Shut down a session by id.
	     */
	    SessionManager.prototype.shutdown = function (id, options) {
	        var _this = this;
	        return session_1.Session.shutdown(id, this._getOptions(options)).then(function () {
	            _this._onTerminated(id);
	        });
	    };
	    /**
	     * Get optionally overidden options.
	     */
	    SessionManager.prototype._getOptions = function (options) {
	        if (options === void 0) { options = {}; }
	        options.baseUrl = this._baseUrl;
	        options.wsUrl = this._wsUrl;
	        options.ajaxSettings = options.ajaxSettings || this.ajaxSettings;
	        return options;
	    };
	    /**
	     * Handle a session terminating.
	     */
	    SessionManager.prototype._onTerminated = function (id) {
	        var index = searching_1.findIndex(this._running, function (value) { return value.id === id; });
	        if (index !== -1) {
	            this._running.splice(index, 1);
	            this.runningChanged.emit(this._running.slice());
	        }
	    };
	    /**
	     * Handle a session starting.
	     */
	    SessionManager.prototype._onStarted = function (session) {
	        var _this = this;
	        var id = session.id;
	        var index = searching_1.findIndex(this._running, function (value) { return value.id === id; });
	        if (index === -1) {
	            this._running.push(session.model);
	            this.runningChanged.emit(this._running.slice());
	        }
	        session.terminated.connect(function () {
	            _this._onTerminated(id);
	        });
	        session.pathChanged.connect(function () {
	            _this._onChanged(session.model);
	        });
	        session.kernelChanged.connect(function () {
	            _this._onChanged(session.model);
	        });
	    };
	    /**
	     * Handle a change to a session.
	     */
	    SessionManager.prototype._onChanged = function (model) {
	        var index = searching_1.findIndex(this._running, function (value) { return value.id === model.id; });
	        if (index !== -1) {
	            this._running[index] = model;
	            this.runningChanged.emit(this._running.slice());
	        }
	    };
	    /**
	     * Refresh the specs.
	     */
	    SessionManager.prototype._refreshSpecs = function () {
	        var _this = this;
	        var options = {
	            baseUrl: this._baseUrl,
	            ajaxSettings: this.ajaxSettings
	        };
	        return kernel_1.Kernel.getSpecs(options).then(function (specs) {
	            if (!json_1.deepEqual(specs, _this._specs)) {
	                _this._specs = specs;
	                _this.specsChanged.emit(specs);
	            }
	        });
	    };
	    /**
	     * Refresh the running sessions.
	     */
	    SessionManager.prototype._refreshRunning = function () {
	        var _this = this;
	        return session_1.Session.listRunning(this._getOptions({})).then(function (running) {
	            if (!json_1.deepEqual(running, _this._running)) {
	                _this._running = running.slice();
	                _this.runningChanged.emit(running);
	            }
	        });
	    };
	    return SessionManager;
	}());
	exports.SessionManager = SessionManager;
	// Define the signals for the `SessionManager` class.
	signaling_1.defineSignal(SessionManager.prototype, 'specsChanged');
	signaling_1.defineSignal(SessionManager.prototype, 'runningChanged');
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/manager.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/session.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/session/session.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var default_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/session/default.js');
	/**
	 * A namespace for session interfaces and factory functions.
	 */
	var Session;
	(function (Session) {
	    /**
	     * List the running sessions.
	     *
	     * @param options - The options used for the request.
	     *
	     * @returns A promise that resolves with the list of session models.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/sessions), and validates the response.
	     *
	     * All client-side sessions are updated with current information.
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     */
	    function listRunning(options) {
	        return default_1.DefaultSession.listRunning(options);
	    }
	    Session.listRunning = listRunning;
	    /**
	     * Start a new session.
	     *
	     * @param options - The options used to start the session.
	     *
	     * @returns A promise that resolves with the session instance.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/sessions), and validates the response.
	     *
	     * A path must be provided.  If a kernel id is given, it will
	     * connect to an existing kernel.  If no kernel id or name is given,
	     * the server will start the default kernel type.
	     *
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     *
	     * Wrap the result in an Session object. The promise is fulfilled
	     * when the session is created on the server, otherwise the promise is
	     * rejected.
	     */
	    function startNew(options) {
	        return default_1.DefaultSession.startNew(options);
	    }
	    Session.startNew = startNew;
	    /**
	     * Find a session by id.
	     *
	     * @param id - The id of the target session.
	     *
	     * @param options - The options used to fetch the session.
	     *
	     * @returns A promise that resolves with the session model.
	     *
	     * #### Notes
	     * If the session was already started via `startNew`, the existing
	     * Session object's information is used in the fulfillment value.
	     *
	     * Otherwise, if `options` are given, we attempt to find to the existing
	     * session.
	     * The promise is fulfilled when the session is found,
	     * otherwise the promise is rejected.
	     */
	    function findById(id, options) {
	        return default_1.DefaultSession.findById(id, options);
	    }
	    Session.findById = findById;
	    /**
	     * Find a session by path.
	     *
	     * @param path - The path of the target session.
	     *
	     * @param options - The options used to fetch the session.
	     *
	     * @returns A promise that resolves with the session model.
	     *
	     * #### Notes
	     * If the session was already started via `startNewSession`, the existing
	     * Session object's info is used in the fulfillment value.
	     *
	     * Otherwise, if `options` are given, we attempt to find to the existing
	     * session using [listRunningSessions].
	     * The promise is fulfilled when the session is found,
	     * otherwise the promise is rejected.
	     *
	     * If the session was not already started and no `options` are given,
	     * the promise is rejected.
	     */
	    function findByPath(path, options) {
	        return default_1.DefaultSession.findByPath(path, options);
	    }
	    Session.findByPath = findByPath;
	    /**
	     * Connect to a running session.
	     *
	     * @param id - The id of the target session.
	     *
	     * @param options - The options used to fetch the session.
	     *
	     * @returns A promise that resolves with the session instance.
	     *
	     * #### Notes
	     * If the session was already started via `startNew`, the existing
	     * Session object is used as the fulfillment value.
	     *
	     * Otherwise, if `options` are given, we attempt to connect to the existing
	     * session.
	     * The promise is fulfilled when the session is ready on the server,
	     * otherwise the promise is rejected.
	     *
	     * If the session was not already started and no `options` are given,
	     * the promise is rejected.
	     */
	    function connectTo(id, options) {
	        return default_1.DefaultSession.connectTo(id, options);
	    }
	    Session.connectTo = connectTo;
	    /**
	     * Shut down a session by id.
	     *
	     * @param id - The id of the target session.
	     *
	     * @param options - The options used to fetch the session.
	     *
	     * @returns A promise that resolves when the session is shut down.
	     *
	     */
	    function shutdown(id, options) {
	        if (options === void 0) { options = {}; }
	        return default_1.DefaultSession.shutdown(id, options);
	    }
	    Session.shutdown = shutdown;
	})(Session = exports.Session || (exports.Session = {}));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/session.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/default.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/session/default.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var kernel_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/index.js');
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	var validate = __jupyter_require__('@jupyterlab/services@0.36.1/lib/session/validate.js');
	/**
	 * The url for the session service.
	 */
	var SESSION_SERVICE_URL = 'api/sessions';
	/**
	 * Session object for accessing the session REST api. The session
	 * should be used to start kernels and then shut them down -- for
	 * all other operations, the kernel object should be used.
	 */
	var DefaultSession = (function () {
	    /**
	     * Construct a new session.
	     */
	    function DefaultSession(options, id, kernel) {
	        this._id = '';
	        this._path = '';
	        this._ajaxSettings = '';
	        this._token = '';
	        this._kernel = null;
	        this._uuid = '';
	        this._baseUrl = '';
	        this._options = null;
	        this._updating = false;
	        this._id = id;
	        this._path = options.path;
	        this._baseUrl = options.baseUrl || utils.getBaseUrl();
	        this._uuid = utils.uuid();
	        this._ajaxSettings = JSON.stringify(utils.ajaxSettingsWithToken(options.ajaxSettings || {}, options.token));
	        this._token = options.token || utils.getConfigOption('token');
	        Private.runningSessions.pushBack(this);
	        this.setupKernel(kernel);
	        this._options = utils.copy(options);
	    }
	    Object.defineProperty(DefaultSession.prototype, "id", {
	        /**
	         * Get the session id.
	         */
	        get: function () {
	            return this._id;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultSession.prototype, "kernel", {
	        /**
	         * Get the session kernel object.
	         *
	         * #### Notes
	         * This is a read-only property, and can be altered by [changeKernel].
	         * Use the [statusChanged] and [unhandledMessage] signals on the session
	         * instead of the ones on the kernel.
	         */
	        get: function () {
	            return this._kernel;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultSession.prototype, "path", {
	        /**
	         * Get the session path.
	         */
	        get: function () {
	            return this._path;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultSession.prototype, "model", {
	        /**
	         * Get the model associated with the session.
	         */
	        get: function () {
	            return {
	                id: this.id,
	                kernel: this.kernel.model,
	                notebook: {
	                    path: this.path
	                }
	            };
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultSession.prototype, "status", {
	        /**
	         * The current status of the session.
	         *
	         * #### Notes
	         * This is a delegate to the kernel status.
	         */
	        get: function () {
	            return this._kernel ? this._kernel.status : 'dead';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultSession.prototype, "baseUrl", {
	        /**
	         * Get the base url of the session.
	         */
	        get: function () {
	            return this._baseUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultSession.prototype, "ajaxSettings", {
	        /**
	         * Get a copy of the default ajax settings for the session.
	         */
	        get: function () {
	            return JSON.parse(this._ajaxSettings);
	        },
	        /**
	         * Set the default ajax settings for the session.
	         */
	        set: function (value) {
	            this._ajaxSettings = JSON.stringify(value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultSession.prototype, "isDisposed", {
	        /**
	         * Test whether the session has been disposed.
	         */
	        get: function () {
	            return this._options === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Clone the current session with a new clientId.
	     */
	    DefaultSession.prototype.clone = function () {
	        var _this = this;
	        var options = this._getKernelOptions();
	        return kernel_1.Kernel.connectTo(this.kernel.id, options).then(function (kernel) {
	            options = utils.copy(_this._options);
	            options.ajaxSettings = _this.ajaxSettings;
	            return new DefaultSession(options, _this._id, kernel);
	        });
	    };
	    /**
	     * Update the session based on a session model from the server.
	     */
	    DefaultSession.prototype.update = function (model) {
	        var _this = this;
	        // Avoid a race condition if we are waiting for a REST call return.
	        if (this._updating) {
	            return Promise.resolve(void 0);
	        }
	        var oldPath = this._path;
	        var newPath = this._path = model.notebook.path;
	        if (this._kernel.isDisposed || model.kernel.id !== this._kernel.id) {
	            var options = this._getKernelOptions();
	            options.name = model.kernel.name;
	            return kernel_1.Kernel.connectTo(model.kernel.id, options).then(function (kernel) {
	                _this.setupKernel(kernel);
	                _this.kernelChanged.emit(kernel);
	                if (oldPath !== newPath) {
	                    _this.pathChanged.emit(newPath);
	                }
	            });
	        }
	        else if (oldPath !== newPath) {
	            this.pathChanged.emit(newPath);
	        }
	        return Promise.resolve(void 0);
	    };
	    /**
	     * Dispose of the resources held by the session.
	     */
	    DefaultSession.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._options = null;
	        if (this._kernel) {
	            this._kernel.dispose();
	        }
	        Private.runningSessions.remove(this);
	        this._kernel = null;
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Change the session path.
	     *
	     * @param path - The new session path.
	     *
	     * #### Notes
	     * This uses the Jupyter REST API, and the response is validated.
	     * The promise is fulfilled on a valid response and rejected otherwise.
	     */
	    DefaultSession.prototype.rename = function (path) {
	        if (this.isDisposed) {
	            return Promise.reject(new Error('Session is disposed'));
	        }
	        var data = JSON.stringify({
	            notebook: { path: path }
	        });
	        return this._patch(data).then(function () { return void 0; });
	    };
	    /**
	     * Change the kernel.
	     *
	     * @params options - The name or id of the new kernel.
	     *
	     * #### Notes
	     * This shuts down the existing kernel and creates a new kernel,
	     * keeping the existing session ID and session path.
	     */
	    DefaultSession.prototype.changeKernel = function (options) {
	        var _this = this;
	        if (this.isDisposed) {
	            return Promise.reject(new Error('Session is disposed'));
	        }
	        this._kernel.dispose();
	        var data = JSON.stringify({ kernel: options });
	        return this._patch(data).then(function () {
	            return _this.kernel;
	        });
	    };
	    /**
	     * Kill the kernel and shutdown the session.
	     *
	     * @returns - The promise fulfilled on a valid response from the server.
	     *
	     * #### Notes
	     * Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/sessions), and validates the response.
	     * Emits a [sessionDied] signal on success.
	     */
	    DefaultSession.prototype.shutdown = function () {
	        if (this.isDisposed) {
	            return Promise.reject(new Error('Session is disposed'));
	        }
	        return Private.shutdownSession(this.id, this._baseUrl, this.ajaxSettings);
	    };
	    /**
	     * Handle connections to a kernel.
	     */
	    DefaultSession.prototype.setupKernel = function (kernel) {
	        this._kernel = kernel;
	        kernel.statusChanged.connect(this.onKernelStatus, this);
	        kernel.unhandledMessage.connect(this.onUnhandledMessage, this);
	        kernel.iopubMessage.connect(this.onIOPubMessage, this);
	    };
	    /**
	     * Handle to changes in the Kernel status.
	     */
	    DefaultSession.prototype.onKernelStatus = function (sender, state) {
	        this.statusChanged.emit(state);
	    };
	    /**
	     * Handle iopub kernel messages.
	     */
	    DefaultSession.prototype.onIOPubMessage = function (sender, msg) {
	        this.iopubMessage.emit(msg);
	    };
	    /**
	     * Handle unhandled kernel messages.
	     */
	    DefaultSession.prototype.onUnhandledMessage = function (sender, msg) {
	        this.unhandledMessage.emit(msg);
	    };
	    /**
	     * Get the options used to create a new kernel.
	     */
	    DefaultSession.prototype._getKernelOptions = function () {
	        return {
	            baseUrl: this._options.baseUrl,
	            wsUrl: this._options.wsUrl,
	            username: this.kernel.username,
	            ajaxSettings: this.ajaxSettings
	        };
	    };
	    /**
	     * Send a PATCH to the server, updating the session path or the kernel.
	     */
	    DefaultSession.prototype._patch = function (data) {
	        var _this = this;
	        var url = Private.getSessionUrl(this._baseUrl, this._id);
	        var ajaxSettings = this.ajaxSettings;
	        ajaxSettings.method = 'PATCH';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.data = data;
	        ajaxSettings.contentType = 'application/json';
	        ajaxSettings.cache = false;
	        this._updating = true;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            _this._updating = false;
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            var value = success.data;
	            try {
	                validate.validateModel(value);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            return Private.updateFromServer(value);
	        }, function (error) {
	            _this._updating = false;
	            return Private.onSessionError(error);
	        });
	    };
	    return DefaultSession;
	}());
	exports.DefaultSession = DefaultSession;
	// Define the signals for the `DefaultSession` class.
	signaling_1.defineSignal(DefaultSession.prototype, 'terminated');
	signaling_1.defineSignal(DefaultSession.prototype, 'kernelChanged');
	signaling_1.defineSignal(DefaultSession.prototype, 'statusChanged');
	signaling_1.defineSignal(DefaultSession.prototype, 'iopubMessage');
	signaling_1.defineSignal(DefaultSession.prototype, 'unhandledMessage');
	signaling_1.defineSignal(DefaultSession.prototype, 'pathChanged');
	/**
	 * The namespace for `DefaultSession` statics.
	 */
	var DefaultSession;
	(function (DefaultSession) {
	    /**
	     * List the running sessions.
	     */
	    function listRunning(options) {
	        return Private.listRunning(options);
	    }
	    DefaultSession.listRunning = listRunning;
	    /**
	     * Start a new session.
	     */
	    function startNew(options) {
	        return Private.startNew(options);
	    }
	    DefaultSession.startNew = startNew;
	    /**
	     * Find a session by id.
	     */
	    function findById(id, options) {
	        return Private.findById(id, options);
	    }
	    DefaultSession.findById = findById;
	    /**
	     * Find a session by path.
	     */
	    function findByPath(path, options) {
	        return Private.findByPath(path, options);
	    }
	    DefaultSession.findByPath = findByPath;
	    /**
	     * Connect to a running session.
	     */
	    function connectTo(id, options) {
	        return Private.connectTo(id, options);
	    }
	    DefaultSession.connectTo = connectTo;
	    /**
	     * Shut down a session by id.
	     */
	    function shutdown(id, options) {
	        if (options === void 0) { options = {}; }
	        return Private.shutdown(id, options);
	    }
	    DefaultSession.shutdown = shutdown;
	})(DefaultSession = exports.DefaultSession || (exports.DefaultSession = {}));
	/**
	 * A namespace for session private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * The running sessions.
	     */
	    Private.runningSessions = new vector_1.Vector();
	    /**
	     * List the running sessions.
	     */
	    function listRunning(options) {
	        if (options === void 0) { options = {}; }
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var url = utils.urlPathJoin(baseUrl, SESSION_SERVICE_URL);
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'GET';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            var data = success.data;
	            if (!Array.isArray(success.data)) {
	                return utils.makeAjaxError(success, 'Invalid Session list');
	            }
	            for (var i = 0; i < data.length; i++) {
	                try {
	                    validate.validateModel(data[i]);
	                }
	                catch (err) {
	                    return utils.makeAjaxError(success, err.message);
	                }
	            }
	            return updateRunningSessions(data);
	        }, Private.onSessionError);
	    }
	    Private.listRunning = listRunning;
	    /**
	     * Start a new session.
	     */
	    function startNew(options) {
	        if (options.path === void 0) {
	            return Promise.reject(new Error('Must specify a path'));
	        }
	        return startSession(options).then(function (model) {
	            return createSession(model, options);
	        });
	    }
	    Private.startNew = startNew;
	    /**
	     * Find a session by id.
	     */
	    function findById(id, options) {
	        if (options === void 0) { options = {}; }
	        var session = searching_1.find(Private.runningSessions, function (value) { return value.id === id; });
	        if (session) {
	            return Promise.resolve(session.model);
	        }
	        return getSessionModel(id, options).catch(function () {
	            var msg = "No running session for id: " + id;
	            return typedThrow(msg);
	        });
	    }
	    Private.findById = findById;
	    /**
	     * Find a session by path.
	     */
	    function findByPath(path, options) {
	        if (options === void 0) { options = {}; }
	        var session = searching_1.find(Private.runningSessions, function (value) { return value.path === path; });
	        if (session) {
	            return Promise.resolve(session.model);
	        }
	        return listRunning(options).then(function (models) {
	            var model = searching_1.find(models, function (value) {
	                return value.notebook.path === path;
	            });
	            if (model) {
	                return model;
	            }
	            var msg = "No running session for path: " + path;
	            return typedThrow(msg);
	        });
	    }
	    Private.findByPath = findByPath;
	    /**
	     * Connect to a running session.
	     */
	    function connectTo(id, options) {
	        if (options === void 0) { options = {}; }
	        var session = searching_1.find(Private.runningSessions, function (value) { return value.id === id; });
	        if (session) {
	            return Promise.resolve(session.clone());
	        }
	        return getSessionModel(id, options).then(function (model) {
	            return createSession(model, options);
	        }).catch(function () {
	            var msg = "No running session with id: " + id;
	            return typedThrow(msg);
	        });
	    }
	    Private.connectTo = connectTo;
	    /**
	     * Shut down a session by id.
	     */
	    function shutdown(id, options) {
	        if (options === void 0) { options = {}; }
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        return shutdownSession(id, baseUrl, ajaxSettings);
	    }
	    Private.shutdown = shutdown;
	    /**
	     * Create a new session, or return an existing session if a session if
	     * the session path already exists
	     */
	    function startSession(options) {
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var url = utils.urlPathJoin(baseUrl, SESSION_SERVICE_URL);
	        var model = {
	            kernel: { name: options.kernelName, id: options.kernelId },
	            notebook: { path: options.path }
	        };
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'POST';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.data = JSON.stringify(model);
	        ajaxSettings.contentType = 'application/json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 201) {
	                return utils.makeAjaxError(success);
	            }
	            try {
	                validate.validateModel(success.data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            var data = success.data;
	            return updateFromServer(data);
	        }, onSessionError);
	    }
	    Private.startSession = startSession;
	    /**
	     * Create a Promise for a kernel object given a session model and options.
	     */
	    function createKernel(options) {
	        var kernelOptions = {
	            name: options.kernelName,
	            baseUrl: options.baseUrl || utils.getBaseUrl(),
	            wsUrl: options.wsUrl,
	            username: options.username,
	            clientId: options.clientId,
	            token: options.token,
	            ajaxSettings: options.ajaxSettings
	        };
	        return kernel_1.Kernel.connectTo(options.kernelId, kernelOptions);
	    }
	    /**
	     * Create a Session object.
	     *
	     * @returns - A promise that resolves with a started session.
	     */
	    function createSession(model, options) {
	        options.kernelName = model.kernel.name;
	        options.kernelId = model.kernel.id;
	        options.path = model.notebook.path;
	        return createKernel(options).then(function (kernel) {
	            return new DefaultSession(options, model.id, kernel);
	        }).catch(function (error) {
	            return typedThrow('Session failed to start: ' + error.message);
	        });
	    }
	    Private.createSession = createSession;
	    /**
	     * Get a full session model from the server by session id string.
	     */
	    function getSessionModel(id, options) {
	        options = options || {};
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var url = getSessionUrl(baseUrl, id);
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'GET';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            var data = success.data;
	            try {
	                validate.validateModel(data);
	            }
	            catch (err) {
	                return utils.makeAjaxError(success, err.message);
	            }
	            return updateFromServer(data);
	        }, Private.onSessionError);
	    }
	    Private.getSessionModel = getSessionModel;
	    /**
	     * Update the running sessions based on new data from the server.
	     */
	    function updateRunningSessions(sessions) {
	        var promises = [];
	        iteration_1.each(Private.runningSessions, function (session) {
	            var updated = searching_1.find(sessions, function (sId) {
	                if (session.id === sId.id) {
	                    promises.push(session.update(sId));
	                    return true;
	                }
	            });
	            // If session is no longer running on disk, emit dead signal.
	            if (!updated && session.status !== 'dead') {
	                session.terminated.emit(void 0);
	            }
	        });
	        return Promise.all(promises).then(function () { return sessions; });
	    }
	    Private.updateRunningSessions = updateRunningSessions;
	    /**
	     * Update the running sessions given an updated session Id.
	     */
	    function updateFromServer(model) {
	        var promises = [];
	        iteration_1.each(Private.runningSessions, function (session) {
	            if (session.id === model.id) {
	                promises.push(session.update(model));
	            }
	        });
	        return Promise.all(promises).then(function () { return model; });
	    }
	    Private.updateFromServer = updateFromServer;
	    /**
	     * Shut down a session by id.
	     */
	    function shutdownSession(id, baseUrl, ajaxSettings) {
	        if (ajaxSettings === void 0) { ajaxSettings = {}; }
	        var url = getSessionUrl(baseUrl, id);
	        ajaxSettings.method = 'DELETE';
	        ajaxSettings.dataType = 'json';
	        ajaxSettings.cache = false;
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 204) {
	                return utils.makeAjaxError(success);
	            }
	            killSessions(id);
	        }, function (err) {
	            if (err.xhr.status === 404) {
	                var response = JSON.parse(err.xhr.responseText);
	                console.warn(response['message']);
	                killSessions(id);
	                return;
	            }
	            if (err.xhr.status === 410) {
	                err.throwError = 'The kernel was deleted but the session was not';
	            }
	            return onSessionError(err);
	        });
	    }
	    Private.shutdownSession = shutdownSession;
	    /**
	     * Kill the sessions by id.
	     */
	    function killSessions(id) {
	        iteration_1.each(iteration_1.toArray(Private.runningSessions), function (session) {
	            if (session.id === id) {
	                session.terminated.emit(void 0);
	                session.dispose();
	            }
	        });
	    }
	    /**
	     * Get a session url.
	     */
	    function getSessionUrl(baseUrl, id) {
	        return utils.urlPathJoin(baseUrl, SESSION_SERVICE_URL, id);
	    }
	    Private.getSessionUrl = getSessionUrl;
	    /**
	     * Handle an error on a session Ajax call.
	     */
	    function onSessionError(error) {
	        var text = (error.throwError ||
	            error.xhr.statusText ||
	            error.xhr.responseText);
	        var msg = "API request failed: " + text;
	        console.error(msg);
	        return Promise.reject(error);
	    }
	    Private.onSessionError = onSessionError;
	    /**
	     * Throw a typed error.
	     */
	    function typedThrow(msg) {
	        throw new Error(msg);
	    }
	    Private.typedThrow = typedThrow;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/default.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/validate.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/session/validate.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var validate_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/kernel/validate.js');
	/**
	 * Validate a property as being on an object, and optionally
	 * of a given type.
	 */
	function validateProperty(object, name, typeName) {
	    if (!object.hasOwnProperty(name)) {
	        throw Error("Missing property '" + name + "'");
	    }
	    if (typeName !== void 0) {
	        var valid = true;
	        var value = object[name];
	        switch (typeName) {
	            case 'array':
	                valid = Array.isArray(value);
	                break;
	            case 'object':
	                valid = typeof value !== 'undefined';
	                break;
	            default:
	                valid = typeof value === typeName;
	        }
	        if (!valid) {
	            throw new Error("Property '" + name + "' is not of type '" + typeName);
	        }
	    }
	}
	/**
	 * Validate an `Session.IModel` object.
	 */
	function validateModel(model) {
	    validateProperty(model, 'id', 'string');
	    validateProperty(model, 'notebook', 'object');
	    validateProperty(model, 'kernel', 'object');
	    validate_1.validateModel(model.kernel);
	    validateProperty(model.notebook, 'path', 'string');
	}
	exports.validateModel = validateModel;
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/session/validate.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/terminal/index.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/terminal/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/terminal/manager.js'));
	__export(__jupyter_require__('@jupyterlab/services@0.36.1/lib/terminal/terminal.js'));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/terminal/index.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/terminal/manager.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/terminal/manager.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var json_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/json.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	var terminal_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/terminal/terminal.js');
	/**
	 * A terminal session manager.
	 */
	var TerminalManager = (function () {
	    /**
	     * Construct a new terminal manager.
	     */
	    function TerminalManager(options) {
	        var _this = this;
	        if (options === void 0) { options = {}; }
	        this._baseUrl = '';
	        this._wsUrl = '';
	        this._ajaxSettings = '';
	        this._running = [];
	        this._isDisposed = false;
	        this._isReady = false;
	        this._refreshTimer = -1;
	        this._baseUrl = options.baseUrl || utils.getBaseUrl();
	        this._wsUrl = options.wsUrl || utils.getWsUrl(this._baseUrl);
	        this._ajaxSettings = JSON.stringify(options.ajaxSettings || {});
	        // Set up state handling if terminals are available.
	        if (terminal_1.TerminalSession.isAvailable()) {
	            // Initialize internal data.
	            this._readyPromise = this._refreshRunning();
	            // Set up polling.
	            this._refreshTimer = setInterval(function () {
	                _this._refreshRunning();
	            }, 10000);
	        }
	    }
	    Object.defineProperty(TerminalManager.prototype, "isDisposed", {
	        /**
	         * Test whether the terminal manager is disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TerminalManager.prototype, "baseUrl", {
	        /**
	         * The base url of the manager.
	         */
	        get: function () {
	            return this._baseUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TerminalManager.prototype, "wsUrl", {
	        /**
	         * The base ws url of the manager.
	         */
	        get: function () {
	            return this._wsUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TerminalManager.prototype, "ajaxSettings", {
	        /**
	         * The default ajax settings for the manager.
	         */
	        get: function () {
	            return JSON.parse(this._ajaxSettings);
	        },
	        /**
	         * Set the default ajax settings for the manager.
	         */
	        set: function (value) {
	            this._ajaxSettings = JSON.stringify(value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TerminalManager.prototype, "isReady", {
	        /**
	         * Test whether the manger is ready.
	         */
	        get: function () {
	            return this._isReady;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the manager.
	     */
	    TerminalManager.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        clearInterval(this._refreshTimer);
	        signaling_1.clearSignalData(this);
	        this._running = [];
	    };
	    Object.defineProperty(TerminalManager.prototype, "ready", {
	        /**
	         * A promise that fulfills when the manager is ready.
	         */
	        get: function () {
	            return this._readyPromise || Promise.reject('Terminals unavailable');
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Whether the terminal service is available.
	     */
	    TerminalManager.prototype.isAvailable = function () {
	        return terminal_1.TerminalSession.isAvailable();
	    };
	    /**
	     * Create an iterator over the most recent running terminals.
	     *
	     * @returns A new iterator over the running terminals.
	     */
	    TerminalManager.prototype.running = function () {
	        return iteration_1.iter(this._running);
	    };
	    /**
	     * Create a new terminal session.
	     *
	     * @param ajaxSettings - The ajaxSettings to use, overrides manager
	     *   settings.
	     *
	     * @returns A promise that resolves with the terminal instance.
	     *
	     * #### Notes
	     * The baseUrl and wsUrl of the options will be forced
	     * to the ones used by the manager. The ajaxSettings of the manager
	     * will be used unless overridden.
	     */
	    TerminalManager.prototype.startNew = function (options) {
	        var _this = this;
	        return terminal_1.TerminalSession.startNew(this._getOptions(options)).then(function (session) {
	            _this._onStarted(session);
	            return session;
	        });
	    };
	    /*
	     * Connect to a running session.
	     *
	     * @param name - The name of the target session.
	     *
	     * @param ajaxSettings - The ajaxSettings to use, overrides manager
	     *   settings.
	     *
	     * @returns A promise that resolves with the new session instance.
	     *
	     * #### Notes
	     * The baseUrl and wsUrl of the options will be forced
	     * to the ones used by the manager. The ajaxSettings of the manager
	     * will be used unless overridden.
	     */
	    TerminalManager.prototype.connectTo = function (name, options) {
	        var _this = this;
	        return terminal_1.TerminalSession.connectTo(name, this._getOptions(options)).then(function (session) {
	            _this._onStarted(session);
	            return session;
	        });
	    };
	    /**
	     * Shut down a terminal session by name.
	     */
	    TerminalManager.prototype.shutdown = function (name) {
	        var _this = this;
	        return terminal_1.TerminalSession.shutdown(name, this._getOptions()).then(function () {
	            _this._onTerminated(name);
	        });
	    };
	    /**
	     * Force a refresh of the running sessions.
	     *
	     * @returns A promise that with the list of running sessions.
	     *
	     * #### Notes
	     * This is not typically meant to be called by the user, since the
	     * manager maintains its own internal state.
	     */
	    TerminalManager.prototype.refreshRunning = function () {
	        return this._refreshRunning();
	    };
	    /**
	     * Handle a session terminating.
	     */
	    TerminalManager.prototype._onTerminated = function (name) {
	        var index = searching_1.findIndex(this._running, function (value) { return value.name === name; });
	        if (index !== -1) {
	            this._running.splice(index, 1);
	            this.runningChanged.emit(this._running.slice());
	        }
	    };
	    /**
	     * Handle a session starting.
	     */
	    TerminalManager.prototype._onStarted = function (session) {
	        var _this = this;
	        var name = session.name;
	        var index = searching_1.findIndex(this._running, function (value) { return value.name === name; });
	        if (index === -1) {
	            this._running.push(session.model);
	            this.runningChanged.emit(this._running.slice());
	        }
	        session.terminated.connect(function () {
	            _this._onTerminated(name);
	        });
	    };
	    /**
	     * Refresh the running sessions.
	     */
	    TerminalManager.prototype._refreshRunning = function () {
	        var _this = this;
	        return terminal_1.TerminalSession.listRunning(this._getOptions({})).then(function (running) {
	            _this._isReady = true;
	            if (!json_1.deepEqual(running, _this._running)) {
	                _this._running = running.slice();
	                _this.runningChanged.emit(running);
	            }
	        });
	    };
	    /**
	     * Get a set of options to pass.
	     */
	    TerminalManager.prototype._getOptions = function (options) {
	        if (options === void 0) { options = {}; }
	        options.baseUrl = this.baseUrl;
	        options.wsUrl = this.wsUrl;
	        options.ajaxSettings = options.ajaxSettings || this.ajaxSettings;
	        return options;
	    };
	    return TerminalManager;
	}());
	exports.TerminalManager = TerminalManager;
	// Define the signals for the `TerminalManager` class.
	signaling_1.defineSignal(TerminalManager.prototype, 'runningChanged');
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/terminal/manager.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/terminal/terminal.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/terminal/terminal.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var default_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/terminal/default.js');
	/**
	 * The namespace for ISession statics.
	 */
	var TerminalSession;
	(function (TerminalSession) {
	    /**
	     * Test whether the terminal service is available.
	     */
	    function isAvailable() {
	        return default_1.DefaultTerminalSession.isAvailable();
	    }
	    TerminalSession.isAvailable = isAvailable;
	    /**
	     * Start a new terminal session.
	     *
	     * @options - The session options to use.
	     *
	     * @returns A promise that resolves with the session instance.
	     */
	    function startNew(options) {
	        return default_1.DefaultTerminalSession.startNew(options);
	    }
	    TerminalSession.startNew = startNew;
	    /*
	     * Connect to a running session.
	     *
	     * @param name - The name of the target session.
	     *
	     * @param options - The session options to use.
	     *
	     * @returns A promise that resolves with the new session instance.
	     *
	     * #### Notes
	     * If the session was already started via `startNew`, the existing
	     * session object is used as the fulfillment value.
	     *
	     * Otherwise, if `options` are given, we attempt to connect to the existing
	     * session.
	     * The promise is fulfilled when the session is ready on the server,
	     * otherwise the promise is rejected.
	     *
	     * If the session was not already started and no `options` are given,
	     * the promise is rejected.
	     */
	    function connectTo(name, options) {
	        return default_1.DefaultTerminalSession.connectTo(name, options);
	    }
	    TerminalSession.connectTo = connectTo;
	    /**
	     * List the running terminal sessions.
	     *
	     * @param options - The session options to use.
	     *
	     * @returns A promise that resolves with the list of running session models.
	     */
	    function listRunning(options) {
	        return default_1.DefaultTerminalSession.listRunning(options);
	    }
	    TerminalSession.listRunning = listRunning;
	    /**
	     * Shut down a terminal session by name.
	     *
	     * @param name - The name of the target session.
	     *
	     * @param options - The session options to use.
	     *
	     * @returns A promise that resolves when the session is shut down.
	     */
	    function shutdown(name, options) {
	        return default_1.DefaultTerminalSession.shutdown(name, options);
	    }
	    TerminalSession.shutdown = shutdown;
	})(TerminalSession = exports.TerminalSession || (exports.TerminalSession = {}));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/terminal/terminal.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/terminal/default.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/terminal/default.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var utils = __jupyter_require__('@jupyterlab/services@0.36.1/lib/utils.js');
	var terminal_1 = __jupyter_require__('@jupyterlab/services@0.36.1/lib/terminal/terminal.js');
	/**
	 * The url for the terminal service.
	 */
	var TERMINAL_SERVICE_URL = 'api/terminals';
	/**
	 * An implementation of a terminal interface.
	 */
	var DefaultTerminalSession = (function () {
	    /**
	     * Construct a new terminal session.
	     */
	    function DefaultTerminalSession(name, options) {
	        if (options === void 0) { options = {}; }
	        this._token = '';
	        this._ajaxSettings = '';
	        this._ws = null;
	        this._isDisposed = false;
	        this._isReady = false;
	        this._name = name;
	        this._baseUrl = options.baseUrl || utils.getBaseUrl();
	        this._token = options.token || utils.getConfigOption('token');
	        this._ajaxSettings = JSON.stringify(utils.ajaxSettingsWithToken(options.ajaxSettings, this._token));
	        this._wsUrl = options.wsUrl || utils.getWsUrl(this._baseUrl);
	        this._readyPromise = this._initializeSocket();
	    }
	    Object.defineProperty(DefaultTerminalSession.prototype, "name", {
	        /**
	         * Get the name of the terminal session.
	         */
	        get: function () {
	            return this._name;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultTerminalSession.prototype, "model", {
	        /**
	         * Get the model for the terminal session.
	         */
	        get: function () {
	            return { name: this._name };
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultTerminalSession.prototype, "baseUrl", {
	        /**
	         * The base url of the terminal.
	         */
	        get: function () {
	            return this._baseUrl;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultTerminalSession.prototype, "ajaxSettings", {
	        /**
	         * Get a copy of the default ajax settings for the terminal.
	         */
	        get: function () {
	            return JSON.parse(this._ajaxSettings);
	        },
	        /**
	         * Set the default ajax settings for the terminal.
	         */
	        set: function (value) {
	            this._ajaxSettings = JSON.stringify(value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultTerminalSession.prototype, "isReady", {
	        /**
	         * Test whether the session is ready.
	         */
	        get: function () {
	            return this._isReady;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultTerminalSession.prototype, "ready", {
	        /**
	         * A promise that fulfills when the manager is ready.
	         */
	        get: function () {
	            return this._readyPromise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DefaultTerminalSession.prototype, "isDisposed", {
	        /**
	         * Test whether the session is disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the session.
	     */
	    DefaultTerminalSession.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        if (this._ws) {
	            this._ws.close();
	            this._ws = null;
	        }
	        delete Private.running[this._url];
	        this._readyPromise = null;
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Send a message to the terminal session.
	     */
	    DefaultTerminalSession.prototype.send = function (message) {
	        var _this = this;
	        var msg = [message.type];
	        msg.push.apply(msg, message.content);
	        var value = JSON.stringify(msg);
	        if (this._isReady) {
	            this._ws.send(value);
	            return;
	        }
	        this.ready.then(function () {
	            _this._ws.send(value);
	        });
	    };
	    /**
	     * Shut down the terminal session.
	     */
	    DefaultTerminalSession.prototype.shutdown = function () {
	        var options = {
	            baseUrl: this._baseUrl,
	            ajaxSettings: this.ajaxSettings
	        };
	        return DefaultTerminalSession.shutdown(this.name, options);
	    };
	    /**
	     * Connect to the websocket.
	     */
	    DefaultTerminalSession.prototype._initializeSocket = function () {
	        var _this = this;
	        var name = this._name;
	        this._url = Private.getTermUrl(this._baseUrl, this._name);
	        Private.running[this._url] = this;
	        var wsUrl = utils.urlPathJoin(this._wsUrl, "terminals/websocket/" + name);
	        if (this._token) {
	            wsUrl = wsUrl + ("?token=" + this._token);
	        }
	        this._ws = new WebSocket(wsUrl);
	        this._ws.onmessage = function (event) {
	            var data = JSON.parse(event.data);
	            _this.messageReceived.emit({
	                type: data[0],
	                content: data.slice(1)
	            });
	        };
	        return new Promise(function (resolve, reject) {
	            _this._ws.onopen = function (event) {
	                _this._isReady = true;
	                resolve(void 0);
	            };
	            _this._ws.onerror = function (event) {
	                reject(event);
	            };
	        });
	    };
	    return DefaultTerminalSession;
	}());
	exports.DefaultTerminalSession = DefaultTerminalSession;
	/**
	 * The static namespace for `DefaultTerminalSession`.
	 */
	var DefaultTerminalSession;
	(function (DefaultTerminalSession) {
	    /**
	     * Whether the terminal service is available.
	     */
	    function isAvailable() {
	        var available = String(utils.getConfigOption('terminalsAvailable'));
	        return available.toLowerCase() === 'true';
	    }
	    DefaultTerminalSession.isAvailable = isAvailable;
	    /**
	     * Start a new terminal session.
	     *
	     * @options - The session options to use.
	     *
	     * @returns A promise that resolves with the session instance.
	     */
	    function startNew(options) {
	        if (options === void 0) { options = {}; }
	        if (!terminal_1.TerminalSession.isAvailable()) {
	            return Private.unavailable();
	        }
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var url = Private.getBaseUrl(baseUrl);
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'POST';
	        ajaxSettings.dataType = 'json';
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            var name = success.data.name;
	            return new DefaultTerminalSession(name, options);
	        });
	    }
	    DefaultTerminalSession.startNew = startNew;
	    /*
	     * Connect to a running session.
	     *
	     * @param name - The name of the target session.
	     *
	     * @param options - The session options to use.
	     *
	     * @returns A promise that resolves with the new session instance.
	     *
	     * #### Notes
	     * If the session was already started via `startNew`, the existing
	     * session object is used as the fulfillment value.
	     *
	     * Otherwise, if `options` are given, we attempt to connect to the existing
	     * session.
	     * The promise is fulfilled when the session is ready on the server,
	     * otherwise the promise is rejected.
	     *
	     * If the session was not already started and no `options` are given,
	     * the promise is rejected.
	     */
	    function connectTo(name, options) {
	        if (options === void 0) { options = {}; }
	        if (!terminal_1.TerminalSession.isAvailable()) {
	            return Private.unavailable();
	        }
	        var baseUrl = options.baseUrl || utils.getBaseUrl();
	        var url = Private.getTermUrl(baseUrl, name);
	        if (url in Private.running) {
	            return Promise.resolve(Private.running[url]);
	        }
	        var session = new DefaultTerminalSession(name, options);
	        return Promise.resolve(session);
	    }
	    DefaultTerminalSession.connectTo = connectTo;
	    /**
	     * List the running terminal sessions.
	     *
	     * @param options - The session options to use.
	     *
	     * @returns A promise that resolves with the list of running session models.
	     */
	    function listRunning(options) {
	        if (options === void 0) { options = {}; }
	        if (!terminal_1.TerminalSession.isAvailable()) {
	            return Private.unavailable();
	        }
	        var url = Private.getBaseUrl(options.baseUrl);
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'GET';
	        ajaxSettings.dataType = 'json';
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 200) {
	                return utils.makeAjaxError(success);
	            }
	            var data = success.data;
	            if (!Array.isArray(data)) {
	                return utils.makeAjaxError(success, 'Invalid terminal data');
	            }
	            // Update the local data store.
	            var urls = iteration_1.toArray(iteration_1.map(data, function (item) {
	                return utils.urlPathJoin(url, item.name);
	            }));
	            iteration_1.each(Object.keys(Private.running), function (runningUrl) {
	                if (urls.indexOf(runningUrl) === -1) {
	                    var session = Private.running[runningUrl];
	                    session.terminated.emit(void 0);
	                    session.dispose();
	                }
	            });
	            return data;
	        });
	    }
	    DefaultTerminalSession.listRunning = listRunning;
	    /**
	     * Shut down a terminal session by name.
	     *
	     * @param name - The name of the target session.
	     *
	     * @param options - The session options to use.
	     *
	     * @returns A promise that resolves when the session is shut down.
	     */
	    function shutdown(name, options) {
	        if (options === void 0) { options = {}; }
	        if (!terminal_1.TerminalSession.isAvailable()) {
	            return Private.unavailable();
	        }
	        var url = Private.getTermUrl(options.baseUrl, name);
	        var ajaxSettings = utils.ajaxSettingsWithToken(options.ajaxSettings, options.token);
	        ajaxSettings.method = 'DELETE';
	        return utils.ajaxRequest(url, ajaxSettings).then(function (success) {
	            if (success.xhr.status !== 204) {
	                return utils.makeAjaxError(success);
	            }
	            Private.killTerminal(url);
	        }, function (err) {
	            if (err.xhr.status === 404) {
	                var response = JSON.parse(err.xhr.responseText);
	                console.warn(response['message']);
	                Private.killTerminal(url);
	                return;
	            }
	            return Promise.reject(err);
	        });
	    }
	    DefaultTerminalSession.shutdown = shutdown;
	})(DefaultTerminalSession = exports.DefaultTerminalSession || (exports.DefaultTerminalSession = {}));
	// Define the signals for the `DefaultTerminalSession` class.
	signaling_1.defineSignal(DefaultTerminalSession.prototype, 'terminated');
	signaling_1.defineSignal(DefaultTerminalSession.prototype, 'messageReceived');
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * A mapping of running terminals by url.
	     */
	    Private.running = Object.create(null);
	    /**
	     * A promise returned for when terminals are unavailable.
	     */
	    function unavailable() {
	        return Promise.reject('Terminals Unavailable');
	    }
	    Private.unavailable = unavailable;
	    /**
	     * Get the url for a terminal.
	     */
	    function getTermUrl(baseUrl, name) {
	        return utils.urlPathJoin(baseUrl, TERMINAL_SERVICE_URL, name);
	    }
	    Private.getTermUrl = getTermUrl;
	    /**
	     * Get the base url.
	     */
	    function getBaseUrl(baseUrl) {
	        return utils.urlPathJoin(baseUrl, TERMINAL_SERVICE_URL);
	    }
	    Private.getBaseUrl = getBaseUrl;
	    /**
	     * Kill a terminal by url.
	     */
	    function killTerminal(url) {
	        // Update the local data store.
	        if (Private.running[url]) {
	            var session = Private.running[url];
	            session.terminated.emit(void 0);
	            session.dispose();
	        }
	    }
	    Private.killTerminal = killTerminal;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/terminal/default.js **/


/** START DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/nbformat.js **/
jupyter.define('@jupyterlab/services@0.36.1/lib/nbformat.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	// Notebook format interfaces
	// https://nbformat.readthedocs.io/en/latest/format_description.html
	// https://github.com/jupyter/nbformat/blob/master/nbformat/v4/nbformat.v4.schema.json
	var json_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/json.js');
	/**
	 * A namespace for nbformat interfaces.
	 */
	var nbformat;
	(function (nbformat) {
	    /**
	     * The major version of the notebook format.
	     */
	    nbformat.MAJOR_VERSION = 4;
	    /**
	     * The minor version of the notebook format.
	     */
	    nbformat.MINOR_VERSION = 1;
	    /**
	     * Validate a mime type/value pair.
	     *
	     * @param type - The mimetype name.
	     *
	     * @param value - The value associated with the type.
	     *
	     * @returns Whether the type/value pair are valid.
	     */
	    function validateMimeValue(type, value) {
	        // Check if "application/json" or "application/foo+json"
	        var jsonTest = /^application\/(.*?)+\+json$/;
	        var isJSONType = type === 'application/json' || jsonTest.test(type);
	        var isString = function (x) {
	            return Object.prototype.toString.call(x) === '[object String]';
	        };
	        // If it is an array, make sure if is not a JSON type and it is an
	        // array of strings.
	        if (Array.isArray(value)) {
	            if (isJSONType) {
	                return false;
	            }
	            var valid_1 = true;
	            value.forEach(function (v) {
	                if (!isString(v)) {
	                    valid_1 = false;
	                }
	            });
	            return valid_1;
	        }
	        // If it is a string, make sure we are not a JSON type.
	        if (isString(value)) {
	            return !isJSONType;
	        }
	        // It is not a string, make sure it is a JSON type.
	        if (!isJSONType) {
	            return false;
	        }
	        // It is a JSON type, make sure it is a valid JSON object.
	        return json_1.isObject(value);
	    }
	    nbformat.validateMimeValue = validateMimeValue;
	})(nbformat = exports.nbformat || (exports.nbformat = {}));
	
})
/** END DEFINE BLOCK for @jupyterlab/services@0.36.1/lib/nbformat.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/application.js **/
jupyter.define('phosphor@0.7.0/lib/ui/application.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var commandregistry_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/commandregistry.js');
	var keymap_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/keymap.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * An abstract base class for creating pluggable applications.
	 *
	 * #### Notes
	 * The `Application` class is useful when creating large, complex
	 * UI applications with the ability to be safely extended by third
	 * party code via plugins.
	 *
	 * Use of this class is optional. Applications with low to moderate
	 * complexity will have no need for the features this class provides.
	 */
	var Application = (function () {
	    /**
	     * Construct a new application.
	     */
	    function Application() {
	        this._started = false;
	        this._shell = null;
	        this._promise = null;
	        this._pluginMap = Private.createPluginMap();
	        this._serviceMap = Private.createServiceMap();
	        this._commands = new commandregistry_1.CommandRegistry();
	        this._keymap = new keymap_1.Keymap({ commands: this._commands });
	    }
	    Object.defineProperty(Application.prototype, "shell", {
	        /**
	         * The application shell widget.
	         *
	         * #### Notes
	         * The shell widget is the root "container" widget for the entire
	         * application. It will typically expose an API which allows the
	         * application plugins to insert content in a variety of places.
	         *
	         * This is created by a subclass in the `createShell()` method.
	         *
	         * This will be `null` until the application is started.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._shell;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Application.prototype, "commands", {
	        /**
	         * The application command registry.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._commands;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Application.prototype, "keymap", {
	        /**
	         * The application keymap.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._keymap;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Test whether a plugin is registered with the application.
	     *
	     * @param id - The id of the plugin of interest.
	     *
	     * @returns `true` if the plugin is registered, `false` otherwise.
	     */
	    Application.prototype.hasPlugin = function (id) {
	        return id in this._pluginMap;
	    };
	    /**
	     * List the IDs of the plugins registered with the application.
	     *
	     * @returns A new array of the registered plugin IDs.
	     */
	    Application.prototype.listPlugins = function () {
	        return Object.keys(this._pluginMap);
	    };
	    /**
	     * Register a plugin with the application.
	     *
	     * @param plugin - The plugin to register.
	     *
	     * #### Notes
	     * An error will be thrown if a plugin with the same id is already
	     * registered, or if the plugin has a circular dependency.
	     *
	     * If the plugin provides a service which has already been provided
	     * by another plugin, the new service will override the old service.
	     */
	    Application.prototype.registerPlugin = function (plugin) {
	        // Throw an error if the plugin id is already registered.
	        if (plugin.id in this._pluginMap) {
	            throw new Error("Plugin '" + plugin.id + "' is already registered.");
	        }
	        // Create the normalized plugin data.
	        var data = Private.createPluginData(plugin);
	        // Ensure the plugin does not cause a cyclic dependency.
	        Private.ensureNoCycle(data, this._pluginMap, this._serviceMap);
	        // Add the service token to the registry.
	        if (data.provides)
	            this._serviceMap.set(data.provides, data.id);
	        // Add the plugin to the registry.
	        this._pluginMap[data.id] = data;
	    };
	    /**
	     * Register multiple plugins with the application.
	     *
	     * @param plugins - The plugins to register.
	     *
	     * #### Notes
	     * This calls `registerPlugin()` for each of the given plugins.
	     */
	    Application.prototype.registerPlugins = function (plugins) {
	        for (var _i = 0, plugins_1 = plugins; _i < plugins_1.length; _i++) {
	            var plugin = plugins_1[_i];
	            this.registerPlugin(plugin);
	        }
	    };
	    /**
	     * Activate the plugin with the given id.
	     *
	     * @param id - The ID of the plugin of interest.
	     *
	     * @returns A promise which resolves when the plugin is activated
	     *   or rejects with an error if it cannot be activated.
	     */
	    Application.prototype.activatePlugin = function (id) {
	        var _this = this;
	        // Reject the promise if the plugin is not registered.
	        var data = this._pluginMap[id];
	        if (!data) {
	            return Promise.reject(new Error("Plugin '" + id + "' is not registered."));
	        }
	        // Resolve immediately if the plugin is already activated.
	        if (data.activated) {
	            return Promise.resolve(void 0);
	        }
	        // Return the pending resolver promise if it exists.
	        if (data.promise) {
	            return data.promise;
	        }
	        // Resolve the services required by the plugin.
	        var promises = data.requires.map(function (req) { return _this.resolveService(req); });
	        // Setup the resolver promise for the plugin.
	        data.promise = Promise.all(promises).then(function (deps) {
	            return data.activate.apply(void 0, [_this].concat(deps));
	        }).then(function (service) {
	            data.service = service;
	            data.activated = true;
	            data.promise = null;
	        }).catch(function (error) {
	            data.promise = null;
	            throw error;
	        });
	        // Return the pending resolver promise.
	        return data.promise;
	    };
	    /**
	     * Resolve a service of a given type.
	     *
	     * @param token - The token for the service type of interest.
	     *
	     * @returns A promise which resolves to an instance of the requested
	     *   service, or rejects with an error if it cannot be resolved.
	     *
	     * #### Notes
	     * Services are singletons. The same instance will be returned each
	     * time a given service token is resolved.
	     *
	     * If the plugin which provides the service has not been activated,
	     * resolving the service will automatically activate the plugin.
	     *
	     * User code will not typically call this method directly. Instead,
	     * the required services for the user's plugins will be resolved
	     * automatically when the plugin is activated.
	     */
	    Application.prototype.resolveService = function (token) {
	        // Reject the promise if there is no provider for the type.
	        var id = this._serviceMap.get(token);
	        if (!id) {
	            return Promise.reject(new Error("No provider for: " + token.name + "."));
	        }
	        // Resolve immediately if the plugin is already activated.
	        var data = this._pluginMap[id];
	        if (data.activated) {
	            return Promise.resolve(data.service);
	        }
	        // Otherwise, activate the plugin and wait on the results.
	        return this.activatePlugin(id).then(function () { return data.service; });
	    };
	    /**
	     * Start the application.
	     *
	     * @param options - The options for starting the application.
	     *
	     * @returns A promise which resolves when all bootstrapping work
	     *   is complete and the shell is mounted to the DOM, or rejects
	     *   with an error if the bootstrapping process fails.
	     *
	     * #### Notes
	     * This should be called once by the application creator after all
	     * initial plugins have been registered.
	     *
	     * Bootstrapping the application consists of the following steps:
	     * 1. Create the shell widget
	     * 2. Activate the startup plugins
	     * 3. Wait for those plugins to activate
	     * 4. Attach the shell widget to the DOM
	     * 5. Add the application event listeners
	     */
	    Application.prototype.start = function (options) {
	        var _this = this;
	        if (options === void 0) { options = {}; }
	        // Resolve immediately if the application is already started.
	        if (this._started) {
	            return Promise.resolve(void 0);
	        }
	        // Return the pending promise if it exists.
	        if (this._promise) {
	            return this._promise;
	        }
	        // Create the shell widget.
	        this._shell = this.createShell();
	        // Parse the host id for attaching the shell.
	        var hostID = options.hostID || '';
	        // Collect the ids of the startup plugins.
	        var startups = Private.collectStartupPlugins(this._pluginMap, options);
	        // Generate the activation promises.
	        var promises = startups.map(function (id) { return _this.activatePlugin(id); });
	        // Wait for the plugins to activate, then finalize startup.
	        this._promise = Promise.all(promises).then(function () {
	            _this._started = true;
	            _this._promise = null;
	            _this.attachShell(hostID);
	            _this.addEventListeners();
	        }).catch(function (error) {
	            _this._promise = null;
	            throw error;
	        });
	        // Return the pending bootstrapping promise.
	        return this._promise;
	    };
	    /**
	     * Handle the DOM events for the application.
	     *
	     * @param event - The DOM event sent to the application.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events registered for the application. It
	     * should not be called directly by user code.
	     */
	    Application.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'resize':
	                this.evtResize(event);
	                break;
	            case 'keydown':
	                this.evtKeydown(event);
	                break;
	        }
	    };
	    /**
	     * Attach the application shell to the DOM.
	     *
	     * @param id - The id of the host node for the shell, or `''`.
	     *
	     * #### Notes
	     * If the id is not provided, the document body will be the host.
	     *
	     * A subclass may reimplement this method as needed.
	     */
	    Application.prototype.attachShell = function (id) {
	        widget_1.Widget.attach(this.shell, document.getElementById(id) || document.body);
	    };
	    /**
	     * Add the application event listeners.
	     *
	     * #### Notes
	     * The default implementation of this method adds listeners for
	     * `'keydown'` and `'resize'` events.
	     *
	     * A subclass may reimplement this method as needed.
	     */
	    Application.prototype.addEventListeners = function () {
	        document.addEventListener('keydown', this);
	        window.addEventListener('resize', this);
	    };
	    /**
	     * A method invoked on a document `'keydown'` event.
	     *
	     * #### Notes
	     * The default implementation of this method invokes the key down
	     * processing method of the application keymap.
	     *
	     * A subclass may reimplement this method as needed.
	     */
	    Application.prototype.evtKeydown = function (event) {
	        this.keymap.processKeydownEvent(event);
	    };
	    /**
	     * A method invoked on a window `'resize'` event.
	     *
	     * #### Notes
	     * The default implementation of this method updates the shell.
	     *
	     * A subclass may reimplement this method as needed.
	     */
	    Application.prototype.evtResize = function (event) {
	        this.shell.update();
	    };
	    return Application;
	}());
	exports.Application = Application;
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create a new plugin map.
	     */
	    function createPluginMap() {
	        return Object.create(null);
	    }
	    Private.createPluginMap = createPluginMap;
	    /**
	     * Create a new service map.
	     */
	    function createServiceMap() {
	        return new Map();
	    }
	    Private.createServiceMap = createServiceMap;
	    /**
	     * Create a normalized plugin data object for the given plugin.
	     */
	    function createPluginData(plugin) {
	        return {
	            id: plugin.id,
	            service: null,
	            promise: null,
	            activated: false,
	            activate: plugin.activate,
	            provides: plugin.provides || null,
	            autoStart: plugin.autoStart || false,
	            requires: plugin.requires ? plugin.requires.slice() : [],
	        };
	    }
	    Private.createPluginData = createPluginData;
	    /**
	     * Ensure no cycle is present in the plugin resolution graph.
	     *
	     * If a cycle is detected, an error will be thrown.
	     */
	    function ensureNoCycle(data, pluginMap, serviceMap) {
	        // Bail early if there cannot be a cycle.
	        if (!data.provides || data.requires.length === 0) {
	            return;
	        }
	        // Setup a stack to trace service resolution.
	        var trace = [data.id];
	        // Throw an exception if a cycle is present.
	        if (data.requires.some(visit)) {
	            throw new Error("Cycle detected: " + trace.join(' -> ') + ".");
	        }
	        function visit(token) {
	            if (token === data.provides) {
	                return true;
	            }
	            var id = serviceMap.get(token);
	            if (!id) {
	                return false;
	            }
	            var other = pluginMap[id];
	            if (other.requires.length === 0) {
	                return false;
	            }
	            trace.push(id);
	            if (other.requires.some(visit)) {
	                return true;
	            }
	            trace.pop();
	            return false;
	        }
	    }
	    Private.ensureNoCycle = ensureNoCycle;
	    /**
	     * Collect the IDs of the plugins to activate on startup.
	     */
	    function collectStartupPlugins(pluginMap, options) {
	        // Create a map to hold the plugin IDs.
	        var resultMap = Object.create(null);
	        // Collect the auto-start plugins.
	        for (var id in pluginMap) {
	            if (pluginMap[id].autoStart) {
	                resultMap[id] = true;
	            }
	        }
	        // Add the startup plugins.
	        if (options.startPlugins) {
	            for (var _i = 0, _a = options.startPlugins; _i < _a.length; _i++) {
	                var id = _a[_i];
	                resultMap[id] = true;
	            }
	        }
	        // Remove the ignored plugins.
	        if (options.ignorePlugins) {
	            for (var _b = 0, _c = options.ignorePlugins; _b < _c.length; _b++) {
	                var id = _c[_b];
	                delete resultMap[id];
	            }
	        }
	        // Return the final startup plugins.
	        return Object.keys(resultMap);
	    }
	    Private.collectStartupPlugins = collectStartupPlugins;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/application.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/commandregistry.js **/
jupyter.define('phosphor@0.7.0/lib/ui/commandregistry.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var disposable_1 = __jupyter_require__('phosphor@0.7.0/lib/core/disposable.js');
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	/**
	 * A registry which holds user-defined commands.
	 */
	var CommandRegistry = (function () {
	    /**
	     * Construct a new command registry.
	     */
	    function CommandRegistry() {
	        this._commands = Object.create(null);
	    }
	    /**
	     * List the ids of the registered commands.
	     *
	     * @returns A new array of the registered command ids.
	     */
	    CommandRegistry.prototype.listCommands = function () {
	        return Object.keys(this._commands);
	    };
	    /**
	     * Test whether a specific command is registered.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @returns `true` if the command is registered, `false` otherwise.
	     */
	    CommandRegistry.prototype.hasCommand = function (id) {
	        return id in this._commands;
	    };
	    /**
	     * Add a command to the registry.
	     *
	     * @param id - The unique id of the command.
	     *
	     * @param options - The options for the command.
	     *
	     * @returns A disposable which will unregister the command.
	     *
	     * @throws An error if the given `id` is already registered.
	     */
	    CommandRegistry.prototype.addCommand = function (id, options) {
	        var _this = this;
	        // Throw an error if the id is already registered.
	        if (id in this._commands) {
	            throw new Error("Command '" + id + "' already registered.");
	        }
	        // Create the command and add it to the registry.
	        this._commands[id] = Private.createCommand(options);
	        // Emit the `commandChanged` signal.
	        this.commandChanged.emit({ id: id, type: 'added' });
	        // Return a disposable which will remove the command.
	        return new disposable_1.DisposableDelegate(function () {
	            // Remove the command from the registry.
	            delete _this._commands[id];
	            // Emit the `commandChanged` signal.
	            _this.commandChanged.emit({ id: id, type: 'removed' });
	        });
	    };
	    /**
	     * Notify listeners that the state of a command has changed.
	     *
	     * @param id - The id of the command which has changed.
	     *
	     * #### Notes
	     * This method should be called by the command author whenever the
	     * application state changes such that the results of the command
	     * metadata functions may have changed.
	     *
	     * This will cause the `commandChanged` signal to be emitted.
	     *
	     * If the command is not registered, this is a no-op.
	     */
	    CommandRegistry.prototype.notifyCommandChanged = function (id) {
	        if (id in this._commands) {
	            this.commandChanged.emit({ id: id, type: 'changed' });
	        }
	    };
	    /**
	     * Get the display label for a specific command.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns The display label for the command.
	     *
	     * #### Notes
	     * Returns an empty string if the command is not registered.
	     */
	    CommandRegistry.prototype.label = function (id, args) {
	        var cmd = this._commands[id];
	        return cmd ? cmd.label.call(void 0, args) : '';
	    };
	    /**
	     * Get the mnemonic index for a specific command.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns The mnemonic index for the command.
	     *
	     * #### Notes
	     * Returns `-1` if the command is not registered.
	     */
	    CommandRegistry.prototype.mnemonic = function (id, args) {
	        var cmd = this._commands[id];
	        return cmd ? cmd.mnemonic.call(void 0, args) : -1;
	    };
	    /**
	     * Get the icon class for a specific command.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns The icon class for the command.
	     *
	     * #### Notes
	     * Returns an empty string if the command is not registered.
	     */
	    CommandRegistry.prototype.icon = function (id, args) {
	        var cmd = this._commands[id];
	        return cmd ? cmd.icon.call(void 0, args) : '';
	    };
	    /**
	     * Get the short form caption for a specific command.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns The caption for the command.
	     *
	     * #### Notes
	     * Returns an empty string if the command is not registered.
	     */
	    CommandRegistry.prototype.caption = function (id, args) {
	        var cmd = this._commands[id];
	        return cmd ? cmd.caption.call(void 0, args) : '';
	    };
	    /**
	     * Get the usage help text for a specific command.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns The usage text for the command.
	     *
	     * #### Notes
	     * Returns an empty string if the command is not registered.
	     */
	    CommandRegistry.prototype.usage = function (id, args) {
	        var cmd = this._commands[id];
	        return cmd ? cmd.usage.call(void 0, args) : '';
	    };
	    /**
	     * Get the extra class name for a specific command.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns The class name for the command.
	     *
	     * #### Notes
	     * Returns an empty string if the command is not registered.
	     */
	    CommandRegistry.prototype.className = function (id, args) {
	        var cmd = this._commands[id];
	        return cmd ? cmd.className.call(void 0, args) : '';
	    };
	    /**
	     * Test whether a specific command is enabled.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns `true` if the command is enabled, `false` otherwise.
	     *
	     * #### Notes
	     * Returns `false` if the command is not registered.
	     */
	    CommandRegistry.prototype.isEnabled = function (id, args) {
	        var cmd = this._commands[id];
	        return cmd ? cmd.isEnabled.call(void 0, args) : false;
	    };
	    /**
	     * Test whether a specific command is toggled.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns `true` if the command is toggled, `false` otherwise.
	     *
	     * #### Notes
	     * Returns `false` if the command is not registered.
	     */
	    CommandRegistry.prototype.isToggled = function (id, args) {
	        var cmd = this._commands[id];
	        return cmd ? cmd.isToggled.call(void 0, args) : false;
	    };
	    /**
	     * Test whether a specific command is visible.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns `true` if the command is visible, `false` otherwise.
	     *
	     * #### Notes
	     * Returns `false` if the command is not registered.
	     */
	    CommandRegistry.prototype.isVisible = function (id, args) {
	        var cmd = this._commands[id];
	        return cmd ? cmd.isVisible.call(void 0, args) : false;
	    };
	    /**
	     * Execute a specific command.
	     *
	     * @param id - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns A promise which resolves to the result of the command.
	     *
	     * #### Notes
	     * The promise will reject if the command is not registered.
	     */
	    CommandRegistry.prototype.execute = function (id, args) {
	        // Reject if the command is not registered.
	        var cmd = this._commands[id];
	        if (!cmd) {
	            return Promise.reject(new Error("Command '" + id + "' not registered."));
	        }
	        // Execute the command and reject if an exception is thrown.
	        var result;
	        try {
	            result = cmd.execute.call(void 0, args);
	        }
	        catch (err) {
	            result = Promise.reject(err);
	        }
	        // Create the return promise which resolves the result.
	        var promise = Promise.resolve(result);
	        // Emit the command executed signal.
	        this.commandExecuted.emit({ id: id, args: args });
	        // Return the result promise to the caller.
	        return promise;
	    };
	    return CommandRegistry;
	}());
	exports.CommandRegistry = CommandRegistry;
	// Define the signals for the `CommandRegistry` class.
	signaling_1.defineSignal(CommandRegistry.prototype, 'commandChanged');
	signaling_1.defineSignal(CommandRegistry.prototype, 'commandExecuted');
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create a normalized command object from options.
	     */
	    function createCommand(options) {
	        return {
	            execute: options.execute,
	            label: asStringFunc(options.label),
	            mnemonic: asNumberFunc(options.mnemonic),
	            icon: asStringFunc(options.icon),
	            caption: asStringFunc(options.caption),
	            usage: asStringFunc(options.usage),
	            className: asStringFunc(options.className),
	            isEnabled: options.isEnabled || trueFunc,
	            isToggled: options.isToggled || falseFunc,
	            isVisible: options.isVisible || trueFunc
	        };
	    }
	    Private.createCommand = createCommand;
	    /**
	     * A singleton empty string function.
	     */
	    var emptyStringFunc = function (args) { return ''; };
	    /**
	     * A singleton `-1` number function
	     */
	    var negativeOneFunc = function (args) { return -1; };
	    /**
	     * A singleton true boolean function.
	     */
	    var trueFunc = function (args) { return true; };
	    /**
	     * A singleton false boolean function.
	     */
	    var falseFunc = function (args) { return false; };
	    /**
	     * Coerce a value to a string function.
	     */
	    function asStringFunc(value) {
	        if (value === void 0) {
	            return emptyStringFunc;
	        }
	        if (typeof value === 'function') {
	            return value;
	        }
	        return function (args) { return value; };
	    }
	    /**
	     * Coerce a value to a number function.
	     */
	    function asNumberFunc(value) {
	        if (value === void 0) {
	            return negativeOneFunc;
	        }
	        if (typeof value === 'function') {
	            return value;
	        }
	        return function (args) { return value; };
	    }
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/commandregistry.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/keymap.js **/
jupyter.define('phosphor@0.7.0/lib/ui/keymap.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var json_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/json.js');
	var searching_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var disposable_1 = __jupyter_require__('phosphor@0.7.0/lib/core/disposable.js');
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	var platform_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/platform.js');
	var selector_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/selector.js');
	var keyboard_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/keyboard.js');
	/**
	 * The timeout in ms for triggering a chord.
	 */
	var CHORD_TIMEOUT = 1000;
	/**
	 * A class which manages a collection of key bindings.
	 */
	var Keymap = (function () {
	    /**
	     * Construct a new keymap.
	     *
	     * @param options - The options for initializing the keymap.
	     */
	    function Keymap(options) {
	        this._timerID = 0;
	        this._replaying = false;
	        this._keys = [];
	        this._events = [];
	        this._exact = null;
	        this._bindings = new vector_1.Vector();
	        this._commands = options.commands;
	        this._layout = options.layout || keyboard_1.EN_US;
	    }
	    Object.defineProperty(Keymap.prototype, "commands", {
	        /**
	         * The command registry used by the keymap.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._commands;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Keymap.prototype, "layout", {
	        /**
	         * Get the keyboard layout used by the keymap.
	         *
	         * #### Notes
	         * The default is a US English layout.
	         */
	        get: function () {
	            return this._layout;
	        },
	        /**
	         * Set the keyboard layout used by the keymap.
	         *
	         * #### Notes
	         * A keymap requires a keyboard layout, so setting this value to
	         * `null` will revert the layout to the default US English layout.
	         */
	        set: function (value) {
	            var oldValue = this._layout;
	            var newValue = value || keyboard_1.EN_US;
	            if (oldValue === newValue) {
	                return;
	            }
	            this._layout = newValue;
	            this.layoutChanged.emit({ oldValue: oldValue, newValue: newValue });
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Keymap.prototype, "bindings", {
	        /**
	         * A read-only sequence of the key bindings in the keymap.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._bindings;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Find a key binding which matches the given command and args.
	     *
	     * @param command - The id of the command of interest.
	     *
	     * @param args - The arguments for the command.
	     *
	     * @returns The most recently added key binding which matches the
	     *   specified command and args, or `null` if no match is found.
	     *
	     * #### Notes
	     * This is a convenience method which searches through the public
	     * sequence of key `bindings`. If custom search behavior is needed,
	     * user code may search that sequence manually.
	     */
	    Keymap.prototype.findBinding = function (command, args) {
	        var i = searching_1.findLastIndex(this._bindings, function (kb) {
	            return kb.command === command && json_1.deepEqual(kb.args, args);
	        });
	        return i !== -1 ? this._bindings.at(i) : null;
	    };
	    /**
	     * Add a key binding to the keymap.
	     *
	     * @param options - The options for creating the key binding.
	     *
	     * @returns A disposable which removes the added key binding.
	     *
	     * #### Notes
	     * If multiple key bindings are registered for the same sequence, the
	     * binding with the highest selector specificity is executed first. A
	     * tie is broken by using the most recently added key binding.
	     *
	     * Ambiguous key bindings are resolved with a timeout. As an example,
	     * suppose two key bindings are registered: one with the key sequence
	     * `['Ctrl D']`, and another with `['Ctrl D', 'Ctrl W']`. If the user
	     * presses `Ctrl D`, the first binding cannot be immediately executed
	     * since the user may intend to complete the chord with `Ctrl W`. For
	     * such cases, a timer is used to allow the chord to be completed. If
	     * the chord is not completed before the timeout, the first binding
	     * is executed.
	     */
	    Keymap.prototype.addBinding = function (options) {
	        var _this = this;
	        // Create the binding for the given options.
	        var binding = Private.createBinding(options);
	        // Add the key binding to the internal vector.
	        this._bindings.pushBack(binding);
	        // Emit the `bindingChanged` signal.
	        this.bindingChanged.emit({ binding: binding, type: 'added' });
	        // Return a disposable which will remove the binding.
	        return new disposable_1.DisposableDelegate(function () {
	            // Remove the binding from the vector.
	            _this._bindings.remove(binding);
	            // Emit the `bindingChanged` signal.
	            _this.bindingChanged.emit({ binding: binding, type: 'removed' });
	        });
	    };
	    /**
	     * Process a `'keydown'` event and invoke a matching key binding.
	     *
	     * @param event - The event object for a `'keydown'` event.
	     *
	     * #### Notes
	     * This should be called in response to a `'keydown'` event in order
	     * to invoke the command for the best matching key binding.
	     *
	     * The keymap **does not** install its own key event listeners. This
	     * allows the application full control over the nodes for which the
	     * keymap processes `'keydown'` events.
	     */
	    Keymap.prototype.processKeydownEvent = function (event) {
	        // Bail immediately if playing back keystrokes.
	        if (this._replaying) {
	            return;
	        }
	        // Get the normalized keystroke for the event.
	        var keystroke = Keymap.keystrokeForKeydownEvent(event, this._layout);
	        // If the keystroke is not valid for the keyboard layout, replay
	        // any suppressed events and clear the pending state.
	        if (!keystroke) {
	            this._replayEvents();
	            this._clearPendingState();
	            return;
	        }
	        // Add the keystroke to the current key sequence.
	        this._keys.push(keystroke);
	        // Find the exact and partial matches for the key sequence.
	        var _a = Private.match(this._bindings, this._keys, event), exact = _a.exact, partial = _a.partial;
	        // If there is no exact match and no partial match, replay
	        // any suppressed events and clear the pending state.
	        if (!exact && !partial) {
	            this._replayEvents();
	            this._clearPendingState();
	            return;
	        }
	        // Stop propagation of the event. If there is only a partial match,
	        // the event will be replayed if a final exact match never occurs.
	        event.preventDefault();
	        event.stopPropagation();
	        // If there is an exact match but no partial match, the exact match
	        // can be dispatched immediately. The pending state is cleared so
	        // the next key press starts from the default state.
	        if (!partial) {
	            this._execute(exact);
	            this._clearPendingState();
	            return;
	        }
	        // If there is both an exact match and a partial match, the exact
	        // match is stored for future dispatch in case the timer expires
	        // before a more specific match is triggered.
	        if (exact)
	            this._exact = exact;
	        // Store the event for possible playback in the future.
	        this._events.push(event);
	        // (Re)start the timer to dispatch the most recent exact match
	        // in case the partial match fails to result in an exact match.
	        this._startTimer();
	    };
	    /**
	     * Start or restart the pending timeout.
	     */
	    Keymap.prototype._startTimer = function () {
	        var _this = this;
	        this._clearTimer();
	        this._timerID = setTimeout(function () {
	            _this._onPendingTimeout();
	        }, CHORD_TIMEOUT);
	    };
	    /**
	     * Clear the pending timeout.
	     */
	    Keymap.prototype._clearTimer = function () {
	        if (this._timerID !== 0) {
	            clearTimeout(this._timerID);
	            this._timerID = 0;
	        }
	    };
	    /**
	     * Clear the internal pending state.
	     */
	    Keymap.prototype._clearPendingState = function () {
	        this._clearTimer();
	        this._exact = null;
	        this._keys.length = 0;
	        this._events.length = 0;
	    };
	    /**
	     * Replay the events which were suppressed.
	     */
	    Keymap.prototype._replayEvents = function () {
	        if (this._events.length === 0) {
	            return;
	        }
	        this._replaying = true;
	        this._events.forEach(Private.replayEvent);
	        this._replaying = false;
	    };
	    /**
	     * Execute the command for the given key binding.
	     *
	     * If the command is disabled, a message will be logged.
	     */
	    Keymap.prototype._execute = function (binding) {
	        var command = binding.command, args = binding.args;
	        if (this._commands.isEnabled(command, args)) {
	            this._commands.execute(command, args);
	        }
	        else {
	            // TODO - right way to handle disabled command?
	            var formatted = binding.keys.map(Keymap.formatKeystroke).join(' ');
	            console.log("Command '" + command + "' is disabled (" + formatted + ").");
	        }
	    };
	    /**
	     * Handle the partial match timeout.
	     */
	    Keymap.prototype._onPendingTimeout = function () {
	        this._timerID = 0;
	        if (this._exact) {
	            this._execute(this._exact);
	        }
	        else {
	            this._replayEvents();
	        }
	        this._clearPendingState();
	    };
	    return Keymap;
	}());
	exports.Keymap = Keymap;
	// Define the signals for the `Keymap` class.
	signaling_1.defineSignal(Keymap.prototype, 'bindingChanged');
	signaling_1.defineSignal(Keymap.prototype, 'layoutChanged');
	/**
	 * The namespace for the `Keymap` class statics.
	 */
	var Keymap;
	(function (Keymap) {
	    /**
	     * Parse a keystroke into its constituent components.
	     *
	     * @param keystroke - The keystroke of interest.
	     *
	     * @returns The parsed components of the keystroke.
	     *
	     * #### Notes
	     * The keystroke should be of the form:
	     *   `[<modifier 1> [<modifier 2> [<modifier N> ]]]<primary key>`
	     *
	     * The supported modifiers are: `Accel`, `Alt`, `Cmd`, `Ctrl`, and
	     * `Shift`. The `Accel` modifier is translated to `Cmd` on Mac and
	     * `Ctrl` on all other platforms.
	     *
	     * The parsing is tolerant and will not throw exceptions. Notably:
	     *   - Duplicate modifiers are ignored.
	     *   - Extra primary keys are ignored.
	     *   - The order of modifiers and primary key is irrelevant.
	     *   - The keystroke parts should be separated by whitespace.
	     *   - The keystroke is case sensitive.
	     */
	    function parseKeystroke(keystroke) {
	        var key = '';
	        var alt = false;
	        var cmd = false;
	        var ctrl = false;
	        var shift = false;
	        for (var _i = 0, _a = keystroke.split(/\s+/); _i < _a.length; _i++) {
	            var token = _a[_i];
	            if (token === 'Accel') {
	                if (platform_1.IS_MAC) {
	                    cmd = true;
	                }
	                else {
	                    ctrl = true;
	                }
	            }
	            else if (token === 'Alt') {
	                alt = true;
	            }
	            else if (token === 'Cmd') {
	                cmd = true;
	            }
	            else if (token === 'Ctrl') {
	                ctrl = true;
	            }
	            else if (token === 'Shift') {
	                shift = true;
	            }
	            else if (token.length > 0) {
	                key = token;
	            }
	        }
	        return { cmd: cmd, ctrl: ctrl, alt: alt, shift: shift, key: key };
	    }
	    Keymap.parseKeystroke = parseKeystroke;
	    /**
	     * Normalize a keystroke into a canonical representation.
	     *
	     * @param keystroke - The keystroke of interest.
	     *
	     * @returns The normalized representation of the keystroke.
	     *
	     * #### Notes
	     * This normalizes the keystroke by removing duplicate modifiers and
	     * extra primary keys, and assembling the parts in a canonical order.
	     *
	     * The `Cmd` modifier is ignored on non-Mac platforms.
	     */
	    function normalizeKeystroke(keystroke) {
	        var mods = '';
	        var parts = parseKeystroke(keystroke);
	        if (parts.ctrl) {
	            mods += 'Ctrl ';
	        }
	        if (parts.alt) {
	            mods += 'Alt ';
	        }
	        if (parts.shift) {
	            mods += 'Shift ';
	        }
	        if (parts.cmd && platform_1.IS_MAC) {
	            mods += 'Cmd ';
	        }
	        return mods + parts.key;
	    }
	    Keymap.normalizeKeystroke = normalizeKeystroke;
	    /**
	     * Format a keystroke for display on the local system.
	     *
	     * @param keystroke - The keystroke of interest.
	     *
	     * @returns The keystroke formatted for display on the local system.
	     *
	     * #### Notes
	     * On Mac, this replaces the modifiers with the Mac-specific unicode
	     * characters. On other systems, this joins the modifiers with `+`.
	     */
	    function formatKeystroke(keystroke) {
	        var mods = '';
	        var parts = parseKeystroke(keystroke);
	        if (platform_1.IS_MAC) {
	            if (parts.ctrl) {
	                mods += '\u2303';
	            }
	            if (parts.alt) {
	                mods += '\u2325';
	            }
	            if (parts.shift) {
	                mods += '\u21E7';
	            }
	            if (parts.cmd) {
	                mods += '\u2318';
	            }
	        }
	        else {
	            if (parts.ctrl) {
	                mods += 'Ctrl+';
	            }
	            if (parts.alt) {
	                mods += 'Alt+';
	            }
	            if (parts.shift) {
	                mods += 'Shift+';
	            }
	        }
	        return mods + parts.key;
	    }
	    Keymap.formatKeystroke = formatKeystroke;
	    /**
	     * Create a normalized keystroke for a `'keydown'` event.
	     *
	     * @param event - The event object for a `'keydown'` event.
	     *
	     * @param layout - The keyboard layout for looking up the primary key.
	     *
	     * @returns A normalized keystroke, or an empty string if the event
	     *   does not represent a valid keystroke for the given layout.
	     */
	    function keystrokeForKeydownEvent(event, layout) {
	        var key = layout.keyForKeydownEvent(event);
	        if (!key) {
	            return '';
	        }
	        var mods = '';
	        if (event.ctrlKey) {
	            mods += 'Ctrl ';
	        }
	        if (event.altKey) {
	            mods += 'Alt ';
	        }
	        if (event.shiftKey) {
	            mods += 'Shift ';
	        }
	        if (event.metaKey && platform_1.IS_MAC) {
	            mods += 'Cmd ';
	        }
	        return mods + key;
	    }
	    Keymap.keystrokeForKeydownEvent = keystrokeForKeydownEvent;
	})(Keymap = exports.Keymap || (exports.Keymap = {}));
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create a binding object from binding options.
	     */
	    function createBinding(options) {
	        return new KeyBinding(options);
	    }
	    Private.createBinding = createBinding;
	    /**
	     * Find the bindings which match a key sequence.
	     *
	     * This returns a match result which contains the best exact matching
	     * binding, and a flag which indicates if there are partial matches.
	     */
	    function match(bindings, keys, event) {
	        // Whether a partial match has been found.
	        var partial = false;
	        // The current best exact match.
	        var exact = null;
	        // The match distance for the exact match.
	        var distance = Infinity;
	        // The specificity for the exact match.
	        var specificity = 0;
	        // Iterate over the bindings and search for the best match.
	        for (var i = 0, n = bindings.length; i < n; ++i) {
	            // Lookup the current binding.
	            var binding = bindings.at(i);
	            // Check whether the key binding sequence is a match.
	            var sqm = matchSequence(binding.keys, keys);
	            // If there is no match, the binding is ignored.
	            if (sqm === 0 /* None */) {
	                continue;
	            }
	            // If it is a partial match and no other partial match has been
	            // found, ensure the selector matches and set the partial flag.
	            if (sqm === 2 /* Partial */) {
	                if (!partial && targetDistance(binding.selector, event) !== -1) {
	                    partial = true;
	                }
	                continue;
	            }
	            // Ignore the match if the selector doesn't match, or if the
	            // matched node is farther away than the current best match.
	            var td = targetDistance(binding.selector, event);
	            if (td === -1 || td > distance) {
	                continue;
	            }
	            // Get the specificity for the selector.
	            var sp = selector_1.calculateSpecificity(binding.selector);
	            // Update the best match if this match is stronger.
	            if (exact === null || td < distance || sp >= specificity) {
	                exact = binding;
	                distance = td;
	                specificity = sp;
	            }
	        }
	        // Return the match result.
	        return { exact: exact, partial: partial };
	    }
	    Private.match = match;
	    /**
	     * Replay a keyboard event.
	     *
	     * This synthetically dispatches a clone of the keyboard event.
	     */
	    function replayEvent(event) {
	        event.target.dispatchEvent(cloneKeyboardEvent(event));
	    }
	    Private.replayEvent = replayEvent;
	    /**
	     * A concrete implementation of `Keymap.IBinding`.
	     */
	    var KeyBinding = (function () {
	        /**
	         * Construct a new binding.
	         */
	        function KeyBinding(options) {
	            this._keys = normalizeKeys(options);
	            this._selector = normalizeSelector(options);
	            this._command = options.command;
	            this._args = options.args || null;
	        }
	        Object.defineProperty(KeyBinding.prototype, "keys", {
	            /**
	             * The key sequence for the key binding.
	             */
	            get: function () {
	                return this._keys;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(KeyBinding.prototype, "selector", {
	            /**
	             * The CSS selector for the key binding.
	             */
	            get: function () {
	                return this._selector;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(KeyBinding.prototype, "command", {
	            /**
	             * The command to execute when the key binding is matched.
	             */
	            get: function () {
	                return this._command;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(KeyBinding.prototype, "args", {
	            /**
	             * The arguments for the command.
	             */
	            get: function () {
	                return this._args;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        return KeyBinding;
	    }());
	    /**
	     * Get the platform-specific normalized keys for an options object.
	     *
	     * The normalized keys are frozen to prevent further modification.
	     */
	    function normalizeKeys(options) {
	        var keys;
	        if (platform_1.IS_WIN) {
	            keys = options.winKeys || options.keys;
	        }
	        else if (platform_1.IS_MAC) {
	            keys = options.macKeys || options.keys;
	        }
	        else {
	            keys = options.linuxKeys || options.keys;
	        }
	        return Object.freeze(keys.map(Keymap.normalizeKeystroke));
	    }
	    /**
	     * Normalize the selector for an options object.
	     *
	     * This returns the validated first clause of the selector.
	     */
	    function normalizeSelector(options) {
	        return selector_1.validateSelector(options.selector.split(',', 1)[0]);
	    }
	    ;
	    /**
	     * Test whether a binding sequence matches a key sequence.
	     *
	     * Returns a `SequenceMatch` value indicating the type of match.
	     */
	    function matchSequence(bindKeys, userKeys) {
	        if (bindKeys.length < userKeys.length) {
	            return 0 /* None */;
	        }
	        for (var i = 0, n = userKeys.length; i < n; ++i) {
	            if (bindKeys[i] !== userKeys[i]) {
	                return 0 /* None */;
	            }
	        }
	        if (bindKeys.length > userKeys.length) {
	            return 2 /* Partial */;
	        }
	        return 1 /* Exact */;
	    }
	    /**
	     * Find the distance from the target node to the first matching node.
	     *
	     * This traverses the event path from `target` to `currentTarget` and
	     * computes the distance from `target` to the first node which matches
	     * the CSS selector. If no match is found, `-1` is returned.
	     */
	    function targetDistance(selector, event) {
	        var distance = 0;
	        var target = event.target;
	        var current = event.currentTarget;
	        for (; target !== null; target = target.parentElement, ++distance) {
	            if (selector_1.matchesSelector(target, selector)) {
	                return distance;
	            }
	            if (target === current) {
	                return -1;
	            }
	        }
	        return -1;
	    }
	    /**
	     * Clone a keyboard event.
	     */
	    function cloneKeyboardEvent(event) {
	        // A custom event is required because Chrome nulls out the
	        // `keyCode` field in user-generated `KeyboardEvent` types.
	        var clone = document.createEvent('Event');
	        var bubbles = event.bubbles || true;
	        var cancelable = event.cancelable || true;
	        clone.initEvent(event.type || 'keydown', bubbles, cancelable);
	        clone.key = event.key || '';
	        clone.keyCode = event.keyCode || 0;
	        clone.which = event.keyCode || 0;
	        clone.ctrlKey = event.ctrlKey || false;
	        clone.altKey = event.altKey || false;
	        clone.shiftKey = event.shiftKey || false;
	        clone.metaKey = event.metaKey || false;
	        clone.view = event.view || window;
	        return clone;
	    }
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/keymap.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/dom/platform.js **/
jupyter.define('phosphor@0.7.0/lib/dom/platform.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * A boolean indicating whether the platform is Mac.
	 */
	exports.IS_MAC = !!navigator.platform.match(/Mac/i);
	/**
	 * A boolean indicating whether the platform is Windows.
	 */
	exports.IS_WIN = !!navigator.platform.match(/Win/i);
	/**
	 * A flag indicating whether the browser is IE.
	 */
	exports.IS_IE = /Trident/.test(navigator.userAgent);
	/**
	 * A flag indicating whether the browser is Edge.
	 */
	exports.IS_EDGE = /Edge/.test(navigator.userAgent);
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/dom/platform.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/dom/selector.js **/
jupyter.define('phosphor@0.7.0/lib/dom/selector.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * Calculate the specificity of a single CSS selector.
	 *
	 * @param selector - The CSS selector of interest.
	 *
	 * @returns The specificity of the selector.
	 *
	 * #### Undefined Behavior
	 * The selector is invalid.
	 *
	 * #### Notes
	 * This is based on https://www.w3.org/TR/css3-selectors/#specificity
	 *
	 * A larger number represents a more specific selector.
	 *
	 * The smallest possible specificity is `0`.
	 *
	 * The result is represented as a hex number `0x<aa><bb><cc>` where
	 * each component is the count of the respective selector clause.
	 *
	 * If the selector contains commas, only the first clause is used.
	 *
	 * The computed result is cached, so subsequent calculations for the
	 * same selector are extremely fast.
	 */
	function calculateSpecificity(selector) {
	    var result = Private.specificityCache[selector];
	    if (result === void 0) {
	        result = Private.calculateSingle(selector);
	        Private.specificityCache[selector] = result;
	    }
	    return result;
	}
	exports.calculateSpecificity = calculateSpecificity;
	/**
	 * Test whether a selector is a valid CSS selector.
	 *
	 * @param selector - The CSS selector of interest.
	 *
	 * @returns `true` if the selector is valid, `false` otherwise.
	 *
	 * #### Notes
	 * The computed result is cached, so subsequent tests for the same
	 * selector are extremely fast.
	 */
	function isValidSelector(selector) {
	    var result = Private.validityCache[selector];
	    if (result === void 0) {
	        try {
	            Private.testElem.querySelector(selector);
	            result = true;
	        }
	        catch (err) {
	            result = false;
	        }
	        Private.validityCache[selector] = result;
	    }
	    return result;
	}
	exports.isValidSelector = isValidSelector;
	/**
	 * Validate a CSS selector.
	 *
	 * @param selector - The CSS selector of interest.
	 *
	 * @returns The provided selector.
	 *
	 * @throws An error if the selector is invalid.
	 */
	function validateSelector(selector) {
	    if (!isValidSelector(selector)) {
	        throw new Error("Invalid selector: " + selector);
	    }
	    return selector;
	}
	exports.validateSelector = validateSelector;
	/**
	 * Test whether an element matches a CSS selector.
	 *
	 * @param elem - The element of interest.
	 *
	 * @param selector - The valid CSS selector of interest.
	 *
	 * @returns `true` if the element is a match, `false` otherwise.
	 *
	 * #### Notes
	 * This function uses the builtin browser capabilities when possible,
	 * falling back onto a document query otherwise.
	 */
	function matchesSelector(elem, selector) {
	    return Private.protoMatchFunc.call(elem, selector);
	}
	exports.matchesSelector = matchesSelector;
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * A regex which matches an ID selector at string start.
	     */
	    var ID_RE = /^#[^\s\+>~#\.\[:]+/;
	    /**
	     * A regex which matches a class selector at string start.
	     */
	    var CLASS_RE = /^\.[^\s\+>~#\.\[:]+/;
	    /**
	     * A regex which matches an attribute selector at string start.
	     */
	    var ATTR_RE = /^\[[^\]]+\]/;
	    /**
	     * A regex which matches a type selector at string start.
	     */
	    var TYPE_RE = /^[^\s\+>~#\.\[:]+/;
	    /**
	     * A regex which matches a pseudo-element selector at string start.
	     */
	    var PSEUDO_ELEM_RE = /^(::[^\s\+>~#\.\[:]+|:first-line|:first-letter|:before|:after)/;
	    /**
	     * A regex which matches a pseudo-class selector at string start.
	     */
	    var PSEUDO_CLASS_RE = /^:[^\s\+>~#\.\[:]+/;
	    /**
	     * A regex which matches ignored characters at string start.
	     */
	    var IGNORE_RE = /^[\s\+>~\*]+/;
	    /**
	     * A regex which matches the negation pseudo-class globally.
	     */
	    var NEGATION_RE = /:not\(([^\)]+)\)/g;
	    /**
	     * A cached of computed selector specificity values.
	     */
	    Private.specificityCache = Object.create(null);
	    /**
	     * A cached of computed selector validity.
	     */
	    Private.validityCache = Object.create(null);
	    /**
	     * An empty element for testing selector validity.
	     */
	    Private.testElem = document.createElement('div');
	    /**
	     * A cross-browser CSS selector matching prototype function.
	     */
	    Private.protoMatchFunc = (function () {
	        var proto = Element.prototype;
	        return (proto.matches ||
	            proto.matchesSelector ||
	            proto.mozMatchesSelector ||
	            proto.msMatchesSelector ||
	            proto.oMatchesSelector ||
	            proto.webkitMatchesSelector ||
	            (function (selector) {
	                var elem = this;
	                var matches = elem.ownerDocument.querySelectorAll(selector);
	                return Array.prototype.indexOf.call(matches, elem) !== -1;
	            }));
	    })();
	    /**
	     * Calculate the specificity of a single selector.
	     *
	     * The behavior is undefined if the selector is invalid.
	     */
	    function calculateSingle(selector) {
	        // Ignore anything after the first comma.
	        selector = selector.split(',', 1)[0];
	        // Setup the aggregate counters.
	        var a = 0;
	        var b = 0;
	        var c = 0;
	        // Apply a regex to the front selector. If the match succeeds, that
	        // portion of the selector is removed. Returns a success/fail flag.
	        function match(re) {
	            var match = selector.match(re);
	            if (match === null) {
	                return false;
	            }
	            selector = selector.slice(match[0].length);
	            return true;
	        }
	        // Replace the negation pseudo-class (which is ignored),
	        // but keep its inner content (which is not ignored).
	        selector = selector.replace(NEGATION_RE, ' $1 ');
	        // Continue matching until the selector is consumed.
	        while (selector.length > 0) {
	            // Match an ID selector.
	            if (match(ID_RE)) {
	                a++;
	                continue;
	            }
	            // Match a class selector.
	            if (match(CLASS_RE)) {
	                b++;
	                continue;
	            }
	            // Match an attribute selector.
	            if (match(ATTR_RE)) {
	                b++;
	                continue;
	            }
	            // Match a pseudo-element selector. This is done before matching
	            // a pseudo-class since this regex overlaps with the class regex.
	            if (match(PSEUDO_ELEM_RE)) {
	                c++;
	                continue;
	            }
	            // Match a pseudo-class selector.
	            if (match(PSEUDO_CLASS_RE)) {
	                b++;
	                continue;
	            }
	            // Match a plain type selector.
	            if (match(TYPE_RE)) {
	                c++;
	                continue;
	            }
	            // Finally, match any ignored characters.
	            if (match(IGNORE_RE)) {
	                continue;
	            }
	            // At this point, the selector is assumed to be invalid.
	            return 0;
	        }
	        // Clamp each component to a reasonable base.
	        a = Math.min(a, 0xFF);
	        b = Math.min(b, 0xFF);
	        c = Math.min(c, 0xFF);
	        // Combine the components into a single result.
	        return (a << 16) | (b << 8) | c;
	    }
	    Private.calculateSingle = calculateSingle;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/dom/selector.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/keyboard.js **/
jupyter.define('phosphor@0.7.0/lib/ui/keyboard.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * A concrete implementation of [[IKeyboardLayout]] based on keycodes.
	 *
	 * The `.keyCode` property of a `'keydown'` event is a browser and OS
	 * specific representation of the physical key (not character) which
	 * was pressed on a keyboard. While not the most convenient API, it
	 * is currently the only one which works reliably on all browsers.
	 *
	 * This class accepts a user-defined mapping of keycode to key, which
	 * allows for reliable shortcuts tailored to the user's system.
	 */
	var KeycodeLayout = (function () {
	    /**
	     * Construct a new keycode layout.
	     *
	     * @param name - The human readable name for the layout.
	     *
	     * @param codes - A mapping of keycode to key value.
	     */
	    function KeycodeLayout(name, codes) {
	        this._name = name;
	        this._codes = codes;
	        this._keys = KeycodeLayout.extractKeys(codes);
	    }
	    Object.defineProperty(KeycodeLayout.prototype, "name", {
	        /**
	         * The human readable name of the layout.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._name;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Get an array of the key values supported by the layout.
	     *
	     * @returns A new array of the supported key values.
	     */
	    KeycodeLayout.prototype.keys = function () {
	        return Object.keys(this._keys);
	    };
	    /**
	     * Test whether the given key is a valid value for the layout.
	     *
	     * @param key - The user provided key to test for validity.
	     *
	     * @returns `true` if the key is valid, `false` otherwise.
	     */
	    KeycodeLayout.prototype.isValidKey = function (key) {
	        return key in this._keys;
	    };
	    /**
	     * Get the key for a `'keydown'` event.
	     *
	     * @param event - The event object for a `'keydown'` event.
	     *
	     * @returns The associated key value, or an empty string if
	     *   the event does not represent a valid primary key.
	     */
	    KeycodeLayout.prototype.keyForKeydownEvent = function (event) {
	        return this._codes[event.keyCode] || '';
	    };
	    return KeycodeLayout;
	}());
	exports.KeycodeLayout = KeycodeLayout;
	/**
	 * The namespace for the `KeycodeLayout` class statics.
	 */
	var KeycodeLayout;
	(function (KeycodeLayout) {
	    /**
	     * Extract the set of keys from a code map.
	     *
	     * @param code - The code map of interest.
	     *
	     * @returns A set of the keys in the code map.
	     */
	    function extractKeys(codes) {
	        var keys = Object.create(null);
	        for (var c in codes)
	            keys[codes[c]] = true;
	        return keys;
	    }
	    KeycodeLayout.extractKeys = extractKeys;
	})(KeycodeLayout = exports.KeycodeLayout || (exports.KeycodeLayout = {}));
	/**
	 * A keycode-based keyboard layout for US English keyboards.
	 *
	 * This layout is valid for the following OS/Browser combinations.
	 *
	 * - Windows
	 *   - Chrome
	 *   - Firefox
	 *   - IE
	 *
	 * - OSX
	 *   - Chrome
	 *   - Firefox
	 *   - Safari
	 *
	 * - Linux
	 *   - Chrome
	 *   - Firefox
	 *
	 * Other combinations may also work, but are untested.
	 */
	exports.EN_US = new KeycodeLayout('en-us', {
	    8: 'Backspace',
	    9: 'Tab',
	    13: 'Enter',
	    19: 'Pause',
	    27: 'Escape',
	    32: 'Space',
	    33: 'PageUp',
	    34: 'PageDown',
	    35: 'End',
	    36: 'Home',
	    37: 'ArrowLeft',
	    38: 'ArrowUp',
	    39: 'ArrowRight',
	    40: 'ArrowDown',
	    45: 'Insert',
	    46: 'Delete',
	    48: '0',
	    49: '1',
	    50: '2',
	    51: '3',
	    52: '4',
	    53: '5',
	    54: '6',
	    55: '7',
	    56: '8',
	    57: '9',
	    59: ';',
	    61: '=',
	    65: 'A',
	    66: 'B',
	    67: 'C',
	    68: 'D',
	    69: 'E',
	    70: 'F',
	    71: 'G',
	    72: 'H',
	    73: 'I',
	    74: 'J',
	    75: 'K',
	    76: 'L',
	    77: 'M',
	    78: 'N',
	    79: 'O',
	    80: 'P',
	    81: 'Q',
	    82: 'R',
	    83: 'S',
	    84: 'T',
	    85: 'U',
	    86: 'V',
	    87: 'W',
	    88: 'X',
	    89: 'Y',
	    90: 'Z',
	    93: 'ContextMenu',
	    96: '0',
	    97: '1',
	    98: '2',
	    99: '3',
	    100: '4',
	    101: '5',
	    102: '6',
	    103: '7',
	    104: '8',
	    105: '9',
	    106: '*',
	    107: '+',
	    109: '-',
	    110: '.',
	    111: '/',
	    112: 'F1',
	    113: 'F2',
	    114: 'F3',
	    115: 'F4',
	    116: 'F5',
	    117: 'F6',
	    118: 'F7',
	    119: 'F8',
	    120: 'F9',
	    121: 'F10',
	    122: 'F11',
	    123: 'F12',
	    173: '-',
	    186: ';',
	    187: '=',
	    188: ',',
	    189: '-',
	    190: '.',
	    191: '/',
	    192: '`',
	    219: '[',
	    220: '\\',
	    221: ']',
	    222: '\''
	});
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/keyboard.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/widget.js **/
jupyter.define('phosphor@0.7.0/lib/ui/widget.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	var messaging_1 = __jupyter_require__('phosphor@0.7.0/lib/core/messaging.js');
	var properties_1 = __jupyter_require__('phosphor@0.7.0/lib/core/properties.js');
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	var title_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/title.js');
	/**
	 * The class name added to Widget instances.
	 */
	var WIDGET_CLASS = 'p-Widget';
	/**
	 * The class name added to hidden widgets.
	 */
	var HIDDEN_CLASS = 'p-mod-hidden';
	/**
	 * The base class of the Phosphor widget hierarchy.
	 *
	 * #### Notes
	 * This class will typically be subclassed in order to create a useful
	 * widget. However, it can be used directly to host externally created
	 * content.
	 */
	var Widget = (function () {
	    /**
	     * Construct a new widget.
	     *
	     * @param options - The options for initializing the widget.
	     */
	    function Widget(options) {
	        if (options === void 0) { options = {}; }
	        this._flags = 0;
	        this._layout = null;
	        this._parent = null;
	        this._node = Private.createNode(options);
	        this.addClass(WIDGET_CLASS);
	    }
	    /**
	     * Dispose of the widget and its descendant widgets.
	     *
	     * #### Notes
	     * It is unsafe to use the widget after it has been disposed.
	     *
	     * All calls made to this method after the first are a no-op.
	     */
	    Widget.prototype.dispose = function () {
	        // Do nothing if the widget is already disposed.
	        if (this.isDisposed) {
	            return;
	        }
	        // Set the disposed flag and emit the disposed signal.
	        this.setFlag(WidgetFlag.IsDisposed);
	        this.disposed.emit(void 0);
	        // Remove or detach the widget if necessary.
	        if (this.parent) {
	            this.parent = null;
	        }
	        else if (this.isAttached) {
	            Widget.detach(this);
	        }
	        // Dispose of the widget layout.
	        if (this._layout) {
	            this._layout.dispose();
	            this._layout = null;
	        }
	        // Clear the attached data associated with the widget.
	        signaling_1.clearSignalData(this);
	        messaging_1.clearMessageData(this);
	        properties_1.clearPropertyData(this);
	        // Clear the reference to the DOM node.
	        this._node = null;
	    };
	    Object.defineProperty(Widget.prototype, "isDisposed", {
	        /**
	         * Test whether the widget has been disposed.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.testFlag(WidgetFlag.IsDisposed);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Widget.prototype, "isAttached", {
	        /**
	         * Test whether the widget's node is attached to the DOM.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.testFlag(WidgetFlag.IsAttached);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Widget.prototype, "isHidden", {
	        /**
	         * Test whether the widget is explicitly hidden.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.testFlag(WidgetFlag.IsHidden);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Widget.prototype, "isVisible", {
	        /**
	         * Test whether the widget is visible.
	         *
	         * #### Notes
	         * A widget is visible when it is attached to the DOM, is not
	         * explicitly hidden, and has no explicitly hidden ancestors.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.testFlag(WidgetFlag.IsVisible);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Widget.prototype, "node", {
	        /**
	         * Get the DOM node owned by the widget.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._node;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Widget.prototype, "id", {
	        /**
	         * Get the id of the widget's DOM node.
	         */
	        get: function () {
	            return this._node.id;
	        },
	        /**
	         * Set the id of the widget's DOM node.
	         */
	        set: function (value) {
	            this._node.id = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Widget.prototype, "title", {
	        /**
	         * Get the title object for the widget.
	         *
	         * #### Notes
	         * The title object is used by some container widgets when displaying
	         * the widget alongside some title, such as a tab panel or side bar.
	         *
	         * Since not all widgets will use the title, it is created on demand.
	         *
	         * The `owner` property of the title is set to this widget.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return Private.titleProperty.get(this);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Widget.prototype, "parent", {
	        /**
	         * Get the parent of the widget.
	         *
	         * #### Notes
	         * This will be `null` if the widget does not have a parent.
	         */
	        get: function () {
	            return this._parent;
	        },
	        /**
	         * Set the parent of the widget.
	         *
	         * #### Notes
	         * Children are typically added to a widget by using a layout, which
	         * means user code will not normally set the parent widget directly.
	         *
	         * The widget will be automatically removed from its old parent.
	         *
	         * This is a no-op if there is no effective parent change.
	         */
	        set: function (value) {
	            value = value || null;
	            if (this._parent === value) {
	                return;
	            }
	            if (value && this.contains(value)) {
	                throw new Error('Invalid parent widget.');
	            }
	            if (this._parent && !this._parent.isDisposed) {
	                messaging_1.sendMessage(this._parent, new ChildMessage('child-removed', this));
	            }
	            this._parent = value;
	            if (this._parent && !this._parent.isDisposed) {
	                messaging_1.sendMessage(this._parent, new ChildMessage('child-added', this));
	            }
	            messaging_1.sendMessage(this, WidgetMessage.ParentChanged);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Widget.prototype, "layout", {
	        /**
	         * Get the layout for the widget.
	         *
	         * #### Notes
	         * This will be `null` if the widget does not have a layout.
	         */
	        get: function () {
	            return this._layout;
	        },
	        /**
	         * Set the layout for the widget.
	         *
	         * #### Notes
	         * The layout is single-use only. It cannot be set to `null` and it
	         * cannot be changed after the first assignment.
	         *
	         * The layout is disposed automatically when the widget is disposed.
	         */
	        set: function (value) {
	            value = value || null;
	            if (this._layout === value) {
	                return;
	            }
	            if (this.testFlag(WidgetFlag.DisallowLayout)) {
	                throw new Error('Cannot set widget layout.');
	            }
	            if (this._layout) {
	                throw new Error('Cannot change widget layout.');
	            }
	            if (value.parent) {
	                throw new Error('Cannot change layout parent.');
	            }
	            this._layout = value;
	            value.parent = this;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over the widget's children.
	     *
	     * @returns A new iterator over the children of the widget.
	     *
	     * #### Notes
	     * The widget must have a populated layout in order to have children.
	     *
	     * If a layout is not installed, the returned iterator will be empty.
	     */
	    Widget.prototype.children = function () {
	        return this._layout ? this._layout.iter() : iteration_1.empty();
	    };
	    /**
	     * Test whether a widget is a descendant of this widget.
	     *
	     * @param widget - The descendant widget of interest.
	     *
	     * @returns `true` if the widget is a descendant, `false` otherwise.
	     */
	    Widget.prototype.contains = function (widget) {
	        for (; widget; widget = widget._parent) {
	            if (widget === this)
	                return true;
	        }
	        return false;
	    };
	    /**
	     * Test whether the widget's DOM node has the given class name.
	     *
	     * @param name - The class name of interest.
	     *
	     * @returns `true` if the node has the class, `false` otherwise.
	     */
	    Widget.prototype.hasClass = function (name) {
	        return this._node.classList.contains(name);
	    };
	    /**
	     * Add a class name to the widget's DOM node.
	     *
	     * @param name - The class name to add to the node.
	     *
	     * #### Notes
	     * If the class name is already added to the node, this is a no-op.
	     *
	     * The class name must not contain whitespace.
	     */
	    Widget.prototype.addClass = function (name) {
	        this._node.classList.add(name);
	    };
	    /**
	     * Remove a class name from the widget's DOM node.
	     *
	     * @param name - The class name to remove from the node.
	     *
	     * #### Notes
	     * If the class name is not yet added to the node, this is a no-op.
	     *
	     * The class name must not contain whitespace.
	     */
	    Widget.prototype.removeClass = function (name) {
	        this._node.classList.remove(name);
	    };
	    /**
	     * Toggle a class name on the widget's DOM node.
	     *
	     * @param name - The class name to toggle on the node.
	     *
	     * @param force - Whether to force add the class (`true`) or force
	     *   remove the class (`false`). If not provided, the presence of
	     *   the class will be toggled from its current state.
	     *
	     * @returns `true` if the class is now present, `false` otherwise.
	     *
	     * #### Notes
	     * The class name must not contain whitespace.
	     */
	    Widget.prototype.toggleClass = function (name, force) {
	        if (force === true) {
	            this._node.classList.add(name);
	            return true;
	        }
	        if (force === false) {
	            this._node.classList.remove(name);
	            return false;
	        }
	        return this._node.classList.toggle(name);
	    };
	    /**
	     * Post an `'update-request'` message to the widget.
	     *
	     * #### Notes
	     * This is a simple convenience method for posting the message.
	     */
	    Widget.prototype.update = function () {
	        messaging_1.postMessage(this, WidgetMessage.UpdateRequest);
	    };
	    /**
	     * Post a `'fit-request'` message to the widget.
	     *
	     * #### Notes
	     * This is a simple convenience method for posting the message.
	     */
	    Widget.prototype.fit = function () {
	        messaging_1.postMessage(this, WidgetMessage.FitRequest);
	    };
	    /**
	     * Post an `'activate-request'` message to the widget.
	     *
	     * #### Notes
	     * This is a simple convenience method for posting the message.
	     */
	    Widget.prototype.activate = function () {
	        messaging_1.postMessage(this, WidgetMessage.ActivateRequest);
	    };
	    /**
	     * Send a `'close-request'` message to the widget.
	     *
	     * #### Notes
	     * This is a simple convenience method for sending the message.
	     */
	    Widget.prototype.close = function () {
	        messaging_1.sendMessage(this, WidgetMessage.CloseRequest);
	    };
	    /**
	     * Show the widget and make it visible to its parent widget.
	     *
	     * #### Notes
	     * This causes the [[isHidden]] property to be `false`.
	     *
	     * If the widget is not explicitly hidden, this is a no-op.
	     */
	    Widget.prototype.show = function () {
	        if (!this.testFlag(WidgetFlag.IsHidden)) {
	            return;
	        }
	        this.clearFlag(WidgetFlag.IsHidden);
	        this.removeClass(HIDDEN_CLASS);
	        if (this.isAttached && (!this.parent || this.parent.isVisible)) {
	            messaging_1.sendMessage(this, WidgetMessage.AfterShow);
	        }
	        if (this.parent) {
	            messaging_1.sendMessage(this.parent, new ChildMessage('child-shown', this));
	        }
	    };
	    /**
	     * Hide the widget and make it hidden to its parent widget.
	     *
	     * #### Notes
	     * This causes the [[isHidden]] property to be `true`.
	     *
	     * If the widget is explicitly hidden, this is a no-op.
	     */
	    Widget.prototype.hide = function () {
	        if (this.testFlag(WidgetFlag.IsHidden)) {
	            return;
	        }
	        if (this.isAttached && (!this.parent || this.parent.isVisible)) {
	            messaging_1.sendMessage(this, WidgetMessage.BeforeHide);
	        }
	        this.setFlag(WidgetFlag.IsHidden);
	        this.addClass(HIDDEN_CLASS);
	        if (this.parent) {
	            messaging_1.sendMessage(this.parent, new ChildMessage('child-hidden', this));
	        }
	    };
	    /**
	     * Show or hide the widget according to a boolean value.
	     *
	     * @param hidden - `true` to hide the widget, or `false` to show it.
	     *
	     * #### Notes
	     * This is a convenience method for `hide()` and `show()`.
	     */
	    Widget.prototype.setHidden = function (hidden) {
	        if (hidden) {
	            this.hide();
	        }
	        else {
	            this.show();
	        }
	    };
	    /**
	     * Test whether the given widget flag is set.
	     *
	     * #### Notes
	     * This will not typically be called directly by user code.
	     */
	    Widget.prototype.testFlag = function (flag) {
	        return (this._flags & flag) !== 0;
	    };
	    /**
	     * Set the given widget flag.
	     *
	     * #### Notes
	     * This will not typically be called directly by user code.
	     */
	    Widget.prototype.setFlag = function (flag) {
	        this._flags |= flag;
	    };
	    /**
	     * Clear the given widget flag.
	     *
	     * #### Notes
	     * This will not typically be called directly by user code.
	     */
	    Widget.prototype.clearFlag = function (flag) {
	        this._flags &= ~flag;
	    };
	    /**
	     * Process a message sent to the widget.
	     *
	     * @param msg - The message sent to the widget.
	     *
	     * #### Notes
	     * Subclasses may reimplement this method as needed.
	     */
	    Widget.prototype.processMessage = function (msg) {
	        switch (msg.type) {
	            case 'resize':
	                this.notifyLayout(msg);
	                this.onResize(msg);
	                break;
	            case 'update-request':
	                this.notifyLayout(msg);
	                this.onUpdateRequest(msg);
	                break;
	            case 'after-show':
	                this.setFlag(WidgetFlag.IsVisible);
	                this.notifyLayout(msg);
	                this.onAfterShow(msg);
	                break;
	            case 'before-hide':
	                this.notifyLayout(msg);
	                this.onBeforeHide(msg);
	                this.clearFlag(WidgetFlag.IsVisible);
	                break;
	            case 'after-attach':
	                var visible = !this.isHidden && (!this.parent || this.parent.isVisible);
	                if (visible)
	                    this.setFlag(WidgetFlag.IsVisible);
	                this.setFlag(WidgetFlag.IsAttached);
	                this.notifyLayout(msg);
	                this.onAfterAttach(msg);
	                break;
	            case 'before-detach':
	                this.notifyLayout(msg);
	                this.onBeforeDetach(msg);
	                this.clearFlag(WidgetFlag.IsVisible);
	                this.clearFlag(WidgetFlag.IsAttached);
	                break;
	            case 'activate-request':
	                this.notifyLayout(msg);
	                this.onActivateRequest(msg);
	                break;
	            case 'close-request':
	                this.notifyLayout(msg);
	                this.onCloseRequest(msg);
	                break;
	            case 'child-added':
	                this.notifyLayout(msg);
	                this.onChildAdded(msg);
	                break;
	            case 'child-removed':
	                this.notifyLayout(msg);
	                this.onChildRemoved(msg);
	                break;
	            default:
	                this.notifyLayout(msg);
	                break;
	        }
	    };
	    /**
	     * Invoke the message processing routine of the widget's layout.
	     *
	     * @param msg - The message to dispatch to the layout.
	     *
	     * #### Notes
	     * This is a no-op if the widget does not have a layout.
	     *
	     * This will not typically be called directly by user code.
	     */
	    Widget.prototype.notifyLayout = function (msg) {
	        if (this._layout)
	            this._layout.processParentMessage(msg);
	    };
	    /**
	     * A message handler invoked on a `'close-request'` message.
	     *
	     * #### Notes
	     * The default implementation unparents or detaches the widget.
	     */
	    Widget.prototype.onCloseRequest = function (msg) {
	        if (this.parent) {
	            this.parent = null;
	        }
	        else if (this.isAttached) {
	            Widget.detach(this);
	        }
	    };
	    /**
	     * A message handler invoked on a `'resize'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Widget.prototype.onResize = function (msg) { };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Widget.prototype.onUpdateRequest = function (msg) { };
	    /**
	     * A message handler invoked on an `'activate-request'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Widget.prototype.onActivateRequest = function (msg) { };
	    /**
	     * A message handler invoked on an `'after-show'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Widget.prototype.onAfterShow = function (msg) { };
	    /**
	     * A message handler invoked on a `'before-hide'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Widget.prototype.onBeforeHide = function (msg) { };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Widget.prototype.onAfterAttach = function (msg) { };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Widget.prototype.onBeforeDetach = function (msg) { };
	    /**
	     * A message handler invoked on a `'child-added'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Widget.prototype.onChildAdded = function (msg) { };
	    /**
	     * A message handler invoked on a `'child-removed'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Widget.prototype.onChildRemoved = function (msg) { };
	    return Widget;
	}());
	exports.Widget = Widget;
	// Define the signals for the `Widget` class.
	signaling_1.defineSignal(Widget.prototype, 'disposed');
	/**
	 * The namespace for the `Widget` class statics.
	 */
	var Widget;
	(function (Widget) {
	    // TODO - should this be an instance method?
	    /**
	     * Attach a widget to a host DOM node.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @param host - The DOM node to use as the widget's host.
	     *
	     * #### Notes
	     * This will throw an error if the widget is not a root widget, if
	     * the widget is already attached, or if the host is not attached
	     * to the DOM.
	     */
	    function attach(widget, host) {
	        if (widget.parent) {
	            throw new Error('Cannot attach child widget.');
	        }
	        if (widget.isAttached || document.body.contains(widget.node)) {
	            throw new Error('Widget already attached.');
	        }
	        if (!document.body.contains(host)) {
	            throw new Error('Host not attached.');
	        }
	        host.appendChild(widget.node);
	        messaging_1.sendMessage(widget, WidgetMessage.AfterAttach);
	    }
	    Widget.attach = attach;
	    // TODO - should this be an instance method?
	    /**
	     * Detach the widget from its host DOM node.
	     *
	     * @param widget - The widget of interest.
	     *
	     * #### Notes
	     * This will throw an error if the widget is not a root widget, or
	     * if the widget is not attached to the DOM.
	     */
	    function detach(widget) {
	        if (widget.parent) {
	            throw new Error('Cannot detach child widget.');
	        }
	        if (!widget.isAttached || !document.body.contains(widget.node)) {
	            throw new Error('Widget not attached.');
	        }
	        messaging_1.sendMessage(widget, WidgetMessage.BeforeDetach);
	        widget.node.parentNode.removeChild(widget.node);
	    }
	    Widget.detach = detach;
	    /**
	     * Prepare a widget for absolute layout geometry.
	     *
	     * @param widget - The widget of interest.
	     *
	     * #### Notes
	     * This sets the inline style position of the widget to `absolute`.
	     */
	    function prepareGeometry(widget) {
	        widget.node.style.position = 'absolute';
	    }
	    Widget.prepareGeometry = prepareGeometry;
	    /**
	     * Reset the layout geometry of a widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * #### Notes
	     * This clears the inline style position and geometry of the widget.
	     */
	    function resetGeometry(widget) {
	        var style = widget.node.style;
	        var rect = Private.rectProperty.get(widget);
	        rect.top = NaN;
	        rect.left = NaN;
	        rect.width = NaN;
	        rect.height = NaN;
	        style.position = '';
	        style.top = '';
	        style.left = '';
	        style.width = '';
	        style.height = '';
	    }
	    Widget.resetGeometry = resetGeometry;
	    /**
	     * Set the absolute layout geometry of a widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @param left - The desired offset left position of the widget.
	     *
	     * @param top - The desired offset top position of the widget.
	     *
	     * @param width - The desired offset width of the widget.
	     *
	     * @param height - The desired offset height of the widget.
	     *
	     * #### Notes
	     * All dimensions are assumed to be pixels with coordinates relative
	     * to the origin of the widget's offset parent.
	     *
	     * The widget's node is assumed to be position `absolute`.
	     *
	     * If the widget is resized from its previous size, a `ResizeMessage`
	     * will be automatically sent to the widget.
	     */
	    function setGeometry(widget, left, top, width, height) {
	        var resized = false;
	        var style = widget.node.style;
	        var rect = Private.rectProperty.get(widget);
	        if (rect.top !== top) {
	            rect.top = top;
	            style.top = top + "px";
	        }
	        if (rect.left !== left) {
	            rect.left = left;
	            style.left = left + "px";
	        }
	        if (rect.width !== width) {
	            resized = true;
	            rect.width = width;
	            style.width = width + "px";
	        }
	        if (rect.height !== height) {
	            resized = true;
	            rect.height = height;
	            style.height = height + "px";
	        }
	        if (resized) {
	            messaging_1.sendMessage(widget, new ResizeMessage(width, height));
	        }
	    }
	    Widget.setGeometry = setGeometry;
	})(Widget = exports.Widget || (exports.Widget = {}));
	/**
	 * An abstract base class for creating Phosphor layouts.
	 *
	 * #### Notes
	 * A layout is used to add widgets to a parent and to arrange those
	 * widgets within the parent's DOM node.
	 *
	 * This class implements the base functionality which is required of
	 * nearly all layouts. It must be subclassed in order to be useful.
	 *
	 * Notably, this class does not define a uniform interface for adding
	 * widgets to the layout. A subclass should define that API in a way
	 * which is meaningful for its intended use.
	 */
	var Layout = (function () {
	    function Layout() {
	        this._disposed = false;
	        this._parent = null;
	    }
	    /**
	     * Dispose of the resources held by the layout.
	     *
	     * #### Notes
	     * This should be reimplemented to clear and dispose of the widgets.
	     *
	     * All reimplementations should call the superclass method.
	     *
	     * This method is called automatically when the parent is disposed.
	     */
	    Layout.prototype.dispose = function () {
	        this._disposed = true;
	        this._parent = null;
	        signaling_1.clearSignalData(this);
	        properties_1.clearPropertyData(this);
	    };
	    Object.defineProperty(Layout.prototype, "isDisposed", {
	        /**
	         * Test whether the layout is disposed.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._disposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Layout.prototype, "parent", {
	        /**
	         * Get the parent widget of the layout.
	         */
	        get: function () {
	            return this._parent;
	        },
	        /**
	         * Set the parent widget of the layout.
	         *
	         * #### Notes
	         * This is set automatically when installing the layout on the parent
	         * widget. The parent widget should not be set directly by user code.
	         */
	        set: function (value) {
	            if (!value) {
	                throw new Error('Cannot set parent widget to null.');
	            }
	            if (this._parent === value) {
	                return;
	            }
	            if (this._parent) {
	                throw new Error('Cannot change parent widget.');
	            }
	            if (value.layout !== this) {
	                throw new Error('Invalid parent widget.');
	            }
	            this._parent = value;
	            this.init();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Process a message sent to the parent widget.
	     *
	     * @param msg - The message sent to the parent widget.
	     *
	     * #### Notes
	     * This method is called by the parent widget to process a message.
	     *
	     * Subclasses may reimplement this method as needed.
	     */
	    Layout.prototype.processParentMessage = function (msg) {
	        switch (msg.type) {
	            case 'resize':
	                this.onResize(msg);
	                break;
	            case 'update-request':
	                this.onUpdateRequest(msg);
	                break;
	            case 'fit-request':
	                this.onFitRequest(msg);
	                break;
	            case 'after-show':
	                this.onAfterShow(msg);
	                break;
	            case 'before-hide':
	                this.onBeforeHide(msg);
	                break;
	            case 'after-attach':
	                this.onAfterAttach(msg);
	                break;
	            case 'before-detach':
	                this.onBeforeDetach(msg);
	                break;
	            case 'child-removed':
	                this.onChildRemoved(msg);
	                break;
	            case 'child-shown':
	                this.onChildShown(msg);
	                break;
	            case 'child-hidden':
	                this.onChildHidden(msg);
	                break;
	        }
	    };
	    /**
	     * Perform layout initialization which requires the parent widget.
	     *
	     * #### Notes
	     * This method is invoked immediately after the layout is installed
	     * on the parent widget.
	     *
	     * The default implementation reparents all of the widgets to the
	     * layout parent widget.
	     *
	     * Subclasses should reimplement this method and attach the child
	     * widget nodes to the parent widget's node.
	     */
	    Layout.prototype.init = function () {
	        var _this = this;
	        iteration_1.each(this, function (widget) { widget.parent = _this.parent; });
	    };
	    /**
	     * A message handler invoked on a `'resize'` message.
	     *
	     * #### Notes
	     * The layout should ensure that its widgets are resized according
	     * to the specified layout space, and that they are sent a `'resize'`
	     * message if appropriate.
	     *
	     * The default implementation of this method sends an `UnknownSize`
	     * resize message to all widgets.
	     *
	     * This may be reimplemented by subclasses as needed.
	     */
	    Layout.prototype.onResize = function (msg) {
	        iteration_1.each(this, function (widget) { messaging_1.sendMessage(widget, ResizeMessage.UnknownSize); });
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     *
	     * #### Notes
	     * The layout should ensure that its widgets are resized according
	     * to the available layout space, and that they are sent a `'resize'`
	     * message if appropriate.
	     *
	     * The default implementation of this method sends an `UnknownSize`
	     * resize message to all widgets.
	     *
	     * This may be reimplemented by subclasses as needed.
	     */
	    Layout.prototype.onUpdateRequest = function (msg) {
	        iteration_1.each(this, function (widget) { messaging_1.sendMessage(widget, ResizeMessage.UnknownSize); });
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     *
	     * #### Notes
	     * The default implementation of this method forwards the message
	     * to all widgets. It assumes all widget nodes are attached to the
	     * parent widget node.
	     *
	     * This may be reimplemented by subclasses as needed.
	     */
	    Layout.prototype.onAfterAttach = function (msg) {
	        iteration_1.each(this, function (widget) { messaging_1.sendMessage(widget, msg); });
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     *
	     * #### Notes
	     * The default implementation of this method forwards the message
	     * to all widgets. It assumes all widget nodes are attached to the
	     * parent widget node.
	     *
	     * This may be reimplemented by subclasses as needed.
	     */
	    Layout.prototype.onBeforeDetach = function (msg) {
	        iteration_1.each(this, function (widget) { messaging_1.sendMessage(widget, msg); });
	    };
	    /**
	     * A message handler invoked on an `'after-show'` message.
	     *
	     * #### Notes
	     * The default implementation of this method forwards the message to
	     * all non-hidden widgets. It assumes all widget nodes are attached
	     * to the parent widget node.
	     *
	     * This may be reimplemented by subclasses as needed.
	     */
	    Layout.prototype.onAfterShow = function (msg) {
	        iteration_1.each(this, function (widget) { if (!widget.isHidden)
	            messaging_1.sendMessage(widget, msg); });
	    };
	    /**
	     * A message handler invoked on a `'before-hide'` message.
	     *
	     * #### Notes
	     * The default implementation of this method forwards the message to
	     * all non-hidden widgets. It assumes all widget nodes are attached
	     * to the parent widget node.
	     *
	     * This may be reimplemented by subclasses as needed.
	     */
	    Layout.prototype.onBeforeHide = function (msg) {
	        iteration_1.each(this, function (widget) { if (!widget.isHidden)
	            messaging_1.sendMessage(widget, msg); });
	    };
	    /**
	     * A message handler invoked on a `'child-removed'` message.
	     *
	     * #### Notes
	     * This will remove the child widget from the layout.
	     *
	     * Subclasses should **not** typically reimplement this method.
	     */
	    Layout.prototype.onChildRemoved = function (msg) {
	        this.removeWidget(msg.child);
	    };
	    /**
	     * A message handler invoked on a `'fit-request'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Layout.prototype.onFitRequest = function (msg) { };
	    /**
	     * A message handler invoked on a `'child-shown'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Layout.prototype.onChildShown = function (msg) { };
	    /**
	     * A message handler invoked on a `'child-hidden'` message.
	     *
	     * #### Notes
	     * The default implementation of this handler is a no-op.
	     */
	    Layout.prototype.onChildHidden = function (msg) { };
	    return Layout;
	}());
	exports.Layout = Layout;
	// TODO should this be in the Widget namespace?
	/**
	 * An enum of widget bit flags.
	 */
	(function (WidgetFlag) {
	    /**
	     * The widget has been disposed.
	     */
	    WidgetFlag[WidgetFlag["IsDisposed"] = 1] = "IsDisposed";
	    /**
	     * The widget is attached to the DOM.
	     */
	    WidgetFlag[WidgetFlag["IsAttached"] = 2] = "IsAttached";
	    /**
	     * The widget is hidden.
	     */
	    WidgetFlag[WidgetFlag["IsHidden"] = 4] = "IsHidden";
	    /**
	     * The widget is visible.
	     */
	    WidgetFlag[WidgetFlag["IsVisible"] = 8] = "IsVisible";
	    /**
	     * A layout cannot be set on the widget.
	     */
	    WidgetFlag[WidgetFlag["DisallowLayout"] = 16] = "DisallowLayout";
	})(exports.WidgetFlag || (exports.WidgetFlag = {}));
	var WidgetFlag = exports.WidgetFlag;
	// TODO should this be in the Widget namespace?
	/**
	 * A collection of stateless messages related to widgets.
	 */
	var WidgetMessage;
	(function (WidgetMessage) {
	    /**
	     * A singleton `'after-show'` message.
	     *
	     * #### Notes
	     * This message is sent to a widget after it becomes visible.
	     *
	     * This message is **not** sent when the widget is being attached.
	     */
	    WidgetMessage.AfterShow = new messaging_1.Message('after-show');
	    /**
	     * A singleton `'before-hide'` message.
	     *
	     * #### Notes
	     * This message is sent to a widget before it becomes not-visible.
	     *
	     * This message is **not** sent when the widget is being detached.
	     */
	    WidgetMessage.BeforeHide = new messaging_1.Message('before-hide');
	    /**
	     * A singleton `'after-attach'` message.
	     *
	     * #### Notes
	     * This message is sent to a widget after it is attached.
	     */
	    WidgetMessage.AfterAttach = new messaging_1.Message('after-attach');
	    /**
	     * A singleton `'before-detach'` message.
	     *
	     * #### Notes
	     * This message is sent to a widget before it is detached.
	     */
	    WidgetMessage.BeforeDetach = new messaging_1.Message('before-detach');
	    /**
	     * A singleton `'parent-changed'` message.
	     *
	     * #### Notes
	     * This message is sent to a widget when its parent has changed.
	     */
	    WidgetMessage.ParentChanged = new messaging_1.Message('parent-changed');
	    /**
	     * A singleton conflatable `'update-request'` message.
	     *
	     * #### Notes
	     * This message can be dispatched to supporting widgets in order to
	     * update their content based on the current widget state. Not all
	     * widgets will respond to messages of this type.
	     *
	     * For widgets with a layout, this message will inform the layout to
	     * update the position and size of its child widgets.
	     */
	    WidgetMessage.UpdateRequest = new messaging_1.ConflatableMessage('update-request');
	    /**
	     * A singleton conflatable `'fit-request'` message.
	     *
	     * #### Notes
	     * For widgets with a layout, this message will inform the layout to
	     * recalculate its size constraints to fit the space requirements of
	     * its child widgets, and to update their position and size. Not all
	     * layouts will respond to messages of this type.
	     */
	    WidgetMessage.FitRequest = new messaging_1.ConflatableMessage('fit-request');
	    /**
	     * A singleton conflatable `'activate-request'` message.
	     *
	     * #### Notes
	     * This message should be dispatched to a widget when it should
	     * perform the actions necessary to activate the widget, which
	     * may include focusing its node or descendant node.
	     */
	    WidgetMessage.ActivateRequest = new messaging_1.ConflatableMessage('activate-request');
	    /**
	     * A singleton conflatable `'close-request'` message.
	     *
	     * #### Notes
	     * This message should be dispatched to a widget when it should close
	     * and remove itself from the widget hierarchy.
	     */
	    WidgetMessage.CloseRequest = new messaging_1.ConflatableMessage('close-request');
	})(WidgetMessage = exports.WidgetMessage || (exports.WidgetMessage = {}));
	// TODO should this be in the Widget namespace?
	/**
	 * A message class for child related messages.
	 */
	var ChildMessage = (function (_super) {
	    __extends(ChildMessage, _super);
	    /**
	     * Construct a new child message.
	     *
	     * @param type - The message type.
	     *
	     * @param child - The child widget for the message.
	     */
	    function ChildMessage(type, child) {
	        _super.call(this, type);
	        this._child = child;
	    }
	    Object.defineProperty(ChildMessage.prototype, "child", {
	        /**
	         * The child widget for the message.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._child;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return ChildMessage;
	}(messaging_1.Message));
	exports.ChildMessage = ChildMessage;
	// TODO should this be in the Widget namespace?
	/**
	 * A message class for `'resize'` messages.
	 */
	var ResizeMessage = (function (_super) {
	    __extends(ResizeMessage, _super);
	    /**
	     * Construct a new resize message.
	     *
	     * @param width - The **offset width** of the widget, or `-1` if
	     *   the width is not known.
	     *
	     * @param height - The **offset height** of the widget, or `-1` if
	     *   the height is not known.
	     */
	    function ResizeMessage(width, height) {
	        _super.call(this, 'resize');
	        this._width = width;
	        this._height = height;
	    }
	    Object.defineProperty(ResizeMessage.prototype, "width", {
	        /**
	         * The offset width of the widget.
	         *
	         * #### Notes
	         * This will be `-1` if the width is unknown.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._width;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ResizeMessage.prototype, "height", {
	        /**
	         * The offset height of the widget.
	         *
	         * #### Notes
	         * This will be `-1` if the height is unknown.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._height;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return ResizeMessage;
	}(messaging_1.Message));
	exports.ResizeMessage = ResizeMessage;
	/**
	 * The namespace for the `ResizeMessage` class statics.
	 */
	var ResizeMessage;
	(function (ResizeMessage) {
	    /**
	     * A singleton `'resize'` message with an unknown size.
	     */
	    ResizeMessage.UnknownSize = new ResizeMessage(-1, -1);
	})(ResizeMessage = exports.ResizeMessage || (exports.ResizeMessage = {}));
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * A property descriptor for a widget absolute geometry rect.
	     */
	    Private.rectProperty = new properties_1.AttachedProperty({
	        name: 'rect',
	        create: function () { return ({ top: NaN, left: NaN, width: NaN, height: NaN }); },
	    });
	    /**
	     * An attached property for the widget title object.
	     */
	    Private.titleProperty = new properties_1.AttachedProperty({
	        name: 'title',
	        create: function (owner) { return new title_1.Title({ owner: owner }); },
	    });
	    /**
	     * Create a DOM node for the given widget options.
	     */
	    function createNode(options) {
	        return options.node || document.createElement('div');
	    }
	    Private.createNode = createNode;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/widget.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/core/messaging.js **/
jupyter.define('phosphor@0.7.0/lib/core/messaging.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(setImmediate) {"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	var queue_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/queue.js');
	/**
	 * A message which can be delivered to a message handler.
	 *
	 * #### Notes
	 * This class may be subclassed to create complex message types.
	 *
	 * **See also:** [[postMessage]] and [[sendMessage]].
	 */
	var Message = (function () {
	    /**
	     * Construct a new message.
	     *
	     * @param type - The type of the message.
	     */
	    function Message(type) {
	        this._type = type;
	    }
	    Object.defineProperty(Message.prototype, "type", {
	        /**
	         * The type of the message.
	         *
	         * #### Notes
	         * This value can be used to cast the message to a derived type.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._type;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Message.prototype, "isConflatable", {
	        /**
	         * Test whether the message is conflatable.
	         *
	         * #### Notes
	         * Message conflation is an advanced topic. Most message types will
	         * not make use of this feature.
	         *
	         * If a conflatable message is posted to the event queue when another
	         * conflatable message of the same type and handler has already been
	         * posted, the `conflate()` method of the existing message will be
	         * invoked. If that method returns `true`, the new message will not
	         * be enqueued. This allows messages to be compressed, so that only
	         * a single instance of the message type is processed per cycle, no
	         * matter how many times messages of that type are posted.
	         *
	         * Custom message types may reimplement this property. The default
	         * implementation is always `false`.
	         *
	         * This is a read-only property.
	         *
	         * **See also:** [[conflateMessage]]
	         */
	        get: function () {
	            return false;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Conflate this message with another message of the same `type`.
	     *
	     * @param other - A conflatable message of the same `type`.
	     *
	     * @returns `true` if the message was successfully conflated, or
	     *   `false` otherwise.
	     *
	     * #### Notes
	     * Message conflation is an advanced topic. Most message types will
	     * not make use of this feature.
	     *
	     * This method is called automatically by the message loop when the
	     * given message is posted to the handler paired with this message.
	     * This message will already be enqueued and conflatable, and the
	     * given message will have the same `type` and also be conflatable.
	     *
	     * This method should merge the state of the other message into this
	     * message as needed so that when this message is finally delivered
	     * to the handler, it receives the most up-to-date information.
	     *
	     * If this method returns `true`, it signals that the other message
	     * was successfully conflated and it will not be enqueued.
	     *
	     * If this method returns `false`, the other message will be enqueued
	     * for normal delivery.
	     *
	     * Custom message types may reimplement this method. The default
	     * implementation always returns `false`.
	     *
	     * **See also:** [[isConflatable]]
	     */
	    Message.prototype.conflate = function (other) {
	        return false;
	    };
	    return Message;
	}());
	exports.Message = Message;
	/**
	 * A convenience message class which conflates automatically.
	 *
	 * #### Notes
	 * Message conflation is an advanced topic. Most user code will not
	 * make use of this class.
	 *
	 * This message class is useful for creating message instances which
	 * should be conflated, but which have no state other than `type`.
	 *
	 * If conflation of stateful messages is required, a custom `Message`
	 * subclass should be created.
	 */
	var ConflatableMessage = (function (_super) {
	    __extends(ConflatableMessage, _super);
	    function ConflatableMessage() {
	        _super.apply(this, arguments);
	    }
	    Object.defineProperty(ConflatableMessage.prototype, "isConflatable", {
	        /**
	         * Test whether the message is conflatable.
	         *
	         * #### Notes
	         * This property is always `true`.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return true;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Conflate this message with another message of the same `type`.
	     *
	     * #### Notes
	     * This method always returns `true`.
	     */
	    ConflatableMessage.prototype.conflate = function (other) {
	        return true;
	    };
	    return ConflatableMessage;
	}(Message));
	exports.ConflatableMessage = ConflatableMessage;
	/**
	 * Send a message to a message handler to process immediately.
	 *
	 * @param handler - The handler which should process the message.
	 *
	 * @param msg - The message to deliver to the handler.
	 *
	 * #### Notes
	 * The message will first be sent through any installed message hooks
	 * for the handler. If the message passes all hooks, it will then be
	 * delivered to the `processMessage` method of the handler.
	 *
	 * The message will not be conflated with pending posted messages.
	 *
	 * Exceptions in hooks and handlers will be caught and logged.
	 */
	function sendMessage(handler, msg) {
	    MessageLoop.sendMessage(handler, msg);
	}
	exports.sendMessage = sendMessage;
	/**
	 * Post a message to the message handler to process in the future.
	 *
	 * @param handler - The handler which should process the message.
	 *
	 * @param msg - The message to post to the handler.
	 *
	 * #### Notes
	 * The message will be conflated with the pending posted messages for
	 * the handler, if possible. If the message is not conflated, it will
	 * be queued for normal delivery on the next cycle of the event loop.
	 *
	 * Exceptions in hooks and handlers will be caught and logged.
	 */
	function postMessage(handler, msg) {
	    MessageLoop.postMessage(handler, msg);
	}
	exports.postMessage = postMessage;
	/**
	 * Install a message hook for a message handler.
	 *
	 * @param handler - The message handler of interest.
	 *
	 * @param hook - The message hook to install.
	 *
	 * #### Notes
	 * A message hook is invoked before a message is delivered to the
	 * handler. If the hook returns `false`, no other hooks will be
	 * invoked and the message will not be delivered to the handler.
	 *
	 * The most recently installed message hook is executed first.
	 *
	 * If the hook is already installed, it will be moved to the front.
	 *
	 * **See also:** [[removeMessageHook]]
	 */
	function installMessageHook(handler, hook) {
	    MessageLoop.installMessageHook(handler, hook);
	}
	exports.installMessageHook = installMessageHook;
	/**
	 * Remove an installed message hook for a message handler.
	 *
	 * @param handler - The message handler of interest.
	 *
	 * @param hook - The message hook to remove.
	 *
	 * #### Notes
	 * If the hook is not installed, this is a no-op.
	 *
	 * It is safe to call this function while the hook is executing.
	 */
	function removeMessageHook(handler, hook) {
	    MessageLoop.removeMessageHook(handler, hook);
	}
	exports.removeMessageHook = removeMessageHook;
	/**
	 * Clear all message data associated with a message handler.
	 *
	 * @param handler - The message handler of interest.
	 *
	 * #### Notes
	 * This will clear all pending messages and hooks for the handler.
	 */
	function clearMessageData(handler) {
	    MessageLoop.clearMessageData(handler);
	}
	exports.clearMessageData = clearMessageData;
	/**
	 * The namespace for the global singleton message loop.
	 */
	var MessageLoop;
	(function (MessageLoop) {
	    /**
	     * Send a message to a handler for immediate processing.
	     *
	     * This will first call all message hooks for the handler. If any
	     * hook rejects the message, the message will not be delivered.
	     */
	    function sendMessage(handler, msg) {
	        // Handle the common case of no message hooks.
	        var node = hooks.get(handler);
	        if (node === void 0) {
	            invokeHandler(handler, msg);
	            return;
	        }
	        // Run the message hooks and bail early if any hook returns false.
	        // A null hook indicates the hook was removed during dispatch.
	        for (; node !== null; node = node.next) {
	            if (node.hook !== null && !invokeHook(node.hook, handler, msg)) {
	                return;
	            }
	        }
	        // All message hooks returned true, so invoke the handler.
	        invokeHandler(handler, msg);
	    }
	    MessageLoop.sendMessage = sendMessage;
	    /**
	     * Post a message to a handler for processing in the future.
	     *
	     * This will first conflate the message, if possible. If it cannot
	     * be conflated, it will be queued for delivery on the next cycle
	     * of the event loop.
	     */
	    function postMessage(handler, msg) {
	        // Handle the common case a non-conflatable message first.
	        if (!msg.isConflatable) {
	            enqueueMessage(handler, msg);
	            return;
	        }
	        // Conflate message if possible.
	        var conflated = iteration_1.some(queue, function (posted) {
	            if (posted.handler !== handler) {
	                return false;
	            }
	            if (posted.msg.type !== msg.type) {
	                return false;
	            }
	            if (!posted.msg.isConflatable) {
	                return false;
	            }
	            return posted.msg.conflate(msg);
	        });
	        // If the message was not conflated, enqueue the message.
	        if (!conflated)
	            enqueueMessage(handler, msg);
	    }
	    MessageLoop.postMessage = postMessage;
	    /**
	     * Install a message hook for a handler.
	     *
	     * This will first remove the hook if it exists, then install the
	     * hook in front of other hooks for the handler.
	     */
	    function installMessageHook(handler, hook) {
	        // Remove the message hook if it's already installed.
	        removeMessageHook(handler, hook);
	        // Install the hook at the front of the list.
	        var next = hooks.get(handler) || null;
	        hooks.set(handler, { next: next, hook: hook });
	    }
	    MessageLoop.installMessageHook = installMessageHook;
	    /**
	     * Remove a message hook for a handler, if it exists.
	     */
	    function removeMessageHook(handler, hook) {
	        // Traverse the list and find the matching hook. If found, clear
	        // the reference to the hook and remove the node from the list.
	        // The node's next reference is *not* cleared so that dispatch
	        // may continue when the hook is removed during dispatch.
	        var prev = null;
	        var node = hooks.get(handler) || null;
	        for (; node !== null; prev = node, node = node.next) {
	            if (node.hook === hook) {
	                if (prev === null && node.next === null) {
	                    hooks.delete(handler);
	                }
	                else if (prev === null) {
	                    hooks.set(handler, node.next);
	                }
	                else {
	                    prev.next = node.next;
	                }
	                node.hook = null;
	                return;
	            }
	        }
	    }
	    MessageLoop.removeMessageHook = removeMessageHook;
	    /**
	     * Clear all message data for a handler.
	     *
	     * This will remove all message hooks and clear pending messages.
	     */
	    function clearMessageData(handler) {
	        // Clear all message hooks.
	        var node = hooks.get(handler) || null;
	        for (; node !== null; node = node.next) {
	            node.hook = null;
	        }
	        // Remove the handler from the hooks map.
	        hooks.delete(handler);
	        // Clear all pending messages.
	        iteration_1.each(queue, function (posted) {
	            if (posted.handler === handler) {
	                posted.handler = null;
	            }
	        });
	    }
	    MessageLoop.clearMessageData = clearMessageData;
	    /**
	     * The queue of posted message pairs.
	     */
	    var queue = new queue_1.Queue();
	    /**
	     * A mapping of handler to list of installed message hooks.
	     */
	    var hooks = new WeakMap();
	    /**
	     * A local reference to an event loop callback.
	     */
	    var defer = (function () {
	        var ok = typeof requestAnimationFrame === 'function';
	        return ok ? requestAnimationFrame : setImmediate;
	    })();
	    /**
	     * Whether a message loop cycle is pending.
	     */
	    var cyclePending = false;
	    /**
	     * Invoke a message hook with the specified handler and message.
	     *
	     * Returns the result of the hook, or `true` if the hook throws.
	     *
	     * Exceptions in the hook will be caught and logged.
	     */
	    function invokeHook(hook, handler, msg) {
	        var result;
	        try {
	            result = hook(handler, msg);
	        }
	        catch (err) {
	            result = true;
	            console.error(err);
	        }
	        return result;
	    }
	    /**
	     * Invoke a message handler with the specified message.
	     *
	     * Exceptions in the handler will be caught and logged.
	     */
	    function invokeHandler(handler, msg) {
	        try {
	            handler.processMessage(msg);
	        }
	        catch (err) {
	            console.error(err);
	        }
	    }
	    /**
	     * Add a message to the end of the message queue.
	     *
	     * This will automatically schedule a cycle of the loop.
	     */
	    function enqueueMessage(handler, msg) {
	        queue.pushBack({ handler: handler, msg: msg });
	        scheduleMessageLoop();
	    }
	    /**
	     * Schedule a message loop cycle to process any pending messages.
	     *
	     * This is a no-op if a loop cycle is already pending.
	     */
	    function scheduleMessageLoop() {
	        if (!cyclePending) {
	            defer(runMessageLoop);
	            cyclePending = true;
	        }
	    }
	    /**
	     * Run an iteration of the message loop.
	     *
	     * This will process all pending messages in the queue. If a message
	     * is added to the queue while the message loop is running, it will
	     * be processed on the next cycle of the loop.
	     */
	    function runMessageLoop() {
	        // Clear the pending flag so the next loop can be scheduled.
	        cyclePending = false;
	        // If the queue is empty, there is nothing else to do.
	        if (queue.isEmpty) {
	            return;
	        }
	        // Add a sentinel value to the end of the queue. The queue will
	        // only be processed up to the sentinel. Messages posted during
	        // this cycle will execute on the next cycle.
	        var sentinel = { handler: null, msg: null };
	        queue.pushBack(sentinel);
	        // Enter the message loop.
	        while (!queue.isEmpty) {
	            // Remove the first posted message in the queue.
	            var posted = queue.popFront();
	            // If the value is the sentinel, exit the loop.
	            if (posted === sentinel) {
	                return;
	            }
	            // Dispatch the message if the handler has not been cleared.
	            if (posted.handler !== null) {
	                sendMessage(posted.handler, posted.msg);
	            }
	        }
	    }
	})(MessageLoop || (MessageLoop = {}));
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('timers-browserify@2.0.2/main.js').setImmediate))
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/core/messaging.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/collections/queue.js **/
jupyter.define('phosphor@0.7.0/lib/collections/queue.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	/**
	 * A generic FIFO queue data structure.
	 */
	var Queue = (function () {
	    /**
	     * Construct a new queue.
	     *
	     * @param values - The initial values for the queue.
	     */
	    function Queue(values) {
	        var _this = this;
	        this._length = 0;
	        this._front = null;
	        this._back = null;
	        if (values)
	            iteration_1.each(values, function (value) { _this.pushBack(value); });
	    }
	    Object.defineProperty(Queue.prototype, "isEmpty", {
	        /**
	         * Test whether the queue is empty.
	         *
	         * @returns `true` if the queue is empty, `false` otherwise.
	         *
	         * #### Notes
	         * This is a read-only property.
	         *
	         * #### Complexity
	         * Constant.
	         *
	         * #### Iterator Validity
	         * No changes.
	         */
	        get: function () {
	            return this._length === 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Queue.prototype, "length", {
	        /**
	         * Get the length of the queue.
	         *
	         * @return The number of values in the queue.
	         *
	         * #### Notes
	         * This is a read-only property.
	         *
	         * #### Complexity
	         * Constant.
	         *
	         * #### Iterator Validity
	         * No changes.
	         */
	        get: function () {
	            return this._length;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Queue.prototype, "front", {
	        /**
	         * Get the value at the front of the queue.
	         *
	         * @returns The value at the front of the queue, or `undefined` if
	         *   the queue is empty.
	         *
	         * #### Notes
	         * This is a read-only property.
	         *
	         * #### Complexity
	         * Constant.
	         *
	         * #### Iterator Validity
	         * No changes.
	         */
	        get: function () {
	            return this._front ? this._front.value : void 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Queue.prototype, "back", {
	        /**
	         * Get the value at the back of the queue.
	         *
	         * @returns The value at the back of the queue, or `undefined` if
	         *   the queue is empty.
	         *
	         * #### Notes
	         * This is a read-only property.
	         *
	         * #### Complexity
	         * Constant.
	         *
	         * #### Iterator Validity
	         * No changes.
	         */
	        get: function () {
	            return this._back ? this._back.value : void 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over the values in the queue.
	     *
	     * @returns A new iterator starting at the front of the queue.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * No changes.
	     */
	    Queue.prototype.iter = function () {
	        return new QueueIterator(this._front);
	    };
	    /**
	     * Add a value to the back of the queue.
	     *
	     * @param value - The value to add to the back of the queue.
	     *
	     * @returns The new length of the queue.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * No changes.
	     */
	    Queue.prototype.pushBack = function (value) {
	        var node = new QueueNode(value);
	        if (this._length === 0) {
	            this._front = node;
	            this._back = node;
	        }
	        else {
	            this._back.next = node;
	            this._back = node;
	        }
	        return ++this._length;
	    };
	    /**
	     * Remove and return the value at the front of the queue.
	     *
	     * @returns The value at the front of the queue, or `undefined` if
	     *   the queue is empty.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * Iterators pointing at the removed value are invalidated.
	     */
	    Queue.prototype.popFront = function () {
	        if (this._length === 0) {
	            return void 0;
	        }
	        var node = this._front;
	        if (this._length === 1) {
	            this._front = null;
	            this._back = null;
	        }
	        else {
	            this._front = node.next;
	            node.next = null;
	        }
	        this._length--;
	        return node.value;
	    };
	    /**
	     * Remove all values from the queue.
	     *
	     * #### Complexity
	     * Linear.
	     *
	     * #### Iterator Validity
	     * All current iterators are invalidated.
	     */
	    Queue.prototype.clear = function () {
	        var node = this._front;
	        while (node) {
	            var next = node.next;
	            node.next = null;
	            node = next;
	        }
	        this._length = 0;
	        this._front = null;
	        this._back = null;
	    };
	    /**
	     * Swap the contents of the queue with the contents of another.
	     *
	     * @param other - The other queue holding the contents to swap.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * All current iterators remain valid, but will now point to the
	     * contents of the other queue involved in the swap.
	     */
	    Queue.prototype.swap = function (other) {
	        var length = other._length;
	        var front = other._front;
	        var back = other._back;
	        other._length = this._length;
	        other._front = this._front;
	        other._back = this._back;
	        this._length = length;
	        this._front = front;
	        this._back = back;
	    };
	    return Queue;
	}());
	exports.Queue = Queue;
	/**
	 * An iterator for a queue.
	 */
	var QueueIterator = (function () {
	    /**
	     * Construct a new queue iterator.
	     *
	     * @param node - The node at the front of range.
	     */
	    function QueueIterator(node) {
	        this._node = node;
	    }
	    /**
	     * Create an iterator over the object's values.
	     *
	     * @returns A reference to `this` iterator.
	     */
	    QueueIterator.prototype.iter = function () {
	        return this;
	    };
	    /**
	     * Create an independent clone of the queue iterator.
	     *
	     * @returns A new iterator starting with the current value.
	     */
	    QueueIterator.prototype.clone = function () {
	        return new QueueIterator(this._node);
	    };
	    /**
	     * Get the next value from the queue.
	     *
	     * @returns The next value from the queue, or `undefined` if the
	     *   iterator is exhausted.
	     */
	    QueueIterator.prototype.next = function () {
	        if (!this._node) {
	            return void 0;
	        }
	        var value = this._node.value;
	        this._node = this._node.next;
	        return value;
	    };
	    return QueueIterator;
	}());
	/**
	 * The node type for a queue.
	 */
	var QueueNode = (function () {
	    /**
	     * Construct a new queue node.
	     *
	     * @param value - The value for the node.
	     */
	    function QueueNode(value) {
	        /**
	         * The next node the queue.
	         */
	        this.next = null;
	        this.value = value;
	    }
	    return QueueNode;
	}());
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/collections/queue.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/core/properties.js **/
jupyter.define('phosphor@0.7.0/lib/core/properties.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * A class which attaches a value to an external object.
	 *
	 * #### Notes
	 * Attached properties are used to extend the state of an object with
	 * semantic data from an unrelated class. They also encapsulate value
	 * creation, coercion, and notification.
	 *
	 * Because attached property values are stored in a hash table, which
	 * in turn is stored in a WeakMap keyed on the owner object, there is
	 * non-trivial storage overhead involved in their use. The pattern is
	 * therefore best used for the storage of rare data.
	 */
	var AttachedProperty = (function () {
	    /**
	     * Construct a new attached property.
	     *
	     * @param options - The options for initializing the property.
	     */
	    function AttachedProperty(options) {
	        this._pid = nextPID();
	        this._name = options.name;
	        this._value = options.value;
	        this._create = options.create;
	        this._coerce = options.coerce;
	        this._compare = options.compare;
	        this._changed = options.changed;
	    }
	    Object.defineProperty(AttachedProperty.prototype, "name", {
	        /**
	         * Get the human readable name for the property.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._name;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Get the current value of the property for a given owner.
	     *
	     * @param owner - The property owner of interest.
	     *
	     * @returns The current value of the property.
	     *
	     * #### Notes
	     * If the value has not yet been set, the default value will be
	     * computed and assigned as the current value of the property.
	     */
	    AttachedProperty.prototype.get = function (owner) {
	        var value;
	        var map = ensureMap(owner);
	        if (this._pid in map) {
	            value = map[this._pid];
	        }
	        else {
	            value = map[this._pid] = this._createValue(owner);
	        }
	        return value;
	    };
	    /**
	     * Set the current value of the property for a given owner.
	     *
	     * @param owner - The property owner of interest.
	     *
	     * @param value - The value for the property.
	     *
	     * #### Notes
	     * If the value has not yet been set, the default value will be
	     * computed and used as the previous value for the comparison.
	     */
	    AttachedProperty.prototype.set = function (owner, value) {
	        var oldValue;
	        var map = ensureMap(owner);
	        if (this._pid in map) {
	            oldValue = map[this._pid];
	        }
	        else {
	            oldValue = map[this._pid] = this._createValue(owner);
	        }
	        var newValue = this._coerceValue(owner, value);
	        this._maybeNotify(owner, oldValue, map[this._pid] = newValue);
	    };
	    /**
	     * Explicitly coerce the current property value for a given owner.
	     *
	     * @param owner - The property owner of interest.
	     *
	     * #### Notes
	     * If the value has not yet been set, the default value will be
	     * computed and used as the previous value for the comparison.
	     */
	    AttachedProperty.prototype.coerce = function (owner) {
	        var oldValue;
	        var map = ensureMap(owner);
	        if (this._pid in map) {
	            oldValue = map[this._pid];
	        }
	        else {
	            oldValue = map[this._pid] = this._createValue(owner);
	        }
	        var newValue = this._coerceValue(owner, oldValue);
	        this._maybeNotify(owner, oldValue, map[this._pid] = newValue);
	    };
	    /**
	     * Get or create the default value for the given owner.
	     */
	    AttachedProperty.prototype._createValue = function (owner) {
	        var create = this._create;
	        return create ? create(owner) : this._value;
	    };
	    /**
	     * Coerce the value for the given owner.
	     */
	    AttachedProperty.prototype._coerceValue = function (owner, value) {
	        var coerce = this._coerce;
	        return coerce ? coerce(owner, value) : value;
	    };
	    /**
	     * Compare the old value and new value for equality.
	     */
	    AttachedProperty.prototype._compareValue = function (oldValue, newValue) {
	        var compare = this._compare;
	        return compare ? compare(oldValue, newValue) : oldValue === newValue;
	    };
	    /**
	     * Run the change notification if the given values are different.
	     */
	    AttachedProperty.prototype._maybeNotify = function (owner, oldValue, newValue) {
	        if (!this._changed || this._compareValue(oldValue, newValue)) {
	            return;
	        }
	        this._changed.call(void 0, owner, oldValue, newValue);
	    };
	    return AttachedProperty;
	}());
	exports.AttachedProperty = AttachedProperty;
	/**
	 * Clear the stored property data for the given property owner.
	 *
	 * @param owner - The property owner of interest.
	 *
	 * #### Notes
	 * This will clear all property values for the owner, but it will
	 * **not** run the change notification for any of the properties.
	 */
	function clearPropertyData(owner) {
	    ownerData.delete(owner);
	}
	exports.clearPropertyData = clearPropertyData;
	/**
	 * A weak mapping of property owner to property map.
	 */
	var ownerData = new WeakMap();
	/**
	 * A function which computes successive unique property ids.
	 */
	var nextPID = (function () {
	    var id = 0;
	    return function () {
	        var rand = Math.random();
	        var stem = ("" + rand).slice(2);
	        return "pid-" + stem + "-" + id++;
	    };
	})();
	/**
	 * Lookup the data map for the property owner.
	 *
	 * This will create the map if one does not already exist.
	 */
	function ensureMap(owner) {
	    var map = ownerData.get(owner);
	    if (map !== void 0)
	        return map;
	    map = Object.create(null);
	    ownerData.set(owner, map);
	    return map;
	}
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/core/properties.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/title.js **/
jupyter.define('phosphor@0.7.0/lib/ui/title.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	/**
	 * An object which holds data related to a widget's title.
	 *
	 * #### Notes
	 * A title object is intended to hold the data necessary to display a
	 * header for a particular widget. A common example is the `TabPanel`,
	 * which uses the widget title to populate the tab for a child widget.
	 */
	var Title = (function () {
	    /**
	     * Construct a new title.
	     *
	     * @param options - The options for initializing the title.
	     */
	    function Title(options) {
	        if (options === void 0) { options = {}; }
	        this._label = '';
	        this._icon = '';
	        this._caption = '';
	        this._mnemonic = -1;
	        this._className = '';
	        this._closable = false;
	        this._owner = null;
	        if (options.owner !== void 0) {
	            this._owner = options.owner;
	        }
	        if (options.label !== void 0) {
	            this._label = options.label;
	        }
	        if (options.mnemonic !== void 0) {
	            this._mnemonic = options.mnemonic;
	        }
	        if (options.icon !== void 0) {
	            this._icon = options.icon;
	        }
	        if (options.caption !== void 0) {
	            this._caption = options.caption;
	        }
	        if (options.closable !== void 0) {
	            this._closable = options.closable;
	        }
	        if (options.className !== void 0) {
	            this._className = options.className;
	        }
	    }
	    Object.defineProperty(Title.prototype, "owner", {
	        /**
	         * Get the object which owns the title.
	         *
	         * #### Notes
	         * This will be `null` if the title has no owner.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._owner;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Title.prototype, "label", {
	        /**
	         * Get the label for the title.
	         *
	         * #### Notes
	         * The default value is an empty string.
	         */
	        get: function () {
	            return this._label;
	        },
	        /**
	         * Set the label for the title.
	         */
	        set: function (value) {
	            if (this._label === value) {
	                return;
	            }
	            this._label = value;
	            this.changed.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Title.prototype, "mnemonic", {
	        /**
	         * Get the mnemonic index for the title.
	         *
	         * #### Notes
	         * The default value is `-1`.
	         */
	        get: function () {
	            return this._mnemonic;
	        },
	        /**
	         * Set the mnemonic index for the title.
	         */
	        set: function (value) {
	            if (this._mnemonic === value) {
	                return;
	            }
	            this._mnemonic = value;
	            this.changed.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Title.prototype, "icon", {
	        /**
	         * Get the icon class name for the title.
	         *
	         * #### Notes
	         * The default value is an empty string.
	         */
	        get: function () {
	            return this._icon;
	        },
	        /**
	         * Set the icon class name for the title.
	         *
	         * #### Notes
	         * Multiple class names can be separated with whitespace.
	         */
	        set: function (value) {
	            if (this._icon === value) {
	                return;
	            }
	            this._icon = value;
	            this.changed.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Title.prototype, "caption", {
	        /**
	         * Get the caption for the title.
	         *
	         * #### Notes
	         * The default value is an empty string.
	         */
	        get: function () {
	            return this._caption;
	        },
	        /**
	         * Set the caption for the title.
	         */
	        set: function (value) {
	            if (this._caption === value) {
	                return;
	            }
	            this._caption = value;
	            this.changed.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Title.prototype, "className", {
	        /**
	         * Get the extra class name for the title.
	         *
	         * #### Notes
	         * The default value is an empty string.
	         */
	        get: function () {
	            return this._className;
	        },
	        /**
	         * Set the extra class name for the title.
	         *
	         * #### Notes
	         * Multiple class names can be separated with whitespace.
	         */
	        set: function (value) {
	            if (this._className === value) {
	                return;
	            }
	            this._className = value;
	            this.changed.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Title.prototype, "closable", {
	        /**
	         * Get the closable state for the title.
	         *
	         * #### Notes
	         * The default value is `false`.
	         */
	        get: function () {
	            return this._closable;
	        },
	        /**
	         * Set the closable state for the title.
	         *
	         * #### Notes
	         * This controls the presence of a close icon when applicable.
	         */
	        set: function (value) {
	            if (this._closable === value) {
	                return;
	            }
	            this._closable = value;
	            this.changed.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return Title;
	}());
	exports.Title = Title;
	// Define the signals for the `Title` class.
	signaling_1.defineSignal(Title.prototype, 'changed');
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/title.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/application/shell.js **/
jupyter.define('jupyterlab@0.15.1/lib/application/shell.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var boxpanel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/boxpanel.js');
	var dockpanel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/dockpanel.js');
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var splitpanel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/splitpanel.js');
	var stackedpanel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/stackedpanel.js');
	var tabbar_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/tabbar.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to AppShell instances.
	 */
	var APPLICATION_SHELL_CLASS = 'jp-ApplicationShell';
	/**
	 * The class name added to side bar instances.
	 */
	var SIDEBAR_CLASS = 'jp-SideBar';
	/**
	 * The class name added to the current widget's title.
	 */
	var CURRENT_CLASS = 'jp-mod-current';
	/**
	 * The application shell for JupyterLab.
	 */
	var ApplicationShell = (function (_super) {
	    __extends(ApplicationShell, _super);
	    /**
	     * Construct a new application shell.
	     */
	    function ApplicationShell() {
	        _super.call(this);
	        this._database = null;
	        this._isRestored = false;
	        this._restored = new services_1.utils.PromiseDelegate();
	        this.addClass(APPLICATION_SHELL_CLASS);
	        this.id = 'main';
	        var topPanel = this._topPanel = new panel_1.Panel();
	        var hboxPanel = this._hboxPanel = new boxpanel_1.BoxPanel();
	        var dockPanel = this._dockPanel = new dockpanel_1.DockPanel();
	        var hsplitPanel = this._hsplitPanel = new splitpanel_1.SplitPanel();
	        var leftHandler = this._leftHandler = new Private.SideBarHandler('left');
	        var rightHandler = this._rightHandler = new Private.SideBarHandler('right');
	        var rootLayout = new boxpanel_1.BoxLayout();
	        topPanel.id = 'jp-top-panel';
	        hboxPanel.id = 'jp-main-content-panel';
	        dockPanel.id = 'jp-main-dock-panel';
	        hsplitPanel.id = 'jp-main-split-panel';
	        leftHandler.sideBar.addClass(SIDEBAR_CLASS);
	        leftHandler.sideBar.addClass('jp-mod-left');
	        leftHandler.stackedPanel.id = 'jp-left-stack';
	        rightHandler.sideBar.addClass(SIDEBAR_CLASS);
	        rightHandler.sideBar.addClass('jp-mod-right');
	        rightHandler.stackedPanel.id = 'jp-right-stack';
	        hboxPanel.spacing = 0;
	        dockPanel.spacing = 5;
	        hsplitPanel.spacing = 1;
	        hboxPanel.direction = 'left-to-right';
	        hsplitPanel.orientation = 'horizontal';
	        splitpanel_1.SplitPanel.setStretch(leftHandler.stackedPanel, 0);
	        splitpanel_1.SplitPanel.setStretch(dockPanel, 1);
	        splitpanel_1.SplitPanel.setStretch(rightHandler.stackedPanel, 0);
	        boxpanel_1.BoxPanel.setStretch(leftHandler.sideBar, 0);
	        boxpanel_1.BoxPanel.setStretch(hsplitPanel, 1);
	        boxpanel_1.BoxPanel.setStretch(rightHandler.sideBar, 0);
	        hsplitPanel.addWidget(leftHandler.stackedPanel);
	        hsplitPanel.addWidget(dockPanel);
	        hsplitPanel.addWidget(rightHandler.stackedPanel);
	        hboxPanel.addWidget(leftHandler.sideBar);
	        hboxPanel.addWidget(hsplitPanel);
	        hboxPanel.addWidget(rightHandler.sideBar);
	        rootLayout.direction = 'top-to-bottom';
	        rootLayout.spacing = 0; // TODO make this configurable?
	        boxpanel_1.BoxLayout.setStretch(topPanel, 0);
	        boxpanel_1.BoxLayout.setStretch(hboxPanel, 1);
	        rootLayout.addWidget(topPanel);
	        rootLayout.addWidget(hboxPanel);
	        this.layout = rootLayout;
	        this._dockPanel.currentChanged.connect(this._onCurrentChanged, this);
	    }
	    Object.defineProperty(ApplicationShell.prototype, "currentWidget", {
	        /**
	         * The current widget in the shell's main area.
	         */
	        get: function () {
	            return this._dockPanel.currentWidget;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ApplicationShell.prototype, "restored", {
	        /**
	         * Promise that resolves when state is restored, returning layout description.
	         */
	        get: function () {
	            return this._restored.promise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ApplicationShell.prototype, "mainAreaIsEmpty", {
	        /**
	         * True if main area is empty.
	         */
	        get: function () {
	            return this._dockPanel.isEmpty;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ApplicationShell.prototype, "topAreaIsEmpty", {
	        /**
	         * True if top area is empty.
	         */
	        get: function () {
	            return this._topPanel.widgets.length === 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ApplicationShell.prototype, "leftAreaIsEmpty", {
	        /**
	         * True if left area is empty.
	         */
	        get: function () {
	            return this._leftHandler.stackedPanel.widgets.length === 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ApplicationShell.prototype, "rightAreaIsEmpty", {
	        /**
	         * True if right area is empty.
	         */
	        get: function () {
	            return this._rightHandler.stackedPanel.widgets.length === 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a widget to the top content area.
	     *
	     * #### Notes
	     * Widgets must have a unique `id` property, which will be used as the DOM id.
	     */
	    ApplicationShell.prototype.addToTopArea = function (widget, options) {
	        if (options === void 0) { options = {}; }
	        if (!widget.id) {
	            console.error('widgets added to app shell must have unique id property');
	            return;
	        }
	        // Temporary: widgets are added to the panel in order of insertion.
	        this._topPanel.addWidget(widget);
	        this._save();
	    };
	    /**
	     * Add a widget to the left content area.
	     *
	     * #### Notes
	     * Widgets must have a unique `id` property, which will be used as the DOM id.
	     */
	    ApplicationShell.prototype.addToLeftArea = function (widget, options) {
	        if (options === void 0) { options = {}; }
	        if (!widget.id) {
	            console.error('widgets added to app shell must have unique id property');
	            return;
	        }
	        var rank = 'rank' in options ? options.rank : 100;
	        this._leftHandler.addWidget(widget, rank);
	        this._save();
	    };
	    /**
	     * Add a widget to the right content area.
	     *
	     * #### Notes
	     * Widgets must have a unique `id` property, which will be used as the DOM id.
	     */
	    ApplicationShell.prototype.addToRightArea = function (widget, options) {
	        if (options === void 0) { options = {}; }
	        if (!widget.id) {
	            console.error('widgets added to app shell must have unique id property');
	            return;
	        }
	        var rank = 'rank' in options ? options.rank : 100;
	        this._rightHandler.addWidget(widget, rank);
	        this._save();
	    };
	    /**
	     * Add a widget to the main content area.
	     *
	     * #### Notes
	     * Widgets must have a unique `id` property, which will be used as the DOM id.
	     */
	    ApplicationShell.prototype.addToMainArea = function (widget) {
	        if (!widget.id) {
	            console.error('widgets added to app shell must have unique id property');
	            return;
	        }
	        this._dockPanel.addWidget(widget, { mode: 'tab-after' });
	        this._save();
	    };
	    /**
	     * Activate a widget in the left area.
	     */
	    ApplicationShell.prototype.activateLeft = function (id) {
	        this._leftHandler.activate(id);
	    };
	    /**
	     * Activate a widget in the right area.
	     */
	    ApplicationShell.prototype.activateRight = function (id) {
	        this._rightHandler.activate(id);
	    };
	    /**
	     * Activate a widget in the main area.
	     */
	    ApplicationShell.prototype.activateMain = function (id) {
	        var dock = this._dockPanel;
	        var widget = searching_1.find(dock.widgets(), function (value) { return value.id === id; });
	        if (widget) {
	            dock.activateWidget(widget);
	        }
	    };
	    /**
	     * Collapse the left area.
	     */
	    ApplicationShell.prototype.collapseLeft = function () {
	        this._leftHandler.collapse();
	        this._save();
	    };
	    /**
	     * Collapse the right area.
	     */
	    ApplicationShell.prototype.collapseRight = function () {
	        this._rightHandler.collapse();
	        this._save();
	    };
	    /**
	     * Close all widgets in the main area.
	     */
	    ApplicationShell.prototype.closeAll = function () {
	        iteration_1.each(iteration_1.toArray(this._dockPanel.widgets()), function (widget) { widget.close(); });
	        this._save();
	    };
	    /**
	     * Set the layout data store for the application shell.
	     */
	    ApplicationShell.prototype.setLayoutDB = function (database) {
	        var _this = this;
	        if (this._database) {
	            throw new Error('cannot reset layout database');
	        }
	        this._database = database;
	        this._database.fetch().then(function (saved) {
	            if (_this.isDisposed && !saved) {
	                return;
	            }
	            // Rehydrate the application.
	            var currentWidget = saved.currentWidget, leftArea = saved.leftArea, rightArea = saved.rightArea;
	            if (leftArea) {
	                _this._leftHandler.rehydrate(leftArea);
	            }
	            if (rightArea) {
	                _this._rightHandler.rehydrate(rightArea);
	            }
	            if (currentWidget) {
	                _this.activateMain(currentWidget.id);
	            }
	            _this._isRestored = true;
	            return _this._save().then(function () { _this._restored.resolve(saved); });
	        });
	        // Catch current changed events on the side handlers.
	        this._dockPanel.currentChanged.connect(this._save, this);
	        this._leftHandler.sideBar.currentChanged.connect(this._save, this);
	        this._rightHandler.sideBar.currentChanged.connect(this._save, this);
	    };
	    /**
	     * Save the dehydrated state of the application shell.
	     */
	    ApplicationShell.prototype._save = function () {
	        if (!this._database || !this._isRestored) {
	            return;
	        }
	        var data = {
	            currentWidget: this._dockPanel.currentWidget,
	            leftArea: this._leftHandler.dehydrate(),
	            rightArea: this._rightHandler.dehydrate()
	        };
	        return this._database.save(data);
	    };
	    /**
	     * Handle a change to the dock area current widget.
	     */
	    ApplicationShell.prototype._onCurrentChanged = function (sender, args) {
	        if (args.newValue) {
	            args.newValue.title.className += " " + CURRENT_CLASS;
	        }
	        if (args.oldValue) {
	            var title = args.oldValue.title;
	            title.className = title.className.replace(CURRENT_CLASS, '');
	        }
	        this.currentChanged.emit(args);
	    };
	    return ApplicationShell;
	}(widget_1.Widget));
	exports.ApplicationShell = ApplicationShell;
	// Define the signals for the `ApplicationShell` class.
	signaling_1.defineSignal(ApplicationShell.prototype, 'currentChanged');
	var Private;
	(function (Private) {
	    /**
	     * A less-than comparison function for side bar rank items.
	     */
	    function itemCmp(first, second) {
	        return first.rank - second.rank;
	    }
	    Private.itemCmp = itemCmp;
	    /**
	     * A class which manages a side bar and related stacked panel.
	     */
	    var SideBarHandler = (function () {
	        /**
	         * Construct a new side bar handler.
	         */
	        function SideBarHandler(side) {
	            this._items = new vector_1.Vector();
	            this._side = side;
	            this._sideBar = new tabbar_1.TabBar({
	                insertBehavior: 'none',
	                removeBehavior: 'none',
	                allowDeselect: true
	            });
	            this._stackedPanel = new stackedpanel_1.StackedPanel();
	            this._sideBar.hide();
	            this._stackedPanel.hide();
	            this._sideBar.currentChanged.connect(this._onCurrentChanged, this);
	            this._stackedPanel.widgetRemoved.connect(this._onWidgetRemoved, this);
	        }
	        Object.defineProperty(SideBarHandler.prototype, "sideBar", {
	            /**
	             * Get the tab bar managed by the handler.
	             */
	            get: function () {
	                return this._sideBar;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(SideBarHandler.prototype, "stackedPanel", {
	            /**
	             * Get the stacked panel managed by the handler
	             */
	            get: function () {
	                return this._stackedPanel;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        /**
	         * Activate a widget residing in the side bar by ID.
	         *
	         * @param id - The widget's unique ID.
	         */
	        SideBarHandler.prototype.activate = function (id) {
	            var widget = this._findWidgetByID(id);
	            if (widget) {
	                this._sideBar.currentTitle = widget.title;
	                widget.activate();
	            }
	        };
	        /**
	         * Collapse the sidebar so no items are expanded.
	         */
	        SideBarHandler.prototype.collapse = function () {
	            this._sideBar.currentTitle = null;
	        };
	        /**
	         * Add a widget and its title to the stacked panel and side bar.
	         *
	         * If the widget is already added, it will be moved.
	         */
	        SideBarHandler.prototype.addWidget = function (widget, rank) {
	            widget.parent = null;
	            widget.hide();
	            var item = { widget: widget, rank: rank };
	            var index = this._findInsertIndex(item);
	            this._items.insert(index, item);
	            this._stackedPanel.insertWidget(index, widget);
	            this._sideBar.insertTab(index, widget.title);
	            this._refreshVisibility();
	        };
	        /**
	         * Dehydrate the side bar data.
	         */
	        SideBarHandler.prototype.dehydrate = function () {
	            var collapsed = this._sideBar.currentTitle === null;
	            var widgets = iteration_1.toArray(this._stackedPanel.widgets);
	            var currentWidget = widgets[this._sideBar.currentIndex];
	            return { collapsed: collapsed, currentWidget: currentWidget, widgets: widgets };
	        };
	        /**
	         * Rehydrate the side bar.
	         */
	        SideBarHandler.prototype.rehydrate = function (data) {
	            if (data.currentWidget) {
	                this.activate(data.currentWidget.id);
	            }
	            else if (data.collapsed) {
	                this.collapse();
	            }
	        };
	        /**
	         * Find the insertion index for a rank item.
	         */
	        SideBarHandler.prototype._findInsertIndex = function (item) {
	            return searching_1.upperBound(this._items, item, Private.itemCmp);
	        };
	        /**
	         * Find the index of the item with the given widget, or `-1`.
	         */
	        SideBarHandler.prototype._findWidgetIndex = function (widget) {
	            return searching_1.findIndex(this._items, function (item) { return item.widget === widget; });
	        };
	        /**
	         * Find the widget which owns the given title, or `null`.
	         */
	        SideBarHandler.prototype._findWidgetByTitle = function (title) {
	            var item = searching_1.find(this._items, function (value) { return value.widget.title === title; });
	            return item ? item.widget : null;
	        };
	        /**
	         * Find the widget with the given id, or `null`.
	         */
	        SideBarHandler.prototype._findWidgetByID = function (id) {
	            var item = searching_1.find(this._items, function (value) { return value.widget.id === id; });
	            return item ? item.widget : null;
	        };
	        /**
	         * Refresh the visibility of the side bar and stacked panel.
	         */
	        SideBarHandler.prototype._refreshVisibility = function () {
	            this._sideBar.setHidden(this._sideBar.titles.length === 0);
	            this._stackedPanel.setHidden(this._sideBar.currentTitle === null);
	        };
	        /**
	         * Handle the `currentChanged` signal from the sidebar.
	         */
	        SideBarHandler.prototype._onCurrentChanged = function (sender, args) {
	            var oldWidget = this._findWidgetByTitle(args.previousTitle);
	            var newWidget = this._findWidgetByTitle(args.currentTitle);
	            if (oldWidget) {
	                oldWidget.hide();
	            }
	            if (newWidget) {
	                newWidget.show();
	            }
	            if (newWidget) {
	                document.body.setAttribute("data-" + this._side + "Area", newWidget.id);
	            }
	            else {
	                document.body.removeAttribute("data-" + this._side + "Area");
	            }
	            this._refreshVisibility();
	        };
	        /*
	         * Handle the `widgetRemoved` signal from the stacked panel.
	         */
	        SideBarHandler.prototype._onWidgetRemoved = function (sender, widget) {
	            this._items.removeAt(this._findWidgetIndex(widget));
	            this._sideBar.removeTab(widget.title);
	            this._refreshVisibility();
	        };
	        return SideBarHandler;
	    }());
	    Private.SideBarHandler = SideBarHandler;
	})(Private || (Private = {}));
	//# sourceMappingURL=shell.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/application/shell.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/boxpanel.js **/
jupyter.define('phosphor@0.7.0/lib/ui/boxpanel.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var mutation_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/mutation.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var messaging_1 = __jupyter_require__('phosphor@0.7.0/lib/core/messaging.js');
	var properties_1 = __jupyter_require__('phosphor@0.7.0/lib/core/properties.js');
	var platform_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/platform.js');
	var sizing_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/sizing.js');
	var boxengine_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/boxengine.js');
	var panel_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to BoxPanel instances.
	 */
	var BOX_PANEL_CLASS = 'p-BoxPanel';
	/**
	 * The class name added to a BoxPanel child.
	 */
	var CHILD_CLASS = 'p-BoxPanel-child';
	/**
	 * The class name added to left-to-right box layout parents.
	 */
	var LEFT_TO_RIGHT_CLASS = 'p-mod-left-to-right';
	/**
	 * The class name added to right-to-left box layout parents.
	 */
	var RIGHT_TO_LEFT_CLASS = 'p-mod-right-to-left';
	/**
	 * The class name added to top-to-bottom box layout parents.
	 */
	var TOP_TO_BOTTOM_CLASS = 'p-mod-top-to-bottom';
	/**
	 * The class name added to bottom-to-top box layout parents.
	 */
	var BOTTOM_TO_TOP_CLASS = 'p-mod-bottom-to-top';
	/**
	 * A panel which arranges its widgets in a single row or column.
	 *
	 * #### Notes
	 * This class provides a convenience wrapper around a [[BoxLayout]].
	 */
	var BoxPanel = (function (_super) {
	    __extends(BoxPanel, _super);
	    /**
	     * Construct a new box panel.
	     *
	     * @param options - The options for initializing the box panel.
	     */
	    function BoxPanel(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this, { layout: Private.createLayout(options) });
	        this.addClass(BOX_PANEL_CLASS);
	    }
	    Object.defineProperty(BoxPanel.prototype, "direction", {
	        /**
	         * Get the layout direction for the box panel.
	         */
	        get: function () {
	            return this.layout.direction;
	        },
	        /**
	         * Set the layout direction for the box panel.
	         */
	        set: function (value) {
	            this.layout.direction = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(BoxPanel.prototype, "spacing", {
	        /**
	         * Get the inter-element spacing for the box panel.
	         */
	        get: function () {
	            return this.layout.spacing;
	        },
	        /**
	         * Set the inter-element spacing for the box panel.
	         */
	        set: function (value) {
	            this.layout.spacing = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * A message handler invoked on a `'child-added'` message.
	     */
	    BoxPanel.prototype.onChildAdded = function (msg) {
	        msg.child.addClass(CHILD_CLASS);
	    };
	    /**
	     * A message handler invoked on a `'child-removed'` message.
	     */
	    BoxPanel.prototype.onChildRemoved = function (msg) {
	        msg.child.removeClass(CHILD_CLASS);
	    };
	    return BoxPanel;
	}(panel_1.Panel));
	exports.BoxPanel = BoxPanel;
	/**
	 * The namespace for the `BoxPanel` class statics.
	 */
	var BoxPanel;
	(function (BoxPanel) {
	    /**
	     * Get the box panel stretch factor for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The box panel stretch factor for the widget.
	     */
	    function getStretch(widget) {
	        return BoxLayout.getStretch(widget);
	    }
	    BoxPanel.getStretch = getStretch;
	    /**
	     * Set the box panel stretch factor for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @param value - The value for the stretch factor.
	     */
	    function setStretch(widget, value) {
	        BoxLayout.setStretch(widget, value);
	    }
	    BoxPanel.setStretch = setStretch;
	    /**
	     * Get the box panel size basis for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The box panel size basis for the widget.
	     */
	    function getSizeBasis(widget) {
	        return BoxLayout.getSizeBasis(widget);
	    }
	    BoxPanel.getSizeBasis = getSizeBasis;
	    /**
	     * Set the box panel size basis for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @param value - The value for the size basis.
	     */
	    function setSizeBasis(widget, value) {
	        BoxLayout.setSizeBasis(widget, value);
	    }
	    BoxPanel.setSizeBasis = setSizeBasis;
	})(BoxPanel = exports.BoxPanel || (exports.BoxPanel = {}));
	/**
	 * A layout which arranges its widgets in a single row or column.
	 */
	var BoxLayout = (function (_super) {
	    __extends(BoxLayout, _super);
	    /**
	     * Construct a new box layout.
	     *
	     * @param options - The options for initializing the layout.
	     */
	    function BoxLayout(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this);
	        this._fixed = 0;
	        this._spacing = 4;
	        this._dirty = false;
	        this._box = null;
	        this._sizers = new vector_1.Vector();
	        this._direction = 'top-to-bottom';
	        if (options.direction !== void 0) {
	            this._direction = options.direction;
	        }
	        if (options.spacing !== void 0) {
	            this._spacing = Private.clampSpacing(options.spacing);
	        }
	    }
	    Object.defineProperty(BoxLayout.prototype, "direction", {
	        /**
	         * Get the layout direction for the box layout.
	         */
	        get: function () {
	            return this._direction;
	        },
	        /**
	         * Set the layout direction for the box layout.
	         */
	        set: function (value) {
	            if (this._direction === value) {
	                return;
	            }
	            this._direction = value;
	            if (!this.parent) {
	                return;
	            }
	            Private.toggleDirection(this.parent, value);
	            this.parent.fit();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(BoxLayout.prototype, "spacing", {
	        /**
	         * Get the inter-element spacing for the box layout.
	         */
	        get: function () {
	            return this._spacing;
	        },
	        /**
	         * Set the inter-element spacing for the box layout.
	         */
	        set: function (value) {
	            value = Private.clampSpacing(value);
	            if (this._spacing === value) {
	                return;
	            }
	            this._spacing = value;
	            if (!this.parent) {
	                return;
	            }
	            this.parent.fit();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Perform layout initialization which requires the parent widget.
	     */
	    BoxLayout.prototype.init = function () {
	        Private.toggleDirection(this.parent, this.direction);
	        _super.prototype.init.call(this);
	    };
	    /**
	     * Attach a widget to the parent's DOM node.
	     *
	     * @param index - The current index of the widget in the layout.
	     *
	     * @param widget - The widget to attach to the parent.
	     *
	     * #### Notes
	     * This is a reimplementation of the superclass method.
	     */
	    BoxLayout.prototype.attachWidget = function (index, widget) {
	        // Create and add a new sizer for the widget.
	        this._sizers.insert(index, new boxengine_1.BoxSizer());
	        // Prepare the layout geometry for the widget.
	        widget_1.Widget.prepareGeometry(widget);
	        // Add the widget's node to the parent.
	        this.parent.node.appendChild(widget.node);
	        // Send an `'after-attach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.AfterAttach);
	        // Post a fit request for the parent widget.
	        this.parent.fit();
	    };
	    /**
	     * Move a widget in the parent's DOM node.
	     *
	     * @param fromIndex - The previous index of the widget in the layout.
	     *
	     * @param toIndex - The current index of the widget in the layout.
	     *
	     * @param widget - The widget to move in the parent.
	     *
	     * #### Notes
	     * This is a reimplementation of the superclass method.
	     */
	    BoxLayout.prototype.moveWidget = function (fromIndex, toIndex, widget) {
	        // Move the sizer for the widget.
	        mutation_1.move(this._sizers, fromIndex, toIndex);
	        // Post an update request for the parent widget.
	        this.parent.update();
	    };
	    /**
	     * Detach a widget from the parent's DOM node.
	     *
	     * @param index - The previous index of the widget in the layout.
	     *
	     * @param widget - The widget to detach from the parent.
	     *
	     * #### Notes
	     * This is a reimplementation of the superclass method.
	     */
	    BoxLayout.prototype.detachWidget = function (index, widget) {
	        // Remove the sizer for the widget.
	        this._sizers.removeAt(index);
	        // Send a `'before-detach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.BeforeDetach);
	        // Remove the widget's node from the parent.
	        this.parent.node.removeChild(widget.node);
	        // Reset the layout geometry for the widget.
	        widget_1.Widget.resetGeometry(widget);
	        // Post a fit request for the parent widget.
	        this.parent.fit();
	    };
	    /**
	     * A message handler invoked on an `'after-show'` message.
	     */
	    BoxLayout.prototype.onAfterShow = function (msg) {
	        _super.prototype.onAfterShow.call(this, msg);
	        this.parent.update();
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    BoxLayout.prototype.onAfterAttach = function (msg) {
	        _super.prototype.onAfterAttach.call(this, msg);
	        this.parent.fit();
	    };
	    /**
	     * A message handler invoked on a `'child-shown'` message.
	     */
	    BoxLayout.prototype.onChildShown = function (msg) {
	        if (platform_1.IS_IE || platform_1.IS_EDGE) {
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.FitRequest);
	        }
	        else {
	            this.parent.fit();
	        }
	    };
	    /**
	     * A message handler invoked on a `'child-hidden'` message.
	     */
	    BoxLayout.prototype.onChildHidden = function (msg) {
	        if (platform_1.IS_IE || platform_1.IS_EDGE) {
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.FitRequest);
	        }
	        else {
	            this.parent.fit();
	        }
	    };
	    /**
	     * A message handler invoked on a `'resize'` message.
	     */
	    BoxLayout.prototype.onResize = function (msg) {
	        if (this.parent.isVisible) {
	            this._update(msg.width, msg.height);
	        }
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    BoxLayout.prototype.onUpdateRequest = function (msg) {
	        if (this.parent.isVisible) {
	            this._update(-1, -1);
	        }
	    };
	    /**
	     * A message handler invoked on a `'fit-request'` message.
	     */
	    BoxLayout.prototype.onFitRequest = function (msg) {
	        if (this.parent.isAttached) {
	            this._fit();
	        }
	    };
	    /**
	     * Fit the layout to the total size required by the widgets.
	     */
	    BoxLayout.prototype._fit = function () {
	        // Compute the visible item count.
	        var nVisible = 0;
	        var widgets = this.widgets;
	        for (var i = 0, n = widgets.length; i < n; ++i) {
	            if (!widgets.at(i).isHidden)
	                nVisible++;
	        }
	        // Update the fixed space for the visible items.
	        this._fixed = this._spacing * Math.max(0, nVisible - 1);
	        // Setup the initial size limits.
	        var minW = 0;
	        var minH = 0;
	        var maxW = Infinity;
	        var maxH = Infinity;
	        var horz = Private.isHorizontal(this._direction);
	        if (horz) {
	            minW = this._fixed;
	            maxW = nVisible > 0 ? minW : maxW;
	        }
	        else {
	            minH = this._fixed;
	            maxH = nVisible > 0 ? minH : maxH;
	        }
	        // Update the sizers and computed size limits.
	        for (var i = 0, n = widgets.length; i < n; ++i) {
	            var widget = widgets.at(i);
	            var sizer = this._sizers.at(i);
	            if (widget.isHidden) {
	                sizer.minSize = 0;
	                sizer.maxSize = 0;
	                continue;
	            }
	            var limits = sizing_1.sizeLimits(widget.node);
	            sizer.sizeHint = BoxLayout.getSizeBasis(widget);
	            sizer.stretch = BoxLayout.getStretch(widget);
	            if (horz) {
	                sizer.minSize = limits.minWidth;
	                sizer.maxSize = limits.maxWidth;
	                minW += limits.minWidth;
	                maxW += limits.maxWidth;
	                minH = Math.max(minH, limits.minHeight);
	                maxH = Math.min(maxH, limits.maxHeight);
	            }
	            else {
	                sizer.minSize = limits.minHeight;
	                sizer.maxSize = limits.maxHeight;
	                minH += limits.minHeight;
	                maxH += limits.maxHeight;
	                minW = Math.max(minW, limits.minWidth);
	                maxW = Math.min(maxW, limits.maxWidth);
	            }
	        }
	        // Update the box sizing and add it to the size constraints.
	        var box = this._box = sizing_1.boxSizing(this.parent.node);
	        minW += box.horizontalSum;
	        minH += box.verticalSum;
	        maxW += box.horizontalSum;
	        maxH += box.verticalSum;
	        // Update the parent's size constraints.
	        var style = this.parent.node.style;
	        style.minWidth = minW + "px";
	        style.minHeight = minH + "px";
	        style.maxWidth = maxW === Infinity ? 'none' : maxW + "px";
	        style.maxHeight = maxH === Infinity ? 'none' : maxH + "px";
	        // Set the dirty flag to ensure only a single update occurs.
	        this._dirty = true;
	        // Notify the ancestor that it should fit immediately. This may
	        // cause a resize of the parent, fulfilling the required update.
	        var ancestor = this.parent.parent;
	        if (ancestor)
	            messaging_1.sendMessage(ancestor, widget_1.WidgetMessage.FitRequest);
	        // If the dirty flag is still set, the parent was not resized.
	        // Trigger the required update on the parent widget immediately.
	        if (this._dirty)
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.UpdateRequest);
	    };
	    /**
	     * Update the layout position and size of the widgets.
	     *
	     * The parent offset dimensions should be `-1` if unknown.
	     */
	    BoxLayout.prototype._update = function (offsetWidth, offsetHeight) {
	        // Clear the dirty flag to indicate the update occurred.
	        this._dirty = false;
	        // Bail early if there are no widgets to layout.
	        var widgets = this.widgets;
	        if (widgets.length === 0) {
	            return;
	        }
	        // Measure the parent if the offset dimensions are unknown.
	        if (offsetWidth < 0) {
	            offsetWidth = this.parent.node.offsetWidth;
	        }
	        if (offsetHeight < 0) {
	            offsetHeight = this.parent.node.offsetHeight;
	        }
	        // Ensure the parent box sizing data is computed.
	        var box = this._box || (this._box = sizing_1.boxSizing(this.parent.node));
	        // Compute the layout area adjusted for border and padding.
	        var top = box.paddingTop;
	        var left = box.paddingLeft;
	        var width = offsetWidth - box.horizontalSum;
	        var height = offsetHeight - box.verticalSum;
	        // Distribute the layout space and adjust the start position.
	        switch (this._direction) {
	            case 'left-to-right':
	                boxengine_1.boxCalc(this._sizers, Math.max(0, width - this._fixed));
	                break;
	            case 'top-to-bottom':
	                boxengine_1.boxCalc(this._sizers, Math.max(0, height - this._fixed));
	                break;
	            case 'right-to-left':
	                boxengine_1.boxCalc(this._sizers, Math.max(0, width - this._fixed));
	                left += width;
	                break;
	            case 'bottom-to-top':
	                boxengine_1.boxCalc(this._sizers, Math.max(0, height - this._fixed));
	                top += height;
	                break;
	        }
	        // Layout the widgets using the computed box sizes.
	        for (var i = 0, n = widgets.length; i < n; ++i) {
	            var widget = widgets.at(i);
	            if (widget.isHidden) {
	                continue;
	            }
	            var size = this._sizers.at(i).size;
	            switch (this._direction) {
	                case 'left-to-right':
	                    widget_1.Widget.setGeometry(widget, left, top, size, height);
	                    left += size + this._spacing;
	                    break;
	                case 'top-to-bottom':
	                    widget_1.Widget.setGeometry(widget, left, top, width, size);
	                    top += size + this._spacing;
	                    break;
	                case 'right-to-left':
	                    widget_1.Widget.setGeometry(widget, left - size, top, size, height);
	                    left -= size + this._spacing;
	                    break;
	                case 'bottom-to-top':
	                    widget_1.Widget.setGeometry(widget, left, top - size, width, size);
	                    top -= size + this._spacing;
	                    break;
	            }
	        }
	    };
	    return BoxLayout;
	}(panel_1.PanelLayout));
	exports.BoxLayout = BoxLayout;
	/**
	 * The namespace for the `BoxLayout` class statics.
	 */
	var BoxLayout;
	(function (BoxLayout) {
	    /**
	     * Get the box layout stretch factor for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The box layout stretch factor for the widget.
	     */
	    function getStretch(widget) {
	        return Private.stretchProperty.get(widget);
	    }
	    BoxLayout.getStretch = getStretch;
	    /**
	     * Set the box layout stretch factor for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @param value - The value for the stretch factor.
	     */
	    function setStretch(widget, value) {
	        Private.stretchProperty.set(widget, value);
	    }
	    BoxLayout.setStretch = setStretch;
	    /**
	     * Get the box layout size basis for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The box layout size basis for the widget.
	     */
	    function getSizeBasis(widget) {
	        return Private.sizeBasisProperty.get(widget);
	    }
	    BoxLayout.getSizeBasis = getSizeBasis;
	    /**
	     * Set the box layout size basis for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @param value - The value for the size basis.
	     */
	    function setSizeBasis(widget, value) {
	        Private.sizeBasisProperty.set(widget, value);
	    }
	    BoxLayout.setSizeBasis = setSizeBasis;
	})(BoxLayout = exports.BoxLayout || (exports.BoxLayout = {}));
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * The property descriptor for a widget stretch factor.
	     */
	    Private.stretchProperty = new properties_1.AttachedProperty({
	        name: 'stretch',
	        value: 0,
	        coerce: function (owner, value) { return Math.max(0, Math.floor(value)); },
	        changed: onChildPropertyChanged
	    });
	    /**
	     * The property descriptor for a widget size basis.
	     */
	    Private.sizeBasisProperty = new properties_1.AttachedProperty({
	        name: 'sizeBasis',
	        value: 0,
	        coerce: function (owner, value) { return Math.max(0, Math.floor(value)); },
	        changed: onChildPropertyChanged
	    });
	    /**
	     * Create a box layout for the given panel options.
	     */
	    function createLayout(options) {
	        return options.layout || new BoxLayout(options);
	    }
	    Private.createLayout = createLayout;
	    /**
	     * Test whether a direction has horizontal orientation.
	     */
	    function isHorizontal(dir) {
	        return dir === 'left-to-right' || dir === 'right-to-left';
	    }
	    Private.isHorizontal = isHorizontal;
	    /**
	     * Toggle the CSS direction class for the given widget.
	     */
	    function toggleDirection(widget, dir) {
	        widget.toggleClass(LEFT_TO_RIGHT_CLASS, dir === 'left-to-right');
	        widget.toggleClass(RIGHT_TO_LEFT_CLASS, dir === 'right-to-left');
	        widget.toggleClass(TOP_TO_BOTTOM_CLASS, dir === 'top-to-bottom');
	        widget.toggleClass(BOTTOM_TO_TOP_CLASS, dir === 'bottom-to-top');
	    }
	    Private.toggleDirection = toggleDirection;
	    /**
	     * Clamp a spacing value to an integer >= 0.
	     */
	    function clampSpacing(value) {
	        return Math.max(0, Math.floor(value));
	    }
	    Private.clampSpacing = clampSpacing;
	    /**
	     * The change handler for the attached child properties.
	     */
	    function onChildPropertyChanged(child) {
	        var parent = child.parent;
	        var layout = parent && parent.layout;
	        if (layout instanceof BoxLayout)
	            parent.fit();
	    }
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/boxpanel.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/mutation.js **/
jupyter.define('phosphor@0.7.0/lib/algorithm/mutation.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var sequence_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/sequence.js');
	/**
	 * Move an element in a sequence from one index to another.
	 *
	 * @param object - The sequence or array-like object to mutate.
	 *
	 * @param fromIndex - The index of the element to move.
	 *
	 * @param toIndex - The target index of the element.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Undefined Behavior
	 * A `fromIndex` which is non-integral or out of range.
	 *
	 * A `toIndex` which is non-integral or out of range.
	 *
	 * #### Example
	 * ```typescript
	 * import { move } from 'phosphor/lib/algorithm/mutation';
	 *
	 * let data = [0, 1, 2, 3, 4];
	 * move(data, 1, 2);  // [0, 2, 1, 3, 4]
	 * move(data, 4, 2);  // [0, 2, 4, 1, 3]
	 * ```
	 */
	function move(object, fromIndex, toIndex) {
	    if (object.length <= 1 || fromIndex === toIndex) {
	        return;
	    }
	    var d = fromIndex < toIndex ? 1 : -1;
	    var seq = sequence_1.asMutableSequence(object);
	    var value = seq.at(fromIndex);
	    for (var i = fromIndex; i !== toIndex; i += d) {
	        seq.set(i, seq.at(i + d));
	    }
	    seq.set(toIndex, value);
	}
	exports.move = move;
	/**
	 * Reverse a sequence in-place subject to an optional range.
	 *
	 * @param object - The sequence or array-like object to mutate.
	 *
	 * @param first - The index of the first element of the range. This
	 *   should be `<=` the `last` index. The default is `0`.
	 *
	 * @param last - The index of the last element of the range. This
	 *   should be `>=` the `first` index. The default is `length - 1`.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Undefined Behavior
	 * A `first` index which is non-integral or out of range.
	 *
	 * A `last` index which is non-integral or out of range.
	 *
	 * #### Example
	 * ```typescript
	 * import { reverse } from 'phosphor/lib/algorithm/mutation';
	 *
	 * let data = [0, 1, 2, 3, 4];
	 * reverse(data, 1, 3);  // [0, 3, 2, 1, 4]
	 * reverse(data, 3);     // [0, 3, 2, 4, 1]
	 * reverse(data);        // [1, 4, 2, 3, 0]
	 * ```
	 */
	function reverse(object, first, last) {
	    var length = object.length;
	    if (length <= 1) {
	        return;
	    }
	    if (first === void 0) {
	        first = 0;
	    }
	    if (last === void 0) {
	        last = length - 1;
	    }
	    if (first >= last) {
	        return;
	    }
	    var seq = sequence_1.asMutableSequence(object);
	    while (first < last) {
	        var front = seq.at(first);
	        var back = seq.at(last);
	        seq.set(first++, back);
	        seq.set(last--, front);
	    }
	}
	exports.reverse = reverse;
	/**
	 * Rotate the elements of a sequence by a positive or negative amount.
	 *
	 * @param object - The sequence or array-like object to mutate.
	 *
	 * @param delta - The amount of rotation to apply to the elements. A
	 *   positive value will rotate the elements to the left. A negative
	 *   value will rotate the elements to the right.
	 *
	 * #### Complexity
	 * Linear.
	 *
	 * #### Undefined Behavior
	 * A `delta` amount which is non-integral.
	 *
	 * #### Example
	 * ```typescript
	 * import { rotate } from 'phosphor/lib/algorithm/mutation';
	 *
	 * let data = [0, 1, 2, 3, 4];
	 * rotate(data, 2);   // [2, 3, 4, 0, 1]
	 * rotate(data, -2);  // [0, 1, 2, 3, 4]
	 * rotate(data, 10);  // [0, 1, 2, 3, 4]
	 * rotate(data, 9);   // [4, 0, 1, 2, 3]
	 * ```
	 */
	function rotate(object, delta) {
	    var length = object.length;
	    if (length <= 1) {
	        return;
	    }
	    if (delta > 0) {
	        delta = delta % length;
	    }
	    else if (delta < 0) {
	        delta = ((delta % length) + length) % length;
	    }
	    if (delta === 0) {
	        return;
	    }
	    var seq = sequence_1.asMutableSequence(object);
	    reverse(seq, 0, delta - 1);
	    reverse(seq, delta, length - 1);
	    reverse(seq, 0, length - 1);
	}
	exports.rotate = rotate;
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/algorithm/mutation.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/dom/sizing.js **/
jupyter.define('phosphor@0.7.0/lib/dom/sizing.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * Compute the box sizing for a DOM node.
	 *
	 * @param node - The DOM node for which to compute the box sizing.
	 *
	 * @returns The box sizing data for the specified DOM node.
	 *
	 * #### Example
	 * ```typescript
	 * import { boxSizing } from 'phosphor/lib/dom/sizing';
	 *
	 * let div = document.createElement('div');
	 * div.style.borderTop = 'solid 10px black';
	 * document.body.appendChild(div);
	 *
	 * let sizing = boxSizing(div);
	 * sizing.borderTop;    // 10
	 * sizing.paddingLeft;  // 0
	 * // etc...
	 * ```
	 */
	function boxSizing(node) {
	    var cstyle = window.getComputedStyle(node);
	    var bt = parseInt(cstyle.borderTopWidth, 10) || 0;
	    var bl = parseInt(cstyle.borderLeftWidth, 10) || 0;
	    var br = parseInt(cstyle.borderRightWidth, 10) || 0;
	    var bb = parseInt(cstyle.borderBottomWidth, 10) || 0;
	    var pt = parseInt(cstyle.paddingTop, 10) || 0;
	    var pl = parseInt(cstyle.paddingLeft, 10) || 0;
	    var pr = parseInt(cstyle.paddingRight, 10) || 0;
	    var pb = parseInt(cstyle.paddingBottom, 10) || 0;
	    var hs = bl + pl + pr + br;
	    var vs = bt + pt + pb + bb;
	    return {
	        borderTop: bt,
	        borderLeft: bl,
	        borderRight: br,
	        borderBottom: bb,
	        paddingTop: pt,
	        paddingLeft: pl,
	        paddingRight: pr,
	        paddingBottom: pb,
	        horizontalSum: hs,
	        verticalSum: vs
	    };
	}
	exports.boxSizing = boxSizing;
	/**
	 * Compute the size limits for a DOM node.
	 *
	 * @param node - The node for which to compute the size limits.
	 *
	 * @returns The size limit data for the specified DOM node.
	 *
	 * #### Example
	 * ```typescript
	 * import { sizeLimits } from 'phosphor/lib/dom/sizing';
	 *
	 * let div = document.createElement('div');
	 * div.style.minWidth = '90px';
	 * document.body.appendChild(div);
	 *
	 * let limits = sizeLimits(div);
	 * limits.minWidth;   // 90
	 * limits.maxHeight;  // Infinity
	 * // etc...
	 * ```
	 */
	function sizeLimits(node) {
	    var cstyle = window.getComputedStyle(node);
	    return {
	        minWidth: parseInt(cstyle.minWidth, 10) || 0,
	        minHeight: parseInt(cstyle.minHeight, 10) || 0,
	        maxWidth: parseInt(cstyle.maxWidth, 10) || Infinity,
	        maxHeight: parseInt(cstyle.maxHeight, 10) || Infinity
	    };
	}
	exports.sizeLimits = sizeLimits;
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/dom/sizing.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/boxengine.js **/
jupyter.define('phosphor@0.7.0/lib/ui/boxengine.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var sequence_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/sequence.js');
	/**
	 * A sizer object for use with the [[boxCalc]] function.
	 *
	 * #### Notes
	 * A box sizer holds the geometry information for an object along a
	 * layout orientation.
	 *
	 * For best performance, this class should be treated as a raw data
	 * struct. It should not typically be subclassed.
	 */
	var BoxSizer = (function () {
	    function BoxSizer() {
	        /**
	         * The preferred size for the sizer.
	         *
	         * #### Notes
	         * The sizer will be given this initial size subject to its size
	         * bounds. The sizer will not deviate from this size unless such
	         * deviation is required to fit into the available layout space.
	         *
	         * There is no limit to this value, but it will be clamped to the
	         * bounds defined by [[minSize]] and [[maxSize]].
	         *
	         * The default value is `0`.
	         */
	        this.sizeHint = 0;
	        /**
	         * The minimum size of the sizer.
	         *
	         * #### Notes
	         * The sizer will never be sized less than this value, even if
	         * it means the sizer will overflow the available layout space.
	         *
	         * It is assumed that this value lies in the range `[0, Infinity)`
	         * and that it is `<=` to [[maxSize]]. Failure to adhere to this
	         * constraint will yield undefined results.
	         *
	         * The default value is `0`.
	         */
	        this.minSize = 0;
	        /**
	         * The maximum size of the sizer.
	         *
	         * #### Notes
	         * The sizer will never be sized greater than this value, even if
	         * it means the sizer will underflow the available layout space.
	         *
	         * It is assumed that this value lies in the range `[0, Infinity]`
	         * and that it is `>=` to [[minSize]]. Failure to adhere to this
	         * constraint will yield undefined results.
	         *
	         * The default value is `Infinity`.
	         */
	        this.maxSize = Infinity;
	        /**
	         * The stretch factor for the sizer.
	         *
	         * #### Notes
	         * This controls how much the sizer stretches relative to its sibling
	         * sizers when layout space is distributed. A stretch factor of zero
	         * is special and will cause the sizer to only be resized after all
	         * other sizers with a stretch factor greater than zero have been
	         * resized to their limits.
	         *
	         * It is assumed that this value is an integer that lies in the range
	         * `[0, Infinity)`. Failure to adhere to this constraint will yield
	         * undefined results.
	         *
	         * The default value is `1`.
	         */
	        this.stretch = 1;
	        /**
	         * The computed size of the sizer.
	         *
	         * #### Notes
	         * This value is the output of a call to [[boxCalc]]. It represents
	         * the computed size for the object along the layout orientation,
	         * and will always lie in the range `[minSize, maxSize]`.
	         *
	         * This value is output only.
	         *
	         * Changing this value will have no effect.
	         */
	        this.size = 0;
	        /**
	         * An internal storage property for the layout algorithm.
	         *
	         * #### Notes
	         * This value is used as temporary storage by the layout algorithm.
	         *
	         * Changing this value will have no effect.
	         */
	        this.done = false;
	    }
	    return BoxSizer;
	}());
	exports.BoxSizer = BoxSizer;
	/**
	 * Compute the optimal layout sizes for a sequence of box sizers.
	 *
	 * This distributes the available layout space among the box sizers
	 * according to the following algorithm:
	 *
	 * 1. Initialize the sizers's size to its size hint and compute the
	 *    sums for each of size hint, min size, and max size.
	 *
	 * 2. If the total size hint equals the available space, return.
	 *
	 * 3. If the available space is less than the total min size, set all
	 *    sizers to their min size and return.
	 *
	 * 4. If the available space is greater than the total max size, set
	 *    all sizers to their max size and return.
	 *
	 * 5. If the layout space is less than the total size hint, distribute
	 *    the negative delta as follows:
	 *
	 *    a. Shrink each sizer with a stretch factor greater than zero by
	 *       an amount proportional to the negative space and the sum of
	 *       stretch factors. If the sizer reaches its min size, remove
	 *       it and its stretch factor from the computation.
	 *
	 *    b. If after adjusting all stretch sizers there remains negative
	 *       space, distribute the space equally among the sizers with a
	 *       stretch factor of zero. If a sizer reaches its min size,
	 *       remove it from the computation.
	 *
	 * 6. If the layout space is greater than the total size hint,
	 *    distribute the positive delta as follows:
	 *
	 *    a. Expand each sizer with a stretch factor greater than zero by
	 *       an amount proportional to the postive space and the sum of
	 *       stretch factors. If the sizer reaches its max size, remove
	 *       it and its stretch factor from the computation.
	 *
	 *    b. If after adjusting all stretch sizers there remains positive
	 *       space, distribute the space equally among the sizers with a
	 *       stretch factor of zero. If a sizer reaches its max size,
	 *       remove it from the computation.
	 *
	 * 7. return
	 *
	 * @param sizers - The sizers for a particular layout line.
	 *
	 * @param space - The available layout space for the sizers.
	 *
	 * #### Notes
	 * The [[size]] of each sizer is updated with the computed size.
	 *
	 * This function can be called at any time to recompute the layout for
	 * an existing sequence of sizers. The previously computed results will
	 * have no effect on the new output. It is therefore not necessary to
	 * create new sizer objects on each resize event.
	 */
	function boxCalc(object, space) {
	    // Bail early if there is nothing to do.
	    var count = object.length;
	    if (count === 0) {
	        return;
	    }
	    // Cast the object to a sequence of sizers.
	    var sizers = sequence_1.asSequence(object);
	    // Setup the size and stretch counters.
	    var totalMin = 0;
	    var totalMax = 0;
	    var totalSize = 0;
	    var totalStretch = 0;
	    var stretchCount = 0;
	    // Setup the sizers and compute the totals.
	    for (var i = 0; i < count; ++i) {
	        var sizer = sizers.at(i);
	        var min = sizer.minSize;
	        var max = sizer.maxSize;
	        var hint = sizer.sizeHint;
	        sizer.done = false;
	        sizer.size = Math.max(min, Math.min(hint, max));
	        totalSize += sizer.size;
	        totalMin += min;
	        totalMax += max;
	        if (sizer.stretch > 0) {
	            totalStretch += sizer.stretch;
	            stretchCount++;
	        }
	    }
	    // If the space is equal to the total size, return.
	    if (space === totalSize) {
	        return;
	    }
	    // If the space is less than the total min, minimize each sizer.
	    if (space <= totalMin) {
	        for (var i = 0; i < count; ++i) {
	            var sizer = sizers.at(i);
	            sizer.size = sizer.minSize;
	        }
	        return;
	    }
	    // If the space is greater than the total max, maximize each sizer.
	    if (space >= totalMax) {
	        for (var i = 0; i < count; ++i) {
	            var sizer = sizers.at(i);
	            sizer.size = sizer.maxSize;
	        }
	        return;
	    }
	    // The loops below perform sub-pixel precision sizing. A near zero
	    // value is used for compares instead of zero to ensure that the
	    // loop terminates when the subdivided space is reasonably small.
	    var nearZero = 0.01;
	    // A counter which is decremented each time a sizer is resized to
	    // its limit. This ensures the loops terminate even if there is
	    // space remaining to distribute.
	    var notDoneCount = count;
	    // Distribute negative delta space.
	    if (space < totalSize) {
	        // Shrink each stretchable sizer by an amount proportional to its
	        // stretch factor. If a sizer reaches its min size it's marked as
	        // done. The loop progresses in phases where each sizer is given
	        // a chance to consume its fair share for the pass, regardless of
	        // whether a sizer before it reached its limit. This continues
	        // until the stretchable sizers or the free space is exhausted.
	        var freeSpace = totalSize - space;
	        while (stretchCount > 0 && freeSpace > nearZero) {
	            var distSpace = freeSpace;
	            var distStretch = totalStretch;
	            for (var i = 0; i < count; ++i) {
	                var sizer = sizers.at(i);
	                if (sizer.done || sizer.stretch === 0) {
	                    continue;
	                }
	                var amt = sizer.stretch * distSpace / distStretch;
	                if (sizer.size - amt <= sizer.minSize) {
	                    freeSpace -= sizer.size - sizer.minSize;
	                    totalStretch -= sizer.stretch;
	                    sizer.size = sizer.minSize;
	                    sizer.done = true;
	                    notDoneCount--;
	                    stretchCount--;
	                }
	                else {
	                    freeSpace -= amt;
	                    sizer.size -= amt;
	                }
	            }
	        }
	        // Distribute any remaining space evenly among the non-stretchable
	        // sizers. This progresses in phases in the same manner as above.
	        while (notDoneCount > 0 && freeSpace > nearZero) {
	            var amt = freeSpace / notDoneCount;
	            for (var i = 0; i < count; ++i) {
	                var sizer = sizers.at(i);
	                if (sizer.done) {
	                    continue;
	                }
	                if (sizer.size - amt <= sizer.minSize) {
	                    freeSpace -= sizer.size - sizer.minSize;
	                    sizer.size = sizer.minSize;
	                    sizer.done = true;
	                    notDoneCount--;
	                }
	                else {
	                    freeSpace -= amt;
	                    sizer.size -= amt;
	                }
	            }
	        }
	    }
	    else {
	        // Expand each stretchable sizer by an amount proportional to its
	        // stretch factor. If a sizer reaches its max size it's marked as
	        // done. The loop progresses in phases where each sizer is given
	        // a chance to consume its fair share for the pass, regardless of
	        // whether a sizer before it reached its limit. This continues
	        // until the stretchable sizers or the free space is exhausted.
	        var freeSpace = space - totalSize;
	        while (stretchCount > 0 && freeSpace > nearZero) {
	            var distSpace = freeSpace;
	            var distStretch = totalStretch;
	            for (var i = 0; i < count; ++i) {
	                var sizer = sizers.at(i);
	                if (sizer.done || sizer.stretch === 0) {
	                    continue;
	                }
	                var amt = sizer.stretch * distSpace / distStretch;
	                if (sizer.size + amt >= sizer.maxSize) {
	                    freeSpace -= sizer.maxSize - sizer.size;
	                    totalStretch -= sizer.stretch;
	                    sizer.size = sizer.maxSize;
	                    sizer.done = true;
	                    notDoneCount--;
	                    stretchCount--;
	                }
	                else {
	                    freeSpace -= amt;
	                    sizer.size += amt;
	                }
	            }
	        }
	        // Distribute any remaining space evenly among the non-stretchable
	        // sizers. This progresses in phases in the same manner as above.
	        while (notDoneCount > 0 && freeSpace > nearZero) {
	            var amt = freeSpace / notDoneCount;
	            for (var i = 0; i < count; ++i) {
	                var sizer = sizers.at(i);
	                if (sizer.done) {
	                    continue;
	                }
	                if (sizer.size + amt >= sizer.maxSize) {
	                    freeSpace -= sizer.maxSize - sizer.size;
	                    sizer.size = sizer.maxSize;
	                    sizer.done = true;
	                    notDoneCount--;
	                }
	                else {
	                    freeSpace -= amt;
	                    sizer.size += amt;
	                }
	            }
	        }
	    }
	}
	exports.boxCalc = boxCalc;
	/**
	 * Adjust a sizer by a delta and adjust its neighbors accordingly.
	 *
	 * @param object - The sizers which should be adjusted.
	 *
	 * @param index - The index of the sizer to grow.
	 *
	 * @param delta - The amount to adjust the sizer, positive or negative.
	 *
	 * #### Notes
	 * This will adjust the indicated sizer by the specified amount, along
	 * with the sizes of the appropriate neighbors, subject to the limits
	 * specified by each of the sizers.
	 *
	 * This is useful when implementing box layouts where the boundaries
	 * between the sizers are interactively adjustable by the user.
	 */
	function adjustSizer(object, index, delta) {
	    // Bail early when there is nothing to do.
	    if (object.length === 0 || delta === 0) {
	        return;
	    }
	    // Dispatch to the proper implementation.
	    if (delta > 0) {
	        Private.growSizer(object, index, delta);
	    }
	    else {
	        Private.shrinkSizer(object, index, -delta);
	    }
	}
	exports.adjustSizer = adjustSizer;
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Grow a sizer by a positive delta and adjust neighbors.
	     */
	    function growSizer(object, index, delta) {
	        // Cast the object to a sequence of sizers.
	        var sizers = sequence_1.asSequence(object);
	        // Compute how much the items to the left can expand.
	        var growLimit = 0;
	        for (var i = 0; i <= index; ++i) {
	            var sizer = sizers.at(i);
	            growLimit += sizer.maxSize - sizer.size;
	        }
	        // Compute how much the items to the right can shrink.
	        var shrinkLimit = 0;
	        for (var i = index + 1, n = sizers.length; i < n; ++i) {
	            var sizer = sizers.at(i);
	            shrinkLimit += sizer.size - sizer.minSize;
	        }
	        // Clamp the delta adjustment to the limits.
	        delta = Math.min(delta, growLimit, shrinkLimit);
	        // Grow the sizers to the left by the delta.
	        var grow = delta;
	        for (var i = index; i >= 0 && grow > 0; --i) {
	            var sizer = sizers.at(i);
	            var limit = sizer.maxSize - sizer.size;
	            if (limit >= grow) {
	                sizer.sizeHint = sizer.size + grow;
	                grow = 0;
	            }
	            else {
	                sizer.sizeHint = sizer.size + limit;
	                grow -= limit;
	            }
	        }
	        // Shrink the sizers to the right by the delta.
	        var shrink = delta;
	        for (var i = index + 1, n = sizers.length; i < n && shrink > 0; ++i) {
	            var sizer = sizers.at(i);
	            var limit = sizer.size - sizer.minSize;
	            if (limit >= shrink) {
	                sizer.sizeHint = sizer.size - shrink;
	                shrink = 0;
	            }
	            else {
	                sizer.sizeHint = sizer.size - limit;
	                shrink -= limit;
	            }
	        }
	    }
	    Private.growSizer = growSizer;
	    /**
	     * Shrink a sizer by a positive delta and adjust neighbors.
	     */
	    function shrinkSizer(object, index, delta) {
	        // Cast the object to a sequence of sizers.
	        var sizers = sequence_1.asSequence(object);
	        // Compute how much the items to the right can expand.
	        var growLimit = 0;
	        for (var i = index + 1, n = sizers.length; i < n; ++i) {
	            var sizer = sizers.at(i);
	            growLimit += sizer.maxSize - sizer.size;
	        }
	        // Compute how much the items to the left can shrink.
	        var shrinkLimit = 0;
	        for (var i = 0; i <= index; ++i) {
	            var sizer = sizers.at(i);
	            shrinkLimit += sizer.size - sizer.minSize;
	        }
	        // Clamp the delta adjustment to the limits.
	        delta = Math.min(delta, growLimit, shrinkLimit);
	        // Grow the sizers to the right by the delta.
	        var grow = delta;
	        for (var i = index + 1, n = sizers.length; i < n && grow > 0; ++i) {
	            var sizer = sizers.at(i);
	            var limit = sizer.maxSize - sizer.size;
	            if (limit >= grow) {
	                sizer.sizeHint = sizer.size + grow;
	                grow = 0;
	            }
	            else {
	                sizer.sizeHint = sizer.size + limit;
	                grow -= limit;
	            }
	        }
	        // Shrink the sizers to the left by the delta.
	        var shrink = delta;
	        for (var i = index; i >= 0 && shrink > 0; --i) {
	            var sizer = sizers.at(i);
	            var limit = sizer.size - sizer.minSize;
	            if (limit >= shrink) {
	                sizer.sizeHint = sizer.size - shrink;
	                shrink = 0;
	            }
	            else {
	                sizer.sizeHint = sizer.size - limit;
	                shrink -= limit;
	            }
	        }
	    }
	    Private.shrinkSizer = shrinkSizer;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/boxengine.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/panel.js **/
jupyter.define('phosphor@0.7.0/lib/ui/panel.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	var mutation_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/mutation.js');
	var searching_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var messaging_1 = __jupyter_require__('phosphor@0.7.0/lib/core/messaging.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to Panel instances.
	 */
	var PANEL_CLASS = 'p-Panel';
	/**
	 * A simple and convenient panel widget class.
	 *
	 * #### Notes
	 * This class is suitable as a base class for implementing a variety of
	 * convenience panel widgets, but can also be used directly with CSS to
	 * arrange a collection of widgets.
	 *
	 * This class provides a convenience wrapper around a [[PanelLayout]].
	 */
	var Panel = (function (_super) {
	    __extends(Panel, _super);
	    /**
	     * Construct a new panel.
	     *
	     * @param options - The options for initializing the panel.
	     */
	    function Panel(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this);
	        this.addClass(PANEL_CLASS);
	        this.layout = Private.createLayout(options);
	    }
	    Object.defineProperty(Panel.prototype, "widgets", {
	        /**
	         * A read-only sequence of the widgets in the panel.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.layout.widgets;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a widget to the end of the panel.
	     *
	     * @param widget - The widget to add to the panel.
	     *
	     * #### Notes
	     * If the is already contained in the panel, it will be moved.
	     */
	    Panel.prototype.addWidget = function (widget) {
	        this.layout.addWidget(widget);
	    };
	    /**
	     * Insert a widget at the specified index.
	     *
	     * @param index - The index at which to insert the widget.
	     *
	     * @param widget - The widget to insert into to the panel.
	     *
	     * #### Notes
	     * If the widget is already contained in the panel, it will be moved.
	     */
	    Panel.prototype.insertWidget = function (index, widget) {
	        this.layout.insertWidget(index, widget);
	    };
	    return Panel;
	}(widget_1.Widget));
	exports.Panel = Panel;
	/**
	 * A concrete layout implementation suitable for many use cases.
	 *
	 * #### Notes
	 * This class is suitable as a base class for implementing a variety of
	 * layouts, but can also be used directly with standard CSS to layout a
	 * collection of widgets.
	 */
	var PanelLayout = (function (_super) {
	    __extends(PanelLayout, _super);
	    function PanelLayout() {
	        _super.apply(this, arguments);
	        this._widgets = new vector_1.Vector();
	    }
	    /**
	     * Dispose of the resources held by the layout.
	     *
	     * #### Notes
	     * This will clear and dispose all widgets in the layout.
	     *
	     * All reimplementations should call the superclass method.
	     *
	     * This method is called automatically when the parent is disposed.
	     */
	    PanelLayout.prototype.dispose = function () {
	        while (this._widgets.length > 0) {
	            this._widgets.popBack().dispose();
	        }
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(PanelLayout.prototype, "widgets", {
	        /**
	         * A read-only sequence of the widgets in the layout.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._widgets;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over the widgets in the layout.
	     *
	     * @returns A new iterator over the widgets in the layout.
	     */
	    PanelLayout.prototype.iter = function () {
	        return this._widgets.iter();
	    };
	    /**
	     * Add a widget to the end of the layout.
	     *
	     * @param widget - The widget to add to the layout.
	     *
	     * #### Notes
	     * If the widget is already contained in the layout, it will be moved.
	     */
	    PanelLayout.prototype.addWidget = function (widget) {
	        this.insertWidget(this._widgets.length, widget);
	    };
	    /**
	     * Insert a widget into the layout at the specified index.
	     *
	     * @param index - The index at which to insert the widget.
	     *
	     * @param widget - The widget to insert into the layout.
	     *
	     * #### Notes
	     * The index will be clamped to the bounds of the widgets.
	     *
	     * If the widget is already added to the layout, it will be moved.
	     */
	    PanelLayout.prototype.insertWidget = function (index, widget) {
	        // Remove the widget from its current parent. This is a no-op
	        // if the widget's parent is already the layout parent widget.
	        widget.parent = this.parent;
	        // Look up the current index of the widget.
	        var i = searching_1.indexOf(this._widgets, widget);
	        // Clamp the insert index to the vector bounds.
	        var j = Math.max(0, Math.min(Math.floor(index), this._widgets.length));
	        // If the widget is not in the vector, insert it.
	        if (i === -1) {
	            // Insert the widget into the vector.
	            this._widgets.insert(j, widget);
	            // If the layout is parented, attach the widget to the DOM.
	            if (this.parent)
	                this.attachWidget(j, widget);
	            // There is nothing more to do.
	            return;
	        }
	        // Otherwise, the widget exists in the vector and should be moved.
	        // Adjust the index if the location is at the end of the vector.
	        if (j === this._widgets.length)
	            j--;
	        // Bail if there is no effective move.
	        if (i === j)
	            return;
	        // Move the widget to the new location.
	        mutation_1.move(this._widgets, i, j);
	        // If the layout is parented, move the widget in the DOM.
	        if (this.parent)
	            this.moveWidget(i, j, widget);
	    };
	    /**
	     * Remove a widget from the layout.
	     *
	     * @param widget - The widget to remove from the layout.
	     *
	     * #### Notes
	     * A widget is automatically removed from the layout when its `parent`
	     * is set to `null`. This method should only be invoked directly when
	     * removing a widget from a layout which has yet to be installed on a
	     * parent widget.
	     *
	     * This method does *not* modify the widget's `parent`.
	     */
	    PanelLayout.prototype.removeWidget = function (widget) {
	        this.removeWidgetAt(searching_1.indexOf(this._widgets, widget));
	    };
	    /**
	     * Remove the widget at a given index from the layout.
	     *
	     * @param index - The index of the widget to remove.
	     *
	     * #### Notes
	     * A widget is automatically removed from the layout when its `parent`
	     * is set to `null`. This method should only be invoked directly when
	     * removing a widget from a layout which has yet to be installed on a
	     * parent widget.
	     *
	     * This method does *not* modify the widget's `parent`.
	     */
	    PanelLayout.prototype.removeWidgetAt = function (index) {
	        // Bail if the index is out of range.
	        var i = Math.floor(index);
	        if (i < 0 || i >= this._widgets.length) {
	            return;
	        }
	        // Remove the widget from the vector.
	        var widget = this._widgets.removeAt(i);
	        // If the layout is parented, detach the widget from the DOM.
	        if (this.parent)
	            this.detachWidget(i, widget);
	    };
	    /**
	     * Perform layout initialization which requires the parent widget.
	     */
	    PanelLayout.prototype.init = function () {
	        var _this = this;
	        _super.prototype.init.call(this);
	        var index = 0;
	        iteration_1.each(this, function (widget) { _this.attachWidget(index++, widget); });
	    };
	    /**
	     * Attach a widget to the parent's DOM node.
	     *
	     * @param index - The current index of the widget in the layout.
	     *
	     * @param widget - The widget to attach to the parent.
	     *
	     * #### Notes
	     * This method is called automatically by the panel layout at the
	     * appropriate time. It should not be called directly by user code.
	     *
	     * The default implementation adds the widgets's node to the parent's
	     * node at the proper location, and sends an `'after-attach'` message
	     * to the widget if the parent is attached to the DOM.
	     *
	     * Subclasses may reimplement this method to control how the widget's
	     * node is added to the parent's node, but the reimplementation must
	     * send an `'after-attach'` message to the widget if the parent is
	     * attached to the DOM.
	     */
	    PanelLayout.prototype.attachWidget = function (index, widget) {
	        // Look up the next sibling reference node.
	        var ref = this.parent.node.children[index];
	        // Insert the widget's node before the sibling.
	        this.parent.node.insertBefore(widget.node, ref);
	        // Send an `'after-attach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.AfterAttach);
	    };
	    /**
	     * Move a widget in the parent's DOM node.
	     *
	     * @param fromIndex - The previous index of the widget in the layout.
	     *
	     * @param toIndex - The current index of the widget in the layout.
	     *
	     * @param widget - The widget to move in the parent.
	     *
	     * #### Notes
	     * This method is called automatically by the panel layout at the
	     * appropriate time. It should not be called directly by user code.
	     *
	     * The default implementation moves the widget's node to the proper
	     * location in the parent's node and sends both a `'before-detach'`
	     * and an `'after-attach'` message to the widget if the parent is
	     * attached to the DOM.
	     *
	     * Subclasses may reimplement this method to control how the widget's
	     * node is moved in the parent's node, but the reimplementation must
	     * send both a `'before-detach'` and an `'after-attach'` message to
	     * the widget if the parent is attached to the DOM.
	     */
	    PanelLayout.prototype.moveWidget = function (fromIndex, toIndex, widget) {
	        // Send a `'before-detach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.BeforeDetach);
	        // Remove the widget's node from the parent.
	        this.parent.node.removeChild(widget.node);
	        // Look up the next sibling reference node.
	        var ref = this.parent.node.children[toIndex];
	        // Insert the widget's node before the sibling.
	        this.parent.node.insertBefore(widget.node, ref);
	        // Send an `'after-attach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.AfterAttach);
	    };
	    /**
	     * Detach a widget from the parent's DOM node.
	     *
	     * @param index - The previous index of the widget in the layout.
	     *
	     * @param widget - The widget to detach from the parent.
	     *
	     * #### Notes
	     * This method is called automatically by the panel layout at the
	     * appropriate time. It should not be called directly by user code.
	     *
	     * The default implementation removes the widget's node from the
	     * parent's node, and sends a `'before-detach'` message to the widget
	     * if the parent is attached to the DOM.
	     *
	     * Subclasses may reimplement this method to control how the widget's
	     * node is removed from the parent's node, but the reimplementation
	     * must send a `'before-detach'` message to the widget if the parent
	     * is attached to the DOM.
	     */
	    PanelLayout.prototype.detachWidget = function (index, widget) {
	        // Send a `'before-detach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.BeforeDetach);
	        // Remove the widget's node from the parent.
	        this.parent.node.removeChild(widget.node);
	    };
	    return PanelLayout;
	}(widget_1.Layout));
	exports.PanelLayout = PanelLayout;
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create a panel layout for the given panel options.
	     */
	    function createLayout(options) {
	        return options.layout || new PanelLayout();
	    }
	    Private.createLayout = createLayout;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/panel.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/dockpanel.js **/
jupyter.define('phosphor@0.7.0/lib/ui/dockpanel.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var messaging_1 = __jupyter_require__('phosphor@0.7.0/lib/core/messaging.js');
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	var mimedata_1 = __jupyter_require__('phosphor@0.7.0/lib/core/mimedata.js');
	var cursor_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/cursor.js');
	var dragdrop_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/dragdrop.js');
	var platform_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/platform.js');
	var query_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/query.js');
	var sizing_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/sizing.js');
	var boxengine_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/boxengine.js');
	var focustracker_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/focustracker.js');
	var tabbar_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/tabbar.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to a DockPanel instance.
	 */
	var DOCK_PANEL_CLASS = 'p-DockPanel';
	/**
	 * The class name added to DockPanel widgets.
	 */
	var WIDGET_CLASS = 'p-DockPanel-widget';
	/**
	 * The class name added to a DockPanel tab bar.
	 */
	var TAB_BAR_CLASS = 'p-DockPanel-tabBar';
	/**
	 * The class name added to a DockPanel handle.
	 */
	var HANDLE_CLASS = 'p-DockPanel-handle';
	/**
	 * The class name added to a DockPanel overlay.
	 */
	var OVERLAY_CLASS = 'p-DockPanel-overlay';
	/**
	 * The class name added to hidden entities.
	 */
	var HIDDEN_CLASS = 'p-mod-hidden';
	/**
	 * The class name added to horizontal handles.
	 */
	var HORIZONTAL_CLASS = 'p-mod-horizontal';
	/**
	 * The class name added to vertical handles.
	 */
	var VERTICAL_CLASS = 'p-mod-vertical';
	/**
	 * The factory MIME type supported by the dock panel.
	 */
	var FACTORY_MIME = 'application/vnd.phosphor.widget-factory';
	/**
	 * A fraction used for sizing root panels; ~= `1 / golden_ratio`.
	 */
	var GOLDEN = 0.618;
	/**
	 * A widget which provides a flexible docking area for widgets.
	 */
	var DockPanel = (function (_super) {
	    __extends(DockPanel, _super);
	    /**
	     * Construct a new dock panel.
	     *
	     * @param options - The options for initializing the panel.
	     */
	    function DockPanel(options) {
	        var _this = this;
	        if (options === void 0) { options = {}; }
	        _super.call(this);
	        this._drag = null;
	        this._pressData = null;
	        this._tracker = new focustracker_1.FocusTracker();
	        this.addClass(DOCK_PANEL_CLASS);
	        // Extract the inter-panel spacing.
	        var spacing = options.spacing !== void 0 ? options.spacing : 4;
	        // Extract the content renderer for the panel.
	        this._renderer = options.renderer || DockPanel.defaultRenderer;
	        // Create the delegate renderer for the layout.
	        var renderer = {
	            createTabBar: function () { return _this._createTabBar(); },
	            createHandle: function () { return _this._createHandle(); }
	        };
	        // Setup the dock layout for the panel.
	        this.layout = new DockLayout({ renderer: renderer, spacing: spacing });
	        // Setup the overlay drop indicator.
	        this._overlay = options.overlay || new DockPanel.Overlay();
	        this._overlay.node.classList.add(OVERLAY_CLASS);
	        this.node.appendChild(this._overlay.node);
	        // Connect the focus tracker changed signal.
	        this._tracker.currentChanged.connect(this._onCurrentChanged, this);
	    }
	    /**
	     * Dispose of the resources held by the panel.
	     */
	    DockPanel.prototype.dispose = function () {
	        // Ensure the mouse is released.
	        this._releaseMouse();
	        // Hide the overlay.
	        this._overlay.hide(0);
	        // Cancel a drag if one is in progress.
	        if (this._drag) {
	            this._drag.dispose();
	        }
	        // Dispose of the focus tracker.
	        this._tracker.dispose();
	        // Dispose of the base class.
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(DockPanel.prototype, "currentWidget", {
	        /**
	         * The current widget in the dock panel.
	         *
	         * #### Notes
	         * The current widget is the widget among the added widgets which
	         * has the *descendant node* which has most recently been focused.
	         *
	         * This is the `currentWidget` of an internal `FocusTracker` which
	         * tracks all widgets in the dock panel.
	         *
	         * This will be `null` if there is no current widget.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._tracker.currentWidget;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DockPanel.prototype, "overlay", {
	        /**
	         * The overlay used by the dock panel.
	         */
	        get: function () {
	            return this._overlay;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DockPanel.prototype, "spacing", {
	        /**
	         * Get the spacing between the widgets.
	         */
	        get: function () {
	            return this.layout.spacing;
	        },
	        /**
	         * Set the spacing between the widgets.
	         */
	        set: function (value) {
	            this.layout.spacing = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DockPanel.prototype, "isEmpty", {
	        /**
	         * Whether the dock panel is empty.
	         */
	        get: function () {
	            return this.layout.isEmpty;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DockPanel.prototype, "renderer", {
	        /**
	         * The renderer used by the dock panel.
	         */
	        get: function () {
	            return this.layout.renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over the user widgets in the panel.
	     *
	     * @returns A new iterator over the user widgets in the panel.
	     *
	     * #### Notes
	     * This iterator does not include the generated tab bars.
	     */
	    DockPanel.prototype.widgets = function () {
	        return this.layout.widgets();
	    };
	    /**
	     * Create an iterator over the tab bars in the panel.
	     *
	     * @returns A new iterator over the tab bars in the panel.
	     *
	     * #### Notes
	     * This iterator does not include the user widgets.
	     */
	    DockPanel.prototype.tabBars = function () {
	        return this.layout.tabBars();
	    };
	    /**
	     * Create an iterator over the handles in the panel.
	     *
	     * @returns A new iterator over the handles in the panel.
	     */
	    DockPanel.prototype.handles = function () {
	        return this.layout.handles();
	    };
	    /**
	     * Activate the specified widget in the dock panel.
	     *
	     * @param widget - The widget of interest.
	     *
	     * #### Notes
	     * This will make the widget the current widget in its tab area and
	     * post the widget an `activate-request` message.
	     */
	    DockPanel.prototype.activateWidget = function (widget) {
	        // Find the tab bar which contains the widget.
	        var title = widget.title;
	        var tabBar = searching_1.find(this.tabBars(), function (bar) { return searching_1.contains(bar.titles, title); });
	        // Throw an error if no tab bar is found.
	        if (!tabBar) {
	            throw new Error('Widget is not contained in the dock panel.');
	        }
	        // Update the current title and activate the widget.
	        tabBar.currentTitle = title;
	        widget.activate();
	    };
	    /**
	     * Add a widget to the dock panel.
	     *
	     * @param widget - The widget to add to the dock panel.
	     *
	     * @param options - The additional options for adding the widget.
	     */
	    DockPanel.prototype.addWidget = function (widget, options) {
	        if (options === void 0) { options = {}; }
	        // Add the widget to the layout.
	        this.layout.addWidget(widget, options);
	        // Add the widget to the focus tracker.
	        this._tracker.add(widget);
	    };
	    /**
	     * Handle the DOM events for the dock panel.
	     *
	     * @param event - The DOM event sent to the panel.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the panel's DOM node. It should
	     * not be called directly by user code.
	     */
	    DockPanel.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'p-dragenter':
	                this._evtDragEnter(event);
	                break;
	            case 'p-dragleave':
	                this._evtDragLeave(event);
	                break;
	            case 'p-dragover':
	                this._evtDragOver(event);
	                break;
	            case 'p-drop':
	                this._evtDrop(event);
	                break;
	            case 'mousedown':
	                this._evtMouseDown(event);
	                break;
	            case 'mousemove':
	                this._evtMouseMove(event);
	                break;
	            case 'mouseup':
	                this._evtMouseUp(event);
	                break;
	            case 'keydown':
	                this._evtKeyDown(event);
	                break;
	            case 'contextmenu':
	                event.preventDefault();
	                event.stopPropagation();
	                break;
	        }
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    DockPanel.prototype.onAfterAttach = function (msg) {
	        this.node.addEventListener('p-dragenter', this);
	        this.node.addEventListener('p-dragleave', this);
	        this.node.addEventListener('p-dragover', this);
	        this.node.addEventListener('p-drop', this);
	        this.node.addEventListener('mousedown', this);
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    DockPanel.prototype.onBeforeDetach = function (msg) {
	        this.node.removeEventListener('p-dragenter', this);
	        this.node.removeEventListener('p-dragleave', this);
	        this.node.removeEventListener('p-dragover', this);
	        this.node.removeEventListener('p-drop', this);
	        this.node.removeEventListener('mousedown', this);
	        this._releaseMouse();
	    };
	    /**
	     * A message handler invoked on a `'child-added'` message.
	     */
	    DockPanel.prototype.onChildAdded = function (msg) {
	        // Ignore the generated tab bars.
	        if (msg.child.hasClass(TAB_BAR_CLASS)) {
	            return;
	        }
	        // Add the widget class to the child.
	        msg.child.addClass(WIDGET_CLASS);
	    };
	    /**
	     * A message handler invoked on a `'child-removed'` message.
	     */
	    DockPanel.prototype.onChildRemoved = function (msg) {
	        // Ignore the generated tab bars.
	        if (msg.child.hasClass(TAB_BAR_CLASS)) {
	            return;
	        }
	        // Remove the widget class from the child.
	        msg.child.removeClass(WIDGET_CLASS);
	        // Remove the widget from the focus tracker.
	        this._tracker.remove(msg.child);
	    };
	    /**
	     * Handle the `'p-dragenter'` event for the dock panel.
	     */
	    DockPanel.prototype._evtDragEnter = function (event) {
	        // If the factory mime type is present, mark the event as
	        // handled in order to get the rest of the drag events.
	        if (event.mimeData.hasData(FACTORY_MIME)) {
	            event.preventDefault();
	            event.stopPropagation();
	        }
	    };
	    /**
	     * Handle the `'p-dragleave'` event for the dock panel.
	     */
	    DockPanel.prototype._evtDragLeave = function (event) {
	        // Always mark the event as handled.
	        event.preventDefault();
	        event.stopPropagation();
	        // Get the node into which the drag is entering.
	        var related = event.relatedTarget;
	        // Hide the overlay if the drag is leaving the dock panel.
	        if (!related || !this.node.contains(related)) {
	            this._overlay.hide(0);
	        }
	    };
	    /**
	     * Handle the `'p-dragover'` event for the dock panel.
	     */
	    DockPanel.prototype._evtDragOver = function (event) {
	        // Always mark the event as handled.
	        event.preventDefault();
	        event.stopPropagation();
	        // Show the drop indicator overlay and update the drop
	        // action based on the drop target zone under the mouse.
	        var clientX = event.clientX, clientY = event.clientY, shiftKey = event.shiftKey;
	        if (this._showOverlay(clientX, clientY, shiftKey) === 'invalid') {
	            event.dropAction = 'none';
	        }
	        else {
	            event.dropAction = event.proposedAction;
	        }
	    };
	    /**
	     * Handle the `'p-drop'` event for the dock panel.
	     */
	    DockPanel.prototype._evtDrop = function (event) {
	        // Always mark the event as handled.
	        event.preventDefault();
	        event.stopPropagation();
	        // Hide the drop indicator overlay.
	        this._overlay.hide(0);
	        // Bail if the proposed action is to do nothing.
	        if (event.proposedAction === 'none') {
	            event.dropAction = 'none';
	            return;
	        }
	        // Find the drop target under the mouse.
	        var clientX = event.clientX, clientY = event.clientY, shiftKey = event.shiftKey;
	        var _a = this._findDropTarget(clientX, clientY, shiftKey), zone = _a.zone, target = _a.target;
	        // Bail if the drop zone is invalid.
	        if (zone === 'invalid') {
	            event.dropAction = 'none';
	            return;
	        }
	        // Bail if the factory mime type has invalid data.
	        var factory = event.mimeData.getData(FACTORY_MIME);
	        if (typeof factory !== 'function') {
	            event.dropAction = 'none';
	            return;
	        }
	        // Bail if the factory does not produce a widget.
	        var widget = factory();
	        if (!(widget instanceof widget_1.Widget)) {
	            event.dropAction = 'none';
	            return;
	        }
	        // Handle the drop using the generated widget.
	        switch (zone) {
	            case 'root':
	                this.addWidget(widget);
	                break;
	            case 'root-top':
	                this.addWidget(widget, { mode: 'split-top' });
	                break;
	            case 'root-left':
	                this.addWidget(widget, { mode: 'split-left' });
	                break;
	            case 'root-right':
	                this.addWidget(widget, { mode: 'split-right' });
	                break;
	            case 'root-bottom':
	                this.addWidget(widget, { mode: 'split-bottom' });
	                break;
	            case 'widget-top':
	                this.addWidget(widget, { mode: 'split-top', ref: target });
	                break;
	            case 'widget-left':
	                this.addWidget(widget, { mode: 'split-left', ref: target });
	                break;
	            case 'widget-right':
	                this.addWidget(widget, { mode: 'split-right', ref: target });
	                break;
	            case 'widget-bottom':
	                this.addWidget(widget, { mode: 'split-bottom', ref: target });
	                break;
	            case 'tab-bar':
	                var ref = Private.tabBarRef(target);
	                this.addWidget(widget, { mode: 'tab-after', ref: ref });
	                break;
	        }
	        // Accept the proposed drop action.
	        event.dropAction = event.proposedAction;
	        // Activate the dropped widget.
	        this.activateWidget(widget);
	    };
	    /**
	     * Handle the `'keydown'` event for the dock panel.
	     */
	    DockPanel.prototype._evtKeyDown = function (event) {
	        // Stop input events during drag.
	        event.preventDefault();
	        event.stopPropagation();
	        // Release the mouse if `Escape` is pressed.
	        if (event.keyCode === 27) {
	            this._releaseMouse();
	        }
	    };
	    /**
	     * Handle the `'mousedown'` event for the dock panel.
	     */
	    DockPanel.prototype._evtMouseDown = function (event) {
	        // Do nothing if the left mouse button is not pressed.
	        if (event.button !== 0) {
	            return;
	        }
	        // Find the handle which contains the mouse target, if any.
	        var layout = this.layout;
	        var target = event.target;
	        var handle = searching_1.find(layout.handles(), function (handle) { return handle.contains(target); });
	        if (!handle) {
	            return;
	        }
	        // Stop the event when a handle is pressed.
	        event.preventDefault();
	        event.stopPropagation();
	        // Add the extra document listeners.
	        document.addEventListener('keydown', this, true);
	        document.addEventListener('mouseup', this, true);
	        document.addEventListener('mousemove', this, true);
	        document.addEventListener('contextmenu', this, true);
	        // Compute the offset deltas for the handle press.
	        var rect = handle.getBoundingClientRect();
	        var deltaX = event.clientX - rect.left;
	        var deltaY = event.clientY - rect.top;
	        // Override the cursor and store the press data.
	        var style = window.getComputedStyle(handle);
	        var override = cursor_1.overrideCursor(style.cursor);
	        this._pressData = { handle: handle, deltaX: deltaX, deltaY: deltaY, override: override };
	    };
	    /**
	     * Handle the `'mousemove'` event for the dock panel.
	     */
	    DockPanel.prototype._evtMouseMove = function (event) {
	        // Stop the event when dragging a handle.
	        event.preventDefault();
	        event.stopPropagation();
	        // Compute the desired offset position for the handle.
	        var rect = this.node.getBoundingClientRect();
	        var xPos = event.clientX - rect.left - this._pressData.deltaX;
	        var yPos = event.clientY - rect.top - this._pressData.deltaY;
	        // Set the handle as close to the desired position as possible.
	        var layout = this.layout;
	        layout.moveHandle(this._pressData.handle, xPos, yPos);
	    };
	    /**
	     * Handle the `'mouseup'` event for the dock panel.
	     */
	    DockPanel.prototype._evtMouseUp = function (event) {
	        // Do nothing if the left mouse button is not released.
	        if (event.button !== 0) {
	            return;
	        }
	        // Stop the event when releasing a handle.
	        event.preventDefault();
	        event.stopPropagation();
	        // Finalize the mouse release.
	        this._releaseMouse();
	    };
	    /**
	     * Release the mouse grab for the dock panel.
	     */
	    DockPanel.prototype._releaseMouse = function () {
	        // Bail early if no drag is in progress.
	        if (!this._pressData) {
	            return;
	        }
	        // Clear the override cursor.
	        this._pressData.override.dispose();
	        this._pressData = null;
	        // Remove the extra document listeners.
	        document.removeEventListener('keydown', this, true);
	        document.removeEventListener('mouseup', this, true);
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('contextmenu', this, true);
	    };
	    /**
	     * Find the drop target for the given client position.
	     *
	     * @param clientX - The client X position of interest.
	     *
	     * @param clientY - The client Y position of interest.
	     *
	     * @param shift - Whether to search for shifted drop targets.
	     *
	     * @returns The dock target at the specified client position.
	     */
	    DockPanel.prototype._findDropTarget = function (clientX, clientY, shift) {
	        // Bail, if the mouse is not over the dock panel.
	        if (!query_1.hitTest(this.node, clientX, clientY)) {
	            return { zone: 'invalid', target: null };
	        }
	        // Lookup the layout for the panel.
	        var layout = this.layout;
	        // If the layout is empty, indicate a root drop zone.
	        if (layout.isEmpty) {
	            return { zone: 'root', target: null };
	        }
	        // Handle the shifted drop zones.
	        if (shift) {
	            var edge_1 = Private.calcEdge(this.node, clientX, clientY);
	            return { zone: ("root-" + edge_1), target: null };
	        }
	        // Find the widget at the given client position.
	        var widget = searching_1.find(layout, function (widget) {
	            return widget.isVisible && query_1.hitTest(widget.node, clientX, clientY);
	        });
	        // Bail if no widget is found.
	        if (!widget) {
	            return { zone: 'invalid', target: null };
	        }
	        // Handle the drop zone for a generated tab bar.
	        if (widget.hasClass(TAB_BAR_CLASS)) {
	            return { zone: 'tab-bar', target: widget };
	        }
	        // Handle the drop zone for a user widget.
	        var edge = Private.calcEdge(widget.node, clientX, clientY);
	        return { zone: ("widget-" + edge), target: widget };
	    };
	    /**
	     * Show the overlay indicator at the given client position.
	     *
	     * @param clientX - The client X position of interest.
	     *
	     * @param clientY - The client Y position of interest.
	     *
	     * @param shift - Whether to show the shifted drop targets.
	     *
	     * @returns The drop zone at the specified client position.
	     *
	     * #### Notes
	     * If the position is not over a valid zone, the overlay is hidden.
	     */
	    DockPanel.prototype._showOverlay = function (clientX, clientY, shift) {
	        // Find the dock target for the given client position.
	        var _a = this._findDropTarget(clientX, clientY, shift), zone = _a.zone, target = _a.target;
	        // If the drop zone is invalid, hide the overlay and bail.
	        if (zone === 'invalid') {
	            this._overlay.hide(100);
	            return zone;
	        }
	        // Setup the variables needed to compute the overlay geometry.
	        var top;
	        var left;
	        var right;
	        var bottom;
	        var tr;
	        var box = sizing_1.boxSizing(this.node); // TODO cache this?
	        var rect = this.node.getBoundingClientRect();
	        // Compute the overlay geometry based on the dock zone.
	        switch (zone) {
	            case 'root':
	                top = box.paddingTop;
	                left = box.paddingLeft;
	                right = box.paddingRight;
	                bottom = box.paddingBottom;
	                break;
	            case 'root-top':
	                top = box.paddingTop;
	                left = box.paddingLeft;
	                right = box.paddingRight;
	                bottom = rect.height * GOLDEN;
	                break;
	            case 'root-left':
	                top = box.paddingTop;
	                left = box.paddingLeft;
	                right = rect.width * GOLDEN;
	                bottom = box.paddingBottom;
	                break;
	            case 'root-right':
	                top = box.paddingTop;
	                left = rect.width * GOLDEN;
	                right = box.paddingRight;
	                bottom = box.paddingBottom;
	                break;
	            case 'root-bottom':
	                top = rect.height * GOLDEN;
	                left = box.paddingLeft;
	                right = box.paddingRight;
	                bottom = box.paddingBottom;
	                break;
	            case 'tab-bar':
	                tr = target.node.getBoundingClientRect();
	                top = tr.top - rect.top - box.borderTop;
	                left = tr.left - rect.left - box.borderLeft;
	                right = rect.right - tr.right - box.borderRight;
	                bottom = rect.bottom - tr.bottom - box.borderBottom;
	                break;
	            case 'widget-top':
	                tr = target.node.getBoundingClientRect();
	                top = tr.top - rect.top - box.borderTop;
	                left = tr.left - rect.left - box.borderLeft;
	                right = rect.right - tr.right - box.borderRight;
	                bottom = rect.bottom - tr.bottom + tr.height / 2 - box.borderBottom;
	                break;
	            case 'widget-left':
	                tr = target.node.getBoundingClientRect();
	                top = tr.top - rect.top - box.borderTop;
	                left = tr.left - rect.left - box.borderLeft;
	                right = rect.right - tr.right + tr.width / 2 - box.borderRight;
	                bottom = rect.bottom - tr.bottom - box.borderBottom;
	                break;
	            case 'widget-right':
	                tr = target.node.getBoundingClientRect();
	                top = tr.top - rect.top - box.borderTop;
	                left = tr.left - rect.left + tr.width / 2 - box.borderLeft;
	                right = rect.right - tr.right - box.borderRight;
	                bottom = rect.bottom - tr.bottom - box.borderBottom;
	                break;
	            case 'widget-bottom':
	                tr = target.node.getBoundingClientRect();
	                top = tr.top - rect.top + tr.height / 2 - box.borderTop;
	                left = tr.left - rect.left - box.borderLeft;
	                right = rect.right - tr.right - box.borderRight;
	                bottom = rect.bottom - tr.bottom - box.borderBottom;
	                break;
	        }
	        // Derive the width and height from the other dimensions.
	        var width = rect.width - right - left - box.borderLeft - box.borderRight;
	        var height = rect.height - bottom - top - box.borderTop - box.borderBottom;
	        // Show the overlay with the computed geometry.
	        this._overlay.show({
	            mouseX: clientX,
	            mouseY: clientY,
	            parentRect: rect,
	            top: top, left: left, right: right, bottom: bottom, width: width, height: height
	        });
	        // Finally, return the computed drop zone.
	        return zone;
	    };
	    /**
	     * Create a new tab bar for use by the panel.
	     */
	    DockPanel.prototype._createTabBar = function () {
	        // Create and initialize the tab bar.
	        var tabBar = this._renderer.createTabBar();
	        tabBar.addClass(TAB_BAR_CLASS);
	        // Setup the signal handlers for the tab bar.
	        tabBar.tabCloseRequested.connect(this._onTabCloseRequested, this);
	        tabBar.tabDetachRequested.connect(this._onTabDetachRequested, this);
	        tabBar.tabActivateRequested.connect(this._onTabActivateRequested, this);
	        // Return the initialized tab bar.
	        return tabBar;
	    };
	    /**
	     * Create a new handle for use by the panel.
	     */
	    DockPanel.prototype._createHandle = function () {
	        var handle = this._renderer.createHandle();
	        handle.classList.add(HANDLE_CLASS);
	        return handle;
	    };
	    /**
	     * Handle the `tabActivateRequested` signal from a tab bar.
	     */
	    DockPanel.prototype._onTabActivateRequested = function (sender, args) {
	        args.title.owner.activate();
	    };
	    /**
	     * Handle the `tabCloseRequested` signal from a tab bar.
	     */
	    DockPanel.prototype._onTabCloseRequested = function (sender, args) {
	        args.title.owner.close();
	    };
	    /**
	     * Handle the `tabDetachRequested` signal from a tab bar.
	     */
	    DockPanel.prototype._onTabDetachRequested = function (sender, args) {
	        var _this = this;
	        // Do nothing if a drag is already in progress.
	        if (this._drag) {
	            return;
	        }
	        // Release the tab bar's hold on the mouse.
	        sender.releaseMouse();
	        // Extract the data from the args.
	        var index = args.index, title = args.title, tab = args.tab, clientX = args.clientX, clientY = args.clientY;
	        // Setup the mime data for the drag operation.
	        var mimeData = new mimedata_1.MimeData();
	        var widget = title.owner;
	        mimeData.setData(FACTORY_MIME, function () { return widget; });
	        // Create the drag image for the drag operation.
	        var dragImage = tab.cloneNode(true);
	        // Create the drag object to manage the drag-drop operation.
	        this._drag = new dragdrop_1.Drag({
	            mimeData: mimeData, dragImage: dragImage,
	            proposedAction: 'move',
	            supportedActions: 'move',
	        });
	        // Hide the tab node in the original tab.
	        tab.classList.add(HIDDEN_CLASS);
	        // Create the cleanup callback.
	        var cleanup = (function () {
	            _this._drag = null;
	            tab.classList.remove(HIDDEN_CLASS);
	        });
	        // Start the drag operation and cleanup when done.
	        this._drag.start(clientX, clientY).then(cleanup);
	    };
	    /**
	     * Handle the `currentChanged` signal from the focus tracker.
	     */
	    DockPanel.prototype._onCurrentChanged = function (sender, args) {
	        this.currentChanged.emit(args);
	    };
	    return DockPanel;
	}(widget_1.Widget));
	exports.DockPanel = DockPanel;
	// Define the signals for the `DockPanel` class.
	signaling_1.defineSignal(DockPanel.prototype, 'currentChanged');
	/**
	 * The namespace for the `DockPanel` class statics.
	 */
	var DockPanel;
	(function (DockPanel) {
	    /**
	     * A concrete implementation of `IOverlay`.
	     *
	     * This is the default overlay implementation for a dock panel.
	     */
	    var Overlay = (function () {
	        /**
	         * Construct a new overlay.
	         */
	        function Overlay() {
	            this._timer = -1;
	            this._hidden = true;
	            this._node = document.createElement('div');
	            this._node.classList.add(HIDDEN_CLASS);
	            this._node.style.position = 'absolute';
	        }
	        Object.defineProperty(Overlay.prototype, "node", {
	            /**
	             * The DOM node for the overlay.
	             */
	            get: function () {
	                return this._node;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        /**
	         * Show the overlay using the given overlay geometry.
	         *
	         * @param geo - The desired geometry for the overlay.
	         */
	        Overlay.prototype.show = function (geo) {
	            // Update the position of the overlay.
	            var style = this._node.style;
	            style.top = geo.top + "px";
	            style.left = geo.left + "px";
	            style.right = geo.right + "px";
	            style.bottom = geo.bottom + "px";
	            // Clear any pending hide timer.
	            clearTimeout(this._timer);
	            this._timer = -1;
	            // If the overlay is already visible, we're done.
	            if (!this._hidden) {
	                return;
	            }
	            // Clear the hidden flag.
	            this._hidden = false;
	            // Finally, show the overlay.
	            this._node.classList.remove(HIDDEN_CLASS);
	        };
	        /**
	         * Hide the overlay node.
	         *
	         * @param delay - The delay (in ms) before hiding the overlay.
	         *   A delay value <= 0 will hide the overlay immediately.
	         */
	        Overlay.prototype.hide = function (delay) {
	            var _this = this;
	            // Do nothing if the overlay is already hidden.
	            if (this._hidden) {
	                return;
	            }
	            // Hide immediately if the delay is <= 0.
	            if (delay <= 0) {
	                clearTimeout(this._timer);
	                this._timer = -1;
	                this._hidden = true;
	                this._node.classList.add(HIDDEN_CLASS);
	                return;
	            }
	            // Do nothing if a hide is already pending.
	            if (this._timer !== -1) {
	                return;
	            }
	            // Otherwise setup the hide timer.
	            this._timer = setTimeout(function () {
	                _this._timer = -1;
	                _this._hidden = true;
	                _this._node.classList.add(HIDDEN_CLASS);
	            }, delay);
	        };
	        return Overlay;
	    }());
	    DockPanel.Overlay = Overlay;
	    /**
	     * The default implementation of `IRenderer`.
	     */
	    var Renderer = (function () {
	        function Renderer() {
	        }
	        /**
	         * Create a new tab bar for use with a dock panel.
	         *
	         * @returns A new tab bar for a dock panel.
	         */
	        Renderer.prototype.createTabBar = function () {
	            return new tabbar_1.TabBar();
	        };
	        /**
	         * Create a new handle node for use with a dock panel.
	         *
	         * @returns A new handle node for a dock panel.
	         */
	        Renderer.prototype.createHandle = function () {
	            return document.createElement('div');
	        };
	        return Renderer;
	    }());
	    DockPanel.Renderer = Renderer;
	    /**
	     * The default `Renderer` instance.
	     */
	    DockPanel.defaultRenderer = new Renderer();
	})(DockPanel = exports.DockPanel || (exports.DockPanel = {}));
	/**
	 * A layout which provides a flexible docking arrangement.
	 *
	 * #### Notes
	 * The layout handles the `currentChanged` signals of the tab bars and
	 * the corresponding visibility of the child widgets. The widget which
	 * consumes the layout is responsible for all other tab interactions
	 * as well as all mouse and drag events.
	 */
	var DockLayout = (function (_super) {
	    __extends(DockLayout, _super);
	    /**
	     * Construct a new dock layout.
	     *
	     * @param options - The options for initializing the layout.
	     */
	    function DockLayout(options) {
	        _super.call(this);
	        this._dirty = false;
	        this._box = null;
	        this._root = null;
	        this._renderer = options.renderer;
	        this._spacing = Private.clampSpacing(options.spacing);
	    }
	    /**
	     * Dispose of the resources held by the layout.
	     *
	     * #### Notes
	     * This will clear and dispose all widgets in the layout.
	     */
	    DockLayout.prototype.dispose = function () {
	        // Clear the reference to the renderer.
	        this._renderer = null;
	        // Get an iterator over the widgets in the layout.
	        var widgets = this.iter();
	        // Clear the layout before disposing the widgets.
	        this._root = null;
	        // Dispose of the widgets contained in the old layout root.
	        iteration_1.each(widgets, function (widget) { widget.dispose(); });
	        // Dispose of the base class.
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(DockLayout.prototype, "spacing", {
	        /**
	         * Get the inter-element spacing for the dock layout.
	         */
	        get: function () {
	            return this._spacing;
	        },
	        /**
	         * Set the inter-element spacing for the dock layout.
	         */
	        set: function (value) {
	            value = Private.clampSpacing(value);
	            if (this._spacing === value) {
	                return;
	            }
	            this._spacing = value;
	            if (!this.parent) {
	                return;
	            }
	            this.parent.fit();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DockLayout.prototype, "isEmpty", {
	        /**
	         * Whether the dock layout is empty.
	         */
	        get: function () {
	            return this._root === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DockLayout.prototype, "renderer", {
	        /**
	         * The renderer used by the dock layout.
	         */
	        get: function () {
	            return this._renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over all widgets in the layout.
	     *
	     * @returns A new iterator over the widgets in the layout.
	     *
	     * #### Notes
	     * This iterator includes the generated tab bars.
	     */
	    DockLayout.prototype.iter = function () {
	        return this._root ? Private.iterAllWidgets(this._root) : iteration_1.empty();
	    };
	    /**
	     * Create an iterator over the user widgets in the layout.
	     *
	     * @returns A new iterator over the user widgets in the layout.
	     *
	     * #### Notes
	     * This iterator does not include the generated tab bars.
	     */
	    DockLayout.prototype.widgets = function () {
	        return this._root ? Private.iterUserWidgets(this._root) : iteration_1.empty();
	    };
	    /**
	     * Create an iterator over the tab bars in the layout.
	     *
	     * @returns A new iterator over the tab bars in the layout.
	     *
	     * #### Notes
	     * This iterator does not include the user widgets.
	     */
	    DockLayout.prototype.tabBars = function () {
	        return this._root ? Private.iterTabBars(this._root) : iteration_1.empty();
	    };
	    /**
	     * Create an iterator over the handles in the layout.
	     *
	     * @returns A new iterator over the handles in the layout.
	     */
	    DockLayout.prototype.handles = function () {
	        return this._root ? Private.iterHandles(this._root) : iteration_1.empty();
	    };
	    /**
	     * Move a handle to the given offset position.
	     *
	     * @param handle - The handle to move.
	     *
	     * @param offsetX - The desired offset X position of the handle.
	     *
	     * @param offsetY - The desired offset Y position of the handle.
	     *
	     * #### Notes
	     * If the given handle is not contained in the layout, this is no-op.
	     *
	     * The handle will be moved as close as possible to the desired
	     * position without violating any of the layout constraints.
	     *
	     * Only one of the coordinates is used depending on the orientation
	     * of the handle. This method accepts both coordinates to make it
	     * easy to invoke from a mouse move event without needing to know
	     * the handle orientation.
	     */
	    DockLayout.prototype.moveHandle = function (handle, offsetX, offsetY) {
	        // Bail early if there is no root or if the handle is hidden.
	        if (!this._root || handle.classList.contains(HIDDEN_CLASS)) {
	            return;
	        }
	        // Lookup the split node for the handle.
	        var data = Private.findSplitNode(this._root, handle);
	        if (!data) {
	            return;
	        }
	        // Compute the desired delta movement for the handle.
	        var delta;
	        if (data.node.orientation === 'horizontal') {
	            delta = offsetX - handle.offsetLeft;
	        }
	        else {
	            delta = offsetY - handle.offsetTop;
	        }
	        // Bail if there is no handle movement.
	        if (delta === 0) {
	            return;
	        }
	        // Prevent sibling resizing unless needed.
	        Private.holdSizes(data.node.sizers);
	        // Adjust the sizers to reflect the handle movement.
	        boxengine_1.adjustSizer(data.node.sizers, data.index, delta);
	        // Update the layout of the widgets.
	        if (this.parent) {
	            this.parent.update();
	        }
	    };
	    /**
	     * Add a widget to the dock layout.
	     *
	     * @param widget - The widget to add to the dock layout.
	     *
	     * @param options - The additional options for adding the widget.
	     *
	     * #### Notes
	     * The widget will be moved if it is already contained in the layout.
	     *
	     * A warning will be logged if the reference widget is invalid.
	     */
	    DockLayout.prototype.addWidget = function (widget, options) {
	        if (options === void 0) { options = {}; }
	        // Parse the options.
	        var ref = options.ref || null;
	        var mode = options.mode || 'tab-after';
	        // Find the tab node which holds the reference widget.
	        var refNode = null;
	        if (this._root && ref) {
	            refNode = Private.findTabNode(this._root, ref);
	        }
	        // Throw an error if the reference widget is invalid.
	        if (ref && !refNode) {
	            throw new Error('Reference widget is not in the layout.');
	        }
	        // Reparent the widget to the current layout parent.
	        widget.parent = this.parent;
	        // Insert the widget according to the insert mode.
	        switch (mode) {
	            case 'tab-after':
	                this._insertTab(widget, ref, refNode, true);
	                break;
	            case 'tab-before':
	                this._insertTab(widget, ref, refNode, false);
	                break;
	            case 'split-top':
	                this._insertSplit(widget, ref, refNode, 'vertical', false);
	                break;
	            case 'split-left':
	                this._insertSplit(widget, ref, refNode, 'horizontal', false);
	                break;
	            case 'split-right':
	                this._insertSplit(widget, ref, refNode, 'horizontal', true);
	                break;
	            case 'split-bottom':
	                this._insertSplit(widget, ref, refNode, 'vertical', true);
	                break;
	        }
	        // Do nothing else if there is no parent widget.
	        if (!this.parent) {
	            return;
	        }
	        // Ensure the widget is attached to the parent widget.
	        this.attachWidget(widget);
	        // Post a fit request for the parent widget.
	        this.parent.fit();
	    };
	    /**
	     * Remove a widget from the layout.
	     *
	     * @param widget - The widget to remove from the layout.
	     *
	     * #### Notes
	     * A widget is automatically removed from the layout when its `parent`
	     * is set to `null`. This method should only be invoked directly when
	     * removing a widget from a layout which has yet to be installed on a
	     * parent widget.
	     *
	     * This method does *not* modify the widget's `parent`.
	     */
	    DockLayout.prototype.removeWidget = function (widget) {
	        // Remove the widget from its current layout location.
	        this._removeWidget(widget);
	        // Do nothing else if there is no parent widget.
	        if (!this.parent) {
	            return;
	        }
	        // Detach the widget from the parent widget.
	        this.detachWidget(widget);
	        // Post a fit request for the parent widget.
	        this.parent.fit();
	    };
	    /**
	     * Perform layout initialization which requires the parent widget.
	     */
	    DockLayout.prototype.init = function () {
	        var _this = this;
	        // Perform superclass initialization.
	        _super.prototype.init.call(this);
	        // Attach each widget to the parent.
	        iteration_1.each(this, function (widget) { _this.attachWidget(widget); });
	        // Attach each handle to the parent.
	        iteration_1.each(this.handles(), function (handle) { _this.parent.node.appendChild(handle); });
	        // Post a fit request for the parent widget.
	        this.parent.fit();
	    };
	    /**
	     * Attach the widget to the layout parent widget.
	     *
	     * @param widget - The widget to attach to the parent.
	     *
	     * #### Notes
	     * This is a no-op if the widget is already attached.
	     */
	    DockLayout.prototype.attachWidget = function (widget) {
	        // Do nothing if the widget is already attached.
	        if (this.parent.node === widget.node.parentNode) {
	            return;
	        }
	        // Prepare the layout geometry for the widget.
	        widget_1.Widget.prepareGeometry(widget);
	        // Add the widget's node to the parent.
	        this.parent.node.appendChild(widget.node);
	        // Send an `'after-attach'` message if the parent is attached.
	        if (this.parent.isAttached) {
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.AfterAttach);
	        }
	    };
	    /**
	     * Detach the widget from the layout parent widget.
	     *
	     * @param widget - The widget to detach from the parent.
	     *
	     * #### Notes
	     * This is a no-op if the widget is not attached.
	     */
	    DockLayout.prototype.detachWidget = function (widget) {
	        // Do nothing if the widget is not attached.
	        if (this.parent.node !== widget.node.parentNode) {
	            return;
	        }
	        // Send a `'before-detach'` message if the parent is attached.
	        if (this.parent.isAttached) {
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.BeforeDetach);
	        }
	        // Remove the widget's node from the parent.
	        this.parent.node.removeChild(widget.node);
	        // Reset the layout geometry for the widget.
	        widget_1.Widget.resetGeometry(widget);
	    };
	    /**
	     * A message handler invoked on an `'after-show'` message.
	     */
	    DockLayout.prototype.onAfterShow = function (msg) {
	        _super.prototype.onAfterShow.call(this, msg);
	        this.parent.update();
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    DockLayout.prototype.onAfterAttach = function (msg) {
	        _super.prototype.onAfterAttach.call(this, msg);
	        this.parent.fit();
	    };
	    /**
	     * A message handler invoked on a `'child-shown'` message.
	     */
	    DockLayout.prototype.onChildShown = function (msg) {
	        if (platform_1.IS_IE || platform_1.IS_EDGE) {
	            // TODO not collapsing can cause lots of fitting
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.FitRequest);
	        }
	        else {
	            this.parent.fit();
	        }
	    };
	    /**
	     * A message handler invoked on a `'child-hidden'` message.
	     */
	    DockLayout.prototype.onChildHidden = function (msg) {
	        if (platform_1.IS_IE || platform_1.IS_EDGE) {
	            // TODO not collapsing can cause lots of fitting
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.FitRequest);
	        }
	        else {
	            this.parent.fit();
	        }
	    };
	    /**
	     * A message handler invoked on a `'resize'` message.
	     */
	    DockLayout.prototype.onResize = function (msg) {
	        if (this.parent.isVisible) {
	            this._update(msg.width, msg.height);
	        }
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    DockLayout.prototype.onUpdateRequest = function (msg) {
	        if (this.parent.isVisible) {
	            this._update(-1, -1);
	        }
	    };
	    /**
	     * A message handler invoked on a `'fit-request'` message.
	     */
	    DockLayout.prototype.onFitRequest = function (msg) {
	        if (this.parent.isAttached) {
	            this._fit();
	        }
	    };
	    /**
	     * Remove the specified widget from the layout structure.
	     *
	     * @param widget - The widget to remove from the layout.
	     *
	     * #### Notes
	     * This is a no-op if the widget is not in the layout tree.
	     *
	     * This does not detach the widget from the parent node.
	     */
	    DockLayout.prototype._removeWidget = function (widget) {
	        // Bail early if there is no layout root.
	        if (!this._root) {
	            return;
	        }
	        // Find the tab node which contains the given widget.
	        var tabNode = Private.findTabNode(this._root, widget);
	        // Bail early if the tab node is not found.
	        if (!tabNode) {
	            return;
	        }
	        // If there are multiple tabs, just remove the widget's tab.
	        if (tabNode.tabBar.titles.length > 1) {
	            tabNode.tabBar.removeTab(widget.title);
	            return;
	        }
	        // Otherwise, the tab node needs to be removed...
	        // Dispose the tab bar.
	        tabNode.tabBar.dispose();
	        // Handle the case where the tab node is the root.
	        if (this._root === tabNode) {
	            this._root = null;
	            return;
	        }
	        // Otherwise, remove the tab node from its parent...
	        // Prevent widget resizing unless needed.
	        Private.holdLayoutSizes(this._root);
	        // Clear the parent reference on the tab node.
	        var splitNode = tabNode.parent;
	        tabNode.parent = null;
	        // Remove the tab node from its parent split node.
	        var i = splitNode.children.remove(tabNode);
	        var handle = splitNode.handles.removeAt(i);
	        splitNode.sizers.removeAt(i);
	        // Remove the handle from its parent DOM node.
	        if (handle.parentNode) {
	            handle.parentNode.removeChild(handle);
	        }
	        // If there are multiple children, just update the handles.
	        if (splitNode.children.length > 1) {
	            Private.syncHandles(splitNode);
	            return;
	        }
	        // Otherwise, the split node also needs to be removed...
	        // Clear the parent reference on the split node.
	        var parentNode = splitNode.parent;
	        splitNode.parent = null;
	        // Lookup the remaining child node and handle.
	        var childNode = splitNode.children.front;
	        var childHandle = splitNode.handles.front;
	        // Clear the split node data.
	        splitNode.children.clear();
	        splitNode.handles.clear();
	        splitNode.sizers.clear();
	        // Remove the child handle from its parent node.
	        if (childHandle.parentNode) {
	            childHandle.parentNode.removeChild(childHandle);
	        }
	        // Handle the case where the split node is the root.
	        if (this._root === splitNode) {
	            childNode.parent = null;
	            this._root = childNode;
	            return;
	        }
	        // Otherwise, move the child node to the parent node...
	        // Lookup the index of the split node.
	        var j = searching_1.indexOf(parentNode.children, splitNode);
	        // Handle the case where the child node is a tab node.
	        if (childNode instanceof Private.TabLayoutNode) {
	            childNode.parent = parentNode;
	            parentNode.children.set(j, childNode);
	            return;
	        }
	        // Remove the split data from the parent.
	        var splitHandle = parentNode.handles.removeAt(j);
	        parentNode.children.removeAt(j);
	        parentNode.sizers.removeAt(j);
	        // Remove the handle from its parent node.
	        if (splitHandle.parentNode) {
	            splitHandle.parentNode.removeChild(splitHandle);
	        }
	        // The child node and the split parent node will have the same
	        // orientation. Merge the grand-children with the parent node.
	        for (var i_1 = 0, n = childNode.children.length; i_1 < n; ++i_1) {
	            var gChild = childNode.children.at(i_1);
	            var gHandle = childNode.handles.at(i_1);
	            var gSizer = childNode.sizers.at(i_1);
	            parentNode.children.insert(j + i_1, gChild);
	            parentNode.handles.insert(j + i_1, gHandle);
	            parentNode.sizers.insert(j + i_1, gSizer);
	            gChild.parent = parentNode;
	        }
	        // Clear the child node.
	        childNode.children.clear();
	        childNode.handles.clear();
	        childNode.sizers.clear();
	        childNode.parent = null;
	        // Sync the handles on the parent node.
	        Private.syncHandles(parentNode);
	    };
	    /**
	     * Insert a widget next to an existing tab.
	     *
	     * @param widget - The widget to add to the layout.
	     *
	     * @param ref - The reference widget, or `null`.
	     *
	     * @param refNode - The layout node for the ref widget, or `null`.
	     *
	     * @param after - Whether to insert the widget after the ref.
	     *
	     * #### Notes
	     * This assumes the target widget is not in the layout tree.
	     *
	     * This does not attach the widget to the parent widget.
	     */
	    DockLayout.prototype._insertTab = function (widget, ref, refNode, after) {
	        // Do nothing if the tab is inserted next to itself.
	        if (widget === ref) {
	            return;
	        }
	        // Create the root if it does not exist.
	        if (!this._root) {
	            var tabNode = new Private.TabLayoutNode(this._createTabBar());
	            tabNode.tabBar.addTab(widget.title);
	            this._root = tabNode;
	            return;
	        }
	        // Use the first tab node as the ref node if needed.
	        if (!refNode) {
	            refNode = Private.firstTabNode(this._root);
	        }
	        // If the widget is not contained in the ref node, ensure it is
	        // removed from the layout and hidden before being added again.
	        if (!searching_1.contains(refNode.tabBar.titles, widget.title)) {
	            this._removeWidget(widget);
	            widget.hide();
	        }
	        // Lookup the target index for inserting the tab.
	        var index;
	        if (ref) {
	            index = searching_1.indexOf(refNode.tabBar.titles, ref.title);
	        }
	        else {
	            index = refNode.tabBar.currentIndex;
	        }
	        // Insert the widget's tab relative to the target index.
	        refNode.tabBar.insertTab(index + (after ? 1 : 0), widget.title);
	    };
	    /**
	     * Insert a widget as a new split area.
	     *
	     * @param widget - The widget to add to the layout.
	     *
	     * @param ref - The reference widget, or `null`.
	     *
	     * @param refNode - The layout node for the ref widget, or `null`.
	     *
	     * @param orientation - The orientation for the split.
	     *
	     * @param after - Whether to insert the widget after the ref.
	     *
	     * #### Notes
	     * This assumes the target widget is not in the layout tree.
	     *
	     * This does not attach the widget to the parent widget.
	     */
	    DockLayout.prototype._insertSplit = function (widget, ref, refNode, orientation, after) {
	        // Do nothing if there is no effective split.
	        if (widget === ref && refNode.tabBar.titles.length === 1) {
	            return;
	        }
	        // Ensure the widget is removed from the current layout.
	        this._removeWidget(widget);
	        // Create the tab layout node to hold the widget.
	        var tabNode = new Private.TabLayoutNode(this._createTabBar());
	        tabNode.tabBar.addTab(widget.title);
	        // Set the root if it does not exist.
	        if (!this._root) {
	            this._root = tabNode;
	            return;
	        }
	        // Lookup the split node for the ref widget.
	        var splitNode = refNode ? refNode.parent : null;
	        // If the split node is null, split the root.
	        if (!splitNode) {
	            // Ensure the root is split with the correct orientation.
	            var root = this._splitRoot(orientation);
	            // Determine the insert index for the new tab node.
	            var i_2 = after ? root.children.length : 0;
	            // Normalize the split node.
	            Private.normalizeSizes(root);
	            // Insert the tab node sized to the golden ratio.
	            root.children.insert(i_2, tabNode);
	            root.sizers.insert(i_2, Private.createSizer(GOLDEN));
	            root.handles.insert(i_2, this._createHandle());
	            tabNode.parent = root;
	            // Re-normalize the split node to maintain the ratios.
	            Private.normalizeSizes(root);
	            // Finally, synchronize the visibility of the handles.
	            Private.syncHandles(root);
	            return;
	        }
	        // If the split node already had the correct orientation,
	        // the widget can be inserted into the split node directly.
	        if (splitNode.orientation === orientation) {
	            // Find the index of the ref node.
	            var i_3 = searching_1.indexOf(splitNode.children, refNode);
	            // Normalize the split node.
	            Private.normalizeSizes(splitNode);
	            // Consume half the space for the insert location.
	            var s = splitNode.sizers.at(i_3).sizeHint /= 2;
	            // Insert the tab node sized to the other half.
	            var j_1 = i_3 + (after ? 1 : 0);
	            splitNode.children.insert(j_1, tabNode);
	            splitNode.sizers.insert(j_1, Private.createSizer(s));
	            splitNode.handles.insert(j_1, this._createHandle());
	            tabNode.parent = splitNode;
	            // Finally, synchronize the visibility of the handles.
	            Private.syncHandles(splitNode);
	            return;
	        }
	        // Remove the ref node from the split node.
	        var i = splitNode.children.remove(refNode);
	        // Create a new normalized split node for the children.
	        var childNode = new Private.SplitLayoutNode(orientation);
	        childNode.normalized = true;
	        // Add the ref node sized to half the space.
	        childNode.children.pushBack(refNode);
	        childNode.sizers.pushBack(Private.createSizer(0.5));
	        childNode.handles.pushBack(this._createHandle());
	        refNode.parent = childNode;
	        // Add the tab node sized to the other half.
	        var j = after ? 1 : 0;
	        childNode.children.insert(j, tabNode);
	        childNode.sizers.insert(j, Private.createSizer(0.5));
	        childNode.handles.insert(j, this._createHandle());
	        tabNode.parent = childNode;
	        // Synchronize the visibility of the handles.
	        Private.syncHandles(childNode);
	        // Finally, add the new child node to the original split node.
	        splitNode.children.insert(i, childNode);
	        childNode.parent = splitNode;
	    };
	    /**
	     * Ensure the root is a split node with the given orientation.
	     *
	     * @param orientation - The required orientation of the root.
	     *
	     * @returns The new root node (as a convenience).
	     */
	    DockLayout.prototype._splitRoot = function (orientation) {
	        // Bail early if the root already meets the requirements.
	        var root = this._root;
	        if (root instanceof Private.SplitLayoutNode) {
	            if (root.orientation === orientation) {
	                return root;
	            }
	        }
	        // Create a new root node with the specified orientation.
	        var result = this._root = new Private.SplitLayoutNode(orientation);
	        // Add the old root to the new root.
	        result.children.pushBack(root);
	        result.sizers.pushBack(Private.createSizer(0));
	        result.handles.pushBack(this._createHandle());
	        root.parent = result;
	        // Return the new root as a convenience.
	        return result;
	    };
	    /**
	     * Fit the layout to the total size required by the widgets.
	     */
	    DockLayout.prototype._fit = function () {
	        // Setup the size limits.
	        var minW = 0;
	        var minH = 0;
	        var maxW = Infinity;
	        var maxH = Infinity;
	        // Update the limits for the root layout node.
	        if (this._root) {
	            var limits = Private.fitLayoutNode(this._root, this._spacing);
	            minW = limits.minWidth;
	            minH = limits.minHeight;
	            maxW = limits.maxWidth;
	            maxH = limits.maxHeight;
	        }
	        // Update the box sizing and add it to the size limits.
	        var box = this._box = sizing_1.boxSizing(this.parent.node);
	        minW += box.horizontalSum;
	        minH += box.verticalSum;
	        maxW += box.horizontalSum;
	        maxH += box.verticalSum;
	        // Update the parent's size constraints.
	        var style = this.parent.node.style;
	        style.minWidth = minW + "px";
	        style.minHeight = minH + "px";
	        style.maxWidth = maxW === Infinity ? 'none' : maxW + "px";
	        style.maxHeight = maxH === Infinity ? 'none' : maxH + "px";
	        // Set the dirty flag to ensure only a single update occurs.
	        this._dirty = true;
	        // Notify the ancestor that it should fit immediately. This may
	        // cause a resize of the parent, fulfilling the required update.
	        if (this.parent.parent) {
	            messaging_1.sendMessage(this.parent.parent, widget_1.WidgetMessage.FitRequest);
	        }
	        // If the dirty flag is still set, the parent was not resized.
	        // Trigger the required update on the parent widget immediately.
	        if (this._dirty) {
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.UpdateRequest);
	        }
	    };
	    /**
	     * Update the layout position and size of the widgets.
	     *
	     * The parent offset dimensions should be `-1` if unknown.
	     */
	    DockLayout.prototype._update = function (offsetWidth, offsetHeight) {
	        // Clear the dirty flag to indicate the update occurred.
	        this._dirty = false;
	        // Bail early if there is no root layout node.
	        if (!this._root) {
	            return;
	        }
	        // Measure the parent if the offset dimensions are unknown.
	        if (offsetWidth < 0) {
	            offsetWidth = this.parent.node.offsetWidth;
	        }
	        if (offsetHeight < 0) {
	            offsetHeight = this.parent.node.offsetHeight;
	        }
	        // Ensure the parent box sizing data is computed.
	        var box = this._box || (this._box = sizing_1.boxSizing(this.parent.node));
	        // Compute the actual layout bounds adjusted for border and padding.
	        var x = box.paddingTop;
	        var y = box.paddingLeft;
	        var width = offsetWidth - box.horizontalSum;
	        var height = offsetHeight - box.verticalSum;
	        // Update the geometry of the root layout node.
	        Private.updateLayoutNode(this._root, x, y, width, height, this._spacing);
	    };
	    /**
	     * Create a new tab bar for use by the dock layout.
	     *
	     * #### Notes
	     * The tab bar will be attached to the parent if it exists.
	     */
	    DockLayout.prototype._createTabBar = function () {
	        // Create the tab bar using the renderer.
	        var tabBar = this._renderer.createTabBar();
	        // Enforce necessary tab bar behavior.
	        // TODO do we really want to enforce *all* of these?
	        tabBar.tabsMovable = true;
	        tabBar.allowDeselect = false;
	        tabBar.orientation = 'horizontal';
	        tabBar.removeBehavior = 'select-previous-tab';
	        tabBar.insertBehavior = 'select-tab-if-needed';
	        // Setup the signal handlers for the tab bar.
	        tabBar.currentChanged.connect(this._onCurrentChanged, this);
	        // Reparent and attach the tab bar to the parent if possible.
	        if (this.parent) {
	            tabBar.parent = this.parent;
	            this.attachWidget(tabBar);
	        }
	        // Return the initialized tab bar.
	        return tabBar;
	    };
	    /**
	     * Create a new handle for the dock layout.
	     *
	     * #### Notes
	     * The handle will be attached to the parent if it exists.
	     */
	    DockLayout.prototype._createHandle = function () {
	        // Create the handle using the renderer.
	        var handle = this._renderer.createHandle();
	        // Initialize the handle layout behavior.
	        var style = handle.style;
	        style.position = 'absolute';
	        style.top = '0';
	        style.left = '0';
	        style.width = '0';
	        style.height = '0';
	        // Attach the handle to the parent if it exists.
	        if (this.parent) {
	            this.parent.node.appendChild(handle);
	        }
	        // Return the initialized handle.
	        return handle;
	    };
	    /**
	     * Handle the `currentChanged` signal from a tab bar in the layout.
	     */
	    DockLayout.prototype._onCurrentChanged = function (sender, args) {
	        // Extract the previous and current title from the args.
	        var previousTitle = args.previousTitle, currentTitle = args.currentTitle;
	        // Extract the widgets from the titles.
	        var previousWidget = previousTitle ? previousTitle.owner : null;
	        var currentWidget = currentTitle ? currentTitle.owner : null;
	        // Hide the previous widget.
	        if (previousWidget) {
	            previousWidget.hide();
	        }
	        // Show the current widget.
	        if (currentWidget) {
	            currentWidget.show();
	        }
	    };
	    return DockLayout;
	}(widget_1.Layout));
	exports.DockLayout = DockLayout;
	/**
	 * The namespace for the module private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * A layout node which holds the data for a tabbed area.
	     */
	    var TabLayoutNode = (function () {
	        /**
	         * Construct a new tab layout node.
	         *
	         * @param tabBar - The tab bar to use for the layout node.
	         */
	        function TabLayoutNode(tabBar) {
	            /**
	             * The parent of the layout node, or `null`.
	             */
	            this.parent = null;
	            /**
	             * The box sizers for the tab bar and current widget.
	             */
	            this.sizers = new vector_1.Vector();
	            var tabSizer = new boxengine_1.BoxSizer();
	            var widgetSizer = new boxengine_1.BoxSizer();
	            tabSizer.stretch = 0;
	            widgetSizer.stretch = 1;
	            this.sizers.pushBack(tabSizer);
	            this.sizers.pushBack(widgetSizer);
	            this.tabBar = tabBar;
	        }
	        return TabLayoutNode;
	    }());
	    Private.TabLayoutNode = TabLayoutNode;
	    /**
	     * A layout node which holds the data for a split area.
	     */
	    var SplitLayoutNode = (function () {
	        /**
	         * Construct a new split layout node.
	         *
	         * @param orientation - The orientation of the node.
	         */
	        function SplitLayoutNode(orientation) {
	            /**
	             * The parent of the layout node, or `null`.
	             */
	            this.parent = null;
	            /**
	             * Whether the sizers have been normalized.
	             */
	            this.normalized = false;
	            /**
	             * The child nodes for the split node.
	             */
	            this.children = new vector_1.Vector();
	            /**
	             * The box sizers for the layout children.
	             */
	            this.sizers = new vector_1.Vector();
	            /**
	             * The handles for the layout children.
	             */
	            this.handles = new vector_1.Vector();
	            this.orientation = orientation;
	        }
	        return SplitLayoutNode;
	    }());
	    Private.SplitLayoutNode = SplitLayoutNode;
	    /**
	     * Clamp a spacing value to an integer >= 0.
	     */
	    function clampSpacing(value) {
	        return Math.max(0, Math.floor(value));
	    }
	    Private.clampSpacing = clampSpacing;
	    /**
	     * Create an iterator for all widgets in the layout tree.
	     *
	     * @param node - The root layout node of interest.
	     *
	     * @returns An iterator which yields all widgets in the tree.
	     *
	     * #### Notes
	     * This includes the tab bars for the tab layout nodes.
	     */
	    function iterAllWidgets(node) {
	        var it;
	        if (node instanceof TabLayoutNode) {
	            it = iteration_1.chain(iteration_1.once(node.tabBar), iterUserWidgets(node));
	        }
	        else {
	            it = new iteration_1.ChainIterator(iteration_1.map(node.children, iterAllWidgets));
	        }
	        return it;
	    }
	    Private.iterAllWidgets = iterAllWidgets;
	    /**
	     * Create an iterator for the user widgets in the layout tree.
	     *
	     * @param node - The root layout node of interest.
	     *
	     * @returns An iterator which yields the user widgets in the tree.
	     *
	     * #### Notes
	     * This does not include the tab bars for the tab layout nodes.
	     */
	    function iterUserWidgets(node) {
	        var it;
	        if (node instanceof TabLayoutNode) {
	            it = iteration_1.map(node.tabBar.titles, function (title) { return title.owner; });
	        }
	        else {
	            it = new iteration_1.ChainIterator(iteration_1.map(node.children, iterUserWidgets));
	        }
	        return it;
	    }
	    Private.iterUserWidgets = iterUserWidgets;
	    /**
	     * Create an iterator for the tab bars in the tree.
	     *
	     * @param node - The root layout node of interest.
	     *
	     * @returns An iterator which yields the tab bars in the tree.
	     */
	    function iterTabBars(node) {
	        var it;
	        if (node instanceof TabLayoutNode) {
	            it = iteration_1.once(node.tabBar);
	        }
	        else {
	            it = new iteration_1.ChainIterator(iteration_1.map(node.children, iterTabBars));
	        }
	        return it;
	    }
	    Private.iterTabBars = iterTabBars;
	    /**
	     * Create an iterator for the handles in the tree.
	     *
	     * @param node - The root layout node of interest.
	     *
	     * @returns An iterator which yields the handles in the tree.
	     */
	    function iterHandles(node) {
	        var it;
	        if (node instanceof TabLayoutNode) {
	            it = iteration_1.empty();
	        }
	        else {
	            var others = iteration_1.map(node.children, iterHandles);
	            it = iteration_1.chain(node.handles, new iteration_1.ChainIterator(others));
	        }
	        return it;
	    }
	    Private.iterHandles = iterHandles;
	    /**
	     * Get the reference widget for a tab bar.
	     *
	     * @param tabBar - The tab bar of interest.
	     *
	     * @returns The target reference widget in the tab bar, or null.
	     */
	    function tabBarRef(tabBar) {
	        if (tabBar.currentTitle) {
	            return tabBar.currentTitle.owner;
	        }
	        if (tabBar.titles.length > 0) {
	            return tabBar.titles.at(tabBar.titles.length - 1).owner;
	        }
	        return null;
	    }
	    Private.tabBarRef = tabBarRef;
	    /**
	     * Find the first tab layout node in a layout tree.
	     *
	     * @param node - The root layout node of interest.
	     *
	     * @returns The first tab node in the tree, or `null`.
	     */
	    function firstTabNode(node) {
	        // Return the node if it's a tab layout node.
	        if (node instanceof TabLayoutNode) {
	            return node;
	        }
	        // Recursively search the children for a tab layout node.
	        for (var i = 0, n = node.children.length; i < n; ++i) {
	            var result = firstTabNode(node.children.at(i));
	            if (result !== null) {
	                return result;
	            }
	        }
	        // Otherwise, there is no tab layout node.
	        return null;
	    }
	    Private.firstTabNode = firstTabNode;
	    /**
	     * Find the tab layout node which contains the given widget.
	     *
	     * @param node - The root layout node of interest.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The tab node which holds the widget, or `null`.
	     */
	    function findTabNode(node, widget) {
	        // Return the tab node if it contains the widget.
	        if (node instanceof TabLayoutNode) {
	            return searching_1.contains(node.tabBar.titles, widget.title) ? node : null;
	        }
	        // Recursively search the children of a split layout node.
	        for (var i = 0, n = node.children.length; i < n; ++i) {
	            var result = findTabNode(node.children.at(i), widget);
	            if (result !== null) {
	                return result;
	            }
	        }
	        // Otherwise, the widget does not exist in the tree.
	        return null;
	    }
	    Private.findTabNode = findTabNode;
	    /**
	     * Find the split layout node which contains the given handle.
	     *
	     * @param node - The root layout node of interest.
	     *
	     * @param handle - The handle of interest.
	     *
	     * @returns An object which contains the split node and the index
	     *   of the handle, or `null` if the split node is not found.
	     */
	    function findSplitNode(node, handle) {
	        // Bail if the node is not a split node.
	        if (node instanceof TabLayoutNode) {
	            return null;
	        }
	        // Return the pair if the node contains the handle.
	        var index = searching_1.indexOf(node.handles, handle);
	        if (index !== -1) {
	            return { index: index, node: node };
	        }
	        // Recursively search the child split nodes.
	        for (var i = 0, n = node.children.length; i < n; ++i) {
	            var result = findSplitNode(node.children.at(i), handle);
	            if (result !== null) {
	                return result;
	            }
	        }
	        // Otherwise, the handle does not exist in the tree.
	        return null;
	    }
	    Private.findSplitNode = findSplitNode;
	    /**
	     * Recursively fit the given layout node.
	     *
	     * @param node - The layout node of interest.
	     *
	     * @param spacing - The spacing to use between tab areas.
	     *
	     * @returns The computed size limits for the layout node.
	     */
	    function fitLayoutNode(node, spacing) {
	        var limits;
	        if (node instanceof TabLayoutNode) {
	            limits = fitTabNode(node);
	        }
	        else {
	            limits = fitSplitNode(node, spacing);
	        }
	        return limits;
	    }
	    Private.fitLayoutNode = fitLayoutNode;
	    /**
	     * Recursively update the given layout node.
	     *
	     * @param node - The layout node of interest.
	     *
	     * @param x - The offset left position of the layout area.
	     *
	     * @param y - The offset top position of the layout area.
	     *
	     * @param width - The width of the layout area.
	     *
	     * @param height - The height of the layout area.
	     *
	     * @param spacing - The spacing to use between tab areas.
	     */
	    function updateLayoutNode(node, x, y, width, height, spacing) {
	        if (node instanceof TabLayoutNode) {
	            updateTabNode(node, x, y, width, height);
	        }
	        else {
	            updateSplitNode(node, x, y, width, height, spacing);
	        }
	    }
	    Private.updateLayoutNode = updateLayoutNode;
	    /**
	     * Sync the visibility and orientation of split node handles.
	     *
	     * @param splitNode - The split node of interest.
	     */
	    function syncHandles(splitNode) {
	        // Do nothing if there are no handles.
	        if (splitNode.handles.isEmpty) {
	            return;
	        }
	        // Compute the classes to add and remove.
	        var horizontal = splitNode.orientation === 'horizontal';
	        var remClass = horizontal ? VERTICAL_CLASS : HORIZONTAL_CLASS;
	        var addClass = horizontal ? HORIZONTAL_CLASS : VERTICAL_CLASS;
	        // Show all handles and update their orientation.
	        iteration_1.each(splitNode.handles, function (handle) {
	            handle.classList.remove(HIDDEN_CLASS);
	            handle.classList.remove(remClass);
	            handle.classList.add(addClass);
	        });
	        // Hide the last handle.
	        splitNode.handles.back.classList.add(HIDDEN_CLASS);
	    }
	    Private.syncHandles = syncHandles;
	    /**
	     * Determine the zone for the given node and client position.
	     *
	     * This assumes the position lies within the node's client rect.
	     */
	    function calcEdge(node, x, y) {
	        var rect = node.getBoundingClientRect();
	        var fracX = (x - rect.left) / rect.width;
	        var fracY = (y - rect.top) / rect.height;
	        var normX = fracX > 0.5 ? 1 - fracX : fracX;
	        var normY = fracY > 0.5 ? 1 - fracY : fracY;
	        var result;
	        if (normX < normY) {
	            result = fracX <= 0.5 ? 'left' : 'right';
	        }
	        else {
	            result = fracY <= 0.5 ? 'top' : 'bottom';
	        }
	        return result;
	    }
	    Private.calcEdge = calcEdge;
	    /**
	     * Hold the current sizes of a vector of box sizers.
	     *
	     * This sets the size hint of each sizer to its current size.
	     */
	    function holdSizes(sizers) {
	        iteration_1.each(sizers, function (sizer) { sizer.sizeHint = sizer.size; });
	    }
	    Private.holdSizes = holdSizes;
	    /**
	     * Recursively hold all the layout sizes in the tree.
	     *
	     * This ignores the sizers of tab layout nodes.
	     */
	    function holdLayoutSizes(node) {
	        if (node instanceof SplitLayoutNode) {
	            iteration_1.each(node.children, holdLayoutSizes);
	            holdSizes(node.sizers);
	        }
	    }
	    Private.holdLayoutSizes = holdLayoutSizes;
	    /**
	     * Create a box sizer with an initial size hint.
	     */
	    function createSizer(hint) {
	        var sizer = new boxengine_1.BoxSizer();
	        sizer.sizeHint = hint;
	        sizer.size = hint;
	        return sizer;
	    }
	    Private.createSizer = createSizer;
	    /**
	     * Normalize the sizes of a split layout node.
	     */
	    function normalizeSizes(splitNode) {
	        // Bail early if the sizers are empty.
	        var n = splitNode.sizers.length;
	        if (n === 0) {
	            return;
	        }
	        // Hold the current sizes of the sizers.
	        holdSizes(splitNode.sizers);
	        // Compute the sum of the sizes.
	        var sum = iteration_1.reduce(splitNode.sizers, function (v, sizer) { return v + sizer.sizeHint; }, 0);
	        // Normalize the sizes based on the sum.
	        if (sum === 0) {
	            iteration_1.each(splitNode.sizers, function (sizer) {
	                sizer.size = sizer.sizeHint = 1 / n;
	            });
	        }
	        else {
	            iteration_1.each(splitNode.sizers, function (sizer) {
	                sizer.size = sizer.sizeHint /= sum;
	            });
	        }
	        // Mark the split node as normalized.
	        splitNode.normalized = true;
	    }
	    Private.normalizeSizes = normalizeSizes;
	    /**
	     * Fit the given tab layout node.
	     *
	     * @param tabNode - The tab node of interest.
	     *
	     * @returns The computed size limits for the node.
	     */
	    function fitTabNode(tabNode) {
	        // Setup the limit variables.
	        var minWidth = 0;
	        var minHeight = 0;
	        var maxWidth = Infinity;
	        var maxHeight = Infinity;
	        // Lookup common variables.
	        var tabBar = tabNode.tabBar;
	        var tabSizer = tabNode.sizers.at(0);
	        var widgetSizer = tabNode.sizers.at(1);
	        var currentTitle = tabBar.currentTitle;
	        var widget = currentTitle ? currentTitle.owner : null;
	        // Adjust the starting max height if a widget is visible.
	        if (!tabBar.isHidden || (widget && !widget.isHidden)) {
	            maxHeight = 0;
	        }
	        // Update the results and sizer for the tab bar.
	        if (!tabBar.isHidden) {
	            var limits = sizing_1.sizeLimits(tabBar.node);
	            minWidth = Math.max(minWidth, limits.minWidth);
	            maxWidth = Math.min(maxWidth, limits.maxWidth);
	            minHeight += limits.minHeight;
	            maxHeight += limits.maxHeight;
	            tabSizer.minSize = limits.minHeight;
	            tabSizer.maxSize = limits.maxHeight;
	        }
	        else {
	            tabSizer.minSize = 0;
	            tabSizer.maxSize = 0;
	        }
	        // Update the results and sizer for the current widget.
	        if (widget && !widget.isHidden) {
	            var limits = sizing_1.sizeLimits(widget.node);
	            minWidth = Math.max(minWidth, limits.minWidth);
	            maxWidth = Math.min(maxWidth, limits.maxWidth);
	            minHeight += limits.minHeight;
	            maxHeight += limits.maxHeight;
	            widgetSizer.minSize = limits.minHeight;
	            widgetSizer.maxSize = limits.maxHeight;
	        }
	        else {
	            widgetSizer.minSize = 0;
	            widgetSizer.maxSize = 0;
	        }
	        // Return the computed size limits for the layout node.
	        return { minWidth: minWidth, minHeight: minHeight, maxWidth: maxWidth, maxHeight: maxHeight };
	    }
	    /**
	     * Recursively fit the given split layout node.
	     *
	     * @param splitNode - The split node of interest.
	     *
	     * @returns The computed size limits for the node.
	     */
	    function fitSplitNode(splitNode, spacing) {
	        // Setup the limit variables.
	        var minWidth = 0;
	        var minHeight = 0;
	        var maxWidth = Infinity;
	        var maxHeight = Infinity;
	        // Compute common values.
	        var horizontal = splitNode.orientation === 'horizontal';
	        var fixed = Math.max(0, splitNode.children.length - 1) * spacing;
	        // Adjust the starting limits for the orientation.
	        if (horizontal) {
	            minWidth = fixed;
	            maxWidth = fixed;
	        }
	        else {
	            minHeight = fixed;
	            maxHeight = fixed;
	        }
	        // Adjust the limits and sizer for each child area.
	        for (var i = 0, n = splitNode.children.length; i < n; ++i) {
	            var sizer = splitNode.sizers.at(i);
	            var child = splitNode.children.at(i);
	            var limits = fitLayoutNode(child, spacing);
	            if (horizontal) {
	                minHeight = Math.max(minHeight, limits.minHeight);
	                maxHeight = Math.min(maxHeight, limits.maxHeight);
	                minWidth += limits.minWidth;
	                maxWidth += limits.maxWidth;
	                sizer.minSize = limits.minWidth;
	                sizer.maxSize = limits.maxWidth;
	            }
	            else {
	                minWidth = Math.max(minWidth, limits.minWidth);
	                maxWidth = Math.min(maxWidth, limits.maxWidth);
	                minHeight += limits.minHeight;
	                maxHeight += limits.maxHeight;
	                sizer.minSize = limits.minHeight;
	                sizer.maxSize = limits.maxHeight;
	            }
	        }
	        // Return the computed size limits for the layout node.
	        return { minWidth: minWidth, minHeight: minHeight, maxWidth: maxWidth, maxHeight: maxHeight };
	    }
	    /**
	     * Update the given tab layout node.
	     *
	     * @param tabNode - The tab node of interest.
	     *
	     * @param x - The offset left position of the layout area.
	     *
	     * @param y - The offset top position of the layout area.
	     *
	     * @param width - The width of the layout area.
	     *
	     * @param height - The height of the layout area.
	     */
	    function updateTabNode(tabNode, x, y, width, height) {
	        // Lookup common variables.
	        var tabBar = tabNode.tabBar;
	        var tabSizer = tabNode.sizers.at(0);
	        var widgetSizer = tabNode.sizers.at(1);
	        var currentTitle = tabBar.currentTitle;
	        var widget = currentTitle ? currentTitle.owner : null;
	        // Distribute the layout space to the sizers.
	        boxengine_1.boxCalc(tabNode.sizers, height);
	        // Layout the tab bar using the computed size.
	        if (!tabBar.isHidden) {
	            widget_1.Widget.setGeometry(tabBar, x, y, width, tabSizer.size);
	            y += tabSizer.size;
	        }
	        // Layout the widget using the computed size.
	        if (widget && !widget.isHidden) {
	            widget_1.Widget.setGeometry(widget, x, y, width, widgetSizer.size);
	        }
	    }
	    /**
	     * Update the given split layout node.
	     *
	     * @param splitNode - The split node of interest.
	     *
	     * @param x - The offset left position of the layout area.
	     *
	     * @param y - The offset top position of the layout area.
	     *
	     * @param width - The width of the layout area.
	     *
	     * @param height - The height of the layout area.
	     *
	     * @param spacing - The spacing to use between tab areas.
	     */
	    function updateSplitNode(splitNode, x, y, width, height, spacing) {
	        // Compute the available layout space.
	        var horizontal = splitNode.orientation === 'horizontal';
	        var fixed = Math.max(0, splitNode.children.length - 1) * spacing;
	        var space = Math.max(0, (horizontal ? width : height) - fixed);
	        // De-normalize the split node if needed.
	        if (splitNode.normalized) {
	            iteration_1.each(splitNode.sizers, function (sizer) { sizer.sizeHint *= space; });
	            splitNode.normalized = false;
	        }
	        // Distribute the layout space to the sizers.
	        boxengine_1.boxCalc(splitNode.sizers, space);
	        // Update the geometry of the child areas and handles.
	        for (var i = 0, n = splitNode.children.length; i < n; ++i) {
	            var child = splitNode.children.at(i);
	            var size = splitNode.sizers.at(i).size;
	            var hStyle = splitNode.handles.at(i).style;
	            if (horizontal) {
	                updateLayoutNode(child, x, y, size, height, spacing);
	                x += size;
	                hStyle.top = y + "px";
	                hStyle.left = x + "px";
	                hStyle.width = spacing + "px";
	                hStyle.height = height + "px";
	                x += spacing;
	            }
	            else {
	                updateLayoutNode(child, x, y, width, size, spacing);
	                y += size;
	                hStyle.top = y + "px";
	                hStyle.left = x + "px";
	                hStyle.width = width + "px";
	                hStyle.height = spacing + "px";
	                y += spacing;
	            }
	        }
	    }
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/dockpanel.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/core/mimedata.js **/
jupyter.define('phosphor@0.7.0/lib/core/mimedata.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * An object which stores MIME data for general application use.
	 *
	 * #### Notes
	 * This class does not attempt to enforce "correctness" of MIME types
	 * and their associated data. Since this class is designed to transfer
	 * arbitrary data and objects within the same application, it assumes
	 * that the user provides correct and accurate data.
	 */
	var MimeData = (function () {
	    function MimeData() {
	        this._types = [];
	        this._values = [];
	    }
	    /**
	     * Get an array of the MIME types contained within the dataset.
	     *
	     * @returns A new array of the MIME types, in order of insertion.
	     */
	    MimeData.prototype.types = function () {
	        return this._types.slice();
	    };
	    /**
	     * Test whether the dataset has an entry for the given type.
	     *
	     * @param mime - The MIME type of interest.
	     *
	     * @returns `true` if the dataset contains a value for the given
	     *   MIME type, `false` otherwise.
	     */
	    MimeData.prototype.hasData = function (mime) {
	        return this._types.indexOf(mime) !== -1;
	    };
	    /**
	     * Get the data value for the given MIME type.
	     *
	     * @param mime - The MIME type of interest.
	     *
	     * @returns The value for the given MIME type, or `undefined` if
	     *   the dataset does not contain a value for the type.
	     */
	    MimeData.prototype.getData = function (mime) {
	        var i = this._types.indexOf(mime);
	        return i !== -1 ? this._values[i] : void 0;
	    };
	    /**
	     * Set the data value for the given MIME type.
	     *
	     * @param mime - The MIME type of interest.
	     *
	     * @param data - The data value for the given MIME type.
	     *
	     * #### Notes
	     * This will overwrite any previous entry for the MIME type.
	     */
	    MimeData.prototype.setData = function (mime, data) {
	        this.clearData(mime);
	        this._types.push(mime);
	        this._values.push(data);
	    };
	    /**
	     * Remove the data entry for the given MIME type.
	     *
	     * @param mime - The MIME type of interest.
	     *
	     * #### Notes
	     * This is a no-op if there is no entry for the given MIME type.
	     */
	    MimeData.prototype.clearData = function (mime) {
	        var i = this._types.indexOf(mime);
	        if (i === -1)
	            return;
	        this._types.splice(i, 1);
	        this._values.splice(i, 1);
	    };
	    /**
	     * Remove all data entries from the dataset.
	     */
	    MimeData.prototype.clear = function () {
	        this._types.length = 0;
	        this._values.length = 0;
	    };
	    return MimeData;
	}());
	exports.MimeData = MimeData;
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/core/mimedata.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/dom/cursor.js **/
jupyter.define('phosphor@0.7.0/lib/dom/cursor.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var disposable_1 = __jupyter_require__('phosphor@0.7.0/lib/core/disposable.js');
	/**
	 * The class name added to the document body during cursor override.
	 */
	var OVERRIDE_CURSOR_CLASS = 'p-mod-override-cursor';
	/**
	 * Override the cursor for the entire document.
	 *
	 * @param cursor - The string representing the cursor style.
	 *
	 * @returns A disposable which will clear the override when disposed.
	 *
	 * #### Notes
	 * The most recent call to `overrideCursor` takes precedence. Disposing
	 * an old override is a no-op and will not effect the current override.
	 *
	 * #### Example
	 * ```typescript
	 * import { overrideCursor } from 'phosphor/lib/dom/cursor';
	 *
	 * // force the cursor to be 'wait' for the entire document
	 * let override = overrideCursor('wait');
	 *
	 * // clear the override by disposing the return value
	 * override.dispose();
	 * ```
	 */
	function overrideCursor(cursor) {
	    var id = ++Private.cursorID;
	    var body = document.body;
	    body.style.cursor = cursor;
	    body.classList.add(OVERRIDE_CURSOR_CLASS);
	    return new disposable_1.DisposableDelegate(function () {
	        if (id === Private.cursorID) {
	            body.style.cursor = '';
	            body.classList.remove(OVERRIDE_CURSOR_CLASS);
	        }
	    });
	}
	exports.overrideCursor = overrideCursor;
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * The id for the active cursor override.
	     */
	    Private.cursorID = 0;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/dom/cursor.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/dom/dragdrop.js **/
jupyter.define('phosphor@0.7.0/lib/dom/dragdrop.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var cursor_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/cursor.js');
	/**
	 * The class name added to drag image nodes.
	 */
	var DRAG_IMAGE_CLASS = 'p-mod-drag-image';
	/**
	 * An object which manages a drag-drop operation.
	 *
	 * A drag object dispatches four different events to drop targets:
	 *
	 * - `'p-dragenter'` - Dispatched when the mouse enters the target
	 *   element. This event must be canceled in order to receive any
	 *   of the other events.
	 *
	 * - `'p-dragover'` - Dispatched when the mouse moves over the drop
	 *   target. It must cancel the event and set the `dropAction` to one
	 *   of the supported actions in order to receive drop events.
	 *
	 * - `'p-dragleave'` - Dispatched when the mouse leaves the target
	 *   element. This includes moving the mouse into child elements.
	 *
	 * - `'p-drop'`- Dispatched when the mouse is released over the target
	 *   element when the target indicates an appropriate drop action. If
	 *   the event is canceled, the indicated drop action is returned to
	 *   the initiator through the resolved promise.
	 *
	 * A drag operation can be canceled at any time by pressing `Escape`
	 * or by disposing the drag object.
	 *
	 * #### Notes
	 * This class is designed to be used when dragging and dropping custom
	 * data *within* a single application. It is *not* a replacement for
	 * the native drag-drop API. Instead, it provides an API which allows
	 * drag operations to be initiated programmatically and enables the
	 * transfer of arbitrary non-string objects; two features which are
	 * not possible with the native drag-drop APIs.
	 */
	var Drag = (function () {
	    /**
	     * Construct a new drag object.
	     *
	     * @param options - The options for initializing the drag.
	     */
	    function Drag(options) {
	        this._disposed = false;
	        this._source = null;
	        this._mimeData = null;
	        this._dragImage = null;
	        this._dropAction = 'none';
	        this._proposedAction = 'copy';
	        this._supportedActions = 'all';
	        this._override = null;
	        this._currentTarget = null;
	        this._currentElement = null;
	        this._promise = null;
	        this._resolve = null;
	        this._mimeData = options.mimeData;
	        if (options.dragImage !== void 0) {
	            this._dragImage = options.dragImage;
	        }
	        if (options.proposedAction !== void 0) {
	            this._proposedAction = options.proposedAction;
	        }
	        if (options.supportedActions !== void 0) {
	            this._supportedActions = options.supportedActions;
	        }
	        if (options.source !== void 0) {
	            this._source = options.source;
	        }
	    }
	    /**
	     * Dispose of the resources held by the drag object.
	     *
	     * #### Notes
	     * This will cancel the drag operation if it is active.
	     *
	     * All calls made after the first call to this method are a no-op.
	     */
	    Drag.prototype.dispose = function () {
	        // Do nothing if the drag object is already disposed.
	        if (this._disposed) {
	            return;
	        }
	        this._disposed = true;
	        // If there is a current target, dispatch a drag leave event.
	        if (this._currentTarget) {
	            var event_1 = Private.createMouseEvent('mouseup', -1, -1);
	            Private.dispatchDragLeave(this, this._currentTarget, null, event_1);
	        }
	        // Finalize the drag object with `'none'`.
	        this._finalize('none');
	    };
	    Object.defineProperty(Drag.prototype, "isDisposed", {
	        /**
	         * Test whether the drag object is disposed.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._disposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Drag.prototype, "mimeData", {
	        /**
	         * Get the mime data for the drag object.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._mimeData;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Drag.prototype, "dragImage", {
	        /**
	         * Get the drag image element for the drag object.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._dragImage;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Drag.prototype, "proposedAction", {
	        /**
	         * Get the proposed drop action for the drag object.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._proposedAction;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Drag.prototype, "supportedActions", {
	        /**
	         * Get the supported drop actions for the drag object.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._supportedActions;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Drag.prototype, "source", {
	        /**
	         * Get the drag source for the drag object.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._source;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Start the drag operation at the specified client position.
	     *
	     * @param clientX - The client X position for the drag start.
	     *
	     * @param clientY - The client Y position for the drag start.
	     *
	     * @returns A promise which resolves to the result of the drag.
	     *
	     * #### Notes
	     * If the drag has already been started, the promise created by the
	     * first call to `start` is returned.
	     *
	     * If the drag operation has ended, or if the drag object has been
	     * disposed, the returned promise will resolve to `'none'`.
	     *
	     * The drag object will be automatically disposed when drag operation
	     * completes. This means `Drag` objects are for single-use only.
	     *
	     * This method assumes the left mouse button is already held down.
	     */
	    Drag.prototype.start = function (clientX, clientY) {
	        var _this = this;
	        // If the drag object is already disposed, resolve to `None`.
	        if (this._disposed) {
	            return Promise.resolve('none');
	        }
	        // If the drag has already been started, return the promise.
	        if (this._promise) {
	            return this._promise;
	        }
	        // Install the document listeners for the drag object.
	        this._addListeners();
	        // Attach the drag image at the specified client position.
	        this._attachDragImage(clientX, clientY);
	        // Create the promise which will be resolved on completion.
	        this._promise = new Promise(function (resolve, reject) {
	            _this._resolve = resolve;
	        });
	        // Trigger a fake move event to kick off the drag operation.
	        var event = Private.createMouseEvent('mousemove', clientX, clientY);
	        document.dispatchEvent(event);
	        // Return the pending promise for the drag operation.
	        return this._promise;
	    };
	    /**
	     * Handle the DOM events for the drag operation.
	     *
	     * @param event - The DOM event sent to the drag object.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the document. It should not be
	     * called directly by user code.
	     */
	    Drag.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'mousemove':
	                this._evtMouseMove(event);
	                break;
	            case 'mouseup':
	                this._evtMouseUp(event);
	                break;
	            case 'keydown':
	                this._evtKeyDown(event);
	                break;
	            default:
	                // Stop all other events during drag-drop.
	                event.preventDefault();
	                event.stopPropagation();
	                break;
	        }
	    };
	    /**
	     * Handle the `'mousemove'` event for the drag object.
	     */
	    Drag.prototype._evtMouseMove = function (event) {
	        // Stop all input events during drag-drop.
	        event.preventDefault();
	        event.stopPropagation();
	        // Update the current target node and dispatch enter/leave events.
	        this._updateCurrentTarget(event);
	        // Move the drag image to the specified client position. This is
	        // performed *after* dispatching to prevent unnecessary reflows.
	        this._moveDragImage(event.clientX, event.clientY);
	    };
	    /**
	     * Handle the `'mouseup'` event for the drag object.
	     */
	    Drag.prototype._evtMouseUp = function (event) {
	        // Stop all input events during drag-drop.
	        event.preventDefault();
	        event.stopPropagation();
	        // Do nothing if the left button is not released.
	        if (event.button !== 0) {
	            return;
	        }
	        // Update the current target node and dispatch enter/leave events.
	        // This prevents a subtle issue where the DOM mutates under the
	        // cursor after the last move event but before the drop event.
	        this._updateCurrentTarget(event);
	        // If there is no current target, finalize with `'none'`.
	        if (!this._currentTarget) {
	            this._finalize('none');
	            return;
	        }
	        // If the last drop action was `'none'`, dispatch a leave event
	        // to the current target and finalize the drag with `'none'`.
	        if (this._dropAction === 'none') {
	            Private.dispatchDragLeave(this, this._currentTarget, null, event);
	            this._finalize('none');
	            return;
	        }
	        // Dispatch the drop event at the current target and finalize
	        // with the resulting drop action.
	        var action = Private.dispatchDrop(this, this._currentTarget, event);
	        this._finalize(action);
	    };
	    /**
	     * Handle the `'keydown'` event for the drag object.
	     */
	    Drag.prototype._evtKeyDown = function (event) {
	        // Stop all input events during drag-drop.
	        event.preventDefault();
	        event.stopPropagation();
	        // Cancel the drag if `Escape` is pressed.
	        if (event.keyCode === 27)
	            this.dispose();
	    };
	    /**
	     * Add the document event listeners for the drag object.
	     */
	    Drag.prototype._addListeners = function () {
	        document.addEventListener('mousedown', this, true);
	        document.addEventListener('mousemove', this, true);
	        document.addEventListener('mouseup', this, true);
	        document.addEventListener('mouseenter', this, true);
	        document.addEventListener('mouseleave', this, true);
	        document.addEventListener('mouseover', this, true);
	        document.addEventListener('mouseout', this, true);
	        document.addEventListener('keydown', this, true);
	        document.addEventListener('keyup', this, true);
	        document.addEventListener('keypress', this, true);
	        document.addEventListener('contextmenu', this, true);
	    };
	    /**
	     * Remove the document event listeners for the drag object.
	     */
	    Drag.prototype._removeListeners = function () {
	        document.removeEventListener('mousedown', this, true);
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('mouseup', this, true);
	        document.removeEventListener('mouseenter', this, true);
	        document.removeEventListener('mouseleave', this, true);
	        document.removeEventListener('mouseover', this, true);
	        document.removeEventListener('mouseout', this, true);
	        document.removeEventListener('keydown', this, true);
	        document.removeEventListener('keyup', this, true);
	        document.removeEventListener('keypress', this, true);
	        document.removeEventListener('contextmenu', this, true);
	    };
	    /**
	     * Update the current target node using the given mouse event.
	     */
	    Drag.prototype._updateCurrentTarget = function (event) {
	        // Fetch common local state.
	        var prevTarget = this._currentTarget;
	        var currTarget = this._currentTarget;
	        var prevElem = this._currentElement;
	        // Find the current indicated element at the given position.
	        var currElem = document.elementFromPoint(event.clientX, event.clientY);
	        // Update the current element reference.
	        this._currentElement = currElem;
	        // Note: drag enter fires *before* drag leave according to spec.
	        // https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model
	        // If the indicated element changes from the previous iteration,
	        // and is different from the current target, dispatch the enter
	        // events and compute the new target element.
	        if (currElem !== prevElem && currElem !== currTarget) {
	            currTarget = Private.dispatchDragEnter(this, currElem, currTarget, event);
	        }
	        // If the current target element has changed, update the current
	        // target reference and dispatch the leave event to the old target.
	        if (currTarget !== prevTarget) {
	            this._currentTarget = currTarget;
	            Private.dispatchDragLeave(this, prevTarget, currTarget, event);
	        }
	        // Dispatch the drag over event and update the drop action.
	        var action = Private.dispatchDragOver(this, currTarget, event);
	        this._setDropAction(action);
	    };
	    /**
	     * Attach the drag image element at the specified location.
	     *
	     * This is a no-op if there is no drag image element.
	     */
	    Drag.prototype._attachDragImage = function (clientX, clientY) {
	        if (!this._dragImage) {
	            return;
	        }
	        this._dragImage.classList.add(DRAG_IMAGE_CLASS);
	        var style = this._dragImage.style;
	        style.pointerEvents = 'none';
	        style.position = 'absolute';
	        style.top = clientY + "px";
	        style.left = clientX + "px";
	        document.body.appendChild(this._dragImage);
	    };
	    /**
	     * Move the drag image element to the specified location.
	     *
	     * This is a no-op if there is no drag image element.
	     */
	    Drag.prototype._moveDragImage = function (clientX, clientY) {
	        if (!this._dragImage) {
	            return;
	        }
	        var style = this._dragImage.style;
	        style.top = clientY + "px";
	        style.left = clientX + "px";
	    };
	    /**
	     * Detach the drag image element from the DOM.
	     *
	     * This is a no-op if there is no drag image element.
	     */
	    Drag.prototype._detachDragImage = function () {
	        if (!this._dragImage) {
	            return;
	        }
	        var parent = this._dragImage.parentNode;
	        if (!parent) {
	            return;
	        }
	        parent.removeChild(this._dragImage);
	    };
	    /**
	     * Set the internal drop action state and update the drag cursor.
	     */
	    Drag.prototype._setDropAction = function (action) {
	        action = Private.validateAction(action, this._supportedActions);
	        if (this._override && this._dropAction === action) {
	            return;
	        }
	        switch (action) {
	            case 'none':
	                this._dropAction = action;
	                this._override = cursor_1.overrideCursor('no-drop');
	                break;
	            case 'copy':
	                this._dropAction = action;
	                this._override = cursor_1.overrideCursor('copy');
	                break;
	            case 'link':
	                this._dropAction = action;
	                this._override = cursor_1.overrideCursor('alias');
	                break;
	            case 'move':
	                this._dropAction = action;
	                this._override = cursor_1.overrideCursor('move');
	                break;
	        }
	    };
	    /**
	     * Finalize the drag operation and resolve the drag promise.
	     */
	    Drag.prototype._finalize = function (action) {
	        // Store the resolve function as a temp variable.
	        var resolve = this._resolve;
	        // Remove the document event listeners.
	        this._removeListeners();
	        // Detach the drag image.
	        this._detachDragImage();
	        // Dispose of the cursor override.
	        if (this._override)
	            this._override.dispose();
	        // Clear the mime data.
	        if (this._mimeData)
	            this._mimeData.clear();
	        // Clear the internal drag state.
	        this._disposed = true;
	        this._source = null;
	        this._mimeData = null;
	        this._dragImage = null;
	        this._dropAction = 'none';
	        this._proposedAction = 'none';
	        this._supportedActions = 'none';
	        this._override = null;
	        this._currentTarget = null;
	        this._currentElement = null;
	        this._promise = null;
	        this._resolve = null;
	        // Resolve the promise to the given drop action, if possible.
	        if (resolve)
	            resolve(action);
	    };
	    return Drag;
	}());
	exports.Drag = Drag;
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Validate the given action is one of the supported actions.
	     *
	     * Returns the given action or `'none'` if the action is unsupported.
	     */
	    function validateAction(action, supported) {
	        var a = actionTable[action];
	        var b = supportedTable[supported];
	        return (a & b) ? action : 'none';
	    }
	    Private.validateAction = validateAction;
	    /**
	     * Create a left mouse event at the given position.
	     *
	     * @param type - The event type for the mouse event.
	     *
	     * @param clientX - The client X position.
	     *
	     * @param clientY - The client Y position.
	     *
	     * @returns A newly created and initialized mouse event.
	     */
	    function createMouseEvent(type, clientX, clientY) {
	        var event = document.createEvent('MouseEvent');
	        event.initMouseEvent(type, true, true, window, 0, 0, 0, clientX, clientY, false, false, false, false, 0, null);
	        return event;
	    }
	    Private.createMouseEvent = createMouseEvent;
	    /**
	     * Dispatch a drag enter event to the indicated element.
	     *
	     * @param drag - The drag object associated with the action.
	     *
	     * @param currElem - The currently indicated element, or `null`. This
	     *   is the "immediate user selection" from the whatwg spec.
	     *
	     * @param currTarget - The current drag target element, or `null`. This
	     *   is the "current target element" from the whatwg spec.
	     *
	     * @param event - The mouse event related to the action.
	     *
	     * @returns The element to use as the current drag target. This is the
	     *   "current target element" from the whatwg spec, and may be `null`.
	     *
	     * #### Notes
	     * This largely implements the drag enter portion of the whatwg spec:
	     * https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model
	     */
	    function dispatchDragEnter(drag, currElem, currTarget, event) {
	        // If the current element is null, return null as the new target.
	        if (!currElem) {
	            return null;
	        }
	        // Dispatch a drag enter event to the current element.
	        var dragEvent = createDragEvent('p-dragenter', drag, event, currTarget);
	        var canceled = !currElem.dispatchEvent(dragEvent);
	        // If the event was canceled, use the current element as the new target.
	        if (canceled) {
	            return currElem;
	        }
	        // If the current element is the document body, keep the original target.
	        if (currElem === document.body) {
	            return currTarget;
	        }
	        // Dispatch a drag enter event on the document body.
	        dragEvent = createDragEvent('p-dragenter', drag, event, currTarget);
	        document.body.dispatchEvent(dragEvent);
	        // Ignore the event cancellation, and use the body as the new target.
	        return document.body;
	    }
	    Private.dispatchDragEnter = dispatchDragEnter;
	    /**
	     * Dispatch a drag leave event to the indicated element.
	     *
	     * @param drag - The drag object associated with the action.
	     *
	     * @param prevTarget - The previous target element, or `null`. This
	     *   is the previous "current target element" from the whatwg spec.
	     *
	     * @param currTarget - The current drag target element, or `null`. This
	     *   is the "current target element" from the whatwg spec.
	     *
	     * @param event - The mouse event related to the action.
	     *
	     * #### Notes
	     * This largely implements the drag leave portion of the whatwg spec:
	     * https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model
	     */
	    function dispatchDragLeave(drag, prevTarget, currTarget, event) {
	        // If the previous target is null, do nothing.
	        if (!prevTarget) {
	            return;
	        }
	        // Dispatch the drag leave event to the previous target.
	        var dragEvent = createDragEvent('p-dragleave', drag, event, currTarget);
	        prevTarget.dispatchEvent(dragEvent);
	    }
	    Private.dispatchDragLeave = dispatchDragLeave;
	    /**
	     * Dispatch a drag over event to the indicated element.
	     *
	     * @param drag - The drag object associated with the action.
	     *
	     * @param currTarget - The current drag target element, or `null`. This
	     *   is the "current target element" from the whatwg spec.
	     *
	     * @param event - The mouse event related to the action.
	     *
	     * @returns The `DropAction` result of the drag over event.
	     *
	     * #### Notes
	     * This largely implements the drag over portion of the whatwg spec:
	     * https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model
	     */
	    function dispatchDragOver(drag, currTarget, event) {
	        // If there is no current target, the drop action is none.
	        if (!currTarget) {
	            return 'none';
	        }
	        // Dispatch the drag over event to the current target.
	        var dragEvent = createDragEvent('p-dragover', drag, event, null);
	        var canceled = !currTarget.dispatchEvent(dragEvent);
	        // If the event was canceled, return the drop action result.
	        if (canceled) {
	            return dragEvent.dropAction;
	        }
	        // Otherwise, the effective drop action is none.
	        return 'none';
	    }
	    Private.dispatchDragOver = dispatchDragOver;
	    /**
	     * Dispatch a drop event to the indicated element.
	     *
	     * @param drag - The drag object associated with the action.
	     *
	     * @param currTarget - The current drag target element, or `null`. This
	     *   is the "current target element" from the whatwg spec.
	     *
	     * @param event - The mouse event related to the action.
	     *
	     * @returns The `DropAction` result of the drop event.
	     *
	     * #### Notes
	     * This largely implements the drag over portion of the whatwg spec:
	     * https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model
	     */
	    function dispatchDrop(drag, currTarget, event) {
	        // If there is no current target, the drop action is none.
	        if (!currTarget) {
	            return 'none';
	        }
	        // Dispatch the drop event to the current target.
	        var dragEvent = createDragEvent('p-drop', drag, event, null);
	        var canceled = !currTarget.dispatchEvent(dragEvent);
	        // If the event was canceled, return the drop action result.
	        if (canceled) {
	            return dragEvent.dropAction;
	        }
	        // Otherwise, the effective drop action is none.
	        return 'none';
	    }
	    Private.dispatchDrop = dispatchDrop;
	    /**
	     * A lookup table from drop action to bit value.
	     */
	    var actionTable = {
	        'none': 0x0,
	        'copy': 0x1,
	        'link': 0x2,
	        'move': 0x4
	    };
	    /**
	     * A lookup table from supported action to drop action bit mask.
	     */
	    var supportedTable = {
	        'none': actionTable['none'],
	        'copy': actionTable['copy'],
	        'link': actionTable['link'],
	        'move': actionTable['move'],
	        'copy-link': actionTable['copy'] | actionTable['link'],
	        'copy-move': actionTable['copy'] | actionTable['move'],
	        'link-move': actionTable['link'] | actionTable['move'],
	        'all': actionTable['copy'] | actionTable['link'] | actionTable['move']
	    };
	    /**
	     * Create a new initialized `IDragEvent` from the given data.
	     *
	     * @param type - The event type for the drag event.
	     *
	     * @param drag - The drag object to use for seeding the drag data.
	     *
	     * @param event - The mouse event to use for seeding the mouse data.
	     *
	     * @param related - The related target for the event, or `null`.
	     *
	     * @returns A new object which implements `IDragEvent`.
	     */
	    function createDragEvent(type, drag, event, related) {
	        // Create a new mouse event and cast to a custom drag event.
	        var dragEvent = document.createEvent('MouseEvent');
	        // Initialize the mouse event data.
	        dragEvent.initMouseEvent(type, true, true, window, 0, event.screenX, event.screenY, event.clientX, event.clientY, event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, event.button, related);
	        // Add the custom drag event data.
	        dragEvent.dropAction = 'none';
	        dragEvent.mimeData = drag.mimeData;
	        dragEvent.proposedAction = drag.proposedAction;
	        dragEvent.supportedActions = drag.supportedActions;
	        dragEvent.source = drag.source;
	        // Return the fully initialized drag event.
	        return dragEvent;
	    }
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/dom/dragdrop.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/dom/query.js **/
jupyter.define('phosphor@0.7.0/lib/dom/query.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * Test whether a client position lies within a node.
	 *
	 * @param node - The DOM node of interest.
	 *
	 * @param clientX - The client X coordinate of interest.
	 *
	 * @param clientY - The client Y coordinate of interest.
	 *
	 * @returns `true` if the node covers the position, `false` otherwise.
	 *
	 * #### Example
	 * ```typescript
	 * import { hitTest } from 'phosphor/lib/dom/query';
	 *
	 * let div = document.createElement('div');
	 * div.style.position = 'absolute';
	 * div.style.left = '0px';
	 * div.style.top = '0px';
	 * div.style.width = '100px';
	 * div.style.height = '100px';
	 * document.body.appendChild(div);
	 *
	 * hitTest(div, 50, 50);   // true
	 * hitTest(div, 150, 150); // false
	 * ```
	 */
	function hitTest(node, clientX, clientY) {
	    var rect = node.getBoundingClientRect();
	    return (clientX >= rect.left &&
	        clientX < rect.right &&
	        clientY >= rect.top &&
	        clientY < rect.bottom);
	}
	exports.hitTest = hitTest;
	/**
	 * Vertically scroll an element into view if needed.
	 *
	 * @param area - The scroll area element.
	 *
	 * @param elem - The element of interest.
	 *
	 * #### Notes
	 * This follows the "nearest" behavior of the native `scrollIntoView`
	 * method, which is not supported by all browsers.
	 * https://drafts.csswg.org/cssom-view/#element-scrolling-members
	 *
	 * If the element fully covers the visible area or is fully contained
	 * within the visible area, no scrolling will take place. Otherwise,
	 * the nearest edges of the area and element are aligned.
	 *
	 * #### Example
	 * ```typescript
	 * import { scrollIntoViewIfNeeded } from 'phosphor/lib/dom/query';
	 *
	 * let area = document.createElement('div');
	 * let elem = document.createElement('div');
	 *
	 * // Style the scrollable area with a small height and a black border.
	 * area.style.height = '100px';
	 * area.style.overflow = 'auto';
	 * area.style.border = '1px solid black';
	 *
	 * // Style the element of interest with a red border and some content.
	 * elem.style.border = '1px solid red';
	 * elem.textContent = 'visible content';
	 *
	 * // Add enough whitespace to to guarantee scrolling.
	 * for (let i = 0; i < 50; i++) {
	 *   area.appendChild(document.createElement('br'));
	 * }
	 *
	 * // Attach the nodes to the DOM.
	 * area.appendChild(elem);
	 * document.body.appendChild(area);
	 *
	 * // Scroll to the element of interest.
	 * scrollIntoViewIfNeeded(area, elem);
	 * ```
	 */
	function scrollIntoViewIfNeeded(area, elem) {
	    var ar = area.getBoundingClientRect();
	    var er = elem.getBoundingClientRect();
	    if (er.top <= ar.top && er.bottom >= ar.bottom) {
	        return;
	    }
	    if (er.top < ar.top && er.height <= ar.height) {
	        area.scrollTop -= ar.top - er.top;
	        return;
	    }
	    if (er.bottom > ar.bottom && er.height >= ar.height) {
	        area.scrollTop -= ar.top - er.top;
	        return;
	    }
	    if (er.top < ar.top && er.height > ar.height) {
	        area.scrollTop -= ar.bottom - er.bottom;
	        return;
	    }
	    if (er.bottom > ar.bottom && er.height < ar.height) {
	        area.scrollTop -= ar.bottom - er.bottom;
	        return;
	    }
	}
	exports.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded;
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/dom/query.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/focustracker.js **/
jupyter.define('phosphor@0.7.0/lib/ui/focustracker.js', function (module, exports, __jupyter_require__) {
	"use strict";
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	/**
	 * A class which tracks focus among a set of widgets.
	 *
	 * This class is useful when code needs to keep track of the most
	 * recently focused widget(s) among a set of related widgets.
	 */
	var FocusTracker = (function () {
	    /**
	     * Construct a new focus tracker.
	     */
	    function FocusTracker() {
	        this._counter = 0;
	        this._currentWidget = null;
	        this._widgets = new vector_1.Vector();
	        this._numbers = new Map();
	        this._nodes = new Map();
	    }
	    /**
	     * Dispose of the resources held by the tracker.
	     */
	    FocusTracker.prototype.dispose = function () {
	        var _this = this;
	        // Do nothing if the tracker is already disposed.
	        if (this._counter < 0) {
	            return;
	        }
	        // Mark the tracker as disposed.
	        this._counter = -1;
	        // Clear the connections for the tracker.
	        signaling_1.clearSignalData(this);
	        // Remove all event listeners.
	        iteration_1.each(this._widgets, function (widget) {
	            widget.node.removeEventListener('focus', _this, true);
	        });
	        // Clear the internal data structures.
	        this._currentWidget = null;
	        this._nodes.clear();
	        this._numbers.clear();
	        this._widgets.clear();
	    };
	    Object.defineProperty(FocusTracker.prototype, "isDisposed", {
	        /**
	         * A flag indicated whether the tracker is disposed.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._counter < 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FocusTracker.prototype, "currentWidget", {
	        /**
	         * The current widget in the tracker.
	         *
	         * #### Notes
	         * The current widget is the widget among the tracked widgets which
	         * has the *descendant node* which has most recently been focused.
	         *
	         * The current widget will not be updated if the node loses focus. It
	         * will only be updated when a different tracked widget gains focus.
	         *
	         * If the current widget is removed from the tracker, the previous
	         * current widget will be restored.
	         *
	         * This behavior is intended to follow a user's conceptual model of
	         * a semantically "active" widget, where the "last thing of type X"
	         * to be interacted with is the "active instance of X", regardless
	         * of whether that instance still has focus.
	         *
	         * This will be `null` if there is no current widget.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._currentWidget;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FocusTracker.prototype, "widgets", {
	        /**
	         * A read only sequence of the widgets being tracked.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._widgets;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Get the focus number for a particular widget in the tracker.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The focus number for the given widget, or `-1` if the
	     *   widget has not had focus since being added to the tracker.
	     *
	     * #### Notes
	     * The focus number indicates the relative order in which the widgets
	     * have gained focus. A widget with a larger number has gained focus
	     * more recently than a widget with a smaller number.
	     *
	     * The `currentWidget` will always have the largest focus number.
	     *
	     * All widgets start with a focus number of `-1`, which indicates that
	     * the widget has not been focused since being added to the tracker.
	     *
	     * #### Undefined Behavior
	     * A `widget` which is not contained in the tracker.
	     */
	    FocusTracker.prototype.focusNumber = function (widget) {
	        return this._numbers.get(widget);
	    };
	    /**
	     * Test whether the focus tracker contains a given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns `true` if the widget is tracked, `false` otherwise.
	     */
	    FocusTracker.prototype.has = function (widget) {
	        return this._numbers.has(widget);
	    };
	    /**
	     * Add a widget to the focus tracker.
	     *
	     * @param widget - The widget of interest.
	     *
	     * #### Notes
	     * If the widget is currently focused, it will automatically become
	     * the new `currentWidget`.
	     *
	     * A widget will be automatically removed from the tracker if it
	     * is disposed after being added.
	     *
	     * If the widget is already tracked, this is a no-op.
	     */
	    FocusTracker.prototype.add = function (widget) {
	        // Do nothing if the widget is already tracked.
	        if (this._numbers.has(widget)) {
	            return;
	        }
	        // Test whether this widget has focus.
	        var focused = widget.node.contains(document.activeElement);
	        // Setup the initial focus number.
	        var n = focused ? this._counter++ : -1;
	        // Add the widget to the internal data structures.
	        this._numbers.set(widget, n);
	        this._widgets.pushBack(widget);
	        this._nodes.set(widget.node, widget);
	        // Setup the focus event listener. The capturing phase must
	        // be used since the 'focus' event doesn't bubble and since
	        // firefox doesn't support the 'focusin' event.
	        widget.node.addEventListener('focus', this, true);
	        // Connect the disposed signal handler.
	        widget.disposed.connect(this._onWidgetDisposed, this);
	        // Update the current widget if the new widget has focus.
	        if (focused)
	            this._setCurrentWidget(widget);
	    };
	    /**
	     * Remove a widget from the focus tracker.
	     *
	     * #### Notes
	     * If the widget is the `currentWidget`, the previous current widget
	     * will become the new `currentWidget`.
	     *
	     * A widget will be automatically removed from the tracker if it
	     * is disposed after being added.
	     *
	     * If the widget is not tracked, this is a no-op.
	     */
	    FocusTracker.prototype.remove = function (widget) {
	        var _this = this;
	        // Do nothing if the widget is not tracked.
	        if (!this._numbers.has(widget)) {
	            return;
	        }
	        // Disconnect the disposed signal handler.
	        widget.disposed.disconnect(this._onWidgetDisposed, this);
	        // Remove the focus event listener.
	        widget.node.removeEventListener('focus', this, true);
	        // Remove the widget from the internal data structures.
	        this._widgets.remove(widget);
	        this._nodes.delete(widget.node);
	        this._numbers.delete(widget);
	        // If the widget is not the current widget, we're done.
	        if (this._currentWidget !== widget) {
	            return;
	        }
	        // Otherwise, filter the widgets for those which have had focus.
	        var valid = iteration_1.filter(this._widgets, function (w) { return _this._numbers.get(w) !== -1; });
	        // Get the valid widget with the max focus number.
	        var previous = searching_1.max(valid, function (first, second) {
	            var a = _this._numbers.get(first);
	            var b = _this._numbers.get(second);
	            return a - b;
	        }) || null;
	        // Finally, update the current widget.
	        this._setCurrentWidget(previous);
	    };
	    /**
	     * Handle the DOM events for the focus tracker.
	     *
	     * @param event - The DOM event sent to the panel.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the tracked nodes. It should
	     * not be called directly by user code.
	     */
	    FocusTracker.prototype.handleEvent = function (event) {
	        if (event.type === 'focus') {
	            this._evtFocus(event);
	        }
	    };
	    /**
	     * Set the current widget for the tracker.
	     */
	    FocusTracker.prototype._setCurrentWidget = function (widget) {
	        // Do nothing if there is no change.
	        if (this._currentWidget === widget) {
	            return;
	        }
	        // Swap the current widget.
	        var old = this._currentWidget;
	        this._currentWidget = widget;
	        // Emit the changed signal.
	        this.currentChanged.emit({ oldValue: old, newValue: widget });
	    };
	    /**
	     * Handle the `'focus'` event for a tracked widget.
	     */
	    FocusTracker.prototype._evtFocus = function (event) {
	        // Find the widget which gained focus.
	        var widget = this._nodes.get(event.currentTarget);
	        // Update the focus number for the widget.
	        this._numbers.set(widget, this._counter++);
	        // Update the current widget.
	        this._setCurrentWidget(widget);
	    };
	    /**
	     * Handle the `disposed` signal for a tracked widget.
	     */
	    FocusTracker.prototype._onWidgetDisposed = function (sender) {
	        this.remove(sender);
	    };
	    return FocusTracker;
	}());
	exports.FocusTracker = FocusTracker;
	// Define the signals for the `FocusTracker` class.
	signaling_1.defineSignal(FocusTracker.prototype, 'currentChanged');
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/focustracker.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/tabbar.js **/
jupyter.define('phosphor@0.7.0/lib/ui/tabbar.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	var mutation_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/mutation.js');
	var searching_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var messaging_1 = __jupyter_require__('phosphor@0.7.0/lib/core/messaging.js');
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	var cursor_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/cursor.js');
	var query_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/query.js');
	var title_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/title.js');
	var vdom_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/vdom.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to TabBar instances.
	 */
	var TAB_BAR_CLASS = 'p-TabBar';
	/**
	 * The class name added to a tab bar content node.
	 */
	var CONTENT_CLASS = 'p-TabBar-content';
	/**
	 * The class name added to a tab bar tab.
	 */
	var TAB_CLASS = 'p-TabBar-tab';
	/**
	 * The class name added to a tab label node.
	 */
	var LABEL_CLASS = 'p-TabBar-tabLabel';
	/**
	 * The class name added to a tab icon node.
	 */
	var ICON_CLASS = 'p-TabBar-tabIcon';
	/**
	 * The class name added to a tab close icon node.
	 */
	var CLOSE_ICON_CLASS = 'p-TabBar-tabCloseIcon';
	/**
	 * The class name added to a tab bar and tab when dragging.
	 */
	var DRAGGING_CLASS = 'p-mod-dragging';
	/**
	 * The class name added to the current tab.
	 */
	var CURRENT_CLASS = 'p-mod-current';
	/**
	 * The class name added to a closable tab.
	 */
	var CLOSABLE_CLASS = 'p-mod-closable';
	/**
	 * The start drag distance threshold.
	 */
	var DRAG_THRESHOLD = 5;
	/**
	 * The detach distance threshold.
	 */
	var DETACH_THRESHOLD = 20;
	/**
	 * The DOM structure for a TabBar.
	 */
	var TAB_BAR_NODE = (vdom_1.h.div(vdom_1.h.ul({ className: CONTENT_CLASS })));
	/**
	 * A widget which displays titles as a single row or column of tabs.
	 *
	 * #### Notes
	 * If CSS transforms are used to rotate nodes for vertically oriented
	 * text, then tab dragging will not work correctly. The `tabsMovable`
	 * property should be set to `false` when rotating nodes from CSS.
	 */
	var TabBar = (function (_super) {
	    __extends(TabBar, _super);
	    /**
	     * Construct a new tab bar.
	     *
	     * @param options - The options for initializing the tab bar.
	     */
	    function TabBar(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this, { node: vdom_1.realize(TAB_BAR_NODE) });
	        this._currentIndex = -1;
	        this._previousTitle = null;
	        this._titles = new vector_1.Vector();
	        this._dragData = null;
	        this.addClass(TAB_BAR_CLASS);
	        this.setFlag(widget_1.WidgetFlag.DisallowLayout);
	        this._tabsMovable = options.tabsMovable || false;
	        this._allowDeselect = options.allowDeselect || false;
	        this._orientation = options.orientation || 'horizontal';
	        this._renderer = options.renderer || TabBar.defaultRenderer;
	        this._insertBehavior = options.insertBehavior || 'select-tab-if-needed';
	        this._removeBehavior = options.removeBehavior || 'select-tab-after';
	        this.addClass("p-mod-" + this._orientation);
	    }
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    TabBar.prototype.dispose = function () {
	        this._releaseMouse();
	        this._titles.clear();
	        this._renderer = null;
	        this._previousTitle = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(TabBar.prototype, "contentNode", {
	        /**
	         * Get the tab bar content node.
	         *
	         * #### Notes
	         * This is the node which holds the tab nodes.
	         *
	         * Modifying this node directly can lead to undefined behavior.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.node.getElementsByClassName(CONTENT_CLASS)[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabBar.prototype, "titles", {
	        /**
	         * A read-only sequence of the titles in the tab bar.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._titles;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabBar.prototype, "currentTitle", {
	        /**
	         * Get the currently selected title.
	         *
	         * #### Notes
	         * This will be `null` if no tab is selected.
	         */
	        get: function () {
	            var i = this._currentIndex;
	            return i !== -1 ? this._titles.at(i) : null;
	        },
	        /**
	         * Set the currently selected title.
	         *
	         * #### Notes
	         * If the title does not exist, the title will be set to `null`.
	         */
	        set: function (value) {
	            this.currentIndex = searching_1.indexOf(this._titles, value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabBar.prototype, "currentIndex", {
	        /**
	         * Get the index of the currently selected tab.
	         *
	         * #### Notes
	         * This will be `-1` if no tab is selected.
	         */
	        get: function () {
	            return this._currentIndex;
	        },
	        /**
	         * Set the index of the currently selected tab.
	         *
	         * #### Notes
	         * If the value is out of range, the index will be set to `-1`.
	         */
	        set: function (value) {
	            // Coerce the value to an index.
	            var i = Math.floor(value);
	            if (i < 0 || i >= this._titles.length) {
	                i = -1;
	            }
	            // Bail early if the index will not change.
	            if (this._currentIndex === i) {
	                return;
	            }
	            // Look up the previous index and title.
	            var pi = this._currentIndex;
	            var pt = pi === -1 ? null : this._titles.at(pi);
	            // Look up the current index and title.
	            var ci = i;
	            var ct = ci === -1 ? null : this._titles.at(ci);
	            // Update the current index and previous title.
	            this._currentIndex = ci;
	            this._previousTitle = pt;
	            // Emit the current changed signal.
	            this.currentChanged.emit({
	                previousIndex: pi, previousTitle: pt,
	                currentIndex: ci, currentTitle: ct
	            });
	            // Schedule an update of the tabs.
	            this.update();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabBar.prototype, "orientation", {
	        /**
	         * Get the orientation of the tab bar.
	         *
	         * #### Notes
	         * This controls whether the tabs are arranged in a row or column.
	         */
	        get: function () {
	            return this._orientation;
	        },
	        /**
	         * Set the orientation of the tab bar.
	         *
	         * #### Notes
	         * This controls whether the tabs are arranged in a row or column.
	         */
	        set: function (value) {
	            // Do nothing if the orientation does not change.
	            if (this._orientation === value) {
	                return;
	            }
	            // Release the mouse before making any changes.
	            this._releaseMouse();
	            // Swap the orientation values.
	            var old = this._orientation;
	            this._orientation = value;
	            // Toggle the orientation classes.
	            this.removeClass("p-mod-" + old);
	            this.addClass("p-mod-" + value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabBar.prototype, "tabsMovable", {
	        /**
	         * Get whether the tabs are movable by the user.
	         *
	         * #### Notes
	         * Tabs can always be moved programmatically.
	         */
	        get: function () {
	            return this._tabsMovable;
	        },
	        /**
	         * Set whether the tabs are movable by the user.
	         *
	         * #### Notes
	         * Tabs can always be moved programmatically.
	         */
	        set: function (value) {
	            this._tabsMovable = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabBar.prototype, "allowDeselect", {
	        /**
	         * Get whether a tab can be deselected by the user.
	         *
	         * #### Notes
	         * Tabs can be always be deselected programmatically.
	         */
	        get: function () {
	            return this._allowDeselect;
	        },
	        /**
	         * Set whether a tab can be deselected by the user.
	         *
	         * #### Notes
	         * Tabs can be always be deselected programmatically.
	         */
	        set: function (value) {
	            this._allowDeselect = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabBar.prototype, "insertBehavior", {
	        /**
	         * Get the selection behavior when inserting a tab.
	         */
	        get: function () {
	            return this._insertBehavior;
	        },
	        /**
	         * Set the selection behavior when inserting a tab.
	         */
	        set: function (value) {
	            this._insertBehavior = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabBar.prototype, "removeBehavior", {
	        /**
	         * Get the selection behavior when removing a tab.
	         */
	        get: function () {
	            return this._removeBehavior;
	        },
	        /**
	         * Set the selection behavior when removing a tab.
	         */
	        set: function (value) {
	            this._removeBehavior = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabBar.prototype, "renderer", {
	        /**
	         * The renderer used by the tab bar.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a tab to the end of the tab bar.
	     *
	     * @param value - The title which holds the data for the tab,
	     *   or an options object to convert to a title.
	     *
	     * @returns The title object added to the tab bar.
	     *
	     * #### Notes
	     * If the title is already added to the tab bar, it will be moved.
	     */
	    TabBar.prototype.addTab = function (value) {
	        return this.insertTab(this._titles.length, value);
	    };
	    /**
	     * Insert a tab into the tab bar at the specified index.
	     *
	     * @param index - The index at which to insert the tab.
	     *
	     * @param value - The title which holds the data for the tab,
	     *   or an options object to convert to a title.
	     *
	     * @returns The title object added to the tab bar.
	     *
	     * #### Notes
	     * The index will be clamped to the bounds of the tabs.
	     *
	     * If the title is already added to the tab bar, it will be moved.
	     */
	    TabBar.prototype.insertTab = function (index, value) {
	        // Release the mouse before making any changes.
	        this._releaseMouse();
	        // Coerce the value to a title.
	        var title = Private.asTitle(value);
	        // Look up the index of the title.
	        var i = searching_1.indexOf(this._titles, title);
	        // Clamp the insert index to the vector bounds.
	        var j = Math.max(0, Math.min(Math.floor(index), this._titles.length));
	        // If the title is not in the vector, insert it.
	        if (i === -1) {
	            // Insert the title into the vector.
	            this._titles.insert(j, title);
	            // Connect to the title changed signal.
	            title.changed.connect(this._onTitleChanged, this);
	            // Adjust the current index for the insert.
	            this._adjustCurrentForInsert(j, title);
	            // Schedule an update of the tabs.
	            this.update();
	            // Return the title added to the tab bar.
	            return title;
	        }
	        // Otherwise, the title exists in the vector and should be moved.
	        // Adjust the index if the location is at the end of the vector.
	        if (j === this._titles.length)
	            j--;
	        // Bail if there is no effective move.
	        if (i === j)
	            return title;
	        // Move the title to the new location.
	        mutation_1.move(this._titles, i, j);
	        // Adjust the current index for the move.
	        this._adjustCurrentForMove(i, j);
	        // Schedule an update of the tabs.
	        this.update();
	        // Return the title added to the tab bar.
	        return title;
	    };
	    /**
	     * Remove a tab from the tab bar.
	     *
	     * @param title - The title for the tab to remove.
	     *
	     * @returns The index occupied by the tab, or `-1` if the tab
	     *   was not contained in the tab bar.
	     */
	    TabBar.prototype.removeTab = function (title) {
	        var index = searching_1.indexOf(this._titles, title);
	        if (index !== -1)
	            this.removeTabAt(index);
	        return index;
	    };
	    /**
	     * Remove the tab at a given index from the tab bar.
	     *
	     * @param index - The index of the tab to remove.
	     *
	     * @returns The title occupying the index, or `null` if the index
	     *   is out of range.
	     */
	    TabBar.prototype.removeTabAt = function (index) {
	        // Bail if the index is out of range.
	        var i = Math.floor(index);
	        if (i < 0 || i >= this._titles.length) {
	            return null;
	        }
	        // Release the mouse before making any changes.
	        this._releaseMouse();
	        // Remove the title from the vector.
	        var title = this._titles.removeAt(i);
	        // Disconnect from the title changed signal.
	        title.changed.disconnect(this._onTitleChanged, this);
	        // Clear the previous title if it's being removed.
	        if (title === this._previousTitle) {
	            this._previousTitle = null;
	        }
	        // Adjust the current index for the remove.
	        this._adjustCurrentForRemove(i, title);
	        // Schedule an update of the tabs.
	        this.update();
	        // Return the removed title.
	        return title;
	    };
	    /**
	     * Remove all tabs from the tab bar.
	     */
	    TabBar.prototype.clearTabs = function () {
	        var _this = this;
	        // Bail if there is nothing to remove.
	        if (this._titles.length === 0) {
	            return;
	        }
	        // Release the mouse before making any changes.
	        this._releaseMouse();
	        // Disconnect from the title changed signals.
	        iteration_1.each(this._titles, function (title) {
	            title.changed.disconnect(_this._onTitleChanged, _this);
	        });
	        // Get the current index and title.
	        var pi = this.currentIndex;
	        var pt = this.currentTitle;
	        // Reset the current index and previous title.
	        this._currentIndex = -1;
	        this._previousTitle = null;
	        // Clear the title vector.
	        this._titles.clear();
	        // Schedule an update of the tabs.
	        this.update();
	        // If no tab was selected, there's nothing else to do.
	        if (pi === -1) {
	            return;
	        }
	        // Emit the current changed signal.
	        this.currentChanged.emit({
	            previousIndex: pi, previousTitle: pt,
	            currentIndex: -1, currentTitle: null
	        });
	    };
	    /**
	     * Release the mouse and restore the non-dragged tab positions.
	     *
	     * #### Notes
	     * This will cause the tab bar to stop handling mouse events and to
	     * restore the tabs to their non-dragged positions.
	     */
	    TabBar.prototype.releaseMouse = function () {
	        this._releaseMouse();
	    };
	    /**
	     * Handle the DOM events for the tab bar.
	     *
	     * @param event - The DOM event sent to the tab bar.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the tab bar's DOM node.
	     *
	     * This should not be called directly by user code.
	     */
	    TabBar.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'click':
	                this._evtClick(event);
	                break;
	            case 'mousedown':
	                this._evtMouseDown(event);
	                break;
	            case 'mousemove':
	                this._evtMouseMove(event);
	                break;
	            case 'mouseup':
	                this._evtMouseUp(event);
	                break;
	            case 'keydown':
	                this._evtKeyDown(event);
	                break;
	            case 'contextmenu':
	                event.preventDefault();
	                event.stopPropagation();
	                break;
	        }
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    TabBar.prototype.onAfterAttach = function (msg) {
	        this.node.addEventListener('click', this);
	        this.node.addEventListener('mousedown', this);
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    TabBar.prototype.onBeforeDetach = function (msg) {
	        this.node.removeEventListener('click', this);
	        this.node.removeEventListener('mousedown', this);
	        this._releaseMouse();
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    TabBar.prototype.onUpdateRequest = function (msg) {
	        var content = [];
	        var titles = this._titles;
	        var renderer = this._renderer;
	        var currentTitle = this.currentTitle;
	        for (var i = 0, n = titles.length; i < n; ++i) {
	            var title = titles.at(i);
	            var current = title === currentTitle;
	            var zIndex = current ? n : n - i - 1;
	            content.push(renderer.renderTab({ title: title, current: current, zIndex: zIndex }));
	        }
	        vdom_1.render(content, this.contentNode);
	    };
	    /**
	     * Handle the `'keydown'` event for the tab bar.
	     */
	    TabBar.prototype._evtKeyDown = function (event) {
	        // Stop all input events during drag.
	        event.preventDefault();
	        event.stopPropagation();
	        // Release the mouse if `Escape` is pressed.
	        if (event.keyCode === 27)
	            this._releaseMouse();
	    };
	    /**
	     * Handle the `'click'` event for the tab bar.
	     */
	    TabBar.prototype._evtClick = function (event) {
	        // Do nothing if it's not a left click.
	        if (event.button !== 0) {
	            return;
	        }
	        // Do nothing if a drag is in progress.
	        if (this._dragData) {
	            return;
	        }
	        // Lookup the tab nodes.
	        var tabs = this.contentNode.children;
	        // Do nothing if the click is not on a tab.
	        var x = event.clientX;
	        var y = event.clientY;
	        var i = searching_1.findIndex(tabs, function (tab) { return query_1.hitTest(tab, x, y); });
	        if (i < 0) {
	            return;
	        }
	        // Clicking on a tab stops the event propagation.
	        event.preventDefault();
	        event.stopPropagation();
	        // Ignore the click if the title is not closable.
	        var title = this._titles.at(i);
	        if (!title.closable) {
	            return;
	        }
	        // Ignore the click if it was not on a close icon.
	        var icon = tabs[i].querySelector(this._renderer.closeIconSelector);
	        if (!icon || !icon.contains(event.target)) {
	            return;
	        }
	        // Emit the tab close requested signal.
	        this.tabCloseRequested.emit({ index: i, title: title });
	    };
	    /**
	     * Handle the `'mousedown'` event for the tab bar.
	     */
	    TabBar.prototype._evtMouseDown = function (event) {
	        // Do nothing if it's not a left mouse press.
	        if (event.button !== 0) {
	            return;
	        }
	        // Do nothing if a drag is in progress.
	        if (this._dragData) {
	            return;
	        }
	        // Lookup the tab nodes.
	        var tabs = this.contentNode.children;
	        // Do nothing if the press is not on a tab.
	        var x = event.clientX;
	        var y = event.clientY;
	        var i = searching_1.findIndex(tabs, function (tab) { return query_1.hitTest(tab, x, y); });
	        if (i < 0) {
	            return;
	        }
	        // Pressing on a tab stops the event propagation.
	        event.preventDefault();
	        event.stopPropagation();
	        // Ignore the press if it was on a close icon.
	        var icon = tabs[i].querySelector(this._renderer.closeIconSelector);
	        if (icon && icon.contains(event.target)) {
	            return;
	        }
	        // Setup the drag data if the tabs are movable.
	        if (this._tabsMovable) {
	            this._dragData = new Private.DragData();
	            this._dragData.index = i;
	            this._dragData.tab = tabs[i];
	            this._dragData.pressX = event.clientX;
	            this._dragData.pressY = event.clientY;
	            document.addEventListener('mousemove', this, true);
	            document.addEventListener('mouseup', this, true);
	            document.addEventListener('keydown', this, true);
	            document.addEventListener('contextmenu', this, true);
	        }
	        // Update the current index as appropriate.
	        if (this._allowDeselect && this._currentIndex === i) {
	            this.currentIndex = -1;
	        }
	        else {
	            this.currentIndex = i;
	        }
	        // Do nothing else if there is no current tab.
	        if (this._currentIndex === -1) {
	            return;
	        }
	        // Emit the tab activate request signal.
	        this.tabActivateRequested.emit({
	            index: this.currentIndex,
	            title: this.currentTitle
	        });
	    };
	    /**
	     * Handle the `'mousemove'` event for the tab bar.
	     */
	    TabBar.prototype._evtMouseMove = function (event) {
	        // Do nothing if no drag is in progress.
	        if (!this._dragData) {
	            return;
	        }
	        // Suppress the event during a drag.
	        event.preventDefault();
	        event.stopPropagation();
	        // Lookup the tab nodes.
	        var tabs = this.contentNode.children;
	        // Check the threshold if the drag is not active.
	        var data = this._dragData;
	        if (!data.dragActive) {
	            // Bail if the drag threshold is not exceeded.
	            var dx = Math.abs(event.clientX - data.pressX);
	            var dy = Math.abs(event.clientY - data.pressY);
	            if (dx < DRAG_THRESHOLD && dy < DRAG_THRESHOLD) {
	                return;
	            }
	            // Fill in the rest of the drag data measurements.
	            var tabRect = data.tab.getBoundingClientRect();
	            if (this._orientation === 'horizontal') {
	                data.tabPos = data.tab.offsetLeft;
	                data.tabSize = tabRect.width;
	                data.tabPressPos = data.pressX - tabRect.left;
	            }
	            else {
	                data.tabPos = data.tab.offsetTop;
	                data.tabSize = tabRect.height;
	                data.tabPressPos = data.pressY - tabRect.top;
	            }
	            data.tabLayout = Private.snapTabLayout(tabs, this._orientation);
	            data.contentRect = this.contentNode.getBoundingClientRect();
	            data.override = cursor_1.overrideCursor('default');
	            // Add the dragging style classes.
	            data.tab.classList.add(DRAGGING_CLASS);
	            this.addClass(DRAGGING_CLASS);
	            // Mark the drag as active.
	            data.dragActive = true;
	        }
	        // Emit the detach requested signal if the threshold is exceeded.
	        if (!data.detachRequested && Private.detachExceeded(data, event)) {
	            // Only emit the signal once per drag cycle.
	            data.detachRequested = true;
	            // Setup the arguments for the signal.
	            var index = data.index;
	            var clientX = event.clientX;
	            var clientY = event.clientY;
	            var tab = tabs[index];
	            var title = this._titles.at(index);
	            // Emit the tab detach requested signal.
	            this.tabDetachRequested.emit({ index: index, title: title, tab: tab, clientX: clientX, clientY: clientY });
	            // Bail if the signal handler aborted the drag.
	            if (data.dragAborted) {
	                return;
	            }
	        }
	        // Update the positions of the tabs.
	        Private.layoutTabs(tabs, data, event, this._orientation);
	    };
	    /**
	     * Handle the `'mouseup'` event for the tab bar.
	     */
	    TabBar.prototype._evtMouseUp = function (event) {
	        var _this = this;
	        // Do nothing if it's not a left mouse release.
	        if (event.button !== 0) {
	            return;
	        }
	        // Do nothing if no drag is in progress.
	        if (!this._dragData) {
	            return;
	        }
	        // Suppress the event during a drag operation.
	        event.preventDefault();
	        event.stopPropagation();
	        // Remove the extra mouse event listeners.
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('mouseup', this, true);
	        document.removeEventListener('keydown', this, true);
	        document.removeEventListener('contextmenu', this, true);
	        // Bail early if the drag is not active.
	        var data = this._dragData;
	        if (!data.dragActive) {
	            this._dragData = null;
	            return;
	        }
	        // Position the tab at its final resting position.
	        Private.finalizeTabPosition(data, this._orientation);
	        // Remove the dragging class from the tab so it can be transitioned.
	        data.tab.classList.remove(DRAGGING_CLASS);
	        // Parse the transition duration for releasing the tab.
	        var duration = Private.parseTransitionDuration(data.tab);
	        // Complete the release on a timer to allow the tab to transition.
	        setTimeout(function () {
	            // Do nothing if the drag has been aborted.
	            if (data.dragAborted) {
	                return;
	            }
	            // Clear the drag data reference.
	            _this._dragData = null;
	            // Reset the positions of the tabs.
	            Private.resetTabPositions(_this.contentNode.children, _this._orientation);
	            // Clear the cursor grab.
	            data.override.dispose();
	            // Remove the remaining dragging style.
	            _this.removeClass(DRAGGING_CLASS);
	            // If the tab was not moved, there is nothing else to do.
	            var i = data.index;
	            var j = data.targetIndex;
	            if (j === -1 || i === j) {
	                return;
	            }
	            // Move the title to the new locations.
	            mutation_1.move(_this._titles, i, j);
	            // Adjust the current index for the move.
	            _this._adjustCurrentForMove(i, j);
	            // Emit the tab moved signal.
	            _this.tabMoved.emit({
	                fromIndex: i, toIndex: j, title: _this._titles.at(j)
	            });
	            // Update the tabs immediately to prevent flicker.
	            messaging_1.sendMessage(_this, widget_1.WidgetMessage.UpdateRequest);
	        }, duration);
	    };
	    /**
	     * Release the mouse and restore the non-dragged tab positions.
	     */
	    TabBar.prototype._releaseMouse = function () {
	        // Do nothing if no drag is in progress.
	        if (!this._dragData) {
	            return;
	        }
	        // Remove the extra mouse listeners.
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('mouseup', this, true);
	        document.removeEventListener('keydown', this, true);
	        document.removeEventListener('contextmenu', this, true);
	        // Clear the drag data reference.
	        var data = this._dragData;
	        this._dragData = null;
	        // Indicate the drag has been aborted. This allows the mouse
	        // event handlers to return early when the drag is canceled.
	        data.dragAborted = true;
	        // If the drag is not active, there's nothing more to do.
	        if (!data.dragActive) {
	            return;
	        }
	        // Reset the tabs to their non-dragged positions.
	        Private.resetTabPositions(this.contentNode.children, this._orientation);
	        // Clear the cursor override.
	        data.override.dispose();
	        // Clear the dragging style classes.
	        data.tab.classList.remove(DRAGGING_CLASS);
	        this.removeClass(DRAGGING_CLASS);
	    };
	    /**
	     * Adjust the current index for a tab insert operation.
	     *
	     * This method accounts for the tab bar's insertion behavior when
	     * adjusting the current index and emitting the changed signal.
	     */
	    TabBar.prototype._adjustCurrentForInsert = function (i, title) {
	        // Lookup commonly used variables.
	        var ct = this.currentTitle;
	        var ci = this._currentIndex;
	        var bh = this._insertBehavior;
	        // Handle the behavior where the new tab is always selected,
	        // or the behavior where the new tab is selected if needed.
	        if (bh === 'select-tab' || (bh === 'select-tab-if-needed' && ci === -1)) {
	            this._currentIndex = i;
	            this._previousTitle = ct;
	            this.currentChanged.emit({
	                previousIndex: ci, previousTitle: ct,
	                currentIndex: i, currentTitle: title
	            });
	            return;
	        }
	        // Otherwise, silently adjust the current index if needed.
	        if (ci >= i)
	            this._currentIndex++;
	    };
	    /**
	     * Adjust the current index for a tab move operation.
	     *
	     * This method will not cause the actual current tab to change.
	     * It silently adjusts the index to account for the given move.
	     */
	    TabBar.prototype._adjustCurrentForMove = function (i, j) {
	        if (this._currentIndex === i) {
	            this._currentIndex = j;
	        }
	        else if (this._currentIndex < i && this._currentIndex >= j) {
	            this._currentIndex++;
	        }
	        else if (this._currentIndex > i && this._currentIndex <= j) {
	            this._currentIndex--;
	        }
	    };
	    /**
	     * Adjust the current index for a tab remove operation.
	     *
	     * This method accounts for the tab bar's remove behavior when
	     * adjusting the current index and emitting the changed signal.
	     */
	    TabBar.prototype._adjustCurrentForRemove = function (i, title) {
	        // Lookup commonly used variables.
	        var ci = this._currentIndex;
	        var bh = this._removeBehavior;
	        // Silently adjust the index if the current tab is not removed.
	        if (ci !== i) {
	            if (ci > i)
	                this._currentIndex--;
	            return;
	        }
	        // No tab gets selected if the tab bar is empty.
	        if (this._titles.length === 0) {
	            this._currentIndex = -1;
	            this.currentChanged.emit({
	                previousIndex: i, previousTitle: title,
	                currentIndex: -1, currentTitle: null
	            });
	            return;
	        }
	        // Handle behavior where the next sibling tab is selected.
	        if (bh === 'select-tab-after') {
	            this._currentIndex = Math.min(i, this._titles.length - 1);
	            this.currentChanged.emit({
	                previousIndex: i, previousTitle: title,
	                currentIndex: this._currentIndex, currentTitle: this.currentTitle
	            });
	            return;
	        }
	        // Handle behavior where the previous sibling tab is selected.
	        if (bh === 'select-tab-before') {
	            this._currentIndex = Math.max(0, i - 1);
	            this.currentChanged.emit({
	                previousIndex: i, previousTitle: title,
	                currentIndex: this._currentIndex, currentTitle: this.currentTitle
	            });
	            return;
	        }
	        // Handle behavior where the previous history tab is selected.
	        if (bh === 'select-previous-tab') {
	            if (this._previousTitle) {
	                this._currentIndex = searching_1.indexOf(this._titles, this._previousTitle);
	                this._previousTitle = null;
	            }
	            else {
	                this._currentIndex = Math.min(i, this._titles.length - 1);
	            }
	            this.currentChanged.emit({
	                previousIndex: i, previousTitle: title,
	                currentIndex: this._currentIndex, currentTitle: this.currentTitle
	            });
	            return;
	        }
	        // Otherwise, no tab gets selected.
	        this._currentIndex = -1;
	        this.currentChanged.emit({
	            previousIndex: i, previousTitle: title,
	            currentIndex: -1, currentTitle: null
	        });
	    };
	    /**
	     * Handle the `changed` signal of a title object.
	     */
	    TabBar.prototype._onTitleChanged = function (sender) {
	        this.update();
	    };
	    return TabBar;
	}(widget_1.Widget));
	exports.TabBar = TabBar;
	// Define the signals for the `TabBar` class.
	signaling_1.defineSignal(TabBar.prototype, 'currentChanged');
	signaling_1.defineSignal(TabBar.prototype, 'tabMoved');
	signaling_1.defineSignal(TabBar.prototype, 'tabActivateRequested');
	signaling_1.defineSignal(TabBar.prototype, 'tabCloseRequested');
	signaling_1.defineSignal(TabBar.prototype, 'tabDetachRequested');
	/**
	 * The namespace for the `TabBar` class statics.
	 */
	var TabBar;
	(function (TabBar) {
	    /**
	     * The default implementation of `IRenderer`.
	     */
	    var Renderer = (function () {
	        /**
	         * Construct a new renderer.
	         *
	         * @param options - The options for initializing the renderer.
	         */
	        function Renderer(options) {
	            if (options === void 0) { options = {}; }
	            this._tabID = 0;
	            this._tabKeys = new WeakMap();
	            this._extraTabClass = options.extraTabClass || '';
	        }
	        Object.defineProperty(Renderer.prototype, "closeIconSelector", {
	            /**
	             * A selector which matches the close icon node in a tab.
	             *
	             * #### Notes
	             * This is a read-only property.
	             */
	            get: function () {
	                return "." + CLOSE_ICON_CLASS;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        /**
	         * Render the node for the a tab.
	         *
	         * @param data - The data to use for rendering the tab.
	         *
	         * @returns A virtual DOM node representing the tab.
	         */
	        Renderer.prototype.renderTab = function (data) {
	            var _a = data.title, label = _a.label, caption = _a.caption;
	            var key = this.createTabKey(data);
	            var style = this.createTabStyle(data);
	            var tabClass = this.createTabClass(data);
	            var iconClass = this.createIconClass(data);
	            return (vdom_1.h.li({ key: key, className: tabClass, title: caption, style: style }, vdom_1.h.div({ className: iconClass }), vdom_1.h.div({ className: LABEL_CLASS }, label), vdom_1.h.div({ className: CLOSE_ICON_CLASS })));
	        };
	        /**
	         * Create a unique render key for the tab.
	         *
	         * @param data - The data to use for the tab.
	         *
	         * @returns The unique render key for the tab.
	         *
	         * #### Notes
	         * This method caches the key against the tab title the first time
	         * the key is generated. This enables efficient rendering of moved
	         * tabs and avoids subtle hover style artifacts.
	         */
	        Renderer.prototype.createTabKey = function (data) {
	            var key = this._tabKeys.get(data.title);
	            if (key === void 0) {
	                key = "tab-key-" + this._tabID++;
	                this._tabKeys.set(data.title, key);
	            }
	            return key;
	        };
	        /**
	         * Create the inline style object for a tab.
	         *
	         * @param data - The data to use for the tab.
	         *
	         * @returns The inline style data for the tab.
	         */
	        Renderer.prototype.createTabStyle = function (data) {
	            return { zIndex: "" + data.zIndex };
	        };
	        /**
	         * Create the class name for the tab.
	         *
	         * @param data - The data to use for the tab.
	         *
	         * @returns The full class name for the tab.
	         */
	        Renderer.prototype.createTabClass = function (data) {
	            var title = data.title, current = data.current;
	            var name = TAB_CLASS;
	            if (title.className) {
	                name += " " + title.className;
	            }
	            if (title.closable) {
	                name += " " + CLOSABLE_CLASS;
	            }
	            if (current) {
	                name += " " + CURRENT_CLASS;
	            }
	            if (this._extraTabClass) {
	                name += " " + this._extraTabClass;
	            }
	            return name;
	        };
	        /**
	         * Create the class name for the tab icon.
	         *
	         * @param data - The data to use for the tab.
	         *
	         * @returns The full class name for the tab icon.
	         */
	        Renderer.prototype.createIconClass = function (data) {
	            var title = data.title;
	            var name = ICON_CLASS;
	            if (title.icon) {
	                name += " " + title.icon;
	            }
	            return name;
	        };
	        return Renderer;
	    }());
	    TabBar.Renderer = Renderer;
	    /**
	     * The default `Renderer` instance.
	     */
	    TabBar.defaultRenderer = new Renderer();
	})(TabBar = exports.TabBar || (exports.TabBar = {}));
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * A struct which holds the drag data for a tab bar.
	     */
	    var DragData = (function () {
	        function DragData() {
	            /**
	             * The tab node being dragged.
	             */
	            this.tab = null;
	            /**
	             * The index of the tab being dragged.
	             */
	            this.index = -1;
	            /**
	             * The offset left/top of the tab being dragged.
	             */
	            this.tabPos = -1;
	            /**
	             * The offset width/height of the tab being dragged.
	             */
	            this.tabSize = -1;
	            /**
	             * The original mouse X/Y position in tab coordinates.
	             */
	            this.tabPressPos = -1;
	            /**
	             * The tab target index upon mouse release.
	             */
	            this.targetIndex = -1;
	            /**
	             * The array of tab layout objects snapped at drag start.
	             */
	            this.tabLayout = null;
	            /**
	             * The mouse press client X position.
	             */
	            this.pressX = -1;
	            /**
	             * The mouse press client Y position.
	             */
	            this.pressY = -1;
	            /**
	             * The bounding client rect of the tab bar content node.
	             */
	            this.contentRect = null;
	            /**
	             * The disposable to clean up the cursor override.
	             */
	            this.override = null;
	            /**
	             * Whether the drag is currently active.
	             */
	            this.dragActive = false;
	            /**
	             * Whether the drag has been aborted.
	             */
	            this.dragAborted = false;
	            /**
	             * Whether a detach request as been made.
	             */
	            this.detachRequested = false;
	        }
	        return DragData;
	    }());
	    Private.DragData = DragData;
	    /**
	     * Coerce a title or options into a real title.
	     */
	    function asTitle(value) {
	        return value instanceof title_1.Title ? value : new title_1.Title(value);
	    }
	    Private.asTitle = asTitle;
	    /**
	     * Parse the transition duration for a tab node.
	     */
	    function parseTransitionDuration(tab) {
	        var style = window.getComputedStyle(tab);
	        return 1000 * (parseFloat(style.transitionDuration) || 0);
	    }
	    Private.parseTransitionDuration = parseTransitionDuration;
	    /**
	     * Get a snapshot of the current tab layout values.
	     */
	    function snapTabLayout(tabs, orientation) {
	        var layout = new Array(tabs.length);
	        if (orientation === 'horizontal') {
	            for (var i = 0, n = tabs.length; i < n; ++i) {
	                var node = tabs[i];
	                var pos = node.offsetLeft;
	                var size = node.offsetWidth;
	                var cstyle = window.getComputedStyle(node);
	                var margin = parseInt(cstyle.marginLeft, 10) || 0;
	                layout[i] = { margin: margin, pos: pos, size: size };
	            }
	        }
	        else {
	            for (var i = 0, n = tabs.length; i < n; ++i) {
	                var node = tabs[i];
	                var pos = node.offsetTop;
	                var size = node.offsetHeight;
	                var cstyle = window.getComputedStyle(node);
	                var margin = parseInt(cstyle.marginTop, 10) || 0;
	                layout[i] = { margin: margin, pos: pos, size: size };
	            }
	        }
	        return layout;
	    }
	    Private.snapTabLayout = snapTabLayout;
	    /**
	     * Test if the event exceeds the drag detach threshold.
	     */
	    function detachExceeded(data, event) {
	        var rect = data.contentRect;
	        return ((event.clientX < rect.left - DETACH_THRESHOLD) ||
	            (event.clientX >= rect.right + DETACH_THRESHOLD) ||
	            (event.clientY < rect.top - DETACH_THRESHOLD) ||
	            (event.clientY >= rect.bottom + DETACH_THRESHOLD));
	    }
	    Private.detachExceeded = detachExceeded;
	    /**
	     * Update the relative tab positions and computed target index.
	     */
	    function layoutTabs(tabs, data, event, orientation) {
	        // Compute the orientation-sensitive values.
	        var pressPos;
	        var localPos;
	        var clientPos;
	        var clientSize;
	        if (orientation === 'horizontal') {
	            pressPos = data.pressX;
	            localPos = event.clientX - data.contentRect.left;
	            clientPos = event.clientX;
	            clientSize = data.contentRect.width;
	        }
	        else {
	            pressPos = data.pressY;
	            localPos = event.clientY - data.contentRect.top;
	            clientPos = event.clientY;
	            clientSize = data.contentRect.height;
	        }
	        // Compute the target data.
	        var targetIndex = data.index;
	        var targetPos = localPos - data.tabPressPos;
	        var targetEnd = targetPos + data.tabSize;
	        // Update the relative tab positions.
	        for (var i = 0, n = tabs.length; i < n; ++i) {
	            var pxPos = void 0;
	            var layout = data.tabLayout[i];
	            var threshold = layout.pos + (layout.size >> 1);
	            if (i < data.index && targetPos < threshold) {
	                pxPos = (data.tabSize + data.tabLayout[i + 1].margin) + "px";
	                targetIndex = Math.min(targetIndex, i);
	            }
	            else if (i > data.index && targetEnd > threshold) {
	                pxPos = (-data.tabSize - layout.margin) + "px";
	                targetIndex = Math.max(targetIndex, i);
	            }
	            else if (i === data.index) {
	                var ideal = clientPos - pressPos;
	                var limit = clientSize - (data.tabPos + data.tabSize);
	                pxPos = Math.max(-data.tabPos, Math.min(ideal, limit)) + "px";
	            }
	            else {
	                pxPos = '';
	            }
	            if (orientation === 'horizontal') {
	                tabs[i].style.left = pxPos;
	            }
	            else {
	                tabs[i].style.top = pxPos;
	            }
	        }
	        // Update the computed target index.
	        data.targetIndex = targetIndex;
	    }
	    Private.layoutTabs = layoutTabs;
	    /**
	     * Position the drag tab at its final resting relative position.
	     */
	    function finalizeTabPosition(data, orientation) {
	        // Compute the orientation-sensitive client size.
	        var clientSize;
	        if (orientation === 'horizontal') {
	            clientSize = data.contentRect.width;
	        }
	        else {
	            clientSize = data.contentRect.height;
	        }
	        // Compute the ideal final tab position.
	        var ideal;
	        if (data.targetIndex === data.index) {
	            ideal = 0;
	        }
	        else if (data.targetIndex > data.index) {
	            var tgt = data.tabLayout[data.targetIndex];
	            ideal = tgt.pos + tgt.size - data.tabSize - data.tabPos;
	        }
	        else {
	            var tgt = data.tabLayout[data.targetIndex];
	            ideal = tgt.pos - data.tabPos;
	        }
	        // Compute the tab position limit.
	        var limit = clientSize - (data.tabPos + data.tabSize);
	        var final = Math.max(-data.tabPos, Math.min(ideal, limit));
	        // Set the final orientation-sensitive position.
	        if (orientation === 'horizontal') {
	            data.tab.style.left = final + "px";
	        }
	        else {
	            data.tab.style.top = final + "px";
	        }
	    }
	    Private.finalizeTabPosition = finalizeTabPosition;
	    /**
	     * Reset the relative positions of the given tabs.
	     */
	    function resetTabPositions(tabs, orientation) {
	        if (orientation === 'horizontal') {
	            iteration_1.each(tabs, function (tab) { tab.style.left = ''; });
	        }
	        else {
	            iteration_1.each(tabs, function (tab) { tab.style.top = ''; });
	        }
	    }
	    Private.resetTabPositions = resetTabPositions;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/tabbar.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/vdom.js **/
jupyter.define('phosphor@0.7.0/lib/ui/vdom.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * A node in a virtual DOM hierarchy.
	 *
	 * #### Notes
	 * User code will not usually instantiate an node directly. Rather, the
	 * `h()` function will be called to create a node in a type-safe manner.
	 *
	 * A node *must* be treated as immutable. Mutating the state of a node
	 * **will** result in undefined rendering behavior.
	 */
	var VNode = (function () {
	    /**
	     * Construct a new virtual DOM node.
	     *
	     * @param type - The type of the node.
	     *
	     * @param tag - The node tag.
	     *
	     * @param attrs - The node attributes.
	     *
	     * @param children - The node children.
	     */
	    function VNode(type, tag, attrs, children) {
	        this.type = type;
	        this.tag = tag;
	        this.attrs = attrs;
	        this.children = children;
	    }
	    return VNode;
	}());
	exports.VNode = VNode;
	function h(tag, first) {
	    // Setup the variables to hold the parsed data.
	    var attrs;
	    var children;
	    // Parse the first variadic argument.
	    if (first) {
	        if (typeof first === 'string') {
	            children = [first];
	        }
	        else if (first instanceof VNode) {
	            children = [first];
	        }
	        else if (first instanceof Array) {
	            children = first.slice();
	        }
	        else {
	            attrs = first;
	        }
	    }
	    // Parse the rest of the variadic arguments.
	    if (arguments.length > 2) {
	        children = children || [];
	        for (var i = 2, n = arguments.length; i < n; ++i) {
	            var child = arguments[i];
	            if (child instanceof Array) {
	                for (var j = 0, k = child.length; j < k; ++j) {
	                    if (child[j])
	                        children.push(child[j]);
	                }
	            }
	            else if (child) {
	                children.push(child);
	            }
	        }
	    }
	    // Convert string literal children into text nodes.
	    if (children) {
	        for (var i = 0, n = children.length; i < n; ++i) {
	            var child = children[i];
	            if (typeof child === 'string') {
	                children[i] = Private.createTextVNode(child);
	            }
	        }
	    }
	    // Return a new virtual DOM node.
	    return Private.createElementVNode(tag, attrs, children);
	}
	exports.h = h;
	/**
	 * The namespace for the `h()` function statics.
	 */
	var h;
	(function (h) {
	    h.a = h.bind(void 0, 'a');
	    h.abbr = h.bind(void 0, 'abbr');
	    h.address = h.bind(void 0, 'address');
	    h.area = h.bind(void 0, 'area');
	    h.article = h.bind(void 0, 'article');
	    h.aside = h.bind(void 0, 'aside');
	    h.audio = h.bind(void 0, 'audio');
	    h.b = h.bind(void 0, 'b');
	    h.bdi = h.bind(void 0, 'bdi');
	    h.bdo = h.bind(void 0, 'bdo');
	    h.blockquote = h.bind(void 0, 'blockquote');
	    h.br = h.bind(void 0, 'br');
	    h.button = h.bind(void 0, 'button');
	    h.canvas = h.bind(void 0, 'canvas');
	    h.caption = h.bind(void 0, 'caption');
	    h.cite = h.bind(void 0, 'cite');
	    h.code = h.bind(void 0, 'code');
	    h.col = h.bind(void 0, 'col');
	    h.colgroup = h.bind(void 0, 'colgroup');
	    h.data = h.bind(void 0, 'data');
	    h.datalist = h.bind(void 0, 'datalist');
	    h.dd = h.bind(void 0, 'dd');
	    h.del = h.bind(void 0, 'del');
	    h.dfn = h.bind(void 0, 'dfn');
	    h.div = h.bind(void 0, 'div');
	    h.dl = h.bind(void 0, 'dl');
	    h.dt = h.bind(void 0, 'dt');
	    h.em = h.bind(void 0, 'em');
	    h.embed = h.bind(void 0, 'embed');
	    h.fieldset = h.bind(void 0, 'fieldset');
	    h.figcaption = h.bind(void 0, 'figcaption');
	    h.figure = h.bind(void 0, 'figure');
	    h.footer = h.bind(void 0, 'footer');
	    h.form = h.bind(void 0, 'form');
	    h.h1 = h.bind(void 0, 'h1');
	    h.h2 = h.bind(void 0, 'h2');
	    h.h3 = h.bind(void 0, 'h3');
	    h.h4 = h.bind(void 0, 'h4');
	    h.h5 = h.bind(void 0, 'h5');
	    h.h6 = h.bind(void 0, 'h6');
	    h.header = h.bind(void 0, 'header');
	    h.hr = h.bind(void 0, 'hr');
	    h.i = h.bind(void 0, 'i');
	    h.iframe = h.bind(void 0, 'iframe');
	    h.img = h.bind(void 0, 'img');
	    h.input = h.bind(void 0, 'input');
	    h.ins = h.bind(void 0, 'ins');
	    h.kbd = h.bind(void 0, 'kbd');
	    h.label = h.bind(void 0, 'label');
	    h.legend = h.bind(void 0, 'legend');
	    h.li = h.bind(void 0, 'li');
	    h.main = h.bind(void 0, 'main');
	    h.map = h.bind(void 0, 'map');
	    h.mark = h.bind(void 0, 'mark');
	    h.meter = h.bind(void 0, 'meter');
	    h.nav = h.bind(void 0, 'nav');
	    h.noscript = h.bind(void 0, 'noscript');
	    h.object = h.bind(void 0, 'object');
	    h.ol = h.bind(void 0, 'ol');
	    h.optgroup = h.bind(void 0, 'optgroup');
	    h.option = h.bind(void 0, 'option');
	    h.output = h.bind(void 0, 'output');
	    h.p = h.bind(void 0, 'p');
	    h.param = h.bind(void 0, 'param');
	    h.pre = h.bind(void 0, 'pre');
	    h.progress = h.bind(void 0, 'progress');
	    h.q = h.bind(void 0, 'q');
	    h.rp = h.bind(void 0, 'rp');
	    h.rt = h.bind(void 0, 'rt');
	    h.ruby = h.bind(void 0, 'ruby');
	    h.s = h.bind(void 0, 's');
	    h.samp = h.bind(void 0, 'samp');
	    h.section = h.bind(void 0, 'section');
	    h.select = h.bind(void 0, 'select');
	    h.small = h.bind(void 0, 'small');
	    h.source = h.bind(void 0, 'source');
	    h.span = h.bind(void 0, 'span');
	    h.strong = h.bind(void 0, 'strong');
	    h.sub = h.bind(void 0, 'sub');
	    h.summary = h.bind(void 0, 'summary');
	    h.sup = h.bind(void 0, 'sup');
	    h.table = h.bind(void 0, 'table');
	    h.tbody = h.bind(void 0, 'tbody');
	    h.td = h.bind(void 0, 'td');
	    h.textarea = h.bind(void 0, 'textarea');
	    h.tfoot = h.bind(void 0, 'tfoot');
	    h.th = h.bind(void 0, 'th');
	    h.thead = h.bind(void 0, 'thead');
	    h.time = h.bind(void 0, 'time');
	    h.title = h.bind(void 0, 'title');
	    h.tr = h.bind(void 0, 'tr');
	    h.track = h.bind(void 0, 'track');
	    h.u = h.bind(void 0, 'u');
	    h.ul = h.bind(void 0, 'ul');
	    h.var_ = h.bind(void 0, 'var');
	    h.video = h.bind(void 0, 'video');
	    h.wbr = h.bind(void 0, 'wbr');
	})(h = exports.h || (exports.h = {}));
	/**
	 * Create a real DOM node from a virtual DOM node.
	 *
	 * @param content - The virtual DOM content to realize.
	 *
	 * @returns A new DOM node for the given virtual DOM tree.
	 *
	 * #### Notes
	 * The content node is assumed to be of the `'element'` type.
	 *
	 * This creates a brand new *real* DOM node with a structure which
	 * matches the given virtual DOM node.
	 *
	 * If virtual diffing is desired, use the `render` function instead.
	 */
	function realize(content) {
	    return Private.realizeImpl(content);
	}
	exports.realize = realize;
	/**
	 * Render virtual DOM content into a host element.
	 *
	 * @param content - The virtual DOM content to render.
	 *
	 * @param host - The host element for the rendered content.
	 *
	 * #### Notes
	 * This renders the delta from the previous rendering. It assumes that
	 * the content of the host element is not manipulated by external code.
	 *
	 * Providing `null` content will clear the rendering.
	 *
	 * Externally modifying the provided content or the host element will
	 * result in undefined rendering behavior.
	 */
	function render(content, host) {
	    Private.renderImpl(content, host);
	}
	exports.render = render;
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create a virtual text node for the given string.
	     */
	    function createTextVNode(text) {
	        return new VNode('text', text, emptyObject, emptyArray);
	    }
	    Private.createTextVNode = createTextVNode;
	    /**
	     * Create a virtual element node for the given parameters.
	     */
	    function createElementVNode(tag, attrs, children) {
	        attrs = attrs || emptyObject;
	        children = children || emptyArray;
	        return new VNode('element', tag, attrs, children);
	    }
	    Private.createElementVNode = createElementVNode;
	    /**
	     * The internal `realize` entry point.
	     */
	    function realizeImpl(content) {
	        return createDOMNode(content);
	    }
	    Private.realizeImpl = realizeImpl;
	    /**
	     * The internal `render` entry point.
	     */
	    function renderImpl(content, host) {
	        var oldContent = hostMap.get(host) || emptyArray;
	        var newContent = asVNodeArray(content);
	        hostMap.set(host, newContent);
	        updateContent(host, oldContent, newContent);
	    }
	    Private.renderImpl = renderImpl;
	    /**
	     * A shared frozen empty array.
	     */
	    var emptyArray = Object.freeze([]);
	    /**
	     * A shared frozen empty object.
	     */
	    var emptyObject = Object.freeze({});
	    /**
	     * A weak mapping of host element to virtual DOM content.
	     */
	    var hostMap = new WeakMap();
	    /**
	     * Coerce content into a virtual node array.
	     *
	     * Null content will be coerced to an empty array.
	     */
	    function asVNodeArray(content) {
	        if (content instanceof Array) {
	            return content;
	        }
	        if (content) {
	            return [content];
	        }
	        return emptyArray;
	    }
	    /**
	     * Update a host element with the delta of the virtual content.
	     *
	     * This is the core "diff" algorithm. There is no explicit "patch"
	     * phase. The host is patched at each step as the diff progresses.
	     */
	    function updateContent(host, oldContent, newContent) {
	        // Bail early if the content is identical. This can occur when an
	        // node has no children or if the user is rendering cached content.
	        if (oldContent === newContent) {
	            return;
	        }
	        // Collect the old keyed elems into a mapping.
	        var oldKeyed = collectKeys(host, oldContent);
	        // Create a copy of the old content which can be modified in-place.
	        var oldCopy = oldContent.slice();
	        // Update the host with the new content. The diff always proceeds
	        // forward and never modifies a previously visited index. The old
	        // copy array is modified in-place to reflect the changes made to
	        // the host children. This causes the stale nodes to be pushed to
	        // the end of the host node and removed at the end of the loop.
	        var currNode = host.firstChild;
	        var newCount = newContent.length;
	        for (var i = 0; i < newCount; ++i) {
	            // If the old elems are exhausted, create a new node.
	            if (i >= oldCopy.length) {
	                host.appendChild(createDOMNode(newContent[i]));
	                continue;
	            }
	            // Cache a reference to the old and new elems.
	            var oldVNode = oldCopy[i];
	            var newVNode = newContent[i];
	            // If the new elem is keyed, move an old keyed elem to the proper
	            // location before proceeding with the diff. The search can start
	            // at the current index, since the unmatched old keyed elems are
	            // pushed forward in the old copy array.
	            var newKey = newVNode.attrs.key;
	            if (newKey && newKey in oldKeyed) {
	                var pair = oldKeyed[newKey];
	                if (pair.vNode !== oldVNode) {
	                    arrayMove(oldCopy, oldCopy.indexOf(pair.vNode), i);
	                    host.insertBefore(pair.element, currNode);
	                    oldVNode = pair.vNode;
	                    currNode = pair.element;
	                }
	            }
	            // If both elements are identical, there is nothing to do.
	            // This can occur when the user renders cached content.
	            if (oldVNode === newVNode) {
	                currNode = currNode.nextSibling;
	                continue;
	            }
	            // If the old elem is keyed and does not match the new elem key,
	            // create a new node. This is necessary since the old keyed elem
	            // may be matched at a later point in the diff.
	            var oldKey = oldVNode.attrs.key;
	            if (oldKey && oldKey !== newKey) {
	                arrayInsert(oldCopy, i, newVNode);
	                host.insertBefore(createDOMNode(newVNode), currNode);
	                continue;
	            }
	            // If the elements have different types, create a new node.
	            if (oldVNode.type !== newVNode.type) {
	                arrayInsert(oldCopy, i, newVNode);
	                host.insertBefore(createDOMNode(newVNode), currNode);
	                continue;
	            }
	            // If the element is a text node, update its text content.
	            if (newVNode.type === 'text') {
	                currNode.textContent = newVNode.tag;
	                currNode = currNode.nextSibling;
	                continue;
	            }
	            // At this point, the node is an 'element' type. If the tags
	            // are different, create a new node.
	            if (oldVNode.tag !== newVNode.tag) {
	                arrayInsert(oldCopy, i, newVNode);
	                host.insertBefore(createDOMNode(newVNode), currNode);
	                continue;
	            }
	            // The element tags match, update the element in place.
	            updateAttrs(currNode, oldVNode.attrs, newVNode.attrs);
	            updateContent(currNode, oldVNode.children, newVNode.children);
	            currNode = currNode.nextSibling;
	        }
	        // Dispose of the old nodes pushed to the end of the host.
	        for (var i = oldCopy.length - 1; i >= newCount; --i) {
	            host.removeChild(host.lastChild);
	        }
	    }
	    /**
	     * Add attributes to a newly created DOM node.
	     */
	    function addAttrs(node, attrs) {
	        // Set the known attributes defined in the attr table.
	        for (var name_1 in attrs) {
	            var mode = attrModeTable[name_1];
	            if (mode === 0 /* Property */ || mode === 2 /* Event */) {
	                node[name_1] = attrs[name_1];
	            }
	            else if (mode === 1 /* Attribute */) {
	                node.setAttribute(name_1.toLowerCase(), attrs[name_1]);
	            }
	        }
	        // Handle the dataset values.
	        var dataset = attrs.dataset;
	        if (dataset) {
	            for (var name_2 in dataset) {
	                node.setAttribute("data-" + name_2, dataset[name_2]);
	            }
	        }
	        // Handle the inline styles.
	        var styles = attrs.style;
	        if (styles) {
	            var nodeStyle = node.style;
	            for (var name_3 in styles) {
	                nodeStyle[name_3] = styles[name_3];
	            }
	        }
	    }
	    /**
	     * Update the node attributes with the delta of attribute objects.
	     */
	    function updateAttrs(node, oldAttrs, newAttrs) {
	        // Do nothing if the attrs are the same object.
	        if (oldAttrs === newAttrs) {
	            return;
	        }
	        // Remove attributes which no longer exist.
	        for (var name_4 in oldAttrs) {
	            if (!(name_4 in newAttrs)) {
	                var mode = attrModeTable[name_4];
	                if (mode === 0 /* Property */) {
	                    node.removeAttribute(name_4);
	                }
	                else if (mode === 1 /* Attribute */) {
	                    node.removeAttribute(name_4.toLowerCase());
	                }
	                else if (mode === 2 /* Event */) {
	                    node[name_4] = null;
	                }
	            }
	        }
	        // Add new attributes an update existing ones.
	        for (var name_5 in newAttrs) {
	            var value = newAttrs[name_5];
	            if (oldAttrs[name_5] !== value) {
	                var mode = attrModeTable[name_5];
	                if (mode === 0 /* Property */ || mode === 2 /* Event */) {
	                    node[name_5] = value;
	                }
	                else if (mode === 1 /* Attribute */) {
	                    node.setAttribute(name_5.toLowerCase(), value);
	                }
	            }
	        }
	        // Handle the dataset values.
	        var oldDataset = oldAttrs.dataset || emptyObject;
	        var newDataset = newAttrs.dataset || emptyObject;
	        if (oldDataset !== newDataset) {
	            for (var name_6 in oldDataset) {
	                if (!(name_6 in newDataset)) {
	                    node.removeAttribute('data-' + name_6);
	                }
	            }
	            for (var name_7 in newDataset) {
	                var value = newDataset[name_7];
	                if (oldDataset[name_7] !== value) {
	                    node.setAttribute('data-' + name_7, value);
	                }
	            }
	        }
	        // Handle the inline styles.
	        var oldStyle = oldAttrs.style || emptyObject;
	        var newStyle = newAttrs.style || emptyObject;
	        if (oldStyle !== newStyle) {
	            var nodeStyle = node.style;
	            for (var name_8 in oldStyle) {
	                if (!(name_8 in newStyle)) {
	                    nodeStyle[name_8] = '';
	                }
	            }
	            for (var name_9 in newStyle) {
	                var value = newStyle[name_9];
	                if (oldStyle[name_9] !== value) {
	                    nodeStyle[name_9] = value;
	                }
	            }
	        }
	    }
	    /**
	     * Collect a mapping of keyed elements for the host content.
	     */
	    function collectKeys(host, content) {
	        var node = host.firstChild;
	        var keyed = Object.create(null);
	        for (var i = 0, n = content.length; i < n; ++i) {
	            var vNode = content[i];
	            if (vNode.type === 'element') {
	                var key = vNode.attrs.key;
	                if (key)
	                    keyed[key] = { vNode: vNode, element: node };
	            }
	            node = node.nextSibling;
	        }
	        return keyed;
	    }
	    /**
	     * Create and return a new DOM node for a virtual element.
	     */
	    function createDOMNode(elem) {
	        var node;
	        if (elem.type === 'text') {
	            node = document.createTextNode(elem.tag);
	        }
	        else {
	            node = document.createElement(elem.tag);
	            addAttrs(node, elem.attrs);
	            addContent(node, elem.children);
	        }
	        return node;
	    }
	    /**
	     * Create and add child content to a newly created DOM node.
	     */
	    function addContent(node, content) {
	        for (var i = 0, n = content.length; i < n; ++i) {
	            node.appendChild(createDOMNode(content[i]));
	        }
	    }
	    /**
	     * A mapping of attribute name to attribute mode.
	     */
	    var attrModeTable = {
	        accept: 0 /* Property */,
	        acceptCharset: 0 /* Property */,
	        accessKey: 0 /* Property */,
	        action: 0 /* Property */,
	        allowFullscreen: 1 /* Attribute */,
	        alt: 0 /* Property */,
	        autocomplete: 0 /* Property */,
	        autofocus: 0 /* Property */,
	        autoplay: 0 /* Property */,
	        checked: 0 /* Property */,
	        cite: 0 /* Property */,
	        className: 0 /* Property */,
	        colSpan: 0 /* Property */,
	        cols: 0 /* Property */,
	        contentEditable: 0 /* Property */,
	        controls: 0 /* Property */,
	        coords: 0 /* Property */,
	        crossOrigin: 0 /* Property */,
	        data: 0 /* Property */,
	        dateTime: 0 /* Property */,
	        default: 0 /* Property */,
	        dir: 0 /* Property */,
	        dirName: 0 /* Property */,
	        disabled: 0 /* Property */,
	        download: 0 /* Property */,
	        draggable: 0 /* Property */,
	        enctype: 0 /* Property */,
	        form: 1 /* Attribute */,
	        formAction: 0 /* Property */,
	        formEnctype: 0 /* Property */,
	        formMethod: 0 /* Property */,
	        formNoValidate: 0 /* Property */,
	        formTarget: 0 /* Property */,
	        headers: 0 /* Property */,
	        height: 0 /* Property */,
	        hidden: 0 /* Property */,
	        high: 0 /* Property */,
	        href: 0 /* Property */,
	        hreflang: 0 /* Property */,
	        htmlFor: 0 /* Property */,
	        id: 0 /* Property */,
	        inputMode: 0 /* Property */,
	        isMap: 0 /* Property */,
	        kind: 0 /* Property */,
	        label: 0 /* Property */,
	        lang: 0 /* Property */,
	        list: 1 /* Attribute */,
	        loop: 0 /* Property */,
	        low: 0 /* Property */,
	        max: 0 /* Property */,
	        maxLength: 0 /* Property */,
	        media: 1 /* Attribute */,
	        mediaGroup: 0 /* Property */,
	        method: 0 /* Property */,
	        min: 0 /* Property */,
	        minLength: 0 /* Property */,
	        multiple: 0 /* Property */,
	        muted: 0 /* Property */,
	        name: 0 /* Property */,
	        noValidate: 0 /* Property */,
	        optimum: 0 /* Property */,
	        pattern: 0 /* Property */,
	        placeholder: 0 /* Property */,
	        poster: 0 /* Property */,
	        preload: 0 /* Property */,
	        readOnly: 0 /* Property */,
	        rel: 0 /* Property */,
	        required: 0 /* Property */,
	        reversed: 0 /* Property */,
	        rowSpan: 0 /* Property */,
	        rows: 0 /* Property */,
	        sandbox: 0 /* Property */,
	        scope: 0 /* Property */,
	        seamless: 1 /* Attribute */,
	        selected: 0 /* Property */,
	        shape: 0 /* Property */,
	        size: 0 /* Property */,
	        sizes: 1 /* Attribute */,
	        sorted: 0 /* Property */,
	        span: 0 /* Property */,
	        spellcheck: 0 /* Property */,
	        src: 0 /* Property */,
	        srcdoc: 0 /* Property */,
	        srclang: 0 /* Property */,
	        srcset: 1 /* Attribute */,
	        start: 0 /* Property */,
	        step: 0 /* Property */,
	        tabIndex: 0 /* Property */,
	        target: 0 /* Property */,
	        title: 0 /* Property */,
	        type: 0 /* Property */,
	        typeMustMatch: 0 /* Property */,
	        useMap: 0 /* Property */,
	        value: 0 /* Property */,
	        volume: 0 /* Property */,
	        width: 0 /* Property */,
	        wrap: 0 /* Property */,
	        onabort: 2 /* Event */,
	        onbeforecopy: 2 /* Event */,
	        onbeforecut: 2 /* Event */,
	        onbeforepaste: 2 /* Event */,
	        onblur: 2 /* Event */,
	        oncanplay: 2 /* Event */,
	        oncanplaythrough: 2 /* Event */,
	        onchange: 2 /* Event */,
	        onclick: 2 /* Event */,
	        oncontextmenu: 2 /* Event */,
	        oncopy: 2 /* Event */,
	        oncuechange: 2 /* Event */,
	        oncut: 2 /* Event */,
	        ondblclick: 2 /* Event */,
	        ondrag: 2 /* Event */,
	        ondragend: 2 /* Event */,
	        ondragenter: 2 /* Event */,
	        ondragleave: 2 /* Event */,
	        ondragover: 2 /* Event */,
	        ondragstart: 2 /* Event */,
	        ondrop: 2 /* Event */,
	        ondurationchange: 2 /* Event */,
	        onended: 2 /* Event */,
	        onemptied: 2 /* Event */,
	        onerror: 2 /* Event */,
	        onfocus: 2 /* Event */,
	        onhelp: 2 /* Event */,
	        oninput: 2 /* Event */,
	        onkeydown: 2 /* Event */,
	        onkeypress: 2 /* Event */,
	        onkeyup: 2 /* Event */,
	        onload: 2 /* Event */,
	        onloadeddata: 2 /* Event */,
	        onloadedmetadata: 2 /* Event */,
	        onloadstart: 2 /* Event */,
	        onmousedown: 2 /* Event */,
	        onmouseenter: 2 /* Event */,
	        onmouseleave: 2 /* Event */,
	        onmousemove: 2 /* Event */,
	        onmouseout: 2 /* Event */,
	        onmouseover: 2 /* Event */,
	        onmouseup: 2 /* Event */,
	        onmousewheel: 2 /* Event */,
	        onpaste: 2 /* Event */,
	        onpause: 2 /* Event */,
	        onplay: 2 /* Event */,
	        onplaying: 2 /* Event */,
	        onprogress: 2 /* Event */,
	        onratechange: 2 /* Event */,
	        onreadystatechange: 2 /* Event */,
	        onreset: 2 /* Event */,
	        onscroll: 2 /* Event */,
	        onseeked: 2 /* Event */,
	        onseeking: 2 /* Event */,
	        onselect: 2 /* Event */,
	        onselectstart: 2 /* Event */,
	        onstalled: 2 /* Event */,
	        onsubmit: 2 /* Event */,
	        onsuspend: 2 /* Event */,
	        ontimeupdate: 2 /* Event */,
	        onvolumechange: 2 /* Event */,
	        onwaiting: 2 /* Event */
	    };
	    /**
	     * Insert an element into an array at a specified index.
	     */
	    function arrayInsert(array, i, value) {
	        for (var k = array.length; k > i; --k) {
	            array[k] = array[k - 1];
	        }
	        array[i] = value;
	    }
	    /**
	     * Move an element in an array from one index to another.
	     */
	    function arrayMove(array, i, j) {
	        if (i === j) {
	            return;
	        }
	        var value = array[i];
	        var d = i < j ? 1 : -1;
	        for (var k = i; k !== j; k += d) {
	            array[k] = array[k + d];
	        }
	        array[j] = value;
	    }
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/vdom.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/splitpanel.js **/
jupyter.define('phosphor@0.7.0/lib/ui/splitpanel.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	var mutation_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/mutation.js');
	var searching_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var messaging_1 = __jupyter_require__('phosphor@0.7.0/lib/core/messaging.js');
	var properties_1 = __jupyter_require__('phosphor@0.7.0/lib/core/properties.js');
	var cursor_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/cursor.js');
	var platform_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/platform.js');
	var sizing_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/sizing.js');
	var boxengine_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/boxengine.js');
	var panel_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to SplitPanel instances.
	 */
	var SPLIT_PANEL_CLASS = 'p-SplitPanel';
	/**
	 * The class name added to split panel children.
	 */
	var CHILD_CLASS = 'p-SplitPanel-child';
	/**
	 * The class name added to split panel handles.
	 */
	var HANDLE_CLASS = 'p-SplitPanel-handle';
	/**
	 * The class name added to hidden split handles.
	 */
	var HIDDEN_CLASS = 'p-mod-hidden';
	/**
	 * The class name added to horizontal split panels.
	 */
	var HORIZONTAL_CLASS = 'p-mod-horizontal';
	/**
	 * The class name added to vertical split panels.
	 */
	var VERTICAL_CLASS = 'p-mod-vertical';
	/**
	 * A panel which arranges its widgets into resizable sections.
	 *
	 * #### Notes
	 * This class provides a convenience wrapper around a [[SplitLayout]].
	 */
	var SplitPanel = (function (_super) {
	    __extends(SplitPanel, _super);
	    /**
	     * Construct a new split panel.
	     *
	     * @param options - The options for initializing the split panel.
	     */
	    function SplitPanel(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this, { layout: Private.createLayout(options) });
	        this._pressData = null;
	        this.addClass(SPLIT_PANEL_CLASS);
	    }
	    /**
	     * Dispose of the resources held by the panel.
	     */
	    SplitPanel.prototype.dispose = function () {
	        this._releaseMouse();
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(SplitPanel.prototype, "orientation", {
	        /**
	         * Get the layout orientation for the split panel.
	         */
	        get: function () {
	            return this.layout.orientation;
	        },
	        /**
	         * Set the layout orientation for the split panel.
	         */
	        set: function (value) {
	            this.layout.orientation = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SplitPanel.prototype, "spacing", {
	        /**
	         * Get the inter-element spacing for the split panel.
	         */
	        get: function () {
	            return this.layout.spacing;
	        },
	        /**
	         * Set the inter-element spacing for the split panel.
	         */
	        set: function (value) {
	            this.layout.spacing = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SplitPanel.prototype, "renderer", {
	        /**
	         * The renderer used by the split panel.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.layout.renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SplitPanel.prototype, "handles", {
	        /**
	         * A read-only sequence of the split handles in the panel.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.layout.handles;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Get the relative sizes of the widgets in the panel.
	     *
	     * @returns A new array of the relative sizes of the widgets.
	     *
	     * #### Notes
	     * The returned sizes reflect the sizes of the widgets normalized
	     * relative to their siblings.
	     *
	     * This method **does not** measure the DOM nodes.
	     */
	    SplitPanel.prototype.relativeSizes = function () {
	        return this.layout.relativeSizes();
	    };
	    /**
	     * Set the relative sizes for the widgets in the panel.
	     *
	     * @param sizes - The relative sizes for the widgets in the panel.
	     *
	     * #### Notes
	     * Extra values are ignored, too few will yield an undefined layout.
	     *
	     * The actual geometry of the DOM nodes is updated asynchronously.
	     */
	    SplitPanel.prototype.setRelativeSizes = function (sizes) {
	        this.layout.setRelativeSizes(sizes);
	    };
	    /**
	     * Handle the DOM events for the split panel.
	     *
	     * @param event - The DOM event sent to the panel.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the panel's DOM node. It should
	     * not be called directly by user code.
	     */
	    SplitPanel.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'mousedown':
	                this._evtMouseDown(event);
	                break;
	            case 'mousemove':
	                this._evtMouseMove(event);
	                break;
	            case 'mouseup':
	                this._evtMouseUp(event);
	                break;
	            case 'keydown':
	                this._evtKeyDown(event);
	                break;
	            case 'contextmenu':
	                event.preventDefault();
	                event.stopPropagation();
	                break;
	        }
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    SplitPanel.prototype.onAfterAttach = function (msg) {
	        this.node.addEventListener('mousedown', this);
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    SplitPanel.prototype.onBeforeDetach = function (msg) {
	        this.node.removeEventListener('mousedown', this);
	        this._releaseMouse();
	    };
	    /**
	     * A message handler invoked on a `'child-added'` message.
	     */
	    SplitPanel.prototype.onChildAdded = function (msg) {
	        msg.child.addClass(CHILD_CLASS);
	        this._releaseMouse();
	    };
	    /**
	     * A message handler invoked on a `'child-removed'` message.
	     */
	    SplitPanel.prototype.onChildRemoved = function (msg) {
	        msg.child.removeClass(CHILD_CLASS);
	        this._releaseMouse();
	    };
	    /**
	     * Handle the `'keydown'` event for the split panel.
	     */
	    SplitPanel.prototype._evtKeyDown = function (event) {
	        // Stop input events during drag.
	        event.preventDefault();
	        event.stopPropagation();
	        // Release the mouse if `Escape` is pressed.
	        if (event.keyCode === 27)
	            this._releaseMouse();
	    };
	    /**
	     * Handle the `'mousedown'` event for the split panel.
	     */
	    SplitPanel.prototype._evtMouseDown = function (event) {
	        // Do nothing if the left mouse button is not pressed.
	        if (event.button !== 0) {
	            return;
	        }
	        // Find the handle which contains the mouse target, if any.
	        var layout = this.layout;
	        var target = event.target;
	        var index = searching_1.findIndex(layout.handles, function (handle) { return handle.contains(target); });
	        if (index === -1) {
	            return;
	        }
	        // Stop the event when a split handle is pressed.
	        event.preventDefault();
	        event.stopPropagation();
	        // Add the extra document listeners.
	        document.addEventListener('mouseup', this, true);
	        document.addEventListener('mousemove', this, true);
	        document.addEventListener('keydown', this, true);
	        document.addEventListener('contextmenu', this, true);
	        // Compute the offset delta for the handle press.
	        var delta;
	        var handle = layout.handles.at(index);
	        var rect = handle.getBoundingClientRect();
	        if (layout.orientation === 'horizontal') {
	            delta = event.clientX - rect.left;
	        }
	        else {
	            delta = event.clientY - rect.top;
	        }
	        // Override the cursor and store the press data.
	        var style = window.getComputedStyle(handle);
	        var override = cursor_1.overrideCursor(style.cursor);
	        this._pressData = { index: index, delta: delta, override: override };
	    };
	    /**
	     * Handle the `'mousemove'` event for the split panel.
	     */
	    SplitPanel.prototype._evtMouseMove = function (event) {
	        // Stop the event when dragging a split handle.
	        event.preventDefault();
	        event.stopPropagation();
	        // Compute the desired offset position for the handle.
	        var pos;
	        var layout = this.layout;
	        var rect = this.node.getBoundingClientRect();
	        if (layout.orientation === 'horizontal') {
	            pos = event.clientX - rect.left - this._pressData.delta;
	        }
	        else {
	            pos = event.clientY - rect.top - this._pressData.delta;
	        }
	        // Set the handle as close to the desired position as possible.
	        layout.setHandlePosition(this._pressData.index, pos);
	    };
	    /**
	     * Handle the `'mouseup'` event for the split panel.
	     */
	    SplitPanel.prototype._evtMouseUp = function (event) {
	        // Do nothing if the left mouse button is not released.
	        if (event.button !== 0) {
	            return;
	        }
	        // Stop the event when releasing a handle.
	        event.preventDefault();
	        event.stopPropagation();
	        // Finalize the mouse release.
	        this._releaseMouse();
	    };
	    /**
	     * Release the mouse grab for the split panel.
	     */
	    SplitPanel.prototype._releaseMouse = function () {
	        // Bail early if no drag is in progress.
	        if (!this._pressData) {
	            return;
	        }
	        // Clear the override cursor.
	        this._pressData.override.dispose();
	        this._pressData = null;
	        // Remove the extra document listeners.
	        document.removeEventListener('mouseup', this, true);
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('keydown', this, true);
	        document.removeEventListener('contextmenu', this, true);
	    };
	    return SplitPanel;
	}(panel_1.Panel));
	exports.SplitPanel = SplitPanel;
	/**
	 * The namespace for the `SplitPanel` class statics.
	 */
	var SplitPanel;
	(function (SplitPanel) {
	    /**
	     * The default implementation of `IRenderer`.
	     */
	    var Renderer = (function () {
	        function Renderer() {
	        }
	        /**
	         * Create a new handle node for use with a split panel.
	         *
	         * @returns A new handle node for a split panel.
	         */
	        Renderer.prototype.createHandleNode = function () {
	            var node = document.createElement('div');
	            node.className = HANDLE_CLASS;
	            return node;
	        };
	        return Renderer;
	    }());
	    SplitPanel.Renderer = Renderer;
	    /**
	     * The default `Renderer` instance.
	     */
	    SplitPanel.defaultRenderer = new Renderer();
	    /**
	     * Get the split panel stretch factor for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The split panel stretch factor for the widget.
	     */
	    function getStretch(widget) {
	        return SplitLayout.getStretch(widget);
	    }
	    SplitPanel.getStretch = getStretch;
	    /**
	     * Set the split panel stretch factor for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @param value - The value for the stretch factor.
	     */
	    function setStretch(widget, value) {
	        SplitLayout.setStretch(widget, value);
	    }
	    SplitPanel.setStretch = setStretch;
	})(SplitPanel = exports.SplitPanel || (exports.SplitPanel = {}));
	/**
	 * A layout which arranges its widgets into resizable sections.
	 */
	var SplitLayout = (function (_super) {
	    __extends(SplitLayout, _super);
	    /**
	     * Construct a new split layout.
	     *
	     * @param options - The options for initializing the layout.
	     */
	    function SplitLayout(options) {
	        _super.call(this);
	        this._fixed = 0;
	        this._spacing = 4;
	        this._dirty = false;
	        this._hasNormedSizes = false;
	        this._box = null;
	        this._sizers = new vector_1.Vector();
	        this._handles = new vector_1.Vector();
	        this._orientation = 'horizontal';
	        this._renderer = options.renderer;
	        if (options.orientation !== void 0) {
	            this._orientation = options.orientation;
	        }
	        if (options.spacing !== void 0) {
	            this._spacing = Private.clampSpacing(options.spacing);
	        }
	    }
	    Object.defineProperty(SplitLayout.prototype, "orientation", {
	        /**
	         * Get the layout orientation for the split layout.
	         */
	        get: function () {
	            return this._orientation;
	        },
	        /**
	         * Set the layout orientation for the split layout.
	         */
	        set: function (value) {
	            if (this._orientation === value) {
	                return;
	            }
	            this._orientation = value;
	            if (!this.parent) {
	                return;
	            }
	            Private.toggleOrientation(this.parent, value);
	            this.parent.fit();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SplitLayout.prototype, "spacing", {
	        /**
	         * Get the inter-element spacing for the split layout.
	         */
	        get: function () {
	            return this._spacing;
	        },
	        /**
	         * Set the inter-element spacing for the split layout.
	         */
	        set: function (value) {
	            value = Private.clampSpacing(value);
	            if (this._spacing === value) {
	                return;
	            }
	            this._spacing = value;
	            if (!this.parent) {
	                return;
	            }
	            this.parent.fit();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SplitLayout.prototype, "renderer", {
	        /**
	         * The renderer used by the split layout.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SplitLayout.prototype, "handles", {
	        /**
	         * A read-only sequence of the split handles in the layout.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._handles;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Get the relative sizes of the widgets in the layout.
	     *
	     * @returns A new array of the relative sizes of the widgets.
	     *
	     * #### Notes
	     * The returned sizes reflect the sizes of the widgets normalized
	     * relative to their siblings.
	     *
	     * This method **does not** measure the DOM nodes.
	     */
	    SplitLayout.prototype.relativeSizes = function () {
	        return Private.normalize(iteration_1.toArray(iteration_1.map(this._sizers, function (sizer) { return sizer.size; })));
	    };
	    /**
	     * Set the relative sizes for the widgets in the layout.
	     *
	     * @param sizes - The relative sizes for the widgets in the panel.
	     *
	     * #### Notes
	     * Extra values are ignored, too few will yield an undefined layout.
	     *
	     * The actual geometry of the DOM nodes is updated asynchronously.
	     */
	    SplitLayout.prototype.setRelativeSizes = function (sizes) {
	        // Copy the sizes and pad with zeros as needed.
	        var n = this._sizers.length;
	        var temp = sizes.slice(0, n);
	        while (temp.length < n)
	            temp.push(0);
	        // Normalize the padded sizes.
	        var normed = Private.normalize(temp);
	        // Apply the normalized sizes to the sizers.
	        for (var i = 0; i < n; ++i) {
	            var sizer = this._sizers.at(i);
	            sizer.sizeHint = sizer.size = normed[i];
	        }
	        // Set the flag indicating the sizes are normalized.
	        this._hasNormedSizes = true;
	        // Trigger an update of the parent widget.
	        if (this.parent)
	            this.parent.update();
	    };
	    // TODO rename this to `moveHandle`
	    /**
	     * Set the offset position of a split handle.
	     *
	     * @param index - The index of the handle of the interest.
	     *
	     * @param position - The desired offset position of the handle.
	     *
	     * #### Notes
	     * The position is relative to the offset parent.
	     *
	     * This will move the handle as close as possible to the desired
	     * position. The sibling widgets will be adjusted as necessary.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral or out of range.
	     */
	    SplitLayout.prototype.setHandlePosition = function (index, position) {
	        // Bail if the index is invalid or the handle is hidden.
	        var handle = this._handles.at(index);
	        if (!handle || handle.classList.contains(HIDDEN_CLASS)) {
	            return;
	        }
	        // Compute the desired delta movement for the handle.
	        var delta;
	        if (this._orientation === 'horizontal') {
	            delta = position - handle.offsetLeft;
	        }
	        else {
	            delta = position - handle.offsetTop;
	        }
	        // Bail if there is no handle movement.
	        if (delta === 0) {
	            return;
	        }
	        // Prevent widget resizing unless needed.
	        iteration_1.each(this._sizers, function (sizer) {
	            // TODO is this check actually necessary?
	            if (sizer.size > 0)
	                sizer.sizeHint = sizer.size;
	        });
	        // Adjust the sizers to reflect the handle movement.
	        boxengine_1.adjustSizer(this._sizers, index, delta);
	        // Update the layout of the widgets.
	        if (this.parent)
	            this.parent.update();
	    };
	    /**
	     * Perform layout initialization which requires the parent widget.
	     */
	    SplitLayout.prototype.init = function () {
	        Private.toggleOrientation(this.parent, this.orientation);
	        _super.prototype.init.call(this);
	    };
	    /**
	     * Attach a widget to the parent's DOM node.
	     *
	     * @param index - The current index of the widget in the layout.
	     *
	     * @param widget - The widget to attach to the parent.
	     *
	     * #### Notes
	     * This is a reimplementation of the superclass method.
	     */
	    SplitLayout.prototype.attachWidget = function (index, widget) {
	        // Create and add the handle and sizer for the new widget.
	        var handle = Private.createHandle(this._renderer);
	        var average = Private.averageSize(this._sizers);
	        var sizer = Private.createSizer(average);
	        this._sizers.insert(index, sizer);
	        this._handles.insert(index, handle);
	        // Prepare the layout geometry for the widget.
	        widget_1.Widget.prepareGeometry(widget);
	        // Add the widget and handle nodes to the parent.
	        this.parent.node.appendChild(widget.node);
	        this.parent.node.appendChild(handle);
	        // Send an `'after-attach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.AfterAttach);
	        // Post a fit request for the parent widget.
	        this.parent.fit();
	    };
	    /**
	     * Move a widget in the parent's DOM node.
	     *
	     * @param fromIndex - The previous index of the widget in the layout.
	     *
	     * @param toIndex - The current index of the widget in the layout.
	     *
	     * @param widget - The widget to move in the parent.
	     *
	     * #### Notes
	     * This is a reimplementation of the superclass method.
	     */
	    SplitLayout.prototype.moveWidget = function (fromIndex, toIndex, widget) {
	        // Move the sizer and handle for the widget.
	        mutation_1.move(this._sizers, fromIndex, toIndex);
	        mutation_1.move(this._handles, fromIndex, toIndex);
	        // Post a fit request to the parent to show/hide last handle.
	        this.parent.fit();
	    };
	    /**
	     * Detach a widget from the parent's DOM node.
	     *
	     * @param index - The previous index of the widget in the layout.
	     *
	     * @param widget - The widget to detach from the parent.
	     *
	     * #### Notes
	     * This is a reimplementation of the superclass method.
	     */
	    SplitLayout.prototype.detachWidget = function (index, widget) {
	        // Remove the handle for the widget.
	        var handle = this._handles.removeAt(index);
	        // Remove the sizer for the widget.
	        this._sizers.removeAt(index);
	        // Send a `'before-detach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.BeforeDetach);
	        // Remove the widget and handle nodes from the parent.
	        this.parent.node.removeChild(widget.node);
	        this.parent.node.removeChild(handle);
	        // Reset the layout geometry for the widget.
	        widget_1.Widget.resetGeometry(widget);
	        // Post a fit request for the parent widget.
	        this.parent.fit();
	    };
	    /**
	     * A message handler invoked on an `'after-show'` message.
	     */
	    SplitLayout.prototype.onAfterShow = function (msg) {
	        _super.prototype.onAfterShow.call(this, msg);
	        this.parent.update();
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    SplitLayout.prototype.onAfterAttach = function (msg) {
	        _super.prototype.onAfterAttach.call(this, msg);
	        this.parent.fit();
	    };
	    /**
	     * A message handler invoked on a `'child-shown'` message.
	     */
	    SplitLayout.prototype.onChildShown = function (msg) {
	        if (platform_1.IS_IE || platform_1.IS_EDGE) {
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.FitRequest);
	        }
	        else {
	            this.parent.fit();
	        }
	    };
	    /**
	     * A message handler invoked on a `'child-hidden'` message.
	     */
	    SplitLayout.prototype.onChildHidden = function (msg) {
	        if (platform_1.IS_IE || platform_1.IS_EDGE) {
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.FitRequest);
	        }
	        else {
	            this.parent.fit();
	        }
	    };
	    /**
	     * A message handler invoked on a `'resize'` message.
	     */
	    SplitLayout.prototype.onResize = function (msg) {
	        if (this.parent.isVisible) {
	            this._update(msg.width, msg.height);
	        }
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    SplitLayout.prototype.onUpdateRequest = function (msg) {
	        if (this.parent.isVisible) {
	            this._update(-1, -1);
	        }
	    };
	    /**
	     * A message handler invoked on a `'fit-request'` message.
	     */
	    SplitLayout.prototype.onFitRequest = function (msg) {
	        if (this.parent.isAttached) {
	            this._fit();
	        }
	    };
	    /**
	     * Fit the layout to the total size required by the widgets.
	     */
	    SplitLayout.prototype._fit = function () {
	        // Update the handles and track the visible widget count.
	        var nVisible = 0;
	        var widgets = this.widgets;
	        var lastHandle = null;
	        for (var i = 0, n = widgets.length; i < n; ++i) {
	            var handle = this._handles.at(i);
	            if (widgets.at(i).isHidden) {
	                handle.classList.add(HIDDEN_CLASS);
	            }
	            else {
	                handle.classList.remove(HIDDEN_CLASS);
	                lastHandle = handle;
	                nVisible++;
	            }
	        }
	        // Hide the handle for the last visible widget.
	        if (lastHandle)
	            lastHandle.classList.add(HIDDEN_CLASS);
	        // Update the fixed space for the visible items.
	        this._fixed = this._spacing * Math.max(0, nVisible - 1);
	        // Setup the initial size limits.
	        var minW = 0;
	        var minH = 0;
	        var maxW = Infinity;
	        var maxH = Infinity;
	        var horz = this._orientation === 'horizontal';
	        if (horz) {
	            minW = this._fixed;
	            maxW = nVisible > 0 ? minW : maxW;
	        }
	        else {
	            minH = this._fixed;
	            maxH = nVisible > 0 ? minH : maxH;
	        }
	        // Update the sizers and computed size limits.
	        for (var i = 0, n = widgets.length; i < n; ++i) {
	            var widget = widgets.at(i);
	            var sizer = this._sizers.at(i);
	            if (sizer.size > 0) {
	                sizer.sizeHint = sizer.size;
	            }
	            if (widget.isHidden) {
	                sizer.minSize = 0;
	                sizer.maxSize = 0;
	                continue;
	            }
	            var limits = sizing_1.sizeLimits(widget.node);
	            sizer.stretch = SplitLayout.getStretch(widget);
	            if (horz) {
	                sizer.minSize = limits.minWidth;
	                sizer.maxSize = limits.maxWidth;
	                minW += limits.minWidth;
	                maxW += limits.maxWidth;
	                minH = Math.max(minH, limits.minHeight);
	                maxH = Math.min(maxH, limits.maxHeight);
	            }
	            else {
	                sizer.minSize = limits.minHeight;
	                sizer.maxSize = limits.maxHeight;
	                minH += limits.minHeight;
	                maxH += limits.maxHeight;
	                minW = Math.max(minW, limits.minWidth);
	                maxW = Math.min(maxW, limits.maxWidth);
	            }
	        }
	        // Update the box sizing and add it to the size constraints.
	        var box = this._box = sizing_1.boxSizing(this.parent.node);
	        minW += box.horizontalSum;
	        minH += box.verticalSum;
	        maxW += box.horizontalSum;
	        maxH += box.verticalSum;
	        // Update the parent's size constraints.
	        var style = this.parent.node.style;
	        style.minWidth = minW + "px";
	        style.minHeight = minH + "px";
	        style.maxWidth = maxW === Infinity ? 'none' : maxW + "px";
	        style.maxHeight = maxH === Infinity ? 'none' : maxH + "px";
	        // Set the dirty flag to ensure only a single update occurs.
	        this._dirty = true;
	        // Notify the ancestor that it should fit immediately. This may
	        // cause a resize of the parent, fulfilling the required update.
	        var ancestor = this.parent.parent;
	        if (ancestor)
	            messaging_1.sendMessage(ancestor, widget_1.WidgetMessage.FitRequest);
	        // If the dirty flag is still set, the parent was not resized.
	        // Trigger the required update on the parent widget immediately.
	        if (this._dirty)
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.UpdateRequest);
	    };
	    /**
	     * Update the layout position and size of the widgets.
	     *
	     * The parent offset dimensions should be `-1` if unknown.
	     */
	    SplitLayout.prototype._update = function (offsetWidth, offsetHeight) {
	        // Clear the dirty flag to indicate the update occurred.
	        this._dirty = false;
	        // Bail early if there are no widgets to layout.
	        var widgets = this.widgets;
	        if (widgets.length === 0) {
	            return;
	        }
	        // Measure the parent if the offset dimensions are unknown.
	        if (offsetWidth < 0) {
	            offsetWidth = this.parent.node.offsetWidth;
	        }
	        if (offsetHeight < 0) {
	            offsetHeight = this.parent.node.offsetHeight;
	        }
	        // Ensure the parent box sizing data is computed.
	        var box = this._box || (this._box = sizing_1.boxSizing(this.parent.node));
	        // Compute the actual layout bounds adjusted for border and padding.
	        var top = box.paddingTop;
	        var left = box.paddingLeft;
	        var width = offsetWidth - box.horizontalSum;
	        var height = offsetHeight - box.verticalSum;
	        // Compute the adjusted layout space.
	        var space;
	        var horz = this._orientation === 'horizontal';
	        if (horz) {
	            space = Math.max(0, width - this._fixed);
	        }
	        else {
	            space = Math.max(0, height - this._fixed);
	        }
	        // Scale the size hints if they are normalized.
	        if (this._hasNormedSizes) {
	            iteration_1.each(this._sizers, function (sizer) { sizer.sizeHint *= space; });
	            this._hasNormedSizes = false;
	        }
	        // Distribute the layout space to the box sizers.
	        boxengine_1.boxCalc(this._sizers, space);
	        // Layout the widgets using the computed box sizes.
	        var spacing = this._spacing;
	        for (var i = 0, n = widgets.length; i < n; ++i) {
	            var widget = widgets.at(i);
	            if (widget.isHidden) {
	                continue;
	            }
	            var size = this._sizers.at(i).size;
	            var hstyle = this._handles.at(i).style;
	            if (horz) {
	                widget_1.Widget.setGeometry(widget, left, top, size, height);
	                left += size;
	                hstyle.top = top + "px";
	                hstyle.left = left + "px";
	                hstyle.width = spacing + "px";
	                hstyle.height = height + "px";
	                left += spacing;
	            }
	            else {
	                widget_1.Widget.setGeometry(widget, left, top, width, size);
	                top += size;
	                hstyle.top = top + "px";
	                hstyle.left = left + "px";
	                hstyle.width = width + "px";
	                hstyle.height = spacing + "px";
	                top += spacing;
	            }
	        }
	    };
	    return SplitLayout;
	}(panel_1.PanelLayout));
	exports.SplitLayout = SplitLayout;
	/**
	 * The namespace for the `SplitLayout` class statics.
	 */
	var SplitLayout;
	(function (SplitLayout) {
	    /**
	     * Get the split layout stretch factor for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The split layout stretch factor for the widget.
	     */
	    function getStretch(widget) {
	        return Private.stretchProperty.get(widget);
	    }
	    SplitLayout.getStretch = getStretch;
	    /**
	     * Set the split layout stretch factor for the given widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @param value - The value for the stretch factor.
	     */
	    function setStretch(widget, value) {
	        Private.stretchProperty.set(widget, value);
	    }
	    SplitLayout.setStretch = setStretch;
	})(SplitLayout = exports.SplitLayout || (exports.SplitLayout = {}));
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * The property descriptor for a widget stretch factor.
	     */
	    Private.stretchProperty = new properties_1.AttachedProperty({
	        name: 'stretch',
	        value: 0,
	        coerce: function (owner, value) { return Math.max(0, Math.floor(value)); },
	        changed: onChildPropertyChanged
	    });
	    /**
	     * Create a split layout for the given panel options.
	     */
	    function createLayout(options) {
	        return options.layout || new SplitLayout({
	            renderer: options.renderer || SplitPanel.defaultRenderer,
	            orientation: options.orientation,
	            spacing: options.spacing
	        });
	    }
	    Private.createLayout = createLayout;
	    /**
	     * Create a new box sizer with the given size hint.
	     */
	    function createSizer(size) {
	        var sizer = new boxengine_1.BoxSizer();
	        sizer.sizeHint = Math.floor(size);
	        return sizer;
	    }
	    Private.createSizer = createSizer;
	    /**
	     * Create a new split handle node using the given renderer.
	     */
	    function createHandle(renderer) {
	        var node = renderer.createHandleNode();
	        node.style.position = 'absolute';
	        return node;
	    }
	    Private.createHandle = createHandle;
	    /**
	     * Toggle the CSS orientation class for the given widget.
	     */
	    function toggleOrientation(widget, orient) {
	        widget.toggleClass(HORIZONTAL_CLASS, orient === 'horizontal');
	        widget.toggleClass(VERTICAL_CLASS, orient === 'vertical');
	    }
	    Private.toggleOrientation = toggleOrientation;
	    /**
	     * Clamp a spacing value to an integer >= 0.
	     */
	    function clampSpacing(value) {
	        return Math.max(0, Math.floor(value));
	    }
	    Private.clampSpacing = clampSpacing;
	    /**
	     * Compute the average size of a vector of box sizers.
	     */
	    function averageSize(sizers) {
	        return iteration_1.reduce(sizers, function (v, s) { return v + s.size; }, 0) / sizers.length || 0;
	    }
	    Private.averageSize = averageSize;
	    /**
	     * Normalize an array of values.
	     */
	    function normalize(values) {
	        var n = values.length;
	        if (n === 0)
	            return [];
	        var sum = values.reduce(function (a, b) { return a + Math.abs(b); }, 0);
	        return sum === 0 ? values.map(function (v) { return 1 / n; }) : values.map(function (v) { return v / sum; });
	    }
	    Private.normalize = normalize;
	    /**
	     * The change handler for the attached child properties.
	     */
	    function onChildPropertyChanged(child) {
	        var parent = child.parent;
	        var layout = parent && parent.layout;
	        if (layout instanceof SplitLayout)
	            parent.fit();
	    }
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/splitpanel.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/stackedpanel.js **/
jupyter.define('phosphor@0.7.0/lib/ui/stackedpanel.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var messaging_1 = __jupyter_require__('phosphor@0.7.0/lib/core/messaging.js');
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	var platform_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/platform.js');
	var sizing_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/sizing.js');
	var panel_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to StackedPanel instances.
	 */
	var STACKED_PANEL_CLASS = 'p-StackedPanel';
	/**
	 * The class name added to a StackedPanel child.
	 */
	var CHILD_CLASS = 'p-StackedPanel-child';
	/**
	 * A panel where visible widgets are stacked atop one another.
	 *
	 * #### Notes
	 * This class provides a convenience wrapper around a [[StackedLayout]].
	 */
	var StackedPanel = (function (_super) {
	    __extends(StackedPanel, _super);
	    /**
	     * Construct a new stacked panel.
	     *
	     * @param options - The options for initializing the panel.
	     */
	    function StackedPanel(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this, { layout: Private.createLayout(options) });
	        this.addClass(STACKED_PANEL_CLASS);
	    }
	    /**
	     * A message handler invoked on a `'child-added'` message.
	     */
	    StackedPanel.prototype.onChildAdded = function (msg) {
	        msg.child.addClass(CHILD_CLASS);
	    };
	    /**
	     * A message handler invoked on a `'child-removed'` message.
	     */
	    StackedPanel.prototype.onChildRemoved = function (msg) {
	        msg.child.removeClass(CHILD_CLASS);
	        this.widgetRemoved.emit(msg.child);
	    };
	    return StackedPanel;
	}(panel_1.Panel));
	exports.StackedPanel = StackedPanel;
	// Define the signals for the `StackedPanel` class.
	signaling_1.defineSignal(StackedPanel.prototype, 'widgetRemoved');
	/**
	 * A layout where visible widgets are stacked atop one another.
	 *
	 * #### Notes
	 * The Z-order of the visible widgets follows their layout order.
	 */
	var StackedLayout = (function (_super) {
	    __extends(StackedLayout, _super);
	    function StackedLayout() {
	        _super.apply(this, arguments);
	        this._dirty = false;
	        this._box = null;
	    }
	    /**
	     * Attach a widget to the parent's DOM node.
	     *
	     * @param index - The current index of the widget in the layout.
	     *
	     * @param widget - The widget to attach to the parent.
	     *
	     * #### Notes
	     * This is a reimplementation of the superclass method.
	     */
	    StackedLayout.prototype.attachWidget = function (index, widget) {
	        // Prepare the layout geometry for the widget.
	        widget_1.Widget.prepareGeometry(widget);
	        // Add the widget's node to the parent.
	        this.parent.node.appendChild(widget.node);
	        // Send an `'after-attach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.AfterAttach);
	        // Post a fit request for the parent widget.
	        this.parent.fit();
	    };
	    /**
	     * Move a widget in the parent's DOM node.
	     *
	     * @param fromIndex - The previous index of the widget in the layout.
	     *
	     * @param toIndex - The current index of the widget in the layout.
	     *
	     * @param widget - The widget to move in the parent.
	     *
	     * #### Notes
	     * This is a reimplementation of the superclass method.
	     */
	    StackedLayout.prototype.moveWidget = function (fromIndex, toIndex, widget) {
	        // Post an update request for the parent widget.
	        this.parent.update();
	    };
	    /**
	     * Detach a widget from the parent's DOM node.
	     *
	     * @param index - The previous index of the widget in the layout.
	     *
	     * @param widget - The widget to detach from the parent.
	     *
	     * #### Notes
	     * This is a reimplementation of the superclass method.
	     */
	    StackedLayout.prototype.detachWidget = function (index, widget) {
	        // Send a `'before-detach'` message if the parent is attached.
	        if (this.parent.isAttached)
	            messaging_1.sendMessage(widget, widget_1.WidgetMessage.BeforeDetach);
	        // Remove the widget's node from the parent.
	        this.parent.node.removeChild(widget.node);
	        // Reset the layout geometry for the widget.
	        widget_1.Widget.resetGeometry(widget);
	        // Reset the z-index for the widget.
	        widget.node.style.zIndex = '';
	        // Post a fit request for the parent widget.
	        this.parent.fit();
	    };
	    /**
	     * A message handler invoked on an `'after-show'` message.
	     */
	    StackedLayout.prototype.onAfterShow = function (msg) {
	        _super.prototype.onAfterShow.call(this, msg);
	        this.parent.update();
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    StackedLayout.prototype.onAfterAttach = function (msg) {
	        _super.prototype.onAfterAttach.call(this, msg);
	        this.parent.fit();
	    };
	    /**
	     * A message handler invoked on a `'child-shown'` message.
	     */
	    StackedLayout.prototype.onChildShown = function (msg) {
	        if (platform_1.IS_IE || platform_1.IS_EDGE) {
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.FitRequest);
	        }
	        else {
	            this.parent.fit();
	        }
	    };
	    /**
	     * A message handler invoked on a `'child-hidden'` message.
	     */
	    StackedLayout.prototype.onChildHidden = function (msg) {
	        if (platform_1.IS_IE || platform_1.IS_EDGE) {
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.FitRequest);
	        }
	        else {
	            this.parent.fit();
	        }
	    };
	    /**
	     * A message handler invoked on a `'resize'` message.
	     */
	    StackedLayout.prototype.onResize = function (msg) {
	        if (this.parent.isVisible) {
	            this._update(msg.width, msg.height);
	        }
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    StackedLayout.prototype.onUpdateRequest = function (msg) {
	        if (this.parent.isVisible) {
	            this._update(-1, -1);
	        }
	    };
	    /**
	     * A message handler invoked on a `'fit-request'` message.
	     */
	    StackedLayout.prototype.onFitRequest = function (msg) {
	        if (this.parent.isAttached) {
	            this._fit();
	        }
	    };
	    /**
	     * Fit the layout to the total size required by the widgets.
	     */
	    StackedLayout.prototype._fit = function () {
	        // Setup the initial size limits.
	        var minW = 0;
	        var minH = 0;
	        var maxW = Infinity;
	        var maxH = Infinity;
	        // Update the computed size limits.
	        var widgets = this.widgets;
	        for (var i = 0, n = widgets.length; i < n; ++i) {
	            var widget = widgets.at(i);
	            if (widget.isHidden) {
	                continue;
	            }
	            var limits = sizing_1.sizeLimits(widget.node);
	            minW = Math.max(minW, limits.minWidth);
	            minH = Math.max(minH, limits.minHeight);
	            maxW = Math.min(maxW, limits.maxWidth);
	            maxH = Math.min(maxH, limits.maxHeight);
	        }
	        // Ensure max limits >= min limits.
	        maxW = Math.max(minW, maxW);
	        maxH = Math.max(minH, maxH);
	        // Update the box sizing and add it to the size constraints.
	        var box = this._box = sizing_1.boxSizing(this.parent.node);
	        minW += box.horizontalSum;
	        minH += box.verticalSum;
	        maxW += box.horizontalSum;
	        maxH += box.verticalSum;
	        // Update the parent's size constraints.
	        var style = this.parent.node.style;
	        style.minWidth = minW + "px";
	        style.minHeight = minH + "px";
	        style.maxWidth = maxW === Infinity ? 'none' : maxW + "px";
	        style.maxHeight = maxH === Infinity ? 'none' : maxH + "px";
	        // Set the dirty flag to ensure only a single update occurs.
	        this._dirty = true;
	        // Notify the ancestor that it should fit immediately. This may
	        // cause a resize of the parent, fulfilling the required update.
	        var ancestor = this.parent.parent;
	        if (ancestor)
	            messaging_1.sendMessage(ancestor, widget_1.WidgetMessage.FitRequest);
	        // If the dirty flag is still set, the parent was not resized.
	        // Trigger the required update on the parent widget immediately.
	        if (this._dirty)
	            messaging_1.sendMessage(this.parent, widget_1.WidgetMessage.UpdateRequest);
	    };
	    /**
	     * Update the layout position and size of the widgets.
	     *
	     * The parent offset dimensions should be `-1` if unknown.
	     */
	    StackedLayout.prototype._update = function (offsetWidth, offsetHeight) {
	        // Clear the dirty flag to indicate the update occurred.
	        this._dirty = false;
	        // Bail early if there are no widgets to layout.
	        var widgets = this.widgets;
	        if (widgets.length === 0) {
	            return;
	        }
	        // Measure the parent if the offset dimensions are unknown.
	        if (offsetWidth < 0) {
	            offsetWidth = this.parent.node.offsetWidth;
	        }
	        if (offsetHeight < 0) {
	            offsetHeight = this.parent.node.offsetHeight;
	        }
	        // Ensure the parent box sizing data is computed.
	        var box = this._box || (this._box = sizing_1.boxSizing(this.parent.node));
	        // Compute the actual layout bounds adjusted for border and padding.
	        var top = box.paddingTop;
	        var left = box.paddingLeft;
	        var width = offsetWidth - box.horizontalSum;
	        var height = offsetHeight - box.verticalSum;
	        // Update the widget stacking order and layout geometry.
	        for (var i = 0, n = widgets.length; i < n; ++i) {
	            var widget = widgets.at(i);
	            if (widget.isHidden) {
	                continue;
	            }
	            widget.node.style.zIndex = "" + i;
	            widget_1.Widget.setGeometry(widget, left, top, width, height);
	        }
	    };
	    return StackedLayout;
	}(panel_1.PanelLayout));
	exports.StackedLayout = StackedLayout;
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create a stacked layout for the given panel options.
	     */
	    function createLayout(options) {
	        return options.layout || new StackedLayout();
	    }
	    Private.createLayout = createLayout;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/stackedpanel.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/application/loader.js **/
jupyter.define('jupyterlab@0.15.1/lib/application/loader.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var semver_1 = __jupyter_require__('semver@^5.3.0/semver.js');
	/**
	 * A module loader using semver for dynamic resolution of requires.
	 *
	 * It is meant to be used in conjunction with the JupyterLabPlugin
	 * for WebPack from `@jupyterlab/extension-builder`.
	 */
	var ModuleLoader = (function () {
	    /**
	     * Construct a new module loader.
	     */
	    function ModuleLoader() {
	        this._registered = Object.create(null);
	        this._parsed = Object.create(null);
	        this._modules = Object.create(null);
	        this._bundles = Object.create(null);
	        this._matches = Object.create(null);
	        // Provide the `require.ensure` function used for code
	        // splitting in the WebPack bundles.
	        // https://webpack.github.io/docs/code-splitting.html
	        this._boundRequire = this.require.bind(this);
	        this._boundRequire.ensure = this.ensureBundle.bind(this);
	    }
	    /**
	     * Define a module that can be synchronously required.
	     *
	     * @param path - The version-mangled fully qualified path of the module.
	     *   For example, "foo@1.0.1/lib/bar/baz.js".
	     *
	     * @param callback - The callback function for invoking the module.
	     *
	     * #### Notes
	     * This is a no-op if the path is already registered.
	     */
	    ModuleLoader.prototype.define = function (path, callback) {
	        if (!(path in this._registered)) {
	            this._registered[path] = callback;
	        }
	    };
	    /**
	     * Synchronously require a module that has already been loaded.
	     *
	     * @param path - The semver-mangled fully qualified path of the module.
	     *   For example, "foo@^1.1.0/lib/bar/baz.js".
	     *
	     * @returns The exports of the requested module, if registered.  The module
	     *   selected is the registered module that maximally satisfies the semver
	     *   range of the request.
	     *
	     * #### Notes
	     * Will throw an error if the required path cannot be satisfied.
	     */
	    ModuleLoader.prototype.require = function (path) {
	        // Check if module is in cache.
	        var id = this._findMatch(path);
	        if (!id) {
	            throw new Error("No matching module found for: \"" + path + "\"");
	        }
	        var installed = this._modules;
	        if (installed[id]) {
	            return installed[id].exports;
	        }
	        // Create a new module (and put it into the cache).
	        var mod = installed[id] = {
	            exports: {},
	            require: this._boundRequire,
	            id: id,
	            loaded: false
	        };
	        // Execute the module function.
	        var callback = this._registered[id];
	        callback.call(mod.exports, mod, mod.exports, this._boundRequire);
	        // Flag the module as loaded.
	        mod.loaded = true;
	        // Return the exports of the module.
	        return mod.exports;
	    };
	    /**
	     * Ensure a bundle is loaded on the page.
	     *
	     * @param path - The public path of the bundle (e.g. "lab/jupyter.bundle.js").
	     *
	     * @param callback - The callback invoked when the bundle has loaded.
	     *
	     * @returns A promise that resolves when the bundle is loaded.
	     */
	    ModuleLoader.prototype.ensureBundle = function (path, callback) {
	        var bundle = this._getBundle(path);
	        if (bundle.loaded) {
	            if (callback) {
	                callback.call(null, this._boundRequire);
	            }
	            return Promise.resolve(void 0);
	        }
	        if (callback) {
	            bundle.callbacks.push(callback);
	        }
	        return bundle.promise;
	    };
	    /**
	     * Extract the entry point plugins of an extension.
	     *
	     * @param data - The loaded entry point module.
	     *
	     * @returns An array of validated plugins.
	     *
	     * #### Notes
	     * The plugin(s) are extracted and validated before being returned.
	     */
	    ModuleLoader.prototype.extractPlugins = function (data) {
	        // We use the default export from es6 modules.
	        if (data.__esModule) {
	            data = data.default;
	        }
	        if (!Array.isArray(data)) {
	            data = [data];
	        }
	        if (!data.length) {
	            throw new Error("No plugins found");
	        }
	        for (var i = 0; i < data.length; i++) {
	            var plugin = data[i];
	            if (!plugin.hasOwnProperty('id')) {
	                throw new Error("Missing id for plugin " + i);
	            }
	            if (typeof (plugin['activate']) !== 'function') {
	                var id = plugin.id;
	                throw Error("Missing activate function in '" + id + "'");
	            }
	        }
	        return data;
	    };
	    /**
	     * Find a module path matching a given module request.
	     *
	     * @param path - The semver-mangled fully qualified path to the module.
	     *   For example, "foo@^1.1.0/lib/bar/baz.js".
	     *
	     * @returns The matching defined module path, if registered.  A match is
	     *   the registered path that maximally satisfies the semver range of the
	     *   request.
	     *
	     * #### Notes
	     * If the path has loaders, and thus multiple packages and modules delimited
	     * by '!', then the versions are matched in reverse order.
	     */
	    ModuleLoader.prototype._findMatch = function (path) {
	        var _this = this;
	        // Use the cached match if available.
	        var cache = this._matches;
	        if (cache[path]) {
	            return cache[path];
	        }
	        var modules = Object.keys(this._registered);
	        var sources = path.split('!').map(function (value) { return _this._parsePath(value); });
	        if (sources.some(function (elem) { return !elem; })) {
	            // check to see if any element of sources is falsey
	            throw Error('Invalid module path ' + path);
	        }
	        var matches = [];
	        var versions = [];
	        var _loop_1 = function(mod) {
	            var targets = mod.split('!').map(function (value) { return _this._parsePath(value); });
	            if (targets.some(function (e) { return !e; })) {
	                return "continue";
	            }
	            if (sources.length === targets.length && sources.every(function (source, i) {
	                return (source.package === targets[i].package
	                    && source.module === targets[i].module
	                    && semver_1.satisfies(targets[i].version, source.version));
	            })) {
	                matches.push(mod);
	                versions.push(targets.map(function (t) { return t.version; }));
	            }
	        };
	        for (var _i = 0, modules_1 = modules; _i < modules_1.length; _i++) {
	            var mod = modules_1[_i];
	            _loop_1(mod);
	        }
	        if (!matches.length) {
	            throw Error("No module found matching: " + path);
	        }
	        // If we have a chain of loaders, we want
	        // to filter for best versions in reverse order.
	        var _loop_2 = function(part) {
	            var best = semver_1.maxSatisfying(versions.map(function (v) { return v[part]; }), sources[part].version);
	            if (!best) {
	                throw new Error("No module found satisfying " + path);
	            }
	            matches = matches.filter(function (mod, index) { return versions[index][part] === best; });
	            versions = versions.filter(function (v) { return v[part] === best; });
	        };
	        for (var part = versions[0].length - 1; matches.length > 1 && part >= 0; part--) {
	            _loop_2(part);
	        }
	        cache[path] = matches[0];
	        return matches[0];
	    };
	    /**
	     * Get or create a bundle record for a path.
	     */
	    ModuleLoader.prototype._getBundle = function (path) {
	        var _this = this;
	        var bundle = this._bundles[path];
	        if (bundle) {
	            return bundle;
	        }
	        // Start bundle loading.
	        var head = document.getElementsByTagName('head')[0];
	        var script = document.createElement('script');
	        script.type = 'text/javascript';
	        script.charset = 'utf-8';
	        script.async = true;
	        var promise = new Promise(function (resolve, reject) {
	            script.onload = function () {
	                while (bundle.callbacks.length) {
	                    bundle.callbacks.shift().call(null, _this._boundRequire);
	                }
	                bundle.loaded = true;
	                resolve(void 0);
	            };
	            script.onerror = function (err) {
	                reject(err);
	            };
	        });
	        head.appendChild(script);
	        script.src = path;
	        bundle = this._bundles[path] = {
	            loaded: false,
	            callbacks: [],
	            promise: promise
	        };
	        return bundle;
	    };
	    /**
	     * Parse a version-mangled module path.
	     *
	     * @param path - The module path (e.g. "foo@^1.1.0/lib/bar/baz.js").
	     *
	     * @returns A parsed object describing the module path.
	     */
	    ModuleLoader.prototype._parsePath = function (path) {
	        var cache = this._parsed;
	        if (cache[path]) {
	            return cache[path];
	        }
	        var match = path.match(/(^(?:@[^/]+\/)??[^/@]+?)@([^/]+?)(\/.*)?$/);
	        if (!match) {
	            cache[path] = null;
	        }
	        else {
	            cache[path] = {
	                package: match[1],
	                version: match[2],
	                module: match[3]
	            };
	        }
	        return cache[path];
	    };
	    return ModuleLoader;
	}());
	exports.ModuleLoader = ModuleLoader;
	//# sourceMappingURL=loader.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/application/loader.js **/


/** START DEFINE BLOCK for semver@5.3.0/semver.js **/
jupyter.define('semver@5.3.0/semver.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(process) {exports = module.exports = SemVer;
	
	// The debug function is excluded entirely from the minified version.
	/* nomin */ var debug;
	/* nomin */ if (typeof process === 'object' &&
	    /* nomin */ ({"GIT_DESCRIPTION":"v0.15.1"}) &&
	    /* nomin */ ({"GIT_DESCRIPTION":"v0.15.1"}).NODE_DEBUG &&
	    /* nomin */ /\bsemver\b/i.test(({"GIT_DESCRIPTION":"v0.15.1"}).NODE_DEBUG))
	  /* nomin */ debug = function() {
	    /* nomin */ var args = Array.prototype.slice.call(arguments, 0);
	    /* nomin */ args.unshift('SEMVER');
	    /* nomin */ console.log.apply(console, args);
	    /* nomin */ };
	/* nomin */ else
	  /* nomin */ debug = function() {};
	
	// Note: this is the semver.org version of the spec that it implements
	// Not necessarily the package version of this code.
	exports.SEMVER_SPEC_VERSION = '2.0.0';
	
	var MAX_LENGTH = 256;
	var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;
	
	// The actual regexps go on exports.re
	var re = exports.re = [];
	var src = exports.src = [];
	var R = 0;
	
	// The following Regular Expressions can be used for tokenizing,
	// validating, and parsing SemVer version strings.
	
	// ## Numeric Identifier
	// A single `0`, or a non-zero digit followed by zero or more digits.
	
	var NUMERICIDENTIFIER = R++;
	src[NUMERICIDENTIFIER] = '0|[1-9]\\d*';
	var NUMERICIDENTIFIERLOOSE = R++;
	src[NUMERICIDENTIFIERLOOSE] = '[0-9]+';
	
	
	// ## Non-numeric Identifier
	// Zero or more digits, followed by a letter or hyphen, and then zero or
	// more letters, digits, or hyphens.
	
	var NONNUMERICIDENTIFIER = R++;
	src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*';
	
	
	// ## Main Version
	// Three dot-separated numeric identifiers.
	
	var MAINVERSION = R++;
	src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' +
	                   '(' + src[NUMERICIDENTIFIER] + ')\\.' +
	                   '(' + src[NUMERICIDENTIFIER] + ')';
	
	var MAINVERSIONLOOSE = R++;
	src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
	                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
	                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')';
	
	// ## Pre-release Version Identifier
	// A numeric identifier, or a non-numeric identifier.
	
	var PRERELEASEIDENTIFIER = R++;
	src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +
	                            '|' + src[NONNUMERICIDENTIFIER] + ')';
	
	var PRERELEASEIDENTIFIERLOOSE = R++;
	src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +
	                                 '|' + src[NONNUMERICIDENTIFIER] + ')';
	
	
	// ## Pre-release Version
	// Hyphen, followed by one or more dot-separated pre-release version
	// identifiers.
	
	var PRERELEASE = R++;
	src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +
	                  '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))';
	
	var PRERELEASELOOSE = R++;
	src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +
	                       '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))';
	
	// ## Build Metadata Identifier
	// Any combination of digits, letters, or hyphens.
	
	var BUILDIDENTIFIER = R++;
	src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+';
	
	// ## Build Metadata
	// Plus sign, followed by one or more period-separated build metadata
	// identifiers.
	
	var BUILD = R++;
	src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] +
	             '(?:\\.' + src[BUILDIDENTIFIER] + ')*))';
	
	
	// ## Full Version String
	// A main version, followed optionally by a pre-release version and
	// build metadata.
	
	// Note that the only major, minor, patch, and pre-release sections of
	// the version string are capturing groups.  The build metadata is not a
	// capturing group, because it should not ever be used in version
	// comparison.
	
	var FULL = R++;
	var FULLPLAIN = 'v?' + src[MAINVERSION] +
	                src[PRERELEASE] + '?' +
	                src[BUILD] + '?';
	
	src[FULL] = '^' + FULLPLAIN + '$';
	
	// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
	// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
	// common in the npm registry.
	var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] +
	                 src[PRERELEASELOOSE] + '?' +
	                 src[BUILD] + '?';
	
	var LOOSE = R++;
	src[LOOSE] = '^' + LOOSEPLAIN + '$';
	
	var GTLT = R++;
	src[GTLT] = '((?:<|>)?=?)';
	
	// Something like "2.*" or "1.2.x".
	// Note that "x.x" is a valid xRange identifer, meaning "any version"
	// Only the first item is strictly required.
	var XRANGEIDENTIFIERLOOSE = R++;
	src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*';
	var XRANGEIDENTIFIER = R++;
	src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*';
	
	var XRANGEPLAIN = R++;
	src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' +
	                   '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
	                   '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
	                   '(?:' + src[PRERELEASE] + ')?' +
	                   src[BUILD] + '?' +
	                   ')?)?';
	
	var XRANGEPLAINLOOSE = R++;
	src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
	                        '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
	                        '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
	                        '(?:' + src[PRERELEASELOOSE] + ')?' +
	                        src[BUILD] + '?' +
	                        ')?)?';
	
	var XRANGE = R++;
	src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$';
	var XRANGELOOSE = R++;
	src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$';
	
	// Tilde ranges.
	// Meaning is "reasonably at or greater than"
	var LONETILDE = R++;
	src[LONETILDE] = '(?:~>?)';
	
	var TILDETRIM = R++;
	src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+';
	re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g');
	var tildeTrimReplace = '$1~';
	
	var TILDE = R++;
	src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$';
	var TILDELOOSE = R++;
	src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$';
	
	// Caret ranges.
	// Meaning is "at least and backwards compatible with"
	var LONECARET = R++;
	src[LONECARET] = '(?:\\^)';
	
	var CARETTRIM = R++;
	src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+';
	re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g');
	var caretTrimReplace = '$1^';
	
	var CARET = R++;
	src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$';
	var CARETLOOSE = R++;
	src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$';
	
	// A simple gt/lt/eq thing, or just "" to indicate "any version"
	var COMPARATORLOOSE = R++;
	src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$';
	var COMPARATOR = R++;
	src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$';
	
	
	// An expression to strip any whitespace between the gtlt and the thing
	// it modifies, so that `> 1.2.3` ==> `>1.2.3`
	var COMPARATORTRIM = R++;
	src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] +
	                      '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')';
	
	// this one has to use the /g flag
	re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g');
	var comparatorTrimReplace = '$1$2$3';
	
	
	// Something like `1.2.3 - 1.2.4`
	// Note that these all use the loose form, because they'll be
	// checked against either the strict or loose comparator form
	// later.
	var HYPHENRANGE = R++;
	src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' +
	                   '\\s+-\\s+' +
	                   '(' + src[XRANGEPLAIN] + ')' +
	                   '\\s*$';
	
	var HYPHENRANGELOOSE = R++;
	src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' +
	                        '\\s+-\\s+' +
	                        '(' + src[XRANGEPLAINLOOSE] + ')' +
	                        '\\s*$';
	
	// Star ranges basically just allow anything at all.
	var STAR = R++;
	src[STAR] = '(<|>)?=?\\s*\\*';
	
	// Compile to actual regexp objects.
	// All are flag-free, unless they were created above with a flag.
	for (var i = 0; i < R; i++) {
	  debug(i, src[i]);
	  if (!re[i])
	    re[i] = new RegExp(src[i]);
	}
	
	exports.parse = parse;
	function parse(version, loose) {
	  if (version instanceof SemVer)
	    return version;
	
	  if (typeof version !== 'string')
	    return null;
	
	  if (version.length > MAX_LENGTH)
	    return null;
	
	  var r = loose ? re[LOOSE] : re[FULL];
	  if (!r.test(version))
	    return null;
	
	  try {
	    return new SemVer(version, loose);
	  } catch (er) {
	    return null;
	  }
	}
	
	exports.valid = valid;
	function valid(version, loose) {
	  var v = parse(version, loose);
	  return v ? v.version : null;
	}
	
	
	exports.clean = clean;
	function clean(version, loose) {
	  var s = parse(version.trim().replace(/^[=v]+/, ''), loose);
	  return s ? s.version : null;
	}
	
	exports.SemVer = SemVer;
	
	function SemVer(version, loose) {
	  if (version instanceof SemVer) {
	    if (version.loose === loose)
	      return version;
	    else
	      version = version.version;
	  } else if (typeof version !== 'string') {
	    throw new TypeError('Invalid Version: ' + version);
	  }
	
	  if (version.length > MAX_LENGTH)
	    throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters')
	
	  if (!(this instanceof SemVer))
	    return new SemVer(version, loose);
	
	  debug('SemVer', version, loose);
	  this.loose = loose;
	  var m = version.trim().match(loose ? re[LOOSE] : re[FULL]);
	
	  if (!m)
	    throw new TypeError('Invalid Version: ' + version);
	
	  this.raw = version;
	
	  // these are actually numbers
	  this.major = +m[1];
	  this.minor = +m[2];
	  this.patch = +m[3];
	
	  if (this.major > MAX_SAFE_INTEGER || this.major < 0)
	    throw new TypeError('Invalid major version')
	
	  if (this.minor > MAX_SAFE_INTEGER || this.minor < 0)
	    throw new TypeError('Invalid minor version')
	
	  if (this.patch > MAX_SAFE_INTEGER || this.patch < 0)
	    throw new TypeError('Invalid patch version')
	
	  // numberify any prerelease numeric ids
	  if (!m[4])
	    this.prerelease = [];
	  else
	    this.prerelease = m[4].split('.').map(function(id) {
	      if (/^[0-9]+$/.test(id)) {
	        var num = +id;
	        if (num >= 0 && num < MAX_SAFE_INTEGER)
	          return num;
	      }
	      return id;
	    });
	
	  this.build = m[5] ? m[5].split('.') : [];
	  this.format();
	}
	
	SemVer.prototype.format = function() {
	  this.version = this.major + '.' + this.minor + '.' + this.patch;
	  if (this.prerelease.length)
	    this.version += '-' + this.prerelease.join('.');
	  return this.version;
	};
	
	SemVer.prototype.toString = function() {
	  return this.version;
	};
	
	SemVer.prototype.compare = function(other) {
	  debug('SemVer.compare', this.version, this.loose, other);
	  if (!(other instanceof SemVer))
	    other = new SemVer(other, this.loose);
	
	  return this.compareMain(other) || this.comparePre(other);
	};
	
	SemVer.prototype.compareMain = function(other) {
	  if (!(other instanceof SemVer))
	    other = new SemVer(other, this.loose);
	
	  return compareIdentifiers(this.major, other.major) ||
	         compareIdentifiers(this.minor, other.minor) ||
	         compareIdentifiers(this.patch, other.patch);
	};
	
	SemVer.prototype.comparePre = function(other) {
	  if (!(other instanceof SemVer))
	    other = new SemVer(other, this.loose);
	
	  // NOT having a prerelease is > having one
	  if (this.prerelease.length && !other.prerelease.length)
	    return -1;
	  else if (!this.prerelease.length && other.prerelease.length)
	    return 1;
	  else if (!this.prerelease.length && !other.prerelease.length)
	    return 0;
	
	  var i = 0;
	  do {
	    var a = this.prerelease[i];
	    var b = other.prerelease[i];
	    debug('prerelease compare', i, a, b);
	    if (a === undefined && b === undefined)
	      return 0;
	    else if (b === undefined)
	      return 1;
	    else if (a === undefined)
	      return -1;
	    else if (a === b)
	      continue;
	    else
	      return compareIdentifiers(a, b);
	  } while (++i);
	};
	
	// preminor will bump the version up to the next minor release, and immediately
	// down to pre-release. premajor and prepatch work the same way.
	SemVer.prototype.inc = function(release, identifier) {
	  switch (release) {
	    case 'premajor':
	      this.prerelease.length = 0;
	      this.patch = 0;
	      this.minor = 0;
	      this.major++;
	      this.inc('pre', identifier);
	      break;
	    case 'preminor':
	      this.prerelease.length = 0;
	      this.patch = 0;
	      this.minor++;
	      this.inc('pre', identifier);
	      break;
	    case 'prepatch':
	      // If this is already a prerelease, it will bump to the next version
	      // drop any prereleases that might already exist, since they are not
	      // relevant at this point.
	      this.prerelease.length = 0;
	      this.inc('patch', identifier);
	      this.inc('pre', identifier);
	      break;
	    // If the input is a non-prerelease version, this acts the same as
	    // prepatch.
	    case 'prerelease':
	      if (this.prerelease.length === 0)
	        this.inc('patch', identifier);
	      this.inc('pre', identifier);
	      break;
	
	    case 'major':
	      // If this is a pre-major version, bump up to the same major version.
	      // Otherwise increment major.
	      // 1.0.0-5 bumps to 1.0.0
	      // 1.1.0 bumps to 2.0.0
	      if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0)
	        this.major++;
	      this.minor = 0;
	      this.patch = 0;
	      this.prerelease = [];
	      break;
	    case 'minor':
	      // If this is a pre-minor version, bump up to the same minor version.
	      // Otherwise increment minor.
	      // 1.2.0-5 bumps to 1.2.0
	      // 1.2.1 bumps to 1.3.0
	      if (this.patch !== 0 || this.prerelease.length === 0)
	        this.minor++;
	      this.patch = 0;
	      this.prerelease = [];
	      break;
	    case 'patch':
	      // If this is not a pre-release version, it will increment the patch.
	      // If it is a pre-release it will bump up to the same patch version.
	      // 1.2.0-5 patches to 1.2.0
	      // 1.2.0 patches to 1.2.1
	      if (this.prerelease.length === 0)
	        this.patch++;
	      this.prerelease = [];
	      break;
	    // This probably shouldn't be used publicly.
	    // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
	    case 'pre':
	      if (this.prerelease.length === 0)
	        this.prerelease = [0];
	      else {
	        var i = this.prerelease.length;
	        while (--i >= 0) {
	          if (typeof this.prerelease[i] === 'number') {
	            this.prerelease[i]++;
	            i = -2;
	          }
	        }
	        if (i === -1) // didn't increment anything
	          this.prerelease.push(0);
	      }
	      if (identifier) {
	        // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
	        // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
	        if (this.prerelease[0] === identifier) {
	          if (isNaN(this.prerelease[1]))
	            this.prerelease = [identifier, 0];
	        } else
	          this.prerelease = [identifier, 0];
	      }
	      break;
	
	    default:
	      throw new Error('invalid increment argument: ' + release);
	  }
	  this.format();
	  this.raw = this.version;
	  return this;
	};
	
	exports.inc = inc;
	function inc(version, release, loose, identifier) {
	  if (typeof(loose) === 'string') {
	    identifier = loose;
	    loose = undefined;
	  }
	
	  try {
	    return new SemVer(version, loose).inc(release, identifier).version;
	  } catch (er) {
	    return null;
	  }
	}
	
	exports.diff = diff;
	function diff(version1, version2) {
	  if (eq(version1, version2)) {
	    return null;
	  } else {
	    var v1 = parse(version1);
	    var v2 = parse(version2);
	    if (v1.prerelease.length || v2.prerelease.length) {
	      for (var key in v1) {
	        if (key === 'major' || key === 'minor' || key === 'patch') {
	          if (v1[key] !== v2[key]) {
	            return 'pre'+key;
	          }
	        }
	      }
	      return 'prerelease';
	    }
	    for (var key in v1) {
	      if (key === 'major' || key === 'minor' || key === 'patch') {
	        if (v1[key] !== v2[key]) {
	          return key;
	        }
	      }
	    }
	  }
	}
	
	exports.compareIdentifiers = compareIdentifiers;
	
	var numeric = /^[0-9]+$/;
	function compareIdentifiers(a, b) {
	  var anum = numeric.test(a);
	  var bnum = numeric.test(b);
	
	  if (anum && bnum) {
	    a = +a;
	    b = +b;
	  }
	
	  return (anum && !bnum) ? -1 :
	         (bnum && !anum) ? 1 :
	         a < b ? -1 :
	         a > b ? 1 :
	         0;
	}
	
	exports.rcompareIdentifiers = rcompareIdentifiers;
	function rcompareIdentifiers(a, b) {
	  return compareIdentifiers(b, a);
	}
	
	exports.major = major;
	function major(a, loose) {
	  return new SemVer(a, loose).major;
	}
	
	exports.minor = minor;
	function minor(a, loose) {
	  return new SemVer(a, loose).minor;
	}
	
	exports.patch = patch;
	function patch(a, loose) {
	  return new SemVer(a, loose).patch;
	}
	
	exports.compare = compare;
	function compare(a, b, loose) {
	  return new SemVer(a, loose).compare(b);
	}
	
	exports.compareLoose = compareLoose;
	function compareLoose(a, b) {
	  return compare(a, b, true);
	}
	
	exports.rcompare = rcompare;
	function rcompare(a, b, loose) {
	  return compare(b, a, loose);
	}
	
	exports.sort = sort;
	function sort(list, loose) {
	  return list.sort(function(a, b) {
	    return exports.compare(a, b, loose);
	  });
	}
	
	exports.rsort = rsort;
	function rsort(list, loose) {
	  return list.sort(function(a, b) {
	    return exports.rcompare(a, b, loose);
	  });
	}
	
	exports.gt = gt;
	function gt(a, b, loose) {
	  return compare(a, b, loose) > 0;
	}
	
	exports.lt = lt;
	function lt(a, b, loose) {
	  return compare(a, b, loose) < 0;
	}
	
	exports.eq = eq;
	function eq(a, b, loose) {
	  return compare(a, b, loose) === 0;
	}
	
	exports.neq = neq;
	function neq(a, b, loose) {
	  return compare(a, b, loose) !== 0;
	}
	
	exports.gte = gte;
	function gte(a, b, loose) {
	  return compare(a, b, loose) >= 0;
	}
	
	exports.lte = lte;
	function lte(a, b, loose) {
	  return compare(a, b, loose) <= 0;
	}
	
	exports.cmp = cmp;
	function cmp(a, op, b, loose) {
	  var ret;
	  switch (op) {
	    case '===':
	      if (typeof a === 'object') a = a.version;
	      if (typeof b === 'object') b = b.version;
	      ret = a === b;
	      break;
	    case '!==':
	      if (typeof a === 'object') a = a.version;
	      if (typeof b === 'object') b = b.version;
	      ret = a !== b;
	      break;
	    case '': case '=': case '==': ret = eq(a, b, loose); break;
	    case '!=': ret = neq(a, b, loose); break;
	    case '>': ret = gt(a, b, loose); break;
	    case '>=': ret = gte(a, b, loose); break;
	    case '<': ret = lt(a, b, loose); break;
	    case '<=': ret = lte(a, b, loose); break;
	    default: throw new TypeError('Invalid operator: ' + op);
	  }
	  return ret;
	}
	
	exports.Comparator = Comparator;
	function Comparator(comp, loose) {
	  if (comp instanceof Comparator) {
	    if (comp.loose === loose)
	      return comp;
	    else
	      comp = comp.value;
	  }
	
	  if (!(this instanceof Comparator))
	    return new Comparator(comp, loose);
	
	  debug('comparator', comp, loose);
	  this.loose = loose;
	  this.parse(comp);
	
	  if (this.semver === ANY)
	    this.value = '';
	  else
	    this.value = this.operator + this.semver.version;
	
	  debug('comp', this);
	}
	
	var ANY = {};
	Comparator.prototype.parse = function(comp) {
	  var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
	  var m = comp.match(r);
	
	  if (!m)
	    throw new TypeError('Invalid comparator: ' + comp);
	
	  this.operator = m[1];
	  if (this.operator === '=')
	    this.operator = '';
	
	  // if it literally is just '>' or '' then allow anything.
	  if (!m[2])
	    this.semver = ANY;
	  else
	    this.semver = new SemVer(m[2], this.loose);
	};
	
	Comparator.prototype.toString = function() {
	  return this.value;
	};
	
	Comparator.prototype.test = function(version) {
	  debug('Comparator.test', version, this.loose);
	
	  if (this.semver === ANY)
	    return true;
	
	  if (typeof version === 'string')
	    version = new SemVer(version, this.loose);
	
	  return cmp(version, this.operator, this.semver, this.loose);
	};
	
	
	exports.Range = Range;
	function Range(range, loose) {
	  if ((range instanceof Range) && range.loose === loose)
	    return range;
	
	  if (!(this instanceof Range))
	    return new Range(range, loose);
	
	  this.loose = loose;
	
	  // First, split based on boolean or ||
	  this.raw = range;
	  this.set = range.split(/\s*\|\|\s*/).map(function(range) {
	    return this.parseRange(range.trim());
	  }, this).filter(function(c) {
	    // throw out any that are not relevant for whatever reason
	    return c.length;
	  });
	
	  if (!this.set.length) {
	    throw new TypeError('Invalid SemVer Range: ' + range);
	  }
	
	  this.format();
	}
	
	Range.prototype.format = function() {
	  this.range = this.set.map(function(comps) {
	    return comps.join(' ').trim();
	  }).join('||').trim();
	  return this.range;
	};
	
	Range.prototype.toString = function() {
	  return this.range;
	};
	
	Range.prototype.parseRange = function(range) {
	  var loose = this.loose;
	  range = range.trim();
	  debug('range', range, loose);
	  // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
	  var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE];
	  range = range.replace(hr, hyphenReplace);
	  debug('hyphen replace', range);
	  // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
	  range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace);
	  debug('comparator trim', range, re[COMPARATORTRIM]);
	
	  // `~ 1.2.3` => `~1.2.3`
	  range = range.replace(re[TILDETRIM], tildeTrimReplace);
	
	  // `^ 1.2.3` => `^1.2.3`
	  range = range.replace(re[CARETTRIM], caretTrimReplace);
	
	  // normalize spaces
	  range = range.split(/\s+/).join(' ');
	
	  // At this point, the range is completely trimmed and
	  // ready to be split into comparators.
	
	  var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
	  var set = range.split(' ').map(function(comp) {
	    return parseComparator(comp, loose);
	  }).join(' ').split(/\s+/);
	  if (this.loose) {
	    // in loose mode, throw out any that are not valid comparators
	    set = set.filter(function(comp) {
	      return !!comp.match(compRe);
	    });
	  }
	  set = set.map(function(comp) {
	    return new Comparator(comp, loose);
	  });
	
	  return set;
	};
	
	// Mostly just for testing and legacy API reasons
	exports.toComparators = toComparators;
	function toComparators(range, loose) {
	  return new Range(range, loose).set.map(function(comp) {
	    return comp.map(function(c) {
	      return c.value;
	    }).join(' ').trim().split(' ');
	  });
	}
	
	// comprised of xranges, tildes, stars, and gtlt's at this point.
	// already replaced the hyphen ranges
	// turn into a set of JUST comparators.
	function parseComparator(comp, loose) {
	  debug('comp', comp);
	  comp = replaceCarets(comp, loose);
	  debug('caret', comp);
	  comp = replaceTildes(comp, loose);
	  debug('tildes', comp);
	  comp = replaceXRanges(comp, loose);
	  debug('xrange', comp);
	  comp = replaceStars(comp, loose);
	  debug('stars', comp);
	  return comp;
	}
	
	function isX(id) {
	  return !id || id.toLowerCase() === 'x' || id === '*';
	}
	
	// ~, ~> --> * (any, kinda silly)
	// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
	// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
	// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
	// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
	// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
	function replaceTildes(comp, loose) {
	  return comp.trim().split(/\s+/).map(function(comp) {
	    return replaceTilde(comp, loose);
	  }).join(' ');
	}
	
	function replaceTilde(comp, loose) {
	  var r = loose ? re[TILDELOOSE] : re[TILDE];
	  return comp.replace(r, function(_, M, m, p, pr) {
	    debug('tilde', comp, _, M, m, p, pr);
	    var ret;
	
	    if (isX(M))
	      ret = '';
	    else if (isX(m))
	      ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
	    else if (isX(p))
	      // ~1.2 == >=1.2.0 <1.3.0
	      ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
	    else if (pr) {
	      debug('replaceTilde pr', pr);
	      if (pr.charAt(0) !== '-')
	        pr = '-' + pr;
	      ret = '>=' + M + '.' + m + '.' + p + pr +
	            ' <' + M + '.' + (+m + 1) + '.0';
	    } else
	      // ~1.2.3 == >=1.2.3 <1.3.0
	      ret = '>=' + M + '.' + m + '.' + p +
	            ' <' + M + '.' + (+m + 1) + '.0';
	
	    debug('tilde return', ret);
	    return ret;
	  });
	}
	
	// ^ --> * (any, kinda silly)
	// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0
	// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0
	// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0
	// ^1.2.3 --> >=1.2.3 <2.0.0
	// ^1.2.0 --> >=1.2.0 <2.0.0
	function replaceCarets(comp, loose) {
	  return comp.trim().split(/\s+/).map(function(comp) {
	    return replaceCaret(comp, loose);
	  }).join(' ');
	}
	
	function replaceCaret(comp, loose) {
	  debug('caret', comp, loose);
	  var r = loose ? re[CARETLOOSE] : re[CARET];
	  return comp.replace(r, function(_, M, m, p, pr) {
	    debug('caret', comp, _, M, m, p, pr);
	    var ret;
	
	    if (isX(M))
	      ret = '';
	    else if (isX(m))
	      ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
	    else if (isX(p)) {
	      if (M === '0')
	        ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
	      else
	        ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0';
	    } else if (pr) {
	      debug('replaceCaret pr', pr);
	      if (pr.charAt(0) !== '-')
	        pr = '-' + pr;
	      if (M === '0') {
	        if (m === '0')
	          ret = '>=' + M + '.' + m + '.' + p + pr +
	                ' <' + M + '.' + m + '.' + (+p + 1);
	        else
	          ret = '>=' + M + '.' + m + '.' + p + pr +
	                ' <' + M + '.' + (+m + 1) + '.0';
	      } else
	        ret = '>=' + M + '.' + m + '.' + p + pr +
	              ' <' + (+M + 1) + '.0.0';
	    } else {
	      debug('no pr');
	      if (M === '0') {
	        if (m === '0')
	          ret = '>=' + M + '.' + m + '.' + p +
	                ' <' + M + '.' + m + '.' + (+p + 1);
	        else
	          ret = '>=' + M + '.' + m + '.' + p +
	                ' <' + M + '.' + (+m + 1) + '.0';
	      } else
	        ret = '>=' + M + '.' + m + '.' + p +
	              ' <' + (+M + 1) + '.0.0';
	    }
	
	    debug('caret return', ret);
	    return ret;
	  });
	}
	
	function replaceXRanges(comp, loose) {
	  debug('replaceXRanges', comp, loose);
	  return comp.split(/\s+/).map(function(comp) {
	    return replaceXRange(comp, loose);
	  }).join(' ');
	}
	
	function replaceXRange(comp, loose) {
	  comp = comp.trim();
	  var r = loose ? re[XRANGELOOSE] : re[XRANGE];
	  return comp.replace(r, function(ret, gtlt, M, m, p, pr) {
	    debug('xRange', comp, ret, gtlt, M, m, p, pr);
	    var xM = isX(M);
	    var xm = xM || isX(m);
	    var xp = xm || isX(p);
	    var anyX = xp;
	
	    if (gtlt === '=' && anyX)
	      gtlt = '';
	
	    if (xM) {
	      if (gtlt === '>' || gtlt === '<') {
	        // nothing is allowed
	        ret = '<0.0.0';
	      } else {
	        // nothing is forbidden
	        ret = '*';
	      }
	    } else if (gtlt && anyX) {
	      // replace X with 0
	      if (xm)
	        m = 0;
	      if (xp)
	        p = 0;
	
	      if (gtlt === '>') {
	        // >1 => >=2.0.0
	        // >1.2 => >=1.3.0
	        // >1.2.3 => >= 1.2.4
	        gtlt = '>=';
	        if (xm) {
	          M = +M + 1;
	          m = 0;
	          p = 0;
	        } else if (xp) {
	          m = +m + 1;
	          p = 0;
	        }
	      } else if (gtlt === '<=') {
	        // <=0.7.x is actually <0.8.0, since any 0.7.x should
	        // pass.  Similarly, <=7.x is actually <8.0.0, etc.
	        gtlt = '<';
	        if (xm)
	          M = +M + 1;
	        else
	          m = +m + 1;
	      }
	
	      ret = gtlt + M + '.' + m + '.' + p;
	    } else if (xm) {
	      ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
	    } else if (xp) {
	      ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
	    }
	
	    debug('xRange return', ret);
	
	    return ret;
	  });
	}
	
	// Because * is AND-ed with everything else in the comparator,
	// and '' means "any version", just remove the *s entirely.
	function replaceStars(comp, loose) {
	  debug('replaceStars', comp, loose);
	  // Looseness is ignored here.  star is always as loose as it gets!
	  return comp.trim().replace(re[STAR], '');
	}
	
	// This function is passed to string.replace(re[HYPHENRANGE])
	// M, m, patch, prerelease, build
	// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
	// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
	// 1.2 - 3.4 => >=1.2.0 <3.5.0
	function hyphenReplace($0,
	                       from, fM, fm, fp, fpr, fb,
	                       to, tM, tm, tp, tpr, tb) {
	
	  if (isX(fM))
	    from = '';
	  else if (isX(fm))
	    from = '>=' + fM + '.0.0';
	  else if (isX(fp))
	    from = '>=' + fM + '.' + fm + '.0';
	  else
	    from = '>=' + from;
	
	  if (isX(tM))
	    to = '';
	  else if (isX(tm))
	    to = '<' + (+tM + 1) + '.0.0';
	  else if (isX(tp))
	    to = '<' + tM + '.' + (+tm + 1) + '.0';
	  else if (tpr)
	    to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr;
	  else
	    to = '<=' + to;
	
	  return (from + ' ' + to).trim();
	}
	
	
	// if ANY of the sets match ALL of its comparators, then pass
	Range.prototype.test = function(version) {
	  if (!version)
	    return false;
	
	  if (typeof version === 'string')
	    version = new SemVer(version, this.loose);
	
	  for (var i = 0; i < this.set.length; i++) {
	    if (testSet(this.set[i], version))
	      return true;
	  }
	  return false;
	};
	
	function testSet(set, version) {
	  for (var i = 0; i < set.length; i++) {
	    if (!set[i].test(version))
	      return false;
	  }
	
	  if (version.prerelease.length) {
	    // Find the set of versions that are allowed to have prereleases
	    // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
	    // That should allow `1.2.3-pr.2` to pass.
	    // However, `1.2.4-alpha.notready` should NOT be allowed,
	    // even though it's within the range set by the comparators.
	    for (var i = 0; i < set.length; i++) {
	      debug(set[i].semver);
	      if (set[i].semver === ANY)
	        continue;
	
	      if (set[i].semver.prerelease.length > 0) {
	        var allowed = set[i].semver;
	        if (allowed.major === version.major &&
	            allowed.minor === version.minor &&
	            allowed.patch === version.patch)
	          return true;
	      }
	    }
	
	    // Version has a -pre, but it's not one of the ones we like.
	    return false;
	  }
	
	  return true;
	}
	
	exports.satisfies = satisfies;
	function satisfies(version, range, loose) {
	  try {
	    range = new Range(range, loose);
	  } catch (er) {
	    return false;
	  }
	  return range.test(version);
	}
	
	exports.maxSatisfying = maxSatisfying;
	function maxSatisfying(versions, range, loose) {
	  return versions.filter(function(version) {
	    return satisfies(version, range, loose);
	  }).sort(function(a, b) {
	    return rcompare(a, b, loose);
	  })[0] || null;
	}
	
	exports.minSatisfying = minSatisfying;
	function minSatisfying(versions, range, loose) {
	  return versions.filter(function(version) {
	    return satisfies(version, range, loose);
	  }).sort(function(a, b) {
	    return compare(a, b, loose);
	  })[0] || null;
	}
	
	exports.validRange = validRange;
	function validRange(range, loose) {
	  try {
	    // Return '*' instead of '' so that truthiness works.
	    // This will throw if it's invalid anyway
	    return new Range(range, loose).range || '*';
	  } catch (er) {
	    return null;
	  }
	}
	
	// Determine if version is less than all the versions possible in the range
	exports.ltr = ltr;
	function ltr(version, range, loose) {
	  return outside(version, range, '<', loose);
	}
	
	// Determine if version is greater than all the versions possible in the range.
	exports.gtr = gtr;
	function gtr(version, range, loose) {
	  return outside(version, range, '>', loose);
	}
	
	exports.outside = outside;
	function outside(version, range, hilo, loose) {
	  version = new SemVer(version, loose);
	  range = new Range(range, loose);
	
	  var gtfn, ltefn, ltfn, comp, ecomp;
	  switch (hilo) {
	    case '>':
	      gtfn = gt;
	      ltefn = lte;
	      ltfn = lt;
	      comp = '>';
	      ecomp = '>=';
	      break;
	    case '<':
	      gtfn = lt;
	      ltefn = gte;
	      ltfn = gt;
	      comp = '<';
	      ecomp = '<=';
	      break;
	    default:
	      throw new TypeError('Must provide a hilo val of "<" or ">"');
	  }
	
	  // If it satisifes the range it is not outside
	  if (satisfies(version, range, loose)) {
	    return false;
	  }
	
	  // From now on, variable terms are as if we're in "gtr" mode.
	  // but note that everything is flipped for the "ltr" function.
	
	  for (var i = 0; i < range.set.length; ++i) {
	    var comparators = range.set[i];
	
	    var high = null;
	    var low = null;
	
	    comparators.forEach(function(comparator) {
	      if (comparator.semver === ANY) {
	        comparator = new Comparator('>=0.0.0')
	      }
	      high = high || comparator;
	      low = low || comparator;
	      if (gtfn(comparator.semver, high.semver, loose)) {
	        high = comparator;
	      } else if (ltfn(comparator.semver, low.semver, loose)) {
	        low = comparator;
	      }
	    });
	
	    // If the edge version comparator has a operator then our version
	    // isn't outside it
	    if (high.operator === comp || high.operator === ecomp) {
	      return false;
	    }
	
	    // If the lowest version comparator has an operator and our version
	    // is less than it then it isn't higher than the range
	    if ((!low.operator || low.operator === comp) &&
	        ltefn(version, low.semver)) {
	      return false;
	    } else if (low.operator === ecomp && ltfn(version, low.semver)) {
	      return false;
	    }
	  }
	  return true;
	}
	
	exports.prerelease = prerelease;
	function prerelease(version, loose) {
	  var parsed = parse(version, loose);
	  return (parsed && parsed.prerelease.length) ? parsed.prerelease : null;
	}
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('process@0.11.9/browser.js')))
})
/** END DEFINE BLOCK for semver@5.3.0/semver.js **/


/** START DEFINE BLOCK for font-awesome@4.6.3/css/font-awesome.min.css **/
jupyter.define('font-awesome@4.6.3/css/font-awesome.min.css', function (module, exports, __jupyter_require__) {
	// removed by extract-text-webpack-plugin
})
/** END DEFINE BLOCK for font-awesome@4.6.3/css/font-awesome.min.css **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/default-theme/index.css **/
jupyter.define('jupyterlab@0.15.1/lib/default-theme/index.css', function (module, exports, __jupyter_require__) {
	// removed by extract-text-webpack-plugin
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/default-theme/index.css **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/about/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/about/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/about/index.js');
	/**
	 * The about page extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.about',
	    autoStart: true,
	    requires: [commandpalette_1.ICommandPalette, instancerestorer_1.IInstanceRestorer]
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	function activate(app, palette, restorer) {
	    var namespace = 'about-jupyterlab';
	    var model = new _1.AboutModel({ version: app.info.version });
	    var command = _1.CommandIDs.open;
	    var category = 'Help';
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: namespace });
	    restorer.restore(tracker, {
	        command: command,
	        args: function () { return null; },
	        name: function () { return 'about'; }
	    });
	    var widget;
	    function newWidget() {
	        var widget = new _1.AboutWidget();
	        widget.model = model;
	        widget.id = 'about';
	        widget.title.label = 'About';
	        widget.title.closable = true;
	        tracker.add(widget);
	        return widget;
	    }
	    app.commands.addCommand(command, {
	        label: 'About JupyterLab',
	        execute: function () {
	            if (!widget || widget.isDisposed) {
	                widget = newWidget();
	                app.shell.addToMainArea(widget);
	            }
	            app.shell.activateMain(widget.id);
	        }
	    });
	    palette.addItem({ command: command, category: category });
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/about/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/commandpalette/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/commandpalette/index.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) Jupyter Development Team.
	| Distributed under the terms of the Modified BSD License.
	|----------------------------------------------------------------------------*/
	"use strict";
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	/**
	 * The command IDs used by the command palette plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.activate = 'command-palette:activate';
	    CommandIDs.hide = 'command-palette:hide';
	    CommandIDs.toggle = 'command-palette:toggle';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	/* tslint:disable */
	/**
	 * The command palette token.
	 */
	exports.ICommandPalette = new token_1.Token('jupyter.services.commandpalette');
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/commandpalette/index.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/core/token.js **/
jupyter.define('phosphor@0.7.0/lib/core/token.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	"use strict";
	/**
	 * A runtime object which captures compile-time type information.
	 *
	 * #### Notes
	 * A token captures the compile-time type of an interface or class in
	 * an object which is useful for various type-safe runtime operations.
	 *
	 * #### Example
	 * ``` typescript
	 * interface IThing {
	 *   value: number;
	 * }
	 *
	 * const IThing = new Token<IThing>('my-module/IThing');
	 *
	 * // some runtime type registry
	 * registry.registerFactory(IThing, () => { value: 42 });
	 *
	 * // later...
	 * let thing = registry.getInstance(IThing);
	 * thing.value; // 42
	 * ```
	 */
	var Token = (function () {
	    /**
	     * Construct a new token.
	     *
	     * @param name - A human readable name for the token.
	     */
	    function Token(name) {
	        this._name = name;
	    }
	    Object.defineProperty(Token.prototype, "name", {
	        /**
	         * The human readable name for the token.
	         *
	         * #### Notes
	         * This can be useful for debugging and logging.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._name;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return Token;
	}());
	exports.Token = Token;
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/core/token.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/instancetracker.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/instancetracker.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var properties_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/properties.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var focustracker_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/focustracker.js');
	/**
	 * A class that keeps track of widget instances.
	 *
	 * #### Notes
	 * The API surface area of this concrete implementation is substantially larger
	 * than the instance tracker interface it implements. The interface is intended
	 * for export by JupyterLab plugins that create widgets and have clients who may
	 * wish to keep track of newly created widgets. This class, however, can be used
	 * internally by plugins to restore state as well.
	 */
	var InstanceTracker = (function () {
	    /**
	     * Create a new instance tracker.
	     *
	     * @param options - The instantiation options for an instance tracker.
	     */
	    function InstanceTracker(options) {
	        this._restore = null;
	        this._tracker = new focustracker_1.FocusTracker();
	        this.namespace = options.namespace;
	        this._tracker.currentChanged.connect(this._onCurrentChanged, this);
	    }
	    Object.defineProperty(InstanceTracker.prototype, "currentWidget", {
	        /**
	         * The current widget is the most recently focused widget.
	         */
	        get: function () {
	            return this._tracker.currentWidget;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(InstanceTracker.prototype, "size", {
	        /**
	         * The number of widgets held by the tracker.
	         */
	        get: function () {
	            return this._tracker.widgets.length;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a new widget to the tracker.
	     *
	     * @param widget - The widget being added.
	     */
	    InstanceTracker.prototype.add = function (widget) {
	        if (this._tracker.has(widget)) {
	            var warning = widget.id + " already exists in the tracker.";
	            console.warn(warning);
	            return Promise.reject(warning);
	        }
	        this._tracker.add(widget);
	        var injected = Private.injectedProperty.get(widget);
	        var promise;
	        // Handle widget state restoration.
	        if (!injected && this._restore) {
	            var _a = this._restore, restorer = _a.restorer, state = _a.state;
	            var widgetName = this._restore.name(widget);
	            widget.disposed.connect(this._onWidgetDisposed, this);
	            if (widgetName) {
	                var name_1 = this.namespace + ":" + widgetName;
	                var data = this._restore.args(widget);
	                Private.nameProperty.set(widget, name_1);
	                promise = state.save(name_1, { data: data });
	                if (restorer) {
	                    restorer.add(widget, name_1);
	                }
	            }
	        }
	        return promise || Promise.resolve(void 0);
	    };
	    Object.defineProperty(InstanceTracker.prototype, "isDisposed", {
	        /**
	         * Test whether the tracker is disposed.
	         */
	        get: function () {
	            return this._tracker === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the tracker.
	     */
	    InstanceTracker.prototype.dispose = function () {
	        if (this._tracker === null) {
	            return;
	        }
	        var tracker = this._tracker;
	        this._tracker = null;
	        signaling_1.clearSignalData(this);
	        tracker.dispose();
	    };
	    /**
	     * Find the first widget in the tracker that satisfies a filter function.
	     *
	     * @param - fn The filter function to call on each widget.
	     */
	    InstanceTracker.prototype.find = function (fn) {
	        var result = null;
	        iteration_1.each(this._tracker.widgets, function (widget) {
	            // If a result has already been found, short circuit.
	            if (result) {
	                return;
	            }
	            if (fn(widget)) {
	                result = widget;
	            }
	        });
	        return result;
	    };
	    /**
	     * Iterate through each widget in the tracker.
	     *
	     * @param fn - The function to call on each widget.
	     */
	    InstanceTracker.prototype.forEach = function (fn) {
	        iteration_1.each(this._tracker.widgets, function (widget) { fn(widget); });
	    };
	    /**
	     * Inject a foreign widget into the instance tracker.
	     *
	     * @param widget - The widget to inject into the tracker.
	     *
	     * #### Notes
	     * Any widgets injected into an instance tracker will not have their state
	     * saved by the tracker. The primary use case for widget injection is for a
	     * plugin that offers a sub-class of an extant plugin to have its instances
	     * share the same commands as the parent plugin (since most relevant commands
	     * will use the `currentWidget` of the parent plugin's instance tracker). In
	     * this situation, the sub-class plugin may well have its own instance tracker
	     * for layout and state restoration in addition to injecting its widgets into
	     * the parent plugin's instance tracker.
	     */
	    InstanceTracker.prototype.inject = function (widget) {
	        Private.injectedProperty.set(widget, true);
	        this.add(widget);
	    };
	    /**
	     * Check if this tracker has the specified widget.
	     *
	     * @param widget - The widget whose existence is being checked.
	     */
	    InstanceTracker.prototype.has = function (widget) {
	        return this._tracker.has(widget);
	    };
	    /**
	     * Restore the widgets in this tracker's namespace.
	     *
	     * @param options - The configuration options that describe restoration.
	     *
	     * @returns A promise that resolves when restoration has completed.
	     *
	     * #### Notes
	     * This function should almost never be invoked by client code. Its primary
	     * use case is to be invoked by an instance restorer plugin that handles
	     * multiple instance trackers and, when ready, asks them each to restore their
	     * respective widgets.
	     */
	    InstanceTracker.prototype.restore = function (options) {
	        this._restore = options;
	        var command = options.command, registry = options.registry, state = options.state, when = options.when;
	        var namespace = this.namespace;
	        var promises = [state.fetchNamespace(namespace)];
	        if (when) {
	            promises = promises.concat(when);
	        }
	        return Promise.all(promises).then(function (_a) {
	            var saved = _a[0];
	            return Promise.all(saved.map(function (item) {
	                var args = item.value.data;
	                // Execute the command and if it fails, delete the state restore data.
	                return registry.execute(command, args)
	                    .catch(function () { state.remove(item.id); });
	            }));
	        });
	    };
	    /**
	     * Save the restore data for a given widget.
	     *
	     * @param widget - The widget being saved.
	     */
	    InstanceTracker.prototype.save = function (widget) {
	        var injected = Private.injectedProperty.get(widget);
	        if (!this._restore || !this.has(widget) || injected) {
	            return;
	        }
	        var state = this._restore.state;
	        var widgetName = this._restore.name(widget);
	        var oldName = Private.nameProperty.get(widget);
	        var newName = widgetName ? this.namespace + ":" + widgetName : null;
	        if (oldName && oldName !== newName) {
	            state.remove(oldName);
	        }
	        // Set the name property irrespective of whether the new name is null.
	        Private.nameProperty.set(widget, newName);
	        if (newName) {
	            var data = this._restore.args(widget);
	            state.save(newName, { data: data });
	        }
	    };
	    /**
	     * Handle the current change event.
	     *
	     * #### Notes
	     * The default implementation is a no-op. This may be reimplemented by
	     * subclasses to customize the behavior.
	     */
	    InstanceTracker.prototype.onCurrentChanged = function () {
	        /* This is a no-op. */
	    };
	    /**
	     * Handle the current change signal from the internal focus tracker.
	     */
	    InstanceTracker.prototype._onCurrentChanged = function (sender, args) {
	        this.onCurrentChanged();
	        this.currentChanged.emit(args.newValue);
	    };
	    /**
	     * Clean up after disposed widgets.
	     */
	    InstanceTracker.prototype._onWidgetDisposed = function (widget) {
	        var injected = Private.injectedProperty.get(widget);
	        if (injected || !this._restore) {
	            return;
	        }
	        // If restore data was saved, delete it from the database.
	        var state = this._restore.state;
	        var name = Private.nameProperty.get(widget);
	        if (name) {
	            state.remove(name);
	        }
	    };
	    return InstanceTracker;
	}());
	exports.InstanceTracker = InstanceTracker;
	// Define the signals for the `InstanceTracker` class.
	signaling_1.defineSignal(InstanceTracker.prototype, 'currentChanged');
	/*
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * An attached property to indicate whether a widget has been injected.
	     */
	    Private.injectedProperty = new properties_1.AttachedProperty({
	        name: 'injected',
	        value: false
	    });
	    /**
	     * An attached property for a widget's ID in the state database.
	     */
	    Private.nameProperty = new properties_1.AttachedProperty({ name: 'name' });
	})(Private || (Private = {}));
	//# sourceMappingURL=instancetracker.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/instancetracker.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/instancerestorer/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/instancerestorer/index.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) Jupyter Development Team.
	| Distributed under the terms of the Modified BSD License.
	|----------------------------------------------------------------------------*/
	"use strict";
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/instancerestorer.js');
	exports.IInstanceRestorer = instancerestorer_1.IInstanceRestorer;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/instancerestorer/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/instancerestorer/instancerestorer.js **/
jupyter.define('jupyterlab@0.15.1/lib/instancerestorer/instancerestorer.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) Jupyter Development Team.
	| Distributed under the terms of the Modified BSD License.
	|----------------------------------------------------------------------------*/
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var properties_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/properties.js');
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	/* tslint:disable */
	/**
	 * The instance restorer token.
	 */
	exports.IInstanceRestorer = new token_1.Token('jupyter.services.instance-restorer');
	/**
	 * The state database key for restorer data.
	 */
	var KEY = 'instance-restorer:data';
	/**
	 * The default implementation of an instance restorer.
	 *
	 * #### Notes
	 * The lifecycle for state restoration is subtle. The sequence of events is:
	 *
	 * 1. The instance restorer plugin is instantiated. It installs itself as the
	 *    layout database that the application shell can use to `fetch` and `save`
	 *    layout restoration data.
	 *
	 * 2. Other plugins that care about state restoration require the instance
	 *    restorer as a dependency.
	 *
	 * 3. As each load-time plugin initializes (which happens before the lab
	 *    application has `started`), it instructs the instance restorer whether
	 *    the restorer ought to `restore` its state by passing in its tracker.
	 *    Alternatively, a plugin that does not require its own instance tracker
	 *    (because perhaps it only creates a single widget, like a command palette),
	 *    can simply `add` its widget along with a persistent unique name to the
	 *    instance restorer so that its layout state can be restored when the lab
	 *    application restores.
	 *
	 * 4. After all the load-time plugins have finished initializing, the lab
	 *    application `started` promise will resolve. This is the `first`
	 *    promise that the instance restorer waits for. By this point, all of the
	 *    plugins that care about restoration will have instructed the instance
	 *    restorer to `restore` their state.
	 *
	 * 5. The instance restorer will then instruct each plugin's instance tracker
	 *    to restore its state and reinstantiate whichever widgets it wants. The
	 *    tracker returns a promise to the instance restorer that resolves when it
	 *    has completed restoring the tracked widgets it cares about.
	 *
	 * 6. As each instance finishes restoring, it resolves the promise that was
	 *    made to the instance restorer (in step 5). After all of the promises that
	 *    the restorer is awaiting have resolved, the restorer then resolves its
	 *    `restored` promise allowing the application shell to rehydrate its saved
	 *    layout.
	 *
	 * Of particular note are steps 5 and 6: since state restoration of plugins
	 * is accomplished by executing commands, the command that is used to restore
	 * the state of each plugin must return a promise that only resolves when the
	 * widget has been created and added to the plugin's instance tracker.
	 */
	var InstanceRestorer = (function () {
	    /**
	     * Create an instance restorer.
	     */
	    function InstanceRestorer(options) {
	        var _this = this;
	        this._first = null;
	        this._promises = [];
	        this._restored = new services_1.utils.PromiseDelegate();
	        this._registry = null;
	        this._state = null;
	        this._trackers = new Set();
	        this._widgets = new Map();
	        this._registry = options.registry;
	        this._state = options.state;
	        this._first = options.first;
	        this._first.then(function () { return Promise.all(_this._promises); }).then(function () {
	            // Release the promises held in memory.
	            _this._promises = null;
	            // Release the tracker set.
	            _this._trackers.clear();
	            _this._trackers = null;
	        }).then(function () { _this._restored.resolve(void 0); });
	    }
	    Object.defineProperty(InstanceRestorer.prototype, "restored", {
	        /**
	         * A promise resolved when the instance restorer is ready to receive signals.
	         */
	        get: function () {
	            return this._restored.promise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a widget to be tracked by the instance restorer.
	     */
	    InstanceRestorer.prototype.add = function (widget, name) {
	        Private.nameProperty.set(widget, name);
	        this._widgets.set(name, widget);
	        widget.disposed.connect(this._onWidgetDisposed, this);
	    };
	    /**
	     * Fetch the layout state for the application.
	     *
	     * #### Notes
	     * Fetching the layout relies on all widget restoration to be complete, so
	     * calls to `fetch` are guaranteed to return after restoration is complete.
	     */
	    InstanceRestorer.prototype.fetch = function () {
	        var _this = this;
	        var blank = {
	            currentWidget: null,
	            fresh: true,
	            leftArea: { collapsed: true, currentWidget: null, widgets: null },
	            rightArea: { collapsed: true, currentWidget: null, widgets: null }
	        };
	        var layout = this._state.fetch(KEY);
	        return Promise.all([layout, this.restored]).then(function (_a) {
	            var data = _a[0];
	            if (!data) {
	                return blank;
	            }
	            var _b = data, current = _b.current, left = _b.left, right = _b.right;
	            // If any data exists, then this is not a fresh session.
	            var fresh = false;
	            // Rehydrate main area. Coerce type of `current` in case of bad data.
	            var currentWidget = current && _this._widgets.has("" + current) ?
	                _this._widgets.get("" + current) : null;
	            // Rehydrate left area.
	            var leftArea = _this._rehydrateSideArea(left);
	            // Rehydrate right area.
	            var rightArea = _this._rehydrateSideArea(right);
	            return { currentWidget: currentWidget, fresh: fresh, leftArea: leftArea, rightArea: rightArea };
	        }).catch(function () { return blank; }); // Let fetch fail gracefully; return blank slate.
	    };
	    /**
	     * Restore the widgets of a particular instance tracker.
	     *
	     * @param tracker - The instance tracker whose widgets will be restored.
	     *
	     * @param options - The restoration options.
	     */
	    InstanceRestorer.prototype.restore = function (tracker, options) {
	        if (!this._promises) {
	            var warning = 'restore() can only be called before `first` has resolved.';
	            console.warn(warning);
	            return Promise.reject(warning);
	        }
	        var namespace = tracker.namespace;
	        if (this._trackers.has(namespace)) {
	            var warning = "A tracker namespaced " + namespace + " was already restored.";
	            console.warn(warning);
	            return Promise.reject(warning);
	        }
	        this._trackers.add(namespace);
	        var args = options.args, command = options.command, name = options.name, when = options.when;
	        var first = this._first;
	        var promise = tracker.restore({
	            args: args, command: command, name: name,
	            registry: this._registry,
	            restorer: this,
	            state: this._state,
	            when: when ? [first].concat(when) : first
	        });
	        this._promises.push(promise);
	        return promise;
	    };
	    /**
	     * Save the layout state for the application.
	     */
	    InstanceRestorer.prototype.save = function (data) {
	        // If there are promises that are unresolved, bail.
	        if (this._promises) {
	            var warning = 'save() was called prematurely.';
	            console.warn(warning);
	            return Promise.reject(warning);
	        }
	        var dehydrated = {};
	        var current;
	        // Dehydrate main area.
	        if (data.currentWidget) {
	            current = Private.nameProperty.get(data.currentWidget);
	            if (current) {
	                dehydrated.current = current;
	            }
	        }
	        // Dehydrate left area.
	        dehydrated.left = this._dehydrateSideArea(data.leftArea);
	        // Dehydrate right area.
	        dehydrated.right = this._dehydrateSideArea(data.rightArea);
	        return this._state.save(KEY, dehydrated);
	    };
	    /**
	     * Dehydrate a side area into a serialized description object.
	     */
	    InstanceRestorer.prototype._dehydrateSideArea = function (area) {
	        var dehydrated = { collapsed: area.collapsed };
	        if (area.currentWidget) {
	            var current = Private.nameProperty.get(area.currentWidget);
	            if (current) {
	                dehydrated.current = current;
	            }
	        }
	        if (area.widgets) {
	            dehydrated.widgets = area.widgets
	                .map(function (widget) { return Private.nameProperty.get(widget); })
	                .filter(function (name) { return !!name; });
	        }
	        return dehydrated;
	    };
	    /**
	     * Reydrate a serialized side area description object.
	     *
	     * #### Notes
	     * This function consumes data that can become corrupted, so it uses type
	     * coercion to guarantee the dehydrated object is safely processed.
	     */
	    InstanceRestorer.prototype._rehydrateSideArea = function (area) {
	        if (!area) {
	            return { collapsed: true, currentWidget: null, widgets: null };
	        }
	        var internal = this._widgets;
	        var collapsed = area.hasOwnProperty('collapsed') ? !!area.collapsed
	            : false;
	        var currentWidget = area.current && internal.has("" + area.current) ?
	            internal.get("" + area.current) : null;
	        var widgets = !Array.isArray(area.widgets) ? null
	            : area.widgets
	                .map(function (name) { return internal.has("" + name) ? internal.get("" + name) : null; })
	                .filter(function (widget) { return !!widget; });
	        return { collapsed: collapsed, currentWidget: currentWidget, widgets: widgets };
	    };
	    /**
	     * Handle a widget disposal.
	     */
	    InstanceRestorer.prototype._onWidgetDisposed = function (widget) {
	        var name = Private.nameProperty.get(widget);
	        this._widgets.delete(name);
	    };
	    return InstanceRestorer;
	}());
	exports.InstanceRestorer = InstanceRestorer;
	/*
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * An attached property for a widget's ID in the state database.
	     */
	    Private.nameProperty = new properties_1.AttachedProperty({ name: 'name' });
	})(Private || (Private = {}));
	//# sourceMappingURL=instancerestorer.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/instancerestorer/instancerestorer.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/about/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/about/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var vdom_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/vdom.js');
	var vdom_2 = __jupyter_require__('jupyterlab@0.15.1/lib/common/vdom.js');
	/**
	 * The class name added to each page in the About plugin.
	 */
	var SECTION_CLASS = 'jp-About-section';
	/**
	 * The class name added to center content.
	 */
	var SECTION_CENTER_CLASS = 'jp-About-sectioncenter';
	/**
	 * The class name added to group elements on the initial page.
	 */
	var CONTAINER_CLASS = 'jp-About-container';
	/**
	 * The class name added to elements in a row.
	 */
	var ROW_CLASS = 'jp-About-row';
	/**
	 * The class name added to elements in a column.
	 */
	var COLUMN_CLASS = 'jp-About-column';
	/**
	 * The class name used specify postion of elements.
	 */
	var HALF_CLASS = 'jp-About-one-half';
	/**
	 * The class name added to the About plugin description on the intial page.
	 */
	var DESC_ONE_CLASS = 'jp-About-desc-one';
	/**
	 * The class name added to other plugin descriptions on the intial page.
	 */
	var DESC_TWO_CLASS = 'jp-About-desc-two';
	/**
	 * The class name added to headers of other plugins on the intial page.
	 */
	var DESC_TWO_HEADER_CLASS = 'jp-About-desc-two-header';
	/**
	 * The class name added to headers.
	 */
	var HEADER_CLASS = 'jp-About-header';
	/**
	 * The class name added to plugin pages.
	 */
	var CONTENT_CLASS = 'jp-About-content';
	/**
	 * The class name added to descriptions on plugin pages.
	 */
	var CONTENT_DESC_CLASS = 'jp-About-content-desc';
	/**
	 * The class name added to the navigation down button.
	 */
	var NAV_CLASS = 'jp-About-nav-button';
	/**
	 * The class name added to all images and icons.
	 */
	var IMAGE_CLASS = 'jp-img';
	/**
	 * The class name added to the JupyterLab logo.
	 */
	var LOGO_CLASS = 'jp-About-logo';
	/**
	 * The class name added to the main area icon.
	 */
	var MAIN_AREA_ICON_CLASS = 'jp-About-hero-mainarea';
	/**
	 * The class name added the command palette icon.
	 */
	var COMMAND_ICON_CLASS = 'jp-About-hero-command';
	/**
	 * The class name added to the filebrowser icon.
	 */
	var FILEBROWSER_ICON_CLASS = 'jp-About-hero-filebrowser';
	/**
	 * The class name added for the notebook icon.
	 */
	var NOTEBOOK_ICON_CLASS = 'jp-About-hero-notebook';
	/**
	 * The class name added to the main area image.
	 */
	var MAIN_AREA_IMAGE_CLASS = 'jp-About-mainarea';
	/**
	 * The class name added to the command palette image.
	 */
	var COMMAND_IMAGE_CLASS = 'jp-About-command';
	/**
	 * The class name added to the filebrowser image.
	 */
	var FILEBROWSER_IMAGE_CLASS = 'jp-About-fb';
	/**
	 * The class name added to the notebook image.
	 */
	var NOTEBOOK_IMAGE_CLASS = 'jp-About-nb';
	/**
	 * Title of About page.
	 */
	var TITLE = 'Welcome to the JupyterLab alpha preview';
	/**
	 * Text on the first page that gives a high level overview of JupyterLab.
	 */
	var HEADER_TEXT = [
	    'Click on the Launcher tab for the initial JupyterLab screen.',
	    'This demo gives an alpha developer preview of the JupyterLab environment.',
	    'It is not ready for general usage yet.',
	    'We are developing JupyterLab at ',
	    'https://github.com/jupyterlab/jupyterlab',
	    '. Pull requests and feedback are welcome!',
	    "Here is a brief description of some of the things you'll find in this demo."
	];
	/**
	 * Contains the plugin names.
	 */
	var PLUGIN_HEADERS = [
	    'Main Area',
	    'Command Palette',
	    'File Browser',
	    'Notebook'
	];
	/**
	 * Description of the main area and its functionality.
	 */
	var MAIN_AREA_DESC = [
	    'Open tabs and drag and drop them to rearrange them.',
	    "The main area is divided into panels of tabs. Drag a tab around the area\n   to split the main area in different ways. Drag a tab to the center of a\n   panel to move a tab without splitting the panel (in this case, the whole\n   panel will highlight instead of just a portion).",
	    "Resize panels by dragging their borders (be aware that panels and sidebars\n   also have a minimum width). A file that contains changes to be saved has\n   a circle for a close icon."
	];
	/**
	 * Description of the file browser and its functionality.
	 */
	var FILE_BROWSER_DESC = [
	    'Navigate and organize your files.',
	    "Clicking the \"Files\" tab, located on the left, will toggle the file browser.\n   Navigate into directories by double-clicking, and use the breadcrumbs at the\n   top to navigate out. Create a new file/directory by clicking the plus icon at\n   the top. Click the middle icon to upload files, and click the last icon to\n   reload the file listing. Drag and drop files to move them to subdirectories.\n   Click on a selected file to rename it. Sort the list by clicking on a column\n   header.\n   Open a file by double-clicking it or dragging it into the main area.\n   Opening an image displays the image. Opening a code file opens a code editor.\n   Opening a notebook opens a very preliminary notebook component."
	];
	/**
	 * Description of the command palette and its functionality.
	 */
	var COMMAND_PALETTE_DESC = [
	    'View list of commands and keyboard shortcuts.',
	    "Clicking the \"Commands\" tab, located on the left, will toggle the command\n   palette. Execute a command by clicking, or navigating with your arrow keys\n   and pressing Enter. Filter commands by typing in the text box at the top of\n   the palette. The palette is organized into categories, and you can filter on\n   a single category by clicking on the category header or by typing the header\n   surrounded by colons in the search input (e.g., :file:).",
	    'You can try these things from the command palette:',
	    'Open a new terminal (requires macOS or Linux)',
	    'Open an IPython console',
	    'Open a new file',
	    'Save a file',
	    'Open a help panel on the right'
	];
	/**
	 * Description of the notebook and its functionality.
	 */
	var NOTEBOOK_DESC = [
	    'Dedicate a tab to running a class notebook.',
	    "Opening a notebook will open a minimally-featured notebook.\n   Code execution, Markdown rendering, and basic cell toolbar actions are\n   supported.\n   Future versions will add more features from the existing Jupyter notebook."
	];
	/**
	 * The command IDs used by the about plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.open = 'about-jupyterlab:open';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	/**
	 * AboutModel holds data which the AboutWidgetwill render.
	 */
	var AboutModel = (function (_super) {
	    __extends(AboutModel, _super);
	    /**
	     * Create an about model.
	     */
	    function AboutModel(options) {
	        _super.call(this);
	        /**
	         * Title of About page.
	         */
	        this.title = TITLE;
	        /**
	         * Text on the first page that gives a high level overview of JupyterLab.
	         */
	        this.headerText = HEADER_TEXT;
	        /**
	         * Contains the plugin names.
	         */
	        this.pluginHeaders = PLUGIN_HEADERS;
	        /**
	         * Description of the main area and its functionality.
	         */
	        this.mainAreaDesc = MAIN_AREA_DESC;
	        /**
	         * Description of the file browser and its functionality.
	         */
	        this.filebrowserDesc = FILE_BROWSER_DESC;
	        /**
	         * Description of the command palette and its functionality.
	         */
	        this.commandPaletteDesc = COMMAND_PALETTE_DESC;
	        /**
	         * Description of the notebook and its functionality.
	         */
	        this.notebookDesc = NOTEBOOK_DESC;
	        this.version = options.version;
	    }
	    return AboutModel;
	}(vdom_2.VDomModel));
	exports.AboutModel = AboutModel;
	/**
	 * A virtual-DOM-based widget for the About plugin.
	 */
	var AboutWidget = (function (_super) {
	    __extends(AboutWidget, _super);
	    function AboutWidget() {
	        _super.apply(this, arguments);
	    }
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    AboutWidget.prototype.onActivateRequest = function (msg) {
	        this.node.tabIndex = -1;
	        this.node.focus();
	    };
	    /**
	     * Handle `'close-request'` messages.
	     */
	    AboutWidget.prototype.onCloseRequest = function (msg) {
	        _super.prototype.onCloseRequest.call(this, msg);
	        this.dispose();
	    };
	    /**
	     * Render the about plugin to virtual DOM nodes.
	     */
	    AboutWidget.prototype.render = function () {
	        var title = this.model.title;
	        var version = "v" + this.model.version;
	        var headerText = this.model.headerText;
	        var pluginHeaders = this.model.pluginHeaders;
	        var mainAreaDesc = this.model.mainAreaDesc;
	        var filebrowserDesc = this.model.filebrowserDesc;
	        var commandPaletteDesc = this.model.commandPaletteDesc;
	        var notebookDesc = this.model.notebookDesc;
	        var headerRow = vdom_1.h.div({ className: ROW_CLASS }, vdom_1.h.div({ className: COLUMN_CLASS }, vdom_1.h.span({ className: IMAGE_CLASS + ' ' + LOGO_CLASS }), vdom_1.h.p({ className: HEADER_CLASS }, title, vdom_1.h.span(' (', vdom_1.h.code(version), ')')), vdom_1.h.div({ className: DESC_ONE_CLASS }, vdom_1.h.p(headerText[0]), vdom_1.h.p(headerText[1], ' ', vdom_1.h.strong(headerText[2])), vdom_1.h.p(headerText[3], vdom_1.h.a({ href: headerText[4], target: '_blank' }, headerText[4]), headerText[5]), vdom_1.h.p(headerText[6]))));
	        var mainAreaCommandPaletteRow = vdom_1.h.div({ className: ROW_CLASS }, vdom_1.h.div({ className: HALF_CLASS + ' ' + COLUMN_CLASS }, vdom_1.h.p({ className: DESC_TWO_HEADER_CLASS }, vdom_1.h.a({ href: '#about-main-area' }, vdom_1.h.span({ className: IMAGE_CLASS + ' ' + MAIN_AREA_ICON_CLASS }), pluginHeaders[0])), vdom_1.h.p({ className: DESC_TWO_CLASS }, mainAreaDesc[0])), vdom_1.h.div({ className: HALF_CLASS + ' ' + COLUMN_CLASS }, vdom_1.h.p({ className: DESC_TWO_HEADER_CLASS }, vdom_1.h.a({ href: '#about-command' }, vdom_1.h.span({ className: IMAGE_CLASS + ' ' + COMMAND_ICON_CLASS }), pluginHeaders[1])), vdom_1.h.p({ className: DESC_TWO_CLASS }, commandPaletteDesc[0])));
	        var filebrowserNotebookRow = vdom_1.h.div({ className: ROW_CLASS }, vdom_1.h.div({ className: HALF_CLASS + ' ' + COLUMN_CLASS }, vdom_1.h.p({ className: DESC_TWO_HEADER_CLASS }, vdom_1.h.a({ href: '#about-filebrowser' }, vdom_1.h.span({ className: IMAGE_CLASS + ' ' + FILEBROWSER_ICON_CLASS }), pluginHeaders[2])), vdom_1.h.p({ className: DESC_TWO_CLASS }, filebrowserDesc[0])), vdom_1.h.div({ className: HALF_CLASS + ' ' + COLUMN_CLASS }, vdom_1.h.p({ className: DESC_TWO_HEADER_CLASS }, vdom_1.h.a({ href: '#about-notebook' }, vdom_1.h.span({ className: IMAGE_CLASS + ' ' + NOTEBOOK_ICON_CLASS }), pluginHeaders[3])), vdom_1.h.p({ className: DESC_TWO_CLASS }, notebookDesc[0])));
	        var mainAreaPage = vdom_1.h.div({ className: SECTION_CLASS }, vdom_1.h.a({ id: 'about-main-area' }), vdom_1.h.div({ className: SECTION_CENTER_CLASS }, vdom_1.h.p({ className: HEADER_CLASS + ' ' + CONTENT_CLASS }, vdom_1.h.span({ className: IMAGE_CLASS + ' ' + MAIN_AREA_ICON_CLASS }), pluginHeaders[0]), vdom_1.h.span({ className: IMAGE_CLASS + ' ' + MAIN_AREA_IMAGE_CLASS }), vdom_1.h.p({ className: CONTENT_DESC_CLASS }, mainAreaDesc[1]), vdom_1.h.p({ className: CONTENT_DESC_CLASS }, mainAreaDesc[2]), vdom_1.h.a({ href: '#about-command' }, vdom_1.h.span({ className: NAV_CLASS }))));
	        var commandPalettePage = vdom_1.h.div({ className: SECTION_CLASS }, vdom_1.h.a({ id: 'about-command' }), vdom_1.h.div({ className: SECTION_CENTER_CLASS }, vdom_1.h.p({ className: HEADER_CLASS + ' ' + CONTENT_CLASS }, vdom_1.h.span({ className: IMAGE_CLASS + ' ' + COMMAND_ICON_CLASS }), pluginHeaders[1]), vdom_1.h.span({ className: IMAGE_CLASS + ' ' + COMMAND_IMAGE_CLASS }), vdom_1.h.p({ className: CONTENT_DESC_CLASS }, commandPaletteDesc[1]), vdom_1.h.div({ className: CONTENT_DESC_CLASS }, vdom_1.h.p(commandPaletteDesc[2]), vdom_1.h.ul(vdom_1.h.li(commandPaletteDesc[3]), vdom_1.h.li(commandPaletteDesc[4]), vdom_1.h.li(commandPaletteDesc[5]), vdom_1.h.li(commandPaletteDesc[6]), vdom_1.h.li(commandPaletteDesc[7]))), vdom_1.h.a({ href: '#about-filebrowser' }, vdom_1.h.span({ className: NAV_CLASS }))));
	        var filebrowserPage = vdom_1.h.div({ className: SECTION_CLASS }, vdom_1.h.a({ id: 'about-filebrowser' }), vdom_1.h.div({ className: SECTION_CENTER_CLASS }, vdom_1.h.p({ className: HEADER_CLASS + ' ' + CONTENT_CLASS }, vdom_1.h.span({ className: IMAGE_CLASS + ' ' + FILEBROWSER_ICON_CLASS }), pluginHeaders[2]), vdom_1.h.span({ className: IMAGE_CLASS + ' ' + FILEBROWSER_IMAGE_CLASS }), vdom_1.h.p({ className: CONTENT_DESC_CLASS }, filebrowserDesc[1]), vdom_1.h.a({ href: '#about-notebook' }, vdom_1.h.span({ className: NAV_CLASS }))));
	        var notebookPage = vdom_1.h.div({ className: SECTION_CLASS }, vdom_1.h.a({ id: 'about-notebook' }), vdom_1.h.div({ className: SECTION_CENTER_CLASS }, vdom_1.h.p({ className: HEADER_CLASS + ' ' + CONTENT_CLASS }, vdom_1.h.span({ className: IMAGE_CLASS + ' ' + NOTEBOOK_ICON_CLASS }), pluginHeaders[3]), vdom_1.h.span({ className: IMAGE_CLASS + ' ' + NOTEBOOK_IMAGE_CLASS }), vdom_1.h.p({ className: CONTENT_DESC_CLASS }, notebookDesc[1])));
	        return vdom_1.h.div({ id: 'about' }, vdom_1.h.div({ className: SECTION_CLASS }, vdom_1.h.div({ className: SECTION_CENTER_CLASS }, vdom_1.h.div({ className: CONTAINER_CLASS }, headerRow, mainAreaCommandPaletteRow, filebrowserNotebookRow), vdom_1.h.a({ href: '#about-main-area' }, vdom_1.h.span({ className: NAV_CLASS })))), mainAreaPage, commandPalettePage, filebrowserPage, notebookPage);
	    };
	    return AboutWidget;
	}(vdom_2.VDomWidget));
	exports.AboutWidget = AboutWidget;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/about/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/vdom.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/vdom.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var vdom_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/vdom.js');
	/**
	 * Concrete implementation of IVDomModel.
	 */
	var VDomModel = (function () {
	    function VDomModel() {
	        this._isDisposed = false;
	    }
	    Object.defineProperty(VDomModel.prototype, "isDisposed", {
	        /**
	         * Test whether the model is disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose the model.
	     */
	    VDomModel.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        signaling_1.clearSignalData(this);
	    };
	    return VDomModel;
	}());
	exports.VDomModel = VDomModel;
	// Define the signals for the VDomModel class.
	signaling_1.defineSignal(VDomModel.prototype, 'stateChanged');
	/**
	 * Phosphor widget that encodes best practices for VDOM based rendering.
	 */
	var VDomWidget = (function (_super) {
	    __extends(VDomWidget, _super);
	    function VDomWidget() {
	        _super.apply(this, arguments);
	    }
	    Object.defineProperty(VDomWidget.prototype, "model", {
	        /**
	         * Get the current model.
	         */
	        get: function () {
	            return this._model;
	        },
	        /**
	         * Set the model and fire changed signals.
	         */
	        set: function (newValue) {
	            newValue = newValue || null;
	            if (this._model === newValue) {
	                return;
	            }
	            if (this._model) {
	                this._model.stateChanged.disconnect(this.update, this);
	            }
	            this._model = newValue;
	            this._model.stateChanged.connect(this.update, this);
	            this.update();
	            this.modelChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose this widget.
	     */
	    VDomWidget.prototype.dispose = function () {
	        this._model = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Called to update the state of the widget.
	     *
	     * The default implementation of this method triggers
	     * VDOM based rendering by calling the this.render() method.
	     */
	    VDomWidget.prototype.onUpdateRequest = function (msg) {
	        var vnode = this.render();
	        vdom_1.render(vnode, this.node);
	    };
	    return VDomWidget;
	}(widget_1.Widget));
	exports.VDomWidget = VDomWidget;
	// Define the signal for the VDomWidget class.
	signaling_1.defineSignal(VDomWidget.prototype, 'modelChanged');
	//# sourceMappingURL=vdom.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/vdom.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/application/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/application/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/application/index.js');
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	/**
	 * The main extension.
	 */
	var plugin = {
	    id: 'jupyter.extensions.main',
	    requires: [commandpalette_1.ICommandPalette],
	    activate: function (app, palette) {
	        var command = _1.CommandIDs.closeAll;
	        app.commands.addCommand(command, {
	            label: 'Close All Widgets',
	            execute: function () { app.shell.closeAll(); }
	        });
	        palette.addItem({ command: command, category: 'Main Area' });
	        var message = 'Are you sure you want to exit JupyterLab?\n' +
	            'Any unsaved changes will be lost.';
	        // The spec for the `beforeunload` event is implemented differently by
	        // the different browser vendors. Consequently, the `event.returnValue`
	        // attribute needs to set in addition to a return value being returned.
	        // For more information, see:
	        // https://developer.mozilla.org/en/docs/Web/Events/beforeunload
	        window.addEventListener('beforeunload', function (event) {
	            return event.returnValue = message;
	        });
	    },
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/application/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/clipboard/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/clipboard/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var mimedata_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/mimedata.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/clipboard/index.js');
	/**
	 * The clipboard provider.
	 */
	var plugin = {
	    id: 'jupyter.services.clipboard',
	    provides: _1.IClipboard,
	    activate: function () { return new mimedata_1.MimeData(); }
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/clipboard/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/clipboard/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/clipboard/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	/* tslint:disable */
	/**
	 * The clipboard token.
	 */
	exports.IClipboard = new token_1.Token('jupyter.services.clipboard');
	/**
	 * Copy text to the system clipboard.
	 *
	 * #### Notes
	 * This can only be called in response to a user input event.
	 */
	function copyToClipboard(text) {
	    var node = document.body;
	    var handler = function (event) {
	        var data = event.clipboardData || window.clipboardData;
	        data.setData('text', text);
	        event.preventDefault();
	        node.removeEventListener('copy', handler);
	    };
	    node.addEventListener('copy', handler);
	    generateClipboardEvent(node);
	}
	exports.copyToClipboard = copyToClipboard;
	/**
	 * Generate a clipboard event on a node.
	 *
	 * @param node - The element on which to generate the event.
	 *
	 * @param type - The type of event to generate.
	 *   `'paste'` events cannot be programmatically generated.
	 *
	 * #### Notes
	 * This can only be called in response to a user input event.
	 */
	function generateClipboardEvent(node, type) {
	    // http://stackoverflow.com/a/5210367
	    if (type === void 0) { type = 'copy'; }
	    // Identify selected text.
	    var sel = window.getSelection();
	    // Save the current selection.
	    var savedRanges = [];
	    for (var i = 0, len = sel.rangeCount; i < len; ++i) {
	        savedRanges[i] = sel.getRangeAt(i).cloneRange();
	    }
	    // Select the node content.
	    var range = document.createRange();
	    range.selectNodeContents(node);
	    sel.removeAllRanges();
	    sel.addRange(range);
	    // Execute the command.
	    document.execCommand(type);
	    // Restore the previous selection.
	    sel = window.getSelection();
	    sel.removeAllRanges();
	    for (var i = 0, len = savedRanges.length; i < len; ++i) {
	        sel.addRange(savedRanges[i]);
	    }
	}
	exports.generateClipboardEvent = generateClipboardEvent;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/clipboard/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/codemirror/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	__jupyter_require__('codemirror@^5.20.2/addon/edit/matchbrackets.js');
	__jupyter_require__('codemirror@^5.20.2/addon/edit/closebrackets.js');
	__jupyter_require__('codemirror@^5.20.2/addon/comment/comment.js');
	__jupyter_require__('codemirror@^5.20.2/keymap/vim.js');
	var menu_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/menu.js');
	var codeeditor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/index.js');
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var editorwidget_1 = __jupyter_require__('jupyterlab@0.15.1/lib/editorwidget/index.js');
	var mainmenu_1 = __jupyter_require__('jupyterlab@0.15.1/lib/mainmenu/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/codemirror/index.js');
	/**
	 * The editor services.
	 */
	exports.servicesPlugin = {
	    id: codeeditor_1.IEditorServices.name,
	    provides: codeeditor_1.IEditorServices,
	    activate: function () { return _1.editorServices; }
	};
	/**
	 * The editor commands.
	 */
	exports.commandsPlugin = {
	    id: 'jupyter.services.editor-commands',
	    requires: [editorwidget_1.IEditorTracker, mainmenu_1.IMainMenu, commandpalette_1.ICommandPalette],
	    activate: activateEditorCommands,
	    autoStart: true
	};
	/**
	 * Export the plugins as default.
	 */
	var plugins = [exports.commandsPlugin, exports.servicesPlugin];
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugins;
	/**
	 * The command IDs used by the editor plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.lineNumbers = 'editor:line-numbers';
	    CommandIDs.lineWrap = 'editor:line-wrap';
	    CommandIDs.matchBrackets = 'editor:match-brackets';
	    CommandIDs.vimMode = 'editor:vim-mode';
	    CommandIDs.changeTheme = 'editor:change-theme';
	    CommandIDs.createConsole = 'editor:create-console';
	    CommandIDs.runCode = 'editor:run-code';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	/**
	 * Set up the editor widget menu and commands.
	 */
	function activateEditorCommands(app, tracker, mainMenu, palette) {
	    var commands = app.commands, keymap = app.keymap;
	    /**
	     * Toggle editor matching brackets
	     */
	    function toggleMatchBrackets() {
	        if (tracker.currentWidget) {
	            var editor = tracker.currentWidget.editor;
	            if (editor instanceof _1.CodeMirrorEditor) {
	                var cm = editor.editor;
	                cm.setOption('matchBrackets', !cm.getOption('matchBrackets'));
	            }
	        }
	    }
	    /**
	     * Toggle the editor's vim mode
	     */
	    function toggleVim() {
	        tracker.forEach(function (widget) {
	            if (widget.editor instanceof _1.CodeMirrorEditor) {
	                var cm = widget.editor.editor;
	                var keymap_1 = cm.getOption('keyMap') === 'vim' ? 'default'
	                    : 'vim';
	                cm.setOption('keyMap', keymap_1);
	            }
	        });
	    }
	    /**
	     * Create a menu for the editor.
	     */
	    function createMenu() {
	        var settings = new menu_1.Menu({ commands: commands, keymap: keymap });
	        var theme = new menu_1.Menu({ commands: commands, keymap: keymap });
	        var menu = new menu_1.Menu({ commands: commands, keymap: keymap });
	        menu.title.label = 'Editor';
	        settings.title.label = 'Settings';
	        theme.title.label = 'Theme';
	        settings.addItem({ command: CommandIDs.lineNumbers });
	        settings.addItem({ command: CommandIDs.lineWrap });
	        settings.addItem({ command: CommandIDs.matchBrackets });
	        settings.addItem({ command: CommandIDs.vimMode });
	        commands.addCommand(CommandIDs.changeTheme, {
	            label: function (args) { return args['theme']; },
	            execute: function (args) {
	                var name = args['theme'] || _1.CodeMirrorEditor.DEFAULT_THEME;
	                tracker.forEach(function (widget) {
	                    if (widget.editor instanceof _1.CodeMirrorEditor) {
	                        var cm = widget.editor.editor;
	                        cm.setOption('theme', name);
	                    }
	                });
	            }
	        });
	        [
	            'jupyter', 'default', 'abcdef', 'base16-dark', 'base16-light',
	            'hopscotch', 'material', 'mbo', 'mdn-like', 'seti', 'the-matrix',
	            'xq-light', 'zenburn'
	        ].forEach(function (name) { return theme.addItem({
	            command: 'editor:change-theme',
	            args: { theme: name }
	        }); });
	        menu.addItem({ type: 'separator' });
	        menu.addItem({ type: 'submenu', menu: settings });
	        menu.addItem({ type: 'submenu', menu: theme });
	        return menu;
	    }
	    mainMenu.addMenu(createMenu(), { rank: 30 });
	    commands.addCommand(CommandIDs.matchBrackets, {
	        execute: function () { toggleMatchBrackets(); },
	        label: 'Toggle Match Brackets',
	    });
	    commands.addCommand(CommandIDs.vimMode, {
	        execute: function () { toggleVim(); },
	        label: 'Toggle Vim Mode'
	    });
	    [
	        CommandIDs.lineNumbers,
	        CommandIDs.lineWrap,
	        CommandIDs.matchBrackets,
	        CommandIDs.vimMode,
	        CommandIDs.createConsole,
	        CommandIDs.runCode
	    ].forEach(function (command) { return palette.addItem({ command: command, category: 'Editor' }); });
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/plugin.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/addon/edit/matchbrackets.js **/
jupyter.define('codemirror@5.23.0/addon/edit/matchbrackets.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
	    (document.documentMode == null || document.documentMode < 8);
	
	  var Pos = CodeMirror.Pos;
	
	  var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
	
	  function findMatchingBracket(cm, where, strict, config) {
	    var line = cm.getLineHandle(where.line), pos = where.ch - 1;
	    var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
	    if (!match) return null;
	    var dir = match.charAt(1) == ">" ? 1 : -1;
	    if (strict && (dir > 0) != (pos == where.ch)) return null;
	    var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
	
	    var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
	    if (found == null) return null;
	    return {from: Pos(where.line, pos), to: found && found.pos,
	            match: found && found.ch == match.charAt(0), forward: dir > 0};
	  }
	
	  // bracketRegex is used to specify which type of bracket to scan
	  // should be a regexp, e.g. /[[\]]/
	  //
	  // Note: If "where" is on an open bracket, then this bracket is ignored.
	  //
	  // Returns false when no bracket was found, null when it reached
	  // maxScanLines and gave up
	  function scanForBracket(cm, where, dir, style, config) {
	    var maxScanLen = (config && config.maxScanLineLength) || 10000;
	    var maxScanLines = (config && config.maxScanLines) || 1000;
	
	    var stack = [];
	    var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
	    var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
	                          : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
	    for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
	      var line = cm.getLine(lineNo);
	      if (!line) continue;
	      var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
	      if (line.length > maxScanLen) continue;
	      if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
	      for (; pos != end; pos += dir) {
	        var ch = line.charAt(pos);
	        if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
	          var match = matching[ch];
	          if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
	          else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
	          else stack.pop();
	        }
	      }
	    }
	    return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
	  }
	
	  function matchBrackets(cm, autoclear, config) {
	    // Disable brace matching in long lines, since it'll cause hugely slow updates
	    var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
	    var marks = [], ranges = cm.listSelections();
	    for (var i = 0; i < ranges.length; i++) {
	      var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config);
	      if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
	        var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
	        marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
	        if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
	          marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
	      }
	    }
	
	    if (marks.length) {
	      // Kludge to work around the IE bug from issue #1193, where text
	      // input stops going to the textare whever this fires.
	      if (ie_lt8 && cm.state.focused) cm.focus();
	
	      var clear = function() {
	        cm.operation(function() {
	          for (var i = 0; i < marks.length; i++) marks[i].clear();
	        });
	      };
	      if (autoclear) setTimeout(clear, 800);
	      else return clear;
	    }
	  }
	
	  var currentlyHighlighted = null;
	  function doMatchBrackets(cm) {
	    cm.operation(function() {
	      if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
	      currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
	    });
	  }
	
	  CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
	    if (old && old != CodeMirror.Init) {
	      cm.off("cursorActivity", doMatchBrackets);
	      if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
	    }
	    if (val) {
	      cm.state.matchBrackets = typeof val == "object" ? val : {};
	      cm.on("cursorActivity", doMatchBrackets);
	    }
	  });
	
	  CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
	  CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){
	    return findMatchingBracket(this, pos, strict, config);
	  });
	  CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
	    return scanForBracket(this, pos, dir, style, config);
	  });
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/addon/edit/matchbrackets.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/lib/codemirror.js **/
jupyter.define('codemirror@5.23.0/lib/codemirror.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	// This is CodeMirror (http://codemirror.net), a code editor
	// implemented in JavaScript on top of the browser's DOM.
	//
	// You can find some technical background for some of the code below
	// at http://marijnhaverbeke.nl/blog/#cm-internals .
	
	(function (global, factory) {
	   true ? module.exports = factory() :
	  typeof define === 'function' && define.amd ? define(factory) :
	  (global.CodeMirror = factory());
	}(this, (function () { 'use strict';
	
	// Kludges for bugs and behavior differences that can't be feature
	// detected are enabled based on userAgent etc sniffing.
	var userAgent = navigator.userAgent
	var platform = navigator.platform
	
	var gecko = /gecko\/\d/i.test(userAgent)
	var ie_upto10 = /MSIE \d/.test(userAgent)
	var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent)
	var ie = ie_upto10 || ie_11up
	var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1])
	var webkit = /WebKit\//.test(userAgent)
	var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent)
	var chrome = /Chrome\//.test(userAgent)
	var presto = /Opera\//.test(userAgent)
	var safari = /Apple Computer/.test(navigator.vendor)
	var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent)
	var phantom = /PhantomJS/.test(userAgent)
	
	var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent)
	// This is woefully incomplete. Suggestions for alternative methods welcome.
	var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent)
	var mac = ios || /Mac/.test(platform)
	var chromeOS = /\bCrOS\b/.test(userAgent)
	var windows = /win/i.test(platform)
	
	var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/)
	if (presto_version) { presto_version = Number(presto_version[1]) }
	if (presto_version && presto_version >= 15) { presto = false; webkit = true }
	// Some browsers use the wrong event properties to signal cmd/ctrl on OS X
	var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11))
	var captureRightClick = gecko || (ie && ie_version >= 9)
	
	function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
	
	var rmClass = function(node, cls) {
	  var current = node.className
	  var match = classTest(cls).exec(current)
	  if (match) {
	    var after = current.slice(match.index + match[0].length)
	    node.className = current.slice(0, match.index) + (after ? match[1] + after : "")
	  }
	}
	
	function removeChildren(e) {
	  for (var count = e.childNodes.length; count > 0; --count)
	    { e.removeChild(e.firstChild) }
	  return e
	}
	
	function removeChildrenAndAdd(parent, e) {
	  return removeChildren(parent).appendChild(e)
	}
	
	function elt(tag, content, className, style) {
	  var e = document.createElement(tag)
	  if (className) { e.className = className }
	  if (style) { e.style.cssText = style }
	  if (typeof content == "string") { e.appendChild(document.createTextNode(content)) }
	  else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]) } }
	  return e
	}
	
	var range
	if (document.createRange) { range = function(node, start, end, endNode) {
	  var r = document.createRange()
	  r.setEnd(endNode || node, end)
	  r.setStart(node, start)
	  return r
	} }
	else { range = function(node, start, end) {
	  var r = document.body.createTextRange()
	  try { r.moveToElementText(node.parentNode) }
	  catch(e) { return r }
	  r.collapse(true)
	  r.moveEnd("character", end)
	  r.moveStart("character", start)
	  return r
	} }
	
	function contains(parent, child) {
	  if (child.nodeType == 3) // Android browser always returns false when child is a textnode
	    { child = child.parentNode }
	  if (parent.contains)
	    { return parent.contains(child) }
	  do {
	    if (child.nodeType == 11) { child = child.host }
	    if (child == parent) { return true }
	  } while (child = child.parentNode)
	}
	
	function activeElt() {
	  // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement.
	  // IE < 10 will throw when accessed while the page is loading or in an iframe.
	  // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.
	  var activeElement
	  try {
	    activeElement = document.activeElement
	  } catch(e) {
	    activeElement = document.body || null
	  }
	  while (activeElement && activeElement.root && activeElement.root.activeElement)
	    { activeElement = activeElement.root.activeElement }
	  return activeElement
	}
	
	function addClass(node, cls) {
	  var current = node.className
	  if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls }
	}
	function joinClasses(a, b) {
	  var as = a.split(" ")
	  for (var i = 0; i < as.length; i++)
	    { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i] } }
	  return b
	}
	
	var selectInput = function(node) { node.select() }
	if (ios) // Mobile Safari apparently has a bug where select() is broken.
	  { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length } }
	else if (ie) // Suppress mysterious IE10 errors
	  { selectInput = function(node) { try { node.select() } catch(_e) {} } }
	
	function bind(f) {
	  var args = Array.prototype.slice.call(arguments, 1)
	  return function(){return f.apply(null, args)}
	}
	
	function copyObj(obj, target, overwrite) {
	  if (!target) { target = {} }
	  for (var prop in obj)
	    { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
	      { target[prop] = obj[prop] } }
	  return target
	}
	
	// Counts the column offset in a string, taking tabs into account.
	// Used mostly to find indentation.
	function countColumn(string, end, tabSize, startIndex, startValue) {
	  if (end == null) {
	    end = string.search(/[^\s\u00a0]/)
	    if (end == -1) { end = string.length }
	  }
	  for (var i = startIndex || 0, n = startValue || 0;;) {
	    var nextTab = string.indexOf("\t", i)
	    if (nextTab < 0 || nextTab >= end)
	      { return n + (end - i) }
	    n += nextTab - i
	    n += tabSize - (n % tabSize)
	    i = nextTab + 1
	  }
	}
	
	function Delayed() {this.id = null}
	Delayed.prototype.set = function(ms, f) {
	  clearTimeout(this.id)
	  this.id = setTimeout(f, ms)
	}
	
	function indexOf(array, elt) {
	  for (var i = 0; i < array.length; ++i)
	    { if (array[i] == elt) { return i } }
	  return -1
	}
	
	// Number of pixels added to scroller and sizer to hide scrollbar
	var scrollerGap = 30
	
	// Returned or thrown by various protocols to signal 'I'm not
	// handling this'.
	var Pass = {toString: function(){return "CodeMirror.Pass"}}
	
	// Reused option objects for setSelection & friends
	var sel_dontScroll = {scroll: false};
	var sel_mouse = {origin: "*mouse"};
	var sel_move = {origin: "+move"};
	// The inverse of countColumn -- find the offset that corresponds to
	// a particular column.
	function findColumn(string, goal, tabSize) {
	  for (var pos = 0, col = 0;;) {
	    var nextTab = string.indexOf("\t", pos)
	    if (nextTab == -1) { nextTab = string.length }
	    var skipped = nextTab - pos
	    if (nextTab == string.length || col + skipped >= goal)
	      { return pos + Math.min(skipped, goal - col) }
	    col += nextTab - pos
	    col += tabSize - (col % tabSize)
	    pos = nextTab + 1
	    if (col >= goal) { return pos }
	  }
	}
	
	var spaceStrs = [""]
	function spaceStr(n) {
	  while (spaceStrs.length <= n)
	    { spaceStrs.push(lst(spaceStrs) + " ") }
	  return spaceStrs[n]
	}
	
	function lst(arr) { return arr[arr.length-1] }
	
	function map(array, f) {
	  var out = []
	  for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i) }
	  return out
	}
	
	function insertSorted(array, value, score) {
	  var pos = 0, priority = score(value)
	  while (pos < array.length && score(array[pos]) <= priority) { pos++ }
	  array.splice(pos, 0, value)
	}
	
	function nothing() {}
	
	function createObj(base, props) {
	  var inst
	  if (Object.create) {
	    inst = Object.create(base)
	  } else {
	    nothing.prototype = base
	    inst = new nothing()
	  }
	  if (props) { copyObj(props, inst) }
	  return inst
	}
	
	var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/
	function isWordCharBasic(ch) {
	  return /\w/.test(ch) || ch > "\x80" &&
	    (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))
	}
	function isWordChar(ch, helper) {
	  if (!helper) { return isWordCharBasic(ch) }
	  if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true }
	  return helper.test(ch)
	}
	
	function isEmpty(obj) {
	  for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } }
	  return true
	}
	
	// Extending unicode characters. A series of a non-extending char +
	// any number of extending chars is treated as a single unit as far
	// as editing and measuring is concerned. This is not fully correct,
	// since some scripts/fonts/browsers also treat other configurations
	// of code points as a group.
	var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/
	function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) }
	
	// The display handles the DOM integration, both for input reading
	// and content drawing. It holds references to DOM nodes and
	// display-related state.
	
	function Display(place, doc, input) {
	  var d = this
	  this.input = input
	
	  // Covers bottom-right square when both scrollbars are present.
	  d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler")
	  d.scrollbarFiller.setAttribute("cm-not-content", "true")
	  // Covers bottom of gutter when coverGutterNextToScrollbar is on
	  // and h scrollbar is present.
	  d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler")
	  d.gutterFiller.setAttribute("cm-not-content", "true")
	  // Will contain the actual code, positioned to cover the viewport.
	  d.lineDiv = elt("div", null, "CodeMirror-code")
	  // Elements are added to these to represent selection and cursors.
	  d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1")
	  d.cursorDiv = elt("div", null, "CodeMirror-cursors")
	  // A visibility: hidden element used to find the size of things.
	  d.measure = elt("div", null, "CodeMirror-measure")
	  // When lines outside of the viewport are measured, they are drawn in this.
	  d.lineMeasure = elt("div", null, "CodeMirror-measure")
	  // Wraps everything that needs to exist inside the vertically-padded coordinate system
	  d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
	                    null, "position: relative; outline: none")
	  // Moved around its parent to cover visible view.
	  d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative")
	  // Set to the height of the document, allowing scrolling.
	  d.sizer = elt("div", [d.mover], "CodeMirror-sizer")
	  d.sizerWidth = null
	  // Behavior of elts with overflow: auto and padding is
	  // inconsistent across browsers. This is used to ensure the
	  // scrollable area is big enough.
	  d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;")
	  // Will contain the gutters, if any.
	  d.gutters = elt("div", null, "CodeMirror-gutters")
	  d.lineGutter = null
	  // Actual scrollable element.
	  d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll")
	  d.scroller.setAttribute("tabIndex", "-1")
	  // The element in which the editor lives.
	  d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror")
	
	  // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
	  if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0 }
	  if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true }
	
	  if (place) {
	    if (place.appendChild) { place.appendChild(d.wrapper) }
	    else { place(d.wrapper) }
	  }
	
	  // Current rendered range (may be bigger than the view window).
	  d.viewFrom = d.viewTo = doc.first
	  d.reportedViewFrom = d.reportedViewTo = doc.first
	  // Information about the rendered lines.
	  d.view = []
	  d.renderedView = null
	  // Holds info about a single rendered line when it was rendered
	  // for measurement, while not in view.
	  d.externalMeasured = null
	  // Empty space (in pixels) above the view
	  d.viewOffset = 0
	  d.lastWrapHeight = d.lastWrapWidth = 0
	  d.updateLineNumbers = null
	
	  d.nativeBarWidth = d.barHeight = d.barWidth = 0
	  d.scrollbarsClipped = false
	
	  // Used to only resize the line number gutter when necessary (when
	  // the amount of lines crosses a boundary that makes its width change)
	  d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null
	  // Set to true when a non-horizontal-scrolling line widget is
	  // added. As an optimization, line widget aligning is skipped when
	  // this is false.
	  d.alignWidgets = false
	
	  d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null
	
	  // Tracks the maximum line length so that the horizontal scrollbar
	  // can be kept static when scrolling.
	  d.maxLine = null
	  d.maxLineLength = 0
	  d.maxLineChanged = false
	
	  // Used for measuring wheel scrolling granularity
	  d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null
	
	  // True when shift is held down.
	  d.shift = false
	
	  // Used to track whether anything happened since the context menu
	  // was opened.
	  d.selForContextMenu = null
	
	  d.activeTouch = null
	
	  input.init(d)
	}
	
	// Find the line object corresponding to the given line number.
	function getLine(doc, n) {
	  n -= doc.first
	  if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") }
	  var chunk = doc
	  while (!chunk.lines) {
	    for (var i = 0;; ++i) {
	      var child = chunk.children[i], sz = child.chunkSize()
	      if (n < sz) { chunk = child; break }
	      n -= sz
	    }
	  }
	  return chunk.lines[n]
	}
	
	// Get the part of a document between two positions, as an array of
	// strings.
	function getBetween(doc, start, end) {
	  var out = [], n = start.line
	  doc.iter(start.line, end.line + 1, function (line) {
	    var text = line.text
	    if (n == end.line) { text = text.slice(0, end.ch) }
	    if (n == start.line) { text = text.slice(start.ch) }
	    out.push(text)
	    ++n
	  })
	  return out
	}
	// Get the lines between from and to, as array of strings.
	function getLines(doc, from, to) {
	  var out = []
	  doc.iter(from, to, function (line) { out.push(line.text) }) // iter aborts when callback returns truthy value
	  return out
	}
	
	// Update the height of a line, propagating the height change
	// upwards to parent nodes.
	function updateLineHeight(line, height) {
	  var diff = height - line.height
	  if (diff) { for (var n = line; n; n = n.parent) { n.height += diff } }
	}
	
	// Given a line object, find its line number by walking up through
	// its parent links.
	function lineNo(line) {
	  if (line.parent == null) { return null }
	  var cur = line.parent, no = indexOf(cur.lines, line)
	  for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
	    for (var i = 0;; ++i) {
	      if (chunk.children[i] == cur) { break }
	      no += chunk.children[i].chunkSize()
	    }
	  }
	  return no + cur.first
	}
	
	// Find the line at the given vertical position, using the height
	// information in the document tree.
	function lineAtHeight(chunk, h) {
	  var n = chunk.first
	  outer: do {
	    for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) {
	      var child = chunk.children[i$1], ch = child.height
	      if (h < ch) { chunk = child; continue outer }
	      h -= ch
	      n += child.chunkSize()
	    }
	    return n
	  } while (!chunk.lines)
	  var i = 0
	  for (; i < chunk.lines.length; ++i) {
	    var line = chunk.lines[i], lh = line.height
	    if (h < lh) { break }
	    h -= lh
	  }
	  return n + i
	}
	
	function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size}
	
	function lineNumberFor(options, i) {
	  return String(options.lineNumberFormatter(i + options.firstLineNumber))
	}
	
	// A Pos instance represents a position within the text.
	function Pos (line, ch) {
	  if (!(this instanceof Pos)) { return new Pos(line, ch) }
	  this.line = line; this.ch = ch
	}
	
	// Compare two positions, return 0 if they are the same, a negative
	// number when a is less, and a positive number otherwise.
	function cmp(a, b) { return a.line - b.line || a.ch - b.ch }
	
	function copyPos(x) {return Pos(x.line, x.ch)}
	function maxPos(a, b) { return cmp(a, b) < 0 ? b : a }
	function minPos(a, b) { return cmp(a, b) < 0 ? a : b }
	
	// Most of the external API clips given positions to make sure they
	// actually exist within the document.
	function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))}
	function clipPos(doc, pos) {
	  if (pos.line < doc.first) { return Pos(doc.first, 0) }
	  var last = doc.first + doc.size - 1
	  if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) }
	  return clipToLen(pos, getLine(doc, pos.line).text.length)
	}
	function clipToLen(pos, linelen) {
	  var ch = pos.ch
	  if (ch == null || ch > linelen) { return Pos(pos.line, linelen) }
	  else if (ch < 0) { return Pos(pos.line, 0) }
	  else { return pos }
	}
	function clipPosArray(doc, array) {
	  var out = []
	  for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]) }
	  return out
	}
	
	// Optimize some code when these features are not used.
	var sawReadOnlySpans = false;
	var sawCollapsedSpans = false;
	function seeReadOnlySpans() {
	  sawReadOnlySpans = true
	}
	
	function seeCollapsedSpans() {
	  sawCollapsedSpans = true
	}
	
	// TEXTMARKER SPANS
	
	function MarkedSpan(marker, from, to) {
	  this.marker = marker
	  this.from = from; this.to = to
	}
	
	// Search an array of spans for a span matching the given marker.
	function getMarkedSpanFor(spans, marker) {
	  if (spans) { for (var i = 0; i < spans.length; ++i) {
	    var span = spans[i]
	    if (span.marker == marker) { return span }
	  } }
	}
	// Remove a span from an array, returning undefined if no spans are
	// left (we don't store arrays for lines without spans).
	function removeMarkedSpan(spans, span) {
	  var r
	  for (var i = 0; i < spans.length; ++i)
	    { if (spans[i] != span) { (r || (r = [])).push(spans[i]) } }
	  return r
	}
	// Add a span to a line.
	function addMarkedSpan(line, span) {
	  line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]
	  span.marker.attachLine(line)
	}
	
	// Used for the algorithm that adjusts markers for a change in the
	// document. These functions cut an array of spans at a given
	// character position, returning an array of remaining chunks (or
	// undefined if nothing remains).
	function markedSpansBefore(old, startCh, isInsert) {
	  var nw
	  if (old) { for (var i = 0; i < old.length; ++i) {
	    var span = old[i], marker = span.marker
	    var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh)
	    if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
	      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh)
	      ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to))
	    }
	  } }
	  return nw
	}
	function markedSpansAfter(old, endCh, isInsert) {
	  var nw
	  if (old) { for (var i = 0; i < old.length; ++i) {
	    var span = old[i], marker = span.marker
	    var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh)
	    if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
	      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh)
	      ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
	                                            span.to == null ? null : span.to - endCh))
	    }
	  } }
	  return nw
	}
	
	// Given a change object, compute the new set of marker spans that
	// cover the line in which the change took place. Removes spans
	// entirely within the change, reconnects spans belonging to the
	// same marker that appear on both sides of the change, and cuts off
	// spans partially within the change. Returns an array of span
	// arrays with one element for each line in (after) the change.
	function stretchSpansOverChange(doc, change) {
	  if (change.full) { return null }
	  var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans
	  var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans
	  if (!oldFirst && !oldLast) { return null }
	
	  var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0
	  // Get the spans that 'stick out' on both sides
	  var first = markedSpansBefore(oldFirst, startCh, isInsert)
	  var last = markedSpansAfter(oldLast, endCh, isInsert)
	
	  // Next, merge those two ends
	  var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0)
	  if (first) {
	    // Fix up .to properties of first
	    for (var i = 0; i < first.length; ++i) {
	      var span = first[i]
	      if (span.to == null) {
	        var found = getMarkedSpanFor(last, span.marker)
	        if (!found) { span.to = startCh }
	        else if (sameLine) { span.to = found.to == null ? null : found.to + offset }
	      }
	    }
	  }
	  if (last) {
	    // Fix up .from in last (or move them into first in case of sameLine)
	    for (var i$1 = 0; i$1 < last.length; ++i$1) {
	      var span$1 = last[i$1]
	      if (span$1.to != null) { span$1.to += offset }
	      if (span$1.from == null) {
	        var found$1 = getMarkedSpanFor(first, span$1.marker)
	        if (!found$1) {
	          span$1.from = offset
	          if (sameLine) { (first || (first = [])).push(span$1) }
	        }
	      } else {
	        span$1.from += offset
	        if (sameLine) { (first || (first = [])).push(span$1) }
	      }
	    }
	  }
	  // Make sure we didn't create any zero-length spans
	  if (first) { first = clearEmptySpans(first) }
	  if (last && last != first) { last = clearEmptySpans(last) }
	
	  var newMarkers = [first]
	  if (!sameLine) {
	    // Fill gap with whole-line-spans
	    var gap = change.text.length - 2, gapMarkers
	    if (gap > 0 && first)
	      { for (var i$2 = 0; i$2 < first.length; ++i$2)
	        { if (first[i$2].to == null)
	          { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)) } } }
	    for (var i$3 = 0; i$3 < gap; ++i$3)
	      { newMarkers.push(gapMarkers) }
	    newMarkers.push(last)
	  }
	  return newMarkers
	}
	
	// Remove spans that are empty and don't have a clearWhenEmpty
	// option of false.
	function clearEmptySpans(spans) {
	  for (var i = 0; i < spans.length; ++i) {
	    var span = spans[i]
	    if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
	      { spans.splice(i--, 1) }
	  }
	  if (!spans.length) { return null }
	  return spans
	}
	
	// Used to 'clip' out readOnly ranges when making a change.
	function removeReadOnlyRanges(doc, from, to) {
	  var markers = null
	  doc.iter(from.line, to.line + 1, function (line) {
	    if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
	      var mark = line.markedSpans[i].marker
	      if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
	        { (markers || (markers = [])).push(mark) }
	    } }
	  })
	  if (!markers) { return null }
	  var parts = [{from: from, to: to}]
	  for (var i = 0; i < markers.length; ++i) {
	    var mk = markers[i], m = mk.find(0)
	    for (var j = 0; j < parts.length; ++j) {
	      var p = parts[j]
	      if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue }
	      var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to)
	      if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
	        { newParts.push({from: p.from, to: m.from}) }
	      if (dto > 0 || !mk.inclusiveRight && !dto)
	        { newParts.push({from: m.to, to: p.to}) }
	      parts.splice.apply(parts, newParts)
	      j += newParts.length - 1
	    }
	  }
	  return parts
	}
	
	// Connect or disconnect spans from a line.
	function detachMarkedSpans(line) {
	  var spans = line.markedSpans
	  if (!spans) { return }
	  for (var i = 0; i < spans.length; ++i)
	    { spans[i].marker.detachLine(line) }
	  line.markedSpans = null
	}
	function attachMarkedSpans(line, spans) {
	  if (!spans) { return }
	  for (var i = 0; i < spans.length; ++i)
	    { spans[i].marker.attachLine(line) }
	  line.markedSpans = spans
	}
	
	// Helpers used when computing which overlapping collapsed span
	// counts as the larger one.
	function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 }
	function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 }
	
	// Returns a number indicating which of two overlapping collapsed
	// spans is larger (and thus includes the other). Falls back to
	// comparing ids when the spans cover exactly the same range.
	function compareCollapsedMarkers(a, b) {
	  var lenDiff = a.lines.length - b.lines.length
	  if (lenDiff != 0) { return lenDiff }
	  var aPos = a.find(), bPos = b.find()
	  var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b)
	  if (fromCmp) { return -fromCmp }
	  var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b)
	  if (toCmp) { return toCmp }
	  return b.id - a.id
	}
	
	// Find out whether a line ends or starts in a collapsed span. If
	// so, return the marker for that span.
	function collapsedSpanAtSide(line, start) {
	  var sps = sawCollapsedSpans && line.markedSpans, found
	  if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
	    sp = sps[i]
	    if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
	        (!found || compareCollapsedMarkers(found, sp.marker) < 0))
	      { found = sp.marker }
	  } }
	  return found
	}
	function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) }
	function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) }
	
	// Test whether there exists a collapsed span that partially
	// overlaps (covers the start or end, but not both) of a new span.
	// Such overlap is not allowed.
	function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
	  var line = getLine(doc, lineNo)
	  var sps = sawCollapsedSpans && line.markedSpans
	  if (sps) { for (var i = 0; i < sps.length; ++i) {
	    var sp = sps[i]
	    if (!sp.marker.collapsed) { continue }
	    var found = sp.marker.find(0)
	    var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker)
	    var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker)
	    if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue }
	    if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) ||
	        fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0))
	      { return true }
	  } }
	}
	
	// A visual line is a line as drawn on the screen. Folding, for
	// example, can cause multiple logical lines to appear on the same
	// visual line. This finds the start of the visual line that the
	// given line is part of (usually that is the line itself).
	function visualLine(line) {
	  var merged
	  while (merged = collapsedSpanAtStart(line))
	    { line = merged.find(-1, true).line }
	  return line
	}
	
	// Returns an array of logical lines that continue the visual line
	// started by the argument, or undefined if there are no such lines.
	function visualLineContinued(line) {
	  var merged, lines
	  while (merged = collapsedSpanAtEnd(line)) {
	    line = merged.find(1, true).line
	    ;(lines || (lines = [])).push(line)
	  }
	  return lines
	}
	
	// Get the line number of the start of the visual line that the
	// given line number is part of.
	function visualLineNo(doc, lineN) {
	  var line = getLine(doc, lineN), vis = visualLine(line)
	  if (line == vis) { return lineN }
	  return lineNo(vis)
	}
	
	// Get the line number of the start of the next visual line after
	// the given line.
	function visualLineEndNo(doc, lineN) {
	  if (lineN > doc.lastLine()) { return lineN }
	  var line = getLine(doc, lineN), merged
	  if (!lineIsHidden(doc, line)) { return lineN }
	  while (merged = collapsedSpanAtEnd(line))
	    { line = merged.find(1, true).line }
	  return lineNo(line) + 1
	}
	
	// Compute whether a line is hidden. Lines count as hidden when they
	// are part of a visual line that starts with another line, or when
	// they are entirely covered by collapsed, non-widget span.
	function lineIsHidden(doc, line) {
	  var sps = sawCollapsedSpans && line.markedSpans
	  if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
	    sp = sps[i]
	    if (!sp.marker.collapsed) { continue }
	    if (sp.from == null) { return true }
	    if (sp.marker.widgetNode) { continue }
	    if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
	      { return true }
	  } }
	}
	function lineIsHiddenInner(doc, line, span) {
	  if (span.to == null) {
	    var end = span.marker.find(1, true)
	    return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker))
	  }
	  if (span.marker.inclusiveRight && span.to == line.text.length)
	    { return true }
	  for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) {
	    sp = line.markedSpans[i]
	    if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
	        (sp.to == null || sp.to != span.from) &&
	        (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
	        lineIsHiddenInner(doc, line, sp)) { return true }
	  }
	}
	
	// Find the height above the given line.
	function heightAtLine(lineObj) {
	  lineObj = visualLine(lineObj)
	
	  var h = 0, chunk = lineObj.parent
	  for (var i = 0; i < chunk.lines.length; ++i) {
	    var line = chunk.lines[i]
	    if (line == lineObj) { break }
	    else { h += line.height }
	  }
	  for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
	    for (var i$1 = 0; i$1 < p.children.length; ++i$1) {
	      var cur = p.children[i$1]
	      if (cur == chunk) { break }
	      else { h += cur.height }
	    }
	  }
	  return h
	}
	
	// Compute the character length of a line, taking into account
	// collapsed ranges (see markText) that might hide parts, and join
	// other lines onto it.
	function lineLength(line) {
	  if (line.height == 0) { return 0 }
	  var len = line.text.length, merged, cur = line
	  while (merged = collapsedSpanAtStart(cur)) {
	    var found = merged.find(0, true)
	    cur = found.from.line
	    len += found.from.ch - found.to.ch
	  }
	  cur = line
	  while (merged = collapsedSpanAtEnd(cur)) {
	    var found$1 = merged.find(0, true)
	    len -= cur.text.length - found$1.from.ch
	    cur = found$1.to.line
	    len += cur.text.length - found$1.to.ch
	  }
	  return len
	}
	
	// Find the longest line in the document.
	function findMaxLine(cm) {
	  var d = cm.display, doc = cm.doc
	  d.maxLine = getLine(doc, doc.first)
	  d.maxLineLength = lineLength(d.maxLine)
	  d.maxLineChanged = true
	  doc.iter(function (line) {
	    var len = lineLength(line)
	    if (len > d.maxLineLength) {
	      d.maxLineLength = len
	      d.maxLine = line
	    }
	  })
	}
	
	// BIDI HELPERS
	
	function iterateBidiSections(order, from, to, f) {
	  if (!order) { return f(from, to, "ltr") }
	  var found = false
	  for (var i = 0; i < order.length; ++i) {
	    var part = order[i]
	    if (part.from < to && part.to > from || from == to && part.to == from) {
	      f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr")
	      found = true
	    }
	  }
	  if (!found) { f(from, to, "ltr") }
	}
	
	function bidiLeft(part) { return part.level % 2 ? part.to : part.from }
	function bidiRight(part) { return part.level % 2 ? part.from : part.to }
	
	function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0 }
	function lineRight(line) {
	  var order = getOrder(line)
	  if (!order) { return line.text.length }
	  return bidiRight(lst(order))
	}
	
	function compareBidiLevel(order, a, b) {
	  var linedir = order[0].level
	  if (a == linedir) { return true }
	  if (b == linedir) { return false }
	  return a < b
	}
	
	var bidiOther = null
	function getBidiPartAt(order, pos) {
	  var found
	  bidiOther = null
	  for (var i = 0; i < order.length; ++i) {
	    var cur = order[i]
	    if (cur.from < pos && cur.to > pos) { return i }
	    if ((cur.from == pos || cur.to == pos)) {
	      if (found == null) {
	        found = i
	      } else if (compareBidiLevel(order, cur.level, order[found].level)) {
	        if (cur.from != cur.to) { bidiOther = found }
	        return i
	      } else {
	        if (cur.from != cur.to) { bidiOther = i }
	        return found
	      }
	    }
	  }
	  return found
	}
	
	function moveInLine(line, pos, dir, byUnit) {
	  if (!byUnit) { return pos + dir }
	  do { pos += dir }
	  while (pos > 0 && isExtendingChar(line.text.charAt(pos)))
	  return pos
	}
	
	// This is needed in order to move 'visually' through bi-directional
	// text -- i.e., pressing left should make the cursor go left, even
	// when in RTL text. The tricky part is the 'jumps', where RTL and
	// LTR text touch each other. This often requires the cursor offset
	// to move more than one unit, in order to visually move one unit.
	function moveVisually(line, start, dir, byUnit) {
	  var bidi = getOrder(line)
	  if (!bidi) { return moveLogically(line, start, dir, byUnit) }
	  var pos = getBidiPartAt(bidi, start), part = bidi[pos]
	  var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit)
	
	  for (;;) {
	    if (target > part.from && target < part.to) { return target }
	    if (target == part.from || target == part.to) {
	      if (getBidiPartAt(bidi, target) == pos) { return target }
	      part = bidi[pos += dir]
	      return (dir > 0) == part.level % 2 ? part.to : part.from
	    } else {
	      part = bidi[pos += dir]
	      if (!part) { return null }
	      if ((dir > 0) == part.level % 2)
	        { target = moveInLine(line, part.to, -1, byUnit) }
	      else
	        { target = moveInLine(line, part.from, 1, byUnit) }
	    }
	  }
	}
	
	function moveLogically(line, start, dir, byUnit) {
	  var target = start + dir
	  if (byUnit) { while (target > 0 && isExtendingChar(line.text.charAt(target))) { target += dir } }
	  return target < 0 || target > line.text.length ? null : target
	}
	
	// Bidirectional ordering algorithm
	// See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
	// that this (partially) implements.
	
	// One-char codes used for character types:
	// L (L):   Left-to-Right
	// R (R):   Right-to-Left
	// r (AL):  Right-to-Left Arabic
	// 1 (EN):  European Number
	// + (ES):  European Number Separator
	// % (ET):  European Number Terminator
	// n (AN):  Arabic Number
	// , (CS):  Common Number Separator
	// m (NSM): Non-Spacing Mark
	// b (BN):  Boundary Neutral
	// s (B):   Paragraph Separator
	// t (S):   Segment Separator
	// w (WS):  Whitespace
	// N (ON):  Other Neutrals
	
	// Returns null if characters are ordered as they appear
	// (left-to-right), or an array of sections ({from, to, level}
	// objects) in the order in which they occur visually.
	var bidiOrdering = (function() {
	  // Character types for codepoints 0 to 0xff
	  var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"
	  // Character types for codepoints 0x600 to 0x6f9
	  var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"
	  function charType(code) {
	    if (code <= 0xf7) { return lowTypes.charAt(code) }
	    else if (0x590 <= code && code <= 0x5f4) { return "R" }
	    else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) }
	    else if (0x6ee <= code && code <= 0x8ac) { return "r" }
	    else if (0x2000 <= code && code <= 0x200b) { return "w" }
	    else if (code == 0x200c) { return "b" }
	    else { return "L" }
	  }
	
	  var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/
	  var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/
	  // Browsers seem to always treat the boundaries of block elements as being L.
	  var outerType = "L"
	
	  function BidiSpan(level, from, to) {
	    this.level = level
	    this.from = from; this.to = to
	  }
	
	  return function(str) {
	    if (!bidiRE.test(str)) { return false }
	    var len = str.length, types = []
	    for (var i = 0; i < len; ++i)
	      { types.push(charType(str.charCodeAt(i))) }
	
	    // W1. Examine each non-spacing mark (NSM) in the level run, and
	    // change the type of the NSM to the type of the previous
	    // character. If the NSM is at the start of the level run, it will
	    // get the type of sor.
	    for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) {
	      var type = types[i$1]
	      if (type == "m") { types[i$1] = prev }
	      else { prev = type }
	    }
	
	    // W2. Search backwards from each instance of a European number
	    // until the first strong type (R, L, AL, or sor) is found. If an
	    // AL is found, change the type of the European number to Arabic
	    // number.
	    // W3. Change all ALs to R.
	    for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) {
	      var type$1 = types[i$2]
	      if (type$1 == "1" && cur == "r") { types[i$2] = "n" }
	      else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R" } }
	    }
	
	    // W4. A single European separator between two European numbers
	    // changes to a European number. A single common separator between
	    // two numbers of the same type changes to that type.
	    for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) {
	      var type$2 = types[i$3]
	      if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1" }
	      else if (type$2 == "," && prev$1 == types[i$3+1] &&
	               (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1 }
	      prev$1 = type$2
	    }
	
	    // W5. A sequence of European terminators adjacent to European
	    // numbers changes to all European numbers.
	    // W6. Otherwise, separators and terminators change to Other
	    // Neutral.
	    for (var i$4 = 0; i$4 < len; ++i$4) {
	      var type$3 = types[i$4]
	      if (type$3 == ",") { types[i$4] = "N" }
	      else if (type$3 == "%") {
	        var end = (void 0)
	        for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {}
	        var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"
	        for (var j = i$4; j < end; ++j) { types[j] = replace }
	        i$4 = end - 1
	      }
	    }
	
	    // W7. Search backwards from each instance of a European number
	    // until the first strong type (R, L, or sor) is found. If an L is
	    // found, then change the type of the European number to L.
	    for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) {
	      var type$4 = types[i$5]
	      if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L" }
	      else if (isStrong.test(type$4)) { cur$1 = type$4 }
	    }
	
	    // N1. A sequence of neutrals takes the direction of the
	    // surrounding strong text if the text on both sides has the same
	    // direction. European and Arabic numbers act as if they were R in
	    // terms of their influence on neutrals. Start-of-level-run (sor)
	    // and end-of-level-run (eor) are used at level run boundaries.
	    // N2. Any remaining neutrals take the embedding direction.
	    for (var i$6 = 0; i$6 < len; ++i$6) {
	      if (isNeutral.test(types[i$6])) {
	        var end$1 = (void 0)
	        for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {}
	        var before = (i$6 ? types[i$6-1] : outerType) == "L"
	        var after = (end$1 < len ? types[end$1] : outerType) == "L"
	        var replace$1 = before || after ? "L" : "R"
	        for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1 }
	        i$6 = end$1 - 1
	      }
	    }
	
	    // Here we depart from the documented algorithm, in order to avoid
	    // building up an actual levels array. Since there are only three
	    // levels (0, 1, 2) in an implementation that doesn't take
	    // explicit embedding into account, we can build up the order on
	    // the fly, without following the level-based algorithm.
	    var order = [], m
	    for (var i$7 = 0; i$7 < len;) {
	      if (countsAsLeft.test(types[i$7])) {
	        var start = i$7
	        for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {}
	        order.push(new BidiSpan(0, start, i$7))
	      } else {
	        var pos = i$7, at = order.length
	        for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {}
	        for (var j$2 = pos; j$2 < i$7;) {
	          if (countsAsNum.test(types[j$2])) {
	            if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)) }
	            var nstart = j$2
	            for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {}
	            order.splice(at, 0, new BidiSpan(2, nstart, j$2))
	            pos = j$2
	          } else { ++j$2 }
	        }
	        if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)) }
	      }
	    }
	    if (order[0].level == 1 && (m = str.match(/^\s+/))) {
	      order[0].from = m[0].length
	      order.unshift(new BidiSpan(0, 0, m[0].length))
	    }
	    if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
	      lst(order).to -= m[0].length
	      order.push(new BidiSpan(0, len - m[0].length, len))
	    }
	    if (order[0].level == 2)
	      { order.unshift(new BidiSpan(1, order[0].to, order[0].to)) }
	    if (order[0].level != lst(order).level)
	      { order.push(new BidiSpan(order[0].level, len, len)) }
	
	    return order
	  }
	})()
	
	// Get the bidi ordering for the given line (and cache it). Returns
	// false for lines that are fully left-to-right, and an array of
	// BidiSpan objects otherwise.
	function getOrder(line) {
	  var order = line.order
	  if (order == null) { order = line.order = bidiOrdering(line.text) }
	  return order
	}
	
	// EVENT HANDLING
	
	// Lightweight event framework. on/off also work on DOM nodes,
	// registering native DOM handlers.
	
	var noHandlers = []
	
	var on = function(emitter, type, f) {
	  if (emitter.addEventListener) {
	    emitter.addEventListener(type, f, false)
	  } else if (emitter.attachEvent) {
	    emitter.attachEvent("on" + type, f)
	  } else {
	    var map = emitter._handlers || (emitter._handlers = {})
	    map[type] = (map[type] || noHandlers).concat(f)
	  }
	}
	
	function getHandlers(emitter, type) {
	  return emitter._handlers && emitter._handlers[type] || noHandlers
	}
	
	function off(emitter, type, f) {
	  if (emitter.removeEventListener) {
	    emitter.removeEventListener(type, f, false)
	  } else if (emitter.detachEvent) {
	    emitter.detachEvent("on" + type, f)
	  } else {
	    var map = emitter._handlers, arr = map && map[type]
	    if (arr) {
	      var index = indexOf(arr, f)
	      if (index > -1)
	        { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)) }
	    }
	  }
	}
	
	function signal(emitter, type /*, values...*/) {
	  var handlers = getHandlers(emitter, type)
	  if (!handlers.length) { return }
	  var args = Array.prototype.slice.call(arguments, 2)
	  for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args) }
	}
	
	// The DOM events that CodeMirror handles can be overridden by
	// registering a (non-DOM) handler on the editor for the event name,
	// and preventDefault-ing the event in that handler.
	function signalDOMEvent(cm, e, override) {
	  if (typeof e == "string")
	    { e = {type: e, preventDefault: function() { this.defaultPrevented = true }} }
	  signal(cm, override || e.type, cm, e)
	  return e_defaultPrevented(e) || e.codemirrorIgnore
	}
	
	function signalCursorActivity(cm) {
	  var arr = cm._handlers && cm._handlers.cursorActivity
	  if (!arr) { return }
	  var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = [])
	  for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1)
	    { set.push(arr[i]) } }
	}
	
	function hasHandler(emitter, type) {
	  return getHandlers(emitter, type).length > 0
	}
	
	// Add on and off methods to a constructor's prototype, to make
	// registering events on such objects more convenient.
	function eventMixin(ctor) {
	  ctor.prototype.on = function(type, f) {on(this, type, f)}
	  ctor.prototype.off = function(type, f) {off(this, type, f)}
	}
	
	// Due to the fact that we still support jurassic IE versions, some
	// compatibility wrappers are needed.
	
	function e_preventDefault(e) {
	  if (e.preventDefault) { e.preventDefault() }
	  else { e.returnValue = false }
	}
	function e_stopPropagation(e) {
	  if (e.stopPropagation) { e.stopPropagation() }
	  else { e.cancelBubble = true }
	}
	function e_defaultPrevented(e) {
	  return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false
	}
	function e_stop(e) {e_preventDefault(e); e_stopPropagation(e)}
	
	function e_target(e) {return e.target || e.srcElement}
	function e_button(e) {
	  var b = e.which
	  if (b == null) {
	    if (e.button & 1) { b = 1 }
	    else if (e.button & 2) { b = 3 }
	    else if (e.button & 4) { b = 2 }
	  }
	  if (mac && e.ctrlKey && b == 1) { b = 3 }
	  return b
	}
	
	// Detect drag-and-drop
	var dragAndDrop = function() {
	  // There is *some* kind of drag-and-drop support in IE6-8, but I
	  // couldn't get it to work yet.
	  if (ie && ie_version < 9) { return false }
	  var div = elt('div')
	  return "draggable" in div || "dragDrop" in div
	}()
	
	var zwspSupported
	function zeroWidthElement(measure) {
	  if (zwspSupported == null) {
	    var test = elt("span", "\u200b")
	    removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]))
	    if (measure.firstChild.offsetHeight != 0)
	      { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8) }
	  }
	  var node = zwspSupported ? elt("span", "\u200b") :
	    elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px")
	  node.setAttribute("cm-text", "")
	  return node
	}
	
	// Feature-detect IE's crummy client rect reporting for bidi text
	var badBidiRects
	function hasBadBidiRects(measure) {
	  if (badBidiRects != null) { return badBidiRects }
	  var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"))
	  var r0 = range(txt, 0, 1).getBoundingClientRect()
	  var r1 = range(txt, 1, 2).getBoundingClientRect()
	  removeChildren(measure)
	  if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780)
	  return badBidiRects = (r1.right - r0.right < 3)
	}
	
	// See if "".split is the broken IE version, if so, provide an
	// alternative way to split lines.
	var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) {
	  var pos = 0, result = [], l = string.length
	  while (pos <= l) {
	    var nl = string.indexOf("\n", pos)
	    if (nl == -1) { nl = string.length }
	    var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl)
	    var rt = line.indexOf("\r")
	    if (rt != -1) {
	      result.push(line.slice(0, rt))
	      pos += rt + 1
	    } else {
	      result.push(line)
	      pos = nl + 1
	    }
	  }
	  return result
	} : function (string) { return string.split(/\r\n?|\n/); }
	
	var hasSelection = window.getSelection ? function (te) {
	  try { return te.selectionStart != te.selectionEnd }
	  catch(e) { return false }
	} : function (te) {
	  var range
	  try {range = te.ownerDocument.selection.createRange()}
	  catch(e) {}
	  if (!range || range.parentElement() != te) { return false }
	  return range.compareEndPoints("StartToEnd", range) != 0
	}
	
	var hasCopyEvent = (function () {
	  var e = elt("div")
	  if ("oncopy" in e) { return true }
	  e.setAttribute("oncopy", "return;")
	  return typeof e.oncopy == "function"
	})()
	
	var badZoomedRects = null
	function hasBadZoomedRects(measure) {
	  if (badZoomedRects != null) { return badZoomedRects }
	  var node = removeChildrenAndAdd(measure, elt("span", "x"))
	  var normal = node.getBoundingClientRect()
	  var fromRange = range(node, 0, 1).getBoundingClientRect()
	  return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1
	}
	
	var modes = {};
	var mimeModes = {};
	// Extra arguments are stored as the mode's dependencies, which is
	// used by (legacy) mechanisms like loadmode.js to automatically
	// load a mode. (Preferred mechanism is the require/define calls.)
	function defineMode(name, mode) {
	  if (arguments.length > 2)
	    { mode.dependencies = Array.prototype.slice.call(arguments, 2) }
	  modes[name] = mode
	}
	
	function defineMIME(mime, spec) {
	  mimeModes[mime] = spec
	}
	
	// Given a MIME type, a {name, ...options} config object, or a name
	// string, return a mode config object.
	function resolveMode(spec) {
	  if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
	    spec = mimeModes[spec]
	  } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
	    var found = mimeModes[spec.name]
	    if (typeof found == "string") { found = {name: found} }
	    spec = createObj(found, spec)
	    spec.name = found.name
	  } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
	    return resolveMode("application/xml")
	  } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
	    return resolveMode("application/json")
	  }
	  if (typeof spec == "string") { return {name: spec} }
	  else { return spec || {name: "null"} }
	}
	
	// Given a mode spec (anything that resolveMode accepts), find and
	// initialize an actual mode object.
	function getMode(options, spec) {
	  spec = resolveMode(spec)
	  var mfactory = modes[spec.name]
	  if (!mfactory) { return getMode(options, "text/plain") }
	  var modeObj = mfactory(options, spec)
	  if (modeExtensions.hasOwnProperty(spec.name)) {
	    var exts = modeExtensions[spec.name]
	    for (var prop in exts) {
	      if (!exts.hasOwnProperty(prop)) { continue }
	      if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop] }
	      modeObj[prop] = exts[prop]
	    }
	  }
	  modeObj.name = spec.name
	  if (spec.helperType) { modeObj.helperType = spec.helperType }
	  if (spec.modeProps) { for (var prop$1 in spec.modeProps)
	    { modeObj[prop$1] = spec.modeProps[prop$1] } }
	
	  return modeObj
	}
	
	// This can be used to attach properties to mode objects from
	// outside the actual mode definition.
	var modeExtensions = {}
	function extendMode(mode, properties) {
	  var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {})
	  copyObj(properties, exts)
	}
	
	function copyState(mode, state) {
	  if (state === true) { return state }
	  if (mode.copyState) { return mode.copyState(state) }
	  var nstate = {}
	  for (var n in state) {
	    var val = state[n]
	    if (val instanceof Array) { val = val.concat([]) }
	    nstate[n] = val
	  }
	  return nstate
	}
	
	// Given a mode and a state (for that mode), find the inner mode and
	// state at the position that the state refers to.
	function innerMode(mode, state) {
	  var info
	  while (mode.innerMode) {
	    info = mode.innerMode(state)
	    if (!info || info.mode == mode) { break }
	    state = info.state
	    mode = info.mode
	  }
	  return info || {mode: mode, state: state}
	}
	
	function startState(mode, a1, a2) {
	  return mode.startState ? mode.startState(a1, a2) : true
	}
	
	// STRING STREAM
	
	// Fed to the mode parsers, provides helper functions to make
	// parsers more succinct.
	
	var StringStream = function(string, tabSize) {
	  this.pos = this.start = 0
	  this.string = string
	  this.tabSize = tabSize || 8
	  this.lastColumnPos = this.lastColumnValue = 0
	  this.lineStart = 0
	}
	
	StringStream.prototype = {
	  eol: function() {return this.pos >= this.string.length},
	  sol: function() {return this.pos == this.lineStart},
	  peek: function() {return this.string.charAt(this.pos) || undefined},
	  next: function() {
	    if (this.pos < this.string.length)
	      { return this.string.charAt(this.pos++) }
	  },
	  eat: function(match) {
	    var ch = this.string.charAt(this.pos)
	    var ok
	    if (typeof match == "string") { ok = ch == match }
	    else { ok = ch && (match.test ? match.test(ch) : match(ch)) }
	    if (ok) {++this.pos; return ch}
	  },
	  eatWhile: function(match) {
	    var start = this.pos
	    while (this.eat(match)){}
	    return this.pos > start
	  },
	  eatSpace: function() {
	    var this$1 = this;
	
	    var start = this.pos
	    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos }
	    return this.pos > start
	  },
	  skipToEnd: function() {this.pos = this.string.length},
	  skipTo: function(ch) {
	    var found = this.string.indexOf(ch, this.pos)
	    if (found > -1) {this.pos = found; return true}
	  },
	  backUp: function(n) {this.pos -= n},
	  column: function() {
	    if (this.lastColumnPos < this.start) {
	      this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue)
	      this.lastColumnPos = this.start
	    }
	    return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
	  },
	  indentation: function() {
	    return countColumn(this.string, null, this.tabSize) -
	      (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
	  },
	  match: function(pattern, consume, caseInsensitive) {
	    if (typeof pattern == "string") {
	      var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; }
	      var substr = this.string.substr(this.pos, pattern.length)
	      if (cased(substr) == cased(pattern)) {
	        if (consume !== false) { this.pos += pattern.length }
	        return true
	      }
	    } else {
	      var match = this.string.slice(this.pos).match(pattern)
	      if (match && match.index > 0) { return null }
	      if (match && consume !== false) { this.pos += match[0].length }
	      return match
	    }
	  },
	  current: function(){return this.string.slice(this.start, this.pos)},
	  hideFirstChars: function(n, inner) {
	    this.lineStart += n
	    try { return inner() }
	    finally { this.lineStart -= n }
	  }
	}
	
	// Compute a style array (an array starting with a mode generation
	// -- for invalidation -- followed by pairs of end positions and
	// style strings), which is used to highlight the tokens on the
	// line.
	function highlightLine(cm, line, state, forceToEnd) {
	  // A styles array always starts with a number identifying the
	  // mode/overlays that it is based on (for easy invalidation).
	  var st = [cm.state.modeGen], lineClasses = {}
	  // Compute the base array of styles
	  runMode(cm, line.text, cm.doc.mode, state, function (end, style) { return st.push(end, style); },
	    lineClasses, forceToEnd)
	
	  // Run overlays, adjust style array.
	  var loop = function ( o ) {
	    var overlay = cm.state.overlays[o], i = 1, at = 0
	    runMode(cm, line.text, overlay.mode, true, function (end, style) {
	      var start = i
	      // Ensure there's a token end at the current position, and that i points at it
	      while (at < end) {
	        var i_end = st[i]
	        if (i_end > end)
	          { st.splice(i, 1, end, st[i+1], i_end) }
	        i += 2
	        at = Math.min(end, i_end)
	      }
	      if (!style) { return }
	      if (overlay.opaque) {
	        st.splice(start, i - start, end, "overlay " + style)
	        i = start + 2
	      } else {
	        for (; start < i; start += 2) {
	          var cur = st[start+1]
	          st[start+1] = (cur ? cur + " " : "") + "overlay " + style
	        }
	      }
	    }, lineClasses)
	  };
	
	  for (var o = 0; o < cm.state.overlays.length; ++o) loop( o );
	
	  return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}
	}
	
	function getLineStyles(cm, line, updateFrontier) {
	  if (!line.styles || line.styles[0] != cm.state.modeGen) {
	    var state = getStateBefore(cm, lineNo(line))
	    var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state)
	    line.stateAfter = state
	    line.styles = result.styles
	    if (result.classes) { line.styleClasses = result.classes }
	    else if (line.styleClasses) { line.styleClasses = null }
	    if (updateFrontier === cm.doc.frontier) { cm.doc.frontier++ }
	  }
	  return line.styles
	}
	
	function getStateBefore(cm, n, precise) {
	  var doc = cm.doc, display = cm.display
	  if (!doc.mode.startState) { return true }
	  var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter
	  if (!state) { state = startState(doc.mode) }
	  else { state = copyState(doc.mode, state) }
	  doc.iter(pos, n, function (line) {
	    processLine(cm, line.text, state)
	    var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo
	    line.stateAfter = save ? copyState(doc.mode, state) : null
	    ++pos
	  })
	  if (precise) { doc.frontier = pos }
	  return state
	}
	
	// Lightweight form of highlight -- proceed over this line and
	// update state, but don't save a style array. Used for lines that
	// aren't currently visible.
	function processLine(cm, text, state, startAt) {
	  var mode = cm.doc.mode
	  var stream = new StringStream(text, cm.options.tabSize)
	  stream.start = stream.pos = startAt || 0
	  if (text == "") { callBlankLine(mode, state) }
	  while (!stream.eol()) {
	    readToken(mode, stream, state)
	    stream.start = stream.pos
	  }
	}
	
	function callBlankLine(mode, state) {
	  if (mode.blankLine) { return mode.blankLine(state) }
	  if (!mode.innerMode) { return }
	  var inner = innerMode(mode, state)
	  if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) }
	}
	
	function readToken(mode, stream, state, inner) {
	  for (var i = 0; i < 10; i++) {
	    if (inner) { inner[0] = innerMode(mode, state).mode }
	    var style = mode.token(stream, state)
	    if (stream.pos > stream.start) { return style }
	  }
	  throw new Error("Mode " + mode.name + " failed to advance stream.")
	}
	
	// Utility for getTokenAt and getLineTokens
	function takeToken(cm, pos, precise, asArray) {
	  var getObj = function (copy) { return ({
	    start: stream.start, end: stream.pos,
	    string: stream.current(),
	    type: style || null,
	    state: copy ? copyState(doc.mode, state) : state
	  }); }
	
	  var doc = cm.doc, mode = doc.mode, style
	  pos = clipPos(doc, pos)
	  var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise)
	  var stream = new StringStream(line.text, cm.options.tabSize), tokens
	  if (asArray) { tokens = [] }
	  while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
	    stream.start = stream.pos
	    style = readToken(mode, stream, state)
	    if (asArray) { tokens.push(getObj(true)) }
	  }
	  return asArray ? tokens : getObj()
	}
	
	function extractLineClasses(type, output) {
	  if (type) { for (;;) {
	    var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/)
	    if (!lineClass) { break }
	    type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length)
	    var prop = lineClass[1] ? "bgClass" : "textClass"
	    if (output[prop] == null)
	      { output[prop] = lineClass[2] }
	    else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
	      { output[prop] += " " + lineClass[2] }
	  } }
	  return type
	}
	
	// Run the given mode's parser over a line, calling f for each token.
	function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
	  var flattenSpans = mode.flattenSpans
	  if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans }
	  var curStart = 0, curStyle = null
	  var stream = new StringStream(text, cm.options.tabSize), style
	  var inner = cm.options.addModeClass && [null]
	  if (text == "") { extractLineClasses(callBlankLine(mode, state), lineClasses) }
	  while (!stream.eol()) {
	    if (stream.pos > cm.options.maxHighlightLength) {
	      flattenSpans = false
	      if (forceToEnd) { processLine(cm, text, state, stream.pos) }
	      stream.pos = text.length
	      style = null
	    } else {
	      style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses)
	    }
	    if (inner) {
	      var mName = inner[0].name
	      if (mName) { style = "m-" + (style ? mName + " " + style : mName) }
	    }
	    if (!flattenSpans || curStyle != style) {
	      while (curStart < stream.start) {
	        curStart = Math.min(stream.start, curStart + 5000)
	        f(curStart, curStyle)
	      }
	      curStyle = style
	    }
	    stream.start = stream.pos
	  }
	  while (curStart < stream.pos) {
	    // Webkit seems to refuse to render text nodes longer than 57444
	    // characters, and returns inaccurate measurements in nodes
	    // starting around 5000 chars.
	    var pos = Math.min(stream.pos, curStart + 5000)
	    f(pos, curStyle)
	    curStart = pos
	  }
	}
	
	// Finds the line to start with when starting a parse. Tries to
	// find a line with a stateAfter, so that it can start with a
	// valid state. If that fails, it returns the line with the
	// smallest indentation, which tends to need the least context to
	// parse correctly.
	function findStartLine(cm, n, precise) {
	  var minindent, minline, doc = cm.doc
	  var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100)
	  for (var search = n; search > lim; --search) {
	    if (search <= doc.first) { return doc.first }
	    var line = getLine(doc, search - 1)
	    if (line.stateAfter && (!precise || search <= doc.frontier)) { return search }
	    var indented = countColumn(line.text, null, cm.options.tabSize)
	    if (minline == null || minindent > indented) {
	      minline = search - 1
	      minindent = indented
	    }
	  }
	  return minline
	}
	
	// LINE DATA STRUCTURE
	
	// Line objects. These hold state related to a line, including
	// highlighting info (the styles array).
	function Line(text, markedSpans, estimateHeight) {
	  this.text = text
	  attachMarkedSpans(this, markedSpans)
	  this.height = estimateHeight ? estimateHeight(this) : 1
	}
	eventMixin(Line)
	Line.prototype.lineNo = function() { return lineNo(this) }
	
	// Change the content (text, markers) of a line. Automatically
	// invalidates cached information and tries to re-estimate the
	// line's height.
	function updateLine(line, text, markedSpans, estimateHeight) {
	  line.text = text
	  if (line.stateAfter) { line.stateAfter = null }
	  if (line.styles) { line.styles = null }
	  if (line.order != null) { line.order = null }
	  detachMarkedSpans(line)
	  attachMarkedSpans(line, markedSpans)
	  var estHeight = estimateHeight ? estimateHeight(line) : 1
	  if (estHeight != line.height) { updateLineHeight(line, estHeight) }
	}
	
	// Detach a line from the document tree and its markers.
	function cleanUpLine(line) {
	  line.parent = null
	  detachMarkedSpans(line)
	}
	
	// Convert a style as returned by a mode (either null, or a string
	// containing one or more styles) to a CSS style. This is cached,
	// and also looks for line-wide styles.
	var styleToClassCache = {};
	var styleToClassCacheWithMode = {};
	function interpretTokenStyle(style, options) {
	  if (!style || /^\s*$/.test(style)) { return null }
	  var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache
	  return cache[style] ||
	    (cache[style] = style.replace(/\S+/g, "cm-$&"))
	}
	
	// Render the DOM representation of the text of a line. Also builds
	// up a 'line map', which points at the DOM nodes that represent
	// specific stretches of text, and is used by the measuring code.
	// The returned object contains the DOM node, this map, and
	// information about line-wide styles that were set by the mode.
	function buildLineContent(cm, lineView) {
	  // The padding-right forces the element to have a 'border', which
	  // is needed on Webkit to be able to get line-level bounding
	  // rectangles for it (in measureChar).
	  var content = elt("span", null, null, webkit ? "padding-right: .1px" : null)
	  var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content,
	                 col: 0, pos: 0, cm: cm,
	                 trailingSpace: false,
	                 splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")}
	  // hide from accessibility tree
	  content.setAttribute("role", "presentation")
	  builder.pre.setAttribute("role", "presentation")
	  lineView.measure = {}
	
	  // Iterate over the logical lines that make up this visual line.
	  for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
	    var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0)
	    builder.pos = 0
	    builder.addToken = buildToken
	    // Optionally wire in some hacks into the token-rendering
	    // algorithm, to deal with browser quirks.
	    if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
	      { builder.addToken = buildTokenBadBidi(builder.addToken, order) }
	    builder.map = []
	    var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line)
	    insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate))
	    if (line.styleClasses) {
	      if (line.styleClasses.bgClass)
	        { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "") }
	      if (line.styleClasses.textClass)
	        { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "") }
	    }
	
	    // Ensure at least a single node is present, for measuring.
	    if (builder.map.length == 0)
	      { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))) }
	
	    // Store the map and a cache object for the current logical line
	    if (i == 0) {
	      lineView.measure.map = builder.map
	      lineView.measure.cache = {}
	    } else {
	      ;(lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map)
	      ;(lineView.measure.caches || (lineView.measure.caches = [])).push({})
	    }
	  }
	
	  // See issue #2901
	  if (webkit) {
	    var last = builder.content.lastChild
	    if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab")))
	      { builder.content.className = "cm-tab-wrap-hack" }
	  }
	
	  signal(cm, "renderLine", cm, lineView.line, builder.pre)
	  if (builder.pre.className)
	    { builder.textClass = joinClasses(builder.pre.className, builder.textClass || "") }
	
	  return builder
	}
	
	function defaultSpecialCharPlaceholder(ch) {
	  var token = elt("span", "\u2022", "cm-invalidchar")
	  token.title = "\\u" + ch.charCodeAt(0).toString(16)
	  token.setAttribute("aria-label", token.title)
	  return token
	}
	
	// Build up the DOM representation for a single token, and add it to
	// the line map. Takes care to render special characters separately.
	function buildToken(builder, text, style, startStyle, endStyle, title, css) {
	  if (!text) { return }
	  var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text
	  var special = builder.cm.state.specialChars, mustWrap = false
	  var content
	  if (!special.test(text)) {
	    builder.col += text.length
	    content = document.createTextNode(displayText)
	    builder.map.push(builder.pos, builder.pos + text.length, content)
	    if (ie && ie_version < 9) { mustWrap = true }
	    builder.pos += text.length
	  } else {
	    content = document.createDocumentFragment()
	    var pos = 0
	    while (true) {
	      special.lastIndex = pos
	      var m = special.exec(text)
	      var skipped = m ? m.index - pos : text.length - pos
	      if (skipped) {
	        var txt = document.createTextNode(displayText.slice(pos, pos + skipped))
	        if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])) }
	        else { content.appendChild(txt) }
	        builder.map.push(builder.pos, builder.pos + skipped, txt)
	        builder.col += skipped
	        builder.pos += skipped
	      }
	      if (!m) { break }
	      pos += skipped + 1
	      var txt$1 = (void 0)
	      if (m[0] == "\t") {
	        var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize
	        txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"))
	        txt$1.setAttribute("role", "presentation")
	        txt$1.setAttribute("cm-text", "\t")
	        builder.col += tabWidth
	      } else if (m[0] == "\r" || m[0] == "\n") {
	        txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"))
	        txt$1.setAttribute("cm-text", m[0])
	        builder.col += 1
	      } else {
	        txt$1 = builder.cm.options.specialCharPlaceholder(m[0])
	        txt$1.setAttribute("cm-text", m[0])
	        if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])) }
	        else { content.appendChild(txt$1) }
	        builder.col += 1
	      }
	      builder.map.push(builder.pos, builder.pos + 1, txt$1)
	      builder.pos++
	    }
	  }
	  builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32
	  if (style || startStyle || endStyle || mustWrap || css) {
	    var fullStyle = style || ""
	    if (startStyle) { fullStyle += startStyle }
	    if (endStyle) { fullStyle += endStyle }
	    var token = elt("span", [content], fullStyle, css)
	    if (title) { token.title = title }
	    return builder.content.appendChild(token)
	  }
	  builder.content.appendChild(content)
	}
	
	function splitSpaces(text, trailingBefore) {
	  if (text.length > 1 && !/  /.test(text)) { return text }
	  var spaceBefore = trailingBefore, result = ""
	  for (var i = 0; i < text.length; i++) {
	    var ch = text.charAt(i)
	    if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32))
	      { ch = "\u00a0" }
	    result += ch
	    spaceBefore = ch == " "
	  }
	  return result
	}
	
	// Work around nonsense dimensions being reported for stretches of
	// right-to-left text.
	function buildTokenBadBidi(inner, order) {
	  return function (builder, text, style, startStyle, endStyle, title, css) {
	    style = style ? style + " cm-force-border" : "cm-force-border"
	    var start = builder.pos, end = start + text.length
	    for (;;) {
	      // Find the part that overlaps with the start of this text
	      var part = (void 0)
	      for (var i = 0; i < order.length; i++) {
	        part = order[i]
	        if (part.to > start && part.from <= start) { break }
	      }
	      if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, title, css) }
	      inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css)
	      startStyle = null
	      text = text.slice(part.to - start)
	      start = part.to
	    }
	  }
	}
	
	function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
	  var widget = !ignoreWidget && marker.widgetNode
	  if (widget) { builder.map.push(builder.pos, builder.pos + size, widget) }
	  if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
	    if (!widget)
	      { widget = builder.content.appendChild(document.createElement("span")) }
	    widget.setAttribute("cm-marker", marker.id)
	  }
	  if (widget) {
	    builder.cm.display.input.setUneditable(widget)
	    builder.content.appendChild(widget)
	  }
	  builder.pos += size
	  builder.trailingSpace = false
	}
	
	// Outputs a number of spans to make up a line, taking highlighting
	// and marked text into account.
	function insertLineContent(line, builder, styles) {
	  var spans = line.markedSpans, allText = line.text, at = 0
	  if (!spans) {
	    for (var i$1 = 1; i$1 < styles.length; i$1+=2)
	      { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)) }
	    return
	  }
	
	  var len = allText.length, pos = 0, i = 1, text = "", style, css
	  var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed
	  for (;;) {
	    if (nextChange == pos) { // Update current marker set
	      spanStyle = spanEndStyle = spanStartStyle = title = css = ""
	      collapsed = null; nextChange = Infinity
	      var foundBookmarks = [], endStyles = (void 0)
	      for (var j = 0; j < spans.length; ++j) {
	        var sp = spans[j], m = sp.marker
	        if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
	          foundBookmarks.push(m)
	        } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
	          if (sp.to != null && sp.to != pos && nextChange > sp.to) {
	            nextChange = sp.to
	            spanEndStyle = ""
	          }
	          if (m.className) { spanStyle += " " + m.className }
	          if (m.css) { css = (css ? css + ";" : "") + m.css }
	          if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle }
	          if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to) }
	          if (m.title && !title) { title = m.title }
	          if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
	            { collapsed = sp }
	        } else if (sp.from > pos && nextChange > sp.from) {
	          nextChange = sp.from
	        }
	      }
	      if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2)
	        { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1] } } }
	
	      if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2)
	        { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]) } }
	      if (collapsed && (collapsed.from || 0) == pos) {
	        buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
	                           collapsed.marker, collapsed.from == null)
	        if (collapsed.to == null) { return }
	        if (collapsed.to == pos) { collapsed = false }
	      }
	    }
	    if (pos >= len) { break }
	
	    var upto = Math.min(len, nextChange)
	    while (true) {
	      if (text) {
	        var end = pos + text.length
	        if (!collapsed) {
	          var tokenText = end > upto ? text.slice(0, upto - pos) : text
	          builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
	                           spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css)
	        }
	        if (end >= upto) {text = text.slice(upto - pos); pos = upto; break}
	        pos = end
	        spanStartStyle = ""
	      }
	      text = allText.slice(at, at = styles[i++])
	      style = interpretTokenStyle(styles[i++], builder.cm.options)
	    }
	  }
	}
	
	
	// These objects are used to represent the visible (currently drawn)
	// part of the document. A LineView may correspond to multiple
	// logical lines, if those are connected by collapsed ranges.
	function LineView(doc, line, lineN) {
	  // The starting line
	  this.line = line
	  // Continuing lines, if any
	  this.rest = visualLineContinued(line)
	  // Number of logical lines in this visual line
	  this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1
	  this.node = this.text = null
	  this.hidden = lineIsHidden(doc, line)
	}
	
	// Create a range of LineView objects for the given lines.
	function buildViewArray(cm, from, to) {
	  var array = [], nextPos
	  for (var pos = from; pos < to; pos = nextPos) {
	    var view = new LineView(cm.doc, getLine(cm.doc, pos), pos)
	    nextPos = pos + view.size
	    array.push(view)
	  }
	  return array
	}
	
	var operationGroup = null
	
	function pushOperation(op) {
	  if (operationGroup) {
	    operationGroup.ops.push(op)
	  } else {
	    op.ownsGroup = operationGroup = {
	      ops: [op],
	      delayedCallbacks: []
	    }
	  }
	}
	
	function fireCallbacksForOps(group) {
	  // Calls delayed callbacks and cursorActivity handlers until no
	  // new ones appear
	  var callbacks = group.delayedCallbacks, i = 0
	  do {
	    for (; i < callbacks.length; i++)
	      { callbacks[i].call(null) }
	    for (var j = 0; j < group.ops.length; j++) {
	      var op = group.ops[j]
	      if (op.cursorActivityHandlers)
	        { while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
	          { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm) } }
	    }
	  } while (i < callbacks.length)
	}
	
	function finishOperation(op, endCb) {
	  var group = op.ownsGroup
	  if (!group) { return }
	
	  try { fireCallbacksForOps(group) }
	  finally {
	    operationGroup = null
	    endCb(group)
	  }
	}
	
	var orphanDelayedCallbacks = null
	
	// Often, we want to signal events at a point where we are in the
	// middle of some work, but don't want the handler to start calling
	// other methods on the editor, which might be in an inconsistent
	// state or simply not expect any other events to happen.
	// signalLater looks whether there are any handlers, and schedules
	// them to be executed when the last operation ends, or, if no
	// operation is active, when a timeout fires.
	function signalLater(emitter, type /*, values...*/) {
	  var arr = getHandlers(emitter, type)
	  if (!arr.length) { return }
	  var args = Array.prototype.slice.call(arguments, 2), list
	  if (operationGroup) {
	    list = operationGroup.delayedCallbacks
	  } else if (orphanDelayedCallbacks) {
	    list = orphanDelayedCallbacks
	  } else {
	    list = orphanDelayedCallbacks = []
	    setTimeout(fireOrphanDelayed, 0)
	  }
	  var loop = function ( i ) {
	    list.push(function () { return arr[i].apply(null, args); })
	  };
	
	  for (var i = 0; i < arr.length; ++i)
	    loop( i );
	}
	
	function fireOrphanDelayed() {
	  var delayed = orphanDelayedCallbacks
	  orphanDelayedCallbacks = null
	  for (var i = 0; i < delayed.length; ++i) { delayed[i]() }
	}
	
	// When an aspect of a line changes, a string is added to
	// lineView.changes. This updates the relevant part of the line's
	// DOM structure.
	function updateLineForChanges(cm, lineView, lineN, dims) {
	  for (var j = 0; j < lineView.changes.length; j++) {
	    var type = lineView.changes[j]
	    if (type == "text") { updateLineText(cm, lineView) }
	    else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims) }
	    else if (type == "class") { updateLineClasses(lineView) }
	    else if (type == "widget") { updateLineWidgets(cm, lineView, dims) }
	  }
	  lineView.changes = null
	}
	
	// Lines with gutter elements, widgets or a background class need to
	// be wrapped, and have the extra elements added to the wrapper div
	function ensureLineWrapped(lineView) {
	  if (lineView.node == lineView.text) {
	    lineView.node = elt("div", null, null, "position: relative")
	    if (lineView.text.parentNode)
	      { lineView.text.parentNode.replaceChild(lineView.node, lineView.text) }
	    lineView.node.appendChild(lineView.text)
	    if (ie && ie_version < 8) { lineView.node.style.zIndex = 2 }
	  }
	  return lineView.node
	}
	
	function updateLineBackground(lineView) {
	  var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass
	  if (cls) { cls += " CodeMirror-linebackground" }
	  if (lineView.background) {
	    if (cls) { lineView.background.className = cls }
	    else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null }
	  } else if (cls) {
	    var wrap = ensureLineWrapped(lineView)
	    lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild)
	  }
	}
	
	// Wrapper around buildLineContent which will reuse the structure
	// in display.externalMeasured when possible.
	function getLineContent(cm, lineView) {
	  var ext = cm.display.externalMeasured
	  if (ext && ext.line == lineView.line) {
	    cm.display.externalMeasured = null
	    lineView.measure = ext.measure
	    return ext.built
	  }
	  return buildLineContent(cm, lineView)
	}
	
	// Redraw the line's text. Interacts with the background and text
	// classes because the mode may output tokens that influence these
	// classes.
	function updateLineText(cm, lineView) {
	  var cls = lineView.text.className
	  var built = getLineContent(cm, lineView)
	  if (lineView.text == lineView.node) { lineView.node = built.pre }
	  lineView.text.parentNode.replaceChild(built.pre, lineView.text)
	  lineView.text = built.pre
	  if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
	    lineView.bgClass = built.bgClass
	    lineView.textClass = built.textClass
	    updateLineClasses(lineView)
	  } else if (cls) {
	    lineView.text.className = cls
	  }
	}
	
	function updateLineClasses(lineView) {
	  updateLineBackground(lineView)
	  if (lineView.line.wrapClass)
	    { ensureLineWrapped(lineView).className = lineView.line.wrapClass }
	  else if (lineView.node != lineView.text)
	    { lineView.node.className = "" }
	  var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass
	  lineView.text.className = textClass || ""
	}
	
	function updateLineGutter(cm, lineView, lineN, dims) {
	  if (lineView.gutter) {
	    lineView.node.removeChild(lineView.gutter)
	    lineView.gutter = null
	  }
	  if (lineView.gutterBackground) {
	    lineView.node.removeChild(lineView.gutterBackground)
	    lineView.gutterBackground = null
	  }
	  if (lineView.line.gutterClass) {
	    var wrap = ensureLineWrapped(lineView)
	    lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
	                                    ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px"))
	    wrap.insertBefore(lineView.gutterBackground, lineView.text)
	  }
	  var markers = lineView.line.gutterMarkers
	  if (cm.options.lineNumbers || markers) {
	    var wrap$1 = ensureLineWrapped(lineView)
	    var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"))
	    cm.display.input.setUneditable(gutterWrap)
	    wrap$1.insertBefore(gutterWrap, lineView.text)
	    if (lineView.line.gutterClass)
	      { gutterWrap.className += " " + lineView.line.gutterClass }
	    if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
	      { lineView.lineNumber = gutterWrap.appendChild(
	        elt("div", lineNumberFor(cm.options, lineN),
	            "CodeMirror-linenumber CodeMirror-gutter-elt",
	            ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))) }
	    if (markers) { for (var k = 0; k < cm.options.gutters.length; ++k) {
	      var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]
	      if (found)
	        { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt",
	                                   ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))) }
	    } }
	  }
	}
	
	function updateLineWidgets(cm, lineView, dims) {
	  if (lineView.alignable) { lineView.alignable = null }
	  for (var node = lineView.node.firstChild, next = (void 0); node; node = next) {
	    next = node.nextSibling
	    if (node.className == "CodeMirror-linewidget")
	      { lineView.node.removeChild(node) }
	  }
	  insertLineWidgets(cm, lineView, dims)
	}
	
	// Build a line's DOM representation from scratch
	function buildLineElement(cm, lineView, lineN, dims) {
	  var built = getLineContent(cm, lineView)
	  lineView.text = lineView.node = built.pre
	  if (built.bgClass) { lineView.bgClass = built.bgClass }
	  if (built.textClass) { lineView.textClass = built.textClass }
	
	  updateLineClasses(lineView)
	  updateLineGutter(cm, lineView, lineN, dims)
	  insertLineWidgets(cm, lineView, dims)
	  return lineView.node
	}
	
	// A lineView may contain multiple logical lines (when merged by
	// collapsed spans). The widgets for all of them need to be drawn.
	function insertLineWidgets(cm, lineView, dims) {
	  insertLineWidgetsFor(cm, lineView.line, lineView, dims, true)
	  if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
	    { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false) } }
	}
	
	function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
	  if (!line.widgets) { return }
	  var wrap = ensureLineWrapped(lineView)
	  for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
	    var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget")
	    if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true") }
	    positionLineWidget(widget, node, lineView, dims)
	    cm.display.input.setUneditable(node)
	    if (allowAbove && widget.above)
	      { wrap.insertBefore(node, lineView.gutter || lineView.text) }
	    else
	      { wrap.appendChild(node) }
	    signalLater(widget, "redraw")
	  }
	}
	
	function positionLineWidget(widget, node, lineView, dims) {
	  if (widget.noHScroll) {
	    ;(lineView.alignable || (lineView.alignable = [])).push(node)
	    var width = dims.wrapperWidth
	    node.style.left = dims.fixedPos + "px"
	    if (!widget.coverGutter) {
	      width -= dims.gutterTotalWidth
	      node.style.paddingLeft = dims.gutterTotalWidth + "px"
	    }
	    node.style.width = width + "px"
	  }
	  if (widget.coverGutter) {
	    node.style.zIndex = 5
	    node.style.position = "relative"
	    if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px" }
	  }
	}
	
	function widgetHeight(widget) {
	  if (widget.height != null) { return widget.height }
	  var cm = widget.doc.cm
	  if (!cm) { return 0 }
	  if (!contains(document.body, widget.node)) {
	    var parentStyle = "position: relative;"
	    if (widget.coverGutter)
	      { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;" }
	    if (widget.noHScroll)
	      { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;" }
	    removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle))
	  }
	  return widget.height = widget.node.parentNode.offsetHeight
	}
	
	// Return true when the given mouse event happened in a widget
	function eventInWidget(display, e) {
	  for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
	    if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
	        (n.parentNode == display.sizer && n != display.mover))
	      { return true }
	  }
	}
	
	// POSITION MEASUREMENT
	
	function paddingTop(display) {return display.lineSpace.offsetTop}
	function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight}
	function paddingH(display) {
	  if (display.cachedPaddingH) { return display.cachedPaddingH }
	  var e = removeChildrenAndAdd(display.measure, elt("pre", "x"))
	  var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle
	  var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}
	  if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data }
	  return data
	}
	
	function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth }
	function displayWidth(cm) {
	  return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth
	}
	function displayHeight(cm) {
	  return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight
	}
	
	// Ensure the lineView.wrapping.heights array is populated. This is
	// an array of bottom offsets for the lines that make up a drawn
	// line. When lineWrapping is on, there might be more than one
	// height.
	function ensureLineHeights(cm, lineView, rect) {
	  var wrapping = cm.options.lineWrapping
	  var curWidth = wrapping && displayWidth(cm)
	  if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
	    var heights = lineView.measure.heights = []
	    if (wrapping) {
	      lineView.measure.width = curWidth
	      var rects = lineView.text.firstChild.getClientRects()
	      for (var i = 0; i < rects.length - 1; i++) {
	        var cur = rects[i], next = rects[i + 1]
	        if (Math.abs(cur.bottom - next.bottom) > 2)
	          { heights.push((cur.bottom + next.top) / 2 - rect.top) }
	      }
	    }
	    heights.push(rect.bottom - rect.top)
	  }
	}
	
	// Find a line map (mapping character offsets to text nodes) and a
	// measurement cache for the given line number. (A line view might
	// contain multiple lines when collapsed ranges are present.)
	function mapFromLineView(lineView, line, lineN) {
	  if (lineView.line == line)
	    { return {map: lineView.measure.map, cache: lineView.measure.cache} }
	  for (var i = 0; i < lineView.rest.length; i++)
	    { if (lineView.rest[i] == line)
	      { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
	  for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
	    { if (lineNo(lineView.rest[i$1]) > lineN)
	      { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
	}
	
	// Render a line into the hidden node display.externalMeasured. Used
	// when measurement is needed for a line that's not in the viewport.
	function updateExternalMeasurement(cm, line) {
	  line = visualLine(line)
	  var lineN = lineNo(line)
	  var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN)
	  view.lineN = lineN
	  var built = view.built = buildLineContent(cm, view)
	  view.text = built.pre
	  removeChildrenAndAdd(cm.display.lineMeasure, built.pre)
	  return view
	}
	
	// Get a {top, bottom, left, right} box (in line-local coordinates)
	// for a given character.
	function measureChar(cm, line, ch, bias) {
	  return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias)
	}
	
	// Find a line view that corresponds to the given line number.
	function findViewForLine(cm, lineN) {
	  if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
	    { return cm.display.view[findViewIndex(cm, lineN)] }
	  var ext = cm.display.externalMeasured
	  if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
	    { return ext }
	}
	
	// Measurement can be split in two steps, the set-up work that
	// applies to the whole line, and the measurement of the actual
	// character. Functions like coordsChar, that need to do a lot of
	// measurements in a row, can thus ensure that the set-up work is
	// only done once.
	function prepareMeasureForLine(cm, line) {
	  var lineN = lineNo(line)
	  var view = findViewForLine(cm, lineN)
	  if (view && !view.text) {
	    view = null
	  } else if (view && view.changes) {
	    updateLineForChanges(cm, view, lineN, getDimensions(cm))
	    cm.curOp.forceUpdate = true
	  }
	  if (!view)
	    { view = updateExternalMeasurement(cm, line) }
	
	  var info = mapFromLineView(view, line, lineN)
	  return {
	    line: line, view: view, rect: null,
	    map: info.map, cache: info.cache, before: info.before,
	    hasHeights: false
	  }
	}
	
	// Given a prepared measurement object, measures the position of an
	// actual character (or fetches it from the cache).
	function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
	  if (prepared.before) { ch = -1 }
	  var key = ch + (bias || ""), found
	  if (prepared.cache.hasOwnProperty(key)) {
	    found = prepared.cache[key]
	  } else {
	    if (!prepared.rect)
	      { prepared.rect = prepared.view.text.getBoundingClientRect() }
	    if (!prepared.hasHeights) {
	      ensureLineHeights(cm, prepared.view, prepared.rect)
	      prepared.hasHeights = true
	    }
	    found = measureCharInner(cm, prepared, ch, bias)
	    if (!found.bogus) { prepared.cache[key] = found }
	  }
	  return {left: found.left, right: found.right,
	          top: varHeight ? found.rtop : found.top,
	          bottom: varHeight ? found.rbottom : found.bottom}
	}
	
	var nullRect = {left: 0, right: 0, top: 0, bottom: 0}
	
	function nodeAndOffsetInLineMap(map, ch, bias) {
	  var node, start, end, collapse, mStart, mEnd
	  // First, search the line map for the text node corresponding to,
	  // or closest to, the target character.
	  for (var i = 0; i < map.length; i += 3) {
	    mStart = map[i]
	    mEnd = map[i + 1]
	    if (ch < mStart) {
	      start = 0; end = 1
	      collapse = "left"
	    } else if (ch < mEnd) {
	      start = ch - mStart
	      end = start + 1
	    } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
	      end = mEnd - mStart
	      start = end - 1
	      if (ch >= mEnd) { collapse = "right" }
	    }
	    if (start != null) {
	      node = map[i + 2]
	      if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
	        { collapse = bias }
	      if (bias == "left" && start == 0)
	        { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
	          node = map[(i -= 3) + 2]
	          collapse = "left"
	        } }
	      if (bias == "right" && start == mEnd - mStart)
	        { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
	          node = map[(i += 3) + 2]
	          collapse = "right"
	        } }
	      break
	    }
	  }
	  return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}
	}
	
	function getUsefulRect(rects, bias) {
	  var rect = nullRect
	  if (bias == "left") { for (var i = 0; i < rects.length; i++) {
	    if ((rect = rects[i]).left != rect.right) { break }
	  } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) {
	    if ((rect = rects[i$1]).left != rect.right) { break }
	  } }
	  return rect
	}
	
	function measureCharInner(cm, prepared, ch, bias) {
	  var place = nodeAndOffsetInLineMap(prepared.map, ch, bias)
	  var node = place.node, start = place.start, end = place.end, collapse = place.collapse
	
	  var rect
	  if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
	    for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned
	      while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start }
	      while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end }
	      if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart)
	        { rect = node.parentNode.getBoundingClientRect() }
	      else
	        { rect = getUsefulRect(range(node, start, end).getClientRects(), bias) }
	      if (rect.left || rect.right || start == 0) { break }
	      end = start
	      start = start - 1
	      collapse = "right"
	    }
	    if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect) }
	  } else { // If it is a widget, simply get the box for the whole widget.
	    if (start > 0) { collapse = bias = "right" }
	    var rects
	    if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
	      { rect = rects[bias == "right" ? rects.length - 1 : 0] }
	    else
	      { rect = node.getBoundingClientRect() }
	  }
	  if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
	    var rSpan = node.parentNode.getClientRects()[0]
	    if (rSpan)
	      { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom} }
	    else
	      { rect = nullRect }
	  }
	
	  var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top
	  var mid = (rtop + rbot) / 2
	  var heights = prepared.view.measure.heights
	  var i = 0
	  for (; i < heights.length - 1; i++)
	    { if (mid < heights[i]) { break } }
	  var top = i ? heights[i - 1] : 0, bot = heights[i]
	  var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
	                right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
	                top: top, bottom: bot}
	  if (!rect.left && !rect.right) { result.bogus = true }
	  if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot }
	
	  return result
	}
	
	// Work around problem with bounding client rects on ranges being
	// returned incorrectly when zoomed on IE10 and below.
	function maybeUpdateRectForZooming(measure, rect) {
	  if (!window.screen || screen.logicalXDPI == null ||
	      screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
	    { return rect }
	  var scaleX = screen.logicalXDPI / screen.deviceXDPI
	  var scaleY = screen.logicalYDPI / screen.deviceYDPI
	  return {left: rect.left * scaleX, right: rect.right * scaleX,
	          top: rect.top * scaleY, bottom: rect.bottom * scaleY}
	}
	
	function clearLineMeasurementCacheFor(lineView) {
	  if (lineView.measure) {
	    lineView.measure.cache = {}
	    lineView.measure.heights = null
	    if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
	      { lineView.measure.caches[i] = {} } }
	  }
	}
	
	function clearLineMeasurementCache(cm) {
	  cm.display.externalMeasure = null
	  removeChildren(cm.display.lineMeasure)
	  for (var i = 0; i < cm.display.view.length; i++)
	    { clearLineMeasurementCacheFor(cm.display.view[i]) }
	}
	
	function clearCaches(cm) {
	  clearLineMeasurementCache(cm)
	  cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null
	  if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true }
	  cm.display.lineNumChars = null
	}
	
	function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft }
	function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop }
	
	// Converts a {top, bottom, left, right} box from line-local
	// coordinates into another coordinate system. Context may be one of
	// "line", "div" (display.lineDiv), "local"./null (editor), "window",
	// or "page".
	function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {
	  if (!includeWidgets && lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) {
	    var size = widgetHeight(lineObj.widgets[i])
	    rect.top += size; rect.bottom += size
	  } } }
	  if (context == "line") { return rect }
	  if (!context) { context = "local" }
	  var yOff = heightAtLine(lineObj)
	  if (context == "local") { yOff += paddingTop(cm.display) }
	  else { yOff -= cm.display.viewOffset }
	  if (context == "page" || context == "window") {
	    var lOff = cm.display.lineSpace.getBoundingClientRect()
	    yOff += lOff.top + (context == "window" ? 0 : pageScrollY())
	    var xOff = lOff.left + (context == "window" ? 0 : pageScrollX())
	    rect.left += xOff; rect.right += xOff
	  }
	  rect.top += yOff; rect.bottom += yOff
	  return rect
	}
	
	// Coverts a box from "div" coords to another coordinate system.
	// Context may be "window", "page", "div", or "local"./null.
	function fromCoordSystem(cm, coords, context) {
	  if (context == "div") { return coords }
	  var left = coords.left, top = coords.top
	  // First move into "page" coordinate system
	  if (context == "page") {
	    left -= pageScrollX()
	    top -= pageScrollY()
	  } else if (context == "local" || !context) {
	    var localBox = cm.display.sizer.getBoundingClientRect()
	    left += localBox.left
	    top += localBox.top
	  }
	
	  var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect()
	  return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}
	}
	
	function charCoords(cm, pos, context, lineObj, bias) {
	  if (!lineObj) { lineObj = getLine(cm.doc, pos.line) }
	  return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context)
	}
	
	// Returns a box for a given cursor position, which may have an
	// 'other' property containing the position of the secondary cursor
	// on a bidi boundary.
	function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
	  lineObj = lineObj || getLine(cm.doc, pos.line)
	  if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj) }
	  function get(ch, right) {
	    var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight)
	    if (right) { m.left = m.right; } else { m.right = m.left }
	    return intoCoordSystem(cm, lineObj, m, context)
	  }
	  function getBidi(ch, partPos) {
	    var part = order[partPos], right = part.level % 2
	    if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
	      part = order[--partPos]
	      ch = bidiRight(part) - (part.level % 2 ? 0 : 1)
	      right = true
	    } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
	      part = order[++partPos]
	      ch = bidiLeft(part) - part.level % 2
	      right = false
	    }
	    if (right && ch == part.to && ch > part.from) { return get(ch - 1) }
	    return get(ch, right)
	  }
	  var order = getOrder(lineObj), ch = pos.ch
	  if (!order) { return get(ch) }
	  var partPos = getBidiPartAt(order, ch)
	  var val = getBidi(ch, partPos)
	  if (bidiOther != null) { val.other = getBidi(ch, bidiOther) }
	  return val
	}
	
	// Used to cheaply estimate the coordinates for a position. Used for
	// intermediate scroll updates.
	function estimateCoords(cm, pos) {
	  var left = 0
	  pos = clipPos(cm.doc, pos)
	  if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch }
	  var lineObj = getLine(cm.doc, pos.line)
	  var top = heightAtLine(lineObj) + paddingTop(cm.display)
	  return {left: left, right: left, top: top, bottom: top + lineObj.height}
	}
	
	// Positions returned by coordsChar contain some extra information.
	// xRel is the relative x position of the input coordinates compared
	// to the found position (so xRel > 0 means the coordinates are to
	// the right of the character position, for example). When outside
	// is true, that means the coordinates lie outside the line's
	// vertical range.
	function PosWithInfo(line, ch, outside, xRel) {
	  var pos = Pos(line, ch)
	  pos.xRel = xRel
	  if (outside) { pos.outside = true }
	  return pos
	}
	
	// Compute the character position closest to the given coordinates.
	// Input must be lineSpace-local ("div" coordinate system).
	function coordsChar(cm, x, y) {
	  var doc = cm.doc
	  y += cm.display.viewOffset
	  if (y < 0) { return PosWithInfo(doc.first, 0, true, -1) }
	  var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1
	  if (lineN > last)
	    { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1) }
	  if (x < 0) { x = 0 }
	
	  var lineObj = getLine(doc, lineN)
	  for (;;) {
	    var found = coordsCharInner(cm, lineObj, lineN, x, y)
	    var merged = collapsedSpanAtEnd(lineObj)
	    var mergedPos = merged && merged.find(0, true)
	    if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
	      { lineN = lineNo(lineObj = mergedPos.to.line) }
	    else
	      { return found }
	  }
	}
	
	function coordsCharInner(cm, lineObj, lineNo, x, y) {
	  var innerOff = y - heightAtLine(lineObj)
	  var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth
	  var preparedMeasure = prepareMeasureForLine(cm, lineObj)
	
	  function getX(ch) {
	    var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure)
	    wrongLine = true
	    if (innerOff > sp.bottom) { return sp.left - adjust }
	    else if (innerOff < sp.top) { return sp.left + adjust }
	    else { wrongLine = false }
	    return sp.left
	  }
	
	  var bidi = getOrder(lineObj), dist = lineObj.text.length
	  var from = lineLeft(lineObj), to = lineRight(lineObj)
	  var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine
	
	  if (x > toX) { return PosWithInfo(lineNo, to, toOutside, 1) }
	  // Do a binary search between these bounds.
	  for (;;) {
	    if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
	      var ch = x < fromX || x - fromX <= toX - x ? from : to
	      var outside = ch == from ? fromOutside : toOutside
	      var xDiff = x - (ch == from ? fromX : toX)
	      // This is a kludge to handle the case where the coordinates
	      // are after a line-wrapped line. We should replace it with a
	      // more general handling of cursor positions around line
	      // breaks. (Issue #4078)
	      if (toOutside && !bidi && !/\s/.test(lineObj.text.charAt(ch)) && xDiff > 0 &&
	          ch < lineObj.text.length && preparedMeasure.view.measure.heights.length > 1) {
	        var charSize = measureCharPrepared(cm, preparedMeasure, ch, "right")
	        if (innerOff <= charSize.bottom && innerOff >= charSize.top && Math.abs(x - charSize.right) < xDiff) {
	          outside = false
	          ch++
	          xDiff = x - charSize.right
	        }
	      }
	      while (isExtendingChar(lineObj.text.charAt(ch))) { ++ch }
	      var pos = PosWithInfo(lineNo, ch, outside, xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0)
	      return pos
	    }
	    var step = Math.ceil(dist / 2), middle = from + step
	    if (bidi) {
	      middle = from
	      for (var i = 0; i < step; ++i) { middle = moveVisually(lineObj, middle, 1) }
	    }
	    var middleX = getX(middle)
	    if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) { toX += 1000; } dist = step}
	    else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step}
	  }
	}
	
	var measureText
	// Compute the default text height.
	function textHeight(display) {
	  if (display.cachedTextHeight != null) { return display.cachedTextHeight }
	  if (measureText == null) {
	    measureText = elt("pre")
	    // Measure a bunch of lines, for browsers that compute
	    // fractional heights.
	    for (var i = 0; i < 49; ++i) {
	      measureText.appendChild(document.createTextNode("x"))
	      measureText.appendChild(elt("br"))
	    }
	    measureText.appendChild(document.createTextNode("x"))
	  }
	  removeChildrenAndAdd(display.measure, measureText)
	  var height = measureText.offsetHeight / 50
	  if (height > 3) { display.cachedTextHeight = height }
	  removeChildren(display.measure)
	  return height || 1
	}
	
	// Compute the default character width.
	function charWidth(display) {
	  if (display.cachedCharWidth != null) { return display.cachedCharWidth }
	  var anchor = elt("span", "xxxxxxxxxx")
	  var pre = elt("pre", [anchor])
	  removeChildrenAndAdd(display.measure, pre)
	  var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10
	  if (width > 2) { display.cachedCharWidth = width }
	  return width || 10
	}
	
	// Do a bulk-read of the DOM positions and sizes needed to draw the
	// view, so that we don't interleave reading and writing to the DOM.
	function getDimensions(cm) {
	  var d = cm.display, left = {}, width = {}
	  var gutterLeft = d.gutters.clientLeft
	  for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
	    left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft
	    width[cm.options.gutters[i]] = n.clientWidth
	  }
	  return {fixedPos: compensateForHScroll(d),
	          gutterTotalWidth: d.gutters.offsetWidth,
	          gutterLeft: left,
	          gutterWidth: width,
	          wrapperWidth: d.wrapper.clientWidth}
	}
	
	// Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
	// but using getBoundingClientRect to get a sub-pixel-accurate
	// result.
	function compensateForHScroll(display) {
	  return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left
	}
	
	// Returns a function that estimates the height of a line, to use as
	// first approximation until the line becomes visible (and is thus
	// properly measurable).
	function estimateHeight(cm) {
	  var th = textHeight(cm.display), wrapping = cm.options.lineWrapping
	  var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3)
	  return function (line) {
	    if (lineIsHidden(cm.doc, line)) { return 0 }
	
	    var widgetsHeight = 0
	    if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) {
	      if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height }
	    } }
	
	    if (wrapping)
	      { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th }
	    else
	      { return widgetsHeight + th }
	  }
	}
	
	function estimateLineHeights(cm) {
	  var doc = cm.doc, est = estimateHeight(cm)
	  doc.iter(function (line) {
	    var estHeight = est(line)
	    if (estHeight != line.height) { updateLineHeight(line, estHeight) }
	  })
	}
	
	// Given a mouse event, find the corresponding position. If liberal
	// is false, it checks whether a gutter or scrollbar was clicked,
	// and returns null if it was. forRect is used by rectangular
	// selections, and tries to estimate a character position even for
	// coordinates beyond the right of the text.
	function posFromMouse(cm, e, liberal, forRect) {
	  var display = cm.display
	  if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null }
	
	  var x, y, space = display.lineSpace.getBoundingClientRect()
	  // Fails unpredictably on IE[67] when mouse is dragged around quickly.
	  try { x = e.clientX - space.left; y = e.clientY - space.top }
	  catch (e) { return null }
	  var coords = coordsChar(cm, x, y), line
	  if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
	    var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length
	    coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff))
	  }
	  return coords
	}
	
	// Find the view element corresponding to a given line. Return null
	// when the line isn't visible.
	function findViewIndex(cm, n) {
	  if (n >= cm.display.viewTo) { return null }
	  n -= cm.display.viewFrom
	  if (n < 0) { return null }
	  var view = cm.display.view
	  for (var i = 0; i < view.length; i++) {
	    n -= view[i].size
	    if (n < 0) { return i }
	  }
	}
	
	function updateSelection(cm) {
	  cm.display.input.showSelection(cm.display.input.prepareSelection())
	}
	
	function prepareSelection(cm, primary) {
	  var doc = cm.doc, result = {}
	  var curFragment = result.cursors = document.createDocumentFragment()
	  var selFragment = result.selection = document.createDocumentFragment()
	
	  for (var i = 0; i < doc.sel.ranges.length; i++) {
	    if (primary === false && i == doc.sel.primIndex) { continue }
	    var range = doc.sel.ranges[i]
	    if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue }
	    var collapsed = range.empty()
	    if (collapsed || cm.options.showCursorWhenSelecting)
	      { drawSelectionCursor(cm, range.head, curFragment) }
	    if (!collapsed)
	      { drawSelectionRange(cm, range, selFragment) }
	  }
	  return result
	}
	
	// Draws a cursor for the given range
	function drawSelectionCursor(cm, head, output) {
	  var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine)
	
	  var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"))
	  cursor.style.left = pos.left + "px"
	  cursor.style.top = pos.top + "px"
	  cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"
	
	  if (pos.other) {
	    // Secondary cursor, shown when on a 'jump' in bi-directional text
	    var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"))
	    otherCursor.style.display = ""
	    otherCursor.style.left = pos.other.left + "px"
	    otherCursor.style.top = pos.other.top + "px"
	    otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"
	  }
	}
	
	// Draws the given range as a highlighted selection
	function drawSelectionRange(cm, range, output) {
	  var display = cm.display, doc = cm.doc
	  var fragment = document.createDocumentFragment()
	  var padding = paddingH(cm.display), leftSide = padding.left
	  var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right
	
	  function add(left, top, width, bottom) {
	    if (top < 0) { top = 0 }
	    top = Math.round(top)
	    bottom = Math.round(bottom)
	    fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n                             top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n                             height: " + (bottom - top) + "px")))
	  }
	
	  function drawForLine(line, fromArg, toArg) {
	    var lineObj = getLine(doc, line)
	    var lineLen = lineObj.text.length
	    var start, end
	    function coords(ch, bias) {
	      return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
	    }
	
	    iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) {
	      var leftPos = coords(from, "left"), rightPos, left, right
	      if (from == to) {
	        rightPos = leftPos
	        left = right = leftPos.left
	      } else {
	        rightPos = coords(to - 1, "right")
	        if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp }
	        left = leftPos.left
	        right = rightPos.right
	      }
	      if (fromArg == null && from == 0) { left = leftSide }
	      if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
	        add(left, leftPos.top, null, leftPos.bottom)
	        left = leftSide
	        if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top) }
	      }
	      if (toArg == null && to == lineLen) { right = rightSide }
	      if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
	        { start = leftPos }
	      if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
	        { end = rightPos }
	      if (left < leftSide + 1) { left = leftSide }
	      add(left, rightPos.top, right - left, rightPos.bottom)
	    })
	    return {start: start, end: end}
	  }
	
	  var sFrom = range.from(), sTo = range.to()
	  if (sFrom.line == sTo.line) {
	    drawForLine(sFrom.line, sFrom.ch, sTo.ch)
	  } else {
	    var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line)
	    var singleVLine = visualLine(fromLine) == visualLine(toLine)
	    var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end
	    var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start
	    if (singleVLine) {
	      if (leftEnd.top < rightStart.top - 2) {
	        add(leftEnd.right, leftEnd.top, null, leftEnd.bottom)
	        add(leftSide, rightStart.top, rightStart.left, rightStart.bottom)
	      } else {
	        add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom)
	      }
	    }
	    if (leftEnd.bottom < rightStart.top)
	      { add(leftSide, leftEnd.bottom, null, rightStart.top) }
	  }
	
	  output.appendChild(fragment)
	}
	
	// Cursor-blinking
	function restartBlink(cm) {
	  if (!cm.state.focused) { return }
	  var display = cm.display
	  clearInterval(display.blinker)
	  var on = true
	  display.cursorDiv.style.visibility = ""
	  if (cm.options.cursorBlinkRate > 0)
	    { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; },
	      cm.options.cursorBlinkRate) }
	  else if (cm.options.cursorBlinkRate < 0)
	    { display.cursorDiv.style.visibility = "hidden" }
	}
	
	function ensureFocus(cm) {
	  if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm) }
	}
	
	function delayBlurEvent(cm) {
	  cm.state.delayingBlurEvent = true
	  setTimeout(function () { if (cm.state.delayingBlurEvent) {
	    cm.state.delayingBlurEvent = false
	    onBlur(cm)
	  } }, 100)
	}
	
	function onFocus(cm, e) {
	  if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false }
	
	  if (cm.options.readOnly == "nocursor") { return }
	  if (!cm.state.focused) {
	    signal(cm, "focus", cm, e)
	    cm.state.focused = true
	    addClass(cm.display.wrapper, "CodeMirror-focused")
	    // This test prevents this from firing when a context
	    // menu is closed (since the input reset would kill the
	    // select-all detection hack)
	    if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
	      cm.display.input.reset()
	      if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20) } // Issue #1730
	    }
	    cm.display.input.receivedFocus()
	  }
	  restartBlink(cm)
	}
	function onBlur(cm, e) {
	  if (cm.state.delayingBlurEvent) { return }
	
	  if (cm.state.focused) {
	    signal(cm, "blur", cm, e)
	    cm.state.focused = false
	    rmClass(cm.display.wrapper, "CodeMirror-focused")
	  }
	  clearInterval(cm.display.blinker)
	  setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false } }, 150)
	}
	
	// Re-align line numbers and gutter marks to compensate for
	// horizontal scrolling.
	function alignHorizontally(cm) {
	  var display = cm.display, view = display.view
	  if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }
	  var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft
	  var gutterW = display.gutters.offsetWidth, left = comp + "px"
	  for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {
	    if (cm.options.fixedGutter) {
	      if (view[i].gutter)
	        { view[i].gutter.style.left = left }
	      if (view[i].gutterBackground)
	        { view[i].gutterBackground.style.left = left }
	    }
	    var align = view[i].alignable
	    if (align) { for (var j = 0; j < align.length; j++)
	      { align[j].style.left = left } }
	  } }
	  if (cm.options.fixedGutter)
	    { display.gutters.style.left = (comp + gutterW) + "px" }
	}
	
	// Used to ensure that the line number gutter is still the right
	// size for the current document size. Returns true when an update
	// is needed.
	function maybeUpdateLineNumberWidth(cm) {
	  if (!cm.options.lineNumbers) { return false }
	  var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display
	  if (last.length != display.lineNumChars) {
	    var test = display.measure.appendChild(elt("div", [elt("div", last)],
	                                               "CodeMirror-linenumber CodeMirror-gutter-elt"))
	    var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW
	    display.lineGutter.style.width = ""
	    display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1
	    display.lineNumWidth = display.lineNumInnerWidth + padding
	    display.lineNumChars = display.lineNumInnerWidth ? last.length : -1
	    display.lineGutter.style.width = display.lineNumWidth + "px"
	    updateGutterSpace(cm)
	    return true
	  }
	  return false
	}
	
	// Read the actual heights of the rendered lines, and update their
	// stored heights to match.
	function updateHeightsInViewport(cm) {
	  var display = cm.display
	  var prevBottom = display.lineDiv.offsetTop
	  for (var i = 0; i < display.view.length; i++) {
	    var cur = display.view[i], height = (void 0)
	    if (cur.hidden) { continue }
	    if (ie && ie_version < 8) {
	      var bot = cur.node.offsetTop + cur.node.offsetHeight
	      height = bot - prevBottom
	      prevBottom = bot
	    } else {
	      var box = cur.node.getBoundingClientRect()
	      height = box.bottom - box.top
	    }
	    var diff = cur.line.height - height
	    if (height < 2) { height = textHeight(display) }
	    if (diff > .001 || diff < -.001) {
	      updateLineHeight(cur.line, height)
	      updateWidgetHeight(cur.line)
	      if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
	        { updateWidgetHeight(cur.rest[j]) } }
	    }
	  }
	}
	
	// Read and store the height of line widgets associated with the
	// given line.
	function updateWidgetHeight(line) {
	  if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i)
	    { line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight } }
	}
	
	// Compute the lines that are visible in a given viewport (defaults
	// the the current scroll position). viewport may contain top,
	// height, and ensure (see op.scrollToPos) properties.
	function visibleLines(display, doc, viewport) {
	  var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop
	  top = Math.floor(top - paddingTop(display))
	  var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight
	
	  var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom)
	  // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
	  // forces those lines into the viewport (if possible).
	  if (viewport && viewport.ensure) {
	    var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line
	    if (ensureFrom < from) {
	      from = ensureFrom
	      to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)
	    } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
	      from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight)
	      to = ensureTo
	    }
	  }
	  return {from: from, to: Math.max(to, from + 1)}
	}
	
	// Sync the scrollable area and scrollbars, ensure the viewport
	// covers the visible area.
	function setScrollTop(cm, val) {
	  if (Math.abs(cm.doc.scrollTop - val) < 2) { return }
	  cm.doc.scrollTop = val
	  if (!gecko) { updateDisplaySimple(cm, {top: val}) }
	  if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val }
	  cm.display.scrollbars.setScrollTop(val)
	  if (gecko) { updateDisplaySimple(cm) }
	  startWorker(cm, 100)
	}
	// Sync scroller and scrollbar, ensure the gutter elements are
	// aligned.
	function setScrollLeft(cm, val, isScroller) {
	  if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) { return }
	  val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth)
	  cm.doc.scrollLeft = val
	  alignHorizontally(cm)
	  if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val }
	  cm.display.scrollbars.setScrollLeft(val)
	}
	
	// Since the delta values reported on mouse wheel events are
	// unstandardized between browsers and even browser versions, and
	// generally horribly unpredictable, this code starts by measuring
	// the scroll effect that the first few mouse wheel events have,
	// and, from that, detects the way it can convert deltas to pixel
	// offsets afterwards.
	//
	// The reason we want to know the amount a wheel event will scroll
	// is that it gives us a chance to update the display before the
	// actual scrolling happens, reducing flickering.
	
	var wheelSamples = 0;
	var wheelPixelsPerUnit = null;
	// Fill in a browser-detected starting value on browsers where we
	// know one. These don't have to be accurate -- the result of them
	// being wrong would just be a slight flicker on the first wheel
	// scroll (if it is large enough).
	if (ie) { wheelPixelsPerUnit = -.53 }
	else if (gecko) { wheelPixelsPerUnit = 15 }
	else if (chrome) { wheelPixelsPerUnit = -.7 }
	else if (safari) { wheelPixelsPerUnit = -1/3 }
	
	function wheelEventDelta(e) {
	  var dx = e.wheelDeltaX, dy = e.wheelDeltaY
	  if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail }
	  if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail }
	  else if (dy == null) { dy = e.wheelDelta }
	  return {x: dx, y: dy}
	}
	function wheelEventPixels(e) {
	  var delta = wheelEventDelta(e)
	  delta.x *= wheelPixelsPerUnit
	  delta.y *= wheelPixelsPerUnit
	  return delta
	}
	
	function onScrollWheel(cm, e) {
	  var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y
	
	  var display = cm.display, scroll = display.scroller
	  // Quit if there's nothing to scroll here
	  var canScrollX = scroll.scrollWidth > scroll.clientWidth
	  var canScrollY = scroll.scrollHeight > scroll.clientHeight
	  if (!(dx && canScrollX || dy && canScrollY)) { return }
	
	  // Webkit browsers on OS X abort momentum scrolls when the target
	  // of the scroll event is removed from the scrollable element.
	  // This hack (see related code in patchDisplay) makes sure the
	  // element is kept around.
	  if (dy && mac && webkit) {
	    outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
	      for (var i = 0; i < view.length; i++) {
	        if (view[i].node == cur) {
	          cm.display.currentWheelTarget = cur
	          break outer
	        }
	      }
	    }
	  }
	
	  // On some browsers, horizontal scrolling will cause redraws to
	  // happen before the gutter has been realigned, causing it to
	  // wriggle around in a most unseemly way. When we have an
	  // estimated pixels/delta value, we just handle horizontal
	  // scrolling entirely here. It'll be slightly off from native, but
	  // better than glitching out.
	  if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
	    if (dy && canScrollY)
	      { setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))) }
	    setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)))
	    // Only prevent default scrolling if vertical scrolling is
	    // actually possible. Otherwise, it causes vertical scroll
	    // jitter on OSX trackpads when deltaX is small and deltaY
	    // is large (issue #3579)
	    if (!dy || (dy && canScrollY))
	      { e_preventDefault(e) }
	    display.wheelStartX = null // Abort measurement, if in progress
	    return
	  }
	
	  // 'Project' the visible viewport to cover the area that is being
	  // scrolled into view (if we know enough to estimate it).
	  if (dy && wheelPixelsPerUnit != null) {
	    var pixels = dy * wheelPixelsPerUnit
	    var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight
	    if (pixels < 0) { top = Math.max(0, top + pixels - 50) }
	    else { bot = Math.min(cm.doc.height, bot + pixels + 50) }
	    updateDisplaySimple(cm, {top: top, bottom: bot})
	  }
	
	  if (wheelSamples < 20) {
	    if (display.wheelStartX == null) {
	      display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop
	      display.wheelDX = dx; display.wheelDY = dy
	      setTimeout(function () {
	        if (display.wheelStartX == null) { return }
	        var movedX = scroll.scrollLeft - display.wheelStartX
	        var movedY = scroll.scrollTop - display.wheelStartY
	        var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
	          (movedX && display.wheelDX && movedX / display.wheelDX)
	        display.wheelStartX = display.wheelStartY = null
	        if (!sample) { return }
	        wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1)
	        ++wheelSamples
	      }, 200)
	    } else {
	      display.wheelDX += dx; display.wheelDY += dy
	    }
	  }
	}
	
	// SCROLLBARS
	
	// Prepare DOM reads needed to update the scrollbars. Done in one
	// shot to minimize update/measure roundtrips.
	function measureForScrollbars(cm) {
	  var d = cm.display, gutterW = d.gutters.offsetWidth
	  var docH = Math.round(cm.doc.height + paddingVert(cm.display))
	  return {
	    clientHeight: d.scroller.clientHeight,
	    viewHeight: d.wrapper.clientHeight,
	    scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
	    viewWidth: d.wrapper.clientWidth,
	    barLeft: cm.options.fixedGutter ? gutterW : 0,
	    docHeight: docH,
	    scrollHeight: docH + scrollGap(cm) + d.barHeight,
	    nativeBarWidth: d.nativeBarWidth,
	    gutterWidth: gutterW
	  }
	}
	
	var NativeScrollbars = function(place, scroll, cm) {
	  this.cm = cm
	  var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar")
	  var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar")
	  place(vert); place(horiz)
	
	  on(vert, "scroll", function () {
	    if (vert.clientHeight) { scroll(vert.scrollTop, "vertical") }
	  })
	  on(horiz, "scroll", function () {
	    if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal") }
	  })
	
	  this.checkedZeroWidth = false
	  // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
	  if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px" }
	};
	
	NativeScrollbars.prototype.update = function (measure) {
	  var needsH = measure.scrollWidth > measure.clientWidth + 1
	  var needsV = measure.scrollHeight > measure.clientHeight + 1
	  var sWidth = measure.nativeBarWidth
	
	  if (needsV) {
	    this.vert.style.display = "block"
	    this.vert.style.bottom = needsH ? sWidth + "px" : "0"
	    var totalHeight = measure.viewHeight - (needsH ? sWidth : 0)
	    // A bug in IE8 can cause this value to be negative, so guard it.
	    this.vert.firstChild.style.height =
	      Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"
	  } else {
	    this.vert.style.display = ""
	    this.vert.firstChild.style.height = "0"
	  }
	
	  if (needsH) {
	    this.horiz.style.display = "block"
	    this.horiz.style.right = needsV ? sWidth + "px" : "0"
	    this.horiz.style.left = measure.barLeft + "px"
	    var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0)
	    this.horiz.firstChild.style.width =
	      (measure.scrollWidth - measure.clientWidth + totalWidth) + "px"
	  } else {
	    this.horiz.style.display = ""
	    this.horiz.firstChild.style.width = "0"
	  }
	
	  if (!this.checkedZeroWidth && measure.clientHeight > 0) {
	    if (sWidth == 0) { this.zeroWidthHack() }
	    this.checkedZeroWidth = true
	  }
	
	  return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}
	};
	
	NativeScrollbars.prototype.setScrollLeft = function (pos) {
	  if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos }
	  if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz) }
	};
	
	NativeScrollbars.prototype.setScrollTop = function (pos) {
	  if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos }
	  if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert) }
	};
	
	NativeScrollbars.prototype.zeroWidthHack = function () {
	  var w = mac && !mac_geMountainLion ? "12px" : "18px"
	  this.horiz.style.height = this.vert.style.width = w
	  this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"
	  this.disableHoriz = new Delayed
	  this.disableVert = new Delayed
	};
	
	NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay) {
	  bar.style.pointerEvents = "auto"
	  function maybeDisable() {
	    // To find out whether the scrollbar is still visible, we
	    // check whether the element under the pixel in the bottom
	    // left corner of the scrollbar box is the scrollbar box
	    // itself (when the bar is still visible) or its filler child
	    // (when the bar is hidden). If it is still visible, we keep
	    // it enabled, if it's hidden, we disable pointer events.
	    var box = bar.getBoundingClientRect()
	    var elt = document.elementFromPoint(box.left + 1, box.bottom - 1)
	    if (elt != bar) { bar.style.pointerEvents = "none" }
	    else { delay.set(1000, maybeDisable) }
	  }
	  delay.set(1000, maybeDisable)
	};
	
	NativeScrollbars.prototype.clear = function () {
	  var parent = this.horiz.parentNode
	  parent.removeChild(this.horiz)
	  parent.removeChild(this.vert)
	};
	
	var NullScrollbars = function () {};
	
	NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} };
	NullScrollbars.prototype.setScrollLeft = function () {};
	NullScrollbars.prototype.setScrollTop = function () {};
	NullScrollbars.prototype.clear = function () {};
	
	function updateScrollbars(cm, measure) {
	  if (!measure) { measure = measureForScrollbars(cm) }
	  var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight
	  updateScrollbarsInner(cm, measure)
	  for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
	    if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
	      { updateHeightsInViewport(cm) }
	    updateScrollbarsInner(cm, measureForScrollbars(cm))
	    startWidth = cm.display.barWidth; startHeight = cm.display.barHeight
	  }
	}
	
	// Re-synchronize the fake scrollbars with the actual size of the
	// content.
	function updateScrollbarsInner(cm, measure) {
	  var d = cm.display
	  var sizes = d.scrollbars.update(measure)
	
	  d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"
	  d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"
	  d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"
	
	  if (sizes.right && sizes.bottom) {
	    d.scrollbarFiller.style.display = "block"
	    d.scrollbarFiller.style.height = sizes.bottom + "px"
	    d.scrollbarFiller.style.width = sizes.right + "px"
	  } else { d.scrollbarFiller.style.display = "" }
	  if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
	    d.gutterFiller.style.display = "block"
	    d.gutterFiller.style.height = sizes.bottom + "px"
	    d.gutterFiller.style.width = measure.gutterWidth + "px"
	  } else { d.gutterFiller.style.display = "" }
	}
	
	var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}
	
	function initScrollbars(cm) {
	  if (cm.display.scrollbars) {
	    cm.display.scrollbars.clear()
	    if (cm.display.scrollbars.addClass)
	      { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass) }
	  }
	
	  cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) {
	    cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller)
	    // Prevent clicks in the scrollbars from killing focus
	    on(node, "mousedown", function () {
	      if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0) }
	    })
	    node.setAttribute("cm-not-content", "true")
	  }, function (pos, axis) {
	    if (axis == "horizontal") { setScrollLeft(cm, pos) }
	    else { setScrollTop(cm, pos) }
	  }, cm)
	  if (cm.display.scrollbars.addClass)
	    { addClass(cm.display.wrapper, cm.display.scrollbars.addClass) }
	}
	
	// SCROLLING THINGS INTO VIEW
	
	// If an editor sits on the top or bottom of the window, partially
	// scrolled out of view, this ensures that the cursor is visible.
	function maybeScrollWindow(cm, coords) {
	  if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }
	
	  var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null
	  if (coords.top + box.top < 0) { doScroll = true }
	  else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false }
	  if (doScroll != null && !phantom) {
	    var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n                         top: " + (coords.top - display.viewOffset - paddingTop(cm.display)) + "px;\n                         height: " + (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px;\n                         left: " + (coords.left) + "px; width: 2px;"))
	    cm.display.lineSpace.appendChild(scrollNode)
	    scrollNode.scrollIntoView(doScroll)
	    cm.display.lineSpace.removeChild(scrollNode)
	  }
	}
	
	// Scroll a given position into view (immediately), verifying that
	// it actually became visible (as line heights are accurately
	// measured, the position of something may 'drift' during drawing).
	function scrollPosIntoView(cm, pos, end, margin) {
	  if (margin == null) { margin = 0 }
	  var coords
	  for (var limit = 0; limit < 5; limit++) {
	    var changed = false
	    coords = cursorCoords(cm, pos)
	    var endCoords = !end || end == pos ? coords : cursorCoords(cm, end)
	    var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
	                                       Math.min(coords.top, endCoords.top) - margin,
	                                       Math.max(coords.left, endCoords.left),
	                                       Math.max(coords.bottom, endCoords.bottom) + margin)
	    var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft
	    if (scrollPos.scrollTop != null) {
	      setScrollTop(cm, scrollPos.scrollTop)
	      if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true }
	    }
	    if (scrollPos.scrollLeft != null) {
	      setScrollLeft(cm, scrollPos.scrollLeft)
	      if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true }
	    }
	    if (!changed) { break }
	  }
	  return coords
	}
	
	// Scroll a given set of coordinates into view (immediately).
	function scrollIntoView(cm, x1, y1, x2, y2) {
	  var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2)
	  if (scrollPos.scrollTop != null) { setScrollTop(cm, scrollPos.scrollTop) }
	  if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft) }
	}
	
	// Calculate a new scroll position needed to scroll the given
	// rectangle into view. Returns an object with scrollTop and
	// scrollLeft properties. When these are undefined, the
	// vertical/horizontal position does not need to be adjusted.
	function calculateScrollPos(cm, x1, y1, x2, y2) {
	  var display = cm.display, snapMargin = textHeight(cm.display)
	  if (y1 < 0) { y1 = 0 }
	  var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop
	  var screen = displayHeight(cm), result = {}
	  if (y2 - y1 > screen) { y2 = y1 + screen }
	  var docBottom = cm.doc.height + paddingVert(display)
	  var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin
	  if (y1 < screentop) {
	    result.scrollTop = atTop ? 0 : y1
	  } else if (y2 > screentop + screen) {
	    var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen)
	    if (newTop != screentop) { result.scrollTop = newTop }
	  }
	
	  var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft
	  var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0)
	  var tooWide = x2 - x1 > screenw
	  if (tooWide) { x2 = x1 + screenw }
	  if (x1 < 10)
	    { result.scrollLeft = 0 }
	  else if (x1 < screenleft)
	    { result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10)) }
	  else if (x2 > screenw + screenleft - 3)
	    { result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw }
	  return result
	}
	
	// Store a relative adjustment to the scroll position in the current
	// operation (to be applied when the operation finishes).
	function addToScrollPos(cm, left, top) {
	  if (left != null || top != null) { resolveScrollToPos(cm) }
	  if (left != null)
	    { cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left }
	  if (top != null)
	    { cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top }
	}
	
	// Make sure that at the end of the operation the current cursor is
	// shown.
	function ensureCursorVisible(cm) {
	  resolveScrollToPos(cm)
	  var cur = cm.getCursor(), from = cur, to = cur
	  if (!cm.options.lineWrapping) {
	    from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur
	    to = Pos(cur.line, cur.ch + 1)
	  }
	  cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true}
	}
	
	// When an operation has its scrollToPos property set, and another
	// scroll action is applied before the end of the operation, this
	// 'simulates' scrolling that position into view in a cheap way, so
	// that the effect of intermediate scroll commands is not ignored.
	function resolveScrollToPos(cm) {
	  var range = cm.curOp.scrollToPos
	  if (range) {
	    cm.curOp.scrollToPos = null
	    var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to)
	    var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
	                                  Math.min(from.top, to.top) - range.margin,
	                                  Math.max(from.right, to.right),
	                                  Math.max(from.bottom, to.bottom) + range.margin)
	    cm.scrollTo(sPos.scrollLeft, sPos.scrollTop)
	  }
	}
	
	// Operations are used to wrap a series of changes to the editor
	// state in such a way that each change won't have to update the
	// cursor and display (which would be awkward, slow, and
	// error-prone). Instead, display updates are batched and then all
	// combined and executed at once.
	
	var nextOpId = 0
	// Start a new operation.
	function startOperation(cm) {
	  cm.curOp = {
	    cm: cm,
	    viewChanged: false,      // Flag that indicates that lines might need to be redrawn
	    startHeight: cm.doc.height, // Used to detect need to update scrollbar
	    forceUpdate: false,      // Used to force a redraw
	    updateInput: null,       // Whether to reset the input textarea
	    typing: false,           // Whether this reset should be careful to leave existing text (for compositing)
	    changeObjs: null,        // Accumulated changes, for firing change events
	    cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
	    cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
	    selectionChanged: false, // Whether the selection needs to be redrawn
	    updateMaxLine: false,    // Set when the widest line needs to be determined anew
	    scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
	    scrollToPos: null,       // Used to scroll to a specific position
	    focus: false,
	    id: ++nextOpId           // Unique ID
	  }
	  pushOperation(cm.curOp)
	}
	
	// Finish an operation, updating the display and signalling delayed events
	function endOperation(cm) {
	  var op = cm.curOp
	  finishOperation(op, function (group) {
	    for (var i = 0; i < group.ops.length; i++)
	      { group.ops[i].cm.curOp = null }
	    endOperations(group)
	  })
	}
	
	// The DOM updates done when an operation finishes are batched so
	// that the minimum number of relayouts are required.
	function endOperations(group) {
	  var ops = group.ops
	  for (var i = 0; i < ops.length; i++) // Read DOM
	    { endOperation_R1(ops[i]) }
	  for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe)
	    { endOperation_W1(ops[i$1]) }
	  for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM
	    { endOperation_R2(ops[i$2]) }
	  for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe)
	    { endOperation_W2(ops[i$3]) }
	  for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM
	    { endOperation_finish(ops[i$4]) }
	}
	
	function endOperation_R1(op) {
	  var cm = op.cm, display = cm.display
	  maybeClipScrollbars(cm)
	  if (op.updateMaxLine) { findMaxLine(cm) }
	
	  op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
	    op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
	                       op.scrollToPos.to.line >= display.viewTo) ||
	    display.maxLineChanged && cm.options.lineWrapping
	  op.update = op.mustUpdate &&
	    new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate)
	}
	
	function endOperation_W1(op) {
	  op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update)
	}
	
	function endOperation_R2(op) {
	  var cm = op.cm, display = cm.display
	  if (op.updatedDisplay) { updateHeightsInViewport(cm) }
	
	  op.barMeasure = measureForScrollbars(cm)
	
	  // If the max line changed since it was last measured, measure it,
	  // and ensure the document's width matches it.
	  // updateDisplay_W2 will use these properties to do the actual resizing
	  if (display.maxLineChanged && !cm.options.lineWrapping) {
	    op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3
	    cm.display.sizerWidth = op.adjustWidthTo
	    op.barMeasure.scrollWidth =
	      Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth)
	    op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm))
	  }
	
	  if (op.updatedDisplay || op.selectionChanged)
	    { op.preparedSelection = display.input.prepareSelection(op.focus) }
	}
	
	function endOperation_W2(op) {
	  var cm = op.cm
	
	  if (op.adjustWidthTo != null) {
	    cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"
	    if (op.maxScrollLeft < cm.doc.scrollLeft)
	      { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true) }
	    cm.display.maxLineChanged = false
	  }
	
	  var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus())
	  if (op.preparedSelection)
	    { cm.display.input.showSelection(op.preparedSelection, takeFocus) }
	  if (op.updatedDisplay || op.startHeight != cm.doc.height)
	    { updateScrollbars(cm, op.barMeasure) }
	  if (op.updatedDisplay)
	    { setDocumentHeight(cm, op.barMeasure) }
	
	  if (op.selectionChanged) { restartBlink(cm) }
	
	  if (cm.state.focused && op.updateInput)
	    { cm.display.input.reset(op.typing) }
	  if (takeFocus) { ensureFocus(op.cm) }
	}
	
	function endOperation_finish(op) {
	  var cm = op.cm, display = cm.display, doc = cm.doc
	
	  if (op.updatedDisplay) { postUpdateDisplay(cm, op.update) }
	
	  // Abort mouse wheel delta measurement, when scrolling explicitly
	  if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
	    { display.wheelStartX = display.wheelStartY = null }
	
	  // Propagate the scroll position to the actual DOM scroller
	  if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
	    doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop))
	    display.scrollbars.setScrollTop(doc.scrollTop)
	    display.scroller.scrollTop = doc.scrollTop
	  }
	  if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
	    doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft))
	    display.scrollbars.setScrollLeft(doc.scrollLeft)
	    display.scroller.scrollLeft = doc.scrollLeft
	    alignHorizontally(cm)
	  }
	  // If we need to scroll a specific position into view, do so.
	  if (op.scrollToPos) {
	    var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
	                                   clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin)
	    if (op.scrollToPos.isCursor && cm.state.focused) { maybeScrollWindow(cm, coords) }
	  }
	
	  // Fire events for markers that are hidden/unidden by editing or
	  // undoing
	  var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers
	  if (hidden) { for (var i = 0; i < hidden.length; ++i)
	    { if (!hidden[i].lines.length) { signal(hidden[i], "hide") } } }
	  if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1)
	    { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide") } } }
	
	  if (display.wrapper.offsetHeight)
	    { doc.scrollTop = cm.display.scroller.scrollTop }
	
	  // Fire change events, and delayed event handlers
	  if (op.changeObjs)
	    { signal(cm, "changes", cm, op.changeObjs) }
	  if (op.update)
	    { op.update.finish() }
	}
	
	// Run the given function in an operation
	function runInOp(cm, f) {
	  if (cm.curOp) { return f() }
	  startOperation(cm)
	  try { return f() }
	  finally { endOperation(cm) }
	}
	// Wraps a function in an operation. Returns the wrapped function.
	function operation(cm, f) {
	  return function() {
	    if (cm.curOp) { return f.apply(cm, arguments) }
	    startOperation(cm)
	    try { return f.apply(cm, arguments) }
	    finally { endOperation(cm) }
	  }
	}
	// Used to add methods to editor and doc instances, wrapping them in
	// operations.
	function methodOp(f) {
	  return function() {
	    if (this.curOp) { return f.apply(this, arguments) }
	    startOperation(this)
	    try { return f.apply(this, arguments) }
	    finally { endOperation(this) }
	  }
	}
	function docMethodOp(f) {
	  return function() {
	    var cm = this.cm
	    if (!cm || cm.curOp) { return f.apply(this, arguments) }
	    startOperation(cm)
	    try { return f.apply(this, arguments) }
	    finally { endOperation(cm) }
	  }
	}
	
	// Updates the display.view data structure for a given change to the
	// document. From and to are in pre-change coordinates. Lendiff is
	// the amount of lines added or subtracted by the change. This is
	// used for changes that span multiple lines, or change the way
	// lines are divided into visual lines. regLineChange (below)
	// registers single-line changes.
	function regChange(cm, from, to, lendiff) {
	  if (from == null) { from = cm.doc.first }
	  if (to == null) { to = cm.doc.first + cm.doc.size }
	  if (!lendiff) { lendiff = 0 }
	
	  var display = cm.display
	  if (lendiff && to < display.viewTo &&
	      (display.updateLineNumbers == null || display.updateLineNumbers > from))
	    { display.updateLineNumbers = from }
	
	  cm.curOp.viewChanged = true
	
	  if (from >= display.viewTo) { // Change after
	    if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
	      { resetView(cm) }
	  } else if (to <= display.viewFrom) { // Change before
	    if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
	      resetView(cm)
	    } else {
	      display.viewFrom += lendiff
	      display.viewTo += lendiff
	    }
	  } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
	    resetView(cm)
	  } else if (from <= display.viewFrom) { // Top overlap
	    var cut = viewCuttingPoint(cm, to, to + lendiff, 1)
	    if (cut) {
	      display.view = display.view.slice(cut.index)
	      display.viewFrom = cut.lineN
	      display.viewTo += lendiff
	    } else {
	      resetView(cm)
	    }
	  } else if (to >= display.viewTo) { // Bottom overlap
	    var cut$1 = viewCuttingPoint(cm, from, from, -1)
	    if (cut$1) {
	      display.view = display.view.slice(0, cut$1.index)
	      display.viewTo = cut$1.lineN
	    } else {
	      resetView(cm)
	    }
	  } else { // Gap in the middle
	    var cutTop = viewCuttingPoint(cm, from, from, -1)
	    var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1)
	    if (cutTop && cutBot) {
	      display.view = display.view.slice(0, cutTop.index)
	        .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
	        .concat(display.view.slice(cutBot.index))
	      display.viewTo += lendiff
	    } else {
	      resetView(cm)
	    }
	  }
	
	  var ext = display.externalMeasured
	  if (ext) {
	    if (to < ext.lineN)
	      { ext.lineN += lendiff }
	    else if (from < ext.lineN + ext.size)
	      { display.externalMeasured = null }
	  }
	}
	
	// Register a change to a single line. Type must be one of "text",
	// "gutter", "class", "widget"
	function regLineChange(cm, line, type) {
	  cm.curOp.viewChanged = true
	  var display = cm.display, ext = cm.display.externalMeasured
	  if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
	    { display.externalMeasured = null }
	
	  if (line < display.viewFrom || line >= display.viewTo) { return }
	  var lineView = display.view[findViewIndex(cm, line)]
	  if (lineView.node == null) { return }
	  var arr = lineView.changes || (lineView.changes = [])
	  if (indexOf(arr, type) == -1) { arr.push(type) }
	}
	
	// Clear the view.
	function resetView(cm) {
	  cm.display.viewFrom = cm.display.viewTo = cm.doc.first
	  cm.display.view = []
	  cm.display.viewOffset = 0
	}
	
	function viewCuttingPoint(cm, oldN, newN, dir) {
	  var index = findViewIndex(cm, oldN), diff, view = cm.display.view
	  if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
	    { return {index: index, lineN: newN} }
	  var n = cm.display.viewFrom
	  for (var i = 0; i < index; i++)
	    { n += view[i].size }
	  if (n != oldN) {
	    if (dir > 0) {
	      if (index == view.length - 1) { return null }
	      diff = (n + view[index].size) - oldN
	      index++
	    } else {
	      diff = n - oldN
	    }
	    oldN += diff; newN += diff
	  }
	  while (visualLineNo(cm.doc, newN) != newN) {
	    if (index == (dir < 0 ? 0 : view.length - 1)) { return null }
	    newN += dir * view[index - (dir < 0 ? 1 : 0)].size
	    index += dir
	  }
	  return {index: index, lineN: newN}
	}
	
	// Force the view to cover a given range, adding empty view element
	// or clipping off existing ones as needed.
	function adjustView(cm, from, to) {
	  var display = cm.display, view = display.view
	  if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
	    display.view = buildViewArray(cm, from, to)
	    display.viewFrom = from
	  } else {
	    if (display.viewFrom > from)
	      { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view) }
	    else if (display.viewFrom < from)
	      { display.view = display.view.slice(findViewIndex(cm, from)) }
	    display.viewFrom = from
	    if (display.viewTo < to)
	      { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)) }
	    else if (display.viewTo > to)
	      { display.view = display.view.slice(0, findViewIndex(cm, to)) }
	  }
	  display.viewTo = to
	}
	
	// Count the number of lines in the view whose DOM representation is
	// out of date (or nonexistent).
	function countDirtyView(cm) {
	  var view = cm.display.view, dirty = 0
	  for (var i = 0; i < view.length; i++) {
	    var lineView = view[i]
	    if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty }
	  }
	  return dirty
	}
	
	// HIGHLIGHT WORKER
	
	function startWorker(cm, time) {
	  if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
	    { cm.state.highlight.set(time, bind(highlightWorker, cm)) }
	}
	
	function highlightWorker(cm) {
	  var doc = cm.doc
	  if (doc.frontier < doc.first) { doc.frontier = doc.first }
	  if (doc.frontier >= cm.display.viewTo) { return }
	  var end = +new Date + cm.options.workTime
	  var state = copyState(doc.mode, getStateBefore(cm, doc.frontier))
	  var changedLines = []
	
	  doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) {
	    if (doc.frontier >= cm.display.viewFrom) { // Visible
	      var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength
	      var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true)
	      line.styles = highlighted.styles
	      var oldCls = line.styleClasses, newCls = highlighted.classes
	      if (newCls) { line.styleClasses = newCls }
	      else if (oldCls) { line.styleClasses = null }
	      var ischange = !oldStyles || oldStyles.length != line.styles.length ||
	        oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass)
	      for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i] }
	      if (ischange) { changedLines.push(doc.frontier) }
	      line.stateAfter = tooLong ? state : copyState(doc.mode, state)
	    } else {
	      if (line.text.length <= cm.options.maxHighlightLength)
	        { processLine(cm, line.text, state) }
	      line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null
	    }
	    ++doc.frontier
	    if (+new Date > end) {
	      startWorker(cm, cm.options.workDelay)
	      return true
	    }
	  })
	  if (changedLines.length) { runInOp(cm, function () {
	    for (var i = 0; i < changedLines.length; i++)
	      { regLineChange(cm, changedLines[i], "text") }
	  }) }
	}
	
	// DISPLAY DRAWING
	
	var DisplayUpdate = function(cm, viewport, force) {
	  var display = cm.display
	
	  this.viewport = viewport
	  // Store some values that we'll need later (but don't want to force a relayout for)
	  this.visible = visibleLines(display, cm.doc, viewport)
	  this.editorIsHidden = !display.wrapper.offsetWidth
	  this.wrapperHeight = display.wrapper.clientHeight
	  this.wrapperWidth = display.wrapper.clientWidth
	  this.oldDisplayWidth = displayWidth(cm)
	  this.force = force
	  this.dims = getDimensions(cm)
	  this.events = []
	};
	
	DisplayUpdate.prototype.signal = function (emitter, type) {
	  if (hasHandler(emitter, type))
	    { this.events.push(arguments) }
	};
	DisplayUpdate.prototype.finish = function () {
	    var this$1 = this;
	
	  for (var i = 0; i < this.events.length; i++)
	    { signal.apply(null, this$1.events[i]) }
	};
	
	function maybeClipScrollbars(cm) {
	  var display = cm.display
	  if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
	    display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth
	    display.heightForcer.style.height = scrollGap(cm) + "px"
	    display.sizer.style.marginBottom = -display.nativeBarWidth + "px"
	    display.sizer.style.borderRightWidth = scrollGap(cm) + "px"
	    display.scrollbarsClipped = true
	  }
	}
	
	// Does the actual updating of the line display. Bails out
	// (returning false) when there is nothing to be done and forced is
	// false.
	function updateDisplayIfNeeded(cm, update) {
	  var display = cm.display, doc = cm.doc
	
	  if (update.editorIsHidden) {
	    resetView(cm)
	    return false
	  }
	
	  // Bail out if the visible area is already rendered and nothing changed.
	  if (!update.force &&
	      update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
	      (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
	      display.renderedView == display.view && countDirtyView(cm) == 0)
	    { return false }
	
	  if (maybeUpdateLineNumberWidth(cm)) {
	    resetView(cm)
	    update.dims = getDimensions(cm)
	  }
	
	  // Compute a suitable new viewport (from & to)
	  var end = doc.first + doc.size
	  var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first)
	  var to = Math.min(end, update.visible.to + cm.options.viewportMargin)
	  if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom) }
	  if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo) }
	  if (sawCollapsedSpans) {
	    from = visualLineNo(cm.doc, from)
	    to = visualLineEndNo(cm.doc, to)
	  }
	
	  var different = from != display.viewFrom || to != display.viewTo ||
	    display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth
	  adjustView(cm, from, to)
	
	  display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom))
	  // Position the mover div to align with the current scroll position
	  cm.display.mover.style.top = display.viewOffset + "px"
	
	  var toUpdate = countDirtyView(cm)
	  if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
	      (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
	    { return false }
	
	  // For big changes, we hide the enclosing element during the
	  // update, since that speeds up the operations on most browsers.
	  var focused = activeElt()
	  if (toUpdate > 4) { display.lineDiv.style.display = "none" }
	  patchDisplay(cm, display.updateLineNumbers, update.dims)
	  if (toUpdate > 4) { display.lineDiv.style.display = "" }
	  display.renderedView = display.view
	  // There might have been a widget with a focused element that got
	  // hidden or updated, if so re-focus it.
	  if (focused && activeElt() != focused && focused.offsetHeight) { focused.focus() }
	
	  // Prevent selection and cursors from interfering with the scroll
	  // width and height.
	  removeChildren(display.cursorDiv)
	  removeChildren(display.selectionDiv)
	  display.gutters.style.height = display.sizer.style.minHeight = 0
	
	  if (different) {
	    display.lastWrapHeight = update.wrapperHeight
	    display.lastWrapWidth = update.wrapperWidth
	    startWorker(cm, 400)
	  }
	
	  display.updateLineNumbers = null
	
	  return true
	}
	
	function postUpdateDisplay(cm, update) {
	  var viewport = update.viewport
	
	  for (var first = true;; first = false) {
	    if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
	      // Clip forced viewport to actual scrollable area.
	      if (viewport && viewport.top != null)
	        { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)} }
	      // Updated line heights might result in the drawn area not
	      // actually covering the viewport. Keep looping until it does.
	      update.visible = visibleLines(cm.display, cm.doc, viewport)
	      if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
	        { break }
	    }
	    if (!updateDisplayIfNeeded(cm, update)) { break }
	    updateHeightsInViewport(cm)
	    var barMeasure = measureForScrollbars(cm)
	    updateSelection(cm)
	    updateScrollbars(cm, barMeasure)
	    setDocumentHeight(cm, barMeasure)
	  }
	
	  update.signal(cm, "update", cm)
	  if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
	    update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo)
	    cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo
	  }
	}
	
	function updateDisplaySimple(cm, viewport) {
	  var update = new DisplayUpdate(cm, viewport)
	  if (updateDisplayIfNeeded(cm, update)) {
	    updateHeightsInViewport(cm)
	    postUpdateDisplay(cm, update)
	    var barMeasure = measureForScrollbars(cm)
	    updateSelection(cm)
	    updateScrollbars(cm, barMeasure)
	    setDocumentHeight(cm, barMeasure)
	    update.finish()
	  }
	}
	
	// Sync the actual display DOM structure with display.view, removing
	// nodes for lines that are no longer in view, and creating the ones
	// that are not there yet, and updating the ones that are out of
	// date.
	function patchDisplay(cm, updateNumbersFrom, dims) {
	  var display = cm.display, lineNumbers = cm.options.lineNumbers
	  var container = display.lineDiv, cur = container.firstChild
	
	  function rm(node) {
	    var next = node.nextSibling
	    // Works around a throw-scroll bug in OS X Webkit
	    if (webkit && mac && cm.display.currentWheelTarget == node)
	      { node.style.display = "none" }
	    else
	      { node.parentNode.removeChild(node) }
	    return next
	  }
	
	  var view = display.view, lineN = display.viewFrom
	  // Loop over the elements in the view, syncing cur (the DOM nodes
	  // in display.lineDiv) with the view as we go.
	  for (var i = 0; i < view.length; i++) {
	    var lineView = view[i]
	    if (lineView.hidden) {
	    } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
	      var node = buildLineElement(cm, lineView, lineN, dims)
	      container.insertBefore(node, cur)
	    } else { // Already drawn
	      while (cur != lineView.node) { cur = rm(cur) }
	      var updateNumber = lineNumbers && updateNumbersFrom != null &&
	        updateNumbersFrom <= lineN && lineView.lineNumber
	      if (lineView.changes) {
	        if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false }
	        updateLineForChanges(cm, lineView, lineN, dims)
	      }
	      if (updateNumber) {
	        removeChildren(lineView.lineNumber)
	        lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)))
	      }
	      cur = lineView.node.nextSibling
	    }
	    lineN += lineView.size
	  }
	  while (cur) { cur = rm(cur) }
	}
	
	function updateGutterSpace(cm) {
	  var width = cm.display.gutters.offsetWidth
	  cm.display.sizer.style.marginLeft = width + "px"
	}
	
	function setDocumentHeight(cm, measure) {
	  cm.display.sizer.style.minHeight = measure.docHeight + "px"
	  cm.display.heightForcer.style.top = measure.docHeight + "px"
	  cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"
	}
	
	// Rebuild the gutter elements, ensure the margin to the left of the
	// code matches their width.
	function updateGutters(cm) {
	  var gutters = cm.display.gutters, specs = cm.options.gutters
	  removeChildren(gutters)
	  var i = 0
	  for (; i < specs.length; ++i) {
	    var gutterClass = specs[i]
	    var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass))
	    if (gutterClass == "CodeMirror-linenumbers") {
	      cm.display.lineGutter = gElt
	      gElt.style.width = (cm.display.lineNumWidth || 1) + "px"
	    }
	  }
	  gutters.style.display = i ? "" : "none"
	  updateGutterSpace(cm)
	}
	
	// Make sure the gutters options contains the element
	// "CodeMirror-linenumbers" when the lineNumbers option is true.
	function setGuttersForLineNumbers(options) {
	  var found = indexOf(options.gutters, "CodeMirror-linenumbers")
	  if (found == -1 && options.lineNumbers) {
	    options.gutters = options.gutters.concat(["CodeMirror-linenumbers"])
	  } else if (found > -1 && !options.lineNumbers) {
	    options.gutters = options.gutters.slice(0)
	    options.gutters.splice(found, 1)
	  }
	}
	
	// Selection objects are immutable. A new one is created every time
	// the selection changes. A selection is one or more non-overlapping
	// (and non-touching) ranges, sorted, and an integer that indicates
	// which one is the primary selection (the one that's scrolled into
	// view, that getCursor returns, etc).
	function Selection(ranges, primIndex) {
	  this.ranges = ranges
	  this.primIndex = primIndex
	}
	
	Selection.prototype = {
	  primary: function() { return this.ranges[this.primIndex] },
	  equals: function(other) {
	    var this$1 = this;
	
	    if (other == this) { return true }
	    if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false }
	    for (var i = 0; i < this.ranges.length; i++) {
	      var here = this$1.ranges[i], there = other.ranges[i]
	      if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) { return false }
	    }
	    return true
	  },
	  deepCopy: function() {
	    var this$1 = this;
	
	    var out = []
	    for (var i = 0; i < this.ranges.length; i++)
	      { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)) }
	    return new Selection(out, this.primIndex)
	  },
	  somethingSelected: function() {
	    var this$1 = this;
	
	    for (var i = 0; i < this.ranges.length; i++)
	      { if (!this$1.ranges[i].empty()) { return true } }
	    return false
	  },
	  contains: function(pos, end) {
	    var this$1 = this;
	
	    if (!end) { end = pos }
	    for (var i = 0; i < this.ranges.length; i++) {
	      var range = this$1.ranges[i]
	      if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
	        { return i }
	    }
	    return -1
	  }
	}
	
	function Range(anchor, head) {
	  this.anchor = anchor; this.head = head
	}
	
	Range.prototype = {
	  from: function() { return minPos(this.anchor, this.head) },
	  to: function() { return maxPos(this.anchor, this.head) },
	  empty: function() {
	    return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch
	  }
	}
	
	// Take an unsorted, potentially overlapping set of ranges, and
	// build a selection out of it. 'Consumes' ranges array (modifying
	// it).
	function normalizeSelection(ranges, primIndex) {
	  var prim = ranges[primIndex]
	  ranges.sort(function (a, b) { return cmp(a.from(), b.from()); })
	  primIndex = indexOf(ranges, prim)
	  for (var i = 1; i < ranges.length; i++) {
	    var cur = ranges[i], prev = ranges[i - 1]
	    if (cmp(prev.to(), cur.from()) >= 0) {
	      var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to())
	      var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head
	      if (i <= primIndex) { --primIndex }
	      ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to))
	    }
	  }
	  return new Selection(ranges, primIndex)
	}
	
	function simpleSelection(anchor, head) {
	  return new Selection([new Range(anchor, head || anchor)], 0)
	}
	
	// Compute the position of the end of a change (its 'to' property
	// refers to the pre-change end).
	function changeEnd(change) {
	  if (!change.text) { return change.to }
	  return Pos(change.from.line + change.text.length - 1,
	             lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0))
	}
	
	// Adjust a position to refer to the post-change position of the
	// same text, or the end of the change if the change covers it.
	function adjustForChange(pos, change) {
	  if (cmp(pos, change.from) < 0) { return pos }
	  if (cmp(pos, change.to) <= 0) { return changeEnd(change) }
	
	  var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch
	  if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch }
	  return Pos(line, ch)
	}
	
	function computeSelAfterChange(doc, change) {
	  var out = []
	  for (var i = 0; i < doc.sel.ranges.length; i++) {
	    var range = doc.sel.ranges[i]
	    out.push(new Range(adjustForChange(range.anchor, change),
	                       adjustForChange(range.head, change)))
	  }
	  return normalizeSelection(out, doc.sel.primIndex)
	}
	
	function offsetPos(pos, old, nw) {
	  if (pos.line == old.line)
	    { return Pos(nw.line, pos.ch - old.ch + nw.ch) }
	  else
	    { return Pos(nw.line + (pos.line - old.line), pos.ch) }
	}
	
	// Used by replaceSelections to allow moving the selection to the
	// start or around the replaced test. Hint may be "start" or "around".
	function computeReplacedSel(doc, changes, hint) {
	  var out = []
	  var oldPrev = Pos(doc.first, 0), newPrev = oldPrev
	  for (var i = 0; i < changes.length; i++) {
	    var change = changes[i]
	    var from = offsetPos(change.from, oldPrev, newPrev)
	    var to = offsetPos(changeEnd(change), oldPrev, newPrev)
	    oldPrev = change.to
	    newPrev = to
	    if (hint == "around") {
	      var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0
	      out[i] = new Range(inv ? to : from, inv ? from : to)
	    } else {
	      out[i] = new Range(from, from)
	    }
	  }
	  return new Selection(out, doc.sel.primIndex)
	}
	
	// Used to get the editor into a consistent state again when options change.
	
	function loadMode(cm) {
	  cm.doc.mode = getMode(cm.options, cm.doc.modeOption)
	  resetModeState(cm)
	}
	
	function resetModeState(cm) {
	  cm.doc.iter(function (line) {
	    if (line.stateAfter) { line.stateAfter = null }
	    if (line.styles) { line.styles = null }
	  })
	  cm.doc.frontier = cm.doc.first
	  startWorker(cm, 100)
	  cm.state.modeGen++
	  if (cm.curOp) { regChange(cm) }
	}
	
	// DOCUMENT DATA STRUCTURE
	
	// By default, updates that start and end at the beginning of a line
	// are treated specially, in order to make the association of line
	// widgets and marker elements with the text behave more intuitive.
	function isWholeLineUpdate(doc, change) {
	  return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
	    (!doc.cm || doc.cm.options.wholeLineUpdateBefore)
	}
	
	// Perform a change on the document data structure.
	function updateDoc(doc, change, markedSpans, estimateHeight) {
	  function spansFor(n) {return markedSpans ? markedSpans[n] : null}
	  function update(line, text, spans) {
	    updateLine(line, text, spans, estimateHeight)
	    signalLater(line, "change", line, change)
	  }
	  function linesFor(start, end) {
	    var result = []
	    for (var i = start; i < end; ++i)
	      { result.push(new Line(text[i], spansFor(i), estimateHeight)) }
	    return result
	  }
	
	  var from = change.from, to = change.to, text = change.text
	  var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line)
	  var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line
	
	  // Adjust the line structure
	  if (change.full) {
	    doc.insert(0, linesFor(0, text.length))
	    doc.remove(text.length, doc.size - text.length)
	  } else if (isWholeLineUpdate(doc, change)) {
	    // This is a whole-line replace. Treated specially to make
	    // sure line objects move the way they are supposed to.
	    var added = linesFor(0, text.length - 1)
	    update(lastLine, lastLine.text, lastSpans)
	    if (nlines) { doc.remove(from.line, nlines) }
	    if (added.length) { doc.insert(from.line, added) }
	  } else if (firstLine == lastLine) {
	    if (text.length == 1) {
	      update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans)
	    } else {
	      var added$1 = linesFor(1, text.length - 1)
	      added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight))
	      update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0))
	      doc.insert(from.line + 1, added$1)
	    }
	  } else if (text.length == 1) {
	    update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0))
	    doc.remove(from.line + 1, nlines)
	  } else {
	    update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0))
	    update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans)
	    var added$2 = linesFor(1, text.length - 1)
	    if (nlines > 1) { doc.remove(from.line + 1, nlines - 1) }
	    doc.insert(from.line + 1, added$2)
	  }
	
	  signalLater(doc, "change", doc, change)
	}
	
	// Call f for all linked documents.
	function linkedDocs(doc, f, sharedHistOnly) {
	  function propagate(doc, skip, sharedHist) {
	    if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) {
	      var rel = doc.linked[i]
	      if (rel.doc == skip) { continue }
	      var shared = sharedHist && rel.sharedHist
	      if (sharedHistOnly && !shared) { continue }
	      f(rel.doc, shared)
	      propagate(rel.doc, doc, shared)
	    } }
	  }
	  propagate(doc, null, true)
	}
	
	// Attach a document to an editor.
	function attachDoc(cm, doc) {
	  if (doc.cm) { throw new Error("This document is already in use.") }
	  cm.doc = doc
	  doc.cm = cm
	  estimateLineHeights(cm)
	  loadMode(cm)
	  if (!cm.options.lineWrapping) { findMaxLine(cm) }
	  cm.options.mode = doc.modeOption
	  regChange(cm)
	}
	
	function History(startGen) {
	  // Arrays of change events and selections. Doing something adds an
	  // event to done and clears undo. Undoing moves events from done
	  // to undone, redoing moves them in the other direction.
	  this.done = []; this.undone = []
	  this.undoDepth = Infinity
	  // Used to track when changes can be merged into a single undo
	  // event
	  this.lastModTime = this.lastSelTime = 0
	  this.lastOp = this.lastSelOp = null
	  this.lastOrigin = this.lastSelOrigin = null
	  // Used by the isClean() method
	  this.generation = this.maxGeneration = startGen || 1
	}
	
	// Create a history change event from an updateDoc-style change
	// object.
	function historyChangeFromChange(doc, change) {
	  var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}
	  attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1)
	  linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true)
	  return histChange
	}
	
	// Pop all selection events off the end of a history array. Stop at
	// a change event.
	function clearSelectionEvents(array) {
	  while (array.length) {
	    var last = lst(array)
	    if (last.ranges) { array.pop() }
	    else { break }
	  }
	}
	
	// Find the top change event in the history. Pop off selection
	// events that are in the way.
	function lastChangeEvent(hist, force) {
	  if (force) {
	    clearSelectionEvents(hist.done)
	    return lst(hist.done)
	  } else if (hist.done.length && !lst(hist.done).ranges) {
	    return lst(hist.done)
	  } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
	    hist.done.pop()
	    return lst(hist.done)
	  }
	}
	
	// Register a change in the history. Merges changes that are within
	// a single operation, or are close together with an origin that
	// allows merging (starting with "+") into a single event.
	function addChangeToHistory(doc, change, selAfter, opId) {
	  var hist = doc.history
	  hist.undone.length = 0
	  var time = +new Date, cur
	  var last
	
	  if ((hist.lastOp == opId ||
	       hist.lastOrigin == change.origin && change.origin &&
	       ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
	        change.origin.charAt(0) == "*")) &&
	      (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
	    // Merge this change into the last event
	    last = lst(cur.changes)
	    if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
	      // Optimized case for simple insertion -- don't want to add
	      // new changesets for every character typed
	      last.to = changeEnd(change)
	    } else {
	      // Add new sub-event
	      cur.changes.push(historyChangeFromChange(doc, change))
	    }
	  } else {
	    // Can not be merged, start a new event.
	    var before = lst(hist.done)
	    if (!before || !before.ranges)
	      { pushSelectionToHistory(doc.sel, hist.done) }
	    cur = {changes: [historyChangeFromChange(doc, change)],
	           generation: hist.generation}
	    hist.done.push(cur)
	    while (hist.done.length > hist.undoDepth) {
	      hist.done.shift()
	      if (!hist.done[0].ranges) { hist.done.shift() }
	    }
	  }
	  hist.done.push(selAfter)
	  hist.generation = ++hist.maxGeneration
	  hist.lastModTime = hist.lastSelTime = time
	  hist.lastOp = hist.lastSelOp = opId
	  hist.lastOrigin = hist.lastSelOrigin = change.origin
	
	  if (!last) { signal(doc, "historyAdded") }
	}
	
	function selectionEventCanBeMerged(doc, origin, prev, sel) {
	  var ch = origin.charAt(0)
	  return ch == "*" ||
	    ch == "+" &&
	    prev.ranges.length == sel.ranges.length &&
	    prev.somethingSelected() == sel.somethingSelected() &&
	    new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500)
	}
	
	// Called whenever the selection changes, sets the new selection as
	// the pending selection in the history, and pushes the old pending
	// selection into the 'done' array when it was significantly
	// different (in number of selected ranges, emptiness, or time).
	function addSelectionToHistory(doc, sel, opId, options) {
	  var hist = doc.history, origin = options && options.origin
	
	  // A new event is started when the previous origin does not match
	  // the current, or the origins don't allow matching. Origins
	  // starting with * are always merged, those starting with + are
	  // merged when similar and close together in time.
	  if (opId == hist.lastSelOp ||
	      (origin && hist.lastSelOrigin == origin &&
	       (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
	        selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
	    { hist.done[hist.done.length - 1] = sel }
	  else
	    { pushSelectionToHistory(sel, hist.done) }
	
	  hist.lastSelTime = +new Date
	  hist.lastSelOrigin = origin
	  hist.lastSelOp = opId
	  if (options && options.clearRedo !== false)
	    { clearSelectionEvents(hist.undone) }
	}
	
	function pushSelectionToHistory(sel, dest) {
	  var top = lst(dest)
	  if (!(top && top.ranges && top.equals(sel)))
	    { dest.push(sel) }
	}
	
	// Used to store marked span information in the history.
	function attachLocalSpans(doc, change, from, to) {
	  var existing = change["spans_" + doc.id], n = 0
	  doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) {
	    if (line.markedSpans)
	      { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans }
	    ++n
	  })
	}
	
	// When un/re-doing restores text containing marked spans, those
	// that have been explicitly cleared should not be restored.
	function removeClearedSpans(spans) {
	  if (!spans) { return null }
	  var out
	  for (var i = 0; i < spans.length; ++i) {
	    if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i) } }
	    else if (out) { out.push(spans[i]) }
	  }
	  return !out ? spans : out.length ? out : null
	}
	
	// Retrieve and filter the old marked spans stored in a change event.
	function getOldSpans(doc, change) {
	  var found = change["spans_" + doc.id]
	  if (!found) { return null }
	  var nw = []
	  for (var i = 0; i < change.text.length; ++i)
	    { nw.push(removeClearedSpans(found[i])) }
	  return nw
	}
	
	// Used for un/re-doing changes from the history. Combines the
	// result of computing the existing spans with the set of spans that
	// existed in the history (so that deleting around a span and then
	// undoing brings back the span).
	function mergeOldSpans(doc, change) {
	  var old = getOldSpans(doc, change)
	  var stretched = stretchSpansOverChange(doc, change)
	  if (!old) { return stretched }
	  if (!stretched) { return old }
	
	  for (var i = 0; i < old.length; ++i) {
	    var oldCur = old[i], stretchCur = stretched[i]
	    if (oldCur && stretchCur) {
	      spans: for (var j = 0; j < stretchCur.length; ++j) {
	        var span = stretchCur[j]
	        for (var k = 0; k < oldCur.length; ++k)
	          { if (oldCur[k].marker == span.marker) { continue spans } }
	        oldCur.push(span)
	      }
	    } else if (stretchCur) {
	      old[i] = stretchCur
	    }
	  }
	  return old
	}
	
	// Used both to provide a JSON-safe object in .getHistory, and, when
	// detaching a document, to split the history in two
	function copyHistoryArray(events, newGroup, instantiateSel) {
	  var copy = []
	  for (var i = 0; i < events.length; ++i) {
	    var event = events[i]
	    if (event.ranges) {
	      copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event)
	      continue
	    }
	    var changes = event.changes, newChanges = []
	    copy.push({changes: newChanges})
	    for (var j = 0; j < changes.length; ++j) {
	      var change = changes[j], m = (void 0)
	      newChanges.push({from: change.from, to: change.to, text: change.text})
	      if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) {
	        if (indexOf(newGroup, Number(m[1])) > -1) {
	          lst(newChanges)[prop] = change[prop]
	          delete change[prop]
	        }
	      } } }
	    }
	  }
	  return copy
	}
	
	// The 'scroll' parameter given to many of these indicated whether
	// the new cursor position should be scrolled into view after
	// modifying the selection.
	
	// If shift is held or the extend flag is set, extends a range to
	// include a given position (and optionally a second position).
	// Otherwise, simply returns the range between the given positions.
	// Used for cursor motion and such.
	function extendRange(doc, range, head, other) {
	  if (doc.cm && doc.cm.display.shift || doc.extend) {
	    var anchor = range.anchor
	    if (other) {
	      var posBefore = cmp(head, anchor) < 0
	      if (posBefore != (cmp(other, anchor) < 0)) {
	        anchor = head
	        head = other
	      } else if (posBefore != (cmp(head, other) < 0)) {
	        head = other
	      }
	    }
	    return new Range(anchor, head)
	  } else {
	    return new Range(other || head, head)
	  }
	}
	
	// Extend the primary selection range, discard the rest.
	function extendSelection(doc, head, other, options) {
	  setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options)
	}
	
	// Extend all selections (pos is an array of selections with length
	// equal the number of selections)
	function extendSelections(doc, heads, options) {
	  var out = []
	  for (var i = 0; i < doc.sel.ranges.length; i++)
	    { out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null) }
	  var newSel = normalizeSelection(out, doc.sel.primIndex)
	  setSelection(doc, newSel, options)
	}
	
	// Updates a single range in the selection.
	function replaceOneSelection(doc, i, range, options) {
	  var ranges = doc.sel.ranges.slice(0)
	  ranges[i] = range
	  setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options)
	}
	
	// Reset the selection to a single range.
	function setSimpleSelection(doc, anchor, head, options) {
	  setSelection(doc, simpleSelection(anchor, head), options)
	}
	
	// Give beforeSelectionChange handlers a change to influence a
	// selection update.
	function filterSelectionChange(doc, sel, options) {
	  var obj = {
	    ranges: sel.ranges,
	    update: function(ranges) {
	      var this$1 = this;
	
	      this.ranges = []
	      for (var i = 0; i < ranges.length; i++)
	        { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
	                                   clipPos(doc, ranges[i].head)) }
	    },
	    origin: options && options.origin
	  }
	  signal(doc, "beforeSelectionChange", doc, obj)
	  if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj) }
	  if (obj.ranges != sel.ranges) { return normalizeSelection(obj.ranges, obj.ranges.length - 1) }
	  else { return sel }
	}
	
	function setSelectionReplaceHistory(doc, sel, options) {
	  var done = doc.history.done, last = lst(done)
	  if (last && last.ranges) {
	    done[done.length - 1] = sel
	    setSelectionNoUndo(doc, sel, options)
	  } else {
	    setSelection(doc, sel, options)
	  }
	}
	
	// Set a new selection.
	function setSelection(doc, sel, options) {
	  setSelectionNoUndo(doc, sel, options)
	  addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options)
	}
	
	function setSelectionNoUndo(doc, sel, options) {
	  if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
	    { sel = filterSelectionChange(doc, sel, options) }
	
	  var bias = options && options.bias ||
	    (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1)
	  setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true))
	
	  if (!(options && options.scroll === false) && doc.cm)
	    { ensureCursorVisible(doc.cm) }
	}
	
	function setSelectionInner(doc, sel) {
	  if (sel.equals(doc.sel)) { return }
	
	  doc.sel = sel
	
	  if (doc.cm) {
	    doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true
	    signalCursorActivity(doc.cm)
	  }
	  signalLater(doc, "cursorActivity", doc)
	}
	
	// Verify that the selection does not partially select any atomic
	// marked ranges.
	function reCheckSelection(doc) {
	  setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll)
	}
	
	// Return a selection that does not partially select any atomic
	// ranges.
	function skipAtomicInSelection(doc, sel, bias, mayClear) {
	  var out
	  for (var i = 0; i < sel.ranges.length; i++) {
	    var range = sel.ranges[i]
	    var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]
	    var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear)
	    var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear)
	    if (out || newAnchor != range.anchor || newHead != range.head) {
	      if (!out) { out = sel.ranges.slice(0, i) }
	      out[i] = new Range(newAnchor, newHead)
	    }
	  }
	  return out ? normalizeSelection(out, sel.primIndex) : sel
	}
	
	function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
	  var line = getLine(doc, pos.line)
	  if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
	    var sp = line.markedSpans[i], m = sp.marker
	    if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
	        (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
	      if (mayClear) {
	        signal(m, "beforeCursorEnter")
	        if (m.explicitlyCleared) {
	          if (!line.markedSpans) { break }
	          else {--i; continue}
	        }
	      }
	      if (!m.atomic) { continue }
	
	      if (oldPos) {
	        var near = m.find(dir < 0 ? 1 : -1), diff = (void 0)
	        if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft)
	          { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null) }
	        if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
	          { return skipAtomicInner(doc, near, pos, dir, mayClear) }
	      }
	
	      var far = m.find(dir < 0 ? -1 : 1)
	      if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight)
	        { far = movePos(doc, far, dir, far.line == pos.line ? line : null) }
	      return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null
	    }
	  } }
	  return pos
	}
	
	// Ensure a given position is not inside an atomic range.
	function skipAtomic(doc, pos, oldPos, bias, mayClear) {
	  var dir = bias || 1
	  var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
	      (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
	      skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
	      (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true))
	  if (!found) {
	    doc.cantEdit = true
	    return Pos(doc.first, 0)
	  }
	  return found
	}
	
	function movePos(doc, pos, dir, line) {
	  if (dir < 0 && pos.ch == 0) {
	    if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) }
	    else { return null }
	  } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
	    if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) }
	    else { return null }
	  } else {
	    return new Pos(pos.line, pos.ch + dir)
	  }
	}
	
	function selectAll(cm) {
	  cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll)
	}
	
	// UPDATING
	
	// Allow "beforeChange" event handlers to influence a change
	function filterChange(doc, change, update) {
	  var obj = {
	    canceled: false,
	    from: change.from,
	    to: change.to,
	    text: change.text,
	    origin: change.origin,
	    cancel: function () { return obj.canceled = true; }
	  }
	  if (update) { obj.update = function (from, to, text, origin) {
	    if (from) { obj.from = clipPos(doc, from) }
	    if (to) { obj.to = clipPos(doc, to) }
	    if (text) { obj.text = text }
	    if (origin !== undefined) { obj.origin = origin }
	  } }
	  signal(doc, "beforeChange", doc, obj)
	  if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj) }
	
	  if (obj.canceled) { return null }
	  return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}
	}
	
	// Apply a change to a document, and add it to the document's
	// history, and propagating it to all linked documents.
	function makeChange(doc, change, ignoreReadOnly) {
	  if (doc.cm) {
	    if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) }
	    if (doc.cm.state.suppressEdits) { return }
	  }
	
	  if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
	    change = filterChange(doc, change, true)
	    if (!change) { return }
	  }
	
	  // Possibly split or suppress the update based on the presence
	  // of read-only spans in its range.
	  var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to)
	  if (split) {
	    for (var i = split.length - 1; i >= 0; --i)
	      { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}) }
	  } else {
	    makeChangeInner(doc, change)
	  }
	}
	
	function makeChangeInner(doc, change) {
	  if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return }
	  var selAfter = computeSelAfterChange(doc, change)
	  addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN)
	
	  makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change))
	  var rebased = []
	
	  linkedDocs(doc, function (doc, sharedHist) {
	    if (!sharedHist && indexOf(rebased, doc.history) == -1) {
	      rebaseHist(doc.history, change)
	      rebased.push(doc.history)
	    }
	    makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change))
	  })
	}
	
	// Revert a change stored in a document's history.
	function makeChangeFromHistory(doc, type, allowSelectionOnly) {
	  if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) { return }
	
	  var hist = doc.history, event, selAfter = doc.sel
	  var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done
	
	  // Verify that there is a useable event (so that ctrl-z won't
	  // needlessly clear selection events)
	  var i = 0
	  for (; i < source.length; i++) {
	    event = source[i]
	    if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
	      { break }
	  }
	  if (i == source.length) { return }
	  hist.lastOrigin = hist.lastSelOrigin = null
	
	  for (;;) {
	    event = source.pop()
	    if (event.ranges) {
	      pushSelectionToHistory(event, dest)
	      if (allowSelectionOnly && !event.equals(doc.sel)) {
	        setSelection(doc, event, {clearRedo: false})
	        return
	      }
	      selAfter = event
	    }
	    else { break }
	  }
	
	  // Build up a reverse change object to add to the opposite history
	  // stack (redo when undoing, and vice versa).
	  var antiChanges = []
	  pushSelectionToHistory(selAfter, dest)
	  dest.push({changes: antiChanges, generation: hist.generation})
	  hist.generation = event.generation || ++hist.maxGeneration
	
	  var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")
	
	  var loop = function ( i ) {
	    var change = event.changes[i]
	    change.origin = type
	    if (filter && !filterChange(doc, change, false)) {
	      source.length = 0
	      return {}
	    }
	
	    antiChanges.push(historyChangeFromChange(doc, change))
	
	    var after = i ? computeSelAfterChange(doc, change) : lst(source)
	    makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change))
	    if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}) }
	    var rebased = []
	
	    // Propagate to the linked documents
	    linkedDocs(doc, function (doc, sharedHist) {
	      if (!sharedHist && indexOf(rebased, doc.history) == -1) {
	        rebaseHist(doc.history, change)
	        rebased.push(doc.history)
	      }
	      makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change))
	    })
	  };
	
	  for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) {
	    var returned = loop( i$1 );
	
	    if ( returned ) return returned.v;
	  }
	}
	
	// Sub-views need their line numbers shifted when text is added
	// above or below them in the parent document.
	function shiftDoc(doc, distance) {
	  if (distance == 0) { return }
	  doc.first += distance
	  doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range(
	    Pos(range.anchor.line + distance, range.anchor.ch),
	    Pos(range.head.line + distance, range.head.ch)
	  ); }), doc.sel.primIndex)
	  if (doc.cm) {
	    regChange(doc.cm, doc.first, doc.first - distance, distance)
	    for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
	      { regLineChange(doc.cm, l, "gutter") }
	  }
	}
	
	// More lower-level change function, handling only a single document
	// (not linked ones).
	function makeChangeSingleDoc(doc, change, selAfter, spans) {
	  if (doc.cm && !doc.cm.curOp)
	    { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) }
	
	  if (change.to.line < doc.first) {
	    shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line))
	    return
	  }
	  if (change.from.line > doc.lastLine()) { return }
	
	  // Clip the change to the size of this doc
	  if (change.from.line < doc.first) {
	    var shift = change.text.length - 1 - (doc.first - change.from.line)
	    shiftDoc(doc, shift)
	    change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
	              text: [lst(change.text)], origin: change.origin}
	  }
	  var last = doc.lastLine()
	  if (change.to.line > last) {
	    change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
	              text: [change.text[0]], origin: change.origin}
	  }
	
	  change.removed = getBetween(doc, change.from, change.to)
	
	  if (!selAfter) { selAfter = computeSelAfterChange(doc, change) }
	  if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans) }
	  else { updateDoc(doc, change, spans) }
	  setSelectionNoUndo(doc, selAfter, sel_dontScroll)
	}
	
	// Handle the interaction of a change to a document with the editor
	// that this document is part of.
	function makeChangeSingleDocInEditor(cm, change, spans) {
	  var doc = cm.doc, display = cm.display, from = change.from, to = change.to
	
	  var recomputeMaxLength = false, checkWidthStart = from.line
	  if (!cm.options.lineWrapping) {
	    checkWidthStart = lineNo(visualLine(getLine(doc, from.line)))
	    doc.iter(checkWidthStart, to.line + 1, function (line) {
	      if (line == display.maxLine) {
	        recomputeMaxLength = true
	        return true
	      }
	    })
	  }
	
	  if (doc.sel.contains(change.from, change.to) > -1)
	    { signalCursorActivity(cm) }
	
	  updateDoc(doc, change, spans, estimateHeight(cm))
	
	  if (!cm.options.lineWrapping) {
	    doc.iter(checkWidthStart, from.line + change.text.length, function (line) {
	      var len = lineLength(line)
	      if (len > display.maxLineLength) {
	        display.maxLine = line
	        display.maxLineLength = len
	        display.maxLineChanged = true
	        recomputeMaxLength = false
	      }
	    })
	    if (recomputeMaxLength) { cm.curOp.updateMaxLine = true }
	  }
	
	  // Adjust frontier, schedule worker
	  doc.frontier = Math.min(doc.frontier, from.line)
	  startWorker(cm, 400)
	
	  var lendiff = change.text.length - (to.line - from.line) - 1
	  // Remember that these lines changed, for updating the display
	  if (change.full)
	    { regChange(cm) }
	  else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
	    { regLineChange(cm, from.line, "text") }
	  else
	    { regChange(cm, from.line, to.line + 1, lendiff) }
	
	  var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change")
	  if (changeHandler || changesHandler) {
	    var obj = {
	      from: from, to: to,
	      text: change.text,
	      removed: change.removed,
	      origin: change.origin
	    }
	    if (changeHandler) { signalLater(cm, "change", cm, obj) }
	    if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj) }
	  }
	  cm.display.selForContextMenu = null
	}
	
	function replaceRange(doc, code, from, to, origin) {
	  if (!to) { to = from }
	  if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp }
	  if (typeof code == "string") { code = doc.splitLines(code) }
	  makeChange(doc, {from: from, to: to, text: code, origin: origin})
	}
	
	// Rebasing/resetting history to deal with externally-sourced changes
	
	function rebaseHistSelSingle(pos, from, to, diff) {
	  if (to < pos.line) {
	    pos.line += diff
	  } else if (from < pos.line) {
	    pos.line = from
	    pos.ch = 0
	  }
	}
	
	// Tries to rebase an array of history events given a change in the
	// document. If the change touches the same lines as the event, the
	// event, and everything 'behind' it, is discarded. If the change is
	// before the event, the event's positions are updated. Uses a
	// copy-on-write scheme for the positions, to avoid having to
	// reallocate them all on every rebase, but also avoid problems with
	// shared position objects being unsafely updated.
	function rebaseHistArray(array, from, to, diff) {
	  for (var i = 0; i < array.length; ++i) {
	    var sub = array[i], ok = true
	    if (sub.ranges) {
	      if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true }
	      for (var j = 0; j < sub.ranges.length; j++) {
	        rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff)
	        rebaseHistSelSingle(sub.ranges[j].head, from, to, diff)
	      }
	      continue
	    }
	    for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) {
	      var cur = sub.changes[j$1]
	      if (to < cur.from.line) {
	        cur.from = Pos(cur.from.line + diff, cur.from.ch)
	        cur.to = Pos(cur.to.line + diff, cur.to.ch)
	      } else if (from <= cur.to.line) {
	        ok = false
	        break
	      }
	    }
	    if (!ok) {
	      array.splice(0, i + 1)
	      i = 0
	    }
	  }
	}
	
	function rebaseHist(hist, change) {
	  var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1
	  rebaseHistArray(hist.done, from, to, diff)
	  rebaseHistArray(hist.undone, from, to, diff)
	}
	
	// Utility for applying a change to a line by handle or number,
	// returning the number and optionally registering the line as
	// changed.
	function changeLine(doc, handle, changeType, op) {
	  var no = handle, line = handle
	  if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)) }
	  else { no = lineNo(handle) }
	  if (no == null) { return null }
	  if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType) }
	  return line
	}
	
	// The document is represented as a BTree consisting of leaves, with
	// chunk of lines in them, and branches, with up to ten leaves or
	// other branch nodes below them. The top node is always a branch
	// node, and is the document object itself (meaning it has
	// additional methods and properties).
	//
	// All nodes have parent links. The tree is used both to go from
	// line numbers to line objects, and to go from objects to numbers.
	// It also indexes by height, and is used to convert between height
	// and line object, and to find the total height of the document.
	//
	// See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
	
	function LeafChunk(lines) {
	  var this$1 = this;
	
	  this.lines = lines
	  this.parent = null
	  var height = 0
	  for (var i = 0; i < lines.length; ++i) {
	    lines[i].parent = this$1
	    height += lines[i].height
	  }
	  this.height = height
	}
	
	LeafChunk.prototype = {
	  chunkSize: function() { return this.lines.length },
	  // Remove the n lines at offset 'at'.
	  removeInner: function(at, n) {
	    var this$1 = this;
	
	    for (var i = at, e = at + n; i < e; ++i) {
	      var line = this$1.lines[i]
	      this$1.height -= line.height
	      cleanUpLine(line)
	      signalLater(line, "delete")
	    }
	    this.lines.splice(at, n)
	  },
	  // Helper used to collapse a small branch into a single leaf.
	  collapse: function(lines) {
	    lines.push.apply(lines, this.lines)
	  },
	  // Insert the given array of lines at offset 'at', count them as
	  // having the given height.
	  insertInner: function(at, lines, height) {
	    var this$1 = this;
	
	    this.height += height
	    this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at))
	    for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1 }
	  },
	  // Used to iterate over a part of the tree.
	  iterN: function(at, n, op) {
	    var this$1 = this;
	
	    for (var e = at + n; at < e; ++at)
	      { if (op(this$1.lines[at])) { return true } }
	  }
	}
	
	function BranchChunk(children) {
	  var this$1 = this;
	
	  this.children = children
	  var size = 0, height = 0
	  for (var i = 0; i < children.length; ++i) {
	    var ch = children[i]
	    size += ch.chunkSize(); height += ch.height
	    ch.parent = this$1
	  }
	  this.size = size
	  this.height = height
	  this.parent = null
	}
	
	BranchChunk.prototype = {
	  chunkSize: function() { return this.size },
	  removeInner: function(at, n) {
	    var this$1 = this;
	
	    this.size -= n
	    for (var i = 0; i < this.children.length; ++i) {
	      var child = this$1.children[i], sz = child.chunkSize()
	      if (at < sz) {
	        var rm = Math.min(n, sz - at), oldHeight = child.height
	        child.removeInner(at, rm)
	        this$1.height -= oldHeight - child.height
	        if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null }
	        if ((n -= rm) == 0) { break }
	        at = 0
	      } else { at -= sz }
	    }
	    // If the result is smaller than 25 lines, ensure that it is a
	    // single leaf node.
	    if (this.size - n < 25 &&
	        (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
	      var lines = []
	      this.collapse(lines)
	      this.children = [new LeafChunk(lines)]
	      this.children[0].parent = this
	    }
	  },
	  collapse: function(lines) {
	    var this$1 = this;
	
	    for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines) }
	  },
	  insertInner: function(at, lines, height) {
	    var this$1 = this;
	
	    this.size += lines.length
	    this.height += height
	    for (var i = 0; i < this.children.length; ++i) {
	      var child = this$1.children[i], sz = child.chunkSize()
	      if (at <= sz) {
	        child.insertInner(at, lines, height)
	        if (child.lines && child.lines.length > 50) {
	          // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced.
	          // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest.
	          var remaining = child.lines.length % 25 + 25
	          for (var pos = remaining; pos < child.lines.length;) {
	            var leaf = new LeafChunk(child.lines.slice(pos, pos += 25))
	            child.height -= leaf.height
	            this$1.children.splice(++i, 0, leaf)
	            leaf.parent = this$1
	          }
	          child.lines = child.lines.slice(0, remaining)
	          this$1.maybeSpill()
	        }
	        break
	      }
	      at -= sz
	    }
	  },
	  // When a node has grown, check whether it should be split.
	  maybeSpill: function() {
	    if (this.children.length <= 10) { return }
	    var me = this
	    do {
	      var spilled = me.children.splice(me.children.length - 5, 5)
	      var sibling = new BranchChunk(spilled)
	      if (!me.parent) { // Become the parent node
	        var copy = new BranchChunk(me.children)
	        copy.parent = me
	        me.children = [copy, sibling]
	        me = copy
	     } else {
	        me.size -= sibling.size
	        me.height -= sibling.height
	        var myIndex = indexOf(me.parent.children, me)
	        me.parent.children.splice(myIndex + 1, 0, sibling)
	      }
	      sibling.parent = me.parent
	    } while (me.children.length > 10)
	    me.parent.maybeSpill()
	  },
	  iterN: function(at, n, op) {
	    var this$1 = this;
	
	    for (var i = 0; i < this.children.length; ++i) {
	      var child = this$1.children[i], sz = child.chunkSize()
	      if (at < sz) {
	        var used = Math.min(n, sz - at)
	        if (child.iterN(at, used, op)) { return true }
	        if ((n -= used) == 0) { break }
	        at = 0
	      } else { at -= sz }
	    }
	  }
	}
	
	// Line widgets are block elements displayed above or below a line.
	
	function LineWidget(doc, node, options) {
	  var this$1 = this;
	
	  if (options) { for (var opt in options) { if (options.hasOwnProperty(opt))
	    { this$1[opt] = options[opt] } } }
	  this.doc = doc
	  this.node = node
	}
	eventMixin(LineWidget)
	
	function adjustScrollWhenAboveVisible(cm, line, diff) {
	  if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
	    { addToScrollPos(cm, null, diff) }
	}
	
	LineWidget.prototype.clear = function() {
	  var this$1 = this;
	
	  var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line)
	  if (no == null || !ws) { return }
	  for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1) } }
	  if (!ws.length) { line.widgets = null }
	  var height = widgetHeight(this)
	  updateLineHeight(line, Math.max(0, line.height - height))
	  if (cm) { runInOp(cm, function () {
	    adjustScrollWhenAboveVisible(cm, line, -height)
	    regLineChange(cm, no, "widget")
	  }) }
	}
	LineWidget.prototype.changed = function() {
	  var oldH = this.height, cm = this.doc.cm, line = this.line
	  this.height = null
	  var diff = widgetHeight(this) - oldH
	  if (!diff) { return }
	  updateLineHeight(line, line.height + diff)
	  if (cm) { runInOp(cm, function () {
	    cm.curOp.forceUpdate = true
	    adjustScrollWhenAboveVisible(cm, line, diff)
	  }) }
	}
	
	function addLineWidget(doc, handle, node, options) {
	  var widget = new LineWidget(doc, node, options)
	  var cm = doc.cm
	  if (cm && widget.noHScroll) { cm.display.alignWidgets = true }
	  changeLine(doc, handle, "widget", function (line) {
	    var widgets = line.widgets || (line.widgets = [])
	    if (widget.insertAt == null) { widgets.push(widget) }
	    else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget) }
	    widget.line = line
	    if (cm && !lineIsHidden(doc, line)) {
	      var aboveVisible = heightAtLine(line) < doc.scrollTop
	      updateLineHeight(line, line.height + widgetHeight(widget))
	      if (aboveVisible) { addToScrollPos(cm, null, widget.height) }
	      cm.curOp.forceUpdate = true
	    }
	    return true
	  })
	  return widget
	}
	
	// TEXTMARKERS
	
	// Created with markText and setBookmark methods. A TextMarker is a
	// handle that can be used to clear or find a marked position in the
	// document. Line objects hold arrays (markedSpans) containing
	// {from, to, marker} object pointing to such marker objects, and
	// indicating that such a marker is present on that line. Multiple
	// lines may point to the same marker when it spans across lines.
	// The spans will have null for their from/to properties when the
	// marker continues beyond the start/end of the line. Markers have
	// links back to the lines they currently touch.
	
	// Collapsed markers have unique ids, in order to be able to order
	// them, which is needed for uniquely determining an outer marker
	// when they overlap (they may nest, but not partially overlap).
	var nextMarkerId = 0
	
	function TextMarker(doc, type) {
	  this.lines = []
	  this.type = type
	  this.doc = doc
	  this.id = ++nextMarkerId
	}
	eventMixin(TextMarker)
	
	// Clear the marker.
	TextMarker.prototype.clear = function() {
	  var this$1 = this;
	
	  if (this.explicitlyCleared) { return }
	  var cm = this.doc.cm, withOp = cm && !cm.curOp
	  if (withOp) { startOperation(cm) }
	  if (hasHandler(this, "clear")) {
	    var found = this.find()
	    if (found) { signalLater(this, "clear", found.from, found.to) }
	  }
	  var min = null, max = null
	  for (var i = 0; i < this.lines.length; ++i) {
	    var line = this$1.lines[i]
	    var span = getMarkedSpanFor(line.markedSpans, this$1)
	    if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text") }
	    else if (cm) {
	      if (span.to != null) { max = lineNo(line) }
	      if (span.from != null) { min = lineNo(line) }
	    }
	    line.markedSpans = removeMarkedSpan(line.markedSpans, span)
	    if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm)
	      { updateLineHeight(line, textHeight(cm.display)) }
	  }
	  if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) {
	    var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual)
	    if (len > cm.display.maxLineLength) {
	      cm.display.maxLine = visual
	      cm.display.maxLineLength = len
	      cm.display.maxLineChanged = true
	    }
	  } }
	
	  if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1) }
	  this.lines.length = 0
	  this.explicitlyCleared = true
	  if (this.atomic && this.doc.cantEdit) {
	    this.doc.cantEdit = false
	    if (cm) { reCheckSelection(cm.doc) }
	  }
	  if (cm) { signalLater(cm, "markerCleared", cm, this) }
	  if (withOp) { endOperation(cm) }
	  if (this.parent) { this.parent.clear() }
	}
	
	// Find the position of the marker in the document. Returns a {from,
	// to} object by default. Side can be passed to get a specific side
	// -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
	// Pos objects returned contain a line object, rather than a line
	// number (used to prevent looking up the same line twice).
	TextMarker.prototype.find = function(side, lineObj) {
	  var this$1 = this;
	
	  if (side == null && this.type == "bookmark") { side = 1 }
	  var from, to
	  for (var i = 0; i < this.lines.length; ++i) {
	    var line = this$1.lines[i]
	    var span = getMarkedSpanFor(line.markedSpans, this$1)
	    if (span.from != null) {
	      from = Pos(lineObj ? line : lineNo(line), span.from)
	      if (side == -1) { return from }
	    }
	    if (span.to != null) {
	      to = Pos(lineObj ? line : lineNo(line), span.to)
	      if (side == 1) { return to }
	    }
	  }
	  return from && {from: from, to: to}
	}
	
	// Signals that the marker's widget changed, and surrounding layout
	// should be recomputed.
	TextMarker.prototype.changed = function() {
	  var pos = this.find(-1, true), widget = this, cm = this.doc.cm
	  if (!pos || !cm) { return }
	  runInOp(cm, function () {
	    var line = pos.line, lineN = lineNo(pos.line)
	    var view = findViewForLine(cm, lineN)
	    if (view) {
	      clearLineMeasurementCacheFor(view)
	      cm.curOp.selectionChanged = cm.curOp.forceUpdate = true
	    }
	    cm.curOp.updateMaxLine = true
	    if (!lineIsHidden(widget.doc, line) && widget.height != null) {
	      var oldHeight = widget.height
	      widget.height = null
	      var dHeight = widgetHeight(widget) - oldHeight
	      if (dHeight)
	        { updateLineHeight(line, line.height + dHeight) }
	    }
	  })
	}
	
	TextMarker.prototype.attachLine = function(line) {
	  if (!this.lines.length && this.doc.cm) {
	    var op = this.doc.cm.curOp
	    if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
	      { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this) }
	  }
	  this.lines.push(line)
	}
	TextMarker.prototype.detachLine = function(line) {
	  this.lines.splice(indexOf(this.lines, line), 1)
	  if (!this.lines.length && this.doc.cm) {
	    var op = this.doc.cm.curOp
	    ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this)
	  }
	}
	
	// Create a marker, wire it up to the right lines, and
	function markText(doc, from, to, options, type) {
	  // Shared markers (across linked documents) are handled separately
	  // (markTextShared will call out to this again, once per
	  // document).
	  if (options && options.shared) { return markTextShared(doc, from, to, options, type) }
	  // Ensure we are in an operation.
	  if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) }
	
	  var marker = new TextMarker(doc, type), diff = cmp(from, to)
	  if (options) { copyObj(options, marker, false) }
	  // Don't connect empty markers unless clearWhenEmpty is false
	  if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
	    { return marker }
	  if (marker.replacedWith) {
	    // Showing up as a widget implies collapsed (widget replaces text)
	    marker.collapsed = true
	    marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget")
	    marker.widgetNode.setAttribute("role", "presentation") // hide from accessibility tree
	    if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true") }
	    if (options.insertLeft) { marker.widgetNode.insertLeft = true }
	  }
	  if (marker.collapsed) {
	    if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
	        from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
	      { throw new Error("Inserting collapsed marker partially overlapping an existing one") }
	    seeCollapsedSpans()
	  }
	
	  if (marker.addToHistory)
	    { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN) }
	
	  var curLine = from.line, cm = doc.cm, updateMaxLine
	  doc.iter(curLine, to.line + 1, function (line) {
	    if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
	      { updateMaxLine = true }
	    if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0) }
	    addMarkedSpan(line, new MarkedSpan(marker,
	                                       curLine == from.line ? from.ch : null,
	                                       curLine == to.line ? to.ch : null))
	    ++curLine
	  })
	  // lineIsHidden depends on the presence of the spans, so needs a second pass
	  if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {
	    if (lineIsHidden(doc, line)) { updateLineHeight(line, 0) }
	  }) }
	
	  if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }) }
	
	  if (marker.readOnly) {
	    seeReadOnlySpans()
	    if (doc.history.done.length || doc.history.undone.length)
	      { doc.clearHistory() }
	  }
	  if (marker.collapsed) {
	    marker.id = ++nextMarkerId
	    marker.atomic = true
	  }
	  if (cm) {
	    // Sync editor state
	    if (updateMaxLine) { cm.curOp.updateMaxLine = true }
	    if (marker.collapsed)
	      { regChange(cm, from.line, to.line + 1) }
	    else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
	      { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text") } }
	    if (marker.atomic) { reCheckSelection(cm.doc) }
	    signalLater(cm, "markerAdded", cm, marker)
	  }
	  return marker
	}
	
	// SHARED TEXTMARKERS
	
	// A shared marker spans multiple linked documents. It is
	// implemented as a meta-marker-object controlling multiple normal
	// markers.
	function SharedTextMarker(markers, primary) {
	  var this$1 = this;
	
	  this.markers = markers
	  this.primary = primary
	  for (var i = 0; i < markers.length; ++i)
	    { markers[i].parent = this$1 }
	}
	eventMixin(SharedTextMarker)
	
	SharedTextMarker.prototype.clear = function() {
	  var this$1 = this;
	
	  if (this.explicitlyCleared) { return }
	  this.explicitlyCleared = true
	  for (var i = 0; i < this.markers.length; ++i)
	    { this$1.markers[i].clear() }
	  signalLater(this, "clear")
	}
	SharedTextMarker.prototype.find = function(side, lineObj) {
	  return this.primary.find(side, lineObj)
	}
	
	function markTextShared(doc, from, to, options, type) {
	  options = copyObj(options)
	  options.shared = false
	  var markers = [markText(doc, from, to, options, type)], primary = markers[0]
	  var widget = options.widgetNode
	  linkedDocs(doc, function (doc) {
	    if (widget) { options.widgetNode = widget.cloneNode(true) }
	    markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type))
	    for (var i = 0; i < doc.linked.length; ++i)
	      { if (doc.linked[i].isParent) { return } }
	    primary = lst(markers)
	  })
	  return new SharedTextMarker(markers, primary)
	}
	
	function findSharedMarkers(doc) {
	  return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; })
	}
	
	function copySharedMarkers(doc, markers) {
	  for (var i = 0; i < markers.length; i++) {
	    var marker = markers[i], pos = marker.find()
	    var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to)
	    if (cmp(mFrom, mTo)) {
	      var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type)
	      marker.markers.push(subMark)
	      subMark.parent = marker
	    }
	  }
	}
	
	function detachSharedMarkers(markers) {
	  var loop = function ( i ) {
	    var marker = markers[i], linked = [marker.primary.doc]
	    linkedDocs(marker.primary.doc, function (d) { return linked.push(d); })
	    for (var j = 0; j < marker.markers.length; j++) {
	      var subMarker = marker.markers[j]
	      if (indexOf(linked, subMarker.doc) == -1) {
	        subMarker.parent = null
	        marker.markers.splice(j--, 1)
	      }
	    }
	  };
	
	  for (var i = 0; i < markers.length; i++) loop( i );
	}
	
	var nextDocId = 0
	var Doc = function(text, mode, firstLine, lineSep) {
	  if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep) }
	  if (firstLine == null) { firstLine = 0 }
	
	  BranchChunk.call(this, [new LeafChunk([new Line("", null)])])
	  this.first = firstLine
	  this.scrollTop = this.scrollLeft = 0
	  this.cantEdit = false
	  this.cleanGeneration = 1
	  this.frontier = firstLine
	  var start = Pos(firstLine, 0)
	  this.sel = simpleSelection(start)
	  this.history = new History(null)
	  this.id = ++nextDocId
	  this.modeOption = mode
	  this.lineSep = lineSep
	  this.extend = false
	
	  if (typeof text == "string") { text = this.splitLines(text) }
	  updateDoc(this, {from: start, to: start, text: text})
	  setSelection(this, simpleSelection(start), sel_dontScroll)
	}
	
	Doc.prototype = createObj(BranchChunk.prototype, {
	  constructor: Doc,
	  // Iterate over the document. Supports two forms -- with only one
	  // argument, it calls that for each line in the document. With
	  // three, it iterates over the range given by the first two (with
	  // the second being non-inclusive).
	  iter: function(from, to, op) {
	    if (op) { this.iterN(from - this.first, to - from, op) }
	    else { this.iterN(this.first, this.first + this.size, from) }
	  },
	
	  // Non-public interface for adding and removing lines.
	  insert: function(at, lines) {
	    var height = 0
	    for (var i = 0; i < lines.length; ++i) { height += lines[i].height }
	    this.insertInner(at - this.first, lines, height)
	  },
	  remove: function(at, n) { this.removeInner(at - this.first, n) },
	
	  // From here, the methods are part of the public interface. Most
	  // are also available from CodeMirror (editor) instances.
	
	  getValue: function(lineSep) {
	    var lines = getLines(this, this.first, this.first + this.size)
	    if (lineSep === false) { return lines }
	    return lines.join(lineSep || this.lineSeparator())
	  },
	  setValue: docMethodOp(function(code) {
	    var top = Pos(this.first, 0), last = this.first + this.size - 1
	    makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
	                      text: this.splitLines(code), origin: "setValue", full: true}, true)
	    setSelection(this, simpleSelection(top))
	  }),
	  replaceRange: function(code, from, to, origin) {
	    from = clipPos(this, from)
	    to = to ? clipPos(this, to) : from
	    replaceRange(this, code, from, to, origin)
	  },
	  getRange: function(from, to, lineSep) {
	    var lines = getBetween(this, clipPos(this, from), clipPos(this, to))
	    if (lineSep === false) { return lines }
	    return lines.join(lineSep || this.lineSeparator())
	  },
	
	  getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},
	
	  getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }},
	  getLineNumber: function(line) {return lineNo(line)},
	
	  getLineHandleVisualStart: function(line) {
	    if (typeof line == "number") { line = getLine(this, line) }
	    return visualLine(line)
	  },
	
	  lineCount: function() {return this.size},
	  firstLine: function() {return this.first},
	  lastLine: function() {return this.first + this.size - 1},
	
	  clipPos: function(pos) {return clipPos(this, pos)},
	
	  getCursor: function(start) {
	    var range = this.sel.primary(), pos
	    if (start == null || start == "head") { pos = range.head }
	    else if (start == "anchor") { pos = range.anchor }
	    else if (start == "end" || start == "to" || start === false) { pos = range.to() }
	    else { pos = range.from() }
	    return pos
	  },
	  listSelections: function() { return this.sel.ranges },
	  somethingSelected: function() {return this.sel.somethingSelected()},
	
	  setCursor: docMethodOp(function(line, ch, options) {
	    setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options)
	  }),
	  setSelection: docMethodOp(function(anchor, head, options) {
	    setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options)
	  }),
	  extendSelection: docMethodOp(function(head, other, options) {
	    extendSelection(this, clipPos(this, head), other && clipPos(this, other), options)
	  }),
	  extendSelections: docMethodOp(function(heads, options) {
	    extendSelections(this, clipPosArray(this, heads), options)
	  }),
	  extendSelectionsBy: docMethodOp(function(f, options) {
	    var heads = map(this.sel.ranges, f)
	    extendSelections(this, clipPosArray(this, heads), options)
	  }),
	  setSelections: docMethodOp(function(ranges, primary, options) {
	    var this$1 = this;
	
	    if (!ranges.length) { return }
	    var out = []
	    for (var i = 0; i < ranges.length; i++)
	      { out[i] = new Range(clipPos(this$1, ranges[i].anchor),
	                         clipPos(this$1, ranges[i].head)) }
	    if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex) }
	    setSelection(this, normalizeSelection(out, primary), options)
	  }),
	  addSelection: docMethodOp(function(anchor, head, options) {
	    var ranges = this.sel.ranges.slice(0)
	    ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)))
	    setSelection(this, normalizeSelection(ranges, ranges.length - 1), options)
	  }),
	
	  getSelection: function(lineSep) {
	    var this$1 = this;
	
	    var ranges = this.sel.ranges, lines
	    for (var i = 0; i < ranges.length; i++) {
	      var sel = getBetween(this$1, ranges[i].from(), ranges[i].to())
	      lines = lines ? lines.concat(sel) : sel
	    }
	    if (lineSep === false) { return lines }
	    else { return lines.join(lineSep || this.lineSeparator()) }
	  },
	  getSelections: function(lineSep) {
	    var this$1 = this;
	
	    var parts = [], ranges = this.sel.ranges
	    for (var i = 0; i < ranges.length; i++) {
	      var sel = getBetween(this$1, ranges[i].from(), ranges[i].to())
	      if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()) }
	      parts[i] = sel
	    }
	    return parts
	  },
	  replaceSelection: function(code, collapse, origin) {
	    var dup = []
	    for (var i = 0; i < this.sel.ranges.length; i++)
	      { dup[i] = code }
	    this.replaceSelections(dup, collapse, origin || "+input")
	  },
	  replaceSelections: docMethodOp(function(code, collapse, origin) {
	    var this$1 = this;
	
	    var changes = [], sel = this.sel
	    for (var i = 0; i < sel.ranges.length; i++) {
	      var range = sel.ranges[i]
	      changes[i] = {from: range.from(), to: range.to(), text: this$1.splitLines(code[i]), origin: origin}
	    }
	    var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse)
	    for (var i$1 = changes.length - 1; i$1 >= 0; i$1--)
	      { makeChange(this$1, changes[i$1]) }
	    if (newSel) { setSelectionReplaceHistory(this, newSel) }
	    else if (this.cm) { ensureCursorVisible(this.cm) }
	  }),
	  undo: docMethodOp(function() {makeChangeFromHistory(this, "undo")}),
	  redo: docMethodOp(function() {makeChangeFromHistory(this, "redo")}),
	  undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true)}),
	  redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true)}),
	
	  setExtending: function(val) {this.extend = val},
	  getExtending: function() {return this.extend},
	
	  historySize: function() {
	    var hist = this.history, done = 0, undone = 0
	    for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done } }
	    for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone } }
	    return {undo: done, redo: undone}
	  },
	  clearHistory: function() {this.history = new History(this.history.maxGeneration)},
	
	  markClean: function() {
	    this.cleanGeneration = this.changeGeneration(true)
	  },
	  changeGeneration: function(forceSplit) {
	    if (forceSplit)
	      { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null }
	    return this.history.generation
	  },
	  isClean: function (gen) {
	    return this.history.generation == (gen || this.cleanGeneration)
	  },
	
	  getHistory: function() {
	    return {done: copyHistoryArray(this.history.done),
	            undone: copyHistoryArray(this.history.undone)}
	  },
	  setHistory: function(histData) {
	    var hist = this.history = new History(this.history.maxGeneration)
	    hist.done = copyHistoryArray(histData.done.slice(0), null, true)
	    hist.undone = copyHistoryArray(histData.undone.slice(0), null, true)
	  },
	
	  setGutterMarker: docMethodOp(function(line, gutterID, value) {
	    return changeLine(this, line, "gutter", function (line) {
	      var markers = line.gutterMarkers || (line.gutterMarkers = {})
	      markers[gutterID] = value
	      if (!value && isEmpty(markers)) { line.gutterMarkers = null }
	      return true
	    })
	  }),
	
	  clearGutter: docMethodOp(function(gutterID) {
	    var this$1 = this;
	
	    this.iter(function (line) {
	      if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
	        changeLine(this$1, line, "gutter", function () {
	          line.gutterMarkers[gutterID] = null
	          if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null }
	          return true
	        })
	      }
	    })
	  }),
	
	  lineInfo: function(line) {
	    var n
	    if (typeof line == "number") {
	      if (!isLine(this, line)) { return null }
	      n = line
	      line = getLine(this, line)
	      if (!line) { return null }
	    } else {
	      n = lineNo(line)
	      if (n == null) { return null }
	    }
	    return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
	            textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
	            widgets: line.widgets}
	  },
	
	  addLineClass: docMethodOp(function(handle, where, cls) {
	    return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
	      var prop = where == "text" ? "textClass"
	               : where == "background" ? "bgClass"
	               : where == "gutter" ? "gutterClass" : "wrapClass"
	      if (!line[prop]) { line[prop] = cls }
	      else if (classTest(cls).test(line[prop])) { return false }
	      else { line[prop] += " " + cls }
	      return true
	    })
	  }),
	  removeLineClass: docMethodOp(function(handle, where, cls) {
	    return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
	      var prop = where == "text" ? "textClass"
	               : where == "background" ? "bgClass"
	               : where == "gutter" ? "gutterClass" : "wrapClass"
	      var cur = line[prop]
	      if (!cur) { return false }
	      else if (cls == null) { line[prop] = null }
	      else {
	        var found = cur.match(classTest(cls))
	        if (!found) { return false }
	        var end = found.index + found[0].length
	        line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null
	      }
	      return true
	    })
	  }),
	
	  addLineWidget: docMethodOp(function(handle, node, options) {
	    return addLineWidget(this, handle, node, options)
	  }),
	  removeLineWidget: function(widget) { widget.clear() },
	
	  markText: function(from, to, options) {
	    return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range")
	  },
	  setBookmark: function(pos, options) {
	    var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
	                    insertLeft: options && options.insertLeft,
	                    clearWhenEmpty: false, shared: options && options.shared,
	                    handleMouseEvents: options && options.handleMouseEvents}
	    pos = clipPos(this, pos)
	    return markText(this, pos, pos, realOpts, "bookmark")
	  },
	  findMarksAt: function(pos) {
	    pos = clipPos(this, pos)
	    var markers = [], spans = getLine(this, pos.line).markedSpans
	    if (spans) { for (var i = 0; i < spans.length; ++i) {
	      var span = spans[i]
	      if ((span.from == null || span.from <= pos.ch) &&
	          (span.to == null || span.to >= pos.ch))
	        { markers.push(span.marker.parent || span.marker) }
	    } }
	    return markers
	  },
	  findMarks: function(from, to, filter) {
	    from = clipPos(this, from); to = clipPos(this, to)
	    var found = [], lineNo = from.line
	    this.iter(from.line, to.line + 1, function (line) {
	      var spans = line.markedSpans
	      if (spans) { for (var i = 0; i < spans.length; i++) {
	        var span = spans[i]
	        if (!(span.to != null && lineNo == from.line && from.ch >= span.to ||
	              span.from == null && lineNo != from.line ||
	              span.from != null && lineNo == to.line && span.from >= to.ch) &&
	            (!filter || filter(span.marker)))
	          { found.push(span.marker.parent || span.marker) }
	      } }
	      ++lineNo
	    })
	    return found
	  },
	  getAllMarks: function() {
	    var markers = []
	    this.iter(function (line) {
	      var sps = line.markedSpans
	      if (sps) { for (var i = 0; i < sps.length; ++i)
	        { if (sps[i].from != null) { markers.push(sps[i].marker) } } }
	    })
	    return markers
	  },
	
	  posFromIndex: function(off) {
	    var ch, lineNo = this.first, sepSize = this.lineSeparator().length
	    this.iter(function (line) {
	      var sz = line.text.length + sepSize
	      if (sz > off) { ch = off; return true }
	      off -= sz
	      ++lineNo
	    })
	    return clipPos(this, Pos(lineNo, ch))
	  },
	  indexFromPos: function (coords) {
	    coords = clipPos(this, coords)
	    var index = coords.ch
	    if (coords.line < this.first || coords.ch < 0) { return 0 }
	    var sepSize = this.lineSeparator().length
	    this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value
	      index += line.text.length + sepSize
	    })
	    return index
	  },
	
	  copy: function(copyHistory) {
	    var doc = new Doc(getLines(this, this.first, this.first + this.size),
	                      this.modeOption, this.first, this.lineSep)
	    doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft
	    doc.sel = this.sel
	    doc.extend = false
	    if (copyHistory) {
	      doc.history.undoDepth = this.history.undoDepth
	      doc.setHistory(this.getHistory())
	    }
	    return doc
	  },
	
	  linkedDoc: function(options) {
	    if (!options) { options = {} }
	    var from = this.first, to = this.first + this.size
	    if (options.from != null && options.from > from) { from = options.from }
	    if (options.to != null && options.to < to) { to = options.to }
	    var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep)
	    if (options.sharedHist) { copy.history = this.history
	    ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist})
	    copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]
	    copySharedMarkers(copy, findSharedMarkers(this))
	    return copy
	  },
	  unlinkDoc: function(other) {
	    var this$1 = this;
	
	    if (other instanceof CodeMirror) { other = other.doc }
	    if (this.linked) { for (var i = 0; i < this.linked.length; ++i) {
	      var link = this$1.linked[i]
	      if (link.doc != other) { continue }
	      this$1.linked.splice(i, 1)
	      other.unlinkDoc(this$1)
	      detachSharedMarkers(findSharedMarkers(this$1))
	      break
	    } }
	    // If the histories were shared, split them again
	    if (other.history == this.history) {
	      var splitIds = [other.id]
	      linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true)
	      other.history = new History(null)
	      other.history.done = copyHistoryArray(this.history.done, splitIds)
	      other.history.undone = copyHistoryArray(this.history.undone, splitIds)
	    }
	  },
	  iterLinkedDocs: function(f) {linkedDocs(this, f)},
	
	  getMode: function() {return this.mode},
	  getEditor: function() {return this.cm},
	
	  splitLines: function(str) {
	    if (this.lineSep) { return str.split(this.lineSep) }
	    return splitLinesAuto(str)
	  },
	  lineSeparator: function() { return this.lineSep || "\n" }
	})
	
	// Public alias.
	Doc.prototype.eachLine = Doc.prototype.iter
	
	// Kludge to work around strange IE behavior where it'll sometimes
	// re-fire a series of drag-related events right after the drop (#1551)
	var lastDrop = 0
	
	function onDrop(e) {
	  var cm = this
	  clearDragCursor(cm)
	  if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
	    { return }
	  e_preventDefault(e)
	  if (ie) { lastDrop = +new Date }
	  var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files
	  if (!pos || cm.isReadOnly()) { return }
	  // Might be a file drop, in which case we simply extract the text
	  // and insert it.
	  if (files && files.length && window.FileReader && window.File) {
	    var n = files.length, text = Array(n), read = 0
	    var loadFile = function (file, i) {
	      if (cm.options.allowDropFileTypes &&
	          indexOf(cm.options.allowDropFileTypes, file.type) == -1)
	        { return }
	
	      var reader = new FileReader
	      reader.onload = operation(cm, function () {
	        var content = reader.result
	        if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { content = "" }
	        text[i] = content
	        if (++read == n) {
	          pos = clipPos(cm.doc, pos)
	          var change = {from: pos, to: pos,
	                        text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
	                        origin: "paste"}
	          makeChange(cm.doc, change)
	          setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)))
	        }
	      })
	      reader.readAsText(file)
	    }
	    for (var i = 0; i < n; ++i) { loadFile(files[i], i) }
	  } else { // Normal drop
	    // Don't do a replace if the drop happened inside of the selected text.
	    if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
	      cm.state.draggingText(e)
	      // Ensure the editor is re-focused
	      setTimeout(function () { return cm.display.input.focus(); }, 20)
	      return
	    }
	    try {
	      var text$1 = e.dataTransfer.getData("Text")
	      if (text$1) {
	        var selected
	        if (cm.state.draggingText && !cm.state.draggingText.copy)
	          { selected = cm.listSelections() }
	        setSelectionNoUndo(cm.doc, simpleSelection(pos, pos))
	        if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1)
	          { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag") } }
	        cm.replaceSelection(text$1, "around", "paste")
	        cm.display.input.focus()
	      }
	    }
	    catch(e){}
	  }
	}
	
	function onDragStart(cm, e) {
	  if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }
	  if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return }
	
	  e.dataTransfer.setData("Text", cm.getSelection())
	  e.dataTransfer.effectAllowed = "copyMove"
	
	  // Use dummy image instead of default browsers image.
	  // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
	  if (e.dataTransfer.setDragImage && !safari) {
	    var img = elt("img", null, null, "position: fixed; left: 0; top: 0;")
	    img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
	    if (presto) {
	      img.width = img.height = 1
	      cm.display.wrapper.appendChild(img)
	      // Force a relayout, or Opera won't use our image for some obscure reason
	      img._top = img.offsetTop
	    }
	    e.dataTransfer.setDragImage(img, 0, 0)
	    if (presto) { img.parentNode.removeChild(img) }
	  }
	}
	
	function onDragOver(cm, e) {
	  var pos = posFromMouse(cm, e)
	  if (!pos) { return }
	  var frag = document.createDocumentFragment()
	  drawSelectionCursor(cm, pos, frag)
	  if (!cm.display.dragCursor) {
	    cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors")
	    cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv)
	  }
	  removeChildrenAndAdd(cm.display.dragCursor, frag)
	}
	
	function clearDragCursor(cm) {
	  if (cm.display.dragCursor) {
	    cm.display.lineSpace.removeChild(cm.display.dragCursor)
	    cm.display.dragCursor = null
	  }
	}
	
	// These must be handled carefully, because naively registering a
	// handler for each editor will cause the editors to never be
	// garbage collected.
	
	function forEachCodeMirror(f) {
	  if (!document.body.getElementsByClassName) { return }
	  var byClass = document.body.getElementsByClassName("CodeMirror")
	  for (var i = 0; i < byClass.length; i++) {
	    var cm = byClass[i].CodeMirror
	    if (cm) { f(cm) }
	  }
	}
	
	var globalsRegistered = false
	function ensureGlobalHandlers() {
	  if (globalsRegistered) { return }
	  registerGlobalHandlers()
	  globalsRegistered = true
	}
	function registerGlobalHandlers() {
	  // When the window resizes, we need to refresh active editors.
	  var resizeTimer
	  on(window, "resize", function () {
	    if (resizeTimer == null) { resizeTimer = setTimeout(function () {
	      resizeTimer = null
	      forEachCodeMirror(onResize)
	    }, 100) }
	  })
	  // When the window loses focus, we want to show the editor as blurred
	  on(window, "blur", function () { return forEachCodeMirror(onBlur); })
	}
	// Called when the window resizes
	function onResize(cm) {
	  var d = cm.display
	  if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
	    { return }
	  // Might be a text scaling operation, clear size caches.
	  d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null
	  d.scrollbarsClipped = false
	  cm.setSize()
	}
	
	var keyNames = {
	  3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
	  19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
	  36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
	  46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
	  106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete",
	  173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
	  221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
	  63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
	}
	
	// Number keys
	for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i) }
	// Alphabetic keys
	for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1) }
	// Function keys
	for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2 }
	
	var keyMap = {}
	
	keyMap.basic = {
	  "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
	  "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
	  "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
	  "Tab": "defaultTab", "Shift-Tab": "indentAuto",
	  "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
	  "Esc": "singleSelection"
	}
	// Note that the save and find-related commands aren't defined by
	// default. User code or addons can define them. Unknown commands
	// are simply ignored.
	keyMap.pcDefault = {
	  "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
	  "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
	  "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
	  "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
	  "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
	  "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
	  "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
	  fallthrough: "basic"
	}
	// Very basic readline/emacs-style bindings, which are standard on Mac.
	keyMap.emacsy = {
	  "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
	  "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
	  "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
	  "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars",
	  "Ctrl-O": "openLine"
	}
	keyMap.macDefault = {
	  "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
	  "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
	  "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
	  "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
	  "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
	  "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
	  "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
	  fallthrough: ["basic", "emacsy"]
	}
	keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault
	
	// KEYMAP DISPATCH
	
	function normalizeKeyName(name) {
	  var parts = name.split(/-(?!$)/)
	  name = parts[parts.length - 1]
	  var alt, ctrl, shift, cmd
	  for (var i = 0; i < parts.length - 1; i++) {
	    var mod = parts[i]
	    if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true }
	    else if (/^a(lt)?$/i.test(mod)) { alt = true }
	    else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true }
	    else if (/^s(hift)?$/i.test(mod)) { shift = true }
	    else { throw new Error("Unrecognized modifier name: " + mod) }
	  }
	  if (alt) { name = "Alt-" + name }
	  if (ctrl) { name = "Ctrl-" + name }
	  if (cmd) { name = "Cmd-" + name }
	  if (shift) { name = "Shift-" + name }
	  return name
	}
	
	// This is a kludge to keep keymaps mostly working as raw objects
	// (backwards compatibility) while at the same time support features
	// like normalization and multi-stroke key bindings. It compiles a
	// new normalized keymap, and then updates the old object to reflect
	// this.
	function normalizeKeyMap(keymap) {
	  var copy = {}
	  for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) {
	    var value = keymap[keyname]
	    if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue }
	    if (value == "...") { delete keymap[keyname]; continue }
	
	    var keys = map(keyname.split(" "), normalizeKeyName)
	    for (var i = 0; i < keys.length; i++) {
	      var val = (void 0), name = (void 0)
	      if (i == keys.length - 1) {
	        name = keys.join(" ")
	        val = value
	      } else {
	        name = keys.slice(0, i + 1).join(" ")
	        val = "..."
	      }
	      var prev = copy[name]
	      if (!prev) { copy[name] = val }
	      else if (prev != val) { throw new Error("Inconsistent bindings for " + name) }
	    }
	    delete keymap[keyname]
	  } }
	  for (var prop in copy) { keymap[prop] = copy[prop] }
	  return keymap
	}
	
	function lookupKey(key, map, handle, context) {
	  map = getKeyMap(map)
	  var found = map.call ? map.call(key, context) : map[key]
	  if (found === false) { return "nothing" }
	  if (found === "...") { return "multi" }
	  if (found != null && handle(found)) { return "handled" }
	
	  if (map.fallthrough) {
	    if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
	      { return lookupKey(key, map.fallthrough, handle, context) }
	    for (var i = 0; i < map.fallthrough.length; i++) {
	      var result = lookupKey(key, map.fallthrough[i], handle, context)
	      if (result) { return result }
	    }
	  }
	}
	
	// Modifier key presses don't count as 'real' key presses for the
	// purpose of keymap fallthrough.
	function isModifierKey(value) {
	  var name = typeof value == "string" ? value : keyNames[value.keyCode]
	  return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"
	}
	
	// Look up the name of a key as indicated by an event object.
	function keyName(event, noShift) {
	  if (presto && event.keyCode == 34 && event["char"]) { return false }
	  var base = keyNames[event.keyCode], name = base
	  if (name == null || event.altGraphKey) { return false }
	  if (event.altKey && base != "Alt") { name = "Alt-" + name }
	  if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name }
	  if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name }
	  if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name }
	  return name
	}
	
	function getKeyMap(val) {
	  return typeof val == "string" ? keyMap[val] : val
	}
	
	// Helper for deleting text near the selection(s), used to implement
	// backspace, delete, and similar functionality.
	function deleteNearSelection(cm, compute) {
	  var ranges = cm.doc.sel.ranges, kill = []
	  // Build up a set of ranges to kill first, merging overlapping
	  // ranges.
	  for (var i = 0; i < ranges.length; i++) {
	    var toKill = compute(ranges[i])
	    while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
	      var replaced = kill.pop()
	      if (cmp(replaced.from, toKill.from) < 0) {
	        toKill.from = replaced.from
	        break
	      }
	    }
	    kill.push(toKill)
	  }
	  // Next, remove those actual ranges.
	  runInOp(cm, function () {
	    for (var i = kill.length - 1; i >= 0; i--)
	      { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete") }
	    ensureCursorVisible(cm)
	  })
	}
	
	// Commands are parameter-less actions that can be performed on an
	// editor, mostly used for keybindings.
	var commands = {
	  selectAll: selectAll,
	  singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); },
	  killLine: function (cm) { return deleteNearSelection(cm, function (range) {
	    if (range.empty()) {
	      var len = getLine(cm.doc, range.head.line).text.length
	      if (range.head.ch == len && range.head.line < cm.lastLine())
	        { return {from: range.head, to: Pos(range.head.line + 1, 0)} }
	      else
	        { return {from: range.head, to: Pos(range.head.line, len)} }
	    } else {
	      return {from: range.from(), to: range.to()}
	    }
	  }); },
	  deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({
	    from: Pos(range.from().line, 0),
	    to: clipPos(cm.doc, Pos(range.to().line + 1, 0))
	  }); }); },
	  delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({
	    from: Pos(range.from().line, 0), to: range.from()
	  }); }); },
	  delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) {
	    var top = cm.charCoords(range.head, "div").top + 5
	    var leftPos = cm.coordsChar({left: 0, top: top}, "div")
	    return {from: leftPos, to: range.from()}
	  }); },
	  delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) {
	    var top = cm.charCoords(range.head, "div").top + 5
	    var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
	    return {from: range.from(), to: rightPos }
	  }); },
	  undo: function (cm) { return cm.undo(); },
	  redo: function (cm) { return cm.redo(); },
	  undoSelection: function (cm) { return cm.undoSelection(); },
	  redoSelection: function (cm) { return cm.redoSelection(); },
	  goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); },
	  goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); },
	  goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); },
	    {origin: "+move", bias: 1}
	  ); },
	  goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); },
	    {origin: "+move", bias: 1}
	  ); },
	  goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); },
	    {origin: "+move", bias: -1}
	  ); },
	  goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) {
	    var top = cm.charCoords(range.head, "div").top + 5
	    return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
	  }, sel_move); },
	  goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) {
	    var top = cm.charCoords(range.head, "div").top + 5
	    return cm.coordsChar({left: 0, top: top}, "div")
	  }, sel_move); },
	  goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) {
	    var top = cm.charCoords(range.head, "div").top + 5
	    var pos = cm.coordsChar({left: 0, top: top}, "div")
	    if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) }
	    return pos
	  }, sel_move); },
	  goLineUp: function (cm) { return cm.moveV(-1, "line"); },
	  goLineDown: function (cm) { return cm.moveV(1, "line"); },
	  goPageUp: function (cm) { return cm.moveV(-1, "page"); },
	  goPageDown: function (cm) { return cm.moveV(1, "page"); },
	  goCharLeft: function (cm) { return cm.moveH(-1, "char"); },
	  goCharRight: function (cm) { return cm.moveH(1, "char"); },
	  goColumnLeft: function (cm) { return cm.moveH(-1, "column"); },
	  goColumnRight: function (cm) { return cm.moveH(1, "column"); },
	  goWordLeft: function (cm) { return cm.moveH(-1, "word"); },
	  goGroupRight: function (cm) { return cm.moveH(1, "group"); },
	  goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
	  goWordRight: function (cm) { return cm.moveH(1, "word"); },
	  delCharBefore: function (cm) { return cm.deleteH(-1, "char"); },
	  delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
	  delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
	  delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
	  delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); },
	  delGroupAfter: function (cm) { return cm.deleteH(1, "group"); },
	  indentAuto: function (cm) { return cm.indentSelection("smart"); },
	  indentMore: function (cm) { return cm.indentSelection("add"); },
	  indentLess: function (cm) { return cm.indentSelection("subtract"); },
	  insertTab: function (cm) { return cm.replaceSelection("\t"); },
	  insertSoftTab: function (cm) {
	    var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize
	    for (var i = 0; i < ranges.length; i++) {
	      var pos = ranges[i].from()
	      var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize)
	      spaces.push(spaceStr(tabSize - col % tabSize))
	    }
	    cm.replaceSelections(spaces)
	  },
	  defaultTab: function (cm) {
	    if (cm.somethingSelected()) { cm.indentSelection("add") }
	    else { cm.execCommand("insertTab") }
	  },
	  // Swap the two chars left and right of each selection's head.
	  // Move cursor behind the two swapped characters afterwards.
	  //
	  // Doesn't consider line feeds a character.
	  // Doesn't scan more than one line above to find a character.
	  // Doesn't do anything on an empty line.
	  // Doesn't do anything with non-empty selections.
	  transposeChars: function (cm) { return runInOp(cm, function () {
	    var ranges = cm.listSelections(), newSel = []
	    for (var i = 0; i < ranges.length; i++) {
	      if (!ranges[i].empty()) { continue }
	      var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text
	      if (line) {
	        if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1) }
	        if (cur.ch > 0) {
	          cur = new Pos(cur.line, cur.ch + 1)
	          cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
	                          Pos(cur.line, cur.ch - 2), cur, "+transpose")
	        } else if (cur.line > cm.doc.first) {
	          var prev = getLine(cm.doc, cur.line - 1).text
	          if (prev) {
	            cur = new Pos(cur.line, 1)
	            cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
	                            prev.charAt(prev.length - 1),
	                            Pos(cur.line - 1, prev.length - 1), cur, "+transpose")
	          }
	        }
	      }
	      newSel.push(new Range(cur, cur))
	    }
	    cm.setSelections(newSel)
	  }); },
	  newlineAndIndent: function (cm) { return runInOp(cm, function () {
	    var sels = cm.listSelections()
	    for (var i = sels.length - 1; i >= 0; i--)
	      { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input") }
	    sels = cm.listSelections()
	    for (var i$1 = 0; i$1 < sels.length; i$1++)
	      { cm.indentLine(sels[i$1].from().line, null, true) }
	    ensureCursorVisible(cm)
	  }); },
	  openLine: function (cm) { return cm.replaceSelection("\n", "start"); },
	  toggleOverwrite: function (cm) { return cm.toggleOverwrite(); }
	}
	
	
	function lineStart(cm, lineN) {
	  var line = getLine(cm.doc, lineN)
	  var visual = visualLine(line)
	  if (visual != line) { lineN = lineNo(visual) }
	  var order = getOrder(visual)
	  var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual)
	  return Pos(lineN, ch)
	}
	function lineEnd(cm, lineN) {
	  var merged, line = getLine(cm.doc, lineN)
	  while (merged = collapsedSpanAtEnd(line)) {
	    line = merged.find(1, true).line
	    lineN = null
	  }
	  var order = getOrder(line)
	  var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line)
	  return Pos(lineN == null ? lineNo(line) : lineN, ch)
	}
	function lineStartSmart(cm, pos) {
	  var start = lineStart(cm, pos.line)
	  var line = getLine(cm.doc, start.line)
	  var order = getOrder(line)
	  if (!order || order[0].level == 0) {
	    var firstNonWS = Math.max(0, line.text.search(/\S/))
	    var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch
	    return Pos(start.line, inWS ? 0 : firstNonWS)
	  }
	  return start
	}
	
	// Run a handler that was bound to a key.
	function doHandleBinding(cm, bound, dropShift) {
	  if (typeof bound == "string") {
	    bound = commands[bound]
	    if (!bound) { return false }
	  }
	  // Ensure previous input has been read, so that the handler sees a
	  // consistent view of the document
	  cm.display.input.ensurePolled()
	  var prevShift = cm.display.shift, done = false
	  try {
	    if (cm.isReadOnly()) { cm.state.suppressEdits = true }
	    if (dropShift) { cm.display.shift = false }
	    done = bound(cm) != Pass
	  } finally {
	    cm.display.shift = prevShift
	    cm.state.suppressEdits = false
	  }
	  return done
	}
	
	function lookupKeyForEditor(cm, name, handle) {
	  for (var i = 0; i < cm.state.keyMaps.length; i++) {
	    var result = lookupKey(name, cm.state.keyMaps[i], handle, cm)
	    if (result) { return result }
	  }
	  return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
	    || lookupKey(name, cm.options.keyMap, handle, cm)
	}
	
	var stopSeq = new Delayed
	function dispatchKey(cm, name, e, handle) {
	  var seq = cm.state.keySeq
	  if (seq) {
	    if (isModifierKey(name)) { return "handled" }
	    stopSeq.set(50, function () {
	      if (cm.state.keySeq == seq) {
	        cm.state.keySeq = null
	        cm.display.input.reset()
	      }
	    })
	    name = seq + " " + name
	  }
	  var result = lookupKeyForEditor(cm, name, handle)
	
	  if (result == "multi")
	    { cm.state.keySeq = name }
	  if (result == "handled")
	    { signalLater(cm, "keyHandled", cm, name, e) }
	
	  if (result == "handled" || result == "multi") {
	    e_preventDefault(e)
	    restartBlink(cm)
	  }
	
	  if (seq && !result && /\'$/.test(name)) {
	    e_preventDefault(e)
	    return true
	  }
	  return !!result
	}
	
	// Handle a key from the keydown event.
	function handleKeyBinding(cm, e) {
	  var name = keyName(e, true)
	  if (!name) { return false }
	
	  if (e.shiftKey && !cm.state.keySeq) {
	    // First try to resolve full name (including 'Shift-'). Failing
	    // that, see if there is a cursor-motion command (starting with
	    // 'go') bound to the keyname without 'Shift-'.
	    return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); })
	        || dispatchKey(cm, name, e, function (b) {
	             if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
	               { return doHandleBinding(cm, b) }
	           })
	  } else {
	    return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); })
	  }
	}
	
	// Handle a key from the keypress event
	function handleCharBinding(cm, e, ch) {
	  return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); })
	}
	
	var lastStoppedKey = null
	function onKeyDown(e) {
	  var cm = this
	  cm.curOp.focus = activeElt()
	  if (signalDOMEvent(cm, e)) { return }
	  // IE does strange things with escape.
	  if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false }
	  var code = e.keyCode
	  cm.display.shift = code == 16 || e.shiftKey
	  var handled = handleKeyBinding(cm, e)
	  if (presto) {
	    lastStoppedKey = handled ? code : null
	    // Opera has no cut event... we try to at least catch the key combo
	    if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
	      { cm.replaceSelection("", null, "cut") }
	  }
	
	  // Turn mouse into crosshair when Alt is held on Mac.
	  if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
	    { showCrossHair(cm) }
	}
	
	function showCrossHair(cm) {
	  var lineDiv = cm.display.lineDiv
	  addClass(lineDiv, "CodeMirror-crosshair")
	
	  function up(e) {
	    if (e.keyCode == 18 || !e.altKey) {
	      rmClass(lineDiv, "CodeMirror-crosshair")
	      off(document, "keyup", up)
	      off(document, "mouseover", up)
	    }
	  }
	  on(document, "keyup", up)
	  on(document, "mouseover", up)
	}
	
	function onKeyUp(e) {
	  if (e.keyCode == 16) { this.doc.sel.shift = false }
	  signalDOMEvent(this, e)
	}
	
	function onKeyPress(e) {
	  var cm = this
	  if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return }
	  var keyCode = e.keyCode, charCode = e.charCode
	  if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return}
	  if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return }
	  var ch = String.fromCharCode(charCode == null ? keyCode : charCode)
	  // Some browsers fire keypress events for backspace
	  if (ch == "\x08") { return }
	  if (handleCharBinding(cm, e, ch)) { return }
	  cm.display.input.onKeyPress(e)
	}
	
	// A mouse down can be a single click, double click, triple click,
	// start of selection drag, start of text drag, new cursor
	// (ctrl-click), rectangle drag (alt-drag), or xwin
	// middle-click-paste. Or it might be a click on something we should
	// not interfere with, such as a scrollbar or widget.
	function onMouseDown(e) {
	  var cm = this, display = cm.display
	  if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return }
	  display.input.ensurePolled()
	  display.shift = e.shiftKey
	
	  if (eventInWidget(display, e)) {
	    if (!webkit) {
	      // Briefly turn off draggability, to allow widgets to do
	      // normal dragging things.
	      display.scroller.draggable = false
	      setTimeout(function () { return display.scroller.draggable = true; }, 100)
	    }
	    return
	  }
	  if (clickInGutter(cm, e)) { return }
	  var start = posFromMouse(cm, e)
	  window.focus()
	
	  switch (e_button(e)) {
	  case 1:
	    // #3261: make sure, that we're not starting a second selection
	    if (cm.state.selectingText)
	      { cm.state.selectingText(e) }
	    else if (start)
	      { leftButtonDown(cm, e, start) }
	    else if (e_target(e) == display.scroller)
	      { e_preventDefault(e) }
	    break
	  case 2:
	    if (webkit) { cm.state.lastMiddleDown = +new Date }
	    if (start) { extendSelection(cm.doc, start) }
	    setTimeout(function () { return display.input.focus(); }, 20)
	    e_preventDefault(e)
	    break
	  case 3:
	    if (captureRightClick) { onContextMenu(cm, e) }
	    else { delayBlurEvent(cm) }
	    break
	  }
	}
	
	var lastClick;
	var lastDoubleClick;
	function leftButtonDown(cm, e, start) {
	  if (ie) { setTimeout(bind(ensureFocus, cm), 0) }
	  else { cm.curOp.focus = activeElt() }
	
	  var now = +new Date, type
	  if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
	    type = "triple"
	  } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
	    type = "double"
	    lastDoubleClick = {time: now, pos: start}
	  } else {
	    type = "single"
	    lastClick = {time: now, pos: start}
	  }
	
	  var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained
	  if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
	      type == "single" && (contained = sel.contains(start)) > -1 &&
	      (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
	      (cmp(contained.to(), start) > 0 || start.xRel < 0))
	    { leftButtonStartDrag(cm, e, start, modifier) }
	  else
	    { leftButtonSelect(cm, e, start, type, modifier) }
	}
	
	// Start a text drag. When it ends, see if any dragging actually
	// happen, and treat as a click if it didn't.
	function leftButtonStartDrag(cm, e, start, modifier) {
	  var display = cm.display, startTime = +new Date
	  var dragEnd = operation(cm, function (e2) {
	    if (webkit) { display.scroller.draggable = false }
	    cm.state.draggingText = false
	    off(document, "mouseup", dragEnd)
	    off(display.scroller, "drop", dragEnd)
	    if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
	      e_preventDefault(e2)
	      if (!modifier && +new Date - 200 < startTime)
	        { extendSelection(cm.doc, start) }
	      // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
	      if (webkit || ie && ie_version == 9)
	        { setTimeout(function () {document.body.focus(); display.input.focus()}, 20) }
	      else
	        { display.input.focus() }
	    }
	  })
	  // Let the drag handler handle this.
	  if (webkit) { display.scroller.draggable = true }
	  cm.state.draggingText = dragEnd
	  dragEnd.copy = mac ? e.altKey : e.ctrlKey
	  // IE's approach to draggable
	  if (display.scroller.dragDrop) { display.scroller.dragDrop() }
	  on(document, "mouseup", dragEnd)
	  on(display.scroller, "drop", dragEnd)
	}
	
	// Normal selection, as opposed to text dragging.
	function leftButtonSelect(cm, e, start, type, addNew) {
	  var display = cm.display, doc = cm.doc
	  e_preventDefault(e)
	
	  var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges
	  if (addNew && !e.shiftKey) {
	    ourIndex = doc.sel.contains(start)
	    if (ourIndex > -1)
	      { ourRange = ranges[ourIndex] }
	    else
	      { ourRange = new Range(start, start) }
	  } else {
	    ourRange = doc.sel.primary()
	    ourIndex = doc.sel.primIndex
	  }
	
	  if (chromeOS ? e.shiftKey && e.metaKey : e.altKey) {
	    type = "rect"
	    if (!addNew) { ourRange = new Range(start, start) }
	    start = posFromMouse(cm, e, true, true)
	    ourIndex = -1
	  } else if (type == "double") {
	    var word = cm.findWordAt(start)
	    if (cm.display.shift || doc.extend)
	      { ourRange = extendRange(doc, ourRange, word.anchor, word.head) }
	    else
	      { ourRange = word }
	  } else if (type == "triple") {
	    var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)))
	    if (cm.display.shift || doc.extend)
	      { ourRange = extendRange(doc, ourRange, line.anchor, line.head) }
	    else
	      { ourRange = line }
	  } else {
	    ourRange = extendRange(doc, ourRange, start)
	  }
	
	  if (!addNew) {
	    ourIndex = 0
	    setSelection(doc, new Selection([ourRange], 0), sel_mouse)
	    startSel = doc.sel
	  } else if (ourIndex == -1) {
	    ourIndex = ranges.length
	    setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
	                 {scroll: false, origin: "*mouse"})
	  } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
	    setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
	                 {scroll: false, origin: "*mouse"})
	    startSel = doc.sel
	  } else {
	    replaceOneSelection(doc, ourIndex, ourRange, sel_mouse)
	  }
	
	  var lastPos = start
	  function extendTo(pos) {
	    if (cmp(lastPos, pos) == 0) { return }
	    lastPos = pos
	
	    if (type == "rect") {
	      var ranges = [], tabSize = cm.options.tabSize
	      var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize)
	      var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize)
	      var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol)
	      for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
	           line <= end; line++) {
	        var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize)
	        if (left == right)
	          { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))) }
	        else if (text.length > leftPos)
	          { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))) }
	      }
	      if (!ranges.length) { ranges.push(new Range(start, start)) }
	      setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
	                   {origin: "*mouse", scroll: false})
	      cm.scrollIntoView(pos)
	    } else {
	      var oldRange = ourRange
	      var anchor = oldRange.anchor, head = pos
	      if (type != "single") {
	        var range
	        if (type == "double")
	          { range = cm.findWordAt(pos) }
	        else
	          { range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))) }
	        if (cmp(range.anchor, anchor) > 0) {
	          head = range.head
	          anchor = minPos(oldRange.from(), range.anchor)
	        } else {
	          head = range.anchor
	          anchor = maxPos(oldRange.to(), range.head)
	        }
	      }
	      var ranges$1 = startSel.ranges.slice(0)
	      ranges$1[ourIndex] = new Range(clipPos(doc, anchor), head)
	      setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse)
	    }
	  }
	
	  var editorSize = display.wrapper.getBoundingClientRect()
	  // Used to ensure timeout re-tries don't fire when another extend
	  // happened in the meantime (clearTimeout isn't reliable -- at
	  // least on Chrome, the timeouts still happen even when cleared,
	  // if the clear happens after their scheduled firing time).
	  var counter = 0
	
	  function extend(e) {
	    var curCount = ++counter
	    var cur = posFromMouse(cm, e, true, type == "rect")
	    if (!cur) { return }
	    if (cmp(cur, lastPos) != 0) {
	      cm.curOp.focus = activeElt()
	      extendTo(cur)
	      var visible = visibleLines(display, doc)
	      if (cur.line >= visible.to || cur.line < visible.from)
	        { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e) }}), 150) }
	    } else {
	      var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0
	      if (outside) { setTimeout(operation(cm, function () {
	        if (counter != curCount) { return }
	        display.scroller.scrollTop += outside
	        extend(e)
	      }), 50) }
	    }
	  }
	
	  function done(e) {
	    cm.state.selectingText = false
	    counter = Infinity
	    e_preventDefault(e)
	    display.input.focus()
	    off(document, "mousemove", move)
	    off(document, "mouseup", up)
	    doc.history.lastSelOrigin = null
	  }
	
	  var move = operation(cm, function (e) {
	    if (!e_button(e)) { done(e) }
	    else { extend(e) }
	  })
	  var up = operation(cm, done)
	  cm.state.selectingText = up
	  on(document, "mousemove", move)
	  on(document, "mouseup", up)
	}
	
	
	// Determines whether an event happened in the gutter, and fires the
	// handlers for the corresponding event.
	function gutterEvent(cm, e, type, prevent) {
	  var mX, mY
	  try { mX = e.clientX; mY = e.clientY }
	  catch(e) { return false }
	  if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
	  if (prevent) { e_preventDefault(e) }
	
	  var display = cm.display
	  var lineBox = display.lineDiv.getBoundingClientRect()
	
	  if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) }
	  mY -= lineBox.top - display.viewOffset
	
	  for (var i = 0; i < cm.options.gutters.length; ++i) {
	    var g = display.gutters.childNodes[i]
	    if (g && g.getBoundingClientRect().right >= mX) {
	      var line = lineAtHeight(cm.doc, mY)
	      var gutter = cm.options.gutters[i]
	      signal(cm, type, cm, line, gutter, e)
	      return e_defaultPrevented(e)
	    }
	  }
	}
	
	function clickInGutter(cm, e) {
	  return gutterEvent(cm, e, "gutterClick", true)
	}
	
	// CONTEXT MENU HANDLING
	
	// To make the context menu work, we need to briefly unhide the
	// textarea (making it as unobtrusive as possible) to let the
	// right-click take effect on it.
	function onContextMenu(cm, e) {
	  if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return }
	  if (signalDOMEvent(cm, e, "contextmenu")) { return }
	  cm.display.input.onContextMenu(e)
	}
	
	function contextMenuInGutter(cm, e) {
	  if (!hasHandler(cm, "gutterContextMenu")) { return false }
	  return gutterEvent(cm, e, "gutterContextMenu", false)
	}
	
	function themeChanged(cm) {
	  cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
	    cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-")
	  clearCaches(cm)
	}
	
	var Init = {toString: function(){return "CodeMirror.Init"}}
	
	var defaults = {}
	var optionHandlers = {}
	
	function defineOptions(CodeMirror) {
	  var optionHandlers = CodeMirror.optionHandlers
	
	  function option(name, deflt, handle, notOnInit) {
	    CodeMirror.defaults[name] = deflt
	    if (handle) { optionHandlers[name] =
	      notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old) }} : handle }
	  }
	
	  CodeMirror.defineOption = option
	
	  // Passed to option handlers when there is no old value.
	  CodeMirror.Init = Init
	
	  // These two are, on init, called from the constructor because they
	  // have to be initialized before the editor can start at all.
	  option("value", "", function (cm, val) { return cm.setValue(val); }, true)
	  option("mode", null, function (cm, val) {
	    cm.doc.modeOption = val
	    loadMode(cm)
	  }, true)
	
	  option("indentUnit", 2, loadMode, true)
	  option("indentWithTabs", false)
	  option("smartIndent", true)
	  option("tabSize", 4, function (cm) {
	    resetModeState(cm)
	    clearCaches(cm)
	    regChange(cm)
	  }, true)
	  option("lineSeparator", null, function (cm, val) {
	    cm.doc.lineSep = val
	    if (!val) { return }
	    var newBreaks = [], lineNo = cm.doc.first
	    cm.doc.iter(function (line) {
	      for (var pos = 0;;) {
	        var found = line.text.indexOf(val, pos)
	        if (found == -1) { break }
	        pos = found + val.length
	        newBreaks.push(Pos(lineNo, found))
	      }
	      lineNo++
	    })
	    for (var i = newBreaks.length - 1; i >= 0; i--)
	      { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) }
	  })
	  option("specialChars", /[\u0000-\u001f\u007f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, function (cm, val, old) {
	    cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g")
	    if (old != Init) { cm.refresh() }
	  })
	  option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true)
	  option("electricChars", true)
	  option("inputStyle", mobile ? "contenteditable" : "textarea", function () {
	    throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME
	  }, true)
	  option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true)
	  option("rtlMoveVisually", !windows)
	  option("wholeLineUpdateBefore", true)
	
	  option("theme", "default", function (cm) {
	    themeChanged(cm)
	    guttersChanged(cm)
	  }, true)
	  option("keyMap", "default", function (cm, val, old) {
	    var next = getKeyMap(val)
	    var prev = old != Init && getKeyMap(old)
	    if (prev && prev.detach) { prev.detach(cm, next) }
	    if (next.attach) { next.attach(cm, prev || null) }
	  })
	  option("extraKeys", null)
	
	  option("lineWrapping", false, wrappingChanged, true)
	  option("gutters", [], function (cm) {
	    setGuttersForLineNumbers(cm.options)
	    guttersChanged(cm)
	  }, true)
	  option("fixedGutter", true, function (cm, val) {
	    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"
	    cm.refresh()
	  }, true)
	  option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true)
	  option("scrollbarStyle", "native", function (cm) {
	    initScrollbars(cm)
	    updateScrollbars(cm)
	    cm.display.scrollbars.setScrollTop(cm.doc.scrollTop)
	    cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft)
	  }, true)
	  option("lineNumbers", false, function (cm) {
	    setGuttersForLineNumbers(cm.options)
	    guttersChanged(cm)
	  }, true)
	  option("firstLineNumber", 1, guttersChanged, true)
	  option("lineNumberFormatter", function (integer) { return integer; }, guttersChanged, true)
	  option("showCursorWhenSelecting", false, updateSelection, true)
	
	  option("resetSelectionOnContextMenu", true)
	  option("lineWiseCopyCut", true)
	
	  option("readOnly", false, function (cm, val) {
	    if (val == "nocursor") {
	      onBlur(cm)
	      cm.display.input.blur()
	      cm.display.disabled = true
	    } else {
	      cm.display.disabled = false
	    }
	    cm.display.input.readOnlyChanged(val)
	  })
	  option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset() }}, true)
	  option("dragDrop", true, dragDropChanged)
	  option("allowDropFileTypes", null)
	
	  option("cursorBlinkRate", 530)
	  option("cursorScrollMargin", 0)
	  option("cursorHeight", 1, updateSelection, true)
	  option("singleCursorHeightPerLine", true, updateSelection, true)
	  option("workTime", 100)
	  option("workDelay", 100)
	  option("flattenSpans", true, resetModeState, true)
	  option("addModeClass", false, resetModeState, true)
	  option("pollInterval", 100)
	  option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; })
	  option("historyEventDelay", 1250)
	  option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true)
	  option("maxHighlightLength", 10000, resetModeState, true)
	  option("moveInputWithCursor", true, function (cm, val) {
	    if (!val) { cm.display.input.resetPosition() }
	  })
	
	  option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; })
	  option("autofocus", null)
	}
	
	function guttersChanged(cm) {
	  updateGutters(cm)
	  regChange(cm)
	  alignHorizontally(cm)
	}
	
	function dragDropChanged(cm, value, old) {
	  var wasOn = old && old != Init
	  if (!value != !wasOn) {
	    var funcs = cm.display.dragFunctions
	    var toggle = value ? on : off
	    toggle(cm.display.scroller, "dragstart", funcs.start)
	    toggle(cm.display.scroller, "dragenter", funcs.enter)
	    toggle(cm.display.scroller, "dragover", funcs.over)
	    toggle(cm.display.scroller, "dragleave", funcs.leave)
	    toggle(cm.display.scroller, "drop", funcs.drop)
	  }
	}
	
	function wrappingChanged(cm) {
	  if (cm.options.lineWrapping) {
	    addClass(cm.display.wrapper, "CodeMirror-wrap")
	    cm.display.sizer.style.minWidth = ""
	    cm.display.sizerWidth = null
	  } else {
	    rmClass(cm.display.wrapper, "CodeMirror-wrap")
	    findMaxLine(cm)
	  }
	  estimateLineHeights(cm)
	  regChange(cm)
	  clearCaches(cm)
	  setTimeout(function () { return updateScrollbars(cm); }, 100)
	}
	
	// A CodeMirror instance represents an editor. This is the object
	// that user code is usually dealing with.
	
	function CodeMirror(place, options) {
	  var this$1 = this;
	
	  if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) }
	
	  this.options = options = options ? copyObj(options) : {}
	  // Determine effective options based on given values and defaults.
	  copyObj(defaults, options, false)
	  setGuttersForLineNumbers(options)
	
	  var doc = options.value
	  if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator) }
	  this.doc = doc
	
	  var input = new CodeMirror.inputStyles[options.inputStyle](this)
	  var display = this.display = new Display(place, doc, input)
	  display.wrapper.CodeMirror = this
	  updateGutters(this)
	  themeChanged(this)
	  if (options.lineWrapping)
	    { this.display.wrapper.className += " CodeMirror-wrap" }
	  initScrollbars(this)
	
	  this.state = {
	    keyMaps: [],  // stores maps added by addKeyMap
	    overlays: [], // highlighting overlays, as added by addOverlay
	    modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info
	    overwrite: false,
	    delayingBlurEvent: false,
	    focused: false,
	    suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
	    pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
	    selectingText: false,
	    draggingText: false,
	    highlight: new Delayed(), // stores highlight worker timeout
	    keySeq: null,  // Unfinished key sequence
	    specialChars: null
	  }
	
	  if (options.autofocus && !mobile) { display.input.focus() }
	
	  // Override magic textarea content restore that IE sometimes does
	  // on our hidden textarea on reload
	  if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20) }
	
	  registerEventHandlers(this)
	  ensureGlobalHandlers()
	
	  startOperation(this)
	  this.curOp.forceUpdate = true
	  attachDoc(this, doc)
	
	  if ((options.autofocus && !mobile) || this.hasFocus())
	    { setTimeout(bind(onFocus, this), 20) }
	  else
	    { onBlur(this) }
	
	  for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
	    { optionHandlers[opt](this$1, options[opt], Init) } }
	  maybeUpdateLineNumberWidth(this)
	  if (options.finishInit) { options.finishInit(this) }
	  for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1) }
	  endOperation(this)
	  // Suppress optimizelegibility in Webkit, since it breaks text
	  // measuring on line wrapping boundaries.
	  if (webkit && options.lineWrapping &&
	      getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
	    { display.lineDiv.style.textRendering = "auto" }
	}
	
	// The default configuration options.
	CodeMirror.defaults = defaults
	// Functions to run when options are changed.
	CodeMirror.optionHandlers = optionHandlers
	
	// Attach the necessary event handlers when initializing the editor
	function registerEventHandlers(cm) {
	  var d = cm.display
	  on(d.scroller, "mousedown", operation(cm, onMouseDown))
	  // Older IE's will not fire a second mousedown for a double click
	  if (ie && ie_version < 11)
	    { on(d.scroller, "dblclick", operation(cm, function (e) {
	      if (signalDOMEvent(cm, e)) { return }
	      var pos = posFromMouse(cm, e)
	      if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return }
	      e_preventDefault(e)
	      var word = cm.findWordAt(pos)
	      extendSelection(cm.doc, word.anchor, word.head)
	    })) }
	  else
	    { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }) }
	  // Some browsers fire contextmenu *after* opening the menu, at
	  // which point we can't mess with it anymore. Context menu is
	  // handled in onMouseDown for these browsers.
	  if (!captureRightClick) { on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }) }
	
	  // Used to suppress mouse event handling when a touch happens
	  var touchFinished, prevTouch = {end: 0}
	  function finishTouch() {
	    if (d.activeTouch) {
	      touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000)
	      prevTouch = d.activeTouch
	      prevTouch.end = +new Date
	    }
	  }
	  function isMouseLikeTouchEvent(e) {
	    if (e.touches.length != 1) { return false }
	    var touch = e.touches[0]
	    return touch.radiusX <= 1 && touch.radiusY <= 1
	  }
	  function farAway(touch, other) {
	    if (other.left == null) { return true }
	    var dx = other.left - touch.left, dy = other.top - touch.top
	    return dx * dx + dy * dy > 20 * 20
	  }
	  on(d.scroller, "touchstart", function (e) {
	    if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {
	      d.input.ensurePolled()
	      clearTimeout(touchFinished)
	      var now = +new Date
	      d.activeTouch = {start: now, moved: false,
	                       prev: now - prevTouch.end <= 300 ? prevTouch : null}
	      if (e.touches.length == 1) {
	        d.activeTouch.left = e.touches[0].pageX
	        d.activeTouch.top = e.touches[0].pageY
	      }
	    }
	  })
	  on(d.scroller, "touchmove", function () {
	    if (d.activeTouch) { d.activeTouch.moved = true }
	  })
	  on(d.scroller, "touchend", function (e) {
	    var touch = d.activeTouch
	    if (touch && !eventInWidget(d, e) && touch.left != null &&
	        !touch.moved && new Date - touch.start < 300) {
	      var pos = cm.coordsChar(d.activeTouch, "page"), range
	      if (!touch.prev || farAway(touch, touch.prev)) // Single tap
	        { range = new Range(pos, pos) }
	      else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
	        { range = cm.findWordAt(pos) }
	      else // Triple tap
	        { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) }
	      cm.setSelection(range.anchor, range.head)
	      cm.focus()
	      e_preventDefault(e)
	    }
	    finishTouch()
	  })
	  on(d.scroller, "touchcancel", finishTouch)
	
	  // Sync scrolling between fake scrollbars and real scrollable
	  // area, ensure viewport is updated when scrolling.
	  on(d.scroller, "scroll", function () {
	    if (d.scroller.clientHeight) {
	      setScrollTop(cm, d.scroller.scrollTop)
	      setScrollLeft(cm, d.scroller.scrollLeft, true)
	      signal(cm, "scroll", cm)
	    }
	  })
	
	  // Listen to wheel events in order to try and update the viewport on time.
	  on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); })
	  on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); })
	
	  // Prevent wrapper from ever scrolling
	  on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; })
	
	  d.dragFunctions = {
	    enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e) }},
	    over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e) }},
	    start: function (e) { return onDragStart(cm, e); },
	    drop: operation(cm, onDrop),
	    leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm) }}
	  }
	
	  var inp = d.input.getField()
	  on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); })
	  on(inp, "keydown", operation(cm, onKeyDown))
	  on(inp, "keypress", operation(cm, onKeyPress))
	  on(inp, "focus", function (e) { return onFocus(cm, e); })
	  on(inp, "blur", function (e) { return onBlur(cm, e); })
	}
	
	var initHooks = []
	CodeMirror.defineInitHook = function (f) { return initHooks.push(f); }
	
	// Indent the given line. The how parameter can be "smart",
	// "add"/null, "subtract", or "prev". When aggressive is false
	// (typically set to true for forced single-line indents), empty
	// lines are not indented, and places where the mode returns Pass
	// are left alone.
	function indentLine(cm, n, how, aggressive) {
	  var doc = cm.doc, state
	  if (how == null) { how = "add" }
	  if (how == "smart") {
	    // Fall back to "prev" when the mode doesn't have an indentation
	    // method.
	    if (!doc.mode.indent) { how = "prev" }
	    else { state = getStateBefore(cm, n) }
	  }
	
	  var tabSize = cm.options.tabSize
	  var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize)
	  if (line.stateAfter) { line.stateAfter = null }
	  var curSpaceString = line.text.match(/^\s*/)[0], indentation
	  if (!aggressive && !/\S/.test(line.text)) {
	    indentation = 0
	    how = "not"
	  } else if (how == "smart") {
	    indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text)
	    if (indentation == Pass || indentation > 150) {
	      if (!aggressive) { return }
	      how = "prev"
	    }
	  }
	  if (how == "prev") {
	    if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize) }
	    else { indentation = 0 }
	  } else if (how == "add") {
	    indentation = curSpace + cm.options.indentUnit
	  } else if (how == "subtract") {
	    indentation = curSpace - cm.options.indentUnit
	  } else if (typeof how == "number") {
	    indentation = curSpace + how
	  }
	  indentation = Math.max(0, indentation)
	
	  var indentString = "", pos = 0
	  if (cm.options.indentWithTabs)
	    { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t"} }
	  if (pos < indentation) { indentString += spaceStr(indentation - pos) }
	
	  if (indentString != curSpaceString) {
	    replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input")
	    line.stateAfter = null
	    return true
	  } else {
	    // Ensure that, if the cursor was in the whitespace at the start
	    // of the line, it is moved to the end of that space.
	    for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) {
	      var range = doc.sel.ranges[i$1]
	      if (range.head.line == n && range.head.ch < curSpaceString.length) {
	        var pos$1 = Pos(n, curSpaceString.length)
	        replaceOneSelection(doc, i$1, new Range(pos$1, pos$1))
	        break
	      }
	    }
	  }
	}
	
	// This will be set to a {lineWise: bool, text: [string]} object, so
	// that, when pasting, we know what kind of selections the copied
	// text was made out of.
	var lastCopied = null
	
	function setLastCopied(newLastCopied) {
	  lastCopied = newLastCopied
	}
	
	function applyTextInput(cm, inserted, deleted, sel, origin) {
	  var doc = cm.doc
	  cm.display.shift = false
	  if (!sel) { sel = doc.sel }
	
	  var paste = cm.state.pasteIncoming || origin == "paste"
	  var textLines = splitLinesAuto(inserted), multiPaste = null
	  // When pasing N lines into N selections, insert one line per selection
	  if (paste && sel.ranges.length > 1) {
	    if (lastCopied && lastCopied.text.join("\n") == inserted) {
	      if (sel.ranges.length % lastCopied.text.length == 0) {
	        multiPaste = []
	        for (var i = 0; i < lastCopied.text.length; i++)
	          { multiPaste.push(doc.splitLines(lastCopied.text[i])) }
	      }
	    } else if (textLines.length == sel.ranges.length) {
	      multiPaste = map(textLines, function (l) { return [l]; })
	    }
	  }
	
	  var updateInput
	  // Normal behavior is to insert the new text into every selection
	  for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) {
	    var range = sel.ranges[i$1]
	    var from = range.from(), to = range.to()
	    if (range.empty()) {
	      if (deleted && deleted > 0) // Handle deletion
	        { from = Pos(from.line, from.ch - deleted) }
	      else if (cm.state.overwrite && !paste) // Handle overwrite
	        { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)) }
	      else if (lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted)
	        { from = to = Pos(from.line, 0) }
	    }
	    updateInput = cm.curOp.updateInput
	    var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,
	                       origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")}
	    makeChange(cm.doc, changeEvent)
	    signalLater(cm, "inputRead", cm, changeEvent)
	  }
	  if (inserted && !paste)
	    { triggerElectric(cm, inserted) }
	
	  ensureCursorVisible(cm)
	  cm.curOp.updateInput = updateInput
	  cm.curOp.typing = true
	  cm.state.pasteIncoming = cm.state.cutIncoming = false
	}
	
	function handlePaste(e, cm) {
	  var pasted = e.clipboardData && e.clipboardData.getData("Text")
	  if (pasted) {
	    e.preventDefault()
	    if (!cm.isReadOnly() && !cm.options.disableInput)
	      { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }) }
	    return true
	  }
	}
	
	function triggerElectric(cm, inserted) {
	  // When an 'electric' character is inserted, immediately trigger a reindent
	  if (!cm.options.electricChars || !cm.options.smartIndent) { return }
	  var sel = cm.doc.sel
	
	  for (var i = sel.ranges.length - 1; i >= 0; i--) {
	    var range = sel.ranges[i]
	    if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue }
	    var mode = cm.getModeAt(range.head)
	    var indented = false
	    if (mode.electricChars) {
	      for (var j = 0; j < mode.electricChars.length; j++)
	        { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
	          indented = indentLine(cm, range.head.line, "smart")
	          break
	        } }
	    } else if (mode.electricInput) {
	      if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
	        { indented = indentLine(cm, range.head.line, "smart") }
	    }
	    if (indented) { signalLater(cm, "electricInput", cm, range.head.line) }
	  }
	}
	
	function copyableRanges(cm) {
	  var text = [], ranges = []
	  for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
	    var line = cm.doc.sel.ranges[i].head.line
	    var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}
	    ranges.push(lineRange)
	    text.push(cm.getRange(lineRange.anchor, lineRange.head))
	  }
	  return {text: text, ranges: ranges}
	}
	
	function disableBrowserMagic(field, spellcheck) {
	  field.setAttribute("autocorrect", "off")
	  field.setAttribute("autocapitalize", "off")
	  field.setAttribute("spellcheck", !!spellcheck)
	}
	
	function hiddenTextarea() {
	  var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none")
	  var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;")
	  // The textarea is kept positioned near the cursor to prevent the
	  // fact that it'll be scrolled into view on input from scrolling
	  // our fake cursor out of view. On webkit, when wrap=off, paste is
	  // very slow. So make the area wide instead.
	  if (webkit) { te.style.width = "1000px" }
	  else { te.setAttribute("wrap", "off") }
	  // If border: 0; -- iOS fails to open keyboard (issue #1287)
	  if (ios) { te.style.border = "1px solid black" }
	  disableBrowserMagic(te)
	  return div
	}
	
	// The publicly visible API. Note that methodOp(f) means
	// 'wrap f in an operation, performed on its `this` parameter'.
	
	// This is not the complete set of editor methods. Most of the
	// methods defined on the Doc type are also injected into
	// CodeMirror.prototype, for backwards compatibility and
	// convenience.
	
	function addEditorMethods(CodeMirror) {
	  var optionHandlers = CodeMirror.optionHandlers
	
	  var helpers = CodeMirror.helpers = {}
	
	  CodeMirror.prototype = {
	    constructor: CodeMirror,
	    focus: function(){window.focus(); this.display.input.focus()},
	
	    setOption: function(option, value) {
	      var options = this.options, old = options[option]
	      if (options[option] == value && option != "mode") { return }
	      options[option] = value
	      if (optionHandlers.hasOwnProperty(option))
	        { operation(this, optionHandlers[option])(this, value, old) }
	      signal(this, "optionChange", this, option)
	    },
	
	    getOption: function(option) {return this.options[option]},
	    getDoc: function() {return this.doc},
	
	    addKeyMap: function(map, bottom) {
	      this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map))
	    },
	    removeKeyMap: function(map) {
	      var maps = this.state.keyMaps
	      for (var i = 0; i < maps.length; ++i)
	        { if (maps[i] == map || maps[i].name == map) {
	          maps.splice(i, 1)
	          return true
	        } }
	    },
	
	    addOverlay: methodOp(function(spec, options) {
	      var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec)
	      if (mode.startState) { throw new Error("Overlays may not be stateful.") }
	      insertSorted(this.state.overlays,
	                   {mode: mode, modeSpec: spec, opaque: options && options.opaque,
	                    priority: (options && options.priority) || 0},
	                   function (overlay) { return overlay.priority; })
	      this.state.modeGen++
	      regChange(this)
	    }),
	    removeOverlay: methodOp(function(spec) {
	      var this$1 = this;
	
	      var overlays = this.state.overlays
	      for (var i = 0; i < overlays.length; ++i) {
	        var cur = overlays[i].modeSpec
	        if (cur == spec || typeof spec == "string" && cur.name == spec) {
	          overlays.splice(i, 1)
	          this$1.state.modeGen++
	          regChange(this$1)
	          return
	        }
	      }
	    }),
	
	    indentLine: methodOp(function(n, dir, aggressive) {
	      if (typeof dir != "string" && typeof dir != "number") {
	        if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev" }
	        else { dir = dir ? "add" : "subtract" }
	      }
	      if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive) }
	    }),
	    indentSelection: methodOp(function(how) {
	      var this$1 = this;
	
	      var ranges = this.doc.sel.ranges, end = -1
	      for (var i = 0; i < ranges.length; i++) {
	        var range = ranges[i]
	        if (!range.empty()) {
	          var from = range.from(), to = range.to()
	          var start = Math.max(end, from.line)
	          end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1
	          for (var j = start; j < end; ++j)
	            { indentLine(this$1, j, how) }
	          var newRanges = this$1.doc.sel.ranges
	          if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
	            { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll) }
	        } else if (range.head.line > end) {
	          indentLine(this$1, range.head.line, how, true)
	          end = range.head.line
	          if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1) }
	        }
	      }
	    }),
	
	    // Fetch the parser token for a given character. Useful for hacks
	    // that want to inspect the mode state (say, for completion).
	    getTokenAt: function(pos, precise) {
	      return takeToken(this, pos, precise)
	    },
	
	    getLineTokens: function(line, precise) {
	      return takeToken(this, Pos(line), precise, true)
	    },
	
	    getTokenTypeAt: function(pos) {
	      pos = clipPos(this.doc, pos)
	      var styles = getLineStyles(this, getLine(this.doc, pos.line))
	      var before = 0, after = (styles.length - 1) / 2, ch = pos.ch
	      var type
	      if (ch == 0) { type = styles[2] }
	      else { for (;;) {
	        var mid = (before + after) >> 1
	        if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid }
	        else if (styles[mid * 2 + 1] < ch) { before = mid + 1 }
	        else { type = styles[mid * 2 + 2]; break }
	      } }
	      var cut = type ? type.indexOf("overlay ") : -1
	      return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1)
	    },
	
	    getModeAt: function(pos) {
	      var mode = this.doc.mode
	      if (!mode.innerMode) { return mode }
	      return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode
	    },
	
	    getHelper: function(pos, type) {
	      return this.getHelpers(pos, type)[0]
	    },
	
	    getHelpers: function(pos, type) {
	      var this$1 = this;
	
	      var found = []
	      if (!helpers.hasOwnProperty(type)) { return found }
	      var help = helpers[type], mode = this.getModeAt(pos)
	      if (typeof mode[type] == "string") {
	        if (help[mode[type]]) { found.push(help[mode[type]]) }
	      } else if (mode[type]) {
	        for (var i = 0; i < mode[type].length; i++) {
	          var val = help[mode[type][i]]
	          if (val) { found.push(val) }
	        }
	      } else if (mode.helperType && help[mode.helperType]) {
	        found.push(help[mode.helperType])
	      } else if (help[mode.name]) {
	        found.push(help[mode.name])
	      }
	      for (var i$1 = 0; i$1 < help._global.length; i$1++) {
	        var cur = help._global[i$1]
	        if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1)
	          { found.push(cur.val) }
	      }
	      return found
	    },
	
	    getStateAfter: function(line, precise) {
	      var doc = this.doc
	      line = clipLine(doc, line == null ? doc.first + doc.size - 1: line)
	      return getStateBefore(this, line + 1, precise)
	    },
	
	    cursorCoords: function(start, mode) {
	      var pos, range = this.doc.sel.primary()
	      if (start == null) { pos = range.head }
	      else if (typeof start == "object") { pos = clipPos(this.doc, start) }
	      else { pos = start ? range.from() : range.to() }
	      return cursorCoords(this, pos, mode || "page")
	    },
	
	    charCoords: function(pos, mode) {
	      return charCoords(this, clipPos(this.doc, pos), mode || "page")
	    },
	
	    coordsChar: function(coords, mode) {
	      coords = fromCoordSystem(this, coords, mode || "page")
	      return coordsChar(this, coords.left, coords.top)
	    },
	
	    lineAtHeight: function(height, mode) {
	      height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top
	      return lineAtHeight(this.doc, height + this.display.viewOffset)
	    },
	    heightAtLine: function(line, mode, includeWidgets) {
	      var end = false, lineObj
	      if (typeof line == "number") {
	        var last = this.doc.first + this.doc.size - 1
	        if (line < this.doc.first) { line = this.doc.first }
	        else if (line > last) { line = last; end = true }
	        lineObj = getLine(this.doc, line)
	      } else {
	        lineObj = line
	      }
	      return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets).top +
	        (end ? this.doc.height - heightAtLine(lineObj) : 0)
	    },
	
	    defaultTextHeight: function() { return textHeight(this.display) },
	    defaultCharWidth: function() { return charWidth(this.display) },
	
	    getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}},
	
	    addWidget: function(pos, node, scroll, vert, horiz) {
	      var display = this.display
	      pos = cursorCoords(this, clipPos(this.doc, pos))
	      var top = pos.bottom, left = pos.left
	      node.style.position = "absolute"
	      node.setAttribute("cm-ignore-events", "true")
	      this.display.input.setUneditable(node)
	      display.sizer.appendChild(node)
	      if (vert == "over") {
	        top = pos.top
	      } else if (vert == "above" || vert == "near") {
	        var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
	        hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth)
	        // Default to positioning above (if specified and possible); otherwise default to positioning below
	        if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
	          { top = pos.top - node.offsetHeight }
	        else if (pos.bottom + node.offsetHeight <= vspace)
	          { top = pos.bottom }
	        if (left + node.offsetWidth > hspace)
	          { left = hspace - node.offsetWidth }
	      }
	      node.style.top = top + "px"
	      node.style.left = node.style.right = ""
	      if (horiz == "right") {
	        left = display.sizer.clientWidth - node.offsetWidth
	        node.style.right = "0px"
	      } else {
	        if (horiz == "left") { left = 0 }
	        else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2 }
	        node.style.left = left + "px"
	      }
	      if (scroll)
	        { scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight) }
	    },
	
	    triggerOnKeyDown: methodOp(onKeyDown),
	    triggerOnKeyPress: methodOp(onKeyPress),
	    triggerOnKeyUp: onKeyUp,
	
	    execCommand: function(cmd) {
	      if (commands.hasOwnProperty(cmd))
	        { return commands[cmd].call(null, this) }
	    },
	
	    triggerElectric: methodOp(function(text) { triggerElectric(this, text) }),
	
	    findPosH: function(from, amount, unit, visually) {
	      var this$1 = this;
	
	      var dir = 1
	      if (amount < 0) { dir = -1; amount = -amount }
	      var cur = clipPos(this.doc, from)
	      for (var i = 0; i < amount; ++i) {
	        cur = findPosH(this$1.doc, cur, dir, unit, visually)
	        if (cur.hitSide) { break }
	      }
	      return cur
	    },
	
	    moveH: methodOp(function(dir, unit) {
	      var this$1 = this;
	
	      this.extendSelectionsBy(function (range) {
	        if (this$1.display.shift || this$1.doc.extend || range.empty())
	          { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) }
	        else
	          { return dir < 0 ? range.from() : range.to() }
	      }, sel_move)
	    }),
	
	    deleteH: methodOp(function(dir, unit) {
	      var sel = this.doc.sel, doc = this.doc
	      if (sel.somethingSelected())
	        { doc.replaceSelection("", null, "+delete") }
	      else
	        { deleteNearSelection(this, function (range) {
	          var other = findPosH(doc, range.head, dir, unit, false)
	          return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}
	        }) }
	    }),
	
	    findPosV: function(from, amount, unit, goalColumn) {
	      var this$1 = this;
	
	      var dir = 1, x = goalColumn
	      if (amount < 0) { dir = -1; amount = -amount }
	      var cur = clipPos(this.doc, from)
	      for (var i = 0; i < amount; ++i) {
	        var coords = cursorCoords(this$1, cur, "div")
	        if (x == null) { x = coords.left }
	        else { coords.left = x }
	        cur = findPosV(this$1, coords, dir, unit)
	        if (cur.hitSide) { break }
	      }
	      return cur
	    },
	
	    moveV: methodOp(function(dir, unit) {
	      var this$1 = this;
	
	      var doc = this.doc, goals = []
	      var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected()
	      doc.extendSelectionsBy(function (range) {
	        if (collapse)
	          { return dir < 0 ? range.from() : range.to() }
	        var headPos = cursorCoords(this$1, range.head, "div")
	        if (range.goalColumn != null) { headPos.left = range.goalColumn }
	        goals.push(headPos.left)
	        var pos = findPosV(this$1, headPos, dir, unit)
	        if (unit == "page" && range == doc.sel.primary())
	          { addToScrollPos(this$1, null, charCoords(this$1, pos, "div").top - headPos.top) }
	        return pos
	      }, sel_move)
	      if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)
	        { doc.sel.ranges[i].goalColumn = goals[i] } }
	    }),
	
	    // Find the word at the given position (as returned by coordsChar).
	    findWordAt: function(pos) {
	      var doc = this.doc, line = getLine(doc, pos.line).text
	      var start = pos.ch, end = pos.ch
	      if (line) {
	        var helper = this.getHelper(pos, "wordChars")
	        if ((pos.xRel < 0 || end == line.length) && start) { --start; } else { ++end }
	        var startChar = line.charAt(start)
	        var check = isWordChar(startChar, helper)
	          ? function (ch) { return isWordChar(ch, helper); }
	          : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); }
	          : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); }
	        while (start > 0 && check(line.charAt(start - 1))) { --start }
	        while (end < line.length && check(line.charAt(end))) { ++end }
	      }
	      return new Range(Pos(pos.line, start), Pos(pos.line, end))
	    },
	
	    toggleOverwrite: function(value) {
	      if (value != null && value == this.state.overwrite) { return }
	      if (this.state.overwrite = !this.state.overwrite)
	        { addClass(this.display.cursorDiv, "CodeMirror-overwrite") }
	      else
	        { rmClass(this.display.cursorDiv, "CodeMirror-overwrite") }
	
	      signal(this, "overwriteToggle", this, this.state.overwrite)
	    },
	    hasFocus: function() { return this.display.input.getField() == activeElt() },
	    isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },
	
	    scrollTo: methodOp(function(x, y) {
	      if (x != null || y != null) { resolveScrollToPos(this) }
	      if (x != null) { this.curOp.scrollLeft = x }
	      if (y != null) { this.curOp.scrollTop = y }
	    }),
	    getScrollInfo: function() {
	      var scroller = this.display.scroller
	      return {left: scroller.scrollLeft, top: scroller.scrollTop,
	              height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
	              width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
	              clientHeight: displayHeight(this), clientWidth: displayWidth(this)}
	    },
	
	    scrollIntoView: methodOp(function(range, margin) {
	      if (range == null) {
	        range = {from: this.doc.sel.primary().head, to: null}
	        if (margin == null) { margin = this.options.cursorScrollMargin }
	      } else if (typeof range == "number") {
	        range = {from: Pos(range, 0), to: null}
	      } else if (range.from == null) {
	        range = {from: range, to: null}
	      }
	      if (!range.to) { range.to = range.from }
	      range.margin = margin || 0
	
	      if (range.from.line != null) {
	        resolveScrollToPos(this)
	        this.curOp.scrollToPos = range
	      } else {
	        var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
	                                      Math.min(range.from.top, range.to.top) - range.margin,
	                                      Math.max(range.from.right, range.to.right),
	                                      Math.max(range.from.bottom, range.to.bottom) + range.margin)
	        this.scrollTo(sPos.scrollLeft, sPos.scrollTop)
	      }
	    }),
	
	    setSize: methodOp(function(width, height) {
	      var this$1 = this;
	
	      var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; }
	      if (width != null) { this.display.wrapper.style.width = interpret(width) }
	      if (height != null) { this.display.wrapper.style.height = interpret(height) }
	      if (this.options.lineWrapping) { clearLineMeasurementCache(this) }
	      var lineNo = this.display.viewFrom
	      this.doc.iter(lineNo, this.display.viewTo, function (line) {
	        if (line.widgets) { for (var i = 0; i < line.widgets.length; i++)
	          { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } }
	        ++lineNo
	      })
	      this.curOp.forceUpdate = true
	      signal(this, "refresh", this)
	    }),
	
	    operation: function(f){return runInOp(this, f)},
	
	    refresh: methodOp(function() {
	      var oldHeight = this.display.cachedTextHeight
	      regChange(this)
	      this.curOp.forceUpdate = true
	      clearCaches(this)
	      this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop)
	      updateGutterSpace(this)
	      if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
	        { estimateLineHeights(this) }
	      signal(this, "refresh", this)
	    }),
	
	    swapDoc: methodOp(function(doc) {
	      var old = this.doc
	      old.cm = null
	      attachDoc(this, doc)
	      clearCaches(this)
	      this.display.input.reset()
	      this.scrollTo(doc.scrollLeft, doc.scrollTop)
	      this.curOp.forceScroll = true
	      signalLater(this, "swapDoc", this, old)
	      return old
	    }),
	
	    getInputField: function(){return this.display.input.getField()},
	    getWrapperElement: function(){return this.display.wrapper},
	    getScrollerElement: function(){return this.display.scroller},
	    getGutterElement: function(){return this.display.gutters}
	  }
	  eventMixin(CodeMirror)
	
	  CodeMirror.registerHelper = function(type, name, value) {
	    if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []} }
	    helpers[type][name] = value
	  }
	  CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
	    CodeMirror.registerHelper(type, name, value)
	    helpers[type]._global.push({pred: predicate, val: value})
	  }
	}
	
	// Used for horizontal relative motion. Dir is -1 or 1 (left or
	// right), unit can be "char", "column" (like char, but doesn't
	// cross line boundaries), "word" (across next word), or "group" (to
	// the start of next group of word or non-word-non-whitespace
	// chars). The visually param controls whether, in right-to-left
	// text, direction 1 means to move towards the next index in the
	// string, or towards the character to the right of the current
	// position. The resulting position will have a hitSide=true
	// property if it reached the end of the document.
	function findPosH(doc, pos, dir, unit, visually) {
	  var line = pos.line, ch = pos.ch, origDir = dir
	  var lineObj = getLine(doc, line)
	  function findNextLine() {
	    var l = line + dir
	    if (l < doc.first || l >= doc.first + doc.size) { return false }
	    line = l
	    return lineObj = getLine(doc, l)
	  }
	  function moveOnce(boundToLine) {
	    var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true)
	    if (next == null) {
	      if (!boundToLine && findNextLine()) {
	        if (visually) { ch = (dir < 0 ? lineRight : lineLeft)(lineObj) }
	        else { ch = dir < 0 ? lineObj.text.length : 0 }
	      } else { return false }
	    } else { ch = next }
	    return true
	  }
	
	  if (unit == "char") {
	    moveOnce()
	  } else if (unit == "column") {
	    moveOnce(true)
	  } else if (unit == "word" || unit == "group") {
	    var sawType = null, group = unit == "group"
	    var helper = doc.cm && doc.cm.getHelper(pos, "wordChars")
	    for (var first = true;; first = false) {
	      if (dir < 0 && !moveOnce(!first)) { break }
	      var cur = lineObj.text.charAt(ch) || "\n"
	      var type = isWordChar(cur, helper) ? "w"
	        : group && cur == "\n" ? "n"
	        : !group || /\s/.test(cur) ? null
	        : "p"
	      if (group && !first && !type) { type = "s" }
	      if (sawType && sawType != type) {
	        if (dir < 0) {dir = 1; moveOnce()}
	        break
	      }
	
	      if (type) { sawType = type }
	      if (dir > 0 && !moveOnce(!first)) { break }
	    }
	  }
	  var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true)
	  if (!cmp(pos, result)) { result.hitSide = true }
	  return result
	}
	
	// For relative vertical movement. Dir may be -1 or 1. Unit can be
	// "page" or "line". The resulting position will have a hitSide=true
	// property if it reached the end of the document.
	function findPosV(cm, pos, dir, unit) {
	  var doc = cm.doc, x = pos.left, y
	  if (unit == "page") {
	    var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight)
	    var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3)
	    y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount
	
	  } else if (unit == "line") {
	    y = dir > 0 ? pos.bottom + 3 : pos.top - 3
	  }
	  var target
	  for (;;) {
	    target = coordsChar(cm, x, y)
	    if (!target.outside) { break }
	    if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break }
	    y += dir * 5
	  }
	  return target
	}
	
	// CONTENTEDITABLE INPUT STYLE
	
	var ContentEditableInput = function(cm) {
	  this.cm = cm
	  this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null
	  this.polling = new Delayed()
	  this.composing = null
	  this.gracePeriod = false
	  this.readDOMTimeout = null
	};
	
	ContentEditableInput.prototype.init = function (display) {
	    var this$1 = this;
	
	  var input = this, cm = input.cm
	  var div = input.div = display.lineDiv
	  disableBrowserMagic(div, cm.options.spellcheck)
	
	  on(div, "paste", function (e) {
	    if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
	    // IE doesn't fire input events, so we schedule a read for the pasted content in this way
	    if (ie_version <= 11) { setTimeout(operation(cm, function () {
	      if (!input.pollContent()) { regChange(cm) }
	    }), 20) }
	  })
	
	  on(div, "compositionstart", function (e) {
	    this$1.composing = {data: e.data, done: false}
	  })
	  on(div, "compositionupdate", function (e) {
	    if (!this$1.composing) { this$1.composing = {data: e.data, done: false} }
	  })
	  on(div, "compositionend", function (e) {
	    if (this$1.composing) {
	      if (e.data != this$1.composing.data) { this$1.readFromDOMSoon() }
	      this$1.composing.done = true
	    }
	  })
	
	  on(div, "touchstart", function () { return input.forceCompositionEnd(); })
	
	  on(div, "input", function () {
	    if (!this$1.composing) { this$1.readFromDOMSoon() }
	  })
	
	  function onCopyCut(e) {
	    if (signalDOMEvent(cm, e)) { return }
	    if (cm.somethingSelected()) {
	      setLastCopied({lineWise: false, text: cm.getSelections()})
	      if (e.type == "cut") { cm.replaceSelection("", null, "cut") }
	    } else if (!cm.options.lineWiseCopyCut) {
	      return
	    } else {
	      var ranges = copyableRanges(cm)
	      setLastCopied({lineWise: true, text: ranges.text})
	      if (e.type == "cut") {
	        cm.operation(function () {
	          cm.setSelections(ranges.ranges, 0, sel_dontScroll)
	          cm.replaceSelection("", null, "cut")
	        })
	      }
	    }
	    if (e.clipboardData) {
	      e.clipboardData.clearData()
	      var content = lastCopied.text.join("\n")
	      // iOS exposes the clipboard API, but seems to discard content inserted into it
	      e.clipboardData.setData("Text", content)
	      if (e.clipboardData.getData("Text") == content) {
	        e.preventDefault()
	        return
	      }
	    }
	    // Old-fashioned briefly-focus-a-textarea hack
	    var kludge = hiddenTextarea(), te = kludge.firstChild
	    cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild)
	    te.value = lastCopied.text.join("\n")
	    var hadFocus = document.activeElement
	    selectInput(te)
	    setTimeout(function () {
	      cm.display.lineSpace.removeChild(kludge)
	      hadFocus.focus()
	      if (hadFocus == div) { input.showPrimarySelection() }
	    }, 50)
	  }
	  on(div, "copy", onCopyCut)
	  on(div, "cut", onCopyCut)
	};
	
	ContentEditableInput.prototype.prepareSelection = function () {
	  var result = prepareSelection(this.cm, false)
	  result.focus = this.cm.state.focused
	  return result
	};
	
	ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
	  if (!info || !this.cm.display.view.length) { return }
	  if (info.focus || takeFocus) { this.showPrimarySelection() }
	  this.showMultipleSelections(info)
	};
	
	ContentEditableInput.prototype.showPrimarySelection = function () {
	  var sel = window.getSelection(), prim = this.cm.doc.sel.primary()
	  var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset)
	  var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset)
	  if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
	      cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
	      cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
	    { return }
	
	  var start = posToDOM(this.cm, prim.from())
	  var end = posToDOM(this.cm, prim.to())
	  if (!start && !end) { return }
	
	  var view = this.cm.display.view
	  var old = sel.rangeCount && sel.getRangeAt(0)
	  if (!start) {
	    start = {node: view[0].measure.map[2], offset: 0}
	  } else if (!end) { // FIXME dangerously hacky
	    var measure = view[view.length - 1].measure
	    var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map
	    end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}
	  }
	
	  var rng
	  try { rng = range(start.node, start.offset, end.offset, end.node) }
	  catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
	  if (rng) {
	    if (!gecko && this.cm.state.focused) {
	      sel.collapse(start.node, start.offset)
	      if (!rng.collapsed) {
	        sel.removeAllRanges()
	        sel.addRange(rng)
	      }
	    } else {
	      sel.removeAllRanges()
	      sel.addRange(rng)
	    }
	    if (old && sel.anchorNode == null) { sel.addRange(old) }
	    else if (gecko) { this.startGracePeriod() }
	  }
	  this.rememberSelection()
	};
	
	ContentEditableInput.prototype.startGracePeriod = function () {
	    var this$1 = this;
	
	  clearTimeout(this.gracePeriod)
	  this.gracePeriod = setTimeout(function () {
	    this$1.gracePeriod = false
	    if (this$1.selectionChanged())
	      { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }) }
	  }, 20)
	};
	
	ContentEditableInput.prototype.showMultipleSelections = function (info) {
	  removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors)
	  removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection)
	};
	
	ContentEditableInput.prototype.rememberSelection = function () {
	  var sel = window.getSelection()
	  this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset
	  this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset
	};
	
	ContentEditableInput.prototype.selectionInEditor = function () {
	  var sel = window.getSelection()
	  if (!sel.rangeCount) { return false }
	  var node = sel.getRangeAt(0).commonAncestorContainer
	  return contains(this.div, node)
	};
	
	ContentEditableInput.prototype.focus = function () {
	  if (this.cm.options.readOnly != "nocursor") {
	    if (!this.selectionInEditor())
	      { this.showSelection(this.prepareSelection(), true) }
	    this.div.focus()
	  }
	};
	ContentEditableInput.prototype.blur = function () { this.div.blur() };
	ContentEditableInput.prototype.getField = function () { return this.div };
	
	ContentEditableInput.prototype.supportsTouch = function () { return true };
	
	ContentEditableInput.prototype.receivedFocus = function () {
	  var input = this
	  if (this.selectionInEditor())
	    { this.pollSelection() }
	  else
	    { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }) }
	
	  function poll() {
	    if (input.cm.state.focused) {
	      input.pollSelection()
	      input.polling.set(input.cm.options.pollInterval, poll)
	    }
	  }
	  this.polling.set(this.cm.options.pollInterval, poll)
	};
	
	ContentEditableInput.prototype.selectionChanged = function () {
	  var sel = window.getSelection()
	  return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
	    sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset
	};
	
	ContentEditableInput.prototype.pollSelection = function () {
	  if (!this.composing && this.readDOMTimeout == null && !this.gracePeriod && this.selectionChanged()) {
	    var sel = window.getSelection(), cm = this.cm
	    this.rememberSelection()
	    var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset)
	    var head = domToPos(cm, sel.focusNode, sel.focusOffset)
	    if (anchor && head) { runInOp(cm, function () {
	      setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll)
	      if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true }
	    }) }
	  }
	};
	
	ContentEditableInput.prototype.pollContent = function () {
	  if (this.readDOMTimeout != null) {
	    clearTimeout(this.readDOMTimeout)
	    this.readDOMTimeout = null
	  }
	
	  var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary()
	  var from = sel.from(), to = sel.to()
	  if (from.ch == 0 && from.line > cm.firstLine())
	    { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length) }
	  if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine())
	    { to = Pos(to.line + 1, 0) }
	  if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false }
	
	  var fromIndex, fromLine, fromNode
	  if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
	    fromLine = lineNo(display.view[0].line)
	    fromNode = display.view[0].node
	  } else {
	    fromLine = lineNo(display.view[fromIndex].line)
	    fromNode = display.view[fromIndex - 1].node.nextSibling
	  }
	  var toIndex = findViewIndex(cm, to.line)
	  var toLine, toNode
	  if (toIndex == display.view.length - 1) {
	    toLine = display.viewTo - 1
	    toNode = display.lineDiv.lastChild
	  } else {
	    toLine = lineNo(display.view[toIndex + 1].line) - 1
	    toNode = display.view[toIndex + 1].node.previousSibling
	  }
	
	  if (!fromNode) { return false }
	  var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine))
	  var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length))
	  while (newText.length > 1 && oldText.length > 1) {
	    if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine-- }
	    else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++ }
	    else { break }
	  }
	
	  var cutFront = 0, cutEnd = 0
	  var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length)
	  while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
	    { ++cutFront }
	  var newBot = lst(newText), oldBot = lst(oldText)
	  var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
	                           oldBot.length - (oldText.length == 1 ? cutFront : 0))
	  while (cutEnd < maxCutEnd &&
	         newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
	    { ++cutEnd }
	
	  newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "")
	  newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "")
	
	  var chFrom = Pos(fromLine, cutFront)
	  var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0)
	  if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
	    replaceRange(cm.doc, newText, chFrom, chTo, "+input")
	    return true
	  }
	};
	
	ContentEditableInput.prototype.ensurePolled = function () {
	  this.forceCompositionEnd()
	};
	ContentEditableInput.prototype.reset = function () {
	  this.forceCompositionEnd()
	};
	ContentEditableInput.prototype.forceCompositionEnd = function () {
	  if (!this.composing) { return }
	  clearTimeout(this.readDOMTimeout)
	  this.composing = null
	  if (!this.pollContent()) { regChange(this.cm) }
	  this.div.blur()
	  this.div.focus()
	};
	ContentEditableInput.prototype.readFromDOMSoon = function () {
	    var this$1 = this;
	
	  if (this.readDOMTimeout != null) { return }
	  this.readDOMTimeout = setTimeout(function () {
	    this$1.readDOMTimeout = null
	    if (this$1.composing) {
	      if (this$1.composing.done) { this$1.composing = null }
	      else { return }
	    }
	    if (this$1.cm.isReadOnly() || !this$1.pollContent())
	      { runInOp(this$1.cm, function () { return regChange(this$1.cm); }) }
	  }, 80)
	};
	
	ContentEditableInput.prototype.setUneditable = function (node) {
	  node.contentEditable = "false"
	};
	
	ContentEditableInput.prototype.onKeyPress = function (e) {
	  e.preventDefault()
	  if (!this.cm.isReadOnly())
	    { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0) }
	};
	
	ContentEditableInput.prototype.readOnlyChanged = function (val) {
	  this.div.contentEditable = String(val != "nocursor")
	};
	
	ContentEditableInput.prototype.onContextMenu = function () {};
	ContentEditableInput.prototype.resetPosition = function () {};
	
	ContentEditableInput.prototype.needsContentAttribute = true
	
	function posToDOM(cm, pos) {
	  var view = findViewForLine(cm, pos.line)
	  if (!view || view.hidden) { return null }
	  var line = getLine(cm.doc, pos.line)
	  var info = mapFromLineView(view, line, pos.line)
	
	  var order = getOrder(line), side = "left"
	  if (order) {
	    var partPos = getBidiPartAt(order, pos.ch)
	    side = partPos % 2 ? "right" : "left"
	  }
	  var result = nodeAndOffsetInLineMap(info.map, pos.ch, side)
	  result.offset = result.collapse == "right" ? result.end : result.start
	  return result
	}
	
	function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos }
	
	function domTextBetween(cm, from, to, fromLine, toLine) {
	  var text = "", closing = false, lineSep = cm.doc.lineSeparator()
	  function recognizeMarker(id) { return function (marker) { return marker.id == id; } }
	  function walk(node) {
	    if (node.nodeType == 1) {
	      var cmText = node.getAttribute("cm-text")
	      if (cmText != null) {
	        if (cmText == "") { text += node.textContent.replace(/\u200b/g, "") }
	        else { text += cmText }
	        return
	      }
	      var markerID = node.getAttribute("cm-marker"), range
	      if (markerID) {
	        var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID))
	        if (found.length && (range = found[0].find()))
	          { text += getBetween(cm.doc, range.from, range.to).join(lineSep) }
	        return
	      }
	      if (node.getAttribute("contenteditable") == "false") { return }
	      for (var i = 0; i < node.childNodes.length; i++)
	        { walk(node.childNodes[i]) }
	      if (/^(pre|div|p)$/i.test(node.nodeName))
	        { closing = true }
	    } else if (node.nodeType == 3) {
	      var val = node.nodeValue
	      if (!val) { return }
	      if (closing) {
	        text += lineSep
	        closing = false
	      }
	      text += val
	    }
	  }
	  for (;;) {
	    walk(from)
	    if (from == to) { break }
	    from = from.nextSibling
	  }
	  return text
	}
	
	function domToPos(cm, node, offset) {
	  var lineNode
	  if (node == cm.display.lineDiv) {
	    lineNode = cm.display.lineDiv.childNodes[offset]
	    if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) }
	    node = null; offset = 0
	  } else {
	    for (lineNode = node;; lineNode = lineNode.parentNode) {
	      if (!lineNode || lineNode == cm.display.lineDiv) { return null }
	      if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break }
	    }
	  }
	  for (var i = 0; i < cm.display.view.length; i++) {
	    var lineView = cm.display.view[i]
	    if (lineView.node == lineNode)
	      { return locateNodeInLineView(lineView, node, offset) }
	  }
	}
	
	function locateNodeInLineView(lineView, node, offset) {
	  var wrapper = lineView.text.firstChild, bad = false
	  if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) }
	  if (node == wrapper) {
	    bad = true
	    node = wrapper.childNodes[offset]
	    offset = 0
	    if (!node) {
	      var line = lineView.rest ? lst(lineView.rest) : lineView.line
	      return badPos(Pos(lineNo(line), line.text.length), bad)
	    }
	  }
	
	  var textNode = node.nodeType == 3 ? node : null, topNode = node
	  if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
	    textNode = node.firstChild
	    if (offset) { offset = textNode.nodeValue.length }
	  }
	  while (topNode.parentNode != wrapper) { topNode = topNode.parentNode }
	  var measure = lineView.measure, maps = measure.maps
	
	  function find(textNode, topNode, offset) {
	    for (var i = -1; i < (maps ? maps.length : 0); i++) {
	      var map = i < 0 ? measure.map : maps[i]
	      for (var j = 0; j < map.length; j += 3) {
	        var curNode = map[j + 2]
	        if (curNode == textNode || curNode == topNode) {
	          var line = lineNo(i < 0 ? lineView.line : lineView.rest[i])
	          var ch = map[j] + offset
	          if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)] }
	          return Pos(line, ch)
	        }
	      }
	    }
	  }
	  var found = find(textNode, topNode, offset)
	  if (found) { return badPos(found, bad) }
	
	  // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
	  for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
	    found = find(after, after.firstChild, 0)
	    if (found)
	      { return badPos(Pos(found.line, found.ch - dist), bad) }
	    else
	      { dist += after.textContent.length }
	  }
	  for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) {
	    found = find(before, before.firstChild, -1)
	    if (found)
	      { return badPos(Pos(found.line, found.ch + dist$1), bad) }
	    else
	      { dist$1 += before.textContent.length }
	  }
	}
	
	// TEXTAREA INPUT STYLE
	
	var TextareaInput = function(cm) {
	  this.cm = cm
	  // See input.poll and input.reset
	  this.prevInput = ""
	
	  // Flag that indicates whether we expect input to appear real soon
	  // now (after some event like 'keypress' or 'input') and are
	  // polling intensively.
	  this.pollingFast = false
	  // Self-resetting timeout for the poller
	  this.polling = new Delayed()
	  // Tracks when input.reset has punted to just putting a short
	  // string into the textarea instead of the full selection.
	  this.inaccurateSelection = false
	  // Used to work around IE issue with selection being forgotten when focus moves away from textarea
	  this.hasSelection = false
	  this.composing = null
	};
	
	TextareaInput.prototype.init = function (display) {
	    var this$1 = this;
	
	  var input = this, cm = this.cm
	
	  // Wraps and hides input textarea
	  var div = this.wrapper = hiddenTextarea()
	  // The semihidden textarea that is focused when the editor is
	  // focused, and receives input.
	  var te = this.textarea = div.firstChild
	  display.wrapper.insertBefore(div, display.wrapper.firstChild)
	
	  // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
	  if (ios) { te.style.width = "0px" }
	
	  on(te, "input", function () {
	    if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null }
	    input.poll()
	  })
	
	  on(te, "paste", function (e) {
	    if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
	
	    cm.state.pasteIncoming = true
	    input.fastPoll()
	  })
	
	  function prepareCopyCut(e) {
	    if (signalDOMEvent(cm, e)) { return }
	    if (cm.somethingSelected()) {
	      setLastCopied({lineWise: false, text: cm.getSelections()})
	      if (input.inaccurateSelection) {
	        input.prevInput = ""
	        input.inaccurateSelection = false
	        te.value = lastCopied.text.join("\n")
	        selectInput(te)
	      }
	    } else if (!cm.options.lineWiseCopyCut) {
	      return
	    } else {
	      var ranges = copyableRanges(cm)
	      setLastCopied({lineWise: true, text: ranges.text})
	      if (e.type == "cut") {
	        cm.setSelections(ranges.ranges, null, sel_dontScroll)
	      } else {
	        input.prevInput = ""
	        te.value = ranges.text.join("\n")
	        selectInput(te)
	      }
	    }
	    if (e.type == "cut") { cm.state.cutIncoming = true }
	  }
	  on(te, "cut", prepareCopyCut)
	  on(te, "copy", prepareCopyCut)
	
	  on(display.scroller, "paste", function (e) {
	    if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return }
	    cm.state.pasteIncoming = true
	    input.focus()
	  })
	
	  // Prevent normal selection in the editor (we handle our own)
	  on(display.lineSpace, "selectstart", function (e) {
	    if (!eventInWidget(display, e)) { e_preventDefault(e) }
	  })
	
	  on(te, "compositionstart", function () {
	    var start = cm.getCursor("from")
	    if (input.composing) { input.composing.range.clear() }
	    input.composing = {
	      start: start,
	      range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
	    }
	  })
	  on(te, "compositionend", function () {
	    if (input.composing) {
	      input.poll()
	      input.composing.range.clear()
	      input.composing = null
	    }
	  })
	};
	
	TextareaInput.prototype.prepareSelection = function () {
	  // Redraw the selection and/or cursor
	  var cm = this.cm, display = cm.display, doc = cm.doc
	  var result = prepareSelection(cm)
	
	  // Move the hidden textarea near the cursor to prevent scrolling artifacts
	  if (cm.options.moveInputWithCursor) {
	    var headPos = cursorCoords(cm, doc.sel.primary().head, "div")
	    var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect()
	    result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
	                                        headPos.top + lineOff.top - wrapOff.top))
	    result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
	                                         headPos.left + lineOff.left - wrapOff.left))
	  }
	
	  return result
	};
	
	TextareaInput.prototype.showSelection = function (drawn) {
	  var cm = this.cm, display = cm.display
	  removeChildrenAndAdd(display.cursorDiv, drawn.cursors)
	  removeChildrenAndAdd(display.selectionDiv, drawn.selection)
	  if (drawn.teTop != null) {
	    this.wrapper.style.top = drawn.teTop + "px"
	    this.wrapper.style.left = drawn.teLeft + "px"
	  }
	};
	
	// Reset the input to correspond to the selection (or to be empty,
	// when not typing and nothing is selected)
	TextareaInput.prototype.reset = function (typing) {
	  if (this.contextMenuPending) { return }
	  var minimal, selected, cm = this.cm, doc = cm.doc
	  if (cm.somethingSelected()) {
	    this.prevInput = ""
	    var range = doc.sel.primary()
	    minimal = hasCopyEvent &&
	      (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000)
	    var content = minimal ? "-" : selected || cm.getSelection()
	    this.textarea.value = content
	    if (cm.state.focused) { selectInput(this.textarea) }
	    if (ie && ie_version >= 9) { this.hasSelection = content }
	  } else if (!typing) {
	    this.prevInput = this.textarea.value = ""
	    if (ie && ie_version >= 9) { this.hasSelection = null }
	  }
	  this.inaccurateSelection = minimal
	};
	
	TextareaInput.prototype.getField = function () { return this.textarea };
	
	TextareaInput.prototype.supportsTouch = function () { return false };
	
	TextareaInput.prototype.focus = function () {
	  if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
	    try { this.textarea.focus() }
	    catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
	  }
	};
	
	TextareaInput.prototype.blur = function () { this.textarea.blur() };
	
	TextareaInput.prototype.resetPosition = function () {
	  this.wrapper.style.top = this.wrapper.style.left = 0
	};
	
	TextareaInput.prototype.receivedFocus = function () { this.slowPoll() };
	
	// Poll for input changes, using the normal rate of polling. This
	// runs as long as the editor is focused.
	TextareaInput.prototype.slowPoll = function () {
	    var this$1 = this;
	
	  if (this.pollingFast) { return }
	  this.polling.set(this.cm.options.pollInterval, function () {
	    this$1.poll()
	    if (this$1.cm.state.focused) { this$1.slowPoll() }
	  })
	};
	
	// When an event has just come in that is likely to add or change
	// something in the input textarea, we poll faster, to ensure that
	// the change appears on the screen quickly.
	TextareaInput.prototype.fastPoll = function () {
	  var missed = false, input = this
	  input.pollingFast = true
	  function p() {
	    var changed = input.poll()
	    if (!changed && !missed) {missed = true; input.polling.set(60, p)}
	    else {input.pollingFast = false; input.slowPoll()}
	  }
	  input.polling.set(20, p)
	};
	
	// Read input from the textarea, and update the document to match.
	// When something is selected, it is present in the textarea, and
	// selected (unless it is huge, in which case a placeholder is
	// used). When nothing is selected, the cursor sits after previously
	// seen text (can be empty), which is stored in prevInput (we must
	// not reset the textarea when typing, because that breaks IME).
	TextareaInput.prototype.poll = function () {
	    var this$1 = this;
	
	  var cm = this.cm, input = this.textarea, prevInput = this.prevInput
	  // Since this is called a *lot*, try to bail out as cheaply as
	  // possible when it is clear that nothing happened. hasSelection
	  // will be the case when there is a lot of text in the textarea,
	  // in which case reading its value would be expensive.
	  if (this.contextMenuPending || !cm.state.focused ||
	      (hasSelection(input) && !prevInput && !this.composing) ||
	      cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
	    { return false }
	
	  var text = input.value
	  // If nothing changed, bail.
	  if (text == prevInput && !cm.somethingSelected()) { return false }
	  // Work around nonsensical selection resetting in IE9/10, and
	  // inexplicable appearance of private area unicode characters on
	  // some key combos in Mac (#2689).
	  if (ie && ie_version >= 9 && this.hasSelection === text ||
	      mac && /[\uf700-\uf7ff]/.test(text)) {
	    cm.display.input.reset()
	    return false
	  }
	
	  if (cm.doc.sel == cm.display.selForContextMenu) {
	    var first = text.charCodeAt(0)
	    if (first == 0x200b && !prevInput) { prevInput = "\u200b" }
	    if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") }
	  }
	  // Find the part of the input that is actually new
	  var same = 0, l = Math.min(prevInput.length, text.length)
	  while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same }
	
	  runInOp(cm, function () {
	    applyTextInput(cm, text.slice(same), prevInput.length - same,
	                   null, this$1.composing ? "*compose" : null)
	
	    // Don't leave long text in the textarea, since it makes further polling slow
	    if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = "" }
	    else { this$1.prevInput = text }
	
	    if (this$1.composing) {
	      this$1.composing.range.clear()
	      this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"),
	                                         {className: "CodeMirror-composing"})
	    }
	  })
	  return true
	};
	
	TextareaInput.prototype.ensurePolled = function () {
	  if (this.pollingFast && this.poll()) { this.pollingFast = false }
	};
	
	TextareaInput.prototype.onKeyPress = function () {
	  if (ie && ie_version >= 9) { this.hasSelection = null }
	  this.fastPoll()
	};
	
	TextareaInput.prototype.onContextMenu = function (e) {
	  var input = this, cm = input.cm, display = cm.display, te = input.textarea
	  var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop
	  if (!pos || presto) { return } // Opera is difficult.
	
	  // Reset the current text selection only if the click is done outside of the selection
	  // and 'resetSelectionOnContextMenu' option is true.
	  var reset = cm.options.resetSelectionOnContextMenu
	  if (reset && cm.doc.sel.contains(pos) == -1)
	    { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll) }
	
	  var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText
	  input.wrapper.style.cssText = "position: absolute"
	  var wrapperBox = input.wrapper.getBoundingClientRect()
	  te.style.cssText = "position: absolute; width: 30px; height: 30px;\n      top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n      z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n      outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"
	  var oldScrollY
	  if (webkit) { oldScrollY = window.scrollY } // Work around Chrome issue (#2712)
	  display.input.focus()
	  if (webkit) { window.scrollTo(null, oldScrollY) }
	  display.input.reset()
	  // Adds "Select all" to context menu in FF
	  if (!cm.somethingSelected()) { te.value = input.prevInput = " " }
	  input.contextMenuPending = true
	  display.selForContextMenu = cm.doc.sel
	  clearTimeout(display.detectingSelectAll)
	
	  // Select-all will be greyed out if there's nothing to select, so
	  // this adds a zero-width space so that we can later check whether
	  // it got selected.
	  function prepareSelectAllHack() {
	    if (te.selectionStart != null) {
	      var selected = cm.somethingSelected()
	      var extval = "\u200b" + (selected ? te.value : "")
	      te.value = "\u21da" // Used to catch context-menu undo
	      te.value = extval
	      input.prevInput = selected ? "" : "\u200b"
	      te.selectionStart = 1; te.selectionEnd = extval.length
	      // Re-set this, in case some other handler touched the
	      // selection in the meantime.
	      display.selForContextMenu = cm.doc.sel
	    }
	  }
	  function rehide() {
	    input.contextMenuPending = false
	    input.wrapper.style.cssText = oldWrapperCSS
	    te.style.cssText = oldCSS
	    if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos) }
	
	    // Try to detect the user choosing select-all
	    if (te.selectionStart != null) {
	      if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack() }
	      var i = 0, poll = function () {
	        if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
	            te.selectionEnd > 0 && input.prevInput == "\u200b")
	          { operation(cm, selectAll)(cm) }
	        else if (i++ < 10) { display.detectingSelectAll = setTimeout(poll, 500) }
	        else { display.input.reset() }
	      }
	      display.detectingSelectAll = setTimeout(poll, 200)
	    }
	  }
	
	  if (ie && ie_version >= 9) { prepareSelectAllHack() }
	  if (captureRightClick) {
	    e_stop(e)
	    var mouseup = function () {
	      off(window, "mouseup", mouseup)
	      setTimeout(rehide, 20)
	    }
	    on(window, "mouseup", mouseup)
	  } else {
	    setTimeout(rehide, 50)
	  }
	};
	
	TextareaInput.prototype.readOnlyChanged = function (val) {
	  if (!val) { this.reset() }
	};
	
	TextareaInput.prototype.setUneditable = function () {};
	
	TextareaInput.prototype.needsContentAttribute = false
	
	function fromTextArea(textarea, options) {
	  options = options ? copyObj(options) : {}
	  options.value = textarea.value
	  if (!options.tabindex && textarea.tabIndex)
	    { options.tabindex = textarea.tabIndex }
	  if (!options.placeholder && textarea.placeholder)
	    { options.placeholder = textarea.placeholder }
	  // Set autofocus to true if this textarea is focused, or if it has
	  // autofocus and no other element is focused.
	  if (options.autofocus == null) {
	    var hasFocus = activeElt()
	    options.autofocus = hasFocus == textarea ||
	      textarea.getAttribute("autofocus") != null && hasFocus == document.body
	  }
	
	  function save() {textarea.value = cm.getValue()}
	
	  var realSubmit
	  if (textarea.form) {
	    on(textarea.form, "submit", save)
	    // Deplorable hack to make the submit method do the right thing.
	    if (!options.leaveSubmitMethodAlone) {
	      var form = textarea.form
	      realSubmit = form.submit
	      try {
	        var wrappedSubmit = form.submit = function () {
	          save()
	          form.submit = realSubmit
	          form.submit()
	          form.submit = wrappedSubmit
	        }
	      } catch(e) {}
	    }
	  }
	
	  options.finishInit = function (cm) {
	    cm.save = save
	    cm.getTextArea = function () { return textarea; }
	    cm.toTextArea = function () {
	      cm.toTextArea = isNaN // Prevent this from being ran twice
	      save()
	      textarea.parentNode.removeChild(cm.getWrapperElement())
	      textarea.style.display = ""
	      if (textarea.form) {
	        off(textarea.form, "submit", save)
	        if (typeof textarea.form.submit == "function")
	          { textarea.form.submit = realSubmit }
	      }
	    }
	  }
	
	  textarea.style.display = "none"
	  var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); },
	    options)
	  return cm
	}
	
	function addLegacyProps(CodeMirror) {
	  CodeMirror.off = off
	  CodeMirror.on = on
	  CodeMirror.wheelEventPixels = wheelEventPixels
	  CodeMirror.Doc = Doc
	  CodeMirror.splitLines = splitLinesAuto
	  CodeMirror.countColumn = countColumn
	  CodeMirror.findColumn = findColumn
	  CodeMirror.isWordChar = isWordCharBasic
	  CodeMirror.Pass = Pass
	  CodeMirror.signal = signal
	  CodeMirror.Line = Line
	  CodeMirror.changeEnd = changeEnd
	  CodeMirror.scrollbarModel = scrollbarModel
	  CodeMirror.Pos = Pos
	  CodeMirror.cmpPos = cmp
	  CodeMirror.modes = modes
	  CodeMirror.mimeModes = mimeModes
	  CodeMirror.resolveMode = resolveMode
	  CodeMirror.getMode = getMode
	  CodeMirror.modeExtensions = modeExtensions
	  CodeMirror.extendMode = extendMode
	  CodeMirror.copyState = copyState
	  CodeMirror.startState = startState
	  CodeMirror.innerMode = innerMode
	  CodeMirror.commands = commands
	  CodeMirror.keyMap = keyMap
	  CodeMirror.keyName = keyName
	  CodeMirror.isModifierKey = isModifierKey
	  CodeMirror.lookupKey = lookupKey
	  CodeMirror.normalizeKeyMap = normalizeKeyMap
	  CodeMirror.StringStream = StringStream
	  CodeMirror.SharedTextMarker = SharedTextMarker
	  CodeMirror.TextMarker = TextMarker
	  CodeMirror.LineWidget = LineWidget
	  CodeMirror.e_preventDefault = e_preventDefault
	  CodeMirror.e_stopPropagation = e_stopPropagation
	  CodeMirror.e_stop = e_stop
	  CodeMirror.addClass = addClass
	  CodeMirror.contains = contains
	  CodeMirror.rmClass = rmClass
	  CodeMirror.keyNames = keyNames
	}
	
	// EDITOR CONSTRUCTOR
	
	defineOptions(CodeMirror)
	
	addEditorMethods(CodeMirror)
	
	// Set up methods on CodeMirror's prototype to redirect to the editor's document.
	var dontDelegate = "iter insert remove copy getEditor constructor".split(" ")
	for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
	  { CodeMirror.prototype[prop] = (function(method) {
	    return function() {return method.apply(this.doc, arguments)}
	  })(Doc.prototype[prop]) } }
	
	eventMixin(Doc)
	
	// INPUT HANDLING
	
	CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}
	
	// MODE DEFINITION AND QUERYING
	
	// Extra arguments are stored as the mode's dependencies, which is
	// used by (legacy) mechanisms like loadmode.js to automatically
	// load a mode. (Preferred mechanism is the require/define calls.)
	CodeMirror.defineMode = function(name/*, mode, …*/) {
	  if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name }
	  defineMode.apply(this, arguments)
	}
	
	CodeMirror.defineMIME = defineMIME
	
	// Minimal default mode.
	CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); })
	CodeMirror.defineMIME("text/plain", "null")
	
	// EXTENSIONS
	
	CodeMirror.defineExtension = function (name, func) {
	  CodeMirror.prototype[name] = func
	}
	CodeMirror.defineDocExtension = function (name, func) {
	  Doc.prototype[name] = func
	}
	
	CodeMirror.fromTextArea = fromTextArea
	
	addLegacyProps(CodeMirror)
	
	CodeMirror.version = "5.23.0"
	
	return CodeMirror;
	
	})));
})
/** END DEFINE BLOCK for codemirror@5.23.0/lib/codemirror.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/addon/edit/closebrackets.js **/
jupyter.define('codemirror@5.23.0/addon/edit/closebrackets.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  var defaults = {
	    pairs: "()[]{}''\"\"",
	    triples: "",
	    explode: "[]{}"
	  };
	
	  var Pos = CodeMirror.Pos;
	
	  CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
	    if (old && old != CodeMirror.Init) {
	      cm.removeKeyMap(keyMap);
	      cm.state.closeBrackets = null;
	    }
	    if (val) {
	      cm.state.closeBrackets = val;
	      cm.addKeyMap(keyMap);
	    }
	  });
	
	  function getOption(conf, name) {
	    if (name == "pairs" && typeof conf == "string") return conf;
	    if (typeof conf == "object" && conf[name] != null) return conf[name];
	    return defaults[name];
	  }
	
	  var bind = defaults.pairs + "`";
	  var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
	  for (var i = 0; i < bind.length; i++)
	    keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i));
	
	  function handler(ch) {
	    return function(cm) { return handleChar(cm, ch); };
	  }
	
	  function getConfig(cm) {
	    var deflt = cm.state.closeBrackets;
	    if (!deflt || deflt.override) return deflt;
	    var mode = cm.getModeAt(cm.getCursor());
	    return mode.closeBrackets || deflt;
	  }
	
	  function handleBackspace(cm) {
	    var conf = getConfig(cm);
	    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
	
	    var pairs = getOption(conf, "pairs");
	    var ranges = cm.listSelections();
	    for (var i = 0; i < ranges.length; i++) {
	      if (!ranges[i].empty()) return CodeMirror.Pass;
	      var around = charsAround(cm, ranges[i].head);
	      if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
	    }
	    for (var i = ranges.length - 1; i >= 0; i--) {
	      var cur = ranges[i].head;
	      cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete");
	    }
	  }
	
	  function handleEnter(cm) {
	    var conf = getConfig(cm);
	    var explode = conf && getOption(conf, "explode");
	    if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
	
	    var ranges = cm.listSelections();
	    for (var i = 0; i < ranges.length; i++) {
	      if (!ranges[i].empty()) return CodeMirror.Pass;
	      var around = charsAround(cm, ranges[i].head);
	      if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
	    }
	    cm.operation(function() {
	      cm.replaceSelection("\n\n", null);
	      cm.execCommand("goCharLeft");
	      ranges = cm.listSelections();
	      for (var i = 0; i < ranges.length; i++) {
	        var line = ranges[i].head.line;
	        cm.indentLine(line, null, true);
	        cm.indentLine(line + 1, null, true);
	      }
	    });
	  }
	
	  function contractSelection(sel) {
	    var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
	    return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
	            head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
	  }
	
	  function handleChar(cm, ch) {
	    var conf = getConfig(cm);
	    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
	
	    var pairs = getOption(conf, "pairs");
	    var pos = pairs.indexOf(ch);
	    if (pos == -1) return CodeMirror.Pass;
	    var triples = getOption(conf, "triples");
	
	    var identical = pairs.charAt(pos + 1) == ch;
	    var ranges = cm.listSelections();
	    var opening = pos % 2 == 0;
	
	    var type;
	    for (var i = 0; i < ranges.length; i++) {
	      var range = ranges[i], cur = range.head, curType;
	      var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
	      if (opening && !range.empty()) {
	        curType = "surround";
	      } else if ((identical || !opening) && next == ch) {
	        if (identical && stringStartsAfter(cm, cur))
	          curType = "both";
	        else if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
	          curType = "skipThree";
	        else
	          curType = "skip";
	      } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
	                 cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch &&
	                 (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) {
	        curType = "addFour";
	      } else if (identical) {
	        if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both";
	        else return CodeMirror.Pass;
	      } else if (opening && (cm.getLine(cur.line).length == cur.ch ||
	                             isClosingBracket(next, pairs) ||
	                             /\s/.test(next))) {
	        curType = "both";
	      } else {
	        return CodeMirror.Pass;
	      }
	      if (!type) type = curType;
	      else if (type != curType) return CodeMirror.Pass;
	    }
	
	    var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
	    var right = pos % 2 ? ch : pairs.charAt(pos + 1);
	    cm.operation(function() {
	      if (type == "skip") {
	        cm.execCommand("goCharRight");
	      } else if (type == "skipThree") {
	        for (var i = 0; i < 3; i++)
	          cm.execCommand("goCharRight");
	      } else if (type == "surround") {
	        var sels = cm.getSelections();
	        for (var i = 0; i < sels.length; i++)
	          sels[i] = left + sels[i] + right;
	        cm.replaceSelections(sels, "around");
	        sels = cm.listSelections().slice();
	        for (var i = 0; i < sels.length; i++)
	          sels[i] = contractSelection(sels[i]);
	        cm.setSelections(sels);
	      } else if (type == "both") {
	        cm.replaceSelection(left + right, null);
	        cm.triggerElectric(left + right);
	        cm.execCommand("goCharLeft");
	      } else if (type == "addFour") {
	        cm.replaceSelection(left + left + left + left, "before");
	        cm.execCommand("goCharRight");
	      }
	    });
	  }
	
	  function isClosingBracket(ch, pairs) {
	    var pos = pairs.lastIndexOf(ch);
	    return pos > -1 && pos % 2 == 1;
	  }
	
	  function charsAround(cm, pos) {
	    var str = cm.getRange(Pos(pos.line, pos.ch - 1),
	                          Pos(pos.line, pos.ch + 1));
	    return str.length == 2 ? str : null;
	  }
	
	  // Project the token type that will exists after the given char is
	  // typed, and use it to determine whether it would cause the start
	  // of a string token.
	  function enteringString(cm, pos, ch) {
	    var line = cm.getLine(pos.line);
	    var token = cm.getTokenAt(pos);
	    if (/\bstring2?\b/.test(token.type)) return false;
	    var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
	    stream.pos = stream.start = token.start;
	    for (;;) {
	      var type1 = cm.getMode().token(stream, token.state);
	      if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
	      stream.start = stream.pos;
	    }
	  }
	
	  function stringStartsAfter(cm, pos) {
	    var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1))
	    return /\bstring/.test(token.type) && token.start == pos.ch
	  }
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/addon/edit/closebrackets.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/addon/comment/comment.js **/
jupyter.define('codemirror@5.23.0/addon/comment/comment.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  "use strict";
	
	  var noOptions = {};
	  var nonWS = /[^\s\u00a0]/;
	  var Pos = CodeMirror.Pos;
	
	  function firstNonWS(str) {
	    var found = str.search(nonWS);
	    return found == -1 ? 0 : found;
	  }
	
	  CodeMirror.commands.toggleComment = function(cm) {
	    cm.toggleComment();
	  };
	
	  CodeMirror.defineExtension("toggleComment", function(options) {
	    if (!options) options = noOptions;
	    var cm = this;
	    var minLine = Infinity, ranges = this.listSelections(), mode = null;
	    for (var i = ranges.length - 1; i >= 0; i--) {
	      var from = ranges[i].from(), to = ranges[i].to();
	      if (from.line >= minLine) continue;
	      if (to.line >= minLine) to = Pos(minLine, 0);
	      minLine = from.line;
	      if (mode == null) {
	        if (cm.uncomment(from, to, options)) mode = "un";
	        else { cm.lineComment(from, to, options); mode = "line"; }
	      } else if (mode == "un") {
	        cm.uncomment(from, to, options);
	      } else {
	        cm.lineComment(from, to, options);
	      }
	    }
	  });
	
	  // Rough heuristic to try and detect lines that are part of multi-line string
	  function probablyInsideString(cm, pos, line) {
	    return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"`]/.test(line)
	  }
	
	  CodeMirror.defineExtension("lineComment", function(from, to, options) {
	    if (!options) options = noOptions;
	    var self = this, mode = self.getModeAt(from);
	    var firstLine = self.getLine(from.line);
	    if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
	
	    var commentString = options.lineComment || mode.lineComment;
	    if (!commentString) {
	      if (options.blockCommentStart || mode.blockCommentStart) {
	        options.fullLines = true;
	        self.blockComment(from, to, options);
	      }
	      return;
	    }
	
	    var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
	    var pad = options.padding == null ? " " : options.padding;
	    var blankLines = options.commentBlankLines || from.line == to.line;
	
	    self.operation(function() {
	      if (options.indent) {
	        var baseString = null;
	        for (var i = from.line; i < end; ++i) {
	          var line = self.getLine(i);
	          var whitespace = line.slice(0, firstNonWS(line));
	          if (baseString == null || baseString.length > whitespace.length) {
	            baseString = whitespace;
	          }
	        }
	        for (var i = from.line; i < end; ++i) {
	          var line = self.getLine(i), cut = baseString.length;
	          if (!blankLines && !nonWS.test(line)) continue;
	          if (line.slice(0, cut) != baseString) cut = firstNonWS(line);
	          self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut));
	        }
	      } else {
	        for (var i = from.line; i < end; ++i) {
	          if (blankLines || nonWS.test(self.getLine(i)))
	            self.replaceRange(commentString + pad, Pos(i, 0));
	        }
	      }
	    });
	  });
	
	  CodeMirror.defineExtension("blockComment", function(from, to, options) {
	    if (!options) options = noOptions;
	    var self = this, mode = self.getModeAt(from);
	    var startString = options.blockCommentStart || mode.blockCommentStart;
	    var endString = options.blockCommentEnd || mode.blockCommentEnd;
	    if (!startString || !endString) {
	      if ((options.lineComment || mode.lineComment) && options.fullLines != false)
	        self.lineComment(from, to, options);
	      return;
	    }
	    if (/\bcomment\b/.test(self.getTokenTypeAt(Pos(from.line, 0)))) return
	
	    var end = Math.min(to.line, self.lastLine());
	    if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end;
	
	    var pad = options.padding == null ? " " : options.padding;
	    if (from.line > end) return;
	
	    self.operation(function() {
	      if (options.fullLines != false) {
	        var lastLineHasText = nonWS.test(self.getLine(end));
	        self.replaceRange(pad + endString, Pos(end));
	        self.replaceRange(startString + pad, Pos(from.line, 0));
	        var lead = options.blockCommentLead || mode.blockCommentLead;
	        if (lead != null) for (var i = from.line + 1; i <= end; ++i)
	          if (i != end || lastLineHasText)
	            self.replaceRange(lead + pad, Pos(i, 0));
	      } else {
	        self.replaceRange(endString, to);
	        self.replaceRange(startString, from);
	      }
	    });
	  });
	
	  CodeMirror.defineExtension("uncomment", function(from, to, options) {
	    if (!options) options = noOptions;
	    var self = this, mode = self.getModeAt(from);
	    var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
	
	    // Try finding line comments
	    var lineString = options.lineComment || mode.lineComment, lines = [];
	    var pad = options.padding == null ? " " : options.padding, didSomething;
	    lineComment: {
	      if (!lineString) break lineComment;
	      for (var i = start; i <= end; ++i) {
	        var line = self.getLine(i);
	        var found = line.indexOf(lineString);
	        if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1;
	        if (found == -1 && nonWS.test(line)) break lineComment;
	        if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment;
	        lines.push(line);
	      }
	      self.operation(function() {
	        for (var i = start; i <= end; ++i) {
	          var line = lines[i - start];
	          var pos = line.indexOf(lineString), endPos = pos + lineString.length;
	          if (pos < 0) continue;
	          if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length;
	          didSomething = true;
	          self.replaceRange("", Pos(i, pos), Pos(i, endPos));
	        }
	      });
	      if (didSomething) return true;
	    }
	
	    // Try block comments
	    var startString = options.blockCommentStart || mode.blockCommentStart;
	    var endString = options.blockCommentEnd || mode.blockCommentEnd;
	    if (!startString || !endString) return false;
	    var lead = options.blockCommentLead || mode.blockCommentLead;
	    var startLine = self.getLine(start), open = startLine.indexOf(startString)
	    if (open == -1) return false
	    var endLine = end == start ? startLine : self.getLine(end)
	    var close = endLine.indexOf(endString, end == start ? open + startString.length : 0);
	    if (close == -1 && start != end) {
	      endLine = self.getLine(--end);
	      close = endLine.indexOf(endString);
	    }
	    if (close == -1 ||
	        !/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) ||
	        !/comment/.test(self.getTokenTypeAt(Pos(end, close + 1))))
	      return false;
	
	    // Avoid killing block comments completely outside the selection.
	    // Positions of the last startString before the start of the selection, and the first endString after it.
	    var lastStart = startLine.lastIndexOf(startString, from.ch);
	    var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
	    if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
	    // Positions of the first endString after the end of the selection, and the last startString before it.
	    firstEnd = endLine.indexOf(endString, to.ch);
	    var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
	    lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
	    if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
	
	    self.operation(function() {
	      self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
	                        Pos(end, close + endString.length));
	      var openEnd = open + startString.length;
	      if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length;
	      self.replaceRange("", Pos(start, open), Pos(start, openEnd));
	      if (lead) for (var i = start + 1; i <= end; ++i) {
	        var line = self.getLine(i), found = line.indexOf(lead);
	        if (found == -1 || nonWS.test(line.slice(0, found))) continue;
	        var foundEnd = found + lead.length;
	        if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length;
	        self.replaceRange("", Pos(i, found), Pos(i, foundEnd));
	      }
	    });
	    return true;
	  });
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/addon/comment/comment.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/keymap/vim.js **/
jupyter.define('codemirror@5.23.0/keymap/vim.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	/**
	 * Supported keybindings:
	 *   Too many to list. Refer to defaultKeyMap below.
	 *
	 * Supported Ex commands:
	 *   Refer to defaultExCommandMap below.
	 *
	 * Registers: unnamed, -, a-z, A-Z, 0-9
	 *   (Does not respect the special case for number registers when delete
	 *    operator is made with these commands: %, (, ),  , /, ?, n, N, {, } )
	 *   TODO: Implement the remaining registers.
	 *
	 * Marks: a-z, A-Z, and 0-9
	 *   TODO: Implement the remaining special marks. They have more complex
	 *       behavior.
	 *
	 * Events:
	 *  'vim-mode-change' - raised on the editor anytime the current mode changes,
	 *                      Event object: {mode: "visual", subMode: "linewise"}
	 *
	 * Code structure:
	 *  1. Default keymap
	 *  2. Variable declarations and short basic helpers
	 *  3. Instance (External API) implementation
	 *  4. Internal state tracking objects (input state, counter) implementation
	 *     and instantiation
	 *  5. Key handler (the main command dispatcher) implementation
	 *  6. Motion, operator, and action implementations
	 *  7. Helper functions for the key handler, motions, operators, and actions
	 *  8. Set up Vim to work as a keymap for CodeMirror.
	 *  9. Ex command implementations.
	 */
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'), __jupyter_require__('codemirror@5.23.0/addon/search/searchcursor.js'), __jupyter_require__('codemirror@5.23.0/addon/dialog/dialog.js'), __jupyter_require__('codemirror@5.23.0/addon/edit/matchbrackets.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/dialog/dialog", "../addon/edit/matchbrackets"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  'use strict';
	
	  var defaultKeymap = [
	    // Key to key mapping. This goes first to make it possible to override
	    // existing mappings.
	    { keys: '<Left>', type: 'keyToKey', toKeys: 'h' },
	    { keys: '<Right>', type: 'keyToKey', toKeys: 'l' },
	    { keys: '<Up>', type: 'keyToKey', toKeys: 'k' },
	    { keys: '<Down>', type: 'keyToKey', toKeys: 'j' },
	    { keys: '<Space>', type: 'keyToKey', toKeys: 'l' },
	    { keys: '<BS>', type: 'keyToKey', toKeys: 'h', context: 'normal'},
	    { keys: '<C-Space>', type: 'keyToKey', toKeys: 'W' },
	    { keys: '<C-BS>', type: 'keyToKey', toKeys: 'B', context: 'normal' },
	    { keys: '<S-Space>', type: 'keyToKey', toKeys: 'w' },
	    { keys: '<S-BS>', type: 'keyToKey', toKeys: 'b', context: 'normal' },
	    { keys: '<C-n>', type: 'keyToKey', toKeys: 'j' },
	    { keys: '<C-p>', type: 'keyToKey', toKeys: 'k' },
	    { keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>' },
	    { keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>' },
	    { keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
	    { keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
	    { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' },
	    { keys: 's', type: 'keyToKey', toKeys: 'c', context: 'visual'},
	    { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' },
	    { keys: 'S', type: 'keyToKey', toKeys: 'VdO', context: 'visual' },
	    { keys: '<Home>', type: 'keyToKey', toKeys: '0' },
	    { keys: '<End>', type: 'keyToKey', toKeys: '$' },
	    { keys: '<PageUp>', type: 'keyToKey', toKeys: '<C-b>' },
	    { keys: '<PageDown>', type: 'keyToKey', toKeys: '<C-f>' },
	    { keys: '<CR>', type: 'keyToKey', toKeys: 'j^', context: 'normal' },
	    { keys: '<Ins>', type: 'action', action: 'toggleOverwrite', context: 'insert' },
	    // Motions
	    { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }},
	    { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }},
	    { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }},
	    { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }},
	    { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }},
	    { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }},
	    { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }},
	    { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }},
	    { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }},
	    { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }},
	    { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }},
	    { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }},
	    { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }},
	    { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }},
	    { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }},
	    { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }},
	    { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }},
	    { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }},
	    { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }},
	    { keys: '<C-f>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }},
	    { keys: '<C-b>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }},
	    { keys: '<C-d>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }},
	    { keys: '<C-u>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }},
	    { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }},
	    { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }},
	    { keys: '0', type: 'motion', motion: 'moveToStartOfLine' },
	    { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' },
	    { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }},
	    { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }},
	    { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }},
	    { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }},
	    { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }},
	    { keys: 'f<character>', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }},
	    { keys: 'F<character>', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }},
	    { keys: 't<character>', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }},
	    { keys: 'T<character>', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }},
	    { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }},
	    { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }},
	    { keys: '\'<character>', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}},
	    { keys: '`<character>', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}},
	    { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } },
	    { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } },
	    { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } },
	    { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } },
	    // the next two aren't motions but must come before more general motion declarations
	    { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}},
	    { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}},
	    { keys: ']<character>', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}},
	    { keys: '[<character>', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}},
	    { keys: '|', type: 'motion', motion: 'moveToColumn'},
	    { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'},
	    { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'},
	    // Operators
	    { keys: 'd', type: 'operator', operator: 'delete' },
	    { keys: 'y', type: 'operator', operator: 'yank' },
	    { keys: 'c', type: 'operator', operator: 'change' },
	    { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }},
	    { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }},
	    { keys: 'g~', type: 'operator', operator: 'changeCase' },
	    { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true },
	    { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true },
	    { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }},
	    { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }},
	    // Operator-Motion dual commands
	    { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }},
	    { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }},
	    { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
	    { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'},
	    { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
	    { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'},
	    { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
	    { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'},
	    { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'},
	    { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'},
	    { keys: '<C-w>', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' },
	    // Actions
	    { keys: '<C-i>', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }},
	    { keys: '<C-o>', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }},
	    { keys: '<C-e>', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }},
	    { keys: '<C-y>', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }},
	    { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' },
	    { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' },
	    { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' },
	    { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' },
	    { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' },
	    { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' },
	    { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' },
	    { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' },
	    { keys: 'v', type: 'action', action: 'toggleVisualMode' },
	    { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }},
	    { keys: '<C-v>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }},
	    { keys: '<C-q>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }},
	    { keys: 'gv', type: 'action', action: 'reselectLastSelection' },
	    { keys: 'J', type: 'action', action: 'joinLines', isEdit: true },
	    { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }},
	    { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }},
	    { keys: 'r<character>', type: 'action', action: 'replace', isEdit: true },
	    { keys: '@<character>', type: 'action', action: 'replayMacro' },
	    { keys: 'q<character>', type: 'action', action: 'enterMacroRecordMode' },
	    // Handle Replace-mode as a special case of insert mode.
	    { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }},
	    { keys: 'u', type: 'action', action: 'undo', context: 'normal' },
	    { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true },
	    { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true },
	    { keys: '<C-r>', type: 'action', action: 'redo' },
	    { keys: 'm<character>', type: 'action', action: 'setMark' },
	    { keys: '"<character>', type: 'action', action: 'setRegister' },
	    { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }},
	    { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' },
	    { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }},
	    { keys: 'z<CR>', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' },
	    { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }},
	    { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' },
	    { keys: '.', type: 'action', action: 'repeatLastEdit' },
	    { keys: '<C-a>', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}},
	    { keys: '<C-x>', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}},
	    { keys: '<C-t>', type: 'action', action: 'indent', actionArgs: { indentRight: true }, context: 'insert' },
	    { keys: '<C-d>', type: 'action', action: 'indent', actionArgs: { indentRight: false }, context: 'insert' },
	    // Text object motions
	    { keys: 'a<character>', type: 'motion', motion: 'textObjectManipulation' },
	    { keys: 'i<character>', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }},
	    // Search
	    { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }},
	    { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }},
	    { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }},
	    { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }},
	    { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }},
	    { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }},
	    // Ex command
	    { keys: ':', type: 'ex' }
	  ];
	
	  /**
	   * Ex commands
	   * Care must be taken when adding to the default Ex command map. For any
	   * pair of commands that have a shared prefix, at least one of their
	   * shortNames must not match the prefix of the other command.
	   */
	  var defaultExCommandMap = [
	    { name: 'colorscheme', shortName: 'colo' },
	    { name: 'map' },
	    { name: 'imap', shortName: 'im' },
	    { name: 'nmap', shortName: 'nm' },
	    { name: 'vmap', shortName: 'vm' },
	    { name: 'unmap' },
	    { name: 'write', shortName: 'w' },
	    { name: 'undo', shortName: 'u' },
	    { name: 'redo', shortName: 'red' },
	    { name: 'set', shortName: 'se' },
	    { name: 'set', shortName: 'se' },
	    { name: 'setlocal', shortName: 'setl' },
	    { name: 'setglobal', shortName: 'setg' },
	    { name: 'sort', shortName: 'sor' },
	    { name: 'substitute', shortName: 's', possiblyAsync: true },
	    { name: 'nohlsearch', shortName: 'noh' },
	    { name: 'yank', shortName: 'y' },
	    { name: 'delmarks', shortName: 'delm' },
	    { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },
	    { name: 'global', shortName: 'g' }
	  ];
	
	  var Pos = CodeMirror.Pos;
	
	  var Vim = function() {
	    function enterVimMode(cm) {
	      cm.setOption('disableInput', true);
	      cm.setOption('showCursorWhenSelecting', false);
	      CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
	      cm.on('cursorActivity', onCursorActivity);
	      maybeInitVimState(cm);
	      CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm));
	    }
	
	    function leaveVimMode(cm) {
	      cm.setOption('disableInput', false);
	      cm.off('cursorActivity', onCursorActivity);
	      CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm));
	      cm.state.vim = null;
	    }
	
	    function detachVimMap(cm, next) {
	      if (this == CodeMirror.keyMap.vim)
	        CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor");
	
	      if (!next || next.attach != attachVimMap)
	        leaveVimMode(cm, false);
	    }
	    function attachVimMap(cm, prev) {
	      if (this == CodeMirror.keyMap.vim)
	        CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor");
	
	      if (!prev || prev.attach != attachVimMap)
	        enterVimMode(cm);
	    }
	
	    // Deprecated, simply setting the keymap works again.
	    CodeMirror.defineOption('vimMode', false, function(cm, val, prev) {
	      if (val && cm.getOption("keyMap") != "vim")
	        cm.setOption("keyMap", "vim");
	      else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap")))
	        cm.setOption("keyMap", "default");
	    });
	
	    function cmKey(key, cm) {
	      if (!cm) { return undefined; }
	      if (this[key]) { return this[key]; }
	      var vimKey = cmKeyToVimKey(key);
	      if (!vimKey) {
	        return false;
	      }
	      var cmd = CodeMirror.Vim.findKey(cm, vimKey);
	      if (typeof cmd == 'function') {
	        CodeMirror.signal(cm, 'vim-keypress', vimKey);
	      }
	      return cmd;
	    }
	
	    var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'};
	    var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del',Insert:'Ins'};
	    function cmKeyToVimKey(key) {
	      if (key.charAt(0) == '\'') {
	        // Keypress character binding of format "'a'"
	        return key.charAt(1);
	      }
	      var pieces = key.split(/-(?!$)/);
	      var lastPiece = pieces[pieces.length - 1];
	      if (pieces.length == 1 && pieces[0].length == 1) {
	        // No-modifier bindings use literal character bindings above. Skip.
	        return false;
	      } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) {
	        // Ignore Shift+char bindings as they should be handled by literal character.
	        return false;
	      }
	      var hasCharacter = false;
	      for (var i = 0; i < pieces.length; i++) {
	        var piece = pieces[i];
	        if (piece in modifiers) { pieces[i] = modifiers[piece]; }
	        else { hasCharacter = true; }
	        if (piece in specialKeys) { pieces[i] = specialKeys[piece]; }
	      }
	      if (!hasCharacter) {
	        // Vim does not support modifier only keys.
	        return false;
	      }
	      // TODO: Current bindings expect the character to be lower case, but
	      // it looks like vim key notation uses upper case.
	      if (isUpperCase(lastPiece)) {
	        pieces[pieces.length - 1] = lastPiece.toLowerCase();
	      }
	      return '<' + pieces.join('-') + '>';
	    }
	
	    function getOnPasteFn(cm) {
	      var vim = cm.state.vim;
	      if (!vim.onPasteFn) {
	        vim.onPasteFn = function() {
	          if (!vim.insertMode) {
	            cm.setCursor(offsetCursor(cm.getCursor(), 0, 1));
	            actions.enterInsertMode(cm, {}, vim);
	          }
	        };
	      }
	      return vim.onPasteFn;
	    }
	
	    var numberRegex = /[\d]/;
	    var wordCharTest = [CodeMirror.isWordChar, function(ch) {
	      return ch && !CodeMirror.isWordChar(ch) && !/\s/.test(ch);
	    }], bigWordCharTest = [function(ch) {
	      return /\S/.test(ch);
	    }];
	    function makeKeyRange(start, size) {
	      var keys = [];
	      for (var i = start; i < start + size; i++) {
	        keys.push(String.fromCharCode(i));
	      }
	      return keys;
	    }
	    var upperCaseAlphabet = makeKeyRange(65, 26);
	    var lowerCaseAlphabet = makeKeyRange(97, 26);
	    var numbers = makeKeyRange(48, 10);
	    var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']);
	    var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']);
	
	    function isLine(cm, line) {
	      return line >= cm.firstLine() && line <= cm.lastLine();
	    }
	    function isLowerCase(k) {
	      return (/^[a-z]$/).test(k);
	    }
	    function isMatchableSymbol(k) {
	      return '()[]{}'.indexOf(k) != -1;
	    }
	    function isNumber(k) {
	      return numberRegex.test(k);
	    }
	    function isUpperCase(k) {
	      return (/^[A-Z]$/).test(k);
	    }
	    function isWhiteSpaceString(k) {
	      return (/^\s*$/).test(k);
	    }
	    function inArray(val, arr) {
	      for (var i = 0; i < arr.length; i++) {
	        if (arr[i] == val) {
	          return true;
	        }
	      }
	      return false;
	    }
	
	    var options = {};
	    function defineOption(name, defaultValue, type, aliases, callback) {
	      if (defaultValue === undefined && !callback) {
	        throw Error('defaultValue is required unless callback is provided');
	      }
	      if (!type) { type = 'string'; }
	      options[name] = {
	        type: type,
	        defaultValue: defaultValue,
	        callback: callback
	      };
	      if (aliases) {
	        for (var i = 0; i < aliases.length; i++) {
	          options[aliases[i]] = options[name];
	        }
	      }
	      if (defaultValue) {
	        setOption(name, defaultValue);
	      }
	    }
	
	    function setOption(name, value, cm, cfg) {
	      var option = options[name];
	      cfg = cfg || {};
	      var scope = cfg.scope;
	      if (!option) {
	        throw Error('Unknown option: ' + name);
	      }
	      if (option.type == 'boolean') {
	        if (value && value !== true) {
	          throw Error('Invalid argument: ' + name + '=' + value);
	        } else if (value !== false) {
	          // Boolean options are set to true if value is not defined.
	          value = true;
	        }
	      }
	      if (option.callback) {
	        if (scope !== 'local') {
	          option.callback(value, undefined);
	        }
	        if (scope !== 'global' && cm) {
	          option.callback(value, cm);
	        }
	      } else {
	        if (scope !== 'local') {
	          option.value = option.type == 'boolean' ? !!value : value;
	        }
	        if (scope !== 'global' && cm) {
	          cm.state.vim.options[name] = {value: value};
	        }
	      }
	    }
	
	    function getOption(name, cm, cfg) {
	      var option = options[name];
	      cfg = cfg || {};
	      var scope = cfg.scope;
	      if (!option) {
	        throw Error('Unknown option: ' + name);
	      }
	      if (option.callback) {
	        var local = cm && option.callback(undefined, cm);
	        if (scope !== 'global' && local !== undefined) {
	          return local;
	        }
	        if (scope !== 'local') {
	          return option.callback();
	        }
	        return;
	      } else {
	        var local = (scope !== 'global') && (cm && cm.state.vim.options[name]);
	        return (local || (scope !== 'local') && option || {}).value;
	      }
	    }
	
	    defineOption('filetype', undefined, 'string', ['ft'], function(name, cm) {
	      // Option is local. Do nothing for global.
	      if (cm === undefined) {
	        return;
	      }
	      // The 'filetype' option proxies to the CodeMirror 'mode' option.
	      if (name === undefined) {
	        var mode = cm.getOption('mode');
	        return mode == 'null' ? '' : mode;
	      } else {
	        var mode = name == '' ? 'null' : name;
	        cm.setOption('mode', mode);
	      }
	    });
	
	    var createCircularJumpList = function() {
	      var size = 100;
	      var pointer = -1;
	      var head = 0;
	      var tail = 0;
	      var buffer = new Array(size);
	      function add(cm, oldCur, newCur) {
	        var current = pointer % size;
	        var curMark = buffer[current];
	        function useNextSlot(cursor) {
	          var next = ++pointer % size;
	          var trashMark = buffer[next];
	          if (trashMark) {
	            trashMark.clear();
	          }
	          buffer[next] = cm.setBookmark(cursor);
	        }
	        if (curMark) {
	          var markPos = curMark.find();
	          // avoid recording redundant cursor position
	          if (markPos && !cursorEqual(markPos, oldCur)) {
	            useNextSlot(oldCur);
	          }
	        } else {
	          useNextSlot(oldCur);
	        }
	        useNextSlot(newCur);
	        head = pointer;
	        tail = pointer - size + 1;
	        if (tail < 0) {
	          tail = 0;
	        }
	      }
	      function move(cm, offset) {
	        pointer += offset;
	        if (pointer > head) {
	          pointer = head;
	        } else if (pointer < tail) {
	          pointer = tail;
	        }
	        var mark = buffer[(size + pointer) % size];
	        // skip marks that are temporarily removed from text buffer
	        if (mark && !mark.find()) {
	          var inc = offset > 0 ? 1 : -1;
	          var newCur;
	          var oldCur = cm.getCursor();
	          do {
	            pointer += inc;
	            mark = buffer[(size + pointer) % size];
	            // skip marks that are the same as current position
	            if (mark &&
	                (newCur = mark.find()) &&
	                !cursorEqual(oldCur, newCur)) {
	              break;
	            }
	          } while (pointer < head && pointer > tail);
	        }
	        return mark;
	      }
	      return {
	        cachedCursor: undefined, //used for # and * jumps
	        add: add,
	        move: move
	      };
	    };
	
	    // Returns an object to track the changes associated insert mode.  It
	    // clones the object that is passed in, or creates an empty object one if
	    // none is provided.
	    var createInsertModeChanges = function(c) {
	      if (c) {
	        // Copy construction
	        return {
	          changes: c.changes,
	          expectCursorActivityForChange: c.expectCursorActivityForChange
	        };
	      }
	      return {
	        // Change list
	        changes: [],
	        // Set to true on change, false on cursorActivity.
	        expectCursorActivityForChange: false
	      };
	    };
	
	    function MacroModeState() {
	      this.latestRegister = undefined;
	      this.isPlaying = false;
	      this.isRecording = false;
	      this.replaySearchQueries = [];
	      this.onRecordingDone = undefined;
	      this.lastInsertModeChanges = createInsertModeChanges();
	    }
	    MacroModeState.prototype = {
	      exitMacroRecordMode: function() {
	        var macroModeState = vimGlobalState.macroModeState;
	        if (macroModeState.onRecordingDone) {
	          macroModeState.onRecordingDone(); // close dialog
	        }
	        macroModeState.onRecordingDone = undefined;
	        macroModeState.isRecording = false;
	      },
	      enterMacroRecordMode: function(cm, registerName) {
	        var register =
	            vimGlobalState.registerController.getRegister(registerName);
	        if (register) {
	          register.clear();
	          this.latestRegister = registerName;
	          if (cm.openDialog) {
	            this.onRecordingDone = cm.openDialog(
	                '(recording)['+registerName+']', null, {bottom:true});
	          }
	          this.isRecording = true;
	        }
	      }
	    };
	
	    function maybeInitVimState(cm) {
	      if (!cm.state.vim) {
	        // Store instance state in the CodeMirror object.
	        cm.state.vim = {
	          inputState: new InputState(),
	          // Vim's input state that triggered the last edit, used to repeat
	          // motions and operators with '.'.
	          lastEditInputState: undefined,
	          // Vim's action command before the last edit, used to repeat actions
	          // with '.' and insert mode repeat.
	          lastEditActionCommand: undefined,
	          // When using jk for navigation, if you move from a longer line to a
	          // shorter line, the cursor may clip to the end of the shorter line.
	          // If j is pressed again and cursor goes to the next line, the
	          // cursor should go back to its horizontal position on the longer
	          // line if it can. This is to keep track of the horizontal position.
	          lastHPos: -1,
	          // Doing the same with screen-position for gj/gk
	          lastHSPos: -1,
	          // The last motion command run. Cleared if a non-motion command gets
	          // executed in between.
	          lastMotion: null,
	          marks: {},
	          // Mark for rendering fake cursor for visual mode.
	          fakeCursor: null,
	          insertMode: false,
	          // Repeat count for changes made in insert mode, triggered by key
	          // sequences like 3,i. Only exists when insertMode is true.
	          insertModeRepeat: undefined,
	          visualMode: false,
	          // If we are in visual line mode. No effect if visualMode is false.
	          visualLine: false,
	          visualBlock: false,
	          lastSelection: null,
	          lastPastedText: null,
	          sel: {},
	          // Buffer-local/window-local values of vim options.
	          options: {}
	        };
	      }
	      return cm.state.vim;
	    }
	    var vimGlobalState;
	    function resetVimGlobalState() {
	      vimGlobalState = {
	        // The current search query.
	        searchQuery: null,
	        // Whether we are searching backwards.
	        searchIsReversed: false,
	        // Replace part of the last substituted pattern
	        lastSubstituteReplacePart: undefined,
	        jumpList: createCircularJumpList(),
	        macroModeState: new MacroModeState,
	        // Recording latest f, t, F or T motion command.
	        lastCharacterSearch: {increment:0, forward:true, selectedCharacter:''},
	        registerController: new RegisterController({}),
	        // search history buffer
	        searchHistoryController: new HistoryController({}),
	        // ex Command history buffer
	        exCommandHistoryController : new HistoryController({})
	      };
	      for (var optionName in options) {
	        var option = options[optionName];
	        option.value = option.defaultValue;
	      }
	    }
	
	    var lastInsertModeKeyTimer;
	    var vimApi= {
	      buildKeyMap: function() {
	        // TODO: Convert keymap into dictionary format for fast lookup.
	      },
	      // Testing hook, though it might be useful to expose the register
	      // controller anyways.
	      getRegisterController: function() {
	        return vimGlobalState.registerController;
	      },
	      // Testing hook.
	      resetVimGlobalState_: resetVimGlobalState,
	
	      // Testing hook.
	      getVimGlobalState_: function() {
	        return vimGlobalState;
	      },
	
	      // Testing hook.
	      maybeInitVimState_: maybeInitVimState,
	
	      suppressErrorLogging: false,
	
	      InsertModeKey: InsertModeKey,
	      map: function(lhs, rhs, ctx) {
	        // Add user defined key bindings.
	        exCommandDispatcher.map(lhs, rhs, ctx);
	      },
	      unmap: function(lhs, ctx) {
	        exCommandDispatcher.unmap(lhs, ctx);
	      },
	      // TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace
	      // them, or somehow make them work with the existing CodeMirror setOption/getOption API.
	      setOption: setOption,
	      getOption: getOption,
	      defineOption: defineOption,
	      defineEx: function(name, prefix, func){
	        if (!prefix) {
	          prefix = name;
	        } else if (name.indexOf(prefix) !== 0) {
	          throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered');
	        }
	        exCommands[name]=func;
	        exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'};
	      },
	      handleKey: function (cm, key, origin) {
	        var command = this.findKey(cm, key, origin);
	        if (typeof command === 'function') {
	          return command();
	        }
	      },
	      /**
	       * This is the outermost function called by CodeMirror, after keys have
	       * been mapped to their Vim equivalents.
	       *
	       * Finds a command based on the key (and cached keys if there is a
	       * multi-key sequence). Returns `undefined` if no key is matched, a noop
	       * function if a partial match is found (multi-key), and a function to
	       * execute the bound command if a a key is matched. The function always
	       * returns true.
	       */
	      findKey: function(cm, key, origin) {
	        var vim = maybeInitVimState(cm);
	        function handleMacroRecording() {
	          var macroModeState = vimGlobalState.macroModeState;
	          if (macroModeState.isRecording) {
	            if (key == 'q') {
	              macroModeState.exitMacroRecordMode();
	              clearInputState(cm);
	              return true;
	            }
	            if (origin != 'mapping') {
	              logKey(macroModeState, key);
	            }
	          }
	        }
	        function handleEsc() {
	          if (key == '<Esc>') {
	            // Clear input state and get back to normal mode.
	            clearInputState(cm);
	            if (vim.visualMode) {
	              exitVisualMode(cm);
	            } else if (vim.insertMode) {
	              exitInsertMode(cm);
	            }
	            return true;
	          }
	        }
	        function doKeyToKey(keys) {
	          // TODO: prevent infinite recursion.
	          var match;
	          while (keys) {
	            // Pull off one command key, which is either a single character
	            // or a special sequence wrapped in '<' and '>', e.g. '<Space>'.
	            match = (/<\w+-.+?>|<\w+>|./).exec(keys);
	            key = match[0];
	            keys = keys.substring(match.index + key.length);
	            CodeMirror.Vim.handleKey(cm, key, 'mapping');
	          }
	        }
	
	        function handleKeyInsertMode() {
	          if (handleEsc()) { return true; }
	          var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;
	          var keysAreChars = key.length == 1;
	          var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert');
	          // Need to check all key substrings in insert mode.
	          while (keys.length > 1 && match.type != 'full') {
	            var keys = vim.inputState.keyBuffer = keys.slice(1);
	            var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert');
	            if (thisMatch.type != 'none') { match = thisMatch; }
	          }
	          if (match.type == 'none') { clearInputState(cm); return false; }
	          else if (match.type == 'partial') {
	            if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); }
	            lastInsertModeKeyTimer = window.setTimeout(
	              function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } },
	              getOption('insertModeEscKeysTimeout'));
	            return !keysAreChars;
	          }
	
	          if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); }
	          if (keysAreChars) {
	            var selections = cm.listSelections();
	            for (var i = 0; i < selections.length; i++) {
	              var here = selections[i].head;
	              cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input');
	            }
	            vimGlobalState.macroModeState.lastInsertModeChanges.changes.pop();
	          }
	          clearInputState(cm);
	          return match.command;
	        }
	
	        function handleKeyNonInsertMode() {
	          if (handleMacroRecording() || handleEsc()) { return true; };
	
	          var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;
	          if (/^[1-9]\d*$/.test(keys)) { return true; }
	
	          var keysMatcher = /^(\d*)(.*)$/.exec(keys);
	          if (!keysMatcher) { clearInputState(cm); return false; }
	          var context = vim.visualMode ? 'visual' :
	                                         'normal';
	          var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context);
	          if (match.type == 'none') { clearInputState(cm); return false; }
	          else if (match.type == 'partial') { return true; }
	
	          vim.inputState.keyBuffer = '';
	          var keysMatcher = /^(\d*)(.*)$/.exec(keys);
	          if (keysMatcher[1] && keysMatcher[1] != '0') {
	            vim.inputState.pushRepeatDigit(keysMatcher[1]);
	          }
	          return match.command;
	        }
	
	        var command;
	        if (vim.insertMode) { command = handleKeyInsertMode(); }
	        else { command = handleKeyNonInsertMode(); }
	        if (command === false) {
	          return undefined;
	        } else if (command === true) {
	          // TODO: Look into using CodeMirror's multi-key handling.
	          // Return no-op since we are caching the key. Counts as handled, but
	          // don't want act on it just yet.
	          return function() { return true; };
	        } else {
	          return function() {
	            return cm.operation(function() {
	              cm.curOp.isVimOp = true;
	              try {
	                if (command.type == 'keyToKey') {
	                  doKeyToKey(command.toKeys);
	                } else {
	                  commandDispatcher.processCommand(cm, vim, command);
	                }
	              } catch (e) {
	                // clear VIM state in case it's in a bad state.
	                cm.state.vim = undefined;
	                maybeInitVimState(cm);
	                if (!CodeMirror.Vim.suppressErrorLogging) {
	                  console['log'](e);
	                }
	                throw e;
	              }
	              return true;
	            });
	          };
	        }
	      },
	      handleEx: function(cm, input) {
	        exCommandDispatcher.processCommand(cm, input);
	      },
	
	      defineMotion: defineMotion,
	      defineAction: defineAction,
	      defineOperator: defineOperator,
	      mapCommand: mapCommand,
	      _mapCommand: _mapCommand,
	
	      defineRegister: defineRegister,
	
	      exitVisualMode: exitVisualMode,
	      exitInsertMode: exitInsertMode
	    };
	
	    // Represents the current input state.
	    function InputState() {
	      this.prefixRepeat = [];
	      this.motionRepeat = [];
	
	      this.operator = null;
	      this.operatorArgs = null;
	      this.motion = null;
	      this.motionArgs = null;
	      this.keyBuffer = []; // For matching multi-key commands.
	      this.registerName = null; // Defaults to the unnamed register.
	    }
	    InputState.prototype.pushRepeatDigit = function(n) {
	      if (!this.operator) {
	        this.prefixRepeat = this.prefixRepeat.concat(n);
	      } else {
	        this.motionRepeat = this.motionRepeat.concat(n);
	      }
	    };
	    InputState.prototype.getRepeat = function() {
	      var repeat = 0;
	      if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) {
	        repeat = 1;
	        if (this.prefixRepeat.length > 0) {
	          repeat *= parseInt(this.prefixRepeat.join(''), 10);
	        }
	        if (this.motionRepeat.length > 0) {
	          repeat *= parseInt(this.motionRepeat.join(''), 10);
	        }
	      }
	      return repeat;
	    };
	
	    function clearInputState(cm, reason) {
	      cm.state.vim.inputState = new InputState();
	      CodeMirror.signal(cm, 'vim-command-done', reason);
	    }
	
	    /*
	     * Register stores information about copy and paste registers.  Besides
	     * text, a register must store whether it is linewise (i.e., when it is
	     * pasted, should it insert itself into a new line, or should the text be
	     * inserted at the cursor position.)
	     */
	    function Register(text, linewise, blockwise) {
	      this.clear();
	      this.keyBuffer = [text || ''];
	      this.insertModeChanges = [];
	      this.searchQueries = [];
	      this.linewise = !!linewise;
	      this.blockwise = !!blockwise;
	    }
	    Register.prototype = {
	      setText: function(text, linewise, blockwise) {
	        this.keyBuffer = [text || ''];
	        this.linewise = !!linewise;
	        this.blockwise = !!blockwise;
	      },
	      pushText: function(text, linewise) {
	        // if this register has ever been set to linewise, use linewise.
	        if (linewise) {
	          if (!this.linewise) {
	            this.keyBuffer.push('\n');
	          }
	          this.linewise = true;
	        }
	        this.keyBuffer.push(text);
	      },
	      pushInsertModeChanges: function(changes) {
	        this.insertModeChanges.push(createInsertModeChanges(changes));
	      },
	      pushSearchQuery: function(query) {
	        this.searchQueries.push(query);
	      },
	      clear: function() {
	        this.keyBuffer = [];
	        this.insertModeChanges = [];
	        this.searchQueries = [];
	        this.linewise = false;
	      },
	      toString: function() {
	        return this.keyBuffer.join('');
	      }
	    };
	
	    /**
	     * Defines an external register.
	     *
	     * The name should be a single character that will be used to reference the register.
	     * The register should support setText, pushText, clear, and toString(). See Register
	     * for a reference implementation.
	     */
	    function defineRegister(name, register) {
	      var registers = vimGlobalState.registerController.registers[name];
	      if (!name || name.length != 1) {
	        throw Error('Register name must be 1 character');
	      }
	      if (registers[name]) {
	        throw Error('Register already defined ' + name);
	      }
	      registers[name] = register;
	      validRegisters.push(name);
	    }
	
	    /*
	     * vim registers allow you to keep many independent copy and paste buffers.
	     * See http://usevim.com/2012/04/13/registers/ for an introduction.
	     *
	     * RegisterController keeps the state of all the registers.  An initial
	     * state may be passed in.  The unnamed register '"' will always be
	     * overridden.
	     */
	    function RegisterController(registers) {
	      this.registers = registers;
	      this.unnamedRegister = registers['"'] = new Register();
	      registers['.'] = new Register();
	      registers[':'] = new Register();
	      registers['/'] = new Register();
	    }
	    RegisterController.prototype = {
	      pushText: function(registerName, operator, text, linewise, blockwise) {
	        if (linewise && text.charAt(0) == '\n') {
	          text = text.slice(1) + '\n';
	        }
	        if (linewise && text.charAt(text.length - 1) !== '\n'){
	          text += '\n';
	        }
	        // Lowercase and uppercase registers refer to the same register.
	        // Uppercase just means append.
	        var register = this.isValidRegister(registerName) ?
	            this.getRegister(registerName) : null;
	        // if no register/an invalid register was specified, things go to the
	        // default registers
	        if (!register) {
	          switch (operator) {
	            case 'yank':
	              // The 0 register contains the text from the most recent yank.
	              this.registers['0'] = new Register(text, linewise, blockwise);
	              break;
	            case 'delete':
	            case 'change':
	              if (text.indexOf('\n') == -1) {
	                // Delete less than 1 line. Update the small delete register.
	                this.registers['-'] = new Register(text, linewise);
	              } else {
	                // Shift down the contents of the numbered registers and put the
	                // deleted text into register 1.
	                this.shiftNumericRegisters_();
	                this.registers['1'] = new Register(text, linewise);
	              }
	              break;
	          }
	          // Make sure the unnamed register is set to what just happened
	          this.unnamedRegister.setText(text, linewise, blockwise);
	          return;
	        }
	
	        // If we've gotten to this point, we've actually specified a register
	        var append = isUpperCase(registerName);
	        if (append) {
	          register.pushText(text, linewise);
	        } else {
	          register.setText(text, linewise, blockwise);
	        }
	        // The unnamed register always has the same value as the last used
	        // register.
	        this.unnamedRegister.setText(register.toString(), linewise);
	      },
	      // Gets the register named @name.  If one of @name doesn't already exist,
	      // create it.  If @name is invalid, return the unnamedRegister.
	      getRegister: function(name) {
	        if (!this.isValidRegister(name)) {
	          return this.unnamedRegister;
	        }
	        name = name.toLowerCase();
	        if (!this.registers[name]) {
	          this.registers[name] = new Register();
	        }
	        return this.registers[name];
	      },
	      isValidRegister: function(name) {
	        return name && inArray(name, validRegisters);
	      },
	      shiftNumericRegisters_: function() {
	        for (var i = 9; i >= 2; i--) {
	          this.registers[i] = this.getRegister('' + (i - 1));
	        }
	      }
	    };
	    function HistoryController() {
	        this.historyBuffer = [];
	        this.iterator = 0;
	        this.initialPrefix = null;
	    }
	    HistoryController.prototype = {
	      // the input argument here acts a user entered prefix for a small time
	      // until we start autocompletion in which case it is the autocompleted.
	      nextMatch: function (input, up) {
	        var historyBuffer = this.historyBuffer;
	        var dir = up ? -1 : 1;
	        if (this.initialPrefix === null) this.initialPrefix = input;
	        for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) {
	          var element = historyBuffer[i];
	          for (var j = 0; j <= element.length; j++) {
	            if (this.initialPrefix == element.substring(0, j)) {
	              this.iterator = i;
	              return element;
	            }
	          }
	        }
	        // should return the user input in case we reach the end of buffer.
	        if (i >= historyBuffer.length) {
	          this.iterator = historyBuffer.length;
	          return this.initialPrefix;
	        }
	        // return the last autocompleted query or exCommand as it is.
	        if (i < 0 ) return input;
	      },
	      pushInput: function(input) {
	        var index = this.historyBuffer.indexOf(input);
	        if (index > -1) this.historyBuffer.splice(index, 1);
	        if (input.length) this.historyBuffer.push(input);
	      },
	      reset: function() {
	        this.initialPrefix = null;
	        this.iterator = this.historyBuffer.length;
	      }
	    };
	    var commandDispatcher = {
	      matchCommand: function(keys, keyMap, inputState, context) {
	        var matches = commandMatches(keys, keyMap, context, inputState);
	        if (!matches.full && !matches.partial) {
	          return {type: 'none'};
	        } else if (!matches.full && matches.partial) {
	          return {type: 'partial'};
	        }
	
	        var bestMatch;
	        for (var i = 0; i < matches.full.length; i++) {
	          var match = matches.full[i];
	          if (!bestMatch) {
	            bestMatch = match;
	          }
	        }
	        if (bestMatch.keys.slice(-11) == '<character>') {
	          inputState.selectedCharacter = lastChar(keys);
	        }
	        return {type: 'full', command: bestMatch};
	      },
	      processCommand: function(cm, vim, command) {
	        vim.inputState.repeatOverride = command.repeatOverride;
	        switch (command.type) {
	          case 'motion':
	            this.processMotion(cm, vim, command);
	            break;
	          case 'operator':
	            this.processOperator(cm, vim, command);
	            break;
	          case 'operatorMotion':
	            this.processOperatorMotion(cm, vim, command);
	            break;
	          case 'action':
	            this.processAction(cm, vim, command);
	            break;
	          case 'search':
	            this.processSearch(cm, vim, command);
	            break;
	          case 'ex':
	          case 'keyToEx':
	            this.processEx(cm, vim, command);
	            break;
	          default:
	            break;
	        }
	      },
	      processMotion: function(cm, vim, command) {
	        vim.inputState.motion = command.motion;
	        vim.inputState.motionArgs = copyArgs(command.motionArgs);
	        this.evalInput(cm, vim);
	      },
	      processOperator: function(cm, vim, command) {
	        var inputState = vim.inputState;
	        if (inputState.operator) {
	          if (inputState.operator == command.operator) {
	            // Typing an operator twice like 'dd' makes the operator operate
	            // linewise
	            inputState.motion = 'expandToLine';
	            inputState.motionArgs = { linewise: true };
	            this.evalInput(cm, vim);
	            return;
	          } else {
	            // 2 different operators in a row doesn't make sense.
	            clearInputState(cm);
	          }
	        }
	        inputState.operator = command.operator;
	        inputState.operatorArgs = copyArgs(command.operatorArgs);
	        if (vim.visualMode) {
	          // Operating on a selection in visual mode. We don't need a motion.
	          this.evalInput(cm, vim);
	        }
	      },
	      processOperatorMotion: function(cm, vim, command) {
	        var visualMode = vim.visualMode;
	        var operatorMotionArgs = copyArgs(command.operatorMotionArgs);
	        if (operatorMotionArgs) {
	          // Operator motions may have special behavior in visual mode.
	          if (visualMode && operatorMotionArgs.visualLine) {
	            vim.visualLine = true;
	          }
	        }
	        this.processOperator(cm, vim, command);
	        if (!visualMode) {
	          this.processMotion(cm, vim, command);
	        }
	      },
	      processAction: function(cm, vim, command) {
	        var inputState = vim.inputState;
	        var repeat = inputState.getRepeat();
	        var repeatIsExplicit = !!repeat;
	        var actionArgs = copyArgs(command.actionArgs) || {};
	        if (inputState.selectedCharacter) {
	          actionArgs.selectedCharacter = inputState.selectedCharacter;
	        }
	        // Actions may or may not have motions and operators. Do these first.
	        if (command.operator) {
	          this.processOperator(cm, vim, command);
	        }
	        if (command.motion) {
	          this.processMotion(cm, vim, command);
	        }
	        if (command.motion || command.operator) {
	          this.evalInput(cm, vim);
	        }
	        actionArgs.repeat = repeat || 1;
	        actionArgs.repeatIsExplicit = repeatIsExplicit;
	        actionArgs.registerName = inputState.registerName;
	        clearInputState(cm);
	        vim.lastMotion = null;
	        if (command.isEdit) {
	          this.recordLastEdit(vim, inputState, command);
	        }
	        actions[command.action](cm, actionArgs, vim);
	      },
	      processSearch: function(cm, vim, command) {
	        if (!cm.getSearchCursor) {
	          // Search depends on SearchCursor.
	          return;
	        }
	        var forward = command.searchArgs.forward;
	        var wholeWordOnly = command.searchArgs.wholeWordOnly;
	        getSearchState(cm).setReversed(!forward);
	        var promptPrefix = (forward) ? '/' : '?';
	        var originalQuery = getSearchState(cm).getQuery();
	        var originalScrollPos = cm.getScrollInfo();
	        function handleQuery(query, ignoreCase, smartCase) {
	          vimGlobalState.searchHistoryController.pushInput(query);
	          vimGlobalState.searchHistoryController.reset();
	          try {
	            updateSearchQuery(cm, query, ignoreCase, smartCase);
	          } catch (e) {
	            showConfirm(cm, 'Invalid regex: ' + query);
	            clearInputState(cm);
	            return;
	          }
	          commandDispatcher.processMotion(cm, vim, {
	            type: 'motion',
	            motion: 'findNext',
	            motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist }
	          });
	        }
	        function onPromptClose(query) {
	          cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
	          handleQuery(query, true /** ignoreCase */, true /** smartCase */);
	          var macroModeState = vimGlobalState.macroModeState;
	          if (macroModeState.isRecording) {
	            logSearchQuery(macroModeState, query);
	          }
	        }
	        function onPromptKeyUp(e, query, close) {
	          var keyName = CodeMirror.keyName(e), up;
	          if (keyName == 'Up' || keyName == 'Down') {
	            up = keyName == 'Up' ? true : false;
	            query = vimGlobalState.searchHistoryController.nextMatch(query, up) || '';
	            close(query);
	          } else {
	            if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
	              vimGlobalState.searchHistoryController.reset();
	          }
	          var parsedQuery;
	          try {
	            parsedQuery = updateSearchQuery(cm, query,
	                true /** ignoreCase */, true /** smartCase */);
	          } catch (e) {
	            // Swallow bad regexes for incremental search.
	          }
	          if (parsedQuery) {
	            cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30);
	          } else {
	            clearSearchHighlight(cm);
	            cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
	          }
	        }
	        function onPromptKeyDown(e, query, close) {
	          var keyName = CodeMirror.keyName(e);
	          if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
	              (keyName == 'Backspace' && query == '')) {
	            vimGlobalState.searchHistoryController.pushInput(query);
	            vimGlobalState.searchHistoryController.reset();
	            updateSearchQuery(cm, originalQuery);
	            clearSearchHighlight(cm);
	            cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
	            CodeMirror.e_stop(e);
	            clearInputState(cm);
	            close();
	            cm.focus();
	          } else if (keyName == 'Ctrl-U') {
	            // Ctrl-U clears input.
	            CodeMirror.e_stop(e);
	            close('');
	          }
	        }
	        switch (command.searchArgs.querySrc) {
	          case 'prompt':
	            var macroModeState = vimGlobalState.macroModeState;
	            if (macroModeState.isPlaying) {
	              var query = macroModeState.replaySearchQueries.shift();
	              handleQuery(query, true /** ignoreCase */, false /** smartCase */);
	            } else {
	              showPrompt(cm, {
	                  onClose: onPromptClose,
	                  prefix: promptPrefix,
	                  desc: searchPromptDesc,
	                  onKeyUp: onPromptKeyUp,
	                  onKeyDown: onPromptKeyDown
	              });
	            }
	            break;
	          case 'wordUnderCursor':
	            var word = expandWordUnderCursor(cm, false /** inclusive */,
	                true /** forward */, false /** bigWord */,
	                true /** noSymbol */);
	            var isKeyword = true;
	            if (!word) {
	              word = expandWordUnderCursor(cm, false /** inclusive */,
	                  true /** forward */, false /** bigWord */,
	                  false /** noSymbol */);
	              isKeyword = false;
	            }
	            if (!word) {
	              return;
	            }
	            var query = cm.getLine(word.start.line).substring(word.start.ch,
	                word.end.ch);
	            if (isKeyword && wholeWordOnly) {
	                query = '\\b' + query + '\\b';
	            } else {
	              query = escapeRegex(query);
	            }
	
	            // cachedCursor is used to save the old position of the cursor
	            // when * or # causes vim to seek for the nearest word and shift
	            // the cursor before entering the motion.
	            vimGlobalState.jumpList.cachedCursor = cm.getCursor();
	            cm.setCursor(word.start);
	
	            handleQuery(query, true /** ignoreCase */, false /** smartCase */);
	            break;
	        }
	      },
	      processEx: function(cm, vim, command) {
	        function onPromptClose(input) {
	          // Give the prompt some time to close so that if processCommand shows
	          // an error, the elements don't overlap.
	          vimGlobalState.exCommandHistoryController.pushInput(input);
	          vimGlobalState.exCommandHistoryController.reset();
	          exCommandDispatcher.processCommand(cm, input);
	        }
	        function onPromptKeyDown(e, input, close) {
	          var keyName = CodeMirror.keyName(e), up;
	          if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
	              (keyName == 'Backspace' && input == '')) {
	            vimGlobalState.exCommandHistoryController.pushInput(input);
	            vimGlobalState.exCommandHistoryController.reset();
	            CodeMirror.e_stop(e);
	            clearInputState(cm);
	            close();
	            cm.focus();
	          }
	          if (keyName == 'Up' || keyName == 'Down') {
	            up = keyName == 'Up' ? true : false;
	            input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || '';
	            close(input);
	          } else if (keyName == 'Ctrl-U') {
	            // Ctrl-U clears input.
	            CodeMirror.e_stop(e);
	            close('');
	          } else {
	            if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
	              vimGlobalState.exCommandHistoryController.reset();
	          }
	        }
	        if (command.type == 'keyToEx') {
	          // Handle user defined Ex to Ex mappings
	          exCommandDispatcher.processCommand(cm, command.exArgs.input);
	        } else {
	          if (vim.visualMode) {
	            showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>',
	                onKeyDown: onPromptKeyDown});
	          } else {
	            showPrompt(cm, { onClose: onPromptClose, prefix: ':',
	                onKeyDown: onPromptKeyDown});
	          }
	        }
	      },
	      evalInput: function(cm, vim) {
	        // If the motion command is set, execute both the operator and motion.
	        // Otherwise return.
	        var inputState = vim.inputState;
	        var motion = inputState.motion;
	        var motionArgs = inputState.motionArgs || {};
	        var operator = inputState.operator;
	        var operatorArgs = inputState.operatorArgs || {};
	        var registerName = inputState.registerName;
	        var sel = vim.sel;
	        // TODO: Make sure cm and vim selections are identical outside visual mode.
	        var origHead = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.head): cm.getCursor('head'));
	        var origAnchor = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.anchor) : cm.getCursor('anchor'));
	        var oldHead = copyCursor(origHead);
	        var oldAnchor = copyCursor(origAnchor);
	        var newHead, newAnchor;
	        var repeat;
	        if (operator) {
	          this.recordLastEdit(vim, inputState);
	        }
	        if (inputState.repeatOverride !== undefined) {
	          // If repeatOverride is specified, that takes precedence over the
	          // input state's repeat. Used by Ex mode and can be user defined.
	          repeat = inputState.repeatOverride;
	        } else {
	          repeat = inputState.getRepeat();
	        }
	        if (repeat > 0 && motionArgs.explicitRepeat) {
	          motionArgs.repeatIsExplicit = true;
	        } else if (motionArgs.noRepeat ||
	            (!motionArgs.explicitRepeat && repeat === 0)) {
	          repeat = 1;
	          motionArgs.repeatIsExplicit = false;
	        }
	        if (inputState.selectedCharacter) {
	          // If there is a character input, stick it in all of the arg arrays.
	          motionArgs.selectedCharacter = operatorArgs.selectedCharacter =
	              inputState.selectedCharacter;
	        }
	        motionArgs.repeat = repeat;
	        clearInputState(cm);
	        if (motion) {
	          var motionResult = motions[motion](cm, origHead, motionArgs, vim);
	          vim.lastMotion = motions[motion];
	          if (!motionResult) {
	            return;
	          }
	          if (motionArgs.toJumplist) {
	            var jumpList = vimGlobalState.jumpList;
	            // if the current motion is # or *, use cachedCursor
	            var cachedCursor = jumpList.cachedCursor;
	            if (cachedCursor) {
	              recordJumpPosition(cm, cachedCursor, motionResult);
	              delete jumpList.cachedCursor;
	            } else {
	              recordJumpPosition(cm, origHead, motionResult);
	            }
	          }
	          if (motionResult instanceof Array) {
	            newAnchor = motionResult[0];
	            newHead = motionResult[1];
	          } else {
	            newHead = motionResult;
	          }
	          // TODO: Handle null returns from motion commands better.
	          if (!newHead) {
	            newHead = copyCursor(origHead);
	          }
	          if (vim.visualMode) {
	            if (!(vim.visualBlock && newHead.ch === Infinity)) {
	              newHead = clipCursorToContent(cm, newHead, vim.visualBlock);
	            }
	            if (newAnchor) {
	              newAnchor = clipCursorToContent(cm, newAnchor, true);
	            }
	            newAnchor = newAnchor || oldAnchor;
	            sel.anchor = newAnchor;
	            sel.head = newHead;
	            updateCmSelection(cm);
	            updateMark(cm, vim, '<',
	                cursorIsBefore(newAnchor, newHead) ? newAnchor
	                    : newHead);
	            updateMark(cm, vim, '>',
	                cursorIsBefore(newAnchor, newHead) ? newHead
	                    : newAnchor);
	          } else if (!operator) {
	            newHead = clipCursorToContent(cm, newHead);
	            cm.setCursor(newHead.line, newHead.ch);
	          }
	        }
	        if (operator) {
	          if (operatorArgs.lastSel) {
	            // Replaying a visual mode operation
	            newAnchor = oldAnchor;
	            var lastSel = operatorArgs.lastSel;
	            var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line);
	            var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch);
	            if (lastSel.visualLine) {
	              // Linewise Visual mode: The same number of lines.
	              newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch);
	            } else if (lastSel.visualBlock) {
	              // Blockwise Visual mode: The same number of lines and columns.
	              newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset);
	            } else if (lastSel.head.line == lastSel.anchor.line) {
	              // Normal Visual mode within one line: The same number of characters.
	              newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset);
	            } else {
	              // Normal Visual mode with several lines: The same number of lines, in the
	              // last line the same number of characters as in the last line the last time.
	              newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch);
	            }
	            vim.visualMode = true;
	            vim.visualLine = lastSel.visualLine;
	            vim.visualBlock = lastSel.visualBlock;
	            sel = vim.sel = {
	              anchor: newAnchor,
	              head: newHead
	            };
	            updateCmSelection(cm);
	          } else if (vim.visualMode) {
	            operatorArgs.lastSel = {
	              anchor: copyCursor(sel.anchor),
	              head: copyCursor(sel.head),
	              visualBlock: vim.visualBlock,
	              visualLine: vim.visualLine
	            };
	          }
	          var curStart, curEnd, linewise, mode;
	          var cmSel;
	          if (vim.visualMode) {
	            // Init visual op
	            curStart = cursorMin(sel.head, sel.anchor);
	            curEnd = cursorMax(sel.head, sel.anchor);
	            linewise = vim.visualLine || operatorArgs.linewise;
	            mode = vim.visualBlock ? 'block' :
	                   linewise ? 'line' :
	                   'char';
	            cmSel = makeCmSelection(cm, {
	              anchor: curStart,
	              head: curEnd
	            }, mode);
	            if (linewise) {
	              var ranges = cmSel.ranges;
	              if (mode == 'block') {
	                // Linewise operators in visual block mode extend to end of line
	                for (var i = 0; i < ranges.length; i++) {
	                  ranges[i].head.ch = lineLength(cm, ranges[i].head.line);
	                }
	              } else if (mode == 'line') {
	                ranges[0].head = Pos(ranges[0].head.line + 1, 0);
	              }
	            }
	          } else {
	            // Init motion op
	            curStart = copyCursor(newAnchor || oldAnchor);
	            curEnd = copyCursor(newHead || oldHead);
	            if (cursorIsBefore(curEnd, curStart)) {
	              var tmp = curStart;
	              curStart = curEnd;
	              curEnd = tmp;
	            }
	            linewise = motionArgs.linewise || operatorArgs.linewise;
	            if (linewise) {
	              // Expand selection to entire line.
	              expandSelectionToLine(cm, curStart, curEnd);
	            } else if (motionArgs.forward) {
	              // Clip to trailing newlines only if the motion goes forward.
	              clipToLine(cm, curStart, curEnd);
	            }
	            mode = 'char';
	            var exclusive = !motionArgs.inclusive || linewise;
	            cmSel = makeCmSelection(cm, {
	              anchor: curStart,
	              head: curEnd
	            }, mode, exclusive);
	          }
	          cm.setSelections(cmSel.ranges, cmSel.primary);
	          vim.lastMotion = null;
	          operatorArgs.repeat = repeat; // For indent in visual mode.
	          operatorArgs.registerName = registerName;
	          // Keep track of linewise as it affects how paste and change behave.
	          operatorArgs.linewise = linewise;
	          var operatorMoveTo = operators[operator](
	            cm, operatorArgs, cmSel.ranges, oldAnchor, newHead);
	          if (vim.visualMode) {
	            exitVisualMode(cm, operatorMoveTo != null);
	          }
	          if (operatorMoveTo) {
	            cm.setCursor(operatorMoveTo);
	          }
	        }
	      },
	      recordLastEdit: function(vim, inputState, actionCommand) {
	        var macroModeState = vimGlobalState.macroModeState;
	        if (macroModeState.isPlaying) { return; }
	        vim.lastEditInputState = inputState;
	        vim.lastEditActionCommand = actionCommand;
	        macroModeState.lastInsertModeChanges.changes = [];
	        macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false;
	      }
	    };
	
	    /**
	     * typedef {Object{line:number,ch:number}} Cursor An object containing the
	     *     position of the cursor.
	     */
	    // All of the functions below return Cursor objects.
	    var motions = {
	      moveToTopLine: function(cm, _head, motionArgs) {
	        var line = getUserVisibleLines(cm).top + motionArgs.repeat -1;
	        return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
	      },
	      moveToMiddleLine: function(cm) {
	        var range = getUserVisibleLines(cm);
	        var line = Math.floor((range.top + range.bottom) * 0.5);
	        return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
	      },
	      moveToBottomLine: function(cm, _head, motionArgs) {
	        var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1;
	        return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
	      },
	      expandToLine: function(_cm, head, motionArgs) {
	        // Expands forward to end of line, and then to next line if repeat is
	        // >1. Does not handle backward motion!
	        var cur = head;
	        return Pos(cur.line + motionArgs.repeat - 1, Infinity);
	      },
	      findNext: function(cm, _head, motionArgs) {
	        var state = getSearchState(cm);
	        var query = state.getQuery();
	        if (!query) {
	          return;
	        }
	        var prev = !motionArgs.forward;
	        // If search is initiated with ? instead of /, negate direction.
	        prev = (state.isReversed()) ? !prev : prev;
	        highlightSearchMatches(cm, query);
	        return findNext(cm, prev/** prev */, query, motionArgs.repeat);
	      },
	      goToMark: function(cm, _head, motionArgs, vim) {
	        var mark = vim.marks[motionArgs.selectedCharacter];
	        if (mark) {
	          var pos = mark.find();
	          return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos;
	        }
	        return null;
	      },
	      moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) {
	        if (vim.visualBlock && motionArgs.sameLine) {
	          var sel = vim.sel;
	          return [
	            clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)),
	            clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch))
	          ];
	        } else {
	          return ([vim.sel.head, vim.sel.anchor]);
	        }
	      },
	      jumpToMark: function(cm, head, motionArgs, vim) {
	        var best = head;
	        for (var i = 0; i < motionArgs.repeat; i++) {
	          var cursor = best;
	          for (var key in vim.marks) {
	            if (!isLowerCase(key)) {
	              continue;
	            }
	            var mark = vim.marks[key].find();
	            var isWrongDirection = (motionArgs.forward) ?
	              cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark);
	
	            if (isWrongDirection) {
	              continue;
	            }
	            if (motionArgs.linewise && (mark.line == cursor.line)) {
	              continue;
	            }
	
	            var equal = cursorEqual(cursor, best);
	            var between = (motionArgs.forward) ?
	              cursorIsBetween(cursor, mark, best) :
	              cursorIsBetween(best, mark, cursor);
	
	            if (equal || between) {
	              best = mark;
	            }
	          }
	        }
	
	        if (motionArgs.linewise) {
	          // Vim places the cursor on the first non-whitespace character of
	          // the line if there is one, else it places the cursor at the end
	          // of the line, regardless of whether a mark was found.
	          best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line)));
	        }
	        return best;
	      },
	      moveByCharacters: function(_cm, head, motionArgs) {
	        var cur = head;
	        var repeat = motionArgs.repeat;
	        var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat;
	        return Pos(cur.line, ch);
	      },
	      moveByLines: function(cm, head, motionArgs, vim) {
	        var cur = head;
	        var endCh = cur.ch;
	        // Depending what our last motion was, we may want to do different
	        // things. If our last motion was moving vertically, we want to
	        // preserve the HPos from our last horizontal move.  If our last motion
	        // was going to the end of a line, moving vertically we should go to
	        // the end of the line, etc.
	        switch (vim.lastMotion) {
	          case this.moveByLines:
	          case this.moveByDisplayLines:
	          case this.moveByScroll:
	          case this.moveToColumn:
	          case this.moveToEol:
	            endCh = vim.lastHPos;
	            break;
	          default:
	            vim.lastHPos = endCh;
	        }
	        var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0);
	        var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat;
	        var first = cm.firstLine();
	        var last = cm.lastLine();
	        // Vim go to line begin or line end when cursor at first/last line and
	        // move to previous/next line is triggered.
	        if (line < first && cur.line == first){
	          return this.moveToStartOfLine(cm, head, motionArgs, vim);
	        }else if (line > last && cur.line == last){
	            return this.moveToEol(cm, head, motionArgs, vim);
	        }
	        if (motionArgs.toFirstChar){
	          endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line));
	          vim.lastHPos = endCh;
	        }
	        vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left;
	        return Pos(line, endCh);
	      },
	      moveByDisplayLines: function(cm, head, motionArgs, vim) {
	        var cur = head;
	        switch (vim.lastMotion) {
	          case this.moveByDisplayLines:
	          case this.moveByScroll:
	          case this.moveByLines:
	          case this.moveToColumn:
	          case this.moveToEol:
	            break;
	          default:
	            vim.lastHSPos = cm.charCoords(cur,'div').left;
	        }
	        var repeat = motionArgs.repeat;
	        var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos);
	        if (res.hitSide) {
	          if (motionArgs.forward) {
	            var lastCharCoords = cm.charCoords(res, 'div');
	            var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos };
	            var res = cm.coordsChar(goalCoords, 'div');
	          } else {
	            var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div');
	            resCoords.left = vim.lastHSPos;
	            res = cm.coordsChar(resCoords, 'div');
	          }
	        }
	        vim.lastHPos = res.ch;
	        return res;
	      },
	      moveByPage: function(cm, head, motionArgs) {
	        // CodeMirror only exposes functions that move the cursor page down, so
	        // doing this bad hack to move the cursor and move it back. evalInput
	        // will move the cursor to where it should be in the end.
	        var curStart = head;
	        var repeat = motionArgs.repeat;
	        return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page');
	      },
	      moveByParagraph: function(cm, head, motionArgs) {
	        var dir = motionArgs.forward ? 1 : -1;
	        return findParagraph(cm, head, motionArgs.repeat, dir);
	      },
	      moveByScroll: function(cm, head, motionArgs, vim) {
	        var scrollbox = cm.getScrollInfo();
	        var curEnd = null;
	        var repeat = motionArgs.repeat;
	        if (!repeat) {
	          repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight());
	        }
	        var orig = cm.charCoords(head, 'local');
	        motionArgs.repeat = repeat;
	        var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim);
	        if (!curEnd) {
	          return null;
	        }
	        var dest = cm.charCoords(curEnd, 'local');
	        cm.scrollTo(null, scrollbox.top + dest.top - orig.top);
	        return curEnd;
	      },
	      moveByWords: function(cm, head, motionArgs) {
	        return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward,
	            !!motionArgs.wordEnd, !!motionArgs.bigWord);
	      },
	      moveTillCharacter: function(cm, _head, motionArgs) {
	        var repeat = motionArgs.repeat;
	        var curEnd = moveToCharacter(cm, repeat, motionArgs.forward,
	            motionArgs.selectedCharacter);
	        var increment = motionArgs.forward ? -1 : 1;
	        recordLastCharacterSearch(increment, motionArgs);
	        if (!curEnd) return null;
	        curEnd.ch += increment;
	        return curEnd;
	      },
	      moveToCharacter: function(cm, head, motionArgs) {
	        var repeat = motionArgs.repeat;
	        recordLastCharacterSearch(0, motionArgs);
	        return moveToCharacter(cm, repeat, motionArgs.forward,
	            motionArgs.selectedCharacter) || head;
	      },
	      moveToSymbol: function(cm, head, motionArgs) {
	        var repeat = motionArgs.repeat;
	        return findSymbol(cm, repeat, motionArgs.forward,
	            motionArgs.selectedCharacter) || head;
	      },
	      moveToColumn: function(cm, head, motionArgs, vim) {
	        var repeat = motionArgs.repeat;
	        // repeat is equivalent to which column we want to move to!
	        vim.lastHPos = repeat - 1;
	        vim.lastHSPos = cm.charCoords(head,'div').left;
	        return moveToColumn(cm, repeat);
	      },
	      moveToEol: function(cm, head, motionArgs, vim) {
	        var cur = head;
	        vim.lastHPos = Infinity;
	        var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity);
	        var end=cm.clipPos(retval);
	        end.ch--;
	        vim.lastHSPos = cm.charCoords(end,'div').left;
	        return retval;
	      },
	      moveToFirstNonWhiteSpaceCharacter: function(cm, head) {
	        // Go to the start of the line where the text begins, or the end for
	        // whitespace-only lines
	        var cursor = head;
	        return Pos(cursor.line,
	                   findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line)));
	      },
	      moveToMatchedSymbol: function(cm, head) {
	        var cursor = head;
	        var line = cursor.line;
	        var ch = cursor.ch;
	        var lineText = cm.getLine(line);
	        var symbol;
	        do {
	          symbol = lineText.charAt(ch++);
	          if (symbol && isMatchableSymbol(symbol)) {
	            var style = cm.getTokenTypeAt(Pos(line, ch));
	            if (style !== "string" && style !== "comment") {
	              break;
	            }
	          }
	        } while (symbol);
	        if (symbol) {
	          var matched = cm.findMatchingBracket(Pos(line, ch));
	          return matched.to;
	        } else {
	          return cursor;
	        }
	      },
	      moveToStartOfLine: function(_cm, head) {
	        return Pos(head.line, 0);
	      },
	      moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) {
	        var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine();
	        if (motionArgs.repeatIsExplicit) {
	          lineNum = motionArgs.repeat - cm.getOption('firstLineNumber');
	        }
	        return Pos(lineNum,
	                   findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum)));
	      },
	      textObjectManipulation: function(cm, head, motionArgs, vim) {
	        // TODO: lots of possible exceptions that can be thrown here. Try da(
	        //     outside of a () block.
	
	        // TODO: adding <> >< to this map doesn't work, presumably because
	        // they're operators
	        var mirroredPairs = {'(': ')', ')': '(',
	                             '{': '}', '}': '{',
	                             '[': ']', ']': '['};
	        var selfPaired = {'\'': true, '"': true};
	
	        var character = motionArgs.selectedCharacter;
	        // 'b' refers to  '()' block.
	        // 'B' refers to  '{}' block.
	        if (character == 'b') {
	          character = '(';
	        } else if (character == 'B') {
	          character = '{';
	        }
	
	        // Inclusive is the difference between a and i
	        // TODO: Instead of using the additional text object map to perform text
	        //     object operations, merge the map into the defaultKeyMap and use
	        //     motionArgs to define behavior. Define separate entries for 'aw',
	        //     'iw', 'a[', 'i[', etc.
	        var inclusive = !motionArgs.textObjectInner;
	
	        var tmp;
	        if (mirroredPairs[character]) {
	          tmp = selectCompanionObject(cm, head, character, inclusive);
	        } else if (selfPaired[character]) {
	          tmp = findBeginningAndEnd(cm, head, character, inclusive);
	        } else if (character === 'W') {
	          tmp = expandWordUnderCursor(cm, inclusive, true /** forward */,
	                                                     true /** bigWord */);
	        } else if (character === 'w') {
	          tmp = expandWordUnderCursor(cm, inclusive, true /** forward */,
	                                                     false /** bigWord */);
	        } else if (character === 'p') {
	          tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive);
	          motionArgs.linewise = true;
	          if (vim.visualMode) {
	            if (!vim.visualLine) { vim.visualLine = true; }
	          } else {
	            var operatorArgs = vim.inputState.operatorArgs;
	            if (operatorArgs) { operatorArgs.linewise = true; }
	            tmp.end.line--;
	          }
	        } else {
	          // No text object defined for this, don't move.
	          return null;
	        }
	
	        if (!cm.state.vim.visualMode) {
	          return [tmp.start, tmp.end];
	        } else {
	          return expandSelection(cm, tmp.start, tmp.end);
	        }
	      },
	
	      repeatLastCharacterSearch: function(cm, head, motionArgs) {
	        var lastSearch = vimGlobalState.lastCharacterSearch;
	        var repeat = motionArgs.repeat;
	        var forward = motionArgs.forward === lastSearch.forward;
	        var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1);
	        cm.moveH(-increment, 'char');
	        motionArgs.inclusive = forward ? true : false;
	        var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter);
	        if (!curEnd) {
	          cm.moveH(increment, 'char');
	          return head;
	        }
	        curEnd.ch += increment;
	        return curEnd;
	      }
	    };
	
	    function defineMotion(name, fn) {
	      motions[name] = fn;
	    }
	
	    function fillArray(val, times) {
	      var arr = [];
	      for (var i = 0; i < times; i++) {
	        arr.push(val);
	      }
	      return arr;
	    }
	    /**
	     * An operator acts on a text selection. It receives the list of selections
	     * as input. The corresponding CodeMirror selection is guaranteed to
	    * match the input selection.
	     */
	    var operators = {
	      change: function(cm, args, ranges) {
	        var finalHead, text;
	        var vim = cm.state.vim;
	        vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock;
	        if (!vim.visualMode) {
	          var anchor = ranges[0].anchor,
	              head = ranges[0].head;
	          text = cm.getRange(anchor, head);
	          var lastState = vim.lastEditInputState || {};
	          if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) {
	            // Exclude trailing whitespace if the range is not all whitespace.
	            var match = (/\s+$/).exec(text);
	            if (match && lastState.motionArgs && lastState.motionArgs.forward) {
	              head = offsetCursor(head, 0, - match[0].length);
	              text = text.slice(0, - match[0].length);
	            }
	          }
	          var prevLineEnd = new Pos(anchor.line - 1, Number.MAX_VALUE);
	          var wasLastLine = cm.firstLine() == cm.lastLine();
	          if (head.line > cm.lastLine() && args.linewise && !wasLastLine) {
	            cm.replaceRange('', prevLineEnd, head);
	          } else {
	            cm.replaceRange('', anchor, head);
	          }
	          if (args.linewise) {
	            // Push the next line back down, if there is a next line.
	            if (!wasLastLine) {
	              cm.setCursor(prevLineEnd);
	              CodeMirror.commands.newlineAndIndent(cm);
	            }
	            // make sure cursor ends up at the end of the line.
	            anchor.ch = Number.MAX_VALUE;
	          }
	          finalHead = anchor;
	        } else {
	          text = cm.getSelection();
	          var replacement = fillArray('', ranges.length);
	          cm.replaceSelections(replacement);
	          finalHead = cursorMin(ranges[0].head, ranges[0].anchor);
	        }
	        vimGlobalState.registerController.pushText(
	            args.registerName, 'change', text,
	            args.linewise, ranges.length > 1);
	        actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim);
	      },
	      // delete is a javascript keyword.
	      'delete': function(cm, args, ranges) {
	        var finalHead, text;
	        var vim = cm.state.vim;
	        if (!vim.visualBlock) {
	          var anchor = ranges[0].anchor,
	              head = ranges[0].head;
	          if (args.linewise &&
	              head.line != cm.firstLine() &&
	              anchor.line == cm.lastLine() &&
	              anchor.line == head.line - 1) {
	            // Special case for dd on last line (and first line).
	            if (anchor.line == cm.firstLine()) {
	              anchor.ch = 0;
	            } else {
	              anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1));
	            }
	          }
	          text = cm.getRange(anchor, head);
	          cm.replaceRange('', anchor, head);
	          finalHead = anchor;
	          if (args.linewise) {
	            finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor);
	          }
	        } else {
	          text = cm.getSelection();
	          var replacement = fillArray('', ranges.length);
	          cm.replaceSelections(replacement);
	          finalHead = ranges[0].anchor;
	        }
	        vimGlobalState.registerController.pushText(
	            args.registerName, 'delete', text,
	            args.linewise, vim.visualBlock);
	        return clipCursorToContent(cm, finalHead);
	      },
	      indent: function(cm, args, ranges) {
	        var vim = cm.state.vim;
	        var startLine = ranges[0].anchor.line;
	        var endLine = vim.visualBlock ?
	          ranges[ranges.length - 1].anchor.line :
	          ranges[0].head.line;
	        // In visual mode, n> shifts the selection right n times, instead of
	        // shifting n lines right once.
	        var repeat = (vim.visualMode) ? args.repeat : 1;
	        if (args.linewise) {
	          // The only way to delete a newline is to delete until the start of
	          // the next line, so in linewise mode evalInput will include the next
	          // line. We don't want this in indent, so we go back a line.
	          endLine--;
	        }
	        for (var i = startLine; i <= endLine; i++) {
	          for (var j = 0; j < repeat; j++) {
	            cm.indentLine(i, args.indentRight);
	          }
	        }
	        return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor);
	      },
	      changeCase: function(cm, args, ranges, oldAnchor, newHead) {
	        var selections = cm.getSelections();
	        var swapped = [];
	        var toLower = args.toLower;
	        for (var j = 0; j < selections.length; j++) {
	          var toSwap = selections[j];
	          var text = '';
	          if (toLower === true) {
	            text = toSwap.toLowerCase();
	          } else if (toLower === false) {
	            text = toSwap.toUpperCase();
	          } else {
	            for (var i = 0; i < toSwap.length; i++) {
	              var character = toSwap.charAt(i);
	              text += isUpperCase(character) ? character.toLowerCase() :
	                  character.toUpperCase();
	            }
	          }
	          swapped.push(text);
	        }
	        cm.replaceSelections(swapped);
	        if (args.shouldMoveCursor){
	          return newHead;
	        } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) {
	          return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor);
	        } else if (args.linewise){
	          return oldAnchor;
	        } else {
	          return cursorMin(ranges[0].anchor, ranges[0].head);
	        }
	      },
	      yank: function(cm, args, ranges, oldAnchor) {
	        var vim = cm.state.vim;
	        var text = cm.getSelection();
	        var endPos = vim.visualMode
	          ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor)
	          : oldAnchor;
	        vimGlobalState.registerController.pushText(
	            args.registerName, 'yank',
	            text, args.linewise, vim.visualBlock);
	        return endPos;
	      }
	    };
	
	    function defineOperator(name, fn) {
	      operators[name] = fn;
	    }
	
	    var actions = {
	      jumpListWalk: function(cm, actionArgs, vim) {
	        if (vim.visualMode) {
	          return;
	        }
	        var repeat = actionArgs.repeat;
	        var forward = actionArgs.forward;
	        var jumpList = vimGlobalState.jumpList;
	
	        var mark = jumpList.move(cm, forward ? repeat : -repeat);
	        var markPos = mark ? mark.find() : undefined;
	        markPos = markPos ? markPos : cm.getCursor();
	        cm.setCursor(markPos);
	      },
	      scroll: function(cm, actionArgs, vim) {
	        if (vim.visualMode) {
	          return;
	        }
	        var repeat = actionArgs.repeat || 1;
	        var lineHeight = cm.defaultTextHeight();
	        var top = cm.getScrollInfo().top;
	        var delta = lineHeight * repeat;
	        var newPos = actionArgs.forward ? top + delta : top - delta;
	        var cursor = copyCursor(cm.getCursor());
	        var cursorCoords = cm.charCoords(cursor, 'local');
	        if (actionArgs.forward) {
	          if (newPos > cursorCoords.top) {
	             cursor.line += (newPos - cursorCoords.top) / lineHeight;
	             cursor.line = Math.ceil(cursor.line);
	             cm.setCursor(cursor);
	             cursorCoords = cm.charCoords(cursor, 'local');
	             cm.scrollTo(null, cursorCoords.top);
	          } else {
	             // Cursor stays within bounds.  Just reposition the scroll window.
	             cm.scrollTo(null, newPos);
	          }
	        } else {
	          var newBottom = newPos + cm.getScrollInfo().clientHeight;
	          if (newBottom < cursorCoords.bottom) {
	             cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight;
	             cursor.line = Math.floor(cursor.line);
	             cm.setCursor(cursor);
	             cursorCoords = cm.charCoords(cursor, 'local');
	             cm.scrollTo(
	                 null, cursorCoords.bottom - cm.getScrollInfo().clientHeight);
	          } else {
	             // Cursor stays within bounds.  Just reposition the scroll window.
	             cm.scrollTo(null, newPos);
	          }
	        }
	      },
	      scrollToCursor: function(cm, actionArgs) {
	        var lineNum = cm.getCursor().line;
	        var charCoords = cm.charCoords(Pos(lineNum, 0), 'local');
	        var height = cm.getScrollInfo().clientHeight;
	        var y = charCoords.top;
	        var lineHeight = charCoords.bottom - y;
	        switch (actionArgs.position) {
	          case 'center': y = y - (height / 2) + lineHeight;
	            break;
	          case 'bottom': y = y - height + lineHeight;
	            break;
	        }
	        cm.scrollTo(null, y);
	      },
	      replayMacro: function(cm, actionArgs, vim) {
	        var registerName = actionArgs.selectedCharacter;
	        var repeat = actionArgs.repeat;
	        var macroModeState = vimGlobalState.macroModeState;
	        if (registerName == '@') {
	          registerName = macroModeState.latestRegister;
	        }
	        while(repeat--){
	          executeMacroRegister(cm, vim, macroModeState, registerName);
	        }
	      },
	      enterMacroRecordMode: function(cm, actionArgs) {
	        var macroModeState = vimGlobalState.macroModeState;
	        var registerName = actionArgs.selectedCharacter;
	        macroModeState.enterMacroRecordMode(cm, registerName);
	      },
	      toggleOverwrite: function(cm) {
	        if (!cm.state.overwrite) {
	          cm.toggleOverwrite(true);
	          cm.setOption('keyMap', 'vim-replace');
	          CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"});
	        } else {
	          cm.toggleOverwrite(false);
	          cm.setOption('keyMap', 'vim-insert');
	          CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"});
	        }
	      },
	      enterInsertMode: function(cm, actionArgs, vim) {
	        if (cm.getOption('readOnly')) { return; }
	        vim.insertMode = true;
	        vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1;
	        var insertAt = (actionArgs) ? actionArgs.insertAt : null;
	        var sel = vim.sel;
	        var head = actionArgs.head || cm.getCursor('head');
	        var height = cm.listSelections().length;
	        if (insertAt == 'eol') {
	          head = Pos(head.line, lineLength(cm, head.line));
	        } else if (insertAt == 'charAfter') {
	          head = offsetCursor(head, 0, 1);
	        } else if (insertAt == 'firstNonBlank') {
	          head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head);
	        } else if (insertAt == 'startOfSelectedArea') {
	          if (!vim.visualBlock) {
	            if (sel.head.line < sel.anchor.line) {
	              head = sel.head;
	            } else {
	              head = Pos(sel.anchor.line, 0);
	            }
	          } else {
	            head = Pos(
	                Math.min(sel.head.line, sel.anchor.line),
	                Math.min(sel.head.ch, sel.anchor.ch));
	            height = Math.abs(sel.head.line - sel.anchor.line) + 1;
	          }
	        } else if (insertAt == 'endOfSelectedArea') {
	          if (!vim.visualBlock) {
	            if (sel.head.line >= sel.anchor.line) {
	              head = offsetCursor(sel.head, 0, 1);
	            } else {
	              head = Pos(sel.anchor.line, 0);
	            }
	          } else {
	            head = Pos(
	                Math.min(sel.head.line, sel.anchor.line),
	                Math.max(sel.head.ch + 1, sel.anchor.ch));
	            height = Math.abs(sel.head.line - sel.anchor.line) + 1;
	          }
	        } else if (insertAt == 'inplace') {
	          if (vim.visualMode){
	            return;
	          }
	        }
	        cm.setOption('disableInput', false);
	        if (actionArgs && actionArgs.replace) {
	          // Handle Replace-mode as a special case of insert mode.
	          cm.toggleOverwrite(true);
	          cm.setOption('keyMap', 'vim-replace');
	          CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"});
	        } else {
	          cm.toggleOverwrite(false);
	          cm.setOption('keyMap', 'vim-insert');
	          CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"});
	        }
	        if (!vimGlobalState.macroModeState.isPlaying) {
	          // Only record if not replaying.
	          cm.on('change', onChange);
	          CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown);
	        }
	        if (vim.visualMode) {
	          exitVisualMode(cm);
	        }
	        selectForInsert(cm, head, height);
	      },
	      toggleVisualMode: function(cm, actionArgs, vim) {
	        var repeat = actionArgs.repeat;
	        var anchor = cm.getCursor();
	        var head;
	        // TODO: The repeat should actually select number of characters/lines
	        //     equal to the repeat times the size of the previous visual
	        //     operation.
	        if (!vim.visualMode) {
	          // Entering visual mode
	          vim.visualMode = true;
	          vim.visualLine = !!actionArgs.linewise;
	          vim.visualBlock = !!actionArgs.blockwise;
	          head = clipCursorToContent(
	              cm, Pos(anchor.line, anchor.ch + repeat - 1),
	              true /** includeLineBreak */);
	          vim.sel = {
	            anchor: anchor,
	            head: head
	          };
	          CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""});
	          updateCmSelection(cm);
	          updateMark(cm, vim, '<', cursorMin(anchor, head));
	          updateMark(cm, vim, '>', cursorMax(anchor, head));
	        } else if (vim.visualLine ^ actionArgs.linewise ||
	            vim.visualBlock ^ actionArgs.blockwise) {
	          // Toggling between modes
	          vim.visualLine = !!actionArgs.linewise;
	          vim.visualBlock = !!actionArgs.blockwise;
	          CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""});
	          updateCmSelection(cm);
	        } else {
	          exitVisualMode(cm);
	        }
	      },
	      reselectLastSelection: function(cm, _actionArgs, vim) {
	        var lastSelection = vim.lastSelection;
	        if (vim.visualMode) {
	          updateLastSelection(cm, vim);
	        }
	        if (lastSelection) {
	          var anchor = lastSelection.anchorMark.find();
	          var head = lastSelection.headMark.find();
	          if (!anchor || !head) {
	            // If the marks have been destroyed due to edits, do nothing.
	            return;
	          }
	          vim.sel = {
	            anchor: anchor,
	            head: head
	          };
	          vim.visualMode = true;
	          vim.visualLine = lastSelection.visualLine;
	          vim.visualBlock = lastSelection.visualBlock;
	          updateCmSelection(cm);
	          updateMark(cm, vim, '<', cursorMin(anchor, head));
	          updateMark(cm, vim, '>', cursorMax(anchor, head));
	          CodeMirror.signal(cm, 'vim-mode-change', {
	            mode: 'visual',
	            subMode: vim.visualLine ? 'linewise' :
	                     vim.visualBlock ? 'blockwise' : ''});
	        }
	      },
	      joinLines: function(cm, actionArgs, vim) {
	        var curStart, curEnd;
	        if (vim.visualMode) {
	          curStart = cm.getCursor('anchor');
	          curEnd = cm.getCursor('head');
	          if (cursorIsBefore(curEnd, curStart)) {
	            var tmp = curEnd;
	            curEnd = curStart;
	            curStart = tmp;
	          }
	          curEnd.ch = lineLength(cm, curEnd.line) - 1;
	        } else {
	          // Repeat is the number of lines to join. Minimum 2 lines.
	          var repeat = Math.max(actionArgs.repeat, 2);
	          curStart = cm.getCursor();
	          curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1,
	                                               Infinity));
	        }
	        var finalCh = 0;
	        for (var i = curStart.line; i < curEnd.line; i++) {
	          finalCh = lineLength(cm, curStart.line);
	          var tmp = Pos(curStart.line + 1,
	                        lineLength(cm, curStart.line + 1));
	          var text = cm.getRange(curStart, tmp);
	          text = text.replace(/\n\s*/g, ' ');
	          cm.replaceRange(text, curStart, tmp);
	        }
	        var curFinalPos = Pos(curStart.line, finalCh);
	        if (vim.visualMode) {
	          exitVisualMode(cm, false);
	        }
	        cm.setCursor(curFinalPos);
	      },
	      newLineAndEnterInsertMode: function(cm, actionArgs, vim) {
	        vim.insertMode = true;
	        var insertAt = copyCursor(cm.getCursor());
	        if (insertAt.line === cm.firstLine() && !actionArgs.after) {
	          // Special case for inserting newline before start of document.
	          cm.replaceRange('\n', Pos(cm.firstLine(), 0));
	          cm.setCursor(cm.firstLine(), 0);
	        } else {
	          insertAt.line = (actionArgs.after) ? insertAt.line :
	              insertAt.line - 1;
	          insertAt.ch = lineLength(cm, insertAt.line);
	          cm.setCursor(insertAt);
	          var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment ||
	              CodeMirror.commands.newlineAndIndent;
	          newlineFn(cm);
	        }
	        this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim);
	      },
	      paste: function(cm, actionArgs, vim) {
	        var cur = copyCursor(cm.getCursor());
	        var register = vimGlobalState.registerController.getRegister(
	            actionArgs.registerName);
	        var text = register.toString();
	        if (!text) {
	          return;
	        }
	        if (actionArgs.matchIndent) {
	          var tabSize = cm.getOption("tabSize");
	          // length that considers tabs and tabSize
	          var whitespaceLength = function(str) {
	            var tabs = (str.split("\t").length - 1);
	            var spaces = (str.split(" ").length - 1);
	            return tabs * tabSize + spaces * 1;
	          };
	          var currentLine = cm.getLine(cm.getCursor().line);
	          var indent = whitespaceLength(currentLine.match(/^\s*/)[0]);
	          // chomp last newline b/c don't want it to match /^\s*/gm
	          var chompedText = text.replace(/\n$/, '');
	          var wasChomped = text !== chompedText;
	          var firstIndent = whitespaceLength(text.match(/^\s*/)[0]);
	          var text = chompedText.replace(/^\s*/gm, function(wspace) {
	            var newIndent = indent + (whitespaceLength(wspace) - firstIndent);
	            if (newIndent < 0) {
	              return "";
	            }
	            else if (cm.getOption("indentWithTabs")) {
	              var quotient = Math.floor(newIndent / tabSize);
	              return Array(quotient + 1).join('\t');
	            }
	            else {
	              return Array(newIndent + 1).join(' ');
	            }
	          });
	          text += wasChomped ? "\n" : "";
	        }
	        if (actionArgs.repeat > 1) {
	          var text = Array(actionArgs.repeat + 1).join(text);
	        }
	        var linewise = register.linewise;
	        var blockwise = register.blockwise;
	        if (linewise) {
	          if(vim.visualMode) {
	            text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n';
	          } else if (actionArgs.after) {
	            // Move the newline at the end to the start instead, and paste just
	            // before the newline character of the line we are on right now.
	            text = '\n' + text.slice(0, text.length - 1);
	            cur.ch = lineLength(cm, cur.line);
	          } else {
	            cur.ch = 0;
	          }
	        } else {
	          if (blockwise) {
	            text = text.split('\n');
	            for (var i = 0; i < text.length; i++) {
	              text[i] = (text[i] == '') ? ' ' : text[i];
	            }
	          }
	          cur.ch += actionArgs.after ? 1 : 0;
	        }
	        var curPosFinal;
	        var idx;
	        if (vim.visualMode) {
	          //  save the pasted text for reselection if the need arises
	          vim.lastPastedText = text;
	          var lastSelectionCurEnd;
	          var selectedArea = getSelectedAreaRange(cm, vim);
	          var selectionStart = selectedArea[0];
	          var selectionEnd = selectedArea[1];
	          var selectedText = cm.getSelection();
	          var selections = cm.listSelections();
	          var emptyStrings = new Array(selections.length).join('1').split('1');
	          // save the curEnd marker before it get cleared due to cm.replaceRange.
	          if (vim.lastSelection) {
	            lastSelectionCurEnd = vim.lastSelection.headMark.find();
	          }
	          // push the previously selected text to unnamed register
	          vimGlobalState.registerController.unnamedRegister.setText(selectedText);
	          if (blockwise) {
	            // first delete the selected text
	            cm.replaceSelections(emptyStrings);
	            // Set new selections as per the block length of the yanked text
	            selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch);
	            cm.setCursor(selectionStart);
	            selectBlock(cm, selectionEnd);
	            cm.replaceSelections(text);
	            curPosFinal = selectionStart;
	          } else if (vim.visualBlock) {
	            cm.replaceSelections(emptyStrings);
	            cm.setCursor(selectionStart);
	            cm.replaceRange(text, selectionStart, selectionStart);
	            curPosFinal = selectionStart;
	          } else {
	            cm.replaceRange(text, selectionStart, selectionEnd);
	            curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1);
	          }
	          // restore the the curEnd marker
	          if(lastSelectionCurEnd) {
	            vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd);
	          }
	          if (linewise) {
	            curPosFinal.ch=0;
	          }
	        } else {
	          if (blockwise) {
	            cm.setCursor(cur);
	            for (var i = 0; i < text.length; i++) {
	              var line = cur.line+i;
	              if (line > cm.lastLine()) {
	                cm.replaceRange('\n',  Pos(line, 0));
	              }
	              var lastCh = lineLength(cm, line);
	              if (lastCh < cur.ch) {
	                extendLineToColumn(cm, line, cur.ch);
	              }
	            }
	            cm.setCursor(cur);
	            selectBlock(cm, Pos(cur.line + text.length-1, cur.ch));
	            cm.replaceSelections(text);
	            curPosFinal = cur;
	          } else {
	            cm.replaceRange(text, cur);
	            // Now fine tune the cursor to where we want it.
	            if (linewise && actionArgs.after) {
	              curPosFinal = Pos(
	              cur.line + 1,
	              findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1)));
	            } else if (linewise && !actionArgs.after) {
	              curPosFinal = Pos(
	                cur.line,
	                findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line)));
	            } else if (!linewise && actionArgs.after) {
	              idx = cm.indexFromPos(cur);
	              curPosFinal = cm.posFromIndex(idx + text.length - 1);
	            } else {
	              idx = cm.indexFromPos(cur);
	              curPosFinal = cm.posFromIndex(idx + text.length);
	            }
	          }
	        }
	        if (vim.visualMode) {
	          exitVisualMode(cm, false);
	        }
	        cm.setCursor(curPosFinal);
	      },
	      undo: function(cm, actionArgs) {
	        cm.operation(function() {
	          repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)();
	          cm.setCursor(cm.getCursor('anchor'));
	        });
	      },
	      redo: function(cm, actionArgs) {
	        repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)();
	      },
	      setRegister: function(_cm, actionArgs, vim) {
	        vim.inputState.registerName = actionArgs.selectedCharacter;
	      },
	      setMark: function(cm, actionArgs, vim) {
	        var markName = actionArgs.selectedCharacter;
	        updateMark(cm, vim, markName, cm.getCursor());
	      },
	      replace: function(cm, actionArgs, vim) {
	        var replaceWith = actionArgs.selectedCharacter;
	        var curStart = cm.getCursor();
	        var replaceTo;
	        var curEnd;
	        var selections = cm.listSelections();
	        if (vim.visualMode) {
	          curStart = cm.getCursor('start');
	          curEnd = cm.getCursor('end');
	        } else {
	          var line = cm.getLine(curStart.line);
	          replaceTo = curStart.ch + actionArgs.repeat;
	          if (replaceTo > line.length) {
	            replaceTo=line.length;
	          }
	          curEnd = Pos(curStart.line, replaceTo);
	        }
	        if (replaceWith=='\n') {
	          if (!vim.visualMode) cm.replaceRange('', curStart, curEnd);
	          // special case, where vim help says to replace by just one line-break
	          (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm);
	        } else {
	          var replaceWithStr = cm.getRange(curStart, curEnd);
	          //replace all characters in range by selected, but keep linebreaks
	          replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith);
	          if (vim.visualBlock) {
	            // Tabs are split in visua block before replacing
	            var spaces = new Array(cm.getOption("tabSize")+1).join(' ');
	            replaceWithStr = cm.getSelection();
	            replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n');
	            cm.replaceSelections(replaceWithStr);
	          } else {
	            cm.replaceRange(replaceWithStr, curStart, curEnd);
	          }
	          if (vim.visualMode) {
	            curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ?
	                         selections[0].anchor : selections[0].head;
	            cm.setCursor(curStart);
	            exitVisualMode(cm, false);
	          } else {
	            cm.setCursor(offsetCursor(curEnd, 0, -1));
	          }
	        }
	      },
	      incrementNumberToken: function(cm, actionArgs) {
	        var cur = cm.getCursor();
	        var lineStr = cm.getLine(cur.line);
	        var re = /-?\d+/g;
	        var match;
	        var start;
	        var end;
	        var numberStr;
	        var token;
	        while ((match = re.exec(lineStr)) !== null) {
	          token = match[0];
	          start = match.index;
	          end = start + token.length;
	          if (cur.ch < end)break;
	        }
	        if (!actionArgs.backtrack && (end <= cur.ch))return;
	        if (token) {
	          var increment = actionArgs.increase ? 1 : -1;
	          var number = parseInt(token) + (increment * actionArgs.repeat);
	          var from = Pos(cur.line, start);
	          var to = Pos(cur.line, end);
	          numberStr = number.toString();
	          cm.replaceRange(numberStr, from, to);
	        } else {
	          return;
	        }
	        cm.setCursor(Pos(cur.line, start + numberStr.length - 1));
	      },
	      repeatLastEdit: function(cm, actionArgs, vim) {
	        var lastEditInputState = vim.lastEditInputState;
	        if (!lastEditInputState) { return; }
	        var repeat = actionArgs.repeat;
	        if (repeat && actionArgs.repeatIsExplicit) {
	          vim.lastEditInputState.repeatOverride = repeat;
	        } else {
	          repeat = vim.lastEditInputState.repeatOverride || repeat;
	        }
	        repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */);
	      },
	      indent: function(cm, actionArgs) {
	        cm.indentLine(cm.getCursor().line, actionArgs.indentRight);
	      },
	      exitInsertMode: exitInsertMode
	    };
	
	    function defineAction(name, fn) {
	      actions[name] = fn;
	    }
	
	    /*
	     * Below are miscellaneous utility functions used by vim.js
	     */
	
	    /**
	     * Clips cursor to ensure that line is within the buffer's range
	     * If includeLineBreak is true, then allow cur.ch == lineLength.
	     */
	    function clipCursorToContent(cm, cur, includeLineBreak) {
	      var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() );
	      var maxCh = lineLength(cm, line) - 1;
	      maxCh = (includeLineBreak) ? maxCh + 1 : maxCh;
	      var ch = Math.min(Math.max(0, cur.ch), maxCh);
	      return Pos(line, ch);
	    }
	    function copyArgs(args) {
	      var ret = {};
	      for (var prop in args) {
	        if (args.hasOwnProperty(prop)) {
	          ret[prop] = args[prop];
	        }
	      }
	      return ret;
	    }
	    function offsetCursor(cur, offsetLine, offsetCh) {
	      if (typeof offsetLine === 'object') {
	        offsetCh = offsetLine.ch;
	        offsetLine = offsetLine.line;
	      }
	      return Pos(cur.line + offsetLine, cur.ch + offsetCh);
	    }
	    function getOffset(anchor, head) {
	      return {
	        line: head.line - anchor.line,
	        ch: head.line - anchor.line
	      };
	    }
	    function commandMatches(keys, keyMap, context, inputState) {
	      // Partial matches are not applied. They inform the key handler
	      // that the current key sequence is a subsequence of a valid key
	      // sequence, so that the key buffer is not cleared.
	      var match, partial = [], full = [];
	      for (var i = 0; i < keyMap.length; i++) {
	        var command = keyMap[i];
	        if (context == 'insert' && command.context != 'insert' ||
	            command.context && command.context != context ||
	            inputState.operator && command.type == 'action' ||
	            !(match = commandMatch(keys, command.keys))) { continue; }
	        if (match == 'partial') { partial.push(command); }
	        if (match == 'full') { full.push(command); }
	      }
	      return {
	        partial: partial.length && partial,
	        full: full.length && full
	      };
	    }
	    function commandMatch(pressed, mapped) {
	      if (mapped.slice(-11) == '<character>') {
	        // Last character matches anything.
	        var prefixLen = mapped.length - 11;
	        var pressedPrefix = pressed.slice(0, prefixLen);
	        var mappedPrefix = mapped.slice(0, prefixLen);
	        return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' :
	               mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false;
	      } else {
	        return pressed == mapped ? 'full' :
	               mapped.indexOf(pressed) == 0 ? 'partial' : false;
	      }
	    }
	    function lastChar(keys) {
	      var match = /^.*(<[\w\-]+>)$/.exec(keys);
	      var selectedCharacter = match ? match[1] : keys.slice(-1);
	      if (selectedCharacter.length > 1){
	        switch(selectedCharacter){
	          case '<CR>':
	            selectedCharacter='\n';
	            break;
	          case '<Space>':
	            selectedCharacter=' ';
	            break;
	          default:
	            break;
	        }
	      }
	      return selectedCharacter;
	    }
	    function repeatFn(cm, fn, repeat) {
	      return function() {
	        for (var i = 0; i < repeat; i++) {
	          fn(cm);
	        }
	      };
	    }
	    function copyCursor(cur) {
	      return Pos(cur.line, cur.ch);
	    }
	    function cursorEqual(cur1, cur2) {
	      return cur1.ch == cur2.ch && cur1.line == cur2.line;
	    }
	    function cursorIsBefore(cur1, cur2) {
	      if (cur1.line < cur2.line) {
	        return true;
	      }
	      if (cur1.line == cur2.line && cur1.ch < cur2.ch) {
	        return true;
	      }
	      return false;
	    }
	    function cursorMin(cur1, cur2) {
	      if (arguments.length > 2) {
	        cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1));
	      }
	      return cursorIsBefore(cur1, cur2) ? cur1 : cur2;
	    }
	    function cursorMax(cur1, cur2) {
	      if (arguments.length > 2) {
	        cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1));
	      }
	      return cursorIsBefore(cur1, cur2) ? cur2 : cur1;
	    }
	    function cursorIsBetween(cur1, cur2, cur3) {
	      // returns true if cur2 is between cur1 and cur3.
	      var cur1before2 = cursorIsBefore(cur1, cur2);
	      var cur2before3 = cursorIsBefore(cur2, cur3);
	      return cur1before2 && cur2before3;
	    }
	    function lineLength(cm, lineNum) {
	      return cm.getLine(lineNum).length;
	    }
	    function trim(s) {
	      if (s.trim) {
	        return s.trim();
	      }
	      return s.replace(/^\s+|\s+$/g, '');
	    }
	    function escapeRegex(s) {
	      return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1');
	    }
	    function extendLineToColumn(cm, lineNum, column) {
	      var endCh = lineLength(cm, lineNum);
	      var spaces = new Array(column-endCh+1).join(' ');
	      cm.setCursor(Pos(lineNum, endCh));
	      cm.replaceRange(spaces, cm.getCursor());
	    }
	    // This functions selects a rectangular block
	    // of text with selectionEnd as any of its corner
	    // Height of block:
	    // Difference in selectionEnd.line and first/last selection.line
	    // Width of the block:
	    // Distance between selectionEnd.ch and any(first considered here) selection.ch
	    function selectBlock(cm, selectionEnd) {
	      var selections = [], ranges = cm.listSelections();
	      var head = copyCursor(cm.clipPos(selectionEnd));
	      var isClipped = !cursorEqual(selectionEnd, head);
	      var curHead = cm.getCursor('head');
	      var primIndex = getIndex(ranges, curHead);
	      var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor);
	      var max = ranges.length - 1;
	      var index = max - primIndex > primIndex ? max : 0;
	      var base = ranges[index].anchor;
	
	      var firstLine = Math.min(base.line, head.line);
	      var lastLine = Math.max(base.line, head.line);
	      var baseCh = base.ch, headCh = head.ch;
	
	      var dir = ranges[index].head.ch - baseCh;
	      var newDir = headCh - baseCh;
	      if (dir > 0 && newDir <= 0) {
	        baseCh++;
	        if (!isClipped) { headCh--; }
	      } else if (dir < 0 && newDir >= 0) {
	        baseCh--;
	        if (!wasClipped) { headCh++; }
	      } else if (dir < 0 && newDir == -1) {
	        baseCh--;
	        headCh++;
	      }
	      for (var line = firstLine; line <= lastLine; line++) {
	        var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)};
	        selections.push(range);
	      }
	      primIndex = head.line == lastLine ? selections.length - 1 : 0;
	      cm.setSelections(selections);
	      selectionEnd.ch = headCh;
	      base.ch = baseCh;
	      return base;
	    }
	    function selectForInsert(cm, head, height) {
	      var sel = [];
	      for (var i = 0; i < height; i++) {
	        var lineHead = offsetCursor(head, i, 0);
	        sel.push({anchor: lineHead, head: lineHead});
	      }
	      cm.setSelections(sel, 0);
	    }
	    // getIndex returns the index of the cursor in the selections.
	    function getIndex(ranges, cursor, end) {
	      for (var i = 0; i < ranges.length; i++) {
	        var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor);
	        var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor);
	        if (atAnchor || atHead) {
	          return i;
	        }
	      }
	      return -1;
	    }
	    function getSelectedAreaRange(cm, vim) {
	      var lastSelection = vim.lastSelection;
	      var getCurrentSelectedAreaRange = function() {
	        var selections = cm.listSelections();
	        var start =  selections[0];
	        var end = selections[selections.length-1];
	        var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head;
	        var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor;
	        return [selectionStart, selectionEnd];
	      };
	      var getLastSelectedAreaRange = function() {
	        var selectionStart = cm.getCursor();
	        var selectionEnd = cm.getCursor();
	        var block = lastSelection.visualBlock;
	        if (block) {
	          var width = block.width;
	          var height = block.height;
	          selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width);
	          var selections = [];
	          // selectBlock creates a 'proper' rectangular block.
	          // We do not want that in all cases, so we manually set selections.
	          for (var i = selectionStart.line; i < selectionEnd.line; i++) {
	            var anchor = Pos(i, selectionStart.ch);
	            var head = Pos(i, selectionEnd.ch);
	            var range = {anchor: anchor, head: head};
	            selections.push(range);
	          }
	          cm.setSelections(selections);
	        } else {
	          var start = lastSelection.anchorMark.find();
	          var end = lastSelection.headMark.find();
	          var line = end.line - start.line;
	          var ch = end.ch - start.ch;
	          selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch};
	          if (lastSelection.visualLine) {
	            selectionStart = Pos(selectionStart.line, 0);
	            selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line));
	          }
	          cm.setSelection(selectionStart, selectionEnd);
	        }
	        return [selectionStart, selectionEnd];
	      };
	      if (!vim.visualMode) {
	      // In case of replaying the action.
	        return getLastSelectedAreaRange();
	      } else {
	        return getCurrentSelectedAreaRange();
	      }
	    }
	    // Updates the previous selection with the current selection's values. This
	    // should only be called in visual mode.
	    function updateLastSelection(cm, vim) {
	      var anchor = vim.sel.anchor;
	      var head = vim.sel.head;
	      // To accommodate the effect of lastPastedText in the last selection
	      if (vim.lastPastedText) {
	        head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length);
	        vim.lastPastedText = null;
	      }
	      vim.lastSelection = {'anchorMark': cm.setBookmark(anchor),
	                           'headMark': cm.setBookmark(head),
	                           'anchor': copyCursor(anchor),
	                           'head': copyCursor(head),
	                           'visualMode': vim.visualMode,
	                           'visualLine': vim.visualLine,
	                           'visualBlock': vim.visualBlock};
	    }
	    function expandSelection(cm, start, end) {
	      var sel = cm.state.vim.sel;
	      var head = sel.head;
	      var anchor = sel.anchor;
	      var tmp;
	      if (cursorIsBefore(end, start)) {
	        tmp = end;
	        end = start;
	        start = tmp;
	      }
	      if (cursorIsBefore(head, anchor)) {
	        head = cursorMin(start, head);
	        anchor = cursorMax(anchor, end);
	      } else {
	        anchor = cursorMin(start, anchor);
	        head = cursorMax(head, end);
	        head = offsetCursor(head, 0, -1);
	        if (head.ch == -1 && head.line != cm.firstLine()) {
	          head = Pos(head.line - 1, lineLength(cm, head.line - 1));
	        }
	      }
	      return [anchor, head];
	    }
	    /**
	     * Updates the CodeMirror selection to match the provided vim selection.
	     * If no arguments are given, it uses the current vim selection state.
	     */
	    function updateCmSelection(cm, sel, mode) {
	      var vim = cm.state.vim;
	      sel = sel || vim.sel;
	      var mode = mode ||
	        vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char';
	      var cmSel = makeCmSelection(cm, sel, mode);
	      cm.setSelections(cmSel.ranges, cmSel.primary);
	      updateFakeCursor(cm);
	    }
	    function makeCmSelection(cm, sel, mode, exclusive) {
	      var head = copyCursor(sel.head);
	      var anchor = copyCursor(sel.anchor);
	      if (mode == 'char') {
	        var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;
	        var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;
	        head = offsetCursor(sel.head, 0, headOffset);
	        anchor = offsetCursor(sel.anchor, 0, anchorOffset);
	        return {
	          ranges: [{anchor: anchor, head: head}],
	          primary: 0
	        };
	      } else if (mode == 'line') {
	        if (!cursorIsBefore(sel.head, sel.anchor)) {
	          anchor.ch = 0;
	
	          var lastLine = cm.lastLine();
	          if (head.line > lastLine) {
	            head.line = lastLine;
	          }
	          head.ch = lineLength(cm, head.line);
	        } else {
	          head.ch = 0;
	          anchor.ch = lineLength(cm, anchor.line);
	        }
	        return {
	          ranges: [{anchor: anchor, head: head}],
	          primary: 0
	        };
	      } else if (mode == 'block') {
	        var top = Math.min(anchor.line, head.line),
	            left = Math.min(anchor.ch, head.ch),
	            bottom = Math.max(anchor.line, head.line),
	            right = Math.max(anchor.ch, head.ch) + 1;
	        var height = bottom - top + 1;
	        var primary = head.line == top ? 0 : height - 1;
	        var ranges = [];
	        for (var i = 0; i < height; i++) {
	          ranges.push({
	            anchor: Pos(top + i, left),
	            head: Pos(top + i, right)
	          });
	        }
	        return {
	          ranges: ranges,
	          primary: primary
	        };
	      }
	    }
	    function getHead(cm) {
	      var cur = cm.getCursor('head');
	      if (cm.getSelection().length == 1) {
	        // Small corner case when only 1 character is selected. The "real"
	        // head is the left of head and anchor.
	        cur = cursorMin(cur, cm.getCursor('anchor'));
	      }
	      return cur;
	    }
	
	    /**
	     * If moveHead is set to false, the CodeMirror selection will not be
	     * touched. The caller assumes the responsibility of putting the cursor
	    * in the right place.
	     */
	    function exitVisualMode(cm, moveHead) {
	      var vim = cm.state.vim;
	      if (moveHead !== false) {
	        cm.setCursor(clipCursorToContent(cm, vim.sel.head));
	      }
	      updateLastSelection(cm, vim);
	      vim.visualMode = false;
	      vim.visualLine = false;
	      vim.visualBlock = false;
	      CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
	      if (vim.fakeCursor) {
	        vim.fakeCursor.clear();
	      }
	    }
	
	    // Remove any trailing newlines from the selection. For
	    // example, with the caret at the start of the last word on the line,
	    // 'dw' should word, but not the newline, while 'w' should advance the
	    // caret to the first character of the next line.
	    function clipToLine(cm, curStart, curEnd) {
	      var selection = cm.getRange(curStart, curEnd);
	      // Only clip if the selection ends with trailing newline + whitespace
	      if (/\n\s*$/.test(selection)) {
	        var lines = selection.split('\n');
	        // We know this is all whitespace.
	        lines.pop();
	
	        // Cases:
	        // 1. Last word is an empty line - do not clip the trailing '\n'
	        // 2. Last word is not an empty line - clip the trailing '\n'
	        var line;
	        // Find the line containing the last word, and clip all whitespace up
	        // to it.
	        for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) {
	          curEnd.line--;
	          curEnd.ch = 0;
	        }
	        // If the last word is not an empty line, clip an additional newline
	        if (line) {
	          curEnd.line--;
	          curEnd.ch = lineLength(cm, curEnd.line);
	        } else {
	          curEnd.ch = 0;
	        }
	      }
	    }
	
	    // Expand the selection to line ends.
	    function expandSelectionToLine(_cm, curStart, curEnd) {
	      curStart.ch = 0;
	      curEnd.ch = 0;
	      curEnd.line++;
	    }
	
	    function findFirstNonWhiteSpaceCharacter(text) {
	      if (!text) {
	        return 0;
	      }
	      var firstNonWS = text.search(/\S/);
	      return firstNonWS == -1 ? text.length : firstNonWS;
	    }
	
	    function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) {
	      var cur = getHead(cm);
	      var line = cm.getLine(cur.line);
	      var idx = cur.ch;
	
	      // Seek to first word or non-whitespace character, depending on if
	      // noSymbol is true.
	      var test = noSymbol ? wordCharTest[0] : bigWordCharTest [0];
	      while (!test(line.charAt(idx))) {
	        idx++;
	        if (idx >= line.length) { return null; }
	      }
	
	      if (bigWord) {
	        test = bigWordCharTest[0];
	      } else {
	        test = wordCharTest[0];
	        if (!test(line.charAt(idx))) {
	          test = wordCharTest[1];
	        }
	      }
	
	      var end = idx, start = idx;
	      while (test(line.charAt(end)) && end < line.length) { end++; }
	      while (test(line.charAt(start)) && start >= 0) { start--; }
	      start++;
	
	      if (inclusive) {
	        // If present, include all whitespace after word.
	        // Otherwise, include all whitespace before word, except indentation.
	        var wordEnd = end;
	        while (/\s/.test(line.charAt(end)) && end < line.length) { end++; }
	        if (wordEnd == end) {
	          var wordStart = start;
	          while (/\s/.test(line.charAt(start - 1)) && start > 0) { start--; }
	          if (!start) { start = wordStart; }
	        }
	      }
	      return { start: Pos(cur.line, start), end: Pos(cur.line, end) };
	    }
	
	    function recordJumpPosition(cm, oldCur, newCur) {
	      if (!cursorEqual(oldCur, newCur)) {
	        vimGlobalState.jumpList.add(cm, oldCur, newCur);
	      }
	    }
	
	    function recordLastCharacterSearch(increment, args) {
	        vimGlobalState.lastCharacterSearch.increment = increment;
	        vimGlobalState.lastCharacterSearch.forward = args.forward;
	        vimGlobalState.lastCharacterSearch.selectedCharacter = args.selectedCharacter;
	    }
	
	    var symbolToMode = {
	        '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket',
	        '[': 'section', ']': 'section',
	        '*': 'comment', '/': 'comment',
	        'm': 'method', 'M': 'method',
	        '#': 'preprocess'
	    };
	    var findSymbolModes = {
	      bracket: {
	        isComplete: function(state) {
	          if (state.nextCh === state.symb) {
	            state.depth++;
	            if (state.depth >= 1)return true;
	          } else if (state.nextCh === state.reverseSymb) {
	            state.depth--;
	          }
	          return false;
	        }
	      },
	      section: {
	        init: function(state) {
	          state.curMoveThrough = true;
	          state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}';
	        },
	        isComplete: function(state) {
	          return state.index === 0 && state.nextCh === state.symb;
	        }
	      },
	      comment: {
	        isComplete: function(state) {
	          var found = state.lastCh === '*' && state.nextCh === '/';
	          state.lastCh = state.nextCh;
	          return found;
	        }
	      },
	      // TODO: The original Vim implementation only operates on level 1 and 2.
	      // The current implementation doesn't check for code block level and
	      // therefore it operates on any levels.
	      method: {
	        init: function(state) {
	          state.symb = (state.symb === 'm' ? '{' : '}');
	          state.reverseSymb = state.symb === '{' ? '}' : '{';
	        },
	        isComplete: function(state) {
	          if (state.nextCh === state.symb)return true;
	          return false;
	        }
	      },
	      preprocess: {
	        init: function(state) {
	          state.index = 0;
	        },
	        isComplete: function(state) {
	          if (state.nextCh === '#') {
	            var token = state.lineText.match(/#(\w+)/)[1];
	            if (token === 'endif') {
	              if (state.forward && state.depth === 0) {
	                return true;
	              }
	              state.depth++;
	            } else if (token === 'if') {
	              if (!state.forward && state.depth === 0) {
	                return true;
	              }
	              state.depth--;
	            }
	            if (token === 'else' && state.depth === 0)return true;
	          }
	          return false;
	        }
	      }
	    };
	    function findSymbol(cm, repeat, forward, symb) {
	      var cur = copyCursor(cm.getCursor());
	      var increment = forward ? 1 : -1;
	      var endLine = forward ? cm.lineCount() : -1;
	      var curCh = cur.ch;
	      var line = cur.line;
	      var lineText = cm.getLine(line);
	      var state = {
	        lineText: lineText,
	        nextCh: lineText.charAt(curCh),
	        lastCh: null,
	        index: curCh,
	        symb: symb,
	        reverseSymb: (forward ?  { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb],
	        forward: forward,
	        depth: 0,
	        curMoveThrough: false
	      };
	      var mode = symbolToMode[symb];
	      if (!mode)return cur;
	      var init = findSymbolModes[mode].init;
	      var isComplete = findSymbolModes[mode].isComplete;
	      if (init) { init(state); }
	      while (line !== endLine && repeat) {
	        state.index += increment;
	        state.nextCh = state.lineText.charAt(state.index);
	        if (!state.nextCh) {
	          line += increment;
	          state.lineText = cm.getLine(line) || '';
	          if (increment > 0) {
	            state.index = 0;
	          } else {
	            var lineLen = state.lineText.length;
	            state.index = (lineLen > 0) ? (lineLen-1) : 0;
	          }
	          state.nextCh = state.lineText.charAt(state.index);
	        }
	        if (isComplete(state)) {
	          cur.line = line;
	          cur.ch = state.index;
	          repeat--;
	        }
	      }
	      if (state.nextCh || state.curMoveThrough) {
	        return Pos(line, state.index);
	      }
	      return cur;
	    }
	
	    /**
	     * Returns the boundaries of the next word. If the cursor in the middle of
	     * the word, then returns the boundaries of the current word, starting at
	     * the cursor. If the cursor is at the start/end of a word, and we are going
	     * forward/backward, respectively, find the boundaries of the next word.
	     *
	     * @param {CodeMirror} cm CodeMirror object.
	     * @param {Cursor} cur The cursor position.
	     * @param {boolean} forward True to search forward. False to search
	     *     backward.
	     * @param {boolean} bigWord True if punctuation count as part of the word.
	     *     False if only [a-zA-Z0-9] characters count as part of the word.
	     * @param {boolean} emptyLineIsWord True if empty lines should be treated
	     *     as words.
	     * @return {Object{from:number, to:number, line: number}} The boundaries of
	     *     the word, or null if there are no more words.
	     */
	    function findWord(cm, cur, forward, bigWord, emptyLineIsWord) {
	      var lineNum = cur.line;
	      var pos = cur.ch;
	      var line = cm.getLine(lineNum);
	      var dir = forward ? 1 : -1;
	      var charTests = bigWord ? bigWordCharTest: wordCharTest;
	
	      if (emptyLineIsWord && line == '') {
	        lineNum += dir;
	        line = cm.getLine(lineNum);
	        if (!isLine(cm, lineNum)) {
	          return null;
	        }
	        pos = (forward) ? 0 : line.length;
	      }
	
	      while (true) {
	        if (emptyLineIsWord && line == '') {
	          return { from: 0, to: 0, line: lineNum };
	        }
	        var stop = (dir > 0) ? line.length : -1;
	        var wordStart = stop, wordEnd = stop;
	        // Find bounds of next word.
	        while (pos != stop) {
	          var foundWord = false;
	          for (var i = 0; i < charTests.length && !foundWord; ++i) {
	            if (charTests[i](line.charAt(pos))) {
	              wordStart = pos;
	              // Advance to end of word.
	              while (pos != stop && charTests[i](line.charAt(pos))) {
	                pos += dir;
	              }
	              wordEnd = pos;
	              foundWord = wordStart != wordEnd;
	              if (wordStart == cur.ch && lineNum == cur.line &&
	                  wordEnd == wordStart + dir) {
	                // We started at the end of a word. Find the next one.
	                continue;
	              } else {
	                return {
	                  from: Math.min(wordStart, wordEnd + 1),
	                  to: Math.max(wordStart, wordEnd),
	                  line: lineNum };
	              }
	            }
	          }
	          if (!foundWord) {
	            pos += dir;
	          }
	        }
	        // Advance to next/prev line.
	        lineNum += dir;
	        if (!isLine(cm, lineNum)) {
	          return null;
	        }
	        line = cm.getLine(lineNum);
	        pos = (dir > 0) ? 0 : line.length;
	      }
	    }
	
	    /**
	     * @param {CodeMirror} cm CodeMirror object.
	     * @param {Pos} cur The position to start from.
	     * @param {int} repeat Number of words to move past.
	     * @param {boolean} forward True to search forward. False to search
	     *     backward.
	     * @param {boolean} wordEnd True to move to end of word. False to move to
	     *     beginning of word.
	     * @param {boolean} bigWord True if punctuation count as part of the word.
	     *     False if only alphabet characters count as part of the word.
	     * @return {Cursor} The position the cursor should move to.
	     */
	    function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) {
	      var curStart = copyCursor(cur);
	      var words = [];
	      if (forward && !wordEnd || !forward && wordEnd) {
	        repeat++;
	      }
	      // For 'e', empty lines are not considered words, go figure.
	      var emptyLineIsWord = !(forward && wordEnd);
	      for (var i = 0; i < repeat; i++) {
	        var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord);
	        if (!word) {
	          var eodCh = lineLength(cm, cm.lastLine());
	          words.push(forward
	              ? {line: cm.lastLine(), from: eodCh, to: eodCh}
	              : {line: 0, from: 0, to: 0});
	          break;
	        }
	        words.push(word);
	        cur = Pos(word.line, forward ? (word.to - 1) : word.from);
	      }
	      var shortCircuit = words.length != repeat;
	      var firstWord = words[0];
	      var lastWord = words.pop();
	      if (forward && !wordEnd) {
	        // w
	        if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) {
	          // We did not start in the middle of a word. Discard the extra word at the end.
	          lastWord = words.pop();
	        }
	        return Pos(lastWord.line, lastWord.from);
	      } else if (forward && wordEnd) {
	        return Pos(lastWord.line, lastWord.to - 1);
	      } else if (!forward && wordEnd) {
	        // ge
	        if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) {
	          // We did not start in the middle of a word. Discard the extra word at the end.
	          lastWord = words.pop();
	        }
	        return Pos(lastWord.line, lastWord.to);
	      } else {
	        // b
	        return Pos(lastWord.line, lastWord.from);
	      }
	    }
	
	    function moveToCharacter(cm, repeat, forward, character) {
	      var cur = cm.getCursor();
	      var start = cur.ch;
	      var idx;
	      for (var i = 0; i < repeat; i ++) {
	        var line = cm.getLine(cur.line);
	        idx = charIdxInLine(start, line, character, forward, true);
	        if (idx == -1) {
	          return null;
	        }
	        start = idx;
	      }
	      return Pos(cm.getCursor().line, idx);
	    }
	
	    function moveToColumn(cm, repeat) {
	      // repeat is always >= 1, so repeat - 1 always corresponds
	      // to the column we want to go to.
	      var line = cm.getCursor().line;
	      return clipCursorToContent(cm, Pos(line, repeat - 1));
	    }
	
	    function updateMark(cm, vim, markName, pos) {
	      if (!inArray(markName, validMarks)) {
	        return;
	      }
	      if (vim.marks[markName]) {
	        vim.marks[markName].clear();
	      }
	      vim.marks[markName] = cm.setBookmark(pos);
	    }
	
	    function charIdxInLine(start, line, character, forward, includeChar) {
	      // Search for char in line.
	      // motion_options: {forward, includeChar}
	      // If includeChar = true, include it too.
	      // If forward = true, search forward, else search backwards.
	      // If char is not found on this line, do nothing
	      var idx;
	      if (forward) {
	        idx = line.indexOf(character, start + 1);
	        if (idx != -1 && !includeChar) {
	          idx -= 1;
	        }
	      } else {
	        idx = line.lastIndexOf(character, start - 1);
	        if (idx != -1 && !includeChar) {
	          idx += 1;
	        }
	      }
	      return idx;
	    }
	
	    function findParagraph(cm, head, repeat, dir, inclusive) {
	      var line = head.line;
	      var min = cm.firstLine();
	      var max = cm.lastLine();
	      var start, end, i = line;
	      function isEmpty(i) { return !cm.getLine(i); }
	      function isBoundary(i, dir, any) {
	        if (any) { return isEmpty(i) != isEmpty(i + dir); }
	        return !isEmpty(i) && isEmpty(i + dir);
	      }
	      if (dir) {
	        while (min <= i && i <= max && repeat > 0) {
	          if (isBoundary(i, dir)) { repeat--; }
	          i += dir;
	        }
	        return new Pos(i, 0);
	      }
	
	      var vim = cm.state.vim;
	      if (vim.visualLine && isBoundary(line, 1, true)) {
	        var anchor = vim.sel.anchor;
	        if (isBoundary(anchor.line, -1, true)) {
	          if (!inclusive || anchor.line != line) {
	            line += 1;
	          }
	        }
	      }
	      var startState = isEmpty(line);
	      for (i = line; i <= max && repeat; i++) {
	        if (isBoundary(i, 1, true)) {
	          if (!inclusive || isEmpty(i) != startState) {
	            repeat--;
	          }
	        }
	      }
	      end = new Pos(i, 0);
	      // select boundary before paragraph for the last one
	      if (i > max && !startState) { startState = true; }
	      else { inclusive = false; }
	      for (i = line; i > min; i--) {
	        if (!inclusive || isEmpty(i) == startState || i == line) {
	          if (isBoundary(i, -1, true)) { break; }
	        }
	      }
	      start = new Pos(i, 0);
	      return { start: start, end: end };
	    }
	
	    // TODO: perhaps this finagling of start and end positions belonds
	    // in codemirror/replaceRange?
	    function selectCompanionObject(cm, head, symb, inclusive) {
	      var cur = head, start, end;
	
	      var bracketRegexp = ({
	        '(': /[()]/, ')': /[()]/,
	        '[': /[[\]]/, ']': /[[\]]/,
	        '{': /[{}]/, '}': /[{}]/})[symb];
	      var openSym = ({
	        '(': '(', ')': '(',
	        '[': '[', ']': '[',
	        '{': '{', '}': '{'})[symb];
	      var curChar = cm.getLine(cur.line).charAt(cur.ch);
	      // Due to the behavior of scanForBracket, we need to add an offset if the
	      // cursor is on a matching open bracket.
	      var offset = curChar === openSym ? 1 : 0;
	
	      start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp});
	      end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp});
	
	      if (!start || !end) {
	        return { start: cur, end: cur };
	      }
	
	      start = start.pos;
	      end = end.pos;
	
	      if ((start.line == end.line && start.ch > end.ch)
	          || (start.line > end.line)) {
	        var tmp = start;
	        start = end;
	        end = tmp;
	      }
	
	      if (inclusive) {
	        end.ch += 1;
	      } else {
	        start.ch += 1;
	      }
	
	      return { start: start, end: end };
	    }
	
	    // Takes in a symbol and a cursor and tries to simulate text objects that
	    // have identical opening and closing symbols
	    // TODO support across multiple lines
	    function findBeginningAndEnd(cm, head, symb, inclusive) {
	      var cur = copyCursor(head);
	      var line = cm.getLine(cur.line);
	      var chars = line.split('');
	      var start, end, i, len;
	      var firstIndex = chars.indexOf(symb);
	
	      // the decision tree is to always look backwards for the beginning first,
	      // but if the cursor is in front of the first instance of the symb,
	      // then move the cursor forward
	      if (cur.ch < firstIndex) {
	        cur.ch = firstIndex;
	        // Why is this line even here???
	        // cm.setCursor(cur.line, firstIndex+1);
	      }
	      // otherwise if the cursor is currently on the closing symbol
	      else if (firstIndex < cur.ch && chars[cur.ch] == symb) {
	        end = cur.ch; // assign end to the current cursor
	        --cur.ch; // make sure to look backwards
	      }
	
	      // if we're currently on the symbol, we've got a start
	      if (chars[cur.ch] == symb && !end) {
	        start = cur.ch + 1; // assign start to ahead of the cursor
	      } else {
	        // go backwards to find the start
	        for (i = cur.ch; i > -1 && !start; i--) {
	          if (chars[i] == symb) {
	            start = i + 1;
	          }
	        }
	      }
	
	      // look forwards for the end symbol
	      if (start && !end) {
	        for (i = start, len = chars.length; i < len && !end; i++) {
	          if (chars[i] == symb) {
	            end = i;
	          }
	        }
	      }
	
	      // nothing found
	      if (!start || !end) {
	        return { start: cur, end: cur };
	      }
	
	      // include the symbols
	      if (inclusive) {
	        --start; ++end;
	      }
	
	      return {
	        start: Pos(cur.line, start),
	        end: Pos(cur.line, end)
	      };
	    }
	
	    // Search functions
	    defineOption('pcre', true, 'boolean');
	    function SearchState() {}
	    SearchState.prototype = {
	      getQuery: function() {
	        return vimGlobalState.query;
	      },
	      setQuery: function(query) {
	        vimGlobalState.query = query;
	      },
	      getOverlay: function() {
	        return this.searchOverlay;
	      },
	      setOverlay: function(overlay) {
	        this.searchOverlay = overlay;
	      },
	      isReversed: function() {
	        return vimGlobalState.isReversed;
	      },
	      setReversed: function(reversed) {
	        vimGlobalState.isReversed = reversed;
	      },
	      getScrollbarAnnotate: function() {
	        return this.annotate;
	      },
	      setScrollbarAnnotate: function(annotate) {
	        this.annotate = annotate;
	      }
	    };
	    function getSearchState(cm) {
	      var vim = cm.state.vim;
	      return vim.searchState_ || (vim.searchState_ = new SearchState());
	    }
	    function dialog(cm, template, shortText, onClose, options) {
	      if (cm.openDialog) {
	        cm.openDialog(template, onClose, { bottom: true, value: options.value,
	            onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp,
	            selectValueOnOpen: false});
	      }
	      else {
	        onClose(prompt(shortText, ''));
	      }
	    }
	    function splitBySlash(argString) {
	      var slashes = findUnescapedSlashes(argString) || [];
	      if (!slashes.length) return [];
	      var tokens = [];
	      // in case of strings like foo/bar
	      if (slashes[0] !== 0) return;
	      for (var i = 0; i < slashes.length; i++) {
	        if (typeof slashes[i] == 'number')
	          tokens.push(argString.substring(slashes[i] + 1, slashes[i+1]));
	      }
	      return tokens;
	    }
	
	    function findUnescapedSlashes(str) {
	      var escapeNextChar = false;
	      var slashes = [];
	      for (var i = 0; i < str.length; i++) {
	        var c = str.charAt(i);
	        if (!escapeNextChar && c == '/') {
	          slashes.push(i);
	        }
	        escapeNextChar = !escapeNextChar && (c == '\\');
	      }
	      return slashes;
	    }
	
	    // Translates a search string from ex (vim) syntax into javascript form.
	    function translateRegex(str) {
	      // When these match, add a '\' if unescaped or remove one if escaped.
	      var specials = '|(){';
	      // Remove, but never add, a '\' for these.
	      var unescape = '}';
	      var escapeNextChar = false;
	      var out = [];
	      for (var i = -1; i < str.length; i++) {
	        var c = str.charAt(i) || '';
	        var n = str.charAt(i+1) || '';
	        var specialComesNext = (n && specials.indexOf(n) != -1);
	        if (escapeNextChar) {
	          if (c !== '\\' || !specialComesNext) {
	            out.push(c);
	          }
	          escapeNextChar = false;
	        } else {
	          if (c === '\\') {
	            escapeNextChar = true;
	            // Treat the unescape list as special for removing, but not adding '\'.
	            if (n && unescape.indexOf(n) != -1) {
	              specialComesNext = true;
	            }
	            // Not passing this test means removing a '\'.
	            if (!specialComesNext || n === '\\') {
	              out.push(c);
	            }
	          } else {
	            out.push(c);
	            if (specialComesNext && n !== '\\') {
	              out.push('\\');
	            }
	          }
	        }
	      }
	      return out.join('');
	    }
	
	    // Translates the replace part of a search and replace from ex (vim) syntax into
	    // javascript form.  Similar to translateRegex, but additionally fixes back references
	    // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'.
	    var charUnescapes = {'\\n': '\n', '\\r': '\r', '\\t': '\t'};
	    function translateRegexReplace(str) {
	      var escapeNextChar = false;
	      var out = [];
	      for (var i = -1; i < str.length; i++) {
	        var c = str.charAt(i) || '';
	        var n = str.charAt(i+1) || '';
	        if (charUnescapes[c + n]) {
	          out.push(charUnescapes[c+n]);
	          i++;
	        } else if (escapeNextChar) {
	          // At any point in the loop, escapeNextChar is true if the previous
	          // character was a '\' and was not escaped.
	          out.push(c);
	          escapeNextChar = false;
	        } else {
	          if (c === '\\') {
	            escapeNextChar = true;
	            if ((isNumber(n) || n === '$')) {
	              out.push('$');
	            } else if (n !== '/' && n !== '\\') {
	              out.push('\\');
	            }
	          } else {
	            if (c === '$') {
	              out.push('$');
	            }
	            out.push(c);
	            if (n === '/') {
	              out.push('\\');
	            }
	          }
	        }
	      }
	      return out.join('');
	    }
	
	    // Unescape \ and / in the replace part, for PCRE mode.
	    var unescapes = {'\\/': '/', '\\\\': '\\', '\\n': '\n', '\\r': '\r', '\\t': '\t'};
	    function unescapeRegexReplace(str) {
	      var stream = new CodeMirror.StringStream(str);
	      var output = [];
	      while (!stream.eol()) {
	        // Search for \.
	        while (stream.peek() && stream.peek() != '\\') {
	          output.push(stream.next());
	        }
	        var matched = false;
	        for (var matcher in unescapes) {
	          if (stream.match(matcher, true)) {
	            matched = true;
	            output.push(unescapes[matcher]);
	            break;
	          }
	        }
	        if (!matched) {
	          // Don't change anything
	          output.push(stream.next());
	        }
	      }
	      return output.join('');
	    }
	
	    /**
	     * Extract the regular expression from the query and return a Regexp object.
	     * Returns null if the query is blank.
	     * If ignoreCase is passed in, the Regexp object will have the 'i' flag set.
	     * If smartCase is passed in, and the query contains upper case letters,
	     *   then ignoreCase is overridden, and the 'i' flag will not be set.
	     * If the query contains the /i in the flag part of the regular expression,
	     *   then both ignoreCase and smartCase are ignored, and 'i' will be passed
	     *   through to the Regex object.
	     */
	    function parseQuery(query, ignoreCase, smartCase) {
	      // First update the last search register
	      var lastSearchRegister = vimGlobalState.registerController.getRegister('/');
	      lastSearchRegister.setText(query);
	      // Check if the query is already a regex.
	      if (query instanceof RegExp) { return query; }
	      // First try to extract regex + flags from the input. If no flags found,
	      // extract just the regex. IE does not accept flags directly defined in
	      // the regex string in the form /regex/flags
	      var slashes = findUnescapedSlashes(query);
	      var regexPart;
	      var forceIgnoreCase;
	      if (!slashes.length) {
	        // Query looks like 'regexp'
	        regexPart = query;
	      } else {
	        // Query looks like 'regexp/...'
	        regexPart = query.substring(0, slashes[0]);
	        var flagsPart = query.substring(slashes[0]);
	        forceIgnoreCase = (flagsPart.indexOf('i') != -1);
	      }
	      if (!regexPart) {
	        return null;
	      }
	      if (!getOption('pcre')) {
	        regexPart = translateRegex(regexPart);
	      }
	      if (smartCase) {
	        ignoreCase = (/^[^A-Z]*$/).test(regexPart);
	      }
	      var regexp = new RegExp(regexPart,
	          (ignoreCase || forceIgnoreCase) ? 'i' : undefined);
	      return regexp;
	    }
	    function showConfirm(cm, text) {
	      if (cm.openNotification) {
	        cm.openNotification('<span style="color: red">' + text + '</span>',
	                            {bottom: true, duration: 5000});
	      } else {
	        alert(text);
	      }
	    }
	    function makePrompt(prefix, desc) {
	      var raw = '<span style="font-family: monospace; white-space: pre">' +
	          (prefix || "") + '<input type="text"></span>';
	      if (desc)
	        raw += ' <span style="color: #888">' + desc + '</span>';
	      return raw;
	    }
	    var searchPromptDesc = '(Javascript regexp)';
	    function showPrompt(cm, options) {
	      var shortText = (options.prefix || '') + ' ' + (options.desc || '');
	      var prompt = makePrompt(options.prefix, options.desc);
	      dialog(cm, prompt, shortText, options.onClose, options);
	    }
	    function regexEqual(r1, r2) {
	      if (r1 instanceof RegExp && r2 instanceof RegExp) {
	          var props = ['global', 'multiline', 'ignoreCase', 'source'];
	          for (var i = 0; i < props.length; i++) {
	              var prop = props[i];
	              if (r1[prop] !== r2[prop]) {
	                  return false;
	              }
	          }
	          return true;
	      }
	      return false;
	    }
	    // Returns true if the query is valid.
	    function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) {
	      if (!rawQuery) {
	        return;
	      }
	      var state = getSearchState(cm);
	      var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase);
	      if (!query) {
	        return;
	      }
	      highlightSearchMatches(cm, query);
	      if (regexEqual(query, state.getQuery())) {
	        return query;
	      }
	      state.setQuery(query);
	      return query;
	    }
	    function searchOverlay(query) {
	      if (query.source.charAt(0) == '^') {
	        var matchSol = true;
	      }
	      return {
	        token: function(stream) {
	          if (matchSol && !stream.sol()) {
	            stream.skipToEnd();
	            return;
	          }
	          var match = stream.match(query, false);
	          if (match) {
	            if (match[0].length == 0) {
	              // Matched empty string, skip to next.
	              stream.next();
	              return 'searching';
	            }
	            if (!stream.sol()) {
	              // Backtrack 1 to match \b
	              stream.backUp(1);
	              if (!query.exec(stream.next() + match[0])) {
	                stream.next();
	                return null;
	              }
	            }
	            stream.match(query);
	            return 'searching';
	          }
	          while (!stream.eol()) {
	            stream.next();
	            if (stream.match(query, false)) break;
	          }
	        },
	        query: query
	      };
	    }
	    function highlightSearchMatches(cm, query) {
	      var searchState = getSearchState(cm);
	      var overlay = searchState.getOverlay();
	      if (!overlay || query != overlay.query) {
	        if (overlay) {
	          cm.removeOverlay(overlay);
	        }
	        overlay = searchOverlay(query);
	        cm.addOverlay(overlay);
	        if (cm.showMatchesOnScrollbar) {
	          if (searchState.getScrollbarAnnotate()) {
	            searchState.getScrollbarAnnotate().clear();
	          }
	          searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query));
	        }
	        searchState.setOverlay(overlay);
	      }
	    }
	    function findNext(cm, prev, query, repeat) {
	      if (repeat === undefined) { repeat = 1; }
	      return cm.operation(function() {
	        var pos = cm.getCursor();
	        var cursor = cm.getSearchCursor(query, pos);
	        for (var i = 0; i < repeat; i++) {
	          var found = cursor.find(prev);
	          if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); }
	          if (!found) {
	            // SearchCursor may have returned null because it hit EOF, wrap
	            // around and try again.
	            cursor = cm.getSearchCursor(query,
	                (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) );
	            if (!cursor.find(prev)) {
	              return;
	            }
	          }
	        }
	        return cursor.from();
	      });
	    }
	    function clearSearchHighlight(cm) {
	      var state = getSearchState(cm);
	      cm.removeOverlay(getSearchState(cm).getOverlay());
	      state.setOverlay(null);
	      if (state.getScrollbarAnnotate()) {
	        state.getScrollbarAnnotate().clear();
	        state.setScrollbarAnnotate(null);
	      }
	    }
	    /**
	     * Check if pos is in the specified range, INCLUSIVE.
	     * Range can be specified with 1 or 2 arguments.
	     * If the first range argument is an array, treat it as an array of line
	     * numbers. Match pos against any of the lines.
	     * If the first range argument is a number,
	     *   if there is only 1 range argument, check if pos has the same line
	     *       number
	     *   if there are 2 range arguments, then check if pos is in between the two
	     *       range arguments.
	     */
	    function isInRange(pos, start, end) {
	      if (typeof pos != 'number') {
	        // Assume it is a cursor position. Get the line number.
	        pos = pos.line;
	      }
	      if (start instanceof Array) {
	        return inArray(pos, start);
	      } else {
	        if (end) {
	          return (pos >= start && pos <= end);
	        } else {
	          return pos == start;
	        }
	      }
	    }
	    function getUserVisibleLines(cm) {
	      var scrollInfo = cm.getScrollInfo();
	      var occludeToleranceTop = 6;
	      var occludeToleranceBottom = 10;
	      var from = cm.coordsChar({left:0, top: occludeToleranceTop + scrollInfo.top}, 'local');
	      var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top;
	      var to = cm.coordsChar({left:0, top: bottomY}, 'local');
	      return {top: from.line, bottom: to.line};
	    }
	
	    var ExCommandDispatcher = function() {
	      this.buildCommandMap_();
	    };
	    ExCommandDispatcher.prototype = {
	      processCommand: function(cm, input, opt_params) {
	        var that = this;
	        cm.operation(function () {
	          cm.curOp.isVimOp = true;
	          that._processCommand(cm, input, opt_params);
	        });
	      },
	      _processCommand: function(cm, input, opt_params) {
	        var vim = cm.state.vim;
	        var commandHistoryRegister = vimGlobalState.registerController.getRegister(':');
	        var previousCommand = commandHistoryRegister.toString();
	        if (vim.visualMode) {
	          exitVisualMode(cm);
	        }
	        var inputStream = new CodeMirror.StringStream(input);
	        // update ": with the latest command whether valid or invalid
	        commandHistoryRegister.setText(input);
	        var params = opt_params || {};
	        params.input = input;
	        try {
	          this.parseInput_(cm, inputStream, params);
	        } catch(e) {
	          showConfirm(cm, e);
	          throw e;
	        }
	        var command;
	        var commandName;
	        if (!params.commandName) {
	          // If only a line range is defined, move to the line.
	          if (params.line !== undefined) {
	            commandName = 'move';
	          }
	        } else {
	          command = this.matchCommand_(params.commandName);
	          if (command) {
	            commandName = command.name;
	            if (command.excludeFromCommandHistory) {
	              commandHistoryRegister.setText(previousCommand);
	            }
	            this.parseCommandArgs_(inputStream, params, command);
	            if (command.type == 'exToKey') {
	              // Handle Ex to Key mapping.
	              for (var i = 0; i < command.toKeys.length; i++) {
	                CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping');
	              }
	              return;
	            } else if (command.type == 'exToEx') {
	              // Handle Ex to Ex mapping.
	              this.processCommand(cm, command.toInput);
	              return;
	            }
	          }
	        }
	        if (!commandName) {
	          showConfirm(cm, 'Not an editor command ":' + input + '"');
	          return;
	        }
	        try {
	          exCommands[commandName](cm, params);
	          // Possibly asynchronous commands (e.g. substitute, which might have a
	          // user confirmation), are responsible for calling the callback when
	          // done. All others have it taken care of for them here.
	          if ((!command || !command.possiblyAsync) && params.callback) {
	            params.callback();
	          }
	        } catch(e) {
	          showConfirm(cm, e);
	          throw e;
	        }
	      },
	      parseInput_: function(cm, inputStream, result) {
	        inputStream.eatWhile(':');
	        // Parse range.
	        if (inputStream.eat('%')) {
	          result.line = cm.firstLine();
	          result.lineEnd = cm.lastLine();
	        } else {
	          result.line = this.parseLineSpec_(cm, inputStream);
	          if (result.line !== undefined && inputStream.eat(',')) {
	            result.lineEnd = this.parseLineSpec_(cm, inputStream);
	          }
	        }
	
	        // Parse command name.
	        var commandMatch = inputStream.match(/^(\w+)/);
	        if (commandMatch) {
	          result.commandName = commandMatch[1];
	        } else {
	          result.commandName = inputStream.match(/.*/)[0];
	        }
	
	        return result;
	      },
	      parseLineSpec_: function(cm, inputStream) {
	        var numberMatch = inputStream.match(/^(\d+)/);
	        if (numberMatch) {
	          return parseInt(numberMatch[1], 10) - 1;
	        }
	        switch (inputStream.next()) {
	          case '.':
	            return cm.getCursor().line;
	          case '$':
	            return cm.lastLine();
	          case '\'':
	            var mark = cm.state.vim.marks[inputStream.next()];
	            if (mark && mark.find()) {
	              return mark.find().line;
	            }
	            throw new Error('Mark not set');
	          default:
	            inputStream.backUp(1);
	            return undefined;
	        }
	      },
	      parseCommandArgs_: function(inputStream, params, command) {
	        if (inputStream.eol()) {
	          return;
	        }
	        params.argString = inputStream.match(/.*/)[0];
	        // Parse command-line arguments
	        var delim = command.argDelimiter || /\s+/;
	        var args = trim(params.argString).split(delim);
	        if (args.length && args[0]) {
	          params.args = args;
	        }
	      },
	      matchCommand_: function(commandName) {
	        // Return the command in the command map that matches the shortest
	        // prefix of the passed in command name. The match is guaranteed to be
	        // unambiguous if the defaultExCommandMap's shortNames are set up
	        // correctly. (see @code{defaultExCommandMap}).
	        for (var i = commandName.length; i > 0; i--) {
	          var prefix = commandName.substring(0, i);
	          if (this.commandMap_[prefix]) {
	            var command = this.commandMap_[prefix];
	            if (command.name.indexOf(commandName) === 0) {
	              return command;
	            }
	          }
	        }
	        return null;
	      },
	      buildCommandMap_: function() {
	        this.commandMap_ = {};
	        for (var i = 0; i < defaultExCommandMap.length; i++) {
	          var command = defaultExCommandMap[i];
	          var key = command.shortName || command.name;
	          this.commandMap_[key] = command;
	        }
	      },
	      map: function(lhs, rhs, ctx) {
	        if (lhs != ':' && lhs.charAt(0) == ':') {
	          if (ctx) { throw Error('Mode not supported for ex mappings'); }
	          var commandName = lhs.substring(1);
	          if (rhs != ':' && rhs.charAt(0) == ':') {
	            // Ex to Ex mapping
	            this.commandMap_[commandName] = {
	              name: commandName,
	              type: 'exToEx',
	              toInput: rhs.substring(1),
	              user: true
	            };
	          } else {
	            // Ex to key mapping
	            this.commandMap_[commandName] = {
	              name: commandName,
	              type: 'exToKey',
	              toKeys: rhs,
	              user: true
	            };
	          }
	        } else {
	          if (rhs != ':' && rhs.charAt(0) == ':') {
	            // Key to Ex mapping.
	            var mapping = {
	              keys: lhs,
	              type: 'keyToEx',
	              exArgs: { input: rhs.substring(1) },
	              user: true};
	            if (ctx) { mapping.context = ctx; }
	            defaultKeymap.unshift(mapping);
	          } else {
	            // Key to key mapping
	            var mapping = {
	              keys: lhs,
	              type: 'keyToKey',
	              toKeys: rhs,
	              user: true
	            };
	            if (ctx) { mapping.context = ctx; }
	            defaultKeymap.unshift(mapping);
	          }
	        }
	      },
	      unmap: function(lhs, ctx) {
	        if (lhs != ':' && lhs.charAt(0) == ':') {
	          // Ex to Ex or Ex to key mapping
	          if (ctx) { throw Error('Mode not supported for ex mappings'); }
	          var commandName = lhs.substring(1);
	          if (this.commandMap_[commandName] && this.commandMap_[commandName].user) {
	            delete this.commandMap_[commandName];
	            return;
	          }
	        } else {
	          // Key to Ex or key to key mapping
	          var keys = lhs;
	          for (var i = 0; i < defaultKeymap.length; i++) {
	            if (keys == defaultKeymap[i].keys
	                && defaultKeymap[i].context === ctx
	                && defaultKeymap[i].user) {
	              defaultKeymap.splice(i, 1);
	              return;
	            }
	          }
	        }
	        throw Error('No such mapping.');
	      }
	    };
	
	    var exCommands = {
	      colorscheme: function(cm, params) {
	        if (!params.args || params.args.length < 1) {
	          showConfirm(cm, cm.getOption('theme'));
	          return;
	        }
	        cm.setOption('theme', params.args[0]);
	      },
	      map: function(cm, params, ctx) {
	        var mapArgs = params.args;
	        if (!mapArgs || mapArgs.length < 2) {
	          if (cm) {
	            showConfirm(cm, 'Invalid mapping: ' + params.input);
	          }
	          return;
	        }
	        exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx);
	      },
	      imap: function(cm, params) { this.map(cm, params, 'insert'); },
	      nmap: function(cm, params) { this.map(cm, params, 'normal'); },
	      vmap: function(cm, params) { this.map(cm, params, 'visual'); },
	      unmap: function(cm, params, ctx) {
	        var mapArgs = params.args;
	        if (!mapArgs || mapArgs.length < 1) {
	          if (cm) {
	            showConfirm(cm, 'No such mapping: ' + params.input);
	          }
	          return;
	        }
	        exCommandDispatcher.unmap(mapArgs[0], ctx);
	      },
	      move: function(cm, params) {
	        commandDispatcher.processCommand(cm, cm.state.vim, {
	            type: 'motion',
	            motion: 'moveToLineOrEdgeOfDocument',
	            motionArgs: { forward: false, explicitRepeat: true,
	              linewise: true },
	            repeatOverride: params.line+1});
	      },
	      set: function(cm, params) {
	        var setArgs = params.args;
	        // Options passed through to the setOption/getOption calls. May be passed in by the
	        // local/global versions of the set command
	        var setCfg = params.setCfg || {};
	        if (!setArgs || setArgs.length < 1) {
	          if (cm) {
	            showConfirm(cm, 'Invalid mapping: ' + params.input);
	          }
	          return;
	        }
	        var expr = setArgs[0].split('=');
	        var optionName = expr[0];
	        var value = expr[1];
	        var forceGet = false;
	
	        if (optionName.charAt(optionName.length - 1) == '?') {
	          // If post-fixed with ?, then the set is actually a get.
	          if (value) { throw Error('Trailing characters: ' + params.argString); }
	          optionName = optionName.substring(0, optionName.length - 1);
	          forceGet = true;
	        }
	        if (value === undefined && optionName.substring(0, 2) == 'no') {
	          // To set boolean options to false, the option name is prefixed with
	          // 'no'.
	          optionName = optionName.substring(2);
	          value = false;
	        }
	
	        var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean';
	        if (optionIsBoolean && value == undefined) {
	          // Calling set with a boolean option sets it to true.
	          value = true;
	        }
	        // If no value is provided, then we assume this is a get.
	        if (!optionIsBoolean && value === undefined || forceGet) {
	          var oldValue = getOption(optionName, cm, setCfg);
	          if (oldValue === true || oldValue === false) {
	            showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName);
	          } else {
	            showConfirm(cm, '  ' + optionName + '=' + oldValue);
	          }
	        } else {
	          setOption(optionName, value, cm, setCfg);
	        }
	      },
	      setlocal: function (cm, params) {
	        // setCfg is passed through to setOption
	        params.setCfg = {scope: 'local'};
	        this.set(cm, params);
	      },
	      setglobal: function (cm, params) {
	        // setCfg is passed through to setOption
	        params.setCfg = {scope: 'global'};
	        this.set(cm, params);
	      },
	      registers: function(cm, params) {
	        var regArgs = params.args;
	        var registers = vimGlobalState.registerController.registers;
	        var regInfo = '----------Registers----------<br><br>';
	        if (!regArgs) {
	          for (var registerName in registers) {
	            var text = registers[registerName].toString();
	            if (text.length) {
	              regInfo += '"' + registerName + '    ' + text + '<br>';
	            }
	          }
	        } else {
	          var registerName;
	          regArgs = regArgs.join('');
	          for (var i = 0; i < regArgs.length; i++) {
	            registerName = regArgs.charAt(i);
	            if (!vimGlobalState.registerController.isValidRegister(registerName)) {
	              continue;
	            }
	            var register = registers[registerName] || new Register();
	            regInfo += '"' + registerName + '    ' + register.toString() + '<br>';
	          }
	        }
	        showConfirm(cm, regInfo);
	      },
	      sort: function(cm, params) {
	        var reverse, ignoreCase, unique, number;
	        function parseArgs() {
	          if (params.argString) {
	            var args = new CodeMirror.StringStream(params.argString);
	            if (args.eat('!')) { reverse = true; }
	            if (args.eol()) { return; }
	            if (!args.eatSpace()) { return 'Invalid arguments'; }
	            var opts = args.match(/[a-z]+/);
	            if (opts) {
	              opts = opts[0];
	              ignoreCase = opts.indexOf('i') != -1;
	              unique = opts.indexOf('u') != -1;
	              var decimal = opts.indexOf('d') != -1 && 1;
	              var hex = opts.indexOf('x') != -1 && 1;
	              var octal = opts.indexOf('o') != -1 && 1;
	              if (decimal + hex + octal > 1) { return 'Invalid arguments'; }
	              number = decimal && 'decimal' || hex && 'hex' || octal && 'octal';
	            }
	            if (args.match(/\/.*\//)) { return 'patterns not supported'; }
	          }
	        }
	        var err = parseArgs();
	        if (err) {
	          showConfirm(cm, err + ': ' + params.argString);
	          return;
	        }
	        var lineStart = params.line || cm.firstLine();
	        var lineEnd = params.lineEnd || params.line || cm.lastLine();
	        if (lineStart == lineEnd) { return; }
	        var curStart = Pos(lineStart, 0);
	        var curEnd = Pos(lineEnd, lineLength(cm, lineEnd));
	        var text = cm.getRange(curStart, curEnd).split('\n');
	        var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ :
	           (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i :
	           (number == 'octal') ? /([0-7]+)/ : null;
	        var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null;
	        var numPart = [], textPart = [];
	        if (number) {
	          for (var i = 0; i < text.length; i++) {
	            if (numberRegex.exec(text[i])) {
	              numPart.push(text[i]);
	            } else {
	              textPart.push(text[i]);
	            }
	          }
	        } else {
	          textPart = text;
	        }
	        function compareFn(a, b) {
	          if (reverse) { var tmp; tmp = a; a = b; b = tmp; }
	          if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); }
	          var anum = number && numberRegex.exec(a);
	          var bnum = number && numberRegex.exec(b);
	          if (!anum) { return a < b ? -1 : 1; }
	          anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix);
	          bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix);
	          return anum - bnum;
	        }
	        numPart.sort(compareFn);
	        textPart.sort(compareFn);
	        text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart);
	        if (unique) { // Remove duplicate lines
	          var textOld = text;
	          var lastLine;
	          text = [];
	          for (var i = 0; i < textOld.length; i++) {
	            if (textOld[i] != lastLine) {
	              text.push(textOld[i]);
	            }
	            lastLine = textOld[i];
	          }
	        }
	        cm.replaceRange(text.join('\n'), curStart, curEnd);
	      },
	      global: function(cm, params) {
	        // a global command is of the form
	        // :[range]g/pattern/[cmd]
	        // argString holds the string /pattern/[cmd]
	        var argString = params.argString;
	        if (!argString) {
	          showConfirm(cm, 'Regular Expression missing from global');
	          return;
	        }
	        // range is specified here
	        var lineStart = (params.line !== undefined) ? params.line : cm.firstLine();
	        var lineEnd = params.lineEnd || params.line || cm.lastLine();
	        // get the tokens from argString
	        var tokens = splitBySlash(argString);
	        var regexPart = argString, cmd;
	        if (tokens.length) {
	          regexPart = tokens[0];
	          cmd = tokens.slice(1, tokens.length).join('/');
	        }
	        if (regexPart) {
	          // If regex part is empty, then use the previous query. Otherwise
	          // use the regex part as the new query.
	          try {
	           updateSearchQuery(cm, regexPart, true /** ignoreCase */,
	             true /** smartCase */);
	          } catch (e) {
	           showConfirm(cm, 'Invalid regex: ' + regexPart);
	           return;
	          }
	        }
	        // now that we have the regexPart, search for regex matches in the
	        // specified range of lines
	        var query = getSearchState(cm).getQuery();
	        var matchedLines = [], content = '';
	        for (var i = lineStart; i <= lineEnd; i++) {
	          var matched = query.test(cm.getLine(i));
	          if (matched) {
	            matchedLines.push(i+1);
	            content+= cm.getLine(i) + '<br>';
	          }
	        }
	        // if there is no [cmd], just display the list of matched lines
	        if (!cmd) {
	          showConfirm(cm, content);
	          return;
	        }
	        var index = 0;
	        var nextCommand = function() {
	          if (index < matchedLines.length) {
	            var command = matchedLines[index] + cmd;
	            exCommandDispatcher.processCommand(cm, command, {
	              callback: nextCommand
	            });
	          }
	          index++;
	        };
	        nextCommand();
	      },
	      substitute: function(cm, params) {
	        if (!cm.getSearchCursor) {
	          throw new Error('Search feature not available. Requires searchcursor.js or ' +
	              'any other getSearchCursor implementation.');
	        }
	        var argString = params.argString;
	        var tokens = argString ? splitBySlash(argString) : [];
	        var regexPart, replacePart = '', trailing, flagsPart, count;
	        var confirm = false; // Whether to confirm each replace.
	        var global = false; // True to replace all instances on a line, false to replace only 1.
	        if (tokens.length) {
	          regexPart = tokens[0];
	          replacePart = tokens[1];
	          if (replacePart !== undefined) {
	            if (getOption('pcre')) {
	              replacePart = unescapeRegexReplace(replacePart);
	            } else {
	              replacePart = translateRegexReplace(replacePart);
	            }
	            vimGlobalState.lastSubstituteReplacePart = replacePart;
	          }
	          trailing = tokens[2] ? tokens[2].split(' ') : [];
	        } else {
	          // either the argString is empty or its of the form ' hello/world'
	          // actually splitBySlash returns a list of tokens
	          // only if the string starts with a '/'
	          if (argString && argString.length) {
	            showConfirm(cm, 'Substitutions should be of the form ' +
	                ':s/pattern/replace/');
	            return;
	          }
	        }
	        // After the 3rd slash, we can have flags followed by a space followed
	        // by count.
	        if (trailing) {
	          flagsPart = trailing[0];
	          count = parseInt(trailing[1]);
	          if (flagsPart) {
	            if (flagsPart.indexOf('c') != -1) {
	              confirm = true;
	              flagsPart.replace('c', '');
	            }
	            if (flagsPart.indexOf('g') != -1) {
	              global = true;
	              flagsPart.replace('g', '');
	            }
	            regexPart = regexPart + '/' + flagsPart;
	          }
	        }
	        if (regexPart) {
	          // If regex part is empty, then use the previous query. Otherwise use
	          // the regex part as the new query.
	          try {
	            updateSearchQuery(cm, regexPart, true /** ignoreCase */,
	              true /** smartCase */);
	          } catch (e) {
	            showConfirm(cm, 'Invalid regex: ' + regexPart);
	            return;
	          }
	        }
	        replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart;
	        if (replacePart === undefined) {
	          showConfirm(cm, 'No previous substitute regular expression');
	          return;
	        }
	        var state = getSearchState(cm);
	        var query = state.getQuery();
	        var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line;
	        var lineEnd = params.lineEnd || lineStart;
	        if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) {
	          lineEnd = Infinity;
	        }
	        if (count) {
	          lineStart = lineEnd;
	          lineEnd = lineStart + count - 1;
	        }
	        var startPos = clipCursorToContent(cm, Pos(lineStart, 0));
	        var cursor = cm.getSearchCursor(query, startPos);
	        doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback);
	      },
	      redo: CodeMirror.commands.redo,
	      undo: CodeMirror.commands.undo,
	      write: function(cm) {
	        if (CodeMirror.commands.save) {
	          // If a save command is defined, call it.
	          CodeMirror.commands.save(cm);
	        } else if (cm.save) {
	          // Saves to text area if no save command is defined and cm.save() is available.
	          cm.save();
	        }
	      },
	      nohlsearch: function(cm) {
	        clearSearchHighlight(cm);
	      },
	      yank: function (cm) {
	        var cur = copyCursor(cm.getCursor());
	        var line = cur.line;
	        var lineText = cm.getLine(line);
	        vimGlobalState.registerController.pushText(
	          '0', 'yank', lineText, true, true);
	      },
	      delmarks: function(cm, params) {
	        if (!params.argString || !trim(params.argString)) {
	          showConfirm(cm, 'Argument required');
	          return;
	        }
	
	        var state = cm.state.vim;
	        var stream = new CodeMirror.StringStream(trim(params.argString));
	        while (!stream.eol()) {
	          stream.eatSpace();
	
	          // Record the streams position at the beginning of the loop for use
	          // in error messages.
	          var count = stream.pos;
	
	          if (!stream.match(/[a-zA-Z]/, false)) {
	            showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count));
	            return;
	          }
	
	          var sym = stream.next();
	          // Check if this symbol is part of a range
	          if (stream.match('-', true)) {
	            // This symbol is part of a range.
	
	            // The range must terminate at an alphabetic character.
	            if (!stream.match(/[a-zA-Z]/, false)) {
	              showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count));
	              return;
	            }
	
	            var startMark = sym;
	            var finishMark = stream.next();
	            // The range must terminate at an alphabetic character which
	            // shares the same case as the start of the range.
	            if (isLowerCase(startMark) && isLowerCase(finishMark) ||
	                isUpperCase(startMark) && isUpperCase(finishMark)) {
	              var start = startMark.charCodeAt(0);
	              var finish = finishMark.charCodeAt(0);
	              if (start >= finish) {
	                showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count));
	                return;
	              }
	
	              // Because marks are always ASCII values, and we have
	              // determined that they are the same case, we can use
	              // their char codes to iterate through the defined range.
	              for (var j = 0; j <= finish - start; j++) {
	                var mark = String.fromCharCode(start + j);
	                delete state.marks[mark];
	              }
	            } else {
	              showConfirm(cm, 'Invalid argument: ' + startMark + '-');
	              return;
	            }
	          } else {
	            // This symbol is a valid mark, and is not part of a range.
	            delete state.marks[sym];
	          }
	        }
	      }
	    };
	
	    var exCommandDispatcher = new ExCommandDispatcher();
	
	    /**
	    * @param {CodeMirror} cm CodeMirror instance we are in.
	    * @param {boolean} confirm Whether to confirm each replace.
	    * @param {Cursor} lineStart Line to start replacing from.
	    * @param {Cursor} lineEnd Line to stop replacing at.
	    * @param {RegExp} query Query for performing matches with.
	    * @param {string} replaceWith Text to replace matches with. May contain $1,
	    *     $2, etc for replacing captured groups using Javascript replace.
	    * @param {function()} callback A callback for when the replace is done.
	    */
	    function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query,
	        replaceWith, callback) {
	      // Set up all the functions.
	      cm.state.vim.exMode = true;
	      var done = false;
	      var lastPos = searchCursor.from();
	      function replaceAll() {
	        cm.operation(function() {
	          while (!done) {
	            replace();
	            next();
	          }
	          stop();
	        });
	      }
	      function replace() {
	        var text = cm.getRange(searchCursor.from(), searchCursor.to());
	        var newText = text.replace(query, replaceWith);
	        searchCursor.replace(newText);
	      }
	      function next() {
	        // The below only loops to skip over multiple occurrences on the same
	        // line when 'global' is not true.
	        while(searchCursor.findNext() &&
	              isInRange(searchCursor.from(), lineStart, lineEnd)) {
	          if (!global && lastPos && searchCursor.from().line == lastPos.line) {
	            continue;
	          }
	          cm.scrollIntoView(searchCursor.from(), 30);
	          cm.setSelection(searchCursor.from(), searchCursor.to());
	          lastPos = searchCursor.from();
	          done = false;
	          return;
	        }
	        done = true;
	      }
	      function stop(close) {
	        if (close) { close(); }
	        cm.focus();
	        if (lastPos) {
	          cm.setCursor(lastPos);
	          var vim = cm.state.vim;
	          vim.exMode = false;
	          vim.lastHPos = vim.lastHSPos = lastPos.ch;
	        }
	        if (callback) { callback(); }
	      }
	      function onPromptKeyDown(e, _value, close) {
	        // Swallow all keys.
	        CodeMirror.e_stop(e);
	        var keyName = CodeMirror.keyName(e);
	        switch (keyName) {
	          case 'Y':
	            replace(); next(); break;
	          case 'N':
	            next(); break;
	          case 'A':
	            // replaceAll contains a call to close of its own. We don't want it
	            // to fire too early or multiple times.
	            var savedCallback = callback;
	            callback = undefined;
	            cm.operation(replaceAll);
	            callback = savedCallback;
	            break;
	          case 'L':
	            replace();
	            // fall through and exit.
	          case 'Q':
	          case 'Esc':
	          case 'Ctrl-C':
	          case 'Ctrl-[':
	            stop(close);
	            break;
	        }
	        if (done) { stop(close); }
	        return true;
	      }
	
	      // Actually do replace.
	      next();
	      if (done) {
	        showConfirm(cm, 'No matches for ' + query.source);
	        return;
	      }
	      if (!confirm) {
	        replaceAll();
	        if (callback) { callback(); };
	        return;
	      }
	      showPrompt(cm, {
	        prefix: 'replace with <strong>' + replaceWith + '</strong> (y/n/a/q/l)',
	        onKeyDown: onPromptKeyDown
	      });
	    }
	
	    CodeMirror.keyMap.vim = {
	      attach: attachVimMap,
	      detach: detachVimMap,
	      call: cmKey
	    };
	
	    function exitInsertMode(cm) {
	      var vim = cm.state.vim;
	      var macroModeState = vimGlobalState.macroModeState;
	      var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.');
	      var isPlaying = macroModeState.isPlaying;
	      var lastChange = macroModeState.lastInsertModeChanges;
	      // In case of visual block, the insertModeChanges are not saved as a
	      // single word, so we convert them to a single word
	      // so as to update the ". register as expected in real vim.
	      var text = [];
	      if (!isPlaying) {
	        var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1;
	        var changes = lastChange.changes;
	        var text = [];
	        var i = 0;
	        // In case of multiple selections in blockwise visual,
	        // the inserted text, for example: 'f<Backspace>oo', is stored as
	        // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines).
	        // We push the contents of the changes array as per the following:
	        // 1. In case of InsertModeKey, just increment by 1.
	        // 2. In case of a character, jump by selLength (2 in the example).
	        while (i < changes.length) {
	          // This loop will convert 'ff<bs>oooo' to 'f<bs>oo'.
	          text.push(changes[i]);
	          if (changes[i] instanceof InsertModeKey) {
	             i++;
	          } else {
	             i+= selLength;
	          }
	        }
	        lastChange.changes = text;
	        cm.off('change', onChange);
	        CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown);
	      }
	      if (!isPlaying && vim.insertModeRepeat > 1) {
	        // Perform insert mode repeat for commands like 3,a and 3,o.
	        repeatLastEdit(cm, vim, vim.insertModeRepeat - 1,
	            true /** repeatForInsert */);
	        vim.lastEditInputState.repeatOverride = vim.insertModeRepeat;
	      }
	      delete vim.insertModeRepeat;
	      vim.insertMode = false;
	      cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1);
	      cm.setOption('keyMap', 'vim');
	      cm.setOption('disableInput', true);
	      cm.toggleOverwrite(false); // exit replace mode if we were in it.
	      // update the ". register before exiting insert mode
	      insertModeChangeRegister.setText(lastChange.changes.join(''));
	      CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
	      if (macroModeState.isRecording) {
	        logInsertModeChange(macroModeState);
	      }
	    }
	
	    function _mapCommand(command) {
	      defaultKeymap.unshift(command);
	    }
	
	    function mapCommand(keys, type, name, args, extra) {
	      var command = {keys: keys, type: type};
	      command[type] = name;
	      command[type + "Args"] = args;
	      for (var key in extra)
	        command[key] = extra[key];
	      _mapCommand(command);
	    }
	
	    // The timeout in milliseconds for the two-character ESC keymap should be
	    // adjusted according to your typing speed to prevent false positives.
	    defineOption('insertModeEscKeysTimeout', 200, 'number');
	
	    CodeMirror.keyMap['vim-insert'] = {
	      // TODO: override navigation keys so that Esc will cancel automatic
	      // indentation from o, O, i_<CR>
	      fallthrough: ['default'],
	      attach: attachVimMap,
	      detach: detachVimMap,
	      call: cmKey
	    };
	
	    CodeMirror.keyMap['vim-replace'] = {
	      'Backspace': 'goCharLeft',
	      fallthrough: ['vim-insert'],
	      attach: attachVimMap,
	      detach: detachVimMap,
	      call: cmKey
	    };
	
	    function executeMacroRegister(cm, vim, macroModeState, registerName) {
	      var register = vimGlobalState.registerController.getRegister(registerName);
	      if (registerName == ':') {
	        // Read-only register containing last Ex command.
	        if (register.keyBuffer[0]) {
	          exCommandDispatcher.processCommand(cm, register.keyBuffer[0]);
	        }
	        macroModeState.isPlaying = false;
	        return;
	      }
	      var keyBuffer = register.keyBuffer;
	      var imc = 0;
	      macroModeState.isPlaying = true;
	      macroModeState.replaySearchQueries = register.searchQueries.slice(0);
	      for (var i = 0; i < keyBuffer.length; i++) {
	        var text = keyBuffer[i];
	        var match, key;
	        while (text) {
	          // Pull off one command key, which is either a single character
	          // or a special sequence wrapped in '<' and '>', e.g. '<Space>'.
	          match = (/<\w+-.+?>|<\w+>|./).exec(text);
	          key = match[0];
	          text = text.substring(match.index + key.length);
	          CodeMirror.Vim.handleKey(cm, key, 'macro');
	          if (vim.insertMode) {
	            var changes = register.insertModeChanges[imc++].changes;
	            vimGlobalState.macroModeState.lastInsertModeChanges.changes =
	                changes;
	            repeatInsertModeChanges(cm, changes, 1);
	            exitInsertMode(cm);
	          }
	        }
	      };
	      macroModeState.isPlaying = false;
	    }
	
	    function logKey(macroModeState, key) {
	      if (macroModeState.isPlaying) { return; }
	      var registerName = macroModeState.latestRegister;
	      var register = vimGlobalState.registerController.getRegister(registerName);
	      if (register) {
	        register.pushText(key);
	      }
	    }
	
	    function logInsertModeChange(macroModeState) {
	      if (macroModeState.isPlaying) { return; }
	      var registerName = macroModeState.latestRegister;
	      var register = vimGlobalState.registerController.getRegister(registerName);
	      if (register && register.pushInsertModeChanges) {
	        register.pushInsertModeChanges(macroModeState.lastInsertModeChanges);
	      }
	    }
	
	    function logSearchQuery(macroModeState, query) {
	      if (macroModeState.isPlaying) { return; }
	      var registerName = macroModeState.latestRegister;
	      var register = vimGlobalState.registerController.getRegister(registerName);
	      if (register && register.pushSearchQuery) {
	        register.pushSearchQuery(query);
	      }
	    }
	
	    /**
	     * Listens for changes made in insert mode.
	     * Should only be active in insert mode.
	     */
	    function onChange(_cm, changeObj) {
	      var macroModeState = vimGlobalState.macroModeState;
	      var lastChange = macroModeState.lastInsertModeChanges;
	      if (!macroModeState.isPlaying) {
	        while(changeObj) {
	          lastChange.expectCursorActivityForChange = true;
	          if (changeObj.origin == '+input' || changeObj.origin == 'paste'
	              || changeObj.origin === undefined /* only in testing */) {
	            var text = changeObj.text.join('\n');
	            if (lastChange.maybeReset) {
	              lastChange.changes = [];
	              lastChange.maybeReset = false;
	            }
	            lastChange.changes.push(text);
	          }
	          // Change objects may be chained with next.
	          changeObj = changeObj.next;
	        }
	      }
	    }
	
	    /**
	    * Listens for any kind of cursor activity on CodeMirror.
	    */
	    function onCursorActivity(cm) {
	      var vim = cm.state.vim;
	      if (vim.insertMode) {
	        // Tracking cursor activity in insert mode (for macro support).
	        var macroModeState = vimGlobalState.macroModeState;
	        if (macroModeState.isPlaying) { return; }
	        var lastChange = macroModeState.lastInsertModeChanges;
	        if (lastChange.expectCursorActivityForChange) {
	          lastChange.expectCursorActivityForChange = false;
	        } else {
	          // Cursor moved outside the context of an edit. Reset the change.
	          lastChange.maybeReset = true;
	        }
	      } else if (!cm.curOp.isVimOp) {
	        handleExternalSelection(cm, vim);
	      }
	      if (vim.visualMode) {
	        updateFakeCursor(cm);
	      }
	    }
	    function updateFakeCursor(cm) {
	      var vim = cm.state.vim;
	      var from = clipCursorToContent(cm, copyCursor(vim.sel.head));
	      var to = offsetCursor(from, 0, 1);
	      if (vim.fakeCursor) {
	        vim.fakeCursor.clear();
	      }
	      vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'});
	    }
	    function handleExternalSelection(cm, vim) {
	      var anchor = cm.getCursor('anchor');
	      var head = cm.getCursor('head');
	      // Enter or exit visual mode to match mouse selection.
	      if (vim.visualMode && !cm.somethingSelected()) {
	        exitVisualMode(cm, false);
	      } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) {
	        vim.visualMode = true;
	        vim.visualLine = false;
	        CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"});
	      }
	      if (vim.visualMode) {
	        // Bind CodeMirror selection model to vim selection model.
	        // Mouse selections are considered visual characterwise.
	        var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0;
	        var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0;
	        head = offsetCursor(head, 0, headOffset);
	        anchor = offsetCursor(anchor, 0, anchorOffset);
	        vim.sel = {
	          anchor: anchor,
	          head: head
	        };
	        updateMark(cm, vim, '<', cursorMin(head, anchor));
	        updateMark(cm, vim, '>', cursorMax(head, anchor));
	      } else if (!vim.insertMode) {
	        // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse.
	        vim.lastHPos = cm.getCursor().ch;
	      }
	    }
	
	    /** Wrapper for special keys pressed in insert mode */
	    function InsertModeKey(keyName) {
	      this.keyName = keyName;
	    }
	
	    /**
	    * Handles raw key down events from the text area.
	    * - Should only be active in insert mode.
	    * - For recording deletes in insert mode.
	    */
	    function onKeyEventTargetKeyDown(e) {
	      var macroModeState = vimGlobalState.macroModeState;
	      var lastChange = macroModeState.lastInsertModeChanges;
	      var keyName = CodeMirror.keyName(e);
	      if (!keyName) { return; }
	      function onKeyFound() {
	        if (lastChange.maybeReset) {
	          lastChange.changes = [];
	          lastChange.maybeReset = false;
	        }
	        lastChange.changes.push(new InsertModeKey(keyName));
	        return true;
	      }
	      if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) {
	        CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound);
	      }
	    }
	
	    /**
	     * Repeats the last edit, which includes exactly 1 command and at most 1
	     * insert. Operator and motion commands are read from lastEditInputState,
	     * while action commands are read from lastEditActionCommand.
	     *
	     * If repeatForInsert is true, then the function was called by
	     * exitInsertMode to repeat the insert mode changes the user just made. The
	     * corresponding enterInsertMode call was made with a count.
	     */
	    function repeatLastEdit(cm, vim, repeat, repeatForInsert) {
	      var macroModeState = vimGlobalState.macroModeState;
	      macroModeState.isPlaying = true;
	      var isAction = !!vim.lastEditActionCommand;
	      var cachedInputState = vim.inputState;
	      function repeatCommand() {
	        if (isAction) {
	          commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand);
	        } else {
	          commandDispatcher.evalInput(cm, vim);
	        }
	      }
	      function repeatInsert(repeat) {
	        if (macroModeState.lastInsertModeChanges.changes.length > 0) {
	          // For some reason, repeat cw in desktop VIM does not repeat
	          // insert mode changes. Will conform to that behavior.
	          repeat = !vim.lastEditActionCommand ? 1 : repeat;
	          var changeObject = macroModeState.lastInsertModeChanges;
	          repeatInsertModeChanges(cm, changeObject.changes, repeat);
	        }
	      }
	      vim.inputState = vim.lastEditInputState;
	      if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) {
	        // o and O repeat have to be interlaced with insert repeats so that the
	        // insertions appear on separate lines instead of the last line.
	        for (var i = 0; i < repeat; i++) {
	          repeatCommand();
	          repeatInsert(1);
	        }
	      } else {
	        if (!repeatForInsert) {
	          // Hack to get the cursor to end up at the right place. If I is
	          // repeated in insert mode repeat, cursor will be 1 insert
	          // change set left of where it should be.
	          repeatCommand();
	        }
	        repeatInsert(repeat);
	      }
	      vim.inputState = cachedInputState;
	      if (vim.insertMode && !repeatForInsert) {
	        // Don't exit insert mode twice. If repeatForInsert is set, then we
	        // were called by an exitInsertMode call lower on the stack.
	        exitInsertMode(cm);
	      }
	      macroModeState.isPlaying = false;
	    };
	
	    function repeatInsertModeChanges(cm, changes, repeat) {
	      function keyHandler(binding) {
	        if (typeof binding == 'string') {
	          CodeMirror.commands[binding](cm);
	        } else {
	          binding(cm);
	        }
	        return true;
	      }
	      var head = cm.getCursor('head');
	      var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock;
	      if (inVisualBlock) {
	        // Set up block selection again for repeating the changes.
	        var vim = cm.state.vim;
	        var lastSel = vim.lastSelection;
	        var offset = getOffset(lastSel.anchor, lastSel.head);
	        selectForInsert(cm, head, offset.line + 1);
	        repeat = cm.listSelections().length;
	        cm.setCursor(head);
	      }
	      for (var i = 0; i < repeat; i++) {
	        if (inVisualBlock) {
	          cm.setCursor(offsetCursor(head, i, 0));
	        }
	        for (var j = 0; j < changes.length; j++) {
	          var change = changes[j];
	          if (change instanceof InsertModeKey) {
	            CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler);
	          } else {
	            var cur = cm.getCursor();
	            cm.replaceRange(change, cur, cur);
	          }
	        }
	      }
	      if (inVisualBlock) {
	        cm.setCursor(offsetCursor(head, 0, 1));
	      }
	    }
	
	    resetVimGlobalState();
	    return vimApi;
	  };
	  // Initialize Vim and make it available as an API.
	  CodeMirror.Vim = Vim();
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/keymap/vim.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/addon/search/searchcursor.js **/
jupyter.define('codemirror@5.23.0/addon/search/searchcursor.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  "use strict";
	  var Pos = CodeMirror.Pos;
	
	  function SearchCursor(doc, query, pos, caseFold) {
	    this.atOccurrence = false; this.doc = doc;
	    if (caseFold == null && typeof query == "string") caseFold = false;
	
	    pos = pos ? doc.clipPos(pos) : Pos(0, 0);
	    this.pos = {from: pos, to: pos};
	
	    // The matches method is filled in based on the type of query.
	    // It takes a position and a direction, and returns an object
	    // describing the next occurrence of the query, or null if no
	    // more matches were found.
	    if (typeof query != "string") { // Regexp match
	      if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
	      this.matches = function(reverse, pos) {
	        if (reverse) {
	          query.lastIndex = 0;
	          var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
	          for (;;) {
	            query.lastIndex = cutOff;
	            var newMatch = query.exec(line);
	            if (!newMatch) break;
	            match = newMatch;
	            start = match.index;
	            cutOff = match.index + (match[0].length || 1);
	            if (cutOff == line.length) break;
	          }
	          var matchLen = (match && match[0].length) || 0;
	          if (!matchLen) {
	            if (start == 0 && line.length == 0) {match = undefined;}
	            else if (start != doc.getLine(pos.line).length) {
	              matchLen++;
	            }
	          }
	        } else {
	          query.lastIndex = pos.ch;
	          var line = doc.getLine(pos.line), match = query.exec(line);
	          var matchLen = (match && match[0].length) || 0;
	          var start = match && match.index;
	          if (start + matchLen != line.length && !matchLen) matchLen = 1;
	        }
	        if (match && matchLen)
	          return {from: Pos(pos.line, start),
	                  to: Pos(pos.line, start + matchLen),
	                  match: match};
	      };
	    } else { // String query
	      var origQuery = query;
	      if (caseFold) query = query.toLowerCase();
	      var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
	      var target = query.split("\n");
	      // Different methods for single-line and multi-line queries
	      if (target.length == 1) {
	        if (!query.length) {
	          // Empty string would match anything and never progress, so
	          // we define it to match nothing instead.
	          this.matches = function() {};
	        } else {
	          this.matches = function(reverse, pos) {
	            if (reverse) {
	              var orig = doc.getLine(pos.line).slice(0, pos.ch), line = fold(orig);
	              var match = line.lastIndexOf(query);
	              if (match > -1) {
	                match = adjustPos(orig, line, match);
	                return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
	              }
	             } else {
	               var orig = doc.getLine(pos.line).slice(pos.ch), line = fold(orig);
	               var match = line.indexOf(query);
	               if (match > -1) {
	                 match = adjustPos(orig, line, match) + pos.ch;
	                 return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
	               }
	            }
	          };
	        }
	      } else {
	        var origTarget = origQuery.split("\n");
	        this.matches = function(reverse, pos) {
	          var last = target.length - 1;
	          if (reverse) {
	            if (pos.line - (target.length - 1) < doc.firstLine()) return;
	            if (fold(doc.getLine(pos.line).slice(0, origTarget[last].length)) != target[target.length - 1]) return;
	            var to = Pos(pos.line, origTarget[last].length);
	            for (var ln = pos.line - 1, i = last - 1; i >= 1; --i, --ln)
	              if (target[i] != fold(doc.getLine(ln))) return;
	            var line = doc.getLine(ln), cut = line.length - origTarget[0].length;
	            if (fold(line.slice(cut)) != target[0]) return;
	            return {from: Pos(ln, cut), to: to};
	          } else {
	            if (pos.line + (target.length - 1) > doc.lastLine()) return;
	            var line = doc.getLine(pos.line), cut = line.length - origTarget[0].length;
	            if (fold(line.slice(cut)) != target[0]) return;
	            var from = Pos(pos.line, cut);
	            for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln)
	              if (target[i] != fold(doc.getLine(ln))) return;
	            if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return;
	            return {from: from, to: Pos(ln, origTarget[last].length)};
	          }
	        };
	      }
	    }
	  }
	
	  SearchCursor.prototype = {
	    findNext: function() {return this.find(false);},
	    findPrevious: function() {return this.find(true);},
	
	    find: function(reverse) {
	      var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
	      function savePosAndFail(line) {
	        var pos = Pos(line, 0);
	        self.pos = {from: pos, to: pos};
	        self.atOccurrence = false;
	        return false;
	      }
	
	      for (;;) {
	        if (this.pos = this.matches(reverse, pos)) {
	          this.atOccurrence = true;
	          return this.pos.match || true;
	        }
	        if (reverse) {
	          if (!pos.line) return savePosAndFail(0);
	          pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length);
	        }
	        else {
	          var maxLine = this.doc.lineCount();
	          if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
	          pos = Pos(pos.line + 1, 0);
	        }
	      }
	    },
	
	    from: function() {if (this.atOccurrence) return this.pos.from;},
	    to: function() {if (this.atOccurrence) return this.pos.to;},
	
	    replace: function(newText, origin) {
	      if (!this.atOccurrence) return;
	      var lines = CodeMirror.splitLines(newText);
	      this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin);
	      this.pos.to = Pos(this.pos.from.line + lines.length - 1,
	                        lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
	    }
	  };
	
	  // Maps a position in a case-folded line back to a position in the original line
	  // (compensating for codepoints increasing in number during folding)
	  function adjustPos(orig, folded, pos) {
	    if (orig.length == folded.length) return pos;
	    for (var pos1 = Math.min(pos, orig.length);;) {
	      var len1 = orig.slice(0, pos1).toLowerCase().length;
	      if (len1 < pos) ++pos1;
	      else if (len1 > pos) --pos1;
	      else return pos1;
	    }
	  }
	
	  CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
	    return new SearchCursor(this.doc, query, pos, caseFold);
	  });
	  CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
	    return new SearchCursor(this, query, pos, caseFold);
	  });
	
	  CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
	    var ranges = [];
	    var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
	    while (cur.findNext()) {
	      if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
	      ranges.push({anchor: cur.from(), head: cur.to()});
	    }
	    if (ranges.length)
	      this.setSelections(ranges, 0);
	  });
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/addon/search/searchcursor.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/addon/dialog/dialog.js **/
jupyter.define('codemirror@5.23.0/addon/dialog/dialog.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	// Open simple dialogs on top of an editor. Relies on dialog.css.
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  function dialogDiv(cm, template, bottom) {
	    var wrap = cm.getWrapperElement();
	    var dialog;
	    dialog = wrap.appendChild(document.createElement("div"));
	    if (bottom)
	      dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
	    else
	      dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
	
	    if (typeof template == "string") {
	      dialog.innerHTML = template;
	    } else { // Assuming it's a detached DOM element.
	      dialog.appendChild(template);
	    }
	    return dialog;
	  }
	
	  function closeNotification(cm, newVal) {
	    if (cm.state.currentNotificationClose)
	      cm.state.currentNotificationClose();
	    cm.state.currentNotificationClose = newVal;
	  }
	
	  CodeMirror.defineExtension("openDialog", function(template, callback, options) {
	    if (!options) options = {};
	
	    closeNotification(this, null);
	
	    var dialog = dialogDiv(this, template, options.bottom);
	    var closed = false, me = this;
	    function close(newVal) {
	      if (typeof newVal == 'string') {
	        inp.value = newVal;
	      } else {
	        if (closed) return;
	        closed = true;
	        dialog.parentNode.removeChild(dialog);
	        me.focus();
	
	        if (options.onClose) options.onClose(dialog);
	      }
	    }
	
	    var inp = dialog.getElementsByTagName("input")[0], button;
	    if (inp) {
	      inp.focus();
	
	      if (options.value) {
	        inp.value = options.value;
	        if (options.selectValueOnOpen !== false) {
	          inp.select();
	        }
	      }
	
	      if (options.onInput)
	        CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
	      if (options.onKeyUp)
	        CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
	
	      CodeMirror.on(inp, "keydown", function(e) {
	        if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
	        if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
	          inp.blur();
	          CodeMirror.e_stop(e);
	          close();
	        }
	        if (e.keyCode == 13) callback(inp.value, e);
	      });
	
	      if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
	    } else if (button = dialog.getElementsByTagName("button")[0]) {
	      CodeMirror.on(button, "click", function() {
	        close();
	        me.focus();
	      });
	
	      if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
	
	      button.focus();
	    }
	    return close;
	  });
	
	  CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
	    closeNotification(this, null);
	    var dialog = dialogDiv(this, template, options && options.bottom);
	    var buttons = dialog.getElementsByTagName("button");
	    var closed = false, me = this, blurring = 1;
	    function close() {
	      if (closed) return;
	      closed = true;
	      dialog.parentNode.removeChild(dialog);
	      me.focus();
	    }
	    buttons[0].focus();
	    for (var i = 0; i < buttons.length; ++i) {
	      var b = buttons[i];
	      (function(callback) {
	        CodeMirror.on(b, "click", function(e) {
	          CodeMirror.e_preventDefault(e);
	          close();
	          if (callback) callback(me);
	        });
	      })(callbacks[i]);
	      CodeMirror.on(b, "blur", function() {
	        --blurring;
	        setTimeout(function() { if (blurring <= 0) close(); }, 200);
	      });
	      CodeMirror.on(b, "focus", function() { ++blurring; });
	    }
	  });
	
	  /*
	   * openNotification
	   * Opens a notification, that can be closed with an optional timer
	   * (default 5000ms timer) and always closes on click.
	   *
	   * If a notification is opened while another is opened, it will close the
	   * currently opened one and open the new one immediately.
	   */
	  CodeMirror.defineExtension("openNotification", function(template, options) {
	    closeNotification(this, close);
	    var dialog = dialogDiv(this, template, options && options.bottom);
	    var closed = false, doneTimer;
	    var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
	
	    function close() {
	      if (closed) return;
	      closed = true;
	      clearTimeout(doneTimer);
	      dialog.parentNode.removeChild(dialog);
	    }
	
	    CodeMirror.on(dialog, 'click', function(e) {
	      CodeMirror.e_preventDefault(e);
	      close();
	    });
	
	    if (duration)
	      doneTimer = setTimeout(close, duration);
	
	    return close;
	  });
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/addon/dialog/dialog.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/menu.js **/
jupyter.define('phosphor@0.7.0/lib/ui/menu.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var searching_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var messaging_1 = __jupyter_require__('phosphor@0.7.0/lib/core/messaging.js');
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	var query_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/query.js');
	var sizing_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/sizing.js');
	var keymap_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/keymap.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to Menu instances.
	 */
	var MENU_CLASS = 'p-Menu';
	/**
	 * The class name added to a menu content node.
	 */
	var CONTENT_CLASS = 'p-Menu-content';
	/**
	 * The class name added to a menu item node.
	 */
	var ITEM_CLASS = 'p-Menu-item';
	/**
	 * The class name added to a menu item icon node.
	 */
	var ICON_CLASS = 'p-Menu-itemIcon';
	/**
	 * The class name added to a menu item label node.
	 */
	var LABEL_CLASS = 'p-Menu-itemLabel';
	/**
	 * The class name added to a menu item mnemonic node.
	 */
	var MNEMONIC_CLASS = 'p-Menu-itemMnemonic';
	/**
	 * The class name added to a menu item shortcut node.
	 */
	var SHORTCUT_CLASS = 'p-Menu-itemShortcut';
	/**
	 * The class name added to a menu item submenu icon node.
	 */
	var SUBMENU_ICON_CLASS = 'p-Menu-itemSubmenuIcon';
	/**
	 * The class name added to a `'command'` type menu item.
	 */
	var COMMAND_TYPE_CLASS = 'p-type-command';
	/**
	 * The class name added to a `'separator'` type menu item.
	 */
	var SEPARATOR_TYPE_CLASS = 'p-type-separator';
	/**
	 * The class name added to a `'submenu'` type menu item.
	 */
	var SUBMENU_TYPE_CLASS = 'p-type-submenu';
	/**
	 * The class name added to active menu items.
	 */
	var ACTIVE_CLASS = 'p-mod-active';
	/**
	 * The class name added to a disabled menu item.
	 */
	var DISABLED_CLASS = 'p-mod-disabled';
	/**
	 * The class name added to a toggled menu item.
	 */
	var TOGGLED_CLASS = 'p-mod-toggled';
	/**
	 * The class name added to a hidden menu item.
	 */
	var HIDDEN_CLASS = 'p-mod-hidden';
	/**
	 * The ms delay for opening and closing a submenu.
	 */
	var TIMER_DELAY = 300;
	/**
	 * The horizontal pixel overlap for an open submenu.
	 */
	var SUBMENU_OVERLAP = 3;
	/**
	 * A widget which displays menu items as a canonical menu.
	 */
	var Menu = (function (_super) {
	    __extends(Menu, _super);
	    /**
	     * Construct a new menu.
	     *
	     * @param options - The options for initializing the menu.
	     */
	    function Menu(options) {
	        _super.call(this, { node: Private.createNode() });
	        this._childIndex = -1;
	        this._openTimerID = 0;
	        this._closeTimerID = 0;
	        this._activeIndex = -1;
	        this._childMenu = null;
	        this._parentMenu = null;
	        this._items = new vector_1.Vector();
	        this._nodes = new vector_1.Vector();
	        this.addClass(MENU_CLASS);
	        this.setFlag(widget_1.WidgetFlag.DisallowLayout);
	        this._keymap = options.keymap;
	        this._commands = options.commands;
	        this._renderer = options.renderer || Menu.defaultRenderer;
	    }
	    /**
	     * Dispose of the resources held by the menu.
	     */
	    Menu.prototype.dispose = function () {
	        this.close();
	        this._items.clear();
	        this._nodes.clear();
	        this._keymap = null;
	        this._commands = null;
	        this._renderer = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(Menu.prototype, "parentMenu", {
	        /**
	         * Get the parent menu of the menu.
	         *
	         * #### Notes
	         * This will be `null` if the menu is not an open submenu.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._parentMenu;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "childMenu", {
	        /**
	         * Get the child menu of the menu.
	         *
	         * #### Notes
	         * This will be `null` if the menu does not have an open submenu.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._childMenu;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "rootMenu", {
	        /**
	         * Find the root menu of this menu hierarchy.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            var menu = this;
	            while (menu._parentMenu) {
	                menu = menu._parentMenu;
	            }
	            return menu;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "leafMenu", {
	        /**
	         * Find the leaf menu of this menu hierarchy.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            var menu = this;
	            while (menu._childMenu) {
	                menu = menu._childMenu;
	            }
	            return menu;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "contentNode", {
	        /**
	         * Get the menu content node.
	         *
	         * #### Notes
	         * This is the node which holds the menu item nodes.
	         *
	         * Modifying this node directly can lead to undefined behavior.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.node.getElementsByClassName(CONTENT_CLASS)[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "commands", {
	        /**
	         * The command registry used by the menu.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._commands;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "keymap", {
	        /**
	         * The keymap used by the menu.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._keymap;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "renderer", {
	        /**
	         * The renderer used by the menu.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "items", {
	        /**
	         * A read-only sequence of the menu items in the menu.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._items;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "activeItem", {
	        /**
	         * Get the currently active menu item.
	         *
	         * #### Notes
	         * This will be `null` if no menu item is active.
	         */
	        get: function () {
	            var i = this._activeIndex;
	            return i !== -1 ? this._items.at(i) : null;
	        },
	        /**
	         * Set the currently active menu item.
	         *
	         * #### Notes
	         * If the item cannot be activated, the item will be set to `null`.
	         */
	        set: function (value) {
	            this.activeIndex = searching_1.indexOf(this._items, value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Menu.prototype, "activeIndex", {
	        /**
	         * Get the index of the currently active menu item.
	         *
	         * #### Notes
	         * This will be `-1` if no menu item is active.
	         */
	        get: function () {
	            return this._activeIndex;
	        },
	        /**
	         * Set the index of the currently active menu item.
	         *
	         * #### Notes
	         * If the item cannot be activated, the index will be set to `-1`.
	         */
	        set: function (value) {
	            // Coerce the value to an index.
	            var i = Math.floor(value);
	            if (i < 0 || i >= this._items.length) {
	                i = -1;
	            }
	            // Ensure the item can be activated.
	            if (i !== -1) {
	                var item = this._items.at(i);
	                if (item.type === 'separator' || !item.isEnabled || !item.isVisible) {
	                    i = -1;
	                }
	            }
	            // Bail early if the index will not change.
	            if (this._activeIndex === i) {
	                return;
	            }
	            // Remove the active class from the old node.
	            if (this._activeIndex !== -1) {
	                var node = this._nodes.at(this._activeIndex);
	                node.classList.remove(ACTIVE_CLASS);
	            }
	            // Add the active class to the new node.
	            if (i !== -1) {
	                var node = this._nodes.at(i);
	                node.classList.add(ACTIVE_CLASS);
	            }
	            // Update the active index.
	            this._activeIndex = i;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Activate the next selectable item in the menu.
	     *
	     * #### Notes
	     * If no item is selectable, the index will be set to `-1`.
	     */
	    Menu.prototype.activateNextItem = function () {
	        var n = this._items.length;
	        var j = this._activeIndex + 1;
	        for (var i = 0; i < n; ++i) {
	            var k = (i + j) % n;
	            var item = this._items.at(k);
	            if (item.type !== 'separator' && item.isEnabled && item.isVisible) {
	                this.activeIndex = k;
	                return;
	            }
	        }
	        this.activeIndex = -1;
	    };
	    /**
	     * Activate the previous selectable item in the menu.
	     *
	     * #### Notes
	     * If no item is selectable, the index will be set to `-1`.
	     */
	    Menu.prototype.activatePreviousItem = function () {
	        var n = this._items.length;
	        var ai = this._activeIndex;
	        var j = ai <= 0 ? n - 1 : ai - 1;
	        for (var i = 0; i < n; ++i) {
	            var k = (j - i + n) % n;
	            var item = this._items.at(k);
	            if (item.type !== 'separator' && item.isEnabled && item.isVisible) {
	                this.activeIndex = k;
	                return;
	            }
	        }
	        this.activeIndex = -1;
	    };
	    /**
	     * Trigger the active menu item.
	     *
	     * #### Notes
	     * If the active item is a submenu, it will be opened and the first
	     * item will be activated.
	     *
	     * If the active item is a command, the command will be executed.
	     *
	     * If the menu is not attached, this is a no-op.
	     *
	     * If there is no active item, this is a no-op.
	     */
	    Menu.prototype.triggerActiveItem = function () {
	        // Bail if the menu is not attached.
	        if (!this.isAttached) {
	            return;
	        }
	        // Bail if there is no active item.
	        var item = this.activeItem;
	        if (!item) {
	            return;
	        }
	        // Cancel the pending timers.
	        this._cancelOpenTimer();
	        this._cancelCloseTimer();
	        // If the item is a submenu, open it.
	        if (item.type === 'submenu') {
	            this._openChildMenu(true);
	            return;
	        }
	        // Close the root menu before executing the command.
	        this.rootMenu.close();
	        // Execute the command for the item.
	        var command = item.command, args = item.args;
	        if (this._commands.isEnabled(command, args)) {
	            this._commands.execute(command, args);
	        }
	        else {
	            // TODO - is this the right logging here?
	            console.log("Command '" + command + "' is disabled.");
	        }
	    };
	    /**
	     * Add a menu item to the end of the menu.
	     *
	     * @param options - The options for creating the menu item.
	     *
	     * @returns The menu item added to the menu.
	     */
	    Menu.prototype.addItem = function (options) {
	        return this.insertItem(this._items.length, options);
	    };
	    /**
	     * Insert a menu item into the menu at the specified index.
	     *
	     * @param index - The index at which to insert the item.
	     *
	     * @param options - The options for creating the menu item.
	     *
	     * @returns The menu item added to the menu.
	     *
	     * #### Notes
	     * The index will be clamped to the bounds of the items.
	     */
	    Menu.prototype.insertItem = function (index, options) {
	        // Close the menu if it's attached.
	        if (this.isAttached) {
	            this.close();
	        }
	        // Reset the active index.
	        this.activeIndex = -1;
	        // Clamp the insert index to the vector bounds.
	        var i = Math.max(0, Math.min(Math.floor(index), this._items.length));
	        // Create the item for the options.
	        var item = Private.createItem(this._commands, this._keymap, options);
	        // Create the node for the item. It will be initialized on open.
	        var node = this._renderer.createItemNode();
	        // Insert the item and node into the vectors.
	        this._items.insert(i, item);
	        this._nodes.insert(i, node);
	        // Look up the next sibling node.
	        var ref = i + 1 < this._nodes.length ? this._nodes.at(i + 1) : null;
	        // Insert the node into the content node.
	        this.contentNode.insertBefore(node, ref);
	        // Return the item added to the menu.
	        return item;
	    };
	    /**
	     * Remove an item from the menu.
	     *
	     * @param item - The item to remove from the menu.
	     *
	     * @returns The index occupied by the item, or `-1` if the item
	     *   was not contained in the menu.
	     */
	    Menu.prototype.removeItem = function (item) {
	        var index = searching_1.indexOf(this._items, item);
	        if (index !== -1)
	            this.removeItemAt(index);
	        return index;
	    };
	    /**
	     * Remove the item at a given index from the menu.
	     *
	     * @param index - The index of the item to remove.
	     *
	     * @returns The item occupying the index, or `null` if the index
	     *   is out of range.
	     */
	    Menu.prototype.removeItemAt = function (index) {
	        // Bail if the index is out of range.
	        var i = Math.floor(index);
	        if (i < 0 || i >= this._items.length) {
	            return null;
	        }
	        // Close the menu if it's attached.
	        if (this.isAttached) {
	            this.close();
	        }
	        // Reset the active index.
	        this.activeIndex = -1;
	        // Remove the node and items from the vectors.
	        var node = this._nodes.removeAt(i);
	        var item = this._items.removeAt(i);
	        // Remove the node from the content node.
	        this.contentNode.removeChild(node);
	        // Return the removed item.
	        return item;
	    };
	    /**
	     * Remove all menu items from the menu.
	     */
	    Menu.prototype.clearItems = function () {
	        // Close the menu if it's attached.
	        if (this.isAttached) {
	            this.close();
	        }
	        // Reset the active index.
	        this.activeIndex = -1;
	        // Clear the item and node vectors.
	        this._items.clear();
	        this._nodes.clear();
	        // Clear the content node.
	        this.contentNode.textContent = '';
	    };
	    /**
	     * Open the menu at the specified location.
	     *
	     * @param x - The client X coordinate of the menu location.
	     *
	     * @param y - The client Y coordinate of the menu location.
	     *
	     * @param options - The additional options for opening the menu.
	     *
	     * #### Notes
	     * The menu will be opened at the given location unless it will not
	     * fully fit on the screen. If it will not fit, it will be adjusted
	     * to fit naturally on the screen.
	     *
	     * This is a no-op if the menu is already attached to the DOM.
	     */
	    Menu.prototype.open = function (x, y, options) {
	        if (options === void 0) { options = {}; }
	        // Bail early if the menu is already attached.
	        if (this.isAttached) {
	            return;
	        }
	        // Extract the position options.
	        var forceX = options.forceX || false;
	        var forceY = options.forceY || false;
	        // Open the menu as a root menu.
	        Private.openRootMenu(this, x, y, forceX, forceY);
	        // Activate the menu to accept keyboard input.
	        this.activate();
	    };
	    /**
	     * Handle the DOM events for the menu.
	     *
	     * @param event - The DOM event sent to the menu.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the menu's DOM nodes. It should
	     * not be called directly by user code.
	     */
	    Menu.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'keydown':
	                this._evtKeyDown(event);
	                break;
	            case 'mouseup':
	                this._evtMouseUp(event);
	                break;
	            case 'mousemove':
	                this._evtMouseMove(event);
	                break;
	            case 'mouseenter':
	                this._evtMouseEnter(event);
	                break;
	            case 'mouseleave':
	                this._evtMouseLeave(event);
	                break;
	            case 'mousedown':
	                this._evtMouseDown(event);
	                break;
	            case 'contextmenu':
	                event.preventDefault();
	                event.stopPropagation();
	                break;
	        }
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    Menu.prototype.onAfterAttach = function (msg) {
	        this.node.addEventListener('keydown', this);
	        this.node.addEventListener('mouseup', this);
	        this.node.addEventListener('mousemove', this);
	        this.node.addEventListener('mouseenter', this);
	        this.node.addEventListener('mouseleave', this);
	        this.node.addEventListener('contextmenu', this);
	        document.addEventListener('mousedown', this, true);
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    Menu.prototype.onBeforeDetach = function (msg) {
	        this.node.removeEventListener('keydown', this);
	        this.node.removeEventListener('mouseup', this);
	        this.node.removeEventListener('mousemove', this);
	        this.node.removeEventListener('mouseenter', this);
	        this.node.removeEventListener('mouseleave', this);
	        this.node.removeEventListener('contextmenu', this);
	        document.removeEventListener('mousedown', this, true);
	    };
	    /**
	     * A message handler invoked on an `'activate-request'` message.
	     */
	    Menu.prototype.onActivateRequest = function (msg) {
	        if (this.isAttached)
	            this.node.focus();
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    Menu.prototype.onUpdateRequest = function (msg) {
	        // TODO - currently, an 'update-request' message is sent to a menu
	        // just before it is opened. This ensures it is current when shown
	        // without needing to subscribe to any commands or keymap signals.
	        // Often, the update will be unnecessary. If it becomes an issue
	        // for performance, the menu can maintain a dirty flag.
	        // Fetch common variables.
	        var items = this._items;
	        var nodes = this._nodes;
	        var renderer = this._renderer;
	        // Update the state of the item nodes.
	        for (var i = 0, n = items.length; i < n; ++i) {
	            renderer.updateItemNode(nodes.at(i), items.at(i));
	        }
	        // Add the active class to the active item.
	        if (this._activeIndex !== -1) {
	            nodes.at(this._activeIndex).classList.add(ACTIVE_CLASS);
	        }
	        // Hide the extra separator nodes.
	        Private.hideExtraSeparators(nodes, items);
	    };
	    /**
	     * A message handler invoked on a `'close-request'` message.
	     */
	    Menu.prototype.onCloseRequest = function (msg) {
	        // Cancel the pending timers.
	        this._cancelOpenTimer();
	        this._cancelCloseTimer();
	        // Reset the active index.
	        this.activeIndex = -1;
	        // Close any open child menu.
	        var childMenu = this._childMenu;
	        if (childMenu) {
	            this._childIndex = -1;
	            this._childMenu = null;
	            childMenu._parentMenu = null;
	            childMenu.close();
	        }
	        // Remove this menu from its parent and activate the parent.
	        var parentMenu = this._parentMenu;
	        if (parentMenu) {
	            this._parentMenu = null;
	            parentMenu._cancelOpenTimer();
	            parentMenu._cancelCloseTimer();
	            parentMenu._childIndex = -1;
	            parentMenu._childMenu = null;
	            parentMenu.activate();
	        }
	        // Emit the `aboutToClose` signal if the menu is attached.
	        if (this.isAttached) {
	            this.aboutToClose.emit(void 0);
	        }
	        // Finish closing the menu.
	        _super.prototype.onCloseRequest.call(this, msg);
	    };
	    /**
	     * Handle the `'keydown'` event for the menu.
	     *
	     * #### Notes
	     * This listener is attached to the menu node.
	     */
	    Menu.prototype._evtKeyDown = function (event) {
	        // A menu handles all keydown events.
	        event.preventDefault();
	        event.stopPropagation();
	        // Fetch the key code for the event.
	        var kc = event.keyCode;
	        // Enter
	        if (kc === 13) {
	            this.triggerActiveItem();
	            return;
	        }
	        // Escape
	        if (kc === 27) {
	            this.close();
	            return;
	        }
	        // Left Arrow
	        if (kc === 37) {
	            if (this._parentMenu) {
	                this.close();
	            }
	            else {
	                this.menuRequested.emit('previous');
	            }
	            return;
	        }
	        // Up Arrow
	        if (kc === 38) {
	            this.activatePreviousItem();
	            return;
	        }
	        // Right Arrow
	        if (kc === 39) {
	            var item = this.activeItem;
	            if (item && item.type === 'submenu') {
	                this.triggerActiveItem();
	            }
	            else {
	                this.rootMenu.menuRequested.emit('next');
	            }
	            return;
	        }
	        // Down Arrow
	        if (kc === 40) {
	            this.activateNextItem();
	            return;
	        }
	        // The following code activates an item by mnemonic.
	        // Get the pressed key character for the current layout.
	        var key = this._keymap.layout.keyForKeydownEvent(event);
	        // Bail if the key is not valid for the current layout.
	        if (!key) {
	            return;
	        }
	        // Normalize the case of the key.
	        key = key.toUpperCase();
	        // Setup the storage for the search results.
	        var mnIndex = -1;
	        var autoIndex = -1;
	        var mnMultiple = false;
	        // Search for the best mnemonic item. This searches the menu items
	        // starting at the active index and finds the following:
	        //   - the index of the first matching mnemonic item
	        //   - whether there are multiple matching mnemonic items
	        //   - the index of the first item with no mnemonic, but
	        //     which has a matching first character
	        var n = this._items.length;
	        var j = this._activeIndex + 1;
	        for (var i = 0; i < n; ++i) {
	            var k = (i + j) % n;
	            var item = this._items.at(k);
	            if (item.type === 'separator' || !item.isEnabled || !item.isVisible) {
	                continue;
	            }
	            var label = item.label;
	            if (label.length === 0) {
	                continue;
	            }
	            var mn = item.mnemonic;
	            if (mn >= 0 && mn < label.length) {
	                if (label[mn].toUpperCase() === key) {
	                    if (mnIndex === -1) {
	                        mnIndex = k;
	                    }
	                    else {
	                        mnMultiple = true;
	                    }
	                }
	            }
	            else if (autoIndex === -1) {
	                if (label[0].toUpperCase() === key) {
	                    autoIndex = k;
	                }
	            }
	        }
	        // Handle the requested mnemonic based on the search results.
	        // If exactly one mnemonic is matched, that item is triggered.
	        // Otherwise, the next mnemonic is activated if available,
	        // followed by the auto mnemonic if available.
	        if (mnIndex !== -1 && !mnMultiple) {
	            this.activeIndex = mnIndex;
	            this.triggerActiveItem();
	        }
	        else if (mnIndex !== -1) {
	            this.activeIndex = mnIndex;
	        }
	        else if (autoIndex !== -1) {
	            this.activeIndex = autoIndex;
	        }
	    };
	    /**
	     * Handle the `'mouseup'` event for the menu.
	     *
	     * #### Notes
	     * This listener is attached to the menu node.
	     */
	    Menu.prototype._evtMouseUp = function (event) {
	        if (event.button !== 0) {
	            return;
	        }
	        event.preventDefault();
	        event.stopPropagation();
	        this.triggerActiveItem();
	    };
	    /**
	     * Handle the `'mousemove'` event for the menu.
	     *
	     * #### Notes
	     * This listener is attached to the menu node.
	     */
	    Menu.prototype._evtMouseMove = function (event) {
	        // Hit test the item nodes for the item under the mouse.
	        var x = event.clientX;
	        var y = event.clientY;
	        var i = searching_1.findIndex(this._nodes, function (node) { return query_1.hitTest(node, x, y); });
	        // Bail early if the mouse is already over the active index.
	        if (i === this._activeIndex) {
	            return;
	        }
	        // Update and coerce the active index.
	        this.activeIndex = i;
	        i = this.activeIndex;
	        // If the index is the current child index, cancel the timers.
	        if (i === this._childIndex) {
	            this._cancelOpenTimer();
	            this._cancelCloseTimer();
	            return;
	        }
	        // If a child menu is currently open, start the close timer.
	        if (this._childIndex !== -1) {
	            this._startCloseTimer();
	        }
	        // Cancel the open timer to give a full delay for opening.
	        this._cancelOpenTimer();
	        // Bail if the active item is not a valid submenu item.
	        var item = this.activeItem;
	        if (!item || item.type !== 'submenu' || !item.menu) {
	            return;
	        }
	        // Start the open timer to open the active item submenu.
	        this._startOpenTimer();
	    };
	    /**
	     * Handle the `'mouseenter'` event for the menu.
	     *
	     * #### Notes
	     * This listener is attached to the menu node.
	     */
	    Menu.prototype._evtMouseEnter = function (event) {
	        // Synchronize the active ancestor items.
	        for (var menu = this._parentMenu; menu; menu = menu._parentMenu) {
	            menu._cancelOpenTimer();
	            menu._cancelCloseTimer();
	            menu.activeIndex = menu._childIndex;
	        }
	    };
	    /**
	     * Handle the `'mouseleave'` event for the menu.
	     *
	     * #### Notes
	     * This listener is attached to the menu node.
	     */
	    Menu.prototype._evtMouseLeave = function (event) {
	        // Cancel any pending submenu opening.
	        this._cancelOpenTimer();
	        // If there is no open child menu, just reset the active index.
	        if (!this._childMenu) {
	            this.activeIndex = -1;
	            return;
	        }
	        // If the mouse is over the child menu, cancel the close timer.
	        if (query_1.hitTest(this._childMenu.node, event.clientX, event.clientY)) {
	            this._cancelCloseTimer();
	            return;
	        }
	        // Otherwise, reset the active index and start the close timer.
	        this.activeIndex = -1;
	        this._startCloseTimer();
	    };
	    /**
	     * Handle the `'mousedown'` event for the menu.
	     *
	     * #### Notes
	     * This listener is attached to the document node.
	     */
	    Menu.prototype._evtMouseDown = function (event) {
	        // Bail if the menu is not a root menu.
	        if (this._parentMenu) {
	            return;
	        }
	        // The mouse button which is pressed is irrelevant. If the press
	        // is not on a menu, the entire hierarchy is closed and the event
	        // is allowed to propagate. This allows other code to act on the
	        // event, such as focusing the clicked element.
	        if (Private.hitTestMenus(this, event.clientX, event.clientY)) {
	            event.preventDefault();
	            event.stopPropagation();
	        }
	        else {
	            this.close();
	        }
	    };
	    /**
	     * Open the child menu at the active index immediately.
	     *
	     * If a different child menu is already open, it will be closed,
	     * even if the active item is not a valid submenu.
	     */
	    Menu.prototype._openChildMenu = function (activateFirst) {
	        if (activateFirst === void 0) { activateFirst = false; }
	        // If the item is not a valid submenu, close the child menu.
	        var item = this.activeItem;
	        if (!item || item.type !== 'submenu' || !item.menu) {
	            this._closeChildMenu();
	            return;
	        }
	        // Do nothing if the child menu will not change.
	        var menu = item.menu;
	        if (menu === this._childMenu) {
	            return;
	        }
	        // Ensure the current child menu is closed.
	        this._closeChildMenu();
	        // Update the private child state.
	        this._childMenu = menu;
	        this._childIndex = this._activeIndex;
	        // Set the parent menu reference for the child.
	        menu._parentMenu = this;
	        // Open the submenu at the active node.
	        Private.openSubmenu(menu, this._nodes.at(this._activeIndex));
	        // Activate the first item if desired.
	        if (activateFirst) {
	            menu.activeIndex = -1;
	            menu.activateNextItem();
	        }
	        // Activate the child menu.
	        menu.activate();
	    };
	    /**
	     * Close the child menu immediately.
	     *
	     * This is a no-op if a child menu is not open.
	     */
	    Menu.prototype._closeChildMenu = function () {
	        if (this._childMenu) {
	            this._childMenu.close();
	        }
	    };
	    /**
	     * Start the open timer, unless it is already pending.
	     */
	    Menu.prototype._startOpenTimer = function () {
	        var _this = this;
	        if (this._openTimerID === 0) {
	            this._openTimerID = setTimeout(function () {
	                _this._openTimerID = 0;
	                _this._openChildMenu();
	            }, TIMER_DELAY);
	        }
	    };
	    /**
	     * Start the close timer, unless it is already pending.
	     */
	    Menu.prototype._startCloseTimer = function () {
	        var _this = this;
	        if (this._closeTimerID === 0) {
	            this._closeTimerID = setTimeout(function () {
	                _this._closeTimerID = 0;
	                _this._closeChildMenu();
	            }, TIMER_DELAY);
	        }
	    };
	    /**
	     * Cancel the open timer, if the timer is pending.
	     */
	    Menu.prototype._cancelOpenTimer = function () {
	        if (this._openTimerID !== 0) {
	            clearTimeout(this._openTimerID);
	            this._openTimerID = 0;
	        }
	    };
	    /**
	     * Cancel the close timer, if the timer is pending.
	     */
	    Menu.prototype._cancelCloseTimer = function () {
	        if (this._closeTimerID !== 0) {
	            clearTimeout(this._closeTimerID);
	            this._closeTimerID = 0;
	        }
	    };
	    return Menu;
	}(widget_1.Widget));
	exports.Menu = Menu;
	// Define the signals for the `Menu` class.
	signaling_1.defineSignal(Menu.prototype, 'aboutToClose');
	signaling_1.defineSignal(Menu.prototype, 'menuRequested');
	/**
	 * The namespace for the `Menu` class statics.
	 */
	var Menu;
	(function (Menu) {
	    /**
	     * The default implementation of `IRenderer`.
	     */
	    var Renderer = (function () {
	        function Renderer() {
	        }
	        /**
	         * Create a node for a menu item.
	         *
	         * @returns A new node for a menu item.
	         */
	        Renderer.prototype.createItemNode = function () {
	            var node = document.createElement('li');
	            var icon = document.createElement('div');
	            var label = document.createElement('div');
	            var shortcut = document.createElement('div');
	            var submenu = document.createElement('div');
	            node.className = ITEM_CLASS;
	            icon.className = ICON_CLASS;
	            label.className = LABEL_CLASS;
	            shortcut.className = SHORTCUT_CLASS;
	            submenu.className = SUBMENU_ICON_CLASS;
	            node.appendChild(icon);
	            node.appendChild(label);
	            node.appendChild(shortcut);
	            node.appendChild(submenu);
	            return node;
	        };
	        /**
	         * Update an item node to reflect the state of a menu item.
	         *
	         * @param node - A node created by a call to `createItemNode`.
	         *
	         * @param item - The menu item holding the data for the node.
	         */
	        Renderer.prototype.updateItemNode = function (node, item) {
	            // Setup the initial item class.
	            var itemClass = ITEM_CLASS;
	            // Add the item type to the item class.
	            switch (item.type) {
	                case 'command':
	                    itemClass += " " + COMMAND_TYPE_CLASS;
	                    break;
	                case 'submenu':
	                    itemClass += " " + SUBMENU_TYPE_CLASS;
	                    break;
	                case 'separator':
	                    itemClass += " " + SEPARATOR_TYPE_CLASS;
	                    break;
	            }
	            // Add the boolean states to the item class.
	            if (!item.isEnabled) {
	                itemClass += " " + DISABLED_CLASS;
	            }
	            if (item.isToggled) {
	                itemClass += " " + TOGGLED_CLASS;
	            }
	            if (!item.isVisible) {
	                itemClass += " " + HIDDEN_CLASS;
	            }
	            // Add the extra class name(s) to the item class.
	            var extraItemClass = item.className;
	            if (extraItemClass) {
	                itemClass += " " + extraItemClass;
	            }
	            // Setup the initial icon class.
	            var iconClass = ICON_CLASS;
	            // Add the extra class name(s) to the icon class.
	            var extraIconClass = item.icon;
	            if (extraIconClass) {
	                iconClass += " " + extraIconClass;
	            }
	            // Generate the formatted label HTML.
	            var labelHTML = this.formatLabel(item.label, item.mnemonic);
	            // Generate the formatted shortcut text.
	            var shortcutText = this.formatShortcut(item.keyBinding);
	            // Extract the relevant child nodes.
	            var icon = node.firstChild;
	            var label = icon.nextSibling;
	            var shortcut = label.nextSibling;
	            // Set the command ID in the data set.
	            if (item.type === 'command') {
	                node.setAttribute('data-command', item.command);
	            }
	            else {
	                node.removeAttribute('data-command');
	            }
	            // Update the rest of the node state.
	            node.title = item.caption;
	            node.className = itemClass;
	            icon.className = iconClass;
	            label.innerHTML = labelHTML;
	            shortcut.textContent = shortcutText;
	        };
	        /**
	         * Format a label into HTML for display.
	         *
	         * @param label - The label text of interest.
	         *
	         * @param mnemonic - The index of the mnemonic character.
	         *
	         * @return The formatted label HTML for display.
	         */
	        Renderer.prototype.formatLabel = function (label, mnemonic) {
	            // If the index is out of range, do not modify the label.
	            if (mnemonic < 0 || mnemonic >= label.length) {
	                return label;
	            }
	            // Split the label into parts.
	            var pref = label.slice(0, mnemonic);
	            var suff = label.slice(mnemonic + 1);
	            var char = label[mnemonic];
	            // Join the label with the mnemonic span.
	            return pref + "<span class=\"" + MNEMONIC_CLASS + "\">" + char + "</span>" + suff;
	        };
	        /**
	         * Format a key binding into shortcut text for display.
	         *
	         * @param binding - The key binding to format. This may be `null`.
	         *
	         * @returns The formatted shortcut text for display.
	         */
	        Renderer.prototype.formatShortcut = function (binding) {
	            return binding ? binding.keys.map(keymap_1.Keymap.formatKeystroke).join(' ') : '';
	        };
	        return Renderer;
	    }());
	    Menu.Renderer = Renderer;
	    /**
	     * The default `Renderer` instance.
	     */
	    Menu.defaultRenderer = new Renderer();
	})(Menu = exports.Menu || (exports.Menu = {}));
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create the DOM node for a menu.
	     */
	    function createNode() {
	        var node = document.createElement('div');
	        var content = document.createElement('ul');
	        content.className = CONTENT_CLASS;
	        node.appendChild(content);
	        node.tabIndex = -1;
	        return node;
	    }
	    Private.createNode = createNode;
	    /**
	     * Create a new menu item from a keymap, commands, and options.
	     */
	    function createItem(commands, keymap, options) {
	        return new MenuItem(commands, keymap, options);
	    }
	    Private.createItem = createItem;
	    /**
	     * Hit test a menu hierarchy starting at the given root.
	     */
	    function hitTestMenus(menu, x, y) {
	        for (; menu; menu = menu.childMenu) {
	            if (query_1.hitTest(menu.node, x, y))
	                return true;
	        }
	        return false;
	    }
	    Private.hitTestMenus = hitTestMenus;
	    /**
	     * Hide the extra and redundant separator nodes.
	     */
	    function hideExtraSeparators(nodes, items) {
	        // Hide the leading separators.
	        var k1 = 0;
	        var n = items.length;
	        for (; k1 < n; ++k1) {
	            var item = items.at(k1);
	            if (!item.isVisible) {
	                continue;
	            }
	            if (item.type !== 'separator') {
	                break;
	            }
	            nodes.at(k1).classList.add(HIDDEN_CLASS);
	        }
	        // Hide the trailing separators.
	        var k2 = n - 1;
	        for (; k2 >= 0; --k2) {
	            var item = items.at(k2);
	            if (!item.isVisible) {
	                continue;
	            }
	            if (item.type !== 'separator') {
	                break;
	            }
	            nodes.at(k2).classList.add(HIDDEN_CLASS);
	        }
	        // Hide the remaining consecutive separators.
	        var hide = false;
	        while (++k1 < k2) {
	            var item = items.at(k1);
	            if (!item.isVisible) {
	                continue;
	            }
	            if (item.type !== 'separator') {
	                hide = false;
	            }
	            else if (hide) {
	                nodes.at(k1).classList.add(HIDDEN_CLASS);
	            }
	            else {
	                hide = true;
	            }
	        }
	    }
	    Private.hideExtraSeparators = hideExtraSeparators;
	    /**
	     * Open a menu as a root menu at the target location.
	     */
	    function openRootMenu(menu, x, y, forceX, forceY) {
	        // Ensure the menu is updated before opening.
	        messaging_1.sendMessage(menu, widget_1.WidgetMessage.UpdateRequest);
	        // Get the current position and size of the main viewport.
	        var px = window.pageXOffset;
	        var py = window.pageYOffset;
	        var cw = document.documentElement.clientWidth;
	        var ch = document.documentElement.clientHeight;
	        // Compute the maximum allowed height for the menu.
	        var maxHeight = ch - (forceY ? y : 0);
	        // Fetch common variables.
	        var node = menu.node;
	        var style = node.style;
	        // Clear the menu geometry and prepare it for measuring.
	        style.top = '';
	        style.left = '';
	        style.width = '';
	        style.height = '';
	        style.visibility = 'hidden';
	        style.maxHeight = maxHeight + "px";
	        // Attach the menu to the document.
	        widget_1.Widget.attach(menu, document.body);
	        // Expand the menu width by the scrollbar size, if present.
	        if (node.scrollHeight > maxHeight) {
	            style.width = (2 * node.offsetWidth - node.clientWidth) + "px";
	        }
	        // Measure the size of the menu.
	        var _a = node.getBoundingClientRect(), width = _a.width, height = _a.height;
	        // Adjust the X position of the menu to fit on-screen.
	        if (!forceX && (x + width > px + cw)) {
	            x = px + cw - width;
	        }
	        // Adjust the Y position of the menu to fit on-screen.
	        if (!forceY && (y + height > py + ch)) {
	            if (y > py + ch) {
	                y = py + ch - height;
	            }
	            else {
	                y = y - height;
	            }
	        }
	        // Update the position of the menu to the computed position.
	        style.top = Math.max(0, y) + "px";
	        style.left = Math.max(0, x) + "px";
	        // Finally, make the menu visible on the screen.
	        style.visibility = '';
	    }
	    Private.openRootMenu = openRootMenu;
	    /**
	     * Open a menu as a submenu using an item node for positioning.
	     */
	    function openSubmenu(menu, itemNode) {
	        // Ensure the menu is updated before opening.
	        messaging_1.sendMessage(menu, widget_1.WidgetMessage.UpdateRequest);
	        // Get the current position and size of the main viewport.
	        var px = window.pageXOffset;
	        var py = window.pageYOffset;
	        var cw = document.documentElement.clientWidth;
	        var ch = document.documentElement.clientHeight;
	        // Compute the maximum allowed height for the menu.
	        var maxHeight = ch;
	        // Fetch common variables.
	        var node = menu.node;
	        var style = node.style;
	        // Clear the menu geometry and prepare it for measuring.
	        style.top = '';
	        style.left = '';
	        style.width = '';
	        style.height = '';
	        style.visibility = 'hidden';
	        style.maxHeight = maxHeight + "px";
	        // Attach the menu to the document.
	        widget_1.Widget.attach(menu, document.body);
	        // Expand the menu width by the scrollbar size, if present.
	        if (node.scrollHeight > maxHeight) {
	            style.width = (2 * node.offsetWidth - node.clientWidth) + "px";
	        }
	        // Measure the size of the menu.
	        var _a = node.getBoundingClientRect(), width = _a.width, height = _a.height;
	        // Compute the box sizing for the menu.
	        var box = sizing_1.boxSizing(menu.node);
	        // Get the bounding rect for the target item node.
	        var itemRect = itemNode.getBoundingClientRect();
	        // Compute the target X position.
	        var x = itemRect.right - SUBMENU_OVERLAP;
	        // Adjust the X position to fit on the screen.
	        if (x + width > px + cw) {
	            x = itemRect.left + SUBMENU_OVERLAP - width;
	        }
	        // Compute the target Y position.
	        var y = itemRect.top - box.borderTop - box.paddingTop;
	        // Adjust the Y position to fit on the screen.
	        if (y + height > py + ch) {
	            y = itemRect.bottom + box.borderBottom + box.paddingBottom - height;
	        }
	        // Update the position of the menu to the computed position.
	        style.top = Math.max(0, y) + "px";
	        style.left = Math.max(0, x) + "px";
	        // Finally, make the menu visible on the screen.
	        style.visibility = '';
	    }
	    Private.openSubmenu = openSubmenu;
	    /**
	     * A concrete implementation of `Menu.IItem`.
	     */
	    var MenuItem = (function () {
	        /**
	         * Construct a new menu item.
	         */
	        function MenuItem(commands, keymap, options) {
	            this._commands = commands;
	            this._keymap = keymap;
	            this._type = options.type || 'command';
	            this._command = options.command || '';
	            this._args = options.args || null;
	            this._menu = options.menu || null;
	        }
	        Object.defineProperty(MenuItem.prototype, "type", {
	            /**
	             * The type of the menu item.
	             */
	            get: function () {
	                return this._type;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "command", {
	            /**
	             * The command to execute when the item is triggered.
	             */
	            get: function () {
	                return this._command;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "args", {
	            /**
	             * The arguments for the command.
	             */
	            get: function () {
	                return this._args;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "menu", {
	            /**
	             * The menu for a `'submenu'` type item.
	             */
	            get: function () {
	                return this._menu;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "label", {
	            /**
	             * The display label for the menu item.
	             */
	            get: function () {
	                if (this._type === 'command') {
	                    return this._commands.label(this._command, this._args);
	                }
	                if (this._type === 'submenu' && this._menu) {
	                    return this._menu.title.label;
	                }
	                return '';
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "mnemonic", {
	            /**
	             * The mnemonic index for the menu item.
	             */
	            get: function () {
	                if (this._type === 'command') {
	                    return this._commands.mnemonic(this._command, this._args);
	                }
	                if (this._type === 'submenu' && this._menu) {
	                    return this._menu.title.mnemonic;
	                }
	                return -1;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "icon", {
	            /**
	             * The icon class for the menu item.
	             */
	            get: function () {
	                if (this._type === 'command') {
	                    return this._commands.icon(this._command, this._args);
	                }
	                if (this._type === 'submenu' && this._menu) {
	                    return this._menu.title.icon;
	                }
	                return '';
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "caption", {
	            /**
	             * The display caption for the menu item.
	             */
	            get: function () {
	                if (this._type === 'command') {
	                    return this._commands.caption(this._command, this._args);
	                }
	                if (this._type === 'submenu' && this._menu) {
	                    return this._menu.title.caption;
	                }
	                return '';
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "className", {
	            /**
	             * The extra class name for the menu item.
	             */
	            get: function () {
	                if (this._type === 'command') {
	                    return this._commands.className(this._command, this._args);
	                }
	                if (this._type === 'submenu' && this._menu) {
	                    return this._menu.title.className;
	                }
	                return '';
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "isEnabled", {
	            /**
	             * Whether the menu item is enabled.
	             */
	            get: function () {
	                if (this._type === 'command') {
	                    return this._commands.isEnabled(this._command, this._args);
	                }
	                if (this._type === 'submenu') {
	                    return this._menu !== null;
	                }
	                return true;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "isToggled", {
	            /**
	             * Whether the menu item is toggled.
	             */
	            get: function () {
	                if (this._type === 'command') {
	                    return this._commands.isToggled(this._command, this._args);
	                }
	                return false;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "isVisible", {
	            /**
	             * Whether the menu item is visible.
	             */
	            get: function () {
	                if (this._type === 'command') {
	                    return this._commands.isVisible(this._command, this._args);
	                }
	                if (this._type === 'submenu') {
	                    return this._menu !== null;
	                }
	                return true;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(MenuItem.prototype, "keyBinding", {
	            /**
	             * The key binding for the menu item.
	             */
	            get: function () {
	                if (this._type === 'command') {
	                    return this._keymap.findBinding(this._command, this._args);
	                }
	                return null;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        return MenuItem;
	    }());
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/menu.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codeeditor/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/codeeditor/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/editor.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/widget.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/mimetype.js'));
	/* tslint:disable */
	/**
	 * Code editor services token.
	 */
	exports.IEditorServices = new token_1.Token('jupyter.services.editorservices');
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codeeditor/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codeeditor/editor.js **/
jupyter.define('jupyterlab@0.15.1/lib/codeeditor/editor.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var observablestring_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/observablestring.js');
	/**
	 * A namespace for code editors.
	 *
	 * #### Notes
	 * - A code editor is a set of common assumptions which hold for all concrete editors.
	 * - Changes in implementations of the code editor should only be caused by changes in concrete editors.
	 * - Common JLab services which are based on the code editor should belong to `IEditorServices`.
	 */
	var CodeEditor;
	(function (CodeEditor) {
	    /**
	     * Default implementation of `ISelections`.
	     */
	    var Selections = (function () {
	        function Selections() {
	            this._isDisposed = false;
	            this._selections = {};
	        }
	        Object.defineProperty(Selections.prototype, "uuids", {
	            /**
	             * Uuids of all selection owners.
	             */
	            get: function () {
	                return Object.keys(this._selections);
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(Selections.prototype, "isDisposed", {
	            /**
	             * Test whether the selections are disposed.
	             */
	            get: function () {
	                return this._isDisposed;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        /**
	         * Dispose of the resources used by the selections.
	         */
	        Selections.prototype.dispose = function () {
	            if (this.isDisposed) {
	                return;
	            }
	            this._selections = {};
	            this._isDisposed = true;
	            signaling_1.clearSignalData(this);
	        };
	        /**
	         * Gets the selections for all the cursors in ascending order.
	         *
	         * @param uuid - The id of the selection owner.
	         *
	         * @returns A new array of text selections.
	         */
	        Selections.prototype.getSelections = function (uuid) {
	            var selections = this._selections[uuid];
	            return selections ? selections : [];
	        };
	        /**
	         * Sets the selections for all the cursors.
	         *
	         * @param uuid - The id of the selection owner.
	         *
	         * @param newSelections - The replacement text selections.
	         */
	        Selections.prototype.setSelections = function (uuid, newSelections) {
	            var oldSelections = this.getSelections(uuid);
	            this.removeSelections(uuid);
	            this.sortSelections(newSelections);
	            this._selections[uuid] = newSelections;
	            this.changed.emit({ uuid: uuid, oldSelections: oldSelections, newSelections: newSelections });
	        };
	        /**
	         * Sorts given selections in ascending order.
	         */
	        Selections.prototype.sortSelections = function (selections) {
	            selections.sort(function (selection, selection2) {
	                var result = selection.start.line - selection2.start.line;
	                if (result !== 0) {
	                    return result;
	                }
	                return selection.start.column - selection2.start.column;
	            });
	        };
	        /**
	         * Removes selections by the given uuid.
	         */
	        Selections.prototype.removeSelections = function (uuid) {
	            delete this._selections[uuid];
	        };
	        return Selections;
	    }());
	    CodeEditor.Selections = Selections;
	    /**
	     * Define the signals for the `Selections` class.
	     */
	    signaling_1.defineSignal(Selections.prototype, 'changed');
	    /**
	     * The default implementation of the editor model.
	     */
	    var Model = (function () {
	        function Model() {
	            this._value = new observablestring_1.ObservableString();
	            this._selections = new Selections();
	            this._mimetype = 'text/plain';
	            this._isDisposed = false;
	        }
	        Object.defineProperty(Model.prototype, "value", {
	            /**
	             * Get the value of the model.
	             */
	            get: function () {
	                return this._value;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(Model.prototype, "selections", {
	            /**
	             * Get the selections for the model.
	             */
	            get: function () {
	                return this._selections;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(Model.prototype, "mimeType", {
	            /**
	             * A mime type of the model.
	             */
	            get: function () {
	                return this._mimetype;
	            },
	            set: function (newValue) {
	                var oldValue = this._mimetype;
	                if (oldValue === newValue) {
	                    return;
	                }
	                this._mimetype = newValue;
	                this.mimeTypeChanged.emit({
	                    name: 'mimeType',
	                    oldValue: oldValue,
	                    newValue: newValue
	                });
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(Model.prototype, "isDisposed", {
	            /**
	             * Whether the model is disposed.
	             */
	            get: function () {
	                return this._isDisposed;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        /**
	         * Dipose of the resources used by the model.
	         */
	        Model.prototype.dispose = function () {
	            if (this._isDisposed) {
	                return;
	            }
	            this._isDisposed = true;
	            signaling_1.clearSignalData(this);
	            this._selections.dispose();
	            this._value.dispose();
	        };
	        return Model;
	    }());
	    CodeEditor.Model = Model;
	    /**
	     * The signals for the `Model` class.
	     */
	    signaling_1.defineSignal(Model.prototype, 'mimeTypeChanged');
	})(CodeEditor = exports.CodeEditor || (exports.CodeEditor = {}));
	//# sourceMappingURL=editor.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codeeditor/editor.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/observablestring.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/observablestring.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	/**
	 * A concrete implementation of [[IObservableString]]
	 */
	var ObservableString = (function () {
	    /**
	     * Construct a new observable string.
	     */
	    function ObservableString(initialText) {
	        if (initialText === void 0) { initialText = ''; }
	        this._text = '';
	        this._isDisposed = false;
	        this._text = initialText;
	    }
	    Object.defineProperty(ObservableString.prototype, "text", {
	        /**
	         * Get the value of the string.
	         */
	        get: function () {
	            return this._text;
	        },
	        /**
	         * Set the value of the string.
	         */
	        set: function (value) {
	            if (value.length === this._text.length && value === this._text) {
	                return;
	            }
	            this._text = value;
	            this.changed.emit({
	                type: 'set',
	                start: 0,
	                end: value.length,
	                value: value
	            });
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Insert a substring.
	     *
	     * @param index - The starting index.
	     *
	     * @param text - The substring to insert.
	     */
	    ObservableString.prototype.insert = function (index, text) {
	        this._text = this._text.slice(0, index) +
	            text +
	            this._text.slice(index);
	        this.changed.emit({
	            type: 'insert',
	            start: index,
	            end: index + text.length,
	            value: text
	        });
	    };
	    /**
	     * Remove a substring.
	     *
	     * @param start - The starting index.
	     *
	     * @param end - The ending index.
	     */
	    ObservableString.prototype.remove = function (start, end) {
	        var oldValue = this._text.slice(start, end);
	        this._text = this._text.slice(0, start) +
	            this._text.slice(end);
	        this.changed.emit({
	            type: 'remove',
	            start: start,
	            end: end,
	            value: oldValue
	        });
	    };
	    /**
	     * Set the ObservableString to an empty string.
	     */
	    ObservableString.prototype.clear = function () {
	        this.text = '';
	    };
	    Object.defineProperty(ObservableString.prototype, "isDisposed", {
	        /**
	         * Test whether the string has been disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the string.
	     */
	    ObservableString.prototype.dispose = function () {
	        if (this._isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        signaling_1.clearSignalData(this);
	        this.clear();
	    };
	    return ObservableString;
	}());
	exports.ObservableString = ObservableString;
	// Define the signals for the `ObservableString` class.
	signaling_1.defineSignal(ObservableString.prototype, 'changed');
	//# sourceMappingURL=observablestring.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/observablestring.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codeeditor/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/codeeditor/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	/**
	 * A widget which hosts a code editor.
	 */
	var CodeEditorWidget = (function (_super) {
	    __extends(CodeEditorWidget, _super);
	    /**
	     * Construct a new code editor widget.
	     */
	    function CodeEditorWidget(options) {
	        _super.call(this);
	        this._editor = null;
	        this._needsRefresh = true;
	        this._needsResize = false;
	        this._resizing = -1;
	        this._editor = options.factory({
	            host: this.node,
	            model: options.model,
	            uuid: options.uuid,
	            wordWrap: options.wordWrap,
	            readOnly: options.readOnly,
	            selectionStyle: options.selectionStyle
	        });
	    }
	    Object.defineProperty(CodeEditorWidget.prototype, "editor", {
	        /**
	         * Get the editor wrapped by the widget.
	         */
	        get: function () {
	            return this._editor;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeEditorWidget.prototype, "model", {
	        /**
	         * Get the model used by the widget.
	         */
	        get: function () {
	            return this._editor.model;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    CodeEditorWidget.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        clearTimeout(this._resizing);
	        _super.prototype.dispose.call(this);
	        this._editor.dispose();
	        this._editor = null;
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    CodeEditorWidget.prototype.onActivateRequest = function (msg) {
	        this._editor.focus();
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    CodeEditorWidget.prototype.onAfterAttach = function (msg) {
	        _super.prototype.onAfterAttach.call(this, msg);
	        this.node.addEventListener('focus', this, true);
	        if (!this.isVisible) {
	            this._needsRefresh = true;
	            return;
	        }
	        this._editor.refresh();
	        this._needsRefresh = false;
	    };
	    /**
	     * Handle `before_detach` messages for the widget.
	     */
	    CodeEditorWidget.prototype.onBeforeDetach = function (msg) {
	        this.node.removeEventListener('focus', this, true);
	    };
	    /**
	     * A message handler invoked on an `'after-show'` message.
	     */
	    CodeEditorWidget.prototype.onAfterShow = function (msg) {
	        if (this._needsRefresh) {
	            this._editor.refresh();
	            this._needsRefresh = false;
	        }
	    };
	    /**
	     * A message handler invoked on an `'resize'` message.
	     */
	    CodeEditorWidget.prototype.onResize = function (msg) {
	        var _this = this;
	        if (msg.width < 0 || msg.height < 0) {
	            if (this._resizing === -1) {
	                this._editor.setSize(null);
	                this._resizing = setTimeout(function () {
	                    if (_this._needsResize) {
	                        _this._editor.setSize(null);
	                        _this._needsResize = false;
	                    }
	                    _this._resizing = -1;
	                }, 500);
	            }
	            else {
	                this._needsResize = true;
	            }
	        }
	        else {
	            this._editor.setSize(msg);
	        }
	        this._needsRefresh = true;
	    };
	    /**
	     * Handle the DOM events for the widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the panel's DOM node. It should
	     * not be called directly by user code.
	     */
	    CodeEditorWidget.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'focus':
	                this._evtFocus(event);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle `focus` events for the widget.
	     */
	    CodeEditorWidget.prototype._evtFocus = function (event) {
	        if (this._needsRefresh) {
	            this._editor.refresh();
	            this._needsRefresh = false;
	        }
	    };
	    return CodeEditorWidget;
	}(widget_1.Widget));
	exports.CodeEditorWidget = CodeEditorWidget;
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codeeditor/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codeeditor/mimetype.js **/
jupyter.define('jupyterlab@0.15.1/lib/codeeditor/mimetype.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * A namespace for `IEditorMimeTypeService`.
	 */
	var IEditorMimeTypeService;
	(function (IEditorMimeTypeService) {
	    /**
	     * The default mime type.
	     */
	    IEditorMimeTypeService.defaultMimeType = 'text/plain';
	})(IEditorMimeTypeService = exports.IEditorMimeTypeService || (exports.IEditorMimeTypeService = {}));
	//# sourceMappingURL=mimetype.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codeeditor/mimetype.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/editorwidget/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/editorwidget/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/editorwidget/widget.js'));
	/**
	 * The command IDs used by the editor plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.lineNumbers = 'editor:line-numbers';
	    CommandIDs.lineWrap = 'editor:line-wrap';
	    CommandIDs.createConsole = 'editor:create-console';
	    CommandIDs.runCode = 'editor:run-code';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/editorwidget/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/editorwidget/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/editorwidget/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var widget_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/widget.js');
	/**
	 * The class name added to a dirty widget.
	 */
	var DIRTY_CLASS = 'jp-mod-dirty';
	/**
	 * The class name added to a jupyter code mirror widget.
	 */
	var EDITOR_CLASS = 'jp-EditorWidget';
	/* tslint:disable */
	/**
	 * The editor tracker token.
	 */
	exports.IEditorTracker = new token_1.Token('jupyter.services.editor-tracker');
	/* tslint:enable */
	/**
	 * A document widget for editors.
	 */
	var EditorWidget = (function (_super) {
	    __extends(EditorWidget, _super);
	    /**
	     * Construct a new editor widget.
	     */
	    function EditorWidget(options) {
	        var _this = this;
	        _super.call(this, {
	            factory: options.factory,
	            model: options.context.model
	        });
	        this.addClass(EDITOR_CLASS);
	        var context = this._context = options.context;
	        this._mimeTypeService = options.mimeTypeService;
	        this.editor.model.value.text = context.model.toString();
	        this._onPathChanged();
	        context.pathChanged.connect(this._onPathChanged, this);
	        context.ready.then(function () {
	            _this._onContextReady();
	        });
	    }
	    Object.defineProperty(EditorWidget.prototype, "context", {
	        /**
	         * Get the context for the editor widget.
	         */
	        get: function () {
	            return this._context;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Handle actions that should be taken when the context is ready.
	     */
	    EditorWidget.prototype._onContextReady = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        var model = this._context.model;
	        var editor = this.editor;
	        var value = editor.model.value;
	        value.text = model.toString();
	        // Prevent the initial loading from disk from being in the editor history.
	        editor.clearHistory();
	        this._handleDirtyState();
	        model.stateChanged.connect(this._onModelStateChanged, this);
	        model.contentChanged.connect(this._onContentChanged, this);
	    };
	    /**
	     * Handle a change to the model state.
	     */
	    EditorWidget.prototype._onModelStateChanged = function (sender, args) {
	        if (args.name === 'dirty') {
	            this._handleDirtyState();
	        }
	    };
	    /**
	     * Handle the dirty state of the model.
	     */
	    EditorWidget.prototype._handleDirtyState = function () {
	        if (this._context.model.dirty) {
	            this.title.className += " " + DIRTY_CLASS;
	        }
	        else {
	            this.title.className = this.title.className.replace(DIRTY_CLASS, '');
	        }
	    };
	    /**
	     * Handle a change in model content.
	     */
	    EditorWidget.prototype._onContentChanged = function () {
	        var value = this.editor.model.value;
	        var old = value.text;
	        var text = this._context.model.toString();
	        if (old !== text) {
	            value.text = text;
	        }
	    };
	    /**
	     * Handle a change to the path.
	     */
	    EditorWidget.prototype._onPathChanged = function () {
	        var editor = this.editor;
	        var path = this._context.path;
	        editor.model.mimeType = this._mimeTypeService.getMimeTypeByFilePath(path);
	        this.title.label = path.split('/').pop();
	    };
	    return EditorWidget;
	}(widget_1.CodeEditorWidget));
	exports.EditorWidget = EditorWidget;
	/**
	 * A widget factory for editors.
	 */
	var EditorWidgetFactory = (function (_super) {
	    __extends(EditorWidgetFactory, _super);
	    /**
	     * Construct a new editor widget factory.
	     */
	    function EditorWidgetFactory(options) {
	        _super.call(this, options.factoryOptions);
	        this._services = options.editorServices;
	    }
	    /**
	     * Create a new widget given a context.
	     */
	    EditorWidgetFactory.prototype.createNewWidget = function (context) {
	        var func = this._services.factoryService.newDocumentEditor;
	        var factory = function (options) {
	            options.lineNumbers = true;
	            options.readOnly = false;
	            options.wordWrap = true;
	            return func(options);
	        };
	        return new EditorWidget({
	            factory: factory,
	            context: context,
	            mimeTypeService: this._services.mimeTypeService
	        });
	    };
	    return EditorWidgetFactory;
	}(docregistry_1.ABCWidgetFactory));
	exports.EditorWidgetFactory = EditorWidgetFactory;
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/editorwidget/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/docregistry/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/docregistry/context.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/docregistry/default.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/docregistry/kernelactions.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/docregistry/kernelselector.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/docregistry/registry.js'));
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/context.js **/
jupyter.define('jupyterlab@0.15.1/lib/docregistry/context.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var docregistry_2 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	/**
	 * An implementation of a document context.
	 *
	 * This class is typically instantiated by the document manger.
	 */
	var Context = (function () {
	    /**
	     * Construct a new document context.
	     */
	    function Context(options) {
	        var _this = this;
	        this._manager = null;
	        this._opener = null;
	        this._model = null;
	        this._path = '';
	        this._session = null;
	        this._factory = null;
	        this._contentsModel = null;
	        this._populatedPromise = new services_1.utils.PromiseDelegate();
	        this._isPopulated = false;
	        this._isReady = false;
	        var manager = this._manager = options.manager;
	        this._factory = options.factory;
	        this._opener = options.opener;
	        this._path = options.path;
	        var ext = docregistry_2.DocumentRegistry.extname(this._path);
	        var lang = this._factory.preferredLanguage(ext);
	        this._model = this._factory.createNew(lang);
	        manager.sessions.runningChanged.connect(this._onSessionsChanged, this);
	        manager.contents.fileChanged.connect(this._onFileChanged, this);
	        this._readyPromise = manager.ready.then(function () {
	            return _this._populatedPromise.promise;
	        });
	    }
	    Object.defineProperty(Context.prototype, "model", {
	        /**
	         * Get the model associated with the document.
	         */
	        get: function () {
	            return this._model;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Context.prototype, "kernel", {
	        /**
	         * The current kernel associated with the document.
	         */
	        get: function () {
	            return this._session ? this._session.kernel : null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Context.prototype, "path", {
	        /**
	         * The current path associated with the document.
	         */
	        get: function () {
	            return this._path;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Context.prototype, "contentsModel", {
	        /**
	         * The current contents model associated with the document
	         *
	         * #### Notes
	         * The model will have an  empty `contents` field.
	         */
	        get: function () {
	            return this._contentsModel;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Context.prototype, "factoryName", {
	        /**
	         * Get the model factory name.
	         *
	         * #### Notes
	         * This is not part of the `IContext` API.
	         */
	        get: function () {
	            return this.isDisposed ? '' : this._factory.name;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Context.prototype, "isDisposed", {
	        /**
	         * Test whether the context is disposed.
	         */
	        get: function () {
	            return this._model === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the context.
	     */
	    Context.prototype.dispose = function () {
	        if (this._model == null) {
	            return;
	        }
	        var model = this._model;
	        var session = this._session;
	        this._model = null;
	        this._session = null;
	        this._manager = null;
	        this._factory = null;
	        model.dispose();
	        if (session) {
	            session.dispose();
	        }
	        this.disposed.emit(void 0);
	        signaling_1.clearSignalData(this);
	    };
	    Object.defineProperty(Context.prototype, "specs", {
	        /**
	         * The kernel spec models
	         */
	        get: function () {
	            return this._manager.specs;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Context.prototype, "isReady", {
	        /**
	         * Whether the context is ready.
	         */
	        get: function () {
	            return this._isReady;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Context.prototype, "ready", {
	        /**
	         * A promise that is fulfilled when the context is ready.
	         */
	        get: function () {
	            return this._readyPromise;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Start the default kernel for the context.
	     *
	     * @returns A promise that resolves with the new kernel.
	     */
	    Context.prototype.startDefaultKernel = function () {
	        var _this = this;
	        return this.ready.then(function () {
	            if (_this.isDisposed) {
	                return;
	            }
	            var model = _this.model;
	            var name = docregistry_1.findKernel(model.defaultKernelName, model.defaultKernelLanguage, _this._manager.specs);
	            return _this.changeKernel({ name: name });
	        });
	    };
	    /**
	     * Change the current kernel associated with the document.
	     */
	    Context.prototype.changeKernel = function (options) {
	        var _this = this;
	        var session = this._session;
	        if (options) {
	            if (session) {
	                return session.changeKernel(options);
	            }
	            else {
	                var path = this._path;
	                var sOptions = {
	                    path: path,
	                    kernelName: options.name,
	                    kernelId: options.id
	                };
	                return this._startSession(sOptions);
	            }
	        }
	        else {
	            if (session) {
	                this._session = null;
	                return session.shutdown().then(function () {
	                    session.dispose();
	                    if (_this.isDisposed) {
	                        return;
	                    }
	                    _this.kernelChanged.emit(null);
	                    return void 0;
	                });
	            }
	            else {
	                return Promise.resolve(void 0);
	            }
	        }
	    };
	    /**
	     * Save the document contents to disk.
	     */
	    Context.prototype.save = function () {
	        var _this = this;
	        var model = this._model;
	        var path = this._path;
	        if (model.readOnly) {
	            return Promise.reject(new Error('Read only'));
	        }
	        var content;
	        if (this._factory.fileFormat === 'json') {
	            content = model.toJSON();
	        }
	        else {
	            content = model.toString();
	        }
	        var options = {
	            type: this._factory.contentType,
	            format: this._factory.fileFormat,
	            content: content
	        };
	        var promise = this._manager.contents.save(path, options);
	        return promise.then(function (value) {
	            if (_this.isDisposed) {
	                return;
	            }
	            model.dirty = false;
	            _this._updateContentsModel(value);
	            if (!_this._isPopulated) {
	                return _this._populate();
	            }
	        }).catch(function (err) {
	            dialog_1.showDialog({
	                title: 'File Save Error',
	                body: err.xhr.responseText,
	                buttons: [dialog_1.okButton]
	            });
	        });
	    };
	    /**
	     * Save the document to a different path chosen by the user.
	     */
	    Context.prototype.saveAs = function () {
	        var _this = this;
	        return Private.getSavePath(this._path).then(function (newPath) {
	            if (_this.isDisposed || !newPath) {
	                return;
	            }
	            _this._path = newPath;
	            var session = _this._session;
	            if (session) {
	                var options = {
	                    path: newPath,
	                    kernelId: session.kernel.id,
	                    kernelName: session.kernel.name
	                };
	                return _this._startSession(options).then(function () {
	                    if (_this.isDisposed) {
	                        return;
	                    }
	                    return _this.save();
	                });
	            }
	            return _this.save();
	        });
	    };
	    /**
	     * Revert the document contents to disk contents.
	     */
	    Context.prototype.revert = function () {
	        var _this = this;
	        var opts = {
	            format: this._factory.fileFormat,
	            type: this._factory.contentType,
	            content: true
	        };
	        var path = this._path;
	        var model = this._model;
	        return this._manager.contents.get(path, opts).then(function (contents) {
	            if (_this.isDisposed) {
	                return;
	            }
	            if (contents.format === 'json') {
	                model.fromJSON(contents.content);
	            }
	            else {
	                model.fromString(contents.content);
	            }
	            _this._updateContentsModel(contents);
	            model.dirty = false;
	            if (!_this._isPopulated) {
	                return _this._populate();
	            }
	        }).catch(function (err) {
	            dialog_1.showDialog({
	                title: 'File Load Error',
	                body: err.xhr.responseText,
	                buttons: [dialog_1.okButton]
	            });
	        });
	    };
	    /**
	     * Create a checkpoint for the file.
	     */
	    Context.prototype.createCheckpoint = function () {
	        return this._manager.contents.createCheckpoint(this._path);
	    };
	    /**
	     * Delete a checkpoint for the file.
	     */
	    Context.prototype.deleteCheckpoint = function (checkpointId) {
	        return this._manager.contents.deleteCheckpoint(this._path, checkpointId);
	    };
	    /**
	     * Restore the file to a known checkpoint state.
	     */
	    Context.prototype.restoreCheckpoint = function (checkpointId) {
	        var _this = this;
	        var contents = this._manager.contents;
	        var path = this._path;
	        if (checkpointId) {
	            return contents.restoreCheckpoint(path, checkpointId);
	        }
	        return this.listCheckpoints().then(function (checkpoints) {
	            if (_this.isDisposed || !checkpoints.length) {
	                return;
	            }
	            checkpointId = checkpoints[checkpoints.length - 1].id;
	            return contents.restoreCheckpoint(path, checkpointId);
	        });
	    };
	    /**
	     * List available checkpoints for a file.
	     */
	    Context.prototype.listCheckpoints = function () {
	        return this._manager.contents.listCheckpoints(this._path);
	    };
	    /**
	     * Resolve a relative url to a correct server path.
	     */
	    Context.prototype.resolveUrl = function (url) {
	        // Ignore urls that have a protocol.
	        if (services_1.utils.urlParse(url).protocol || url.indexOf('//') === 0) {
	            return Promise.resolve(url);
	        }
	        var cwd = services_1.ContentsManager.dirname(this._path);
	        var path = services_1.ContentsManager.getAbsolutePath(url, cwd);
	        return Promise.resolve(path);
	    };
	    /**
	     * Get the download url of a given absolute server path.
	     */
	    Context.prototype.getDownloadUrl = function (path) {
	        // Ignore urls that have a protocol.
	        if (services_1.utils.urlParse(path).protocol || path.indexOf('//') === 0) {
	            return Promise.resolve(path);
	        }
	        return this._manager.contents.getDownloadUrl(path);
	    };
	    /**
	     * Add a sibling widget to the document manager.
	     */
	    Context.prototype.addSibling = function (widget) {
	        var opener = this._opener;
	        if (opener) {
	            opener(widget);
	        }
	        return new disposable_1.DisposableDelegate(function () {
	            widget.close();
	        });
	    };
	    /**
	     * Handle a change on the contents manager.
	     */
	    Context.prototype._onFileChanged = function (sender, change) {
	        if (change.type !== 'rename') {
	            return;
	        }
	        if (change.oldValue.path === this._path) {
	            if (this._session) {
	                this._session.rename(change.newValue.path);
	            }
	            else {
	                this._path = change.newValue.path;
	                this.pathChanged.emit(this._path);
	            }
	        }
	    };
	    /**
	     * Start a session and set up its signals.
	     */
	    Context.prototype._startSession = function (options) {
	        var _this = this;
	        return this._manager.sessions.startNew(options).then(function (session) {
	            if (_this.isDisposed) {
	                return;
	            }
	            if (_this._session) {
	                _this._session.dispose();
	            }
	            _this._session = session;
	            _this.kernelChanged.emit(session.kernel);
	            session.pathChanged.connect(_this._onSessionPathChanged, _this);
	            session.kernelChanged.connect(_this._onKernelChanged, _this);
	            return session.kernel;
	        }).catch(function (err) {
	            var response = JSON.parse(err.xhr.response);
	            var body = document.createElement('pre');
	            body.textContent = response['traceback'];
	            dialog_1.showDialog({
	                title: 'Error Starting Kernel',
	                body: body,
	                buttons: [dialog_1.okButton]
	            });
	            return Promise.reject(err);
	        });
	    };
	    /**
	     * Handle a change to a session path.
	     */
	    Context.prototype._onSessionPathChanged = function (sender, path) {
	        if (path !== this._path) {
	            this._path = path;
	            this.pathChanged.emit(path);
	        }
	    };
	    /**
	     * Handle a change to the kernel.
	     */
	    Context.prototype._onKernelChanged = function (sender) {
	        this.kernelChanged.emit(sender.kernel);
	    };
	    /**
	     * Update our contents model, without the content.
	     */
	    Context.prototype._updateContentsModel = function (model) {
	        var newModel = {
	            path: model.path,
	            name: model.name,
	            type: model.type,
	            writable: model.writable,
	            created: model.created,
	            last_modified: model.last_modified,
	            mimetype: model.mimetype,
	            format: model.format
	        };
	        var mod = this._contentsModel ? this._contentsModel.last_modified : null;
	        this._contentsModel = newModel;
	        if (!mod || newModel.last_modified !== mod) {
	            this.fileChanged.emit(newModel);
	        }
	    };
	    /**
	     * Handle a change to the running sessions.
	     */
	    Context.prototype._onSessionsChanged = function (sender, models) {
	        var session = this._session;
	        if (!session) {
	            return;
	        }
	        var index = searching_1.findIndex(models, function (model) { return model.id === session.id; });
	        if (index === -1) {
	            session.dispose();
	            this._session = null;
	            this.kernelChanged.emit(null);
	        }
	    };
	    /**
	     * Handle an initial population.
	     */
	    Context.prototype._populate = function () {
	        var _this = this;
	        this._isPopulated = true;
	        // Add a checkpoint if none exists.
	        return this.listCheckpoints().then(function (checkpoints) {
	            if (!_this.isDisposed && !checkpoints) {
	                return _this.createCheckpoint();
	            }
	        }).then(function () {
	            if (_this.isDisposed) {
	                return;
	            }
	            _this._isReady = true;
	            _this._populatedPromise.resolve(void 0);
	        });
	    };
	    return Context;
	}());
	exports.Context = Context;
	// Define the signals for the `Context` class.
	signaling_1.defineSignal(Context.prototype, 'kernelChanged');
	signaling_1.defineSignal(Context.prototype, 'pathChanged');
	signaling_1.defineSignal(Context.prototype, 'fileChanged');
	signaling_1.defineSignal(Context.prototype, 'disposed');
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Get a new file path from the user.
	     */
	    function getSavePath(path) {
	        var input = document.createElement('input');
	        input.value = path;
	        return dialog_1.showDialog({
	            title: 'Save File As..',
	            body: input,
	            okText: 'SAVE'
	        }).then(function (result) {
	            if (result.text === 'SAVE') {
	                return input.value;
	            }
	        });
	    }
	    Private.getSavePath = getSavePath;
	})(Private || (Private = {}));
	//# sourceMappingURL=context.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/context.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/dialog.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/dialog.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to dialog instances.
	 */
	var DIALOG_CLASS = 'jp-Dialog';
	/**
	 * The class name added to dialog content node.
	 */
	var CONTENT_CLASS = 'jp-Dialog-content';
	/**
	 * The class name added to dialog header node.
	 */
	var HEADER_CLASS = 'jp-Dialog-header';
	/**
	 * The class name added to dialog title node.
	 */
	var TITLE_CLASS = 'jp-Dialog-title';
	/**
	 * The class name added to dialog body node.
	 */
	var BODY_CLASS = 'jp-Dialog-body';
	/**
	 * The class name added to a dialog body content node.
	 */
	var BODY_CONTENT_CLASS = 'jp-Dialog-bodyContent';
	/**
	 * The class name added to a dialog content node.
	 */
	var FOOTER_CLASS = 'jp-Dialog-footer';
	/**
	 * The class name added to a dialog button node.
	 */
	var BUTTON_CLASS = 'jp-Dialog-button';
	/**
	 * The class name added to a dialog button icon node.
	 */
	var BUTTON_ICON_CLASS = 'jp-Dialog-buttonIcon';
	/**
	 * The class name added to a dialog button text node.
	 */
	var BUTTON_TEXT_CLASS = 'jp-Dialog-buttonText';
	/*
	 * The class name added to dialog Confirm buttons.
	 */
	var OK_BUTTON_CLASS = 'jp-Dialog-okButton';
	/**
	 * The class name added to dialog Cancel buttons.
	 */
	var CANCEL_BUTTON_CLASS = 'jp-Dialog-cancelButton';
	/**
	 * The class name added to dialog Warning buttons.
	 */
	var WARNING_BUTTON_CLASS = 'jp-Dialog-warningButton';
	/**
	 * The class name added to dialog input field wrappers.
	 */
	var INPUT_WRAPPER_CLASS = 'jp-Dialog-inputWrapper';
	/**
	 * The class name added to dialog input fields.
	 */
	var INPUT_CLASS = 'jp-Dialog-input';
	/**
	 * The class name added to dialog select wrappers.
	 */
	var SELECT_WRAPPER_CLASS = 'jp-Dialog-selectWrapper';
	/**
	 * The class name added to dialog select nodes.
	 */
	var SELECT_CLASS = 'jp-Dialog-select';
	/**
	 * The class name added to focused input and select wrappers.
	 */
	var FOCUS_CLASS = 'jp-mod-focused';
	/**
	 * A default confirmation button.
	 */
	exports.okButton = {
	    text: 'OK',
	    className: OK_BUTTON_CLASS
	};
	/**
	 * A default cancel button.
	 */
	exports.cancelButton = {
	    text: 'CANCEL',
	    className: CANCEL_BUTTON_CLASS
	};
	/**
	 * A default delete button.
	 */
	exports.deleteButton = {
	    text: 'DELETE',
	    className: WARNING_BUTTON_CLASS
	};
	/**
	 * A default warn button.
	 */
	exports.warnButton = {
	    text: 'OK',
	    className: WARNING_BUTTON_CLASS
	};
	/**
	 * Create a dialog and show it.
	 *
	 * @param options - The dialog setup options.
	 *
	 * @returns A promise that resolves to the button item that was selected.
	 */
	function showDialog(options) {
	    options = options || {};
	    var host = options.host || document.body;
	    options.host = host;
	    options.body = options.body || '';
	    // NOTE: This code assumes only one dialog is shown at the time:
	    exports.okButton.text = options.okText ? options.okText : 'OK';
	    options.buttons = options.buttons || [exports.cancelButton, exports.okButton];
	    if (!options.buttons.length) {
	        options.buttons = [exports.okButton];
	    }
	    if (!(options.body instanceof widget_1.Widget)) {
	        options.body = createDialogBody(options.body);
	    }
	    return new Promise(function (resolve, reject) {
	        var dialog = new Dialog(options, resolve, reject);
	        widget_1.Widget.attach(dialog, host);
	    });
	}
	exports.showDialog = showDialog;
	/**
	 * A dialog panel.
	 */
	var Dialog = (function (_super) {
	    __extends(Dialog, _super);
	    /**
	     * Create a dialog panel instance.
	     *
	     * @param options - The dialog setup options.
	     *
	     * @param resolve - The function that resolves the dialog promise.
	     *
	     * @param reject - The function that rejects the dialog promise.
	     *
	     * #### Notes
	     * Currently the dialog resolves with `cancelButton` rather than
	     * rejecting the dialog promise.
	     */
	    function Dialog(options, resolve, reject) {
	        _super.call(this);
	        if (!(options.body instanceof widget_1.Widget)) {
	            throw 'A widget dialog can only be created with a widget as its body.';
	        }
	        this.resolve = resolve;
	        this.reject = reject;
	        // Create the dialog nodes (except for the buttons).
	        var content = new panel_1.Panel();
	        var header = new widget_1.Widget({ node: document.createElement('div') });
	        var body = new panel_1.Panel();
	        var footer = new widget_1.Widget({ node: document.createElement('div') });
	        var title = document.createElement('span');
	        this.addClass(DIALOG_CLASS);
	        if (options.dialogClass) {
	            this.addClass(options.dialogClass);
	        }
	        content.addClass(CONTENT_CLASS);
	        header.addClass(HEADER_CLASS);
	        body.addClass(BODY_CLASS);
	        footer.addClass(FOOTER_CLASS);
	        title.className = TITLE_CLASS;
	        this.addWidget(content);
	        content.addWidget(header);
	        content.addWidget(body);
	        content.addWidget(footer);
	        header.node.appendChild(title);
	        // Populate the nodes.
	        title.textContent = options.title || '';
	        var child = options.body;
	        child.addClass(BODY_CONTENT_CLASS);
	        body.addWidget(child);
	        this._buttons = options.buttons.slice();
	        this._buttonNodes = options.buttons.map(createButton);
	        this._buttonNodes.map(function (buttonNode) {
	            footer.node.appendChild(buttonNode);
	        });
	        var primary = options.primary || this.lastButtonNode;
	        if (typeof primary === 'number') {
	            primary = this._buttonNodes[primary];
	        }
	        this._primary = primary;
	    }
	    Object.defineProperty(Dialog.prototype, "lastButtonNode", {
	        /**
	         * Get the last button node.
	         */
	        get: function () {
	            return this._buttonNodes[this._buttons.length - 1];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Handle the DOM events for the directory listing.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the panel's DOM node. It should
	     * not be called directly by user code.
	     */
	    Dialog.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'keydown':
	                this._evtKeydown(event);
	                break;
	            case 'contextmenu':
	                this._evtContextMenu(event);
	                break;
	            case 'click':
	                this._evtClick(event);
	                break;
	            case 'focus':
	                this._evtFocus(event);
	                break;
	            case 'blur':
	                this._evtBlur(event);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle an `'after-attach'` message to the widget.
	     *
	     * @param msg - The `'after-attach'` message
	     */
	    Dialog.prototype.onAfterAttach = function (msg) {
	        var node = this.node;
	        node.addEventListener('keydown', this, true);
	        node.addEventListener('contextmenu', this, true);
	        node.addEventListener('click', this, true);
	        document.addEventListener('focus', this, true);
	        document.addEventListener('blur', this, true);
	        this._original = document.activeElement;
	        this._primary.focus();
	    };
	    /**
	     * Handle a `'before-detach'` message to the widget.
	     *
	     * @param msg - The `'after-attach'` message
	     */
	    Dialog.prototype.onBeforeDetach = function (msg) {
	        var node = this.node;
	        node.removeEventListener('keydown', this, true);
	        node.removeEventListener('contextmenu', this, true);
	        node.removeEventListener('click', this, true);
	        document.removeEventListener('focus', this, true);
	        document.removeEventListener('blur', this, true);
	        this._original.focus();
	    };
	    /**
	     * Handle the `'click'` event for a dialog button.
	     *
	     * @param event - The DOM event sent to the widget
	     */
	    Dialog.prototype._evtClick = function (event) {
	        var content = this.node.getElementsByClassName(CONTENT_CLASS)[0];
	        if (!content.contains(event.target)) {
	            this.close();
	            this.resolve(exports.cancelButton);
	            event.stopPropagation();
	            return;
	        }
	        for (var _i = 0, _a = this._buttonNodes; _i < _a.length; _i++) {
	            var buttonNode = _a[_i];
	            if (buttonNode.contains(event.target)) {
	                this.close();
	                var button = this._buttons[this._buttonNodes.indexOf(buttonNode)];
	                this.resolve(button);
	            }
	        }
	    };
	    /**
	     * Handle the `'keydown'` event for the widget.
	     *
	     * @param event - The DOM event sent to the widget
	     */
	    Dialog.prototype._evtKeydown = function (event) {
	        // Check for escape key
	        switch (event.keyCode) {
	            case 27:
	                this.close();
	                this.resolve(exports.cancelButton);
	                break;
	            case 9:
	                // Handle a tab on the last button.
	                if (document.activeElement === this.lastButtonNode && !event.shiftKey) {
	                    event.stopPropagation();
	                    event.preventDefault();
	                    if (!this._first) {
	                        this._findFirst();
	                    }
	                    this._first.focus();
	                }
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle the `'focus'` event for the widget.
	     *
	     * @param event - The DOM event sent to the widget
	     */
	    Dialog.prototype._evtFocus = function (event) {
	        var target = event.target;
	        if (!this.node.contains(target)) {
	            event.stopPropagation();
	            this.lastButtonNode.focus();
	        }
	        else {
	            // Add the focus modifier class to input and select wrappers.
	            if (target.classList.contains(INPUT_CLASS) ||
	                target.classList.contains(SELECT_CLASS)) {
	                var parent_1 = target.parentElement;
	                parent_1.classList.add(FOCUS_CLASS);
	            }
	        }
	    };
	    /**
	     * Handle the `'blur'` event for the widget.
	     *
	     * @param event - The DOM event sent to the widget
	     */
	    Dialog.prototype._evtBlur = function (event) {
	        var target = event.target;
	        // Remove the focus modifier class to input and select wrappers.
	        if (target.classList.contains(INPUT_CLASS) ||
	            target.classList.contains(SELECT_CLASS)) {
	            var parent_2 = target.parentElement;
	            parent_2.classList.remove(FOCUS_CLASS);
	        }
	    };
	    /**
	     * Handle the `'contextmenu'` event for the widget.
	     *
	     * @param event - The DOM event sent to the widget
	     */
	    Dialog.prototype._evtContextMenu = function (event) {
	        event.preventDefault();
	        event.stopPropagation();
	    };
	    /**
	     * Find the first focusable item in the dialog.
	     */
	    Dialog.prototype._findFirst = function () {
	        var candidateSelectors = [
	            'input',
	            'select',
	            'a[href]',
	            'textarea',
	            'button',
	            '[tabindex]',
	        ].join(',');
	        this._first = this.node.querySelectorAll(candidateSelectors)[0];
	    };
	    return Dialog;
	}(panel_1.Panel));
	/**
	 * Create a dialog body widget from a non-widget input.
	 */
	function createDialogBody(body) {
	    var child;
	    if (typeof body === 'string') {
	        child = document.createElement('span');
	        child.innerHTML = body;
	    }
	    else if (body) {
	        child = body;
	        switch (child.tagName) {
	            case 'INPUT':
	                child = wrapInput(child);
	                break;
	            case 'SELECT':
	                child = wrapSelect(child);
	                break;
	            default:
	                child = styleElements(child);
	                break;
	        }
	    }
	    child.classList.add(BODY_CONTENT_CLASS);
	    return new widget_1.Widget({ node: child });
	}
	/**
	 * Style the child elements of a parent element.
	 */
	function styleElements(element) {
	    for (var i = 0; i < element.children.length; i++) {
	        var child = element.children[i];
	        var next = child.nextSibling;
	        switch (child.tagName) {
	            case 'INPUT':
	                child = wrapInput(child);
	                element.insertBefore(child, next);
	                break;
	            case 'SELECT':
	                child = wrapSelect(child);
	                element.insertBefore(child, next);
	                break;
	            default:
	                break;
	        }
	    }
	    return element;
	}
	/**
	 * Create a node for a button item.
	 */
	function createButton(item) {
	    var button = document.createElement('button');
	    button.className = BUTTON_CLASS;
	    button.tabIndex = 0;
	    if (item.className) {
	        button.classList.add(item.className);
	    }
	    var icon = document.createElement('span');
	    icon.className = BUTTON_ICON_CLASS;
	    if (item.icon) {
	        icon.classList.add(item.icon);
	    }
	    var text = document.createElement('span');
	    text.className = BUTTON_TEXT_CLASS;
	    text.textContent = item.text;
	    button.appendChild(icon);
	    button.appendChild(text);
	    return button;
	}
	/**
	 * Wrap and style an input node.
	 */
	function wrapInput(input) {
	    var wrapper = document.createElement('div');
	    wrapper.className = INPUT_WRAPPER_CLASS;
	    wrapper.appendChild(input);
	    input.classList.add(INPUT_CLASS);
	    input.tabIndex = 0;
	    return wrapper;
	}
	/**
	 * Wrap and style a select node.
	 */
	function wrapSelect(select) {
	    var wrapper = document.createElement('div');
	    wrapper.className = SELECT_WRAPPER_CLASS;
	    wrapper.appendChild(select);
	    select.classList.add(SELECT_CLASS);
	    select.tabIndex = 0;
	    return wrapper;
	}
	//# sourceMappingURL=dialog.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/dialog.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/default.js **/
jupyter.define('jupyterlab@0.15.1/lib/docregistry/default.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var CodeMirror = __jupyter_require__('codemirror@^5.20.2/lib/codemirror.js');
	__jupyter_require__('codemirror@^5.20.2/mode/meta.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var codeeditor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/index.js');
	/**
	 * The default implementation of a document model.
	 */
	var DocumentModel = (function (_super) {
	    __extends(DocumentModel, _super);
	    /**
	     * Construct a new document model.
	     */
	    function DocumentModel(languagePreference) {
	        _super.call(this);
	        this._defaultLang = '';
	        this._dirty = false;
	        this._readOnly = false;
	        this._defaultLang = languagePreference || '';
	        this.value.changed.connect(this._onValueChanged, this);
	    }
	    Object.defineProperty(DocumentModel.prototype, "dirty", {
	        /**
	         * The dirty state of the document.
	         */
	        get: function () {
	            return this._dirty;
	        },
	        set: function (newValue) {
	            if (newValue === this._dirty) {
	                return;
	            }
	            var oldValue = this._dirty;
	            this._dirty = newValue;
	            this.stateChanged.emit({ name: 'dirty', oldValue: oldValue, newValue: newValue });
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DocumentModel.prototype, "readOnly", {
	        /**
	         * The read only state of the document.
	         */
	        get: function () {
	            return this._readOnly;
	        },
	        set: function (newValue) {
	            if (newValue === this._readOnly) {
	                return;
	            }
	            var oldValue = this._readOnly;
	            this._readOnly = newValue;
	            this.stateChanged.emit({ name: 'readOnly', oldValue: oldValue, newValue: newValue });
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DocumentModel.prototype, "defaultKernelName", {
	        /**
	         * The default kernel name of the document.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return '';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DocumentModel.prototype, "defaultKernelLanguage", {
	        /**
	         * The default kernel language of the document.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._defaultLang;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Serialize the model to a string.
	     */
	    DocumentModel.prototype.toString = function () {
	        return this.value.text;
	    };
	    /**
	     * Deserialize the model from a string.
	     *
	     * #### Notes
	     * Should emit a [contentChanged] signal.
	     */
	    DocumentModel.prototype.fromString = function (value) {
	        this.value.text = value;
	    };
	    /**
	     * Serialize the model to JSON.
	     */
	    DocumentModel.prototype.toJSON = function () {
	        return JSON.stringify(this.value.text);
	    };
	    /**
	     * Deserialize the model from JSON.
	     *
	     * #### Notes
	     * Should emit a [contentChanged] signal.
	     */
	    DocumentModel.prototype.fromJSON = function (value) {
	        this.fromString(JSON.parse(value));
	    };
	    /**
	     * Handle a change to the observable value.
	     */
	    DocumentModel.prototype._onValueChanged = function (sender, args) {
	        this.contentChanged.emit(void 0);
	        this.dirty = true;
	    };
	    return DocumentModel;
	}(codeeditor_1.CodeEditor.Model));
	exports.DocumentModel = DocumentModel;
	// Define the signals for the `DocumentModel` class.
	signaling_1.defineSignal(DocumentModel.prototype, 'contentChanged');
	signaling_1.defineSignal(DocumentModel.prototype, 'stateChanged');
	/**
	 * An implementation of a model factory for text files.
	 */
	var TextModelFactory = (function () {
	    function TextModelFactory() {
	        this._isDisposed = false;
	    }
	    Object.defineProperty(TextModelFactory.prototype, "name", {
	        /**
	         * The name of the model type.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return 'text';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TextModelFactory.prototype, "contentType", {
	        /**
	         * The type of the file.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return 'file';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TextModelFactory.prototype, "fileFormat", {
	        /**
	         * The format of the file.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return 'text';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TextModelFactory.prototype, "isDisposed", {
	        /**
	         * Get whether the model factory has been disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the model factory.
	     */
	    TextModelFactory.prototype.dispose = function () {
	        this._isDisposed = true;
	    };
	    /**
	     * Create a new model.
	     *
	     * @param languagePreference - An optional kernel language preference.
	     *
	     * @returns A new document model.
	     */
	    TextModelFactory.prototype.createNew = function (languagePreference) {
	        return new DocumentModel(languagePreference);
	    };
	    /**
	     * Get the preferred kernel language given an extension.
	     */
	    TextModelFactory.prototype.preferredLanguage = function (ext) {
	        var mode = CodeMirror.findModeByExtension(ext.slice(1));
	        if (mode) {
	            return mode.mode;
	        }
	    };
	    return TextModelFactory;
	}());
	exports.TextModelFactory = TextModelFactory;
	/**
	 * An implementation of a model factory for base64 files.
	 */
	var Base64ModelFactory = (function (_super) {
	    __extends(Base64ModelFactory, _super);
	    function Base64ModelFactory() {
	        _super.apply(this, arguments);
	    }
	    Object.defineProperty(Base64ModelFactory.prototype, "name", {
	        /**
	         * The name of the model type.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return 'base64';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Base64ModelFactory.prototype, "contentType", {
	        /**
	         * The type of the file.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return 'file';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Base64ModelFactory.prototype, "fileFormat", {
	        /**
	         * The format of the file.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return 'base64';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return Base64ModelFactory;
	}(TextModelFactory));
	exports.Base64ModelFactory = Base64ModelFactory;
	/**
	 * The default implemetation of a widget factory.
	 */
	var ABCWidgetFactory = (function () {
	    /**
	     * Construct a new `ABCWidgetFactory`.
	     */
	    function ABCWidgetFactory(options) {
	        this._isDisposed = false;
	        this._name = options.name;
	        this._defaultFor = options.defaultFor ? options.defaultFor.slice() : [];
	        this._fileExtensions = options.fileExtensions.slice();
	        this._modelName = options.modelName || 'text';
	        this._preferKernel = !!options.preferKernel;
	        this._canStartKernel = !!options.canStartKernel;
	    }
	    Object.defineProperty(ABCWidgetFactory.prototype, "isDisposed", {
	        /**
	         * Get whether the model factory has been disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the document manager.
	     */
	    ABCWidgetFactory.prototype.dispose = function () {
	        this._isDisposed = true;
	    };
	    Object.defineProperty(ABCWidgetFactory.prototype, "name", {
	        /**
	         * The name of the widget to display in dialogs.
	         */
	        get: function () {
	            return this._name;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ABCWidgetFactory.prototype, "fileExtensions", {
	        /**
	         * The file extensions the widget can view.
	         */
	        get: function () {
	            return this._fileExtensions.slice();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ABCWidgetFactory.prototype, "modelName", {
	        /**
	         * The registered name of the model type used to create the widgets.
	         */
	        get: function () {
	            return this._modelName;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ABCWidgetFactory.prototype, "defaultFor", {
	        /**
	         * The file extensions for which the factory should be the default.
	         */
	        get: function () {
	            return this._defaultFor.slice();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ABCWidgetFactory.prototype, "preferKernel", {
	        /**
	         * Whether the widgets prefer having a kernel started.
	         */
	        get: function () {
	            return this._preferKernel;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ABCWidgetFactory.prototype, "canStartKernel", {
	        /**
	         * Whether the widgets can start a kernel when opened.
	         */
	        get: function () {
	            return this._canStartKernel;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create a new widget given a document model and a context.
	     *
	     * #### Notes
	     * It should emit the [widgetCreated] signal with the new widget.
	     */
	    ABCWidgetFactory.prototype.createNew = function (context) {
	        var widget = this.createNewWidget(context);
	        this.widgetCreated.emit(widget);
	        return widget;
	    };
	    return ABCWidgetFactory;
	}());
	exports.ABCWidgetFactory = ABCWidgetFactory;
	// Define the signals for the `ABCWidgetFactory` class.
	signaling_1.defineSignal(ABCWidgetFactory.prototype, 'widgetCreated');
	//# sourceMappingURL=default.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/default.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/meta.js **/
jupyter.define('codemirror@5.23.0/mode/meta.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  "use strict";
	
	  CodeMirror.modeInfo = [
	    {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]},
	    {name: "PGP", mimes: ["application/pgp", "application/pgp-keys", "application/pgp-signature"], mode: "asciiarmor", ext: ["pgp"]},
	    {name: "ASN.1", mime: "text/x-ttcn-asn", mode: "asn.1", ext: ["asn", "asn1"]},
	    {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i},
	    {name: "Brainfuck", mime: "text/x-brainfuck", mode: "brainfuck", ext: ["b", "bf"]},
	    {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h"]},
	    {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]},
	    {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]},
	    {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]},
	    {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj", "cljc", "cljx"]},
	    {name: "ClojureScript", mime: "text/x-clojurescript", mode: "clojure", ext: ["cljs"]},
	    {name: "Closure Stylesheets (GSS)", mime: "text/x-gss", mode: "css", ext: ["gss"]},
	    {name: "CMake", mime: "text/x-cmake", mode: "cmake", ext: ["cmake", "cmake.in"], file: /^CMakeLists.txt$/},
	    {name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]},
	    {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]},
	    {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]},
	    {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]},
	    {name: "Crystal", mime: "text/x-crystal", mode: "crystal", ext: ["cr"]},
	    {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]},
	    {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]},
	    {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]},
	    {name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]},
	    {name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]},
	    {name: "Django", mime: "text/x-django", mode: "django"},
	    {name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile", file: /^Dockerfile$/},
	    {name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]},
	    {name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]},
	    {name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"},
	    {name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]},
	    {name: "edn", mime: "application/edn", mode: "clojure", ext: ["edn"]},
	    {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]},
	    {name: "Elm", mime: "text/x-elm", mode: "elm", ext: ["elm"]},
	    {name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]},
	    {name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]},
	    {name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]},
	    {name: "Factor", mime: "text/x-factor", mode: "factor", ext: ["factor"]},
	    {name: "FCL", mime: "text/x-fcl", mode: "fcl"},
	    {name: "Forth", mime: "text/x-forth", mode: "forth", ext: ["forth", "fth", "4th"]},
	    {name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90"]},
	    {name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]},
	    {name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]},
	    {name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]},
	    {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history).md$/i},
	    {name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]},
	    {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy", "gradle"], file: /^Jenkinsfile$/},
	    {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]},
	    {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]},
	    {name: "Haskell (Literate)", mime: "text/x-literate-haskell", mode: "haskell-literate", ext: ["lhs"]},
	    {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]},
	    {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]},
	    {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]},
	    {name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm"], alias: ["xhtml"]},
	    {name: "HTTP", mime: "message/http", mode: "http"},
	    {name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]},
	    {name: "Pug", mime: "text/x-pug", mode: "pug", ext: ["jade", "pug"], alias: ["jade"]},
	    {name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]},
	    {name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]},
	    {name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"],
	     mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]},
	    {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]},
	    {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]},
	    {name: "JSX", mime: "text/jsx", mode: "jsx", ext: ["jsx"]},
	    {name: "Jinja2", mime: "null", mode: "jinja2"},
	    {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]},
	    {name: "Kotlin", mime: "text/x-kotlin", mode: "clike", ext: ["kt"]},
	    {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},
	    {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},
	    {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},
	    {name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]},
	    {name: "mIRC", mime: "text/mirc", mode: "mirc"},
	    {name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"},
	    {name: "Mathematica", mime: "text/x-mathematica", mode: "mathematica", ext: ["m", "nb"]},
	    {name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]},
	    {name: "MUMPS", mime: "text/x-mumps", mode: "mumps", ext: ["mps"]},
	    {name: "MS SQL", mime: "text/x-mssql", mode: "sql"},
	    {name: "mbox", mime: "application/mbox", mode: "mbox", ext: ["mbox"]},
	    {name: "MySQL", mime: "text/x-mysql", mode: "sql"},
	    {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
	    {name: "NSIS", mime: "text/x-nsis", mode: "nsis", ext: ["nsh", "nsi"]},
	    {name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]},
	    {name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"], alias: ["objective-c", "objc"]},
	    {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
	    {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},
	    {name: "Oz", mime: "text/x-oz", mode: "oz", ext: ["oz"]},
	    {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]},
	    {name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]},
	    {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]},
	    {name: "PHP", mime: "application/x-httpd-php", mode: "php", ext: ["php", "php3", "php4", "php5", "phtml"]},
	    {name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]},
	    {name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]},
	    {name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]},
	    {name: "PowerShell", mime: "application/x-powershell", mode: "powershell", ext: ["ps1", "psd1", "psm1"]},
	    {name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]},
	    {name: "ProtoBuf", mime: "text/x-protobuf", mode: "protobuf", ext: ["proto"]},
	    {name: "Python", mime: "text/x-python", mode: "python", ext: ["BUILD", "bzl", "py", "pyw"], file: /^(BUCK|BUILD)$/},
	    {name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]},
	    {name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]},
	    {name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r", "R"], alias: ["rscript"]},
	    {name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]},
	    {name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"},
	    {name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]},
	    {name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]},
	    {name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]},
	    {name: "SAS", mime: "text/x-sas", mode: "sas", ext: ["sas"]},
	    {name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]},
	    {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
	    {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
	    {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},
	    {name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"], file: /^PKGBUILD$/},
	    {name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]},
	    {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]},
	    {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},
	    {name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]},
	    {name: "Solr", mime: "text/x-solr", mode: "solr"},
	    {name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]},
	    {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},
	    {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},
	    {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},
	    {name: "Squirrel", mime: "text/x-squirrel", mode: "clike", ext: ["nut"]},
	    {name: "Stylus", mime: "text/x-styl", mode: "stylus", ext: ["styl"]},
	    {name: "Swift", mime: "text/x-swift", mode: "swift", ext: ["swift"]},
	    {name: "sTeX", mime: "text/x-stex", mode: "stex"},
	    {name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx"], alias: ["tex"]},
	    {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v"]},
	    {name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]},
	    {name: "Textile", mime: "text/x-textile", mode: "textile", ext: ["textile"]},
	    {name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"},
	    {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"},
	    {name: "TOML", mime: "text/x-toml", mode: "toml", ext: ["toml"]},
	    {name: "Tornado", mime: "text/x-tornado", mode: "tornado"},
	    {name: "troff", mime: "text/troff", mode: "troff", ext: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]},
	    {name: "TTCN", mime: "text/x-ttcn", mode: "ttcn", ext: ["ttcn", "ttcn3", "ttcnpp"]},
	    {name: "TTCN_CFG", mime: "text/x-ttcn-cfg", mode: "ttcn-cfg", ext: ["cfg"]},
	    {name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]},
	    {name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]},
	    {name: "Twig", mime: "text/x-twig", mode: "twig"},
	    {name: "Web IDL", mime: "text/x-webidl", mode: "webidl", ext: ["webidl"]},
	    {name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]},
	    {name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]},
	    {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},
	    {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},
	    {name: "VHDL", mime: "text/x-vhdl", mode: "vhdl", ext: ["vhd", "vhdl"]},
	    {name: "Vue.js Component", mimes: ["script/x-vue", "text/x-vue"], mode: "vue", ext: ["vue"]},
	    {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd", "svg"], alias: ["rss", "wsdl", "xsd"]},
	    {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},
	    {name: "Yacas", mime: "text/x-yacas", mode: "yacas", ext: ["ys"]},
	    {name: "YAML", mimes: ["text/x-yaml", "text/yaml"], mode: "yaml", ext: ["yaml", "yml"], alias: ["yml"]},
	    {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]},
	    {name: "mscgen", mime: "text/x-mscgen", mode: "mscgen", ext: ["mscgen", "mscin", "msc"]},
	    {name: "xu", mime: "text/x-xu", mode: "mscgen", ext: ["xu"]},
	    {name: "msgenny", mime: "text/x-msgenny", mode: "mscgen", ext: ["msgenny"]}
	  ];
	  // Ensure all modes have a mime property for backwards compatibility
	  for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	    var info = CodeMirror.modeInfo[i];
	    if (info.mimes) info.mime = info.mimes[0];
	  }
	
	  CodeMirror.findModeByMIME = function(mime) {
	    mime = mime.toLowerCase();
	    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	      var info = CodeMirror.modeInfo[i];
	      if (info.mime == mime) return info;
	      if (info.mimes) for (var j = 0; j < info.mimes.length; j++)
	        if (info.mimes[j] == mime) return info;
	    }
	    if (/\+xml$/.test(mime)) return CodeMirror.findModeByMIME("application/xml")
	    if (/\+json$/.test(mime)) return CodeMirror.findModeByMIME("application/json")
	  };
	
	  CodeMirror.findModeByExtension = function(ext) {
	    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	      var info = CodeMirror.modeInfo[i];
	      if (info.ext) for (var j = 0; j < info.ext.length; j++)
	        if (info.ext[j] == ext) return info;
	    }
	  };
	
	  CodeMirror.findModeByFileName = function(filename) {
	    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	      var info = CodeMirror.modeInfo[i];
	      if (info.file && info.file.test(filename)) return info;
	    }
	    var dot = filename.lastIndexOf(".");
	    var ext = dot > -1 && filename.substring(dot + 1, filename.length);
	    if (ext) return CodeMirror.findModeByExtension(ext);
	  };
	
	  CodeMirror.findModeByName = function(name) {
	    name = name.toLowerCase();
	    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
	      var info = CodeMirror.modeInfo[i];
	      if (info.name.toLowerCase() == name) return info;
	      if (info.alias) for (var j = 0; j < info.alias.length; j++)
	        if (info.alias[j].toLowerCase() == name) return info;
	    }
	  };
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/meta.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/kernelactions.js **/
jupyter.define('jupyterlab@0.15.1/lib/docregistry/kernelactions.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	/**
	 * Restart a kernel after presenting a dialog.
	 *
	 * @param kernel - The kernel to restart.
	 *
	 * @param host - The optional host element for the dialog.
	 *
	 * @returns A promise that resolves to `true` the user elects to restart.
	 *
	 * #### Notes
	 * This is a no-op if there is no kernel.
	 */
	function restartKernel(kernel, host) {
	    if (!kernel) {
	        return Promise.resolve(false);
	    }
	    return dialog_1.showDialog({
	        title: 'Restart Kernel?',
	        body: 'Do you want to restart the current kernel? All variables will be lost.',
	        buttons: [dialog_1.cancelButton, dialog_1.warnButton]
	    }).then(function (result) {
	        if (!kernel.isDisposed && result.text === 'OK') {
	            return kernel.restart().then(function () { return true; });
	        }
	        else {
	            return false;
	        }
	    });
	}
	exports.restartKernel = restartKernel;
	//# sourceMappingURL=kernelactions.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/kernelactions.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/kernelselector.js **/
jupyter.define('jupyterlab@0.15.1/lib/docregistry/kernelselector.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	/**
	 * Bring up a dialog to select a kernel.
	 */
	function selectKernel(options) {
	    var specs = options.specs, kernel = options.kernel, sessions = options.sessions, preferredLanguage = options.preferredLanguage;
	    // Create the dialog body.
	    var body = document.createElement('div');
	    var text = document.createElement('label');
	    text.innerHTML = "Select kernel for: \"" + options.name + "\"";
	    body.appendChild(text);
	    if (kernel) {
	        var displayName = specs.kernelspecs[kernel.name].display_name;
	        var current = document.createElement('span');
	        current.textContent = "Current: \"" + displayName + "\"";
	        current.title = ("Kernel Name: " + displayName + "\n") +
	            ("Kernel Id: " + kernel.id);
	        body.appendChild(current);
	        body.appendChild(document.createElement('br'));
	    }
	    var selector = document.createElement('select');
	    body.appendChild(selector);
	    // Get the current sessions, populate the kernels, and show the dialog.
	    populateKernels(selector, { specs: specs, sessions: sessions, preferredLanguage: preferredLanguage, kernel: kernel });
	    return dialog_1.showDialog({
	        title: 'Select Kernel',
	        body: body,
	        okText: 'SELECT'
	    }).then(function (result) {
	        // Change the kernel if a kernel was selected.
	        if (result.text === 'SELECT') {
	            return JSON.parse(selector.value);
	        }
	        return void 0;
	    });
	}
	exports.selectKernel = selectKernel;
	/**
	 * Change the kernel on a context.
	 */
	function selectKernelForContext(context, manager, host) {
	    return manager.ready.then(function () {
	        var options = {
	            name: context.path.split('/').pop(),
	            specs: manager.specs,
	            sessions: manager.running(),
	            preferredLanguage: context.model.defaultKernelLanguage,
	            kernel: context.kernel ? context.kernel.model : null,
	            host: host
	        };
	        return selectKernel(options);
	    }).then(function (kernel) {
	        if (kernel && (kernel.id || kernel.name)) {
	            context.changeKernel(kernel);
	        }
	        else if (kernel && !kernel.id && !kernel.name) {
	            context.changeKernel();
	        }
	    });
	}
	exports.selectKernelForContext = selectKernelForContext;
	/**
	 * Get the appropriate kernel name.
	 */
	function findKernel(kernelName, language, specs) {
	    if (kernelName === 'unknown') {
	        return specs.default;
	    }
	    // Look for an exact match.
	    for (var specName in specs.kernelspecs) {
	        if (specName === kernelName) {
	            return kernelName;
	        }
	    }
	    // Next try to match the language name.
	    if (language === 'unknown') {
	        return specs.default;
	    }
	    for (var specName in specs.kernelspecs) {
	        var kernelLanguage = specs.kernelspecs[specName].language;
	        if (language === kernelLanguage) {
	            console.log('No exact match found for ' + specName +
	                ', using kernel ' + specName + ' that matches ' +
	                'language=' + language);
	            return specName;
	        }
	    }
	    // Finally, use the default kernel.
	    if (kernelName) {
	        console.log(("No matching kernel found for " + kernelName + ", ") +
	            ("using default kernel " + specs.default));
	    }
	    return specs.default;
	}
	exports.findKernel = findKernel;
	/**
	 * Populate a kernel dropdown list.
	 *
	 * @param node - The host node.
	 *
	 * @param options - The options used to populate the kernels.
	 *
	 * #### Notes
	 * Populates the list with separated sections:
	 *   - Kernels matching the preferred language (display names).
	 *   - "None" signifying no kernel.
	 *   - The remaining kernels.
	 *   - Sessions matching the preferred language (file names).
	 *   - The remaining sessions.
	 * If no preferred language is given or no kernels are found using
	 * the preferred language, the default kernel is used in the first
	 * section.  Kernels are sorted by display name.  Sessions display the
	 * base name of the file with an ellipsis overflow and a tooltip with
	 * the explicit session information.
	 */
	function populateKernels(node, options) {
	    // Clear any existing options.
	    while (node.firstChild) {
	        node.removeChild(node.firstChild);
	    }
	    var maxLength = 10;
	    var preferredKernel = options.preferredKernel, preferredLanguage = options.preferredLanguage, sessions = options.sessions, specs = options.specs, kernel = options.kernel;
	    var existing = kernel ? kernel.id : void 0;
	    // Create mappings of display names and languages for kernel name.
	    var displayNames = Object.create(null);
	    var languages = Object.create(null);
	    for (var name_1 in specs.kernelspecs) {
	        var spec = specs.kernelspecs[name_1];
	        displayNames[name_1] = spec.display_name;
	        maxLength = Math.max(maxLength, displayNames[name_1].length);
	        languages[name_1] = spec.language;
	    }
	    // Handle a kernel by name.
	    var names = [];
	    if (preferredKernel && preferredKernel in specs.kernelspecs) {
	        names.push(name);
	    }
	    // Handle a preferred kernel language in order of display name.
	    var preferred = document.createElement('optgroup');
	    preferred.label = 'Start Preferred Kernel';
	    if (preferredLanguage && specs) {
	        for (var name_2 in specs.kernelspecs) {
	            if (languages[name_2] === preferredLanguage) {
	                names.push(name_2);
	            }
	        }
	        names.sort(function (a, b) { return displayNames[a].localeCompare(displayNames[b]); });
	        for (var _i = 0, names_1 = names; _i < names_1.length; _i++) {
	            var name_3 = names_1[_i];
	            preferred.appendChild(optionForName(name_3, displayNames[name_3]));
	        }
	    }
	    // Use the default kernel if no preferred language or none were found.
	    if (!names.length) {
	        var name_4 = specs.default;
	        preferred.appendChild(optionForName(name_4, displayNames[name_4]));
	    }
	    if (preferred.firstChild) {
	        node.appendChild(preferred);
	    }
	    // Add an option for no kernel
	    node.appendChild(optionForNone());
	    var other = document.createElement('optgroup');
	    other.label = 'Start Other Kernel';
	    // Add the rest of the kernel names in alphabetical order.
	    var otherNames = [];
	    for (var name_5 in specs.kernelspecs) {
	        if (names.indexOf(name_5) !== -1) {
	            continue;
	        }
	        otherNames.push(name_5);
	    }
	    otherNames.sort(function (a, b) { return displayNames[a].localeCompare(displayNames[b]); });
	    for (var _a = 0, otherNames_1 = otherNames; _a < otherNames_1.length; _a++) {
	        var name_6 = otherNames_1[_a];
	        other.appendChild(optionForName(name_6, displayNames[name_6]));
	    }
	    // Add a separator option if there were any other names.
	    if (otherNames.length) {
	        node.appendChild(other);
	    }
	    // Add the sessions using the preferred language first.
	    var matchingSessions = [];
	    var otherSessions = [];
	    iteration_1.each(sessions, function (session) {
	        if (preferredLanguage &&
	            languages[session.kernel.name] === preferredLanguage &&
	            session.kernel.id !== existing) {
	            matchingSessions.push(session);
	        }
	        else if (session.kernel.id !== existing) {
	            otherSessions.push(session);
	        }
	    });
	    var matching = document.createElement('optgroup');
	    matching.label = 'Use Kernel from Preferred Session';
	    node.appendChild(matching);
	    if (matchingSessions.length) {
	        matchingSessions.sort(function (a, b) {
	            return a.notebook.path.localeCompare(b.notebook.path);
	        });
	        iteration_1.each(matchingSessions, function (session) {
	            var name = displayNames[session.kernel.name];
	            matching.appendChild(optionForSession(session, name, maxLength));
	        });
	    }
	    var otherSessionsNode = document.createElement('optgroup');
	    otherSessionsNode.label = 'Use Kernel from Other Session';
	    node.appendChild(otherSessionsNode);
	    if (otherSessions.length) {
	        otherSessions.sort(function (a, b) {
	            return a.notebook.path.localeCompare(b.notebook.path);
	        });
	        iteration_1.each(otherSessions, function (session) {
	            var name = displayNames[session.kernel.name] || session.kernel.name;
	            otherSessionsNode.appendChild(optionForSession(session, name, maxLength));
	        });
	    }
	    node.selectedIndex = 0;
	}
	exports.populateKernels = populateKernels;
	/**
	 * Create an option element for a kernel name.
	 */
	function optionForName(name, displayName) {
	    var option = document.createElement('option');
	    option.text = displayName;
	    option.value = JSON.stringify({ name: name });
	    return option;
	}
	/**
	 * Create an option for no kernel.
	 */
	function optionForNone() {
	    var group = document.createElement('optgroup');
	    group.label = 'Use No Kernel';
	    var option = document.createElement('option');
	    option.text = 'No Kernel';
	    option.value = JSON.stringify({ id: null, name: null });
	    group.appendChild(option);
	    return group;
	}
	/**
	 * Create an option element for a session.
	 */
	function optionForSession(session, displayName, maxLength) {
	    var option = document.createElement('option');
	    var sessionName = session.notebook.path.split('/').pop();
	    var CONSOLE_REGEX = /^console-(\d)+-[0-9a-f]+$/;
	    if (CONSOLE_REGEX.test(sessionName)) {
	        sessionName = "Console " + sessionName.match(CONSOLE_REGEX)[1];
	    }
	    if (sessionName.length > maxLength) {
	        sessionName = sessionName.slice(0, maxLength - 3) + '...';
	    }
	    option.text = sessionName;
	    option.value = JSON.stringify({ id: session.kernel.id });
	    option.title = ("Path: " + session.notebook.path + "\n") +
	        ("Kernel Name: " + displayName + "\n") +
	        ("Kernel Id: " + session.kernel.id);
	    return option;
	}
	//# sourceMappingURL=kernelselector.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/kernelselector.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/registry.js **/
jupyter.define('jupyterlab@0.15.1/lib/docregistry/registry.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	/* tslint:disable */
	/**
	 * The document registry token.
	 */
	exports.IDocumentRegistry = new token_1.Token('jupyter.services.document-registry');
	/**
	 * The document registry.
	 */
	var DocumentRegistry = (function () {
	    function DocumentRegistry() {
	        this._modelFactories = Object.create(null);
	        this._widgetFactories = Object.create(null);
	        this._defaultWidgetFactory = '';
	        this._defaultWidgetFactories = Object.create(null);
	        this._widgetFactoryExtensions = Object.create(null);
	        this._fileTypes = new vector_1.Vector();
	        this._creators = new vector_1.Vector();
	        this._extenders = Object.create(null);
	    }
	    Object.defineProperty(DocumentRegistry.prototype, "isDisposed", {
	        /**
	         * Get whether the document registry has been disposed.
	         */
	        get: function () {
	            return this._widgetFactories === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the document registery.
	     */
	    DocumentRegistry.prototype.dispose = function () {
	        if (this._widgetFactories === null) {
	            return;
	        }
	        var widgetFactories = this._widgetFactories;
	        var modelFactories = this._modelFactories;
	        var extenders = this._extenders;
	        this._widgetFactories = null;
	        this._modelFactories = null;
	        this._extenders = null;
	        for (var modelName in modelFactories) {
	            modelFactories[modelName].dispose();
	        }
	        for (var widgetName in widgetFactories) {
	            widgetFactories[widgetName].dispose();
	        }
	        for (var widgetName in extenders) {
	            extenders[widgetName].clear();
	        }
	        this._fileTypes.clear();
	        this._creators.clear();
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Add a widget factory to the registry.
	     *
	     * @param factory - The factory instance to register.
	     *
	     * @returns A disposable which will unregister the factory.
	     *
	     * #### Notes
	     * If a factory with the given `'displayName'` is already registered,
	     * a warning will be logged, and this will be a no-op.
	     * If `'*'` is given as a default extension, the factory will be registered
	     * as the global default.
	     * If an extension or global default is already registered, this factory
	     * will override the existing default.
	     */
	    DocumentRegistry.prototype.addWidgetFactory = function (factory) {
	        var _this = this;
	        var name = factory.name.toLowerCase();
	        if (this._widgetFactories[name]) {
	            console.warn("Duplicate registered factory " + name);
	            return new disposable_1.DisposableDelegate(null);
	        }
	        this._widgetFactories[name] = factory;
	        for (var _i = 0, _a = factory.defaultFor; _i < _a.length; _i++) {
	            var ext = _a[_i];
	            if (factory.fileExtensions.indexOf(ext) === -1) {
	                continue;
	            }
	            if (ext === '*') {
	                this._defaultWidgetFactory = name;
	            }
	            else {
	                this._defaultWidgetFactories[ext] = name;
	            }
	        }
	        // For convenience, store a mapping of ext -> name
	        for (var _b = 0, _c = factory.fileExtensions; _b < _c.length; _b++) {
	            var ext = _c[_b];
	            if (!this._widgetFactoryExtensions[ext]) {
	                this._widgetFactoryExtensions[ext] = new vector_1.Vector();
	            }
	            this._widgetFactoryExtensions[ext].pushBack(name);
	        }
	        this.changed.emit({
	            type: 'widgetFactory',
	            name: name,
	            change: 'added'
	        });
	        return new disposable_1.DisposableDelegate(function () {
	            delete _this._widgetFactories[name];
	            if (_this._defaultWidgetFactory === name) {
	                _this._defaultWidgetFactory = '';
	            }
	            for (var _i = 0, _a = Object.keys(_this._defaultWidgetFactories); _i < _a.length; _i++) {
	                var ext = _a[_i];
	                if (_this._defaultWidgetFactories[ext] === name) {
	                    delete _this._defaultWidgetFactories[ext];
	                }
	            }
	            for (var _b = 0, _c = Object.keys(_this._widgetFactoryExtensions); _b < _c.length; _b++) {
	                var ext = _c[_b];
	                _this._widgetFactoryExtensions[ext].remove(name);
	                if (_this._widgetFactoryExtensions[ext].length === 0) {
	                    delete _this._widgetFactoryExtensions[ext];
	                }
	            }
	            _this.changed.emit({
	                type: 'widgetFactory',
	                name: name,
	                change: 'removed'
	            });
	        });
	    };
	    /**
	     * Add a model factory to the registry.
	     *
	     * @param factory - The factory instance.
	     *
	     * @returns A disposable which will unregister the factory.
	     *
	     * #### Notes
	     * If a factory with the given `name` is already registered, or
	     * the given factory is already registered, a warning will be logged
	     * and this will be a no-op.
	     */
	    DocumentRegistry.prototype.addModelFactory = function (factory) {
	        var _this = this;
	        var name = factory.name.toLowerCase();
	        if (this._modelFactories[name]) {
	            console.warn("Duplicate registered factory " + name);
	            return new disposable_1.DisposableDelegate(null);
	        }
	        this._modelFactories[name] = factory;
	        this.changed.emit({
	            type: 'modelFactory',
	            name: name,
	            change: 'added'
	        });
	        return new disposable_1.DisposableDelegate(function () {
	            delete _this._modelFactories[name];
	            _this.changed.emit({
	                type: 'modelFactory',
	                name: name,
	                change: 'removed'
	            });
	        });
	    };
	    /**
	     * Add a widget extension to the registry.
	     *
	     * @param widgetName - The name of the widget factory.
	     *
	     * @param extension - A widget extension.
	     *
	     * @returns A disposable which will unregister the extension.
	     *
	     * #### Notes
	     * If the extension is already registered for the given
	     * widget name, a warning will be logged and this will be a no-op.
	     */
	    DocumentRegistry.prototype.addWidgetExtension = function (widgetName, extension) {
	        var _this = this;
	        widgetName = widgetName.toLowerCase();
	        if (!(widgetName in this._extenders)) {
	            this._extenders[widgetName] = new vector_1.Vector();
	        }
	        var extenders = this._extenders[widgetName];
	        var index = searching_1.indexOf(extenders, extension);
	        if (index !== -1) {
	            console.warn("Duplicate registered extension for " + widgetName);
	            return new disposable_1.DisposableDelegate(null);
	        }
	        this._extenders[widgetName].pushBack(extension);
	        this.changed.emit({
	            type: 'widgetExtension',
	            name: null,
	            change: 'added'
	        });
	        return new disposable_1.DisposableDelegate(function () {
	            _this._extenders[widgetName].remove(extension);
	            _this.changed.emit({
	                type: 'widgetExtension',
	                name: null,
	                change: 'removed'
	            });
	        });
	    };
	    /**
	     * Add a file type to the document registry.
	     *
	     * @params fileType - The file type object to register.
	     *
	     * @returns A disposable which will unregister the command.
	     *
	     * #### Notes
	     * These are used to populate the "Create New" dialog.
	     */
	    DocumentRegistry.prototype.addFileType = function (fileType) {
	        var _this = this;
	        this._fileTypes.pushBack(fileType);
	        this.changed.emit({
	            type: 'fileType',
	            name: fileType.name,
	            change: 'added'
	        });
	        return new disposable_1.DisposableDelegate(function () {
	            _this._fileTypes.remove(fileType);
	            _this.changed.emit({
	                type: 'fileType',
	                name: fileType.name,
	                change: 'removed'
	            });
	        });
	    };
	    /**
	     * Add a creator to the registry.
	     *
	     * @params creator - The file creator object to register.
	     *
	     * @returns A disposable which will unregister the creator.
	     */
	    DocumentRegistry.prototype.addCreator = function (creator) {
	        var _this = this;
	        var index = searching_1.findIndex(this._creators, function (value) {
	            return value.name.localeCompare(creator.name) > 0;
	        });
	        if (index !== -1) {
	            this._creators.insert(index, creator);
	        }
	        else {
	            this._creators.pushBack(creator);
	        }
	        this.changed.emit({
	            type: 'fileCreator',
	            name: creator.name,
	            change: 'added'
	        });
	        return new disposable_1.DisposableDelegate(function () {
	            _this._creators.remove(creator);
	            _this.changed.emit({
	                type: 'fileCreator',
	                name: creator.name,
	                change: 'removed'
	            });
	        });
	    };
	    /**
	     * Get a list of the preferred widget factories.
	     *
	     * @param ext - An optional file extension to filter the results.
	     *
	     * @returns A new array of widget factories.
	     *
	     * #### Notes
	     * Only the widget factories whose associated model factory have
	     * been registered will be returned.
	     * The first item is considered the default. The returned iterator
	     * has widget factories in the following order:
	     * - extension-specific default factory
	     * - global default factory
	     * - all other extension-specific factories
	     * - all other global factories
	     */
	    DocumentRegistry.prototype.preferredWidgetFactories = function (ext) {
	        var _this = this;
	        if (ext === void 0) { ext = '*'; }
	        var factories = new Set();
	        ext = Private.normalizeExtension(ext);
	        var last = '.' + ext.split('.').pop();
	        // Start with the extension-specific default factory.
	        if (ext.length > 1) {
	            if (ext in this._defaultWidgetFactories) {
	                factories.add(this._defaultWidgetFactories[ext]);
	            }
	        }
	        // Handle multi-part extension default factories.
	        if (last !== ext) {
	            if (last in this._defaultWidgetFactories) {
	                factories.add(this._defaultWidgetFactories[last]);
	            }
	        }
	        // Add the global default factory.
	        if (this._defaultWidgetFactory) {
	            factories.add(this._defaultWidgetFactory);
	        }
	        // Add the extension-specific factories in registration order.
	        if (ext.length > 1) {
	            if (ext in this._widgetFactoryExtensions) {
	                iteration_1.each(this._widgetFactoryExtensions[ext], function (n) {
	                    factories.add(n);
	                });
	            }
	        }
	        // Handle multi-part extension-specific factories.
	        if (last !== ext) {
	            if (last in this._widgetFactoryExtensions) {
	                iteration_1.each(this._widgetFactoryExtensions[last], function (n) {
	                    factories.add(n);
	                });
	            }
	        }
	        // Add the rest of the global factories, in registration order.
	        if ('*' in this._widgetFactoryExtensions) {
	            iteration_1.each(this._widgetFactoryExtensions['*'], function (n) {
	                factories.add(n);
	            });
	        }
	        // Construct the return list, checking to make sure the corresponding
	        // model factories are registered.
	        var factoryList = [];
	        factories.forEach(function (name) {
	            if (_this._widgetFactories[name].modelName in _this._modelFactories) {
	                factoryList.push(_this._widgetFactories[name]);
	            }
	        });
	        return factoryList;
	    };
	    /**
	     * Get the default widget factory for an extension.
	     *
	     * @param ext - An optional file extension to filter the results.
	     *
	     * @returns The default widget factory for an extension.
	     *
	     * #### Notes
	     * This is equivalent to the first value in [[preferredWidgetFactories]].
	     */
	    DocumentRegistry.prototype.defaultWidgetFactory = function (ext) {
	        if (ext === void 0) { ext = '*'; }
	        return this.preferredWidgetFactories(ext)[0];
	    };
	    /**
	     * Create an iterator over the widget factories that have been registered.
	     *
	     * @returns A new iterator of widget factories.
	     */
	    DocumentRegistry.prototype.widgetFactories = function () {
	        var _this = this;
	        return iteration_1.map(Object.keys(this._widgetFactories), function (name) {
	            return _this._widgetFactories[name];
	        });
	    };
	    /**
	     * Create an iterator over the model factories that have been registered.
	     *
	     * @returns A new iterator of model factories.
	     */
	    DocumentRegistry.prototype.modelFactories = function () {
	        var _this = this;
	        return iteration_1.map(Object.keys(this._modelFactories), function (name) {
	            return _this._modelFactories[name];
	        });
	    };
	    /**
	     * Create an iterator over the registered extensions for a given widget.
	     *
	     * @param widgetName - The name of the widget factory.
	     *
	     * @returns A new iterator over the widget extensions.
	     */
	    DocumentRegistry.prototype.widgetExtensions = function (widgetName) {
	        widgetName = widgetName.toLowerCase();
	        if (!(widgetName in this._extenders)) {
	            return iteration_1.empty();
	        }
	        return this._extenders[widgetName].iter();
	    };
	    /**
	     * Create an iterator over the file types that have been registered.
	     *
	     * @returns A new iterator of file types.
	     */
	    DocumentRegistry.prototype.fileTypes = function () {
	        return this._fileTypes.iter();
	    };
	    /**
	     * Create an iterator over the file creators that have been registered.
	     *
	     * @returns A new iterator of file creatores.
	     */
	    DocumentRegistry.prototype.creators = function () {
	        return this._creators.iter();
	    };
	    /**
	     * Get a widget factory by name.
	     *
	     * @param widgetName - The name of the widget factory.
	     *
	     * @returns A widget factory instance.
	     */
	    DocumentRegistry.prototype.getWidgetFactory = function (widgetName) {
	        return this._widgetFactories[widgetName.toLowerCase()];
	    };
	    /**
	     * Get a model factory by name.
	     *
	     * @param name - The name of the model factory.
	     *
	     * @returns A model factory instance.
	     */
	    DocumentRegistry.prototype.getModelFactory = function (name) {
	        return this._modelFactories[name.toLowerCase()];
	    };
	    /**
	     * Get a file type by name.
	     */
	    DocumentRegistry.prototype.getFileType = function (name) {
	        name = name.toLowerCase();
	        return searching_1.find(this._fileTypes, function (fileType) {
	            return fileType.name.toLowerCase() === name;
	        });
	    };
	    /**
	     * Get a creator by name.
	     */
	    DocumentRegistry.prototype.getCreator = function (name) {
	        name = name.toLowerCase();
	        return searching_1.find(this._creators, function (creator) {
	            return creator.name.toLowerCase() === name;
	        });
	    };
	    /**
	     * Get a kernel preference.
	     *
	     * @param ext - The file extension.
	     *
	     * @param widgetName - The name of the widget factory.
	     *
	     * @returns A kernel preference.
	     */
	    DocumentRegistry.prototype.getKernelPreference = function (ext, widgetName) {
	        ext = Private.normalizeExtension(ext);
	        widgetName = widgetName.toLowerCase();
	        var widgetFactory = this._widgetFactories[widgetName];
	        if (!widgetFactory) {
	            return void 0;
	        }
	        var modelFactory = this.getModelFactory(widgetFactory.modelName);
	        if (!modelFactory) {
	            return void 0;
	        }
	        var language = modelFactory.preferredLanguage(ext);
	        return {
	            language: language,
	            preferKernel: widgetFactory.preferKernel,
	            canStartKernel: widgetFactory.canStartKernel
	        };
	    };
	    return DocumentRegistry;
	}());
	exports.DocumentRegistry = DocumentRegistry;
	/**
	 * The namespace for the `DocumentRegistry` class statics.
	 */
	var DocumentRegistry;
	(function (DocumentRegistry) {
	    /**
	     * Get the extension name of a path.
	     *
	     * @param file - string.
	     *
	     * #### Notes
	     * Dotted filenames (e.g. `".table.json"` are allowed.
	     */
	    function extname(path) {
	        var parts = services_1.ContentsManager.basename(path).split('.');
	        parts.shift();
	        return '.' + parts.join('.');
	    }
	    DocumentRegistry.extname = extname;
	})(DocumentRegistry = exports.DocumentRegistry || (exports.DocumentRegistry = {}));
	// Define the signals for the `DocumentRegistry` class.
	signaling_1.defineSignal(DocumentRegistry.prototype, 'changed');
	/**
	 * A private namespace for DocumentRegistry data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Normalize a file extension to be of the type `'.foo'`.
	     *
	     * Adds a leading dot if not present and converts to lower case.
	     */
	    function normalizeExtension(extension) {
	        if (extension === '*') {
	            return extension;
	        }
	        if (extension === '.*') {
	            return '*';
	        }
	        if (extension.indexOf('.') !== 0) {
	            extension = "." + extension;
	        }
	        return extension.toLowerCase();
	    }
	    Private.normalizeExtension = normalizeExtension;
	})(Private || (Private = {}));
	//# sourceMappingURL=registry.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/registry.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/mainmenu/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/mainmenu/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	var menubar_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/menubar.js');
	/* tslint:disable */
	/**
	 * The main menu token.
	 */
	exports.IMainMenu = new token_1.Token('jupyter.services.main-menu');
	/**
	 * The main menu class.  It is intended to be used as a singleton.
	 */
	var MainMenu = (function (_super) {
	    __extends(MainMenu, _super);
	    function MainMenu() {
	        _super.apply(this, arguments);
	        this._items = new vector_1.Vector();
	    }
	    /**
	     * Add a new menu to the main menu bar.
	     */
	    MainMenu.prototype.addMenu = function (menu, options) {
	        if (options === void 0) { options = {}; }
	        if (searching_1.indexOf(this.menus, menu) > -1) {
	            return;
	        }
	        var rank = 'rank' in options ? options.rank : 100;
	        var rankItem = { menu: menu, rank: rank };
	        var index = searching_1.upperBound(this._items, rankItem, Private.itemCmp);
	        // Upon disposal, remove the menu and its rank reference.
	        menu.disposed.connect(this._onMenuDisposed, this);
	        this._items.insert(index, rankItem);
	        this.insertMenu(index, menu);
	    };
	    /**
	     * Handle the disposal of a menu.
	     */
	    MainMenu.prototype._onMenuDisposed = function (menu) {
	        this.removeMenu(menu);
	        var index = searching_1.findIndex(this._items, function (item) { return item.menu === menu; });
	        if (index !== -1) {
	            this._items.removeAt(index);
	        }
	    };
	    return MainMenu;
	}(menubar_1.MenuBar));
	exports.MainMenu = MainMenu;
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * A comparator function for menu rank items.
	     */
	    function itemCmp(first, second) {
	        return first.rank - second.rank;
	    }
	    Private.itemCmp = itemCmp;
	})(Private || (Private = {}));
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/mainmenu/index.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/menubar.js **/
jupyter.define('phosphor@0.7.0/lib/ui/menubar.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	/*-----------------------------------------------------------------------------
	| Copyright (c) 2014-2016, PhosphorJS Contributors
	|
	| Distributed under the terms of the BSD 3-Clause License.
	|
	| The full license is in the file LICENSE, distributed with this software.
	|----------------------------------------------------------------------------*/
	var iteration_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/iteration.js');
	var mutation_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/mutation.js');
	var searching_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var query_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/query.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to a menu bar widget.
	 */
	var MENU_BAR_CLASS = 'p-MenuBar';
	/**
	 * The class name added to a menu bar content node.
	 */
	var CONTENT_CLASS = 'p-MenuBar-content';
	/**
	 * The class name added to an open menu bar menu.
	 */
	var MENU_CLASS = 'p-MenuBar-menu';
	/**
	 * The class name added to a menu bar item node.
	 */
	var ITEM_CLASS = 'p-MenuBar-item';
	/**
	 * The class name added to a menu bar item icon node.
	 */
	var ICON_CLASS = 'p-MenuBar-itemIcon';
	/**
	 * The class name added to a menu bar item label node.
	 */
	var LABEL_CLASS = 'p-MenuBar-itemLabel';
	/**
	 * The class name added to a menu bar item mnemonic node.
	 */
	var MNEMONIC_CLASS = 'p-MenuBar-itemMnemonic';
	/**
	 * The class name added to an active menu bar and item.
	 */
	var ACTIVE_CLASS = 'p-mod-active';
	/**
	 * A widget which displays menus as a canonical menu bar.
	 */
	var MenuBar = (function (_super) {
	    __extends(MenuBar, _super);
	    /**
	     * Construct a new menu bar.
	     *
	     * @param options - The options for initializing the menu bar.
	     */
	    function MenuBar(options) {
	        _super.call(this, { node: Private.createNode() });
	        this._activeIndex = -1;
	        this._childMenu = null;
	        this._menus = new vector_1.Vector();
	        this._nodes = new vector_1.Vector();
	        this.addClass(MENU_BAR_CLASS);
	        this.setFlag(widget_1.WidgetFlag.DisallowLayout);
	        this._keymap = options.keymap;
	        this._renderer = options.renderer || MenuBar.defaultRenderer;
	    }
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    MenuBar.prototype.dispose = function () {
	        this._closeChildMenu();
	        this._menus.clear();
	        this._nodes.clear();
	        this._keymap = null;
	        this._renderer = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(MenuBar.prototype, "contentNode", {
	        /**
	         * Get the menu bar content node.
	         *
	         * #### Notes
	         * This is the node which holds the menu title nodes.
	         *
	         * Modifying this node directly can lead to undefined behavior.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.node.getElementsByClassName(CONTENT_CLASS)[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(MenuBar.prototype, "keymap", {
	        /**
	         * The keymap used by the menu bar.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._keymap;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(MenuBar.prototype, "renderer", {
	        /**
	         * The renderer used by the menu bar.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(MenuBar.prototype, "menus", {
	        /**
	         * A read-only sequence of the menus in the menu bar.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._menus;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(MenuBar.prototype, "childMenu", {
	        /**
	         * Get the child menu of the menu bar.
	         *
	         * #### Notes
	         * This will be `null` if the menu bar does not have an open menu.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._childMenu;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(MenuBar.prototype, "activeMenu", {
	        /**
	         * Get the currently active menu.
	         *
	         * #### Notes
	         * This will be `null` if no menu is active.
	         */
	        get: function () {
	            var i = this._activeIndex;
	            return i !== -1 ? this._menus.at(i) : null;
	        },
	        /**
	         * Set the currently active menu.
	         *
	         * #### Notes
	         * If the menu does not exist, the menu will be set to `null`.
	         */
	        set: function (value) {
	            this.activeIndex = searching_1.indexOf(this._menus, value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(MenuBar.prototype, "activeIndex", {
	        /**
	         * Get the index of the currently active menu.
	         *
	         * #### Notes
	         * This will be `-1` if no menu is active.
	         */
	        get: function () {
	            return this._activeIndex;
	        },
	        /**
	         * Set the index of the currently active menu.
	         *
	         * #### Notes
	         * If the index is out of range, the index will be set to `-1`.
	         */
	        set: function (value) {
	            // Coerce the value to an index.
	            var i = Math.floor(value);
	            if (i < 0 || i >= this._menus.length) {
	                i = -1;
	            }
	            // Bail early if the index will not change.
	            if (this._activeIndex === i) {
	                return;
	            }
	            // Remove the active class from the old node.
	            if (this._activeIndex !== -1) {
	                var node = this._nodes.at(this._activeIndex);
	                node.classList.remove(ACTIVE_CLASS);
	            }
	            // Add the active class to the new node.
	            if (i !== -1) {
	                var node = this._nodes.at(i);
	                node.classList.add(ACTIVE_CLASS);
	            }
	            // Update the active index.
	            this._activeIndex = i;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Open the active menu and activate its first menu item.
	     *
	     * #### Notes
	     * If there is no active menu, this is a no-op.
	     */
	    MenuBar.prototype.openActiveMenu = function () {
	        // Bail early if there is no active item.
	        if (this._activeIndex === -1) {
	            return;
	        }
	        // Open the child menu.
	        this._openChildMenu();
	        // Activate the first item in the child menu.
	        if (this._childMenu) {
	            this._childMenu.activeIndex = -1;
	            this._childMenu.activateNextItem();
	        }
	    };
	    /**
	     * Add a menu to the end of the menu bar.
	     *
	     * @param menu - The menu to add to the menu bar.
	     *
	     * #### Notes
	     * If the menu is already added to the menu bar, it will be moved.
	     */
	    MenuBar.prototype.addMenu = function (menu) {
	        this.insertMenu(this._menus.length, menu);
	    };
	    /**
	     * Insert a menu into the menu bar at the specified index.
	     *
	     * @param index - The index at which to insert the menu.
	     *
	     * @param menu - The menu to insert into the menu bar.
	     *
	     * #### Notes
	     * The index will be clamped to the bounds of the menus.
	     *
	     * If the menu is already added to the menu bar, it will be moved.
	     */
	    MenuBar.prototype.insertMenu = function (index, menu) {
	        // Close the child menu before making changes.
	        this._closeChildMenu();
	        // Look up the index of the menu.
	        var i = searching_1.indexOf(this._menus, menu);
	        // Clamp the insert index to the vector bounds.
	        var j = Math.max(0, Math.min(Math.floor(index), this._menus.length));
	        // If the menu is not in the vector, insert it.
	        if (i === -1) {
	            // Create the new item node for the menu.
	            var node = this._renderer.createItemNode();
	            this._renderer.updateItemNode(node, menu.title);
	            // Insert the node and menu into the vectors.
	            this._nodes.insert(j, node);
	            this._menus.insert(j, menu);
	            // Add the styling class to the menu.
	            menu.addClass(MENU_CLASS);
	            // Look up the next sibling node.
	            var ref_1 = j + 1 < this._nodes.length ? this._nodes.at(j + 1) : null;
	            // Insert the item node into the content node.
	            this.contentNode.insertBefore(node, ref_1);
	            // Connect to the menu signals.
	            menu.aboutToClose.connect(this._onMenuAboutToClose, this);
	            menu.menuRequested.connect(this._onMenuMenuRequested, this);
	            menu.title.changed.connect(this._onTitleChanged, this);
	            // There is nothing more to do.
	            return;
	        }
	        // Otherwise, the menu exists in the vector and should be moved.
	        // Adjust the index if the location is at the end of the vector.
	        if (j === this._menus.length)
	            j--;
	        // Bail if there is no effective move.
	        if (i === j)
	            return;
	        // Move the item node and menu to the new locations.
	        mutation_1.move(this._nodes, i, j);
	        mutation_1.move(this._menus, i, j);
	        // Look up the next sibling node.
	        var ref = j + 1 < this._nodes.length ? this._nodes.at(j + 1) : null;
	        // Move the node in the content node.
	        this.contentNode.insertBefore(this._nodes.at(j), ref);
	    };
	    /**
	     * Remove a menu from the menu bar.
	     *
	     * @param menu - The menu to remove from the menu bar.
	     *
	     * @returns The index occupied by the menu, or `-1` if the menu
	     *   was not contained in the menu bar.
	     */
	    MenuBar.prototype.removeMenu = function (menu) {
	        var index = searching_1.indexOf(this._menus, menu);
	        if (index !== -1)
	            this.removeMenuAt(index);
	        return index;
	    };
	    /**
	     * Remove the menu at a given index from the menu bar.
	     *
	     * @param index - The index of the menu to remove.
	     *
	     * @returns The menu occupying the index, or `null` if the index
	     *   is out of range.
	     */
	    MenuBar.prototype.removeMenuAt = function (index) {
	        // Bail if the index is out of range.
	        var i = Math.floor(index);
	        if (i < 0 || i >= this._menus.length) {
	            return null;
	        }
	        // Close the child menu before making changes.
	        this._closeChildMenu();
	        // Remove the node and menu from the vectors.
	        var node = this._nodes.removeAt(i);
	        var menu = this._menus.removeAt(i);
	        // Disconnect from the menu signals.
	        menu.aboutToClose.disconnect(this._onMenuAboutToClose, this);
	        menu.menuRequested.disconnect(this._onMenuMenuRequested, this);
	        menu.title.changed.disconnect(this._onTitleChanged, this);
	        // Remove the node from the content node.
	        this.contentNode.removeChild(node);
	        // Remove the styling class from the menu.
	        menu.removeClass(MENU_CLASS);
	        // Return the removed menu.
	        return menu;
	    };
	    /**
	     * Remove all menus from the menu bar.
	     */
	    MenuBar.prototype.clearMenus = function () {
	        var _this = this;
	        // Bail if there is nothing to remove.
	        if (this._menus.length === 0) {
	            return;
	        }
	        // Close the child menu before making changes.
	        this._closeChildMenu();
	        // Disconnect from the menu signals and remove the styling class.
	        iteration_1.each(this._menus, function (menu) {
	            menu.aboutToClose.disconnect(_this._onMenuAboutToClose, _this);
	            menu.menuRequested.disconnect(_this._onMenuMenuRequested, _this);
	            menu.title.changed.disconnect(_this._onTitleChanged, _this);
	            menu.removeClass(MENU_CLASS);
	        });
	        // Clear the node and menus vectors.
	        this._nodes.clear();
	        this._menus.clear();
	        // Clear the content node.
	        this.contentNode.textContent = '';
	    };
	    /**
	     * Handle the DOM events for the menu bar.
	     *
	     * @param event - The DOM event sent to the menu bar.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the menu bar's DOM nodes. It
	     * should not be called directly by user code.
	     */
	    MenuBar.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'keydown':
	                this._evtKeyDown(event);
	                break;
	            case 'mousedown':
	                this._evtMouseDown(event);
	                break;
	            case 'mousemove':
	                this._evtMouseMove(event);
	                break;
	            case 'mouseleave':
	                this._evtMouseLeave(event);
	                break;
	            case 'contextmenu':
	                event.preventDefault();
	                event.stopPropagation();
	                break;
	        }
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    MenuBar.prototype.onAfterAttach = function (msg) {
	        this.node.addEventListener('keydown', this);
	        this.node.addEventListener('mousedown', this);
	        this.node.addEventListener('mousemove', this);
	        this.node.addEventListener('mouseleave', this);
	        this.node.addEventListener('contextmenu', this);
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    MenuBar.prototype.onBeforeDetach = function (msg) {
	        this.node.removeEventListener('keydown', this);
	        this.node.removeEventListener('mousedown', this);
	        this.node.removeEventListener('mousemove', this);
	        this.node.removeEventListener('mouseleave', this);
	        this.node.removeEventListener('contextmenu', this);
	        this._closeChildMenu();
	    };
	    /**
	     * A message handler invoked on an `'activate-request'` message.
	     */
	    MenuBar.prototype.onActivateRequest = function (msg) {
	        if (this.isAttached)
	            this.node.focus();
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    MenuBar.prototype.onUpdateRequest = function (msg) {
	        // Fetch common variables.
	        var menus = this._menus;
	        var nodes = this._nodes;
	        var renderer = this._renderer;
	        // Update the state of the item nodes.
	        for (var i = 0, n = menus.length; i < n; ++i) {
	            renderer.updateItemNode(nodes.at(i), menus.at(i).title);
	        }
	        // Add the active class to the active item.
	        if (this._activeIndex !== -1) {
	            nodes.at(this._activeIndex).classList.add(ACTIVE_CLASS);
	        }
	    };
	    /**
	     * Handle the `'keydown'` event for the menu bar.
	     */
	    MenuBar.prototype._evtKeyDown = function (event) {
	        // A menu bar handles all keydown events.
	        event.preventDefault();
	        event.stopPropagation();
	        // Fetch the key code for the event.
	        var kc = event.keyCode;
	        // Enter, Up Arrow, Down Arrow
	        if (kc === 13 || kc === 38 || kc === 40) {
	            this.openActiveMenu();
	            return;
	        }
	        // Escape
	        if (kc === 27) {
	            this._closeChildMenu();
	            this.activeIndex = -1;
	            this.node.blur();
	            return;
	        }
	        // Left Arrow
	        if (kc === 37) {
	            var i = this._activeIndex;
	            var n_1 = this._menus.length;
	            this.activeIndex = i === 0 ? n_1 - 1 : i - 1;
	            return;
	        }
	        // Right Arrow
	        if (kc === 39) {
	            var i = this._activeIndex;
	            var n_2 = this._menus.length;
	            this.activeIndex = i === n_2 - 1 ? 0 : i + 1;
	            return;
	        }
	        // The following code activates an item by mnemonic.
	        // Get the pressed key character for the current layout.
	        var key = this._keymap.layout.keyForKeydownEvent(event);
	        // Bail if the key is not valid for the current layout.
	        if (!key) {
	            return;
	        }
	        // Normalize the case of the key.
	        key = key.toUpperCase();
	        // Setup the storage for the search results.
	        var mnIndex = -1;
	        var autoIndex = -1;
	        var mnMultiple = false;
	        // Search for the best mnemonic menu. This searches the menus
	        // starting at the active index and finds the following:
	        //   - the index of the first matching mnemonic menu
	        //   - whether there are multiple matching mnemonic menus
	        //   - the index of the first menu with no mnemonic, but
	        //     which has a matching first character.
	        var n = this._menus.length;
	        var j = this._activeIndex + 1;
	        for (var i = 0; i < n; ++i) {
	            var k = (i + j) % n;
	            var title = this._menus.at(k).title;
	            if (title.label.length === 0) {
	                continue;
	            }
	            var mn = title.mnemonic;
	            if (mn >= 0 && mn < title.label.length) {
	                if (title.label[mn].toUpperCase() === key) {
	                    if (mnIndex === -1) {
	                        mnIndex = k;
	                    }
	                    else {
	                        mnMultiple = true;
	                    }
	                }
	            }
	            else if (autoIndex === -1) {
	                if (title.label[0].toUpperCase() === key) {
	                    autoIndex = k;
	                }
	            }
	        }
	        // Handle the requested mnemonic based on the search results.
	        // If exactly one mnemonic is matched, that menu is opened.
	        // Otherwise, the next mnemonic is activated if available,
	        // followed by the auto mnemonic if available.
	        if (mnIndex !== -1 && !mnMultiple) {
	            this.activeIndex = mnIndex;
	            this.openActiveMenu();
	        }
	        else if (mnIndex !== -1) {
	            this.activeIndex = mnIndex;
	        }
	        else if (autoIndex !== -1) {
	            this.activeIndex = autoIndex;
	        }
	    };
	    /**
	     * Handle the `'mousedown'` event for the menu bar.
	     */
	    MenuBar.prototype._evtMouseDown = function (event) {
	        // Bail if the mouse press was not on the menu bar. This can occur
	        // when the document listener is installed for an active menu bar.
	        var x = event.clientX;
	        var y = event.clientY;
	        if (!query_1.hitTest(this.node, x, y)) {
	            return;
	        }
	        // Stop the propagation of the event. Immediate propagation is
	        // also stopped so that an open menu does not handle the event.
	        event.preventDefault();
	        event.stopPropagation();
	        event.stopImmediatePropagation();
	        // Check if the mouse is over one of the menu items.
	        var i = searching_1.findIndex(this._nodes, function (node) { return query_1.hitTest(node, x, y); });
	        // If the press was not on an item, close the child menu.
	        if (i === -1) {
	            this._closeChildMenu();
	            return;
	        }
	        // If the press was not the left mouse button, do nothing further.
	        if (event.button !== 0) {
	            return;
	        }
	        // Otherwise, toggle the open state of the child menu.
	        if (this._childMenu) {
	            this._closeChildMenu();
	            this.activeIndex = i;
	        }
	        else {
	            this.activeIndex = i;
	            this._openChildMenu();
	        }
	    };
	    /**
	     * Handle the `'mousemove'` event for the menu bar.
	     */
	    MenuBar.prototype._evtMouseMove = function (event) {
	        // Check if the mouse is over one of the menu items.
	        var x = event.clientX;
	        var y = event.clientY;
	        var i = searching_1.findIndex(this._nodes, function (node) { return query_1.hitTest(node, x, y); });
	        // Bail early if the active index will not change.
	        if (i === this._activeIndex) {
	            return;
	        }
	        // Bail early if a child menu is open and the mouse is not over
	        // an item. This allows the child menu to be kept open when the
	        // mouse is over the empty part of the menu bar.
	        if (i === -1 && this._childMenu) {
	            return;
	        }
	        // Update the active index to the hovered item.
	        this.activeIndex = i;
	        // Open the new menu if a menu is already open.
	        if (this._childMenu) {
	            this._openChildMenu();
	        }
	    };
	    /**
	     * Handle the `'mouseleave'` event for the menu bar.
	     */
	    MenuBar.prototype._evtMouseLeave = function (event) {
	        // Reset the active index if there is no open menu.
	        if (!this._childMenu) {
	            this.activeIndex = -1;
	        }
	    };
	    /**
	     * Open the child menu at the active index immediately.
	     *
	     * If a different child menu is already open, it will be closed,
	     * even if there is no active menu.
	     */
	    MenuBar.prototype._openChildMenu = function () {
	        // If there is no active menu, close the current menu.
	        var newMenu = this.activeMenu;
	        if (!newMenu) {
	            this._closeChildMenu();
	            return;
	        }
	        // Bail, if there is no effective menu change.
	        var oldMenu = this._childMenu;
	        if (oldMenu === newMenu) {
	            return;
	        }
	        // Swap the internal menu reference.
	        this._childMenu = newMenu;
	        // Close the current menu, or setup for the new menu.
	        if (oldMenu) {
	            oldMenu.close();
	        }
	        else {
	            this.addClass(ACTIVE_CLASS);
	            document.addEventListener('mousedown', this, true);
	        }
	        // Get the positioning data for the new menu.
	        var node = this._nodes.at(this._activeIndex);
	        var _a = node.getBoundingClientRect(), left = _a.left, bottom = _a.bottom;
	        // Open the new menu at the computed location.
	        newMenu.open(left, bottom, { forceX: true, forceY: true });
	    };
	    /**
	     * Close the child menu immediately.
	     *
	     * This is a no-op if a child menu is not open.
	     */
	    MenuBar.prototype._closeChildMenu = function () {
	        // Bail if no child menu is open.
	        if (!this._childMenu) {
	            return;
	        }
	        // Remove the active class from the menu bar.
	        this.removeClass(ACTIVE_CLASS);
	        // Remove the document listeners.
	        document.removeEventListener('mousedown', this, true);
	        // Clear the internal menu reference.
	        var menu = this._childMenu;
	        this._childMenu = null;
	        // Close the menu.
	        menu.close();
	        // Reset the active index.
	        this.activeIndex = -1;
	    };
	    /**
	     * Handle the `aboutToClose` signal of a menu.
	     */
	    MenuBar.prototype._onMenuAboutToClose = function (sender) {
	        // Bail if the sender is not the child menu.
	        if (sender !== this._childMenu) {
	            return;
	        }
	        // Remove the active class from the menu bar.
	        this.removeClass(ACTIVE_CLASS);
	        // Remove the document listeners.
	        document.removeEventListener('mousedown', this, true);
	        // Clear the internal menu reference.
	        this._childMenu = null;
	        // Reset the active index.
	        this.activeIndex = -1;
	    };
	    /**
	     * Handle the `menuRequested` signal of a child menu.
	     */
	    MenuBar.prototype._onMenuMenuRequested = function (sender, args) {
	        // Bail if the sender is not the child menu.
	        if (sender !== this._childMenu) {
	            return;
	        }
	        // Lookup the active index and menu count.
	        var i = this._activeIndex;
	        var n = this._menus.length;
	        // Active the next requested index.
	        switch (args) {
	            case 'next':
	                this.activeIndex = i === n - 1 ? 0 : i + 1;
	                break;
	            case 'previous':
	                this.activeIndex = i === 0 ? n - 1 : i - 1;
	                break;
	        }
	        // Open the active menu.
	        this.openActiveMenu();
	    };
	    /**
	     * Handle the `changed` signal of a title object.
	     */
	    MenuBar.prototype._onTitleChanged = function (sender) {
	        this.update();
	    };
	    return MenuBar;
	}(widget_1.Widget));
	exports.MenuBar = MenuBar;
	/**
	 * The namespaces for the `MenuBar` class statics.
	 */
	var MenuBar;
	(function (MenuBar) {
	    /**
	     * The default implementation of `IRenderer`.
	     */
	    var Renderer = (function () {
	        function Renderer() {
	        }
	        /**
	         * Create a node for a menu bar item.
	         *
	         * @returns A new node for a menu bar item.
	         */
	        Renderer.prototype.createItemNode = function () {
	            var node = document.createElement('li');
	            var icon = document.createElement('div');
	            var label = document.createElement('div');
	            node.className = ITEM_CLASS;
	            icon.className = ICON_CLASS;
	            label.className = LABEL_CLASS;
	            node.appendChild(icon);
	            node.appendChild(label);
	            return node;
	        };
	        /**
	         * Update an item node to reflect the state of a menu title.
	         *
	         * @param node - A node created by a call to `createItemNode`.
	         *
	         * @param title - The menu title holding the data for the node.
	         */
	        Renderer.prototype.updateItemNode = function (node, title) {
	            var icon = node.firstChild;
	            var label = node.lastChild;
	            var itemClass = ITEM_CLASS;
	            var iconClass = ICON_CLASS;
	            if (title.className)
	                itemClass += " " + title.className;
	            if (title.icon)
	                iconClass += " " + title.icon;
	            node.className = itemClass;
	            icon.className = iconClass;
	            label.innerHTML = this.formatLabel(title.label, title.mnemonic);
	        };
	        /**
	         * Format a label into HTML for display.
	         *
	         * @param label - The label text of interest.
	         *
	         * @param mnemonic - The index of the mnemonic character.
	         *
	         * @return The formatted label HTML for display.
	         */
	        Renderer.prototype.formatLabel = function (label, mnemonic) {
	            // If the index is out of range, do not modify the label.
	            if (mnemonic < 0 || mnemonic >= label.length) {
	                return label;
	            }
	            // Split the label into parts.
	            var pref = label.slice(0, mnemonic);
	            var suff = label.slice(mnemonic + 1);
	            var char = label[mnemonic];
	            // Join the label with the mnemonic span.
	            return pref + "<span class=\"" + MNEMONIC_CLASS + "\">" + char + "</span>" + suff;
	        };
	        return Renderer;
	    }());
	    MenuBar.Renderer = Renderer;
	    /**
	     * The default `Renderer` instance.
	     */
	    MenuBar.defaultRenderer = new Renderer();
	})(MenuBar = exports.MenuBar || (exports.MenuBar = {}));
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create the DOM node for a menu bar.
	     */
	    function createNode() {
	        var node = document.createElement('div');
	        var content = document.createElement('ul');
	        content.className = CONTENT_CLASS;
	        node.appendChild(content);
	        node.tabIndex = -1;
	        return node;
	    }
	    Private.createNode = createNode;
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/menubar.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/codemirror/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	var factory_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codemirror/factory.js');
	var mimetype_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codemirror/mimetype.js');
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/codemirror/mode.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/codemirror/editor.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/codemirror/factory.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/codemirror/mimetype.js'));
	/**
	 * The default editor services.
	 */
	exports.editorServices = {
	    factoryService: new factory_1.CodeMirrorEditorFactory(),
	    mimeTypeService: new mimetype_1.CodeMirrorMimeTypeService()
	};
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/factory.js **/
jupyter.define('jupyterlab@0.15.1/lib/codemirror/factory.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var editor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codemirror/editor.js');
	/**
	 * CodeMirror editor factory.
	 */
	var CodeMirrorEditorFactory = (function () {
	    function CodeMirrorEditorFactory() {
	    }
	    /**
	     * Create a new editor for inline code.
	     */
	    CodeMirrorEditorFactory.prototype.newInlineEditor = function (options) {
	        return new editor_1.CodeMirrorEditor(options, {
	            extraKeys: {
	                'Cmd-Right': 'goLineRight',
	                'End': 'goLineRight',
	                'Cmd-Left': 'goLineLeft',
	                'Tab': 'indentMore',
	                'Shift-Tab': 'indentLess',
	                'Cmd-Alt-[': 'indentAuto',
	                'Ctrl-Alt-[': 'indentAuto',
	                'Cmd-/': 'toggleComment',
	                'Ctrl-/': 'toggleComment',
	            }
	        });
	    };
	    /**
	     * Create a new editor for a full document.
	     */
	    CodeMirrorEditorFactory.prototype.newDocumentEditor = function (options) {
	        return new editor_1.CodeMirrorEditor(options, {
	            extraKeys: {
	                'Tab': 'indentMore',
	                'Shift-Enter': function () { }
	            },
	            lineNumbers: true,
	            lineWrapping: true
	        });
	    };
	    return CodeMirrorEditorFactory;
	}());
	exports.CodeMirrorEditorFactory = CodeMirrorEditorFactory;
	//# sourceMappingURL=factory.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/factory.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/editor.js **/
jupyter.define('jupyterlab@0.15.1/lib/codemirror/editor.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var CodeMirror = __jupyter_require__('codemirror@^5.20.2/lib/codemirror.js');
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/codemirror/index.js');
	/**
	 * The class name added to CodeMirrorWidget instances.
	 */
	var EDITOR_CLASS = 'jp-CodeMirrorWidget';
	/**
	 * The class name added to read only cell editor widgets.
	 */
	var READ_ONLY_CLASS = 'jp-mod-readOnly';
	/**
	 * The key code for the up arrow key.
	 */
	var UP_ARROW = 38;
	/**
	 * The key code for the down arrow key.
	 */
	var DOWN_ARROW = 40;
	/**
	 * The key code for the tab key.
	 */
	var TAB = 9;
	/**
	 * CodeMirror editor.
	 */
	var CodeMirrorEditor = (function () {
	    /**
	     * Construct a CodeMirror editor.
	     */
	    function CodeMirrorEditor(options, config) {
	        var _this = this;
	        if (config === void 0) { config = {}; }
	        this.selectionMarkers = {};
	        this._keydownHandlers = new vector_1.Vector();
	        this._changeGuard = false;
	        this._uuid = '';
	        var host = this._host = options.host;
	        host.classList.add(EDITOR_CLASS);
	        this._uuid = options.uuid || services_1.utils.uuid();
	        this._selectionStyle = options.selectionStyle || {};
	        Private.updateConfig(options, config);
	        var model = this._model = options.model;
	        var editor = this._editor = CodeMirror(host, config);
	        var doc = editor.getDoc();
	        // Handle initial values for text, mimetype, and selections.
	        doc.setValue(model.value.text);
	        this._onMimeTypeChanged();
	        this._onCursorActivity();
	        // Connect to changes.
	        model.value.changed.connect(this._onValueChanged, this);
	        model.mimeTypeChanged.connect(this._onMimeTypeChanged, this);
	        model.selections.changed.connect(this._onSelectionsChanged, this);
	        CodeMirror.on(editor, 'keydown', function (editor, event) {
	            var index = searching_1.findIndex(_this._keydownHandlers, function (handler) {
	                if (handler(_this, event) === true) {
	                    event.preventDefault();
	                    return true;
	                }
	            });
	            if (index === -1) {
	                _this.onKeydown(event);
	            }
	        });
	        CodeMirror.on(editor, 'cursorActivity', function () { return _this._onCursorActivity(); });
	        CodeMirror.on(editor.getDoc(), 'change', function (instance, change) {
	            _this._onDocChanged(instance, change);
	        });
	    }
	    Object.defineProperty(CodeMirrorEditor.prototype, "uuid", {
	        /**
	         * The uuid of this editor;
	         */
	        get: function () {
	            return this._uuid;
	        },
	        set: function (value) {
	            this._uuid = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "selectionStyle", {
	        /**
	         * The selection style of this editor.
	         */
	        get: function () {
	            return this._selectionStyle;
	        },
	        set: function (value) {
	            this._selectionStyle = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "editor", {
	        /**
	         * Get the codemirror editor wrapped by the editor.
	         */
	        get: function () {
	            return this._editor;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "doc", {
	        /**
	         * Get the codemirror doc wrapped by the widget.
	         */
	        get: function () {
	            return this._editor.getDoc();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "lineCount", {
	        /**
	         * Get the number of lines in the editor.
	         */
	        get: function () {
	            return this.doc.lineCount();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "lineNumbers", {
	        /**
	         * Control the rendering of line numbers.
	         */
	        get: function () {
	            return this._editor.getOption('lineNumbers');
	        },
	        set: function (value) {
	            this._editor.setOption('lineNumbers', value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "wordWrap", {
	        /**
	         * Set to false for horizontal scrolling. Defaults to true.
	         */
	        get: function () {
	            return this._editor.getOption('lineWrapping');
	        },
	        set: function (value) {
	            this._editor.setOption('lineWrapping', value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "readOnly", {
	        /**
	         * Should the editor be read only.
	         */
	        get: function () {
	            return this._editor.getOption('readOnly') !== false;
	        },
	        set: function (readOnly) {
	            this._editor.setOption('readOnly', readOnly);
	            if (readOnly) {
	                this._host.classList.add(READ_ONLY_CLASS);
	            }
	            else {
	                this._host.classList.remove(READ_ONLY_CLASS);
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "model", {
	        /**
	         * Returns a model for this editor.
	         */
	        get: function () {
	            return this._model;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "lineHeight", {
	        /**
	         * The height of a line in the editor in pixels.
	         */
	        get: function () {
	            return this._editor.defaultTextHeight();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "charWidth", {
	        /**
	         * The widget of a character in the editor in pixels.
	         */
	        get: function () {
	            return this._editor.defaultCharWidth();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeMirrorEditor.prototype, "isDisposed", {
	        /**
	         * Tests whether the editor is disposed.
	         */
	        get: function () {
	            return this._editor === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    CodeMirrorEditor.prototype.dispose = function () {
	        if (this._editor === null) {
	            return;
	        }
	        this._editor = null;
	        this._model = null;
	        this._keydownHandlers.clear();
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Returns the content for the given line number.
	     */
	    CodeMirrorEditor.prototype.getLine = function (line) {
	        return this.doc.getLine(line);
	    };
	    /**
	     * Find an offset for the given position.
	     */
	    CodeMirrorEditor.prototype.getOffsetAt = function (position) {
	        return this.doc.indexFromPos({
	            ch: position.column,
	            line: position.line
	        });
	    };
	    /**
	     * Find a position fot the given offset.
	     */
	    CodeMirrorEditor.prototype.getPositionAt = function (offset) {
	        var _a = this.doc.posFromIndex(offset), ch = _a.ch, line = _a.line;
	        return { line: line, column: ch };
	    };
	    /**
	     * Undo one edit (if any undo events are stored).
	     */
	    CodeMirrorEditor.prototype.undo = function () {
	        this.doc.undo();
	    };
	    /**
	     * Redo one undone edit.
	     */
	    CodeMirrorEditor.prototype.redo = function () {
	        this.doc.redo();
	    };
	    /**
	     * Clear the undo history.
	     */
	    CodeMirrorEditor.prototype.clearHistory = function () {
	        this.doc.clearHistory();
	    };
	    /**
	     * Brings browser focus to this editor text.
	     */
	    CodeMirrorEditor.prototype.focus = function () {
	        this._editor.focus();
	    };
	    /**
	     * Test whether the editor has keyboard focus.
	     */
	    CodeMirrorEditor.prototype.hasFocus = function () {
	        return this._editor.hasFocus();
	    };
	    /**
	     * Repaint editor.
	     */
	    CodeMirrorEditor.prototype.refresh = function () {
	        this._editor.refresh();
	    };
	    /**
	     * Add a keydown handler to the editor.
	     *
	     * @param handler - A keydown handler.
	     *
	     * @returns A disposable that can be used to remove the handler.
	     */
	    CodeMirrorEditor.prototype.addKeydownHandler = function (handler) {
	        var _this = this;
	        this._keydownHandlers.pushBack(handler);
	        return new disposable_1.DisposableDelegate(function () {
	            _this._keydownHandlers.remove(handler);
	        });
	    };
	    /**
	     * Set the size of the editor in pixels.
	     */
	    CodeMirrorEditor.prototype.setSize = function (dimension) {
	        if (dimension) {
	            this._editor.setSize(dimension.width, dimension.height);
	        }
	        else {
	            this._editor.setSize(null, null);
	        }
	    };
	    /**
	     * Reveal the given position in the editor.
	     */
	    CodeMirrorEditor.prototype.revealPosition = function (position) {
	        var cmPosition = this._toCodeMirrorPosition(position);
	        this._editor.scrollIntoView(cmPosition);
	    };
	    /**
	     * Reveal the given selection in the editor.
	     */
	    CodeMirrorEditor.prototype.revealSelection = function (selection) {
	        var range = this._toCodeMirrorRange(selection);
	        this._editor.scrollIntoView(range);
	    };
	    /**
	     * Get the window coordinates given a cursor position.
	     */
	    CodeMirrorEditor.prototype.getCoordinate = function (position) {
	        return this.editor.charCoords(this._toCodeMirrorPosition(position), 'page');
	    };
	    /**
	     * Returns the primary position of the cursor, never `null`.
	     */
	    CodeMirrorEditor.prototype.getCursorPosition = function () {
	        var cursor = this.doc.getCursor();
	        return this._toPosition(cursor);
	    };
	    /**
	     * Set the primary position of the cursor.
	     *
	     * #### Notes
	     * This will remove any secondary cursors.
	     */
	    CodeMirrorEditor.prototype.setCursorPosition = function (position) {
	        var cursor = this._toCodeMirrorPosition(position);
	        this.doc.setCursor(cursor);
	    };
	    /**
	     * Returns the primary selection, never `null`.
	     */
	    CodeMirrorEditor.prototype.getSelection = function () {
	        return this.getSelections()[0];
	    };
	    /**
	     * Set the primary selection. This will remove any secondary cursors.
	     */
	    CodeMirrorEditor.prototype.setSelection = function (selection) {
	        this.setSelections([selection]);
	    };
	    /**
	     * Gets the selections for all the cursors, never `null` or empty.
	     */
	    CodeMirrorEditor.prototype.getSelections = function () {
	        var _this = this;
	        var selections = this.doc.listSelections();
	        if (selections.length > 0) {
	            return selections.map(function (selection) { return _this._toSelection(selection); });
	        }
	        var cursor = this.doc.getCursor();
	        var selection = this._toSelection({ anchor: cursor, head: cursor });
	        return [selection];
	    };
	    /**
	     * Sets the selections for all the cursors, should not be empty.
	     * Cursors will be removed or added, as necessary.
	     * Passing an empty array resets a cursor position to the start of a document.
	     */
	    CodeMirrorEditor.prototype.setSelections = function (selections) {
	        var cmSelections = this._toCodeMirrorSelections(selections);
	        this.doc.setSelections(cmSelections, 0);
	    };
	    /**
	     * Handle keydown events from the editor.
	     */
	    CodeMirrorEditor.prototype.onKeydown = function (event) {
	        var position = this.getCursorPosition();
	        var line = position.line, column = position.column;
	        if (event.keyCode === TAB) {
	            // If the tab is modified, ignore it.
	            if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
	                return false;
	            }
	            this.onTabEvent(event, position);
	            return false;
	        }
	        if (line === 0 && column === 0 && event.keyCode === UP_ARROW) {
	            if (!event.shiftKey) {
	                this.edgeRequested.emit('top');
	            }
	            return false;
	        }
	        var lastLine = this.lineCount - 1;
	        var lastCh = this.getLine(lastLine).length;
	        if (line === lastLine && column === lastCh
	            && event.keyCode === DOWN_ARROW) {
	            if (!event.shiftKey) {
	                this.edgeRequested.emit('bottom');
	            }
	            return false;
	        }
	        return false;
	    };
	    /**
	     * Handle a tab key press.
	     */
	    CodeMirrorEditor.prototype.onTabEvent = function (event, position) {
	        // If there is a text selection, no completion requests should be emitted.
	        var selection = this.getSelection();
	        if (selection.start === selection.end) {
	            return;
	        }
	        var currentLine = this.getLine(position.line);
	        // A completion request signal should only be emitted if the current
	        // character or a preceding character is not whitespace.
	        //
	        // Otherwise, the default tab action of creating a tab character should be
	        // allowed to propagate.
	        if (!currentLine.substring(0, position.column).match(/\S/)) {
	            return;
	        }
	        event.preventDefault();
	        event.stopPropagation();
	        event.stopImmediatePropagation();
	        this.completionRequested.emit(position);
	    };
	    /**
	     * Converts selections to code mirror selections.
	     */
	    CodeMirrorEditor.prototype._toCodeMirrorSelections = function (selections) {
	        var _this = this;
	        if (selections.length > 0) {
	            return selections.map(function (selection) { return _this._toCodeMirrorSelection(selection); });
	        }
	        var position = { line: 0, ch: 0 };
	        return [{ anchor: position, head: position }];
	    };
	    /**
	     * Handles a mime type change.
	     */
	    CodeMirrorEditor.prototype._onMimeTypeChanged = function () {
	        var mime = this._model.mimeType;
	        var editor = this._editor;
	        _1.loadModeByMIME(editor, mime);
	        var isCode = (mime !== 'text/plain') && (mime !== 'text/x-ipythongfm');
	        editor.setOption('matchBrackets', isCode);
	        editor.setOption('autoCloseBrackets', isCode);
	        var extraKeys = editor.getOption('extraKeys') || {};
	        if (isCode) {
	            extraKeys['Backspace'] = 'delSpaceToPrevTabStop';
	        }
	        else {
	            delete extraKeys['Backspace'];
	        }
	        editor.setOption('extraKeys', extraKeys);
	    };
	    /**
	     * Handles a selections change.
	     */
	    CodeMirrorEditor.prototype._onSelectionsChanged = function (selections, args) {
	        var uuid = args.uuid;
	        if (uuid !== this.uuid) {
	            this._cleanSelections(uuid);
	            this._markSelections(uuid, args.newSelections);
	        }
	    };
	    /**
	     * Clean selections for the given uuid.
	     */
	    CodeMirrorEditor.prototype._cleanSelections = function (uuid) {
	        var markers = this.selectionMarkers[uuid];
	        if (markers) {
	            markers.forEach(function (marker) { return marker.clear(); });
	        }
	        delete this.selectionMarkers[uuid];
	    };
	    /**
	     * Marks selections.
	     */
	    CodeMirrorEditor.prototype._markSelections = function (uuid, selections) {
	        var markers = [];
	        for (var _i = 0, selections_1 = selections; _i < selections_1.length; _i++) {
	            var selection = selections_1[_i];
	            var _a = this._toCodeMirrorSelection(selection), anchor = _a.anchor, head = _a.head;
	            var markerOptions = this._toTextMarkerOptions(selection);
	            this.doc.markText(anchor, head, markerOptions);
	        }
	        this.selectionMarkers[uuid] = markers;
	    };
	    /**
	     * Handles a cursor activity event.
	     */
	    CodeMirrorEditor.prototype._onCursorActivity = function () {
	        var selections = this.getSelections();
	        this.model.selections.setSelections(this.uuid, selections);
	    };
	    /**
	     * Converts a code mirror selection to an editor selection.
	     */
	    CodeMirrorEditor.prototype._toSelection = function (selection) {
	        return {
	            uuid: this.uuid,
	            start: this._toPosition(selection.anchor),
	            end: this._toPosition(selection.head),
	            style: this.selectionStyle
	        };
	    };
	    /**
	     * Converts the selection style to a text marker options.
	     */
	    CodeMirrorEditor.prototype._toTextMarkerOptions = function (style) {
	        if (style) {
	            return {
	                className: style.className,
	                title: style.displayName
	            };
	        }
	        return undefined;
	    };
	    /**
	     * Converts an editor selection to a code mirror selection.
	     */
	    CodeMirrorEditor.prototype._toCodeMirrorSelection = function (selection) {
	        return {
	            anchor: this._toCodeMirrorPosition(selection.start),
	            head: this._toCodeMirrorPosition(selection.end)
	        };
	    };
	    /**
	     * Converts an editor selection to a code mirror selection.
	     */
	    CodeMirrorEditor.prototype._toCodeMirrorRange = function (range) {
	        return {
	            from: this._toCodeMirrorPosition(range.start),
	            to: this._toCodeMirrorPosition(range.end)
	        };
	    };
	    /**
	     * Convert a code mirror position to an editor position.
	     */
	    CodeMirrorEditor.prototype._toPosition = function (position) {
	        return {
	            line: position.line,
	            column: position.ch
	        };
	    };
	    /**
	     * Convert an editor position to a code mirror position.
	     */
	    CodeMirrorEditor.prototype._toCodeMirrorPosition = function (position) {
	        return {
	            line: position.line,
	            ch: position.column
	        };
	    };
	    /**
	     * Handle model value changes.
	     */
	    CodeMirrorEditor.prototype._onValueChanged = function (value, args) {
	        if (this._changeGuard) {
	            return;
	        }
	        this._changeGuard = true;
	        var doc = this.doc;
	        switch (args.type) {
	            case 'insert':
	                var pos = doc.posFromIndex(args.start);
	                doc.replaceRange(args.value, pos, pos);
	                break;
	            case 'remove':
	                var from = doc.posFromIndex(args.start);
	                var to = doc.posFromIndex(args.end);
	                doc.replaceRange('', from, to);
	                break;
	            case 'set':
	                doc.setValue(args.value);
	                break;
	            default:
	                break;
	        }
	        this._changeGuard = false;
	    };
	    /**
	     * Handles document changes.
	     */
	    CodeMirrorEditor.prototype._onDocChanged = function (doc, change) {
	        if (this._changeGuard) {
	            return;
	        }
	        this._changeGuard = true;
	        var value = this._model.value;
	        var start = doc.indexFromPos(change.from);
	        var inserted = change.text.join('\n');
	        var removed = change.removed.join('\n');
	        if (removed) {
	            value.remove(start, start + removed.length);
	        }
	        if (inserted) {
	            value.insert(start, inserted);
	        }
	        this._changeGuard = false;
	    };
	    return CodeMirrorEditor;
	}());
	exports.CodeMirrorEditor = CodeMirrorEditor;
	/**
	 * The namespace for `CodeMirrorEditor` statics.
	 */
	var CodeMirrorEditor;
	(function (CodeMirrorEditor) {
	    /**
	     * The name of the default CodeMirror theme
	     */
	    CodeMirrorEditor.DEFAULT_THEME = 'jupyter';
	})(CodeMirrorEditor = exports.CodeMirrorEditor || (exports.CodeMirrorEditor = {}));
	// Define the signals for the `CodeMirrorEditor` class.
	signaling_1.defineSignal(CodeMirrorEditor.prototype, 'completionRequested');
	signaling_1.defineSignal(CodeMirrorEditor.prototype, 'edgeRequested');
	/**
	 * The namespace for module private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Handle extra codemirror config from codeeditor options.
	     */
	    function updateConfig(options, config) {
	        if (options.readOnly !== undefined) {
	            config.readOnly = options.readOnly;
	        }
	        else {
	            config.readOnly = false;
	        }
	        if (options.lineNumbers !== undefined) {
	            config.lineNumbers = options.lineNumbers;
	        }
	        else {
	            config.lineNumbers = false;
	        }
	        if (options.wordWrap !== undefined) {
	            config.lineWrapping = options.wordWrap;
	        }
	        else {
	            config.lineWrapping = true;
	        }
	        config.theme = (config.theme || CodeMirrorEditor.DEFAULT_THEME);
	        config.indentUnit = config.indentUnit || 4;
	    }
	    Private.updateConfig = updateConfig;
	    /**
	     * Delete spaces to the previous tab stob in a codemirror editor.
	     */
	    function delSpaceToPrevTabStop(cm) {
	        var doc = cm.getDoc();
	        var from = doc.getCursor('from');
	        var to = doc.getCursor('to');
	        var sel = !posEq(from, to);
	        if (sel) {
	            var ranges = doc.listSelections();
	            for (var i = ranges.length - 1; i >= 0; i--) {
	                var head = ranges[i].head;
	                var anchor = ranges[i].anchor;
	                doc.replaceRange('', CodeMirror.Pos(head.line, head.ch), CodeMirror.Pos(anchor.line, anchor.ch));
	            }
	            return;
	        }
	        var cur = doc.getCursor();
	        var tabsize = cm.getOption('tabSize');
	        var chToPrevTabStop = cur.ch - (Math.ceil(cur.ch / tabsize) - 1) * tabsize;
	        from = { ch: cur.ch - chToPrevTabStop, line: cur.line };
	        var select = doc.getRange(from, cur);
	        if (select.match(/^\ +$/) !== null) {
	            doc.replaceRange('', from, cur);
	        }
	        else {
	            CodeMirror.commands['delCharBefore'](cm);
	        }
	    }
	    Private.delSpaceToPrevTabStop = delSpaceToPrevTabStop;
	    ;
	    /**
	     * Test whether two CodeMirror positions are equal.
	     */
	    function posEq(a, b) {
	        return a.line === b.line && a.ch === b.ch;
	    }
	    Private.posEq = posEq;
	    ;
	})(Private || (Private = {}));
	/**
	 * Add a CodeMirror command to delete until previous non blanking space
	 * character or first multiple of 4 tabstop.
	 */
	CodeMirror.commands['delSpaceToPrevTabStop'] = Private.delSpaceToPrevTabStop;
	//# sourceMappingURL=editor.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/editor.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/mimetype.js **/
jupyter.define('jupyterlab@0.15.1/lib/codemirror/mimetype.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var CodeMirror = __jupyter_require__('codemirror@^5.20.2/lib/codemirror.js');
	var codeeditor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/index.js');
	var index_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codemirror/index.js');
	/**
	 * The mime type service for CodeMirror.
	 */
	var CodeMirrorMimeTypeService = (function () {
	    function CodeMirrorMimeTypeService() {
	    }
	    /**
	     * Returns a mime type for the given language info.
	     *
	     * #### Notes
	     * If a mime type cannot be found returns the defaul mime type `text/plain`, never `null`.
	     */
	    CodeMirrorMimeTypeService.prototype.getMimeTypeByLanguage = function (info) {
	        if (info.codemirror_mode) {
	            return index_1.findMode(info.codemirror_mode).mime;
	        }
	        var mode = CodeMirror.findModeByMIME(info.mimetype || '');
	        if (mode) {
	            return info.mimetype;
	        }
	        var ext = info.file_extension || '';
	        ext = ext.split('.').slice(-1)[0];
	        mode = CodeMirror.findModeByExtension(ext || '');
	        if (mode) {
	            return mode.mime;
	        }
	        mode = CodeMirror.findModeByName(info.name || '');
	        return mode ? mode.mime : codeeditor_1.IEditorMimeTypeService.defaultMimeType;
	    };
	    /**
	     * Returns a mime type for the given file path.
	     *
	     * #### Notes
	     * If a mime type cannot be found returns the defaul mime type `text/plain`, never `null`.
	     */
	    CodeMirrorMimeTypeService.prototype.getMimeTypeByFilePath = function (path) {
	        var mode = CodeMirror.findModeByFileName(path);
	        return mode ? mode.mime : codeeditor_1.IEditorMimeTypeService.defaultMimeType;
	    };
	    return CodeMirrorMimeTypeService;
	}());
	exports.CodeMirrorMimeTypeService = CodeMirrorMimeTypeService;
	//# sourceMappingURL=mimetype.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/mimetype.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/mode.js **/
jupyter.define('jupyterlab@0.15.1/lib/codemirror/mode.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var CodeMirror = __jupyter_require__('codemirror@^5.20.2/lib/codemirror.js');
	__jupyter_require__('codemirror@^5.20.2/mode/meta.js');
	__jupyter_require__('jupyterlab@0.15.1/lib/codemirror/codemirror-ipython.js');
	__jupyter_require__('jupyterlab@0.15.1/lib/codemirror/codemirror-ipythongfm.js');
	// Bundle other common modes
	__jupyter_require__('codemirror@^5.20.2/mode/javascript/javascript.js');
	__jupyter_require__('codemirror@^5.20.2/mode/css/css.js');
	__jupyter_require__('codemirror@^5.20.2/mode/julia/julia.js');
	__jupyter_require__('codemirror@^5.20.2/mode/r/r.js');
	__jupyter_require__('codemirror@^5.20.2/mode/markdown/markdown.js');
	/**
	 * Load a codemirror mode by file name.
	 */
	function loadModeByFileName(editor, filename) {
	    loadInfo(editor, CodeMirror.findModeByFileName(filename));
	}
	exports.loadModeByFileName = loadModeByFileName;
	/**
	 * Load a codemirror mode by mime type.
	 */
	function loadModeByMIME(editor, mimetype) {
	    loadInfo(editor, CodeMirror.findModeByMIME(mimetype));
	}
	exports.loadModeByMIME = loadModeByMIME;
	/**
	 * Load a codemirror mode by mode name.
	 */
	function loadModeByName(editor, mode) {
	    loadInfo(editor, CodeMirror.findModeByName(mode));
	}
	exports.loadModeByName = loadModeByName;
	/**
	 * Find a codemirror mode by name or CodeMirror spec.
	 */
	function findMode(mode) {
	    var modename = (typeof mode === 'string') ? mode :
	        mode.mode || mode.name;
	    var mimetype = (typeof mode !== 'string') ? mode.mime : '';
	    return (CodeMirror.findModeByName(modename) ||
	        CodeMirror.findModeByMIME(mimetype) ||
	        CodeMirror.modes['null']);
	}
	exports.findMode = findMode;
	/**
	 * Require a codemirror mode by name or Codemirror spec.
	 */
	function requireMode(mode) {
	    var info = findMode(mode);
	    // Simplest, cheapest check by mode name.
	    if (CodeMirror.modes.hasOwnProperty(info.mode)) {
	        return Promise.resolve(info);
	    }
	    // Fetch the mode asynchronously.
	    return new Promise(function (resolve, reject) {
	        __jupyter_require__.ensure('lab/1.1.bundle.js', function(__jupyter_require__) { var __WEBPACK_AMD_REQUIRE_ARRAY__ = [(__jupyter_require__('codemirror@^5.20.2/mode')("./" + info.mode + "/" + info.mode))]; (function () {
	            resolve(info);
	        }.apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__));});
	    });
	}
	exports.requireMode = requireMode;
	/**
	 * Load a CodeMirror mode based on a mode spec.
	 */
	function loadInfo(editor, info) {
	    if (!info) {
	        editor.setOption('mode', 'null');
	        return;
	    }
	    requireMode(info).then(function () {
	        editor.setOption('mode', info.mime);
	    });
	}
	//# sourceMappingURL=mode.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/mode.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/codemirror-ipython.js **/
jupyter.define('jupyterlab@0.15.1/lib/codemirror/codemirror-ipython.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var CodeMirror = __jupyter_require__('codemirror@^5.20.2/lib/codemirror.js');
	__jupyter_require__('codemirror@^5.20.2/mode/meta.js');
	__jupyter_require__('codemirror@^5.20.2/mode/python/python.js');
	/**
	 * Define an IPython codemirror mode.
	 *
	 * It is a slightly altered Python Mode with a `?` operator.
	 */
	CodeMirror.defineMode('ipython', function (config, modeOptions) {
	    var pythonConf = {};
	    for (var prop in modeOptions) {
	        if (modeOptions.hasOwnProperty(prop)) {
	            pythonConf[prop] = modeOptions[prop];
	        }
	    }
	    pythonConf.name = 'python';
	    pythonConf.singleOperators = new RegExp('^[\\+\\-\\*/%&|@\\^~<>!\\?]');
	    pythonConf.identifiers = new RegExp('^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*');
	    return CodeMirror.getMode(config, pythonConf);
	}, 'python');
	CodeMirror.defineMIME('text/x-ipython', 'ipython');
	CodeMirror.modeInfo.push({
	    ext: [],
	    mime: 'text/x-ipython',
	    mode: 'ipython',
	    name: 'ipython'
	});
	//# sourceMappingURL=codemirror-ipython.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/codemirror-ipython.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/python/python.js **/
jupyter.define('codemirror@5.23.0/mode/python/python.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  "use strict";
	
	  function wordRegexp(words) {
	    return new RegExp("^((" + words.join(")|(") + "))\\b");
	  }
	
	  var wordOperators = wordRegexp(["and", "or", "not", "is"]);
	  var commonKeywords = ["as", "assert", "break", "class", "continue",
	                        "def", "del", "elif", "else", "except", "finally",
	                        "for", "from", "global", "if", "import",
	                        "lambda", "pass", "raise", "return",
	                        "try", "while", "with", "yield", "in"];
	  var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
	                        "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
	                        "enumerate", "eval", "filter", "float", "format", "frozenset",
	                        "getattr", "globals", "hasattr", "hash", "help", "hex", "id",
	                        "input", "int", "isinstance", "issubclass", "iter", "len",
	                        "list", "locals", "map", "max", "memoryview", "min", "next",
	                        "object", "oct", "open", "ord", "pow", "property", "range",
	                        "repr", "reversed", "round", "set", "setattr", "slice",
	                        "sorted", "staticmethod", "str", "sum", "super", "tuple",
	                        "type", "vars", "zip", "__import__", "NotImplemented",
	                        "Ellipsis", "__debug__"];
	  CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins));
	
	  function top(state) {
	    return state.scopes[state.scopes.length - 1];
	  }
	
	  CodeMirror.defineMode("python", function(conf, parserConf) {
	    var ERRORCLASS = "error";
	
	    var singleDelimiters = parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.]/;
	    var doubleOperators = parserConf.doubleOperators || /^([!<>]==|<>|<<|>>|\/\/|\*\*)/;
	    var doubleDelimiters = parserConf.doubleDelimiters || /^(\+=|\-=|\*=|%=|\/=|&=|\|=|\^=)/;
	    var tripleDelimiters = parserConf.tripleDelimiters || /^(\/\/=|>>=|<<=|\*\*=)/;
	
	    var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
	
	    var myKeywords = commonKeywords, myBuiltins = commonBuiltins;
	    if (parserConf.extra_keywords != undefined)
	      myKeywords = myKeywords.concat(parserConf.extra_keywords);
	
	    if (parserConf.extra_builtins != undefined)
	      myBuiltins = myBuiltins.concat(parserConf.extra_builtins);
	
	    var py3 = !(parserConf.version && Number(parserConf.version) < 3)
	    if (py3) {
	      // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
	      var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!@]/;
	      var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
	      myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]);
	      myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
	      var stringPrefixes = new RegExp("^(([rbuf]|(br))?('{3}|\"{3}|['\"]))", "i");
	    } else {
	      var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!]/;
	      var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;
	      myKeywords = myKeywords.concat(["exec", "print"]);
	      myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
	                                      "file", "intern", "long", "raw_input", "reduce", "reload",
	                                      "unichr", "unicode", "xrange", "False", "True", "None"]);
	      var stringPrefixes = new RegExp("^(([rubf]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
	    }
	    var keywords = wordRegexp(myKeywords);
	    var builtins = wordRegexp(myBuiltins);
	
	    // tokenizers
	    function tokenBase(stream, state) {
	      if (stream.sol()) state.indent = stream.indentation()
	      // Handle scope changes
	      if (stream.sol() && top(state).type == "py") {
	        var scopeOffset = top(state).offset;
	        if (stream.eatSpace()) {
	          var lineOffset = stream.indentation();
	          if (lineOffset > scopeOffset)
	            pushPyScope(state);
	          else if (lineOffset < scopeOffset && dedent(stream, state) && stream.peek() != "#")
	            state.errorToken = true;
	          return null;
	        } else {
	          var style = tokenBaseInner(stream, state);
	          if (scopeOffset > 0 && dedent(stream, state))
	            style += " " + ERRORCLASS;
	          return style;
	        }
	      }
	      return tokenBaseInner(stream, state);
	    }
	
	    function tokenBaseInner(stream, state) {
	      if (stream.eatSpace()) return null;
	
	      var ch = stream.peek();
	
	      // Handle Comments
	      if (ch == "#") {
	        stream.skipToEnd();
	        return "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 "number";
	        }
	        // 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 "number";
	        }
	      }
	
	      // 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 "punctuation";
	
	      if (stream.match(doubleOperators) || stream.match(singleOperators))
	        return "operator";
	
	      if (stream.match(singleDelimiters))
	        return "punctuation";
	
	      if (state.lastToken == "." && stream.match(identifiers))
	        return "property";
	
	      if (stream.match(keywords) || stream.match(wordOperators))
	        return "keyword";
	
	      if (stream.match(builtins))
	        return "builtin";
	
	      if (stream.match(/^(self|cls)\b/))
	        return "variable-2";
	
	      if (stream.match(identifiers)) {
	        if (state.lastToken == "def" || state.lastToken == "class")
	          return "def";
	        return "variable";
	      }
	
	      // Handle non-detected items
	      stream.next();
	      return ERRORCLASS;
	    }
	
	    function tokenStringFactory(delimiter) {
	      while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
	        delimiter = delimiter.substr(1);
	
	      var singleline = delimiter.length == 1;
	      var OUTCLASS = "string";
	
	      function tokenString(stream, state) {
	        while (!stream.eol()) {
	          stream.eatWhile(/[^'"\\]/);
	          if (stream.eat("\\")) {
	            stream.next();
	            if (singleline && stream.eol())
	              return OUTCLASS;
	          } else if (stream.match(delimiter)) {
	            state.tokenize = tokenBase;
	            return OUTCLASS;
	          } else {
	            stream.eat(/['"]/);
	          }
	        }
	        if (singleline) {
	          if (parserConf.singleLineStringErrors)
	            return ERRORCLASS;
	          else
	            state.tokenize = tokenBase;
	        }
	        return OUTCLASS;
	      }
	      tokenString.isString = true;
	      return tokenString;
	    }
	
	    function pushPyScope(state) {
	      while (top(state).type != "py") state.scopes.pop()
	      state.scopes.push({offset: top(state).offset + conf.indentUnit,
	                         type: "py",
	                         align: null})
	    }
	
	    function pushBracketScope(stream, state, type) {
	      var align = stream.match(/^([\s\[\{\(]|#.*)*$/, false) ? null : stream.column() + 1
	      state.scopes.push({offset: state.indent + hangingIndent,
	                         type: type,
	                         align: align})
	    }
	
	    function dedent(stream, state) {
	      var indented = stream.indentation();
	      while (state.scopes.length > 1 && top(state).offset > indented) {
	        if (top(state).type != "py") return true;
	        state.scopes.pop();
	      }
	      return top(state).offset != indented;
	    }
	
	    function tokenLexer(stream, state) {
	      if (stream.sol()) state.beginningOfLine = true;
	
	      var style = state.tokenize(stream, state);
	      var current = stream.current();
	
	      // Handle decorators
	      if (state.beginningOfLine && current == "@")
	        return stream.match(identifiers, false) ? "meta" : py3 ? "operator" : ERRORCLASS;
	
	      if (/\S/.test(current)) state.beginningOfLine = false;
	
	      if ((style == "variable" || style == "builtin")
	          && state.lastToken == "meta")
	        style = "meta";
	
	      // Handle scope changes.
	      if (current == "pass" || current == "return")
	        state.dedent += 1;
	
	      if (current == "lambda") state.lambda = true;
	      if (current == ":" && !state.lambda && top(state).type == "py")
	        pushPyScope(state);
	
	      var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1;
	      if (delimiter_index != -1)
	        pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
	
	      delimiter_index = "])}".indexOf(current);
	      if (delimiter_index != -1) {
	        if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent
	        else return ERRORCLASS;
	      }
	      if (state.dedent > 0 && stream.eol() && top(state).type == "py") {
	        if (state.scopes.length > 1) state.scopes.pop();
	        state.dedent -= 1;
	      }
	
	      return style;
	    }
	
	    var external = {
	      startState: function(basecolumn) {
	        return {
	          tokenize: tokenBase,
	          scopes: [{offset: basecolumn || 0, type: "py", align: null}],
	          indent: basecolumn || 0,
	          lastToken: null,
	          lambda: false,
	          dedent: 0
	        };
	      },
	
	      token: function(stream, state) {
	        var addErr = state.errorToken;
	        if (addErr) state.errorToken = false;
	        var style = tokenLexer(stream, state);
	
	        if (style && style != "comment")
	          state.lastToken = (style == "keyword" || style == "punctuation") ? stream.current() : style;
	        if (style == "punctuation") style = null;
	
	        if (stream.eol() && state.lambda)
	          state.lambda = false;
	        return addErr ? style + " " + ERRORCLASS : style;
	      },
	
	      indent: function(state, textAfter) {
	        if (state.tokenize != tokenBase)
	          return state.tokenize.isString ? CodeMirror.Pass : 0;
	
	        var scope = top(state), closing = scope.type == textAfter.charAt(0)
	        if (scope.align != null)
	          return scope.align - (closing ? 1 : 0)
	        else
	          return scope.offset - (closing ? hangingIndent : 0)
	      },
	
	      electricInput: /^\s*[\}\]\)]$/,
	      closeBrackets: {triples: "'\""},
	      lineComment: "#",
	      fold: "indent"
	    };
	    return external;
	  });
	
	  CodeMirror.defineMIME("text/x-python", "python");
	
	  var words = function(str) { return str.split(" "); };
	
	  CodeMirror.defineMIME("text/x-cython", {
	    name: "python",
	    extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+
	                          "extern gil include nogil property public"+
	                          "readonly struct union DEF IF ELIF ELSE")
	  });
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/python/python.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/codemirror-ipythongfm.js **/
jupyter.define('jupyterlab@0.15.1/lib/codemirror/codemirror-ipythongfm.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var CodeMirror = __jupyter_require__('codemirror@^5.20.2/lib/codemirror.js');
	__jupyter_require__('codemirror@^5.20.2/mode/stex/stex.js');
	__jupyter_require__('codemirror@^5.20.2/mode/gfm/gfm.js');
	__jupyter_require__('codemirror@^5.20.2/addon/mode/multiplex.js');
	/**
	 * Define an IPython GFM (GitHub Flavored Markdown) mode.
	 *
	 * Is just a slightly altered GFM Mode with support for latex.
	 * Latex support was supported by Codemirror GFM as of
	 *   https://github.com/codemirror/CodeMirror/pull/567
	 *  But was later removed in
	 *   https://github.com/codemirror/CodeMirror/commit/d9c9f1b1ffe984aee41307f3e927f80d1f23590c
	 */
	CodeMirror.defineMode('ipythongfm', function (config, modeOptions) {
	    var gfmMode = CodeMirror.getMode(config, 'gfm');
	    var texMode = CodeMirror.getMode(config, 'stex');
	    return CodeMirror.multiplexingMode(gfmMode, {
	        open: '$', close: '$',
	        mode: texMode,
	        delimStyle: 'delimit'
	    }, {
	        // not sure this works as $$ is interpreted at (opening $, closing $, as defined just above)
	        open: '$$', close: '$$',
	        mode: texMode,
	        delimStyle: 'delimit'
	    }, {
	        open: '\\(', close: '\\)',
	        mode: texMode,
	        delimStyle: 'delimit'
	    }, {
	        open: '\\[', close: '\\]',
	        mode: texMode,
	        delimStyle: 'delimit'
	    });
	}, 'gfm');
	CodeMirror.defineMIME('text/x-ipythongfm', 'ipythongfm');
	CodeMirror.modeInfo.push({
	    ext: [],
	    mime: 'text/x-ipythongfm',
	    mode: 'ipythongfm',
	    name: 'ipythongfm'
	});
	//# sourceMappingURL=codemirror-ipythongfm.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/codemirror/codemirror-ipythongfm.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/stex/stex.js **/
jupyter.define('codemirror@5.23.0/mode/stex/stex.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	/*
	 * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
	 * Licence: MIT
	 */
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	  "use strict";
	
	  CodeMirror.defineMode("stex", function() {
	    "use strict";
	
	    function pushCommand(state, command) {
	      state.cmdState.push(command);
	    }
	
	    function peekCommand(state) {
	      if (state.cmdState.length > 0) {
	        return state.cmdState[state.cmdState.length - 1];
	      } else {
	        return null;
	      }
	    }
	
	    function popCommand(state) {
	      var plug = state.cmdState.pop();
	      if (plug) {
	        plug.closeBracket();
	      }
	    }
	
	    // returns the non-default plugin closest to the end of the list
	    function getMostPowerful(state) {
	      var context = state.cmdState;
	      for (var i = context.length - 1; i >= 0; i--) {
	        var plug = context[i];
	        if (plug.name == "DEFAULT") {
	          continue;
	        }
	        return plug;
	      }
	      return { styleIdentifier: function() { return null; } };
	    }
	
	    function addPluginPattern(pluginName, cmdStyle, styles) {
	      return function () {
	        this.name = pluginName;
	        this.bracketNo = 0;
	        this.style = cmdStyle;
	        this.styles = styles;
	        this.argument = null;   // \begin and \end have arguments that follow. These are stored in the plugin
	
	        this.styleIdentifier = function() {
	          return this.styles[this.bracketNo - 1] || null;
	        };
	        this.openBracket = function() {
	          this.bracketNo++;
	          return "bracket";
	        };
	        this.closeBracket = function() {};
	      };
	    }
	
	    var plugins = {};
	
	    plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]);
	    plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]);
	    plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]);
	    plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]);
	    plugins["end"] = addPluginPattern("end", "tag", ["atom"]);
	
	    plugins["DEFAULT"] = function () {
	      this.name = "DEFAULT";
	      this.style = "tag";
	
	      this.styleIdentifier = this.openBracket = this.closeBracket = function() {};
	    };
	
	    function setState(state, f) {
	      state.f = f;
	    }
	
	    // called when in a normal (no environment) context
	    function normal(source, state) {
	      var plug;
	      // Do we look like '\command' ?  If so, attempt to apply the plugin 'command'
	      if (source.match(/^\\[a-zA-Z@]+/)) {
	        var cmdName = source.current().slice(1);
	        plug = plugins[cmdName] || plugins["DEFAULT"];
	        plug = new plug();
	        pushCommand(state, plug);
	        setState(state, beginParams);
	        return plug.style;
	      }
	
	      // escape characters
	      if (source.match(/^\\[$&%#{}_]/)) {
	        return "tag";
	      }
	
	      // white space control characters
	      if (source.match(/^\\[,;!\/\\]/)) {
	        return "tag";
	      }
	
	      // find if we're starting various math modes
	      if (source.match("\\[")) {
	        setState(state, function(source, state){ return inMathMode(source, state, "\\]"); });
	        return "keyword";
	      }
	      if (source.match("$$")) {
	        setState(state, function(source, state){ return inMathMode(source, state, "$$"); });
	        return "keyword";
	      }
	      if (source.match("$")) {
	        setState(state, function(source, state){ return inMathMode(source, state, "$"); });
	        return "keyword";
	      }
	
	      var ch = source.next();
	      if (ch == "%") {
	        source.skipToEnd();
	        return "comment";
	      } else if (ch == '}' || ch == ']') {
	        plug = peekCommand(state);
	        if (plug) {
	          plug.closeBracket(ch);
	          setState(state, beginParams);
	        } else {
	          return "error";
	        }
	        return "bracket";
	      } else if (ch == '{' || ch == '[') {
	        plug = plugins["DEFAULT"];
	        plug = new plug();
	        pushCommand(state, plug);
	        return "bracket";
	      } else if (/\d/.test(ch)) {
	        source.eatWhile(/[\w.%]/);
	        return "atom";
	      } else {
	        source.eatWhile(/[\w\-_]/);
	        plug = getMostPowerful(state);
	        if (plug.name == 'begin') {
	          plug.argument = source.current();
	        }
	        return plug.styleIdentifier();
	      }
	    }
	
	    function inMathMode(source, state, endModeSeq) {
	      if (source.eatSpace()) {
	        return null;
	      }
	      if (source.match(endModeSeq)) {
	        setState(state, normal);
	        return "keyword";
	      }
	      if (source.match(/^\\[a-zA-Z@]+/)) {
	        return "tag";
	      }
	      if (source.match(/^[a-zA-Z]+/)) {
	        return "variable-2";
	      }
	      // escape characters
	      if (source.match(/^\\[$&%#{}_]/)) {
	        return "tag";
	      }
	      // white space control characters
	      if (source.match(/^\\[,;!\/]/)) {
	        return "tag";
	      }
	      // special math-mode characters
	      if (source.match(/^[\^_&]/)) {
	        return "tag";
	      }
	      // non-special characters
	      if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) {
	        return null;
	      }
	      if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) {
	        return "number";
	      }
	      var ch = source.next();
	      if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {
	        return "bracket";
	      }
	
	      if (ch == "%") {
	        source.skipToEnd();
	        return "comment";
	      }
	      return "error";
	    }
	
	    function beginParams(source, state) {
	      var ch = source.peek(), lastPlug;
	      if (ch == '{' || ch == '[') {
	        lastPlug = peekCommand(state);
	        lastPlug.openBracket(ch);
	        source.eat(ch);
	        setState(state, normal);
	        return "bracket";
	      }
	      if (/[ \t\r]/.test(ch)) {
	        source.eat(ch);
	        return null;
	      }
	      setState(state, normal);
	      popCommand(state);
	
	      return normal(source, state);
	    }
	
	    return {
	      startState: function() {
	        return {
	          cmdState: [],
	          f: normal
	        };
	      },
	      copyState: function(s) {
	        return {
	          cmdState: s.cmdState.slice(),
	          f: s.f
	        };
	      },
	      token: function(stream, state) {
	        return state.f(stream, state);
	      },
	      blankLine: function(state) {
	        state.f = normal;
	        state.cmdState.length = 0;
	      },
	      lineComment: "%"
	    };
	  });
	
	  CodeMirror.defineMIME("text/x-stex", "stex");
	  CodeMirror.defineMIME("text/x-latex", "stex");
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/stex/stex.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/gfm/gfm.js **/
jupyter.define('codemirror@5.23.0/mode/gfm/gfm.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'), __jupyter_require__('codemirror@5.23.0/mode/markdown/markdown.js'), __jupyter_require__('codemirror@5.23.0/addon/mode/overlay.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	var urlRE = /^((?:(?:aaas?|about|acap|adiumxtra|af[ps]|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|cap|chrome(?:-extension)?|cid|coap|com-eventbrite-attendee|content|crid|cvs|data|dav|dict|dlna-(?:playcontainer|playsingle)|dns|doi|dtn|dvb|ed2k|facetime|feed|file|finger|fish|ftp|geo|gg|git|gizmoproject|go|gopher|gtalk|h323|hcp|https?|iax|icap|icon|im|imap|info|ipn|ipp|irc[6s]?|iris(?:\.beep|\.lwz|\.xpc|\.xpcs)?|itms|jar|javascript|jms|keyparc|lastfm|ldaps?|magnet|mailto|maps|market|message|mid|mms|ms-help|msnim|msrps?|mtqp|mumble|mupdate|mvn|news|nfs|nih?|nntp|notes|oid|opaquelocktoken|palm|paparazzi|platform|pop|pres|proxy|psyc|query|res(?:ource)?|rmi|rsync|rtmp|rtsp|secondlife|service|session|sftp|sgn|shttp|sieve|sips?|skype|sm[bs]|snmp|soap\.beeps?|soldat|spotify|ssh|steam|svn|tag|teamspeak|tel(?:net)?|tftp|things|thismessage|tip|tn3270|tv|udp|unreal|urn|ut2004|vemmi|ventrilo|view-source|webcal|wss?|wtai|wyciwyg|xcon(?:-userid)?|xfire|xmlrpc\.beeps?|xmpp|xri|ymsgr|z39\.50[rs]?):(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i
	
	CodeMirror.defineMode("gfm", function(config, modeConfig) {
	  var codeDepth = 0;
	  function blankLine(state) {
	    state.code = false;
	    return null;
	  }
	  var gfmOverlay = {
	    startState: function() {
	      return {
	        code: false,
	        codeBlock: false,
	        ateSpace: false
	      };
	    },
	    copyState: function(s) {
	      return {
	        code: s.code,
	        codeBlock: s.codeBlock,
	        ateSpace: s.ateSpace
	      };
	    },
	    token: function(stream, state) {
	      state.combineTokens = null;
	
	      // Hack to prevent formatting override inside code blocks (block and inline)
	      if (state.codeBlock) {
	        if (stream.match(/^```+/)) {
	          state.codeBlock = false;
	          return null;
	        }
	        stream.skipToEnd();
	        return null;
	      }
	      if (stream.sol()) {
	        state.code = false;
	      }
	      if (stream.sol() && stream.match(/^```+/)) {
	        stream.skipToEnd();
	        state.codeBlock = true;
	        return null;
	      }
	      // If this block is changed, it may need to be updated in Markdown mode
	      if (stream.peek() === '`') {
	        stream.next();
	        var before = stream.pos;
	        stream.eatWhile('`');
	        var difference = 1 + stream.pos - before;
	        if (!state.code) {
	          codeDepth = difference;
	          state.code = true;
	        } else {
	          if (difference === codeDepth) { // Must be exact
	            state.code = false;
	          }
	        }
	        return null;
	      } else if (state.code) {
	        stream.next();
	        return null;
	      }
	      // Check if space. If so, links can be formatted later on
	      if (stream.eatSpace()) {
	        state.ateSpace = true;
	        return null;
	      }
	      if (stream.sol() || state.ateSpace) {
	        state.ateSpace = false;
	        if (modeConfig.gitHubSpice !== false) {
	          if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
	            // User/Project@SHA
	            // User@SHA
	            // SHA
	            state.combineTokens = true;
	            return "link";
	          } else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
	            // User/Project#Num
	            // User#Num
	            // #Num
	            state.combineTokens = true;
	            return "link";
	          }
	        }
	      }
	      if (stream.match(urlRE) &&
	          stream.string.slice(stream.start - 2, stream.start) != "](" &&
	          (stream.start == 0 || /\W/.test(stream.string.charAt(stream.start - 1)))) {
	        // URLs
	        // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
	        // And then (issue #1160) simplified to make it not crash the Chrome Regexp engine
	        // And then limited url schemes to the CommonMark list, so foo:bar isn't matched as a URL
	        state.combineTokens = true;
	        return "link";
	      }
	      stream.next();
	      return null;
	    },
	    blankLine: blankLine
	  };
	
	  var markdownConfig = {
	    underscoresBreakWords: false,
	    taskLists: true,
	    fencedCodeBlocks: '```',
	    strikethrough: true
	  };
	  for (var attr in modeConfig) {
	    markdownConfig[attr] = modeConfig[attr];
	  }
	  markdownConfig.name = "markdown";
	  return CodeMirror.overlayMode(CodeMirror.getMode(config, markdownConfig), gfmOverlay);
	
	}, "markdown");
	
	  CodeMirror.defineMIME("text/x-gfm", "gfm");
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/gfm/gfm.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/markdown/markdown.js **/
jupyter.define('codemirror@5.23.0/mode/markdown/markdown.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'), __jupyter_require__('codemirror@5.23.0/mode/xml/xml.js'), __jupyter_require__('codemirror@5.23.0/mode/meta.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
	
	  var htmlMode = CodeMirror.getMode(cmCfg, "text/html");
	  var htmlModeMissing = htmlMode.name == "null"
	
	  function getMode(name) {
	    if (CodeMirror.findModeByName) {
	      var found = CodeMirror.findModeByName(name);
	      if (found) name = found.mime || found.mimes[0];
	    }
	    var mode = CodeMirror.getMode(cmCfg, name);
	    return mode.name == "null" ? null : mode;
	  }
	
	  // Should characters that affect highlighting be highlighted separate?
	  // Does not include characters that will be output (such as `1.` and `-` for lists)
	  if (modeCfg.highlightFormatting === undefined)
	    modeCfg.highlightFormatting = false;
	
	  // Maximum number of nested blockquotes. Set to 0 for infinite nesting.
	  // Excess `>` will emit `error` token.
	  if (modeCfg.maxBlockquoteDepth === undefined)
	    modeCfg.maxBlockquoteDepth = 0;
	
	  // Should underscores in words open/close em/strong?
	  if (modeCfg.underscoresBreakWords === undefined)
	    modeCfg.underscoresBreakWords = true;
	
	  // Use `fencedCodeBlocks` to configure fenced code blocks. false to
	  // disable, string to specify a precise regexp that the fence should
	  // match, and true to allow three or more backticks or tildes (as
	  // per CommonMark).
	
	  // Turn on task lists? ("- [ ] " and "- [x] ")
	  if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
	
	  // Turn on strikethrough syntax
	  if (modeCfg.strikethrough === undefined)
	    modeCfg.strikethrough = false;
	
	  // Allow token types to be overridden by user-provided token types.
	  if (modeCfg.tokenTypeOverrides === undefined)
	    modeCfg.tokenTypeOverrides = {};
	
	  var tokenTypes = {
	    header: "header",
	    code: "comment",
	    quote: "quote",
	    list1: "variable-2",
	    list2: "variable-3",
	    list3: "keyword",
	    hr: "hr",
	    image: "image",
	    imageAltText: "image-alt-text",
	    imageMarker: "image-marker",
	    formatting: "formatting",
	    linkInline: "link",
	    linkEmail: "link",
	    linkText: "link",
	    linkHref: "string",
	    em: "em",
	    strong: "strong",
	    strikethrough: "strikethrough"
	  };
	
	  for (var tokenType in tokenTypes) {
	    if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) {
	      tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType];
	    }
	  }
	
	  var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/
	  ,   listRE = /^(?:[*\-+]|^[0-9]+([.)]))\s+/
	  ,   taskListRE = /^\[(x| )\](?=\s)/ // Must follow listRE
	  ,   atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
	  ,   setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/
	  ,   textRE = /^[^#!\[\]*_\\<>` "'(~]+/
	  ,   fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) +
	                                ")[ \\t]*([\\w+#\-]*)");
	
	  function switchInline(stream, state, f) {
	    state.f = state.inline = f;
	    return f(stream, state);
	  }
	
	  function switchBlock(stream, state, f) {
	    state.f = state.block = f;
	    return f(stream, state);
	  }
	
	  function lineIsEmpty(line) {
	    return !line || !/\S/.test(line.string)
	  }
	
	  // Blocks
	
	  function blankLine(state) {
	    // Reset linkTitle state
	    state.linkTitle = false;
	    // Reset EM state
	    state.em = false;
	    // Reset STRONG state
	    state.strong = false;
	    // Reset strikethrough state
	    state.strikethrough = false;
	    // Reset state.quote
	    state.quote = 0;
	    // Reset state.indentedCode
	    state.indentedCode = false;
	    if (htmlModeMissing && state.f == htmlBlock) {
	      state.f = inlineNormal;
	      state.block = blockNormal;
	    }
	    // Reset state.trailingSpace
	    state.trailingSpace = 0;
	    state.trailingSpaceNewLine = false;
	    // Mark this line as blank
	    state.prevLine = state.thisLine
	    state.thisLine = null
	    return null;
	  }
	
	  function blockNormal(stream, state) {
	
	    var sol = stream.sol();
	
	    var prevLineIsList = state.list !== false,
	        prevLineIsIndentedCode = state.indentedCode;
	
	    state.indentedCode = false;
	
	    if (prevLineIsList) {
	      if (state.indentationDiff >= 0) { // Continued list
	        if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
	          state.indentation -= state.indentationDiff;
	        }
	        state.list = null;
	      } else if (state.indentation > 0) {
	        state.list = null;
	      } else { // No longer a list
	        state.list = false;
	      }
	    }
	
	    var match = null;
	    if (state.indentationDiff >= 4) {
	      stream.skipToEnd();
	      if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) {
	        state.indentation -= 4;
	        state.indentedCode = true;
	        return tokenTypes.code;
	      } else {
	        return null;
	      }
	    } else if (stream.eatSpace()) {
	      return null;
	    } else if ((match = stream.match(atxHeaderRE)) && match[1].length <= 6) {
	      state.header = match[1].length;
	      if (modeCfg.highlightFormatting) state.formatting = "header";
	      state.f = state.inline;
	      return getType(state);
	    } else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList &&
	               !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) {
	      state.header = match[0].charAt(0) == '=' ? 1 : 2;
	      if (modeCfg.highlightFormatting) state.formatting = "header";
	      state.f = state.inline;
	      return getType(state);
	    } else if (stream.eat('>')) {
	      state.quote = sol ? 1 : state.quote + 1;
	      if (modeCfg.highlightFormatting) state.formatting = "quote";
	      stream.eatSpace();
	      return getType(state);
	    } else if (stream.peek() === '[') {
	      return switchInline(stream, state, footnoteLink);
	    } else if (stream.match(hrRE, true)) {
	      state.hr = true;
	      return tokenTypes.hr;
	    } else if (match = stream.match(listRE)) {
	      var listType = match[1] ? "ol" : "ul";
	      state.indentation = stream.column() + stream.current().length;
	      state.list = true;
	
	      // While this list item's marker's indentation
	      // is less than the deepest list item's content's indentation,
	      // pop the deepest list item indentation off the stack.
	      while (state.listStack && stream.column() < state.listStack[state.listStack.length - 1]) {
	        state.listStack.pop();
	      }
	
	      // Add this list item's content's indentation to the stack
	      state.listStack.push(state.indentation);
	
	      if (modeCfg.taskLists && stream.match(taskListRE, false)) {
	        state.taskList = true;
	      }
	      state.f = state.inline;
	      if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
	      return getType(state);
	    } else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) {
	      state.fencedChars = match[1]
	      // try switching mode
	      state.localMode = getMode(match[2]);
	      if (state.localMode) state.localState = CodeMirror.startState(state.localMode);
	      state.f = state.block = local;
	      if (modeCfg.highlightFormatting) state.formatting = "code-block";
	      state.code = -1
	      return getType(state);
	    }
	
	    return switchInline(stream, state, state.inline);
	  }
	
	  function htmlBlock(stream, state) {
	    var style = htmlMode.token(stream, state.htmlState);
	    if (!htmlModeMissing) {
	      var inner = CodeMirror.innerMode(htmlMode, state.htmlState)
	      if ((inner.mode.name == "xml" && inner.state.tagStart === null &&
	           (!inner.state.context && inner.state.tokenize.isInText)) ||
	          (state.md_inside && stream.current().indexOf(">") > -1)) {
	        state.f = inlineNormal;
	        state.block = blockNormal;
	        state.htmlState = null;
	      }
	    }
	    return style;
	  }
	
	  function local(stream, state) {
	    if (state.fencedChars && stream.match(state.fencedChars, false)) {
	      state.localMode = state.localState = null;
	      state.f = state.block = leavingLocal;
	      return null;
	    } else if (state.localMode) {
	      return state.localMode.token(stream, state.localState);
	    } else {
	      stream.skipToEnd();
	      return tokenTypes.code;
	    }
	  }
	
	  function leavingLocal(stream, state) {
	    stream.match(state.fencedChars);
	    state.block = blockNormal;
	    state.f = inlineNormal;
	    state.fencedChars = null;
	    if (modeCfg.highlightFormatting) state.formatting = "code-block";
	    state.code = 1
	    var returnType = getType(state);
	    state.code = 0
	    return returnType;
	  }
	
	  // Inline
	  function getType(state) {
	    var styles = [];
	
	    if (state.formatting) {
	      styles.push(tokenTypes.formatting);
	
	      if (typeof state.formatting === "string") state.formatting = [state.formatting];
	
	      for (var i = 0; i < state.formatting.length; i++) {
	        styles.push(tokenTypes.formatting + "-" + state.formatting[i]);
	
	        if (state.formatting[i] === "header") {
	          styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header);
	        }
	
	        // Add `formatting-quote` and `formatting-quote-#` for blockquotes
	        // Add `error` instead if the maximum blockquote nesting depth is passed
	        if (state.formatting[i] === "quote") {
	          if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
	            styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote);
	          } else {
	            styles.push("error");
	          }
	        }
	      }
	    }
	
	    if (state.taskOpen) {
	      styles.push("meta");
	      return styles.length ? styles.join(' ') : null;
	    }
	    if (state.taskClosed) {
	      styles.push("property");
	      return styles.length ? styles.join(' ') : null;
	    }
	
	    if (state.linkHref) {
	      styles.push(tokenTypes.linkHref, "url");
	    } else { // Only apply inline styles to non-url text
	      if (state.strong) { styles.push(tokenTypes.strong); }
	      if (state.em) { styles.push(tokenTypes.em); }
	      if (state.strikethrough) { styles.push(tokenTypes.strikethrough); }
	      if (state.linkText) { styles.push(tokenTypes.linkText); }
	      if (state.code) { styles.push(tokenTypes.code); }
	      if (state.image) { styles.push(tokenTypes.image); }
	      if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); }
	      if (state.imageMarker) { styles.push(tokenTypes.imageMarker); }
	    }
	
	    if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); }
	
	    if (state.quote) {
	      styles.push(tokenTypes.quote);
	
	      // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
	      if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
	        styles.push(tokenTypes.quote + "-" + state.quote);
	      } else {
	        styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth);
	      }
	    }
	
	    if (state.list !== false) {
	      var listMod = (state.listStack.length - 1) % 3;
	      if (!listMod) {
	        styles.push(tokenTypes.list1);
	      } else if (listMod === 1) {
	        styles.push(tokenTypes.list2);
	      } else {
	        styles.push(tokenTypes.list3);
	      }
	    }
	
	    if (state.trailingSpaceNewLine) {
	      styles.push("trailing-space-new-line");
	    } else if (state.trailingSpace) {
	      styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
	    }
	
	    return styles.length ? styles.join(' ') : null;
	  }
	
	  function handleText(stream, state) {
	    if (stream.match(textRE, true)) {
	      return getType(state);
	    }
	    return undefined;
	  }
	
	  function inlineNormal(stream, state) {
	    var style = state.text(stream, state);
	    if (typeof style !== 'undefined')
	      return style;
	
	    if (state.list) { // List marker (*, +, -, 1., etc)
	      state.list = null;
	      return getType(state);
	    }
	
	    if (state.taskList) {
	      var taskOpen = stream.match(taskListRE, true)[1] !== "x";
	      if (taskOpen) state.taskOpen = true;
	      else state.taskClosed = true;
	      if (modeCfg.highlightFormatting) state.formatting = "task";
	      state.taskList = false;
	      return getType(state);
	    }
	
	    state.taskOpen = false;
	    state.taskClosed = false;
	
	    if (state.header && stream.match(/^#+$/, true)) {
	      if (modeCfg.highlightFormatting) state.formatting = "header";
	      return getType(state);
	    }
	
	    // Get sol() value now, before character is consumed
	    var sol = stream.sol();
	
	    var ch = stream.next();
	
	    // Matches link titles present on next line
	    if (state.linkTitle) {
	      state.linkTitle = false;
	      var matchCh = ch;
	      if (ch === '(') {
	        matchCh = ')';
	      }
	      matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
	      var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
	      if (stream.match(new RegExp(regex), true)) {
	        return tokenTypes.linkHref;
	      }
	    }
	
	    // If this block is changed, it may need to be updated in GFM mode
	    if (ch === '`') {
	      var previousFormatting = state.formatting;
	      if (modeCfg.highlightFormatting) state.formatting = "code";
	      stream.eatWhile('`');
	      var count = stream.current().length
	      if (state.code == 0) {
	        state.code = count
	        return getType(state)
	      } else if (count == state.code) { // Must be exact
	        var t = getType(state)
	        state.code = 0
	        return t
	      } else {
	        state.formatting = previousFormatting
	        return getType(state)
	      }
	    } else if (state.code) {
	      return getType(state);
	    }
	
	    if (ch === '\\') {
	      stream.next();
	      if (modeCfg.highlightFormatting) {
	        var type = getType(state);
	        var formattingEscape = tokenTypes.formatting + "-escape";
	        return type ? type + " " + formattingEscape : formattingEscape;
	      }
	    }
	
	    if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
	      state.imageMarker = true;
	      state.image = true;
	      if (modeCfg.highlightFormatting) state.formatting = "image";
	      return getType(state);
	    }
	
	    if (ch === '[' && state.imageMarker && stream.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/, false)) {
	      state.imageMarker = false;
	      state.imageAltText = true
	      if (modeCfg.highlightFormatting) state.formatting = "image";
	      return getType(state);
	    }
	
	    if (ch === ']' && state.imageAltText) {
	      if (modeCfg.highlightFormatting) state.formatting = "image";
	      var type = getType(state);
	      state.imageAltText = false;
	      state.image = false;
	      state.inline = state.f = linkHref;
	      return type;
	    }
	
	    if (ch === '[' && stream.match(/[^\]]*\](\(.*\)| ?\[.*?\])/, false) && !state.image) {
	      state.linkText = true;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      return getType(state);
	    }
	
	    if (ch === ']' && state.linkText && stream.match(/\(.*?\)| ?\[.*?\]/, false)) {
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      state.linkText = false;
	      state.inline = state.f = linkHref;
	      return type;
	    }
	
	    if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
	      state.f = state.inline = linkInline;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      if (type){
	        type += " ";
	      } else {
	        type = "";
	      }
	      return type + tokenTypes.linkInline;
	    }
	
	    if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
	      state.f = state.inline = linkInline;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      if (type){
	        type += " ";
	      } else {
	        type = "";
	      }
	      return type + tokenTypes.linkEmail;
	    }
	
	    if (ch === '<' && stream.match(/^(!--|[a-z]+(?:\s+[a-z_:.\-]+(?:\s*=\s*[^ >]+)?)*\s*>)/i, false)) {
	      var end = stream.string.indexOf(">", stream.pos);
	      if (end != -1) {
	        var atts = stream.string.substring(stream.start, end);
	        if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true;
	      }
	      stream.backUp(1);
	      state.htmlState = CodeMirror.startState(htmlMode);
	      return switchBlock(stream, state, htmlBlock);
	    }
	
	    if (ch === '<' && stream.match(/^\/\w*?>/)) {
	      state.md_inside = false;
	      return "tag";
	    }
	
	    var ignoreUnderscore = false;
	    if (!modeCfg.underscoresBreakWords) {
	      if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
	        var prevPos = stream.pos - 2;
	        if (prevPos >= 0) {
	          var prevCh = stream.string.charAt(prevPos);
	          if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
	            ignoreUnderscore = true;
	          }
	        }
	      }
	    }
	    if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
	      if (sol && stream.peek() === ' ') {
	        // Do nothing, surrounded by newline and space
	      } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
	        if (modeCfg.highlightFormatting) state.formatting = "strong";
	        var t = getType(state);
	        state.strong = false;
	        return t;
	      } else if (!state.strong && stream.eat(ch)) { // Add STRONG
	        state.strong = ch;
	        if (modeCfg.highlightFormatting) state.formatting = "strong";
	        return getType(state);
	      } else if (state.em === ch) { // Remove EM
	        if (modeCfg.highlightFormatting) state.formatting = "em";
	        var t = getType(state);
	        state.em = false;
	        return t;
	      } else if (!state.em) { // Add EM
	        state.em = ch;
	        if (modeCfg.highlightFormatting) state.formatting = "em";
	        return getType(state);
	      }
	    } else if (ch === ' ') {
	      if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
	        if (stream.peek() === ' ') { // Surrounded by spaces, ignore
	          return getType(state);
	        } else { // Not surrounded by spaces, back up pointer
	          stream.backUp(1);
	        }
	      }
	    }
	
	    if (modeCfg.strikethrough) {
	      if (ch === '~' && stream.eatWhile(ch)) {
	        if (state.strikethrough) {// Remove strikethrough
	          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
	          var t = getType(state);
	          state.strikethrough = false;
	          return t;
	        } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
	          state.strikethrough = true;
	          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
	          return getType(state);
	        }
	      } else if (ch === ' ') {
	        if (stream.match(/^~~/, true)) { // Probably surrounded by space
	          if (stream.peek() === ' ') { // Surrounded by spaces, ignore
	            return getType(state);
	          } else { // Not surrounded by spaces, back up pointer
	            stream.backUp(2);
	          }
	        }
	      }
	    }
	
	    if (ch === ' ') {
	      if (stream.match(/ +$/, false)) {
	        state.trailingSpace++;
	      } else if (state.trailingSpace) {
	        state.trailingSpaceNewLine = true;
	      }
	    }
	
	    return getType(state);
	  }
	
	  function linkInline(stream, state) {
	    var ch = stream.next();
	
	    if (ch === ">") {
	      state.f = state.inline = inlineNormal;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      if (type){
	        type += " ";
	      } else {
	        type = "";
	      }
	      return type + tokenTypes.linkInline;
	    }
	
	    stream.match(/^[^>]+/, true);
	
	    return tokenTypes.linkInline;
	  }
	
	  function linkHref(stream, state) {
	    // Check if space, and return NULL if so (to avoid marking the space)
	    if(stream.eatSpace()){
	      return null;
	    }
	    var ch = stream.next();
	    if (ch === '(' || ch === '[') {
	      state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]", 0);
	      if (modeCfg.highlightFormatting) state.formatting = "link-string";
	      state.linkHref = true;
	      return getType(state);
	    }
	    return 'error';
	  }
	
	  var linkRE = {
	    ")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,
	    "]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\\]]|\\.)*\])*?(?=\])/
	  }
	
	  function getLinkHrefInside(endChar) {
	    return function(stream, state) {
	      var ch = stream.next();
	
	      if (ch === endChar) {
	        state.f = state.inline = inlineNormal;
	        if (modeCfg.highlightFormatting) state.formatting = "link-string";
	        var returnState = getType(state);
	        state.linkHref = false;
	        return returnState;
	      }
	
	      stream.match(linkRE[endChar])
	      state.linkHref = true;
	      return getType(state);
	    };
	  }
	
	  function footnoteLink(stream, state) {
	    if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) {
	      state.f = footnoteLinkInside;
	      stream.next(); // Consume [
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      state.linkText = true;
	      return getType(state);
	    }
	    return switchInline(stream, state, inlineNormal);
	  }
	
	  function footnoteLinkInside(stream, state) {
	    if (stream.match(/^\]:/, true)) {
	      state.f = state.inline = footnoteUrl;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var returnType = getType(state);
	      state.linkText = false;
	      return returnType;
	    }
	
	    stream.match(/^([^\]\\]|\\.)+/, true);
	
	    return tokenTypes.linkText;
	  }
	
	  function footnoteUrl(stream, state) {
	    // Check if space, and return NULL if so (to avoid marking the space)
	    if(stream.eatSpace()){
	      return null;
	    }
	    // Match URL
	    stream.match(/^[^\s]+/, true);
	    // Check for link title
	    if (stream.peek() === undefined) { // End of line, set flag to check next line
	      state.linkTitle = true;
	    } else { // More content on line, check if link title
	      stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
	    }
	    state.f = state.inline = inlineNormal;
	    return tokenTypes.linkHref + " url";
	  }
	
	  var mode = {
	    startState: function() {
	      return {
	        f: blockNormal,
	
	        prevLine: null,
	        thisLine: null,
	
	        block: blockNormal,
	        htmlState: null,
	        indentation: 0,
	
	        inline: inlineNormal,
	        text: handleText,
	
	        formatting: false,
	        linkText: false,
	        linkHref: false,
	        linkTitle: false,
	        code: 0,
	        em: false,
	        strong: false,
	        header: 0,
	        hr: false,
	        taskList: false,
	        list: false,
	        listStack: [],
	        quote: 0,
	        trailingSpace: 0,
	        trailingSpaceNewLine: false,
	        strikethrough: false,
	        fencedChars: null
	      };
	    },
	
	    copyState: function(s) {
	      return {
	        f: s.f,
	
	        prevLine: s.prevLine,
	        thisLine: s.thisLine,
	
	        block: s.block,
	        htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
	        indentation: s.indentation,
	
	        localMode: s.localMode,
	        localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
	
	        inline: s.inline,
	        text: s.text,
	        formatting: false,
	        linkTitle: s.linkTitle,
	        code: s.code,
	        em: s.em,
	        strong: s.strong,
	        strikethrough: s.strikethrough,
	        header: s.header,
	        hr: s.hr,
	        taskList: s.taskList,
	        list: s.list,
	        listStack: s.listStack.slice(0),
	        quote: s.quote,
	        indentedCode: s.indentedCode,
	        trailingSpace: s.trailingSpace,
	        trailingSpaceNewLine: s.trailingSpaceNewLine,
	        md_inside: s.md_inside,
	        fencedChars: s.fencedChars
	      };
	    },
	
	    token: function(stream, state) {
	
	      // Reset state.formatting
	      state.formatting = false;
	
	      if (stream != state.thisLine) {
	        var forceBlankLine = state.header || state.hr;
	
	        // Reset state.header and state.hr
	        state.header = 0;
	        state.hr = false;
	
	        if (stream.match(/^\s*$/, true) || forceBlankLine) {
	          blankLine(state);
	          if (!forceBlankLine) return null
	          state.prevLine = null
	        }
	
	        state.prevLine = state.thisLine
	        state.thisLine = stream
	
	        // Reset state.taskList
	        state.taskList = false;
	
	        // Reset state.trailingSpace
	        state.trailingSpace = 0;
	        state.trailingSpaceNewLine = false;
	
	        state.f = state.block;
	        var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, '    ').length;
	        state.indentationDiff = Math.min(indentation - state.indentation, 4);
	        state.indentation = state.indentation + state.indentationDiff;
	        if (indentation > 0) return null;
	      }
	      return state.f(stream, state);
	    },
	
	    innerMode: function(state) {
	      if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
	      if (state.localState) return {state: state.localState, mode: state.localMode};
	      return {state: state, mode: mode};
	    },
	
	    blankLine: blankLine,
	
	    getType: getType,
	
	    closeBrackets: "()[]{}''\"\"``",
	    fold: "markdown"
	  };
	  return mode;
	}, "xml");
	
	CodeMirror.defineMIME("text/x-markdown", "markdown");
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/markdown/markdown.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/xml/xml.js **/
jupyter.define('codemirror@5.23.0/mode/xml/xml.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	var htmlConfig = {
	  autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
	                    'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
	                    'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
	                    'track': true, 'wbr': true, 'menuitem': true},
	  implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
	                     'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
	                     'th': true, 'tr': true},
	  contextGrabbers: {
	    'dd': {'dd': true, 'dt': true},
	    'dt': {'dd': true, 'dt': true},
	    'li': {'li': true},
	    'option': {'option': true, 'optgroup': true},
	    'optgroup': {'optgroup': true},
	    'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
	          'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
	          'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
	          'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
	          'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
	    'rp': {'rp': true, 'rt': true},
	    'rt': {'rp': true, 'rt': true},
	    'tbody': {'tbody': true, 'tfoot': true},
	    'td': {'td': true, 'th': true},
	    'tfoot': {'tbody': true},
	    'th': {'td': true, 'th': true},
	    'thead': {'tbody': true, 'tfoot': true},
	    'tr': {'tr': true}
	  },
	  doNotIndent: {"pre": true},
	  allowUnquoted: true,
	  allowMissing: true,
	  caseFold: true
	}
	
	var xmlConfig = {
	  autoSelfClosers: {},
	  implicitlyClosed: {},
	  contextGrabbers: {},
	  doNotIndent: {},
	  allowUnquoted: false,
	  allowMissing: false,
	  caseFold: false
	}
	
	CodeMirror.defineMode("xml", function(editorConf, config_) {
	  var indentUnit = editorConf.indentUnit
	  var config = {}
	  var defaults = config_.htmlMode ? htmlConfig : xmlConfig
	  for (var prop in defaults) config[prop] = defaults[prop]
	  for (var prop in config_) config[prop] = config_[prop]
	
	  // Return variables for tokenizers
	  var type, setStyle;
	
	  function inText(stream, state) {
	    function chain(parser) {
	      state.tokenize = parser;
	      return parser(stream, state);
	    }
	
	    var ch = stream.next();
	    if (ch == "<") {
	      if (stream.eat("!")) {
	        if (stream.eat("[")) {
	          if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
	          else return null;
	        } else if (stream.match("--")) {
	          return chain(inBlock("comment", "-->"));
	        } else if (stream.match("DOCTYPE", true, true)) {
	          stream.eatWhile(/[\w\._\-]/);
	          return chain(doctype(1));
	        } else {
	          return null;
	        }
	      } else if (stream.eat("?")) {
	        stream.eatWhile(/[\w\._\-]/);
	        state.tokenize = inBlock("meta", "?>");
	        return "meta";
	      } else {
	        type = stream.eat("/") ? "closeTag" : "openTag";
	        state.tokenize = inTag;
	        return "tag bracket";
	      }
	    } else if (ch == "&") {
	      var ok;
	      if (stream.eat("#")) {
	        if (stream.eat("x")) {
	          ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
	        } else {
	          ok = stream.eatWhile(/[\d]/) && stream.eat(";");
	        }
	      } else {
	        ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
	      }
	      return ok ? "atom" : "error";
	    } else {
	      stream.eatWhile(/[^&<]/);
	      return null;
	    }
	  }
	  inText.isInText = true;
	
	  function inTag(stream, state) {
	    var ch = stream.next();
	    if (ch == ">" || (ch == "/" && stream.eat(">"))) {
	      state.tokenize = inText;
	      type = ch == ">" ? "endTag" : "selfcloseTag";
	      return "tag bracket";
	    } else if (ch == "=") {
	      type = "equals";
	      return null;
	    } else if (ch == "<") {
	      state.tokenize = inText;
	      state.state = baseState;
	      state.tagName = state.tagStart = null;
	      var next = state.tokenize(stream, state);
	      return next ? next + " tag error" : "tag error";
	    } else if (/[\'\"]/.test(ch)) {
	      state.tokenize = inAttribute(ch);
	      state.stringStartCol = stream.column();
	      return state.tokenize(stream, state);
	    } else {
	      stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
	      return "word";
	    }
	  }
	
	  function inAttribute(quote) {
	    var closure = function(stream, state) {
	      while (!stream.eol()) {
	        if (stream.next() == quote) {
	          state.tokenize = inTag;
	          break;
	        }
	      }
	      return "string";
	    };
	    closure.isInAttribute = true;
	    return closure;
	  }
	
	  function inBlock(style, terminator) {
	    return function(stream, state) {
	      while (!stream.eol()) {
	        if (stream.match(terminator)) {
	          state.tokenize = inText;
	          break;
	        }
	        stream.next();
	      }
	      return style;
	    };
	  }
	  function doctype(depth) {
	    return function(stream, state) {
	      var ch;
	      while ((ch = stream.next()) != null) {
	        if (ch == "<") {
	          state.tokenize = doctype(depth + 1);
	          return state.tokenize(stream, state);
	        } else if (ch == ">") {
	          if (depth == 1) {
	            state.tokenize = inText;
	            break;
	          } else {
	            state.tokenize = doctype(depth - 1);
	            return state.tokenize(stream, state);
	          }
	        }
	      }
	      return "meta";
	    };
	  }
	
	  function Context(state, tagName, startOfLine) {
	    this.prev = state.context;
	    this.tagName = tagName;
	    this.indent = state.indented;
	    this.startOfLine = startOfLine;
	    if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
	      this.noIndent = true;
	  }
	  function popContext(state) {
	    if (state.context) state.context = state.context.prev;
	  }
	  function maybePopContext(state, nextTagName) {
	    var parentTagName;
	    while (true) {
	      if (!state.context) {
	        return;
	      }
	      parentTagName = state.context.tagName;
	      if (!config.contextGrabbers.hasOwnProperty(parentTagName) ||
	          !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
	        return;
	      }
	      popContext(state);
	    }
	  }
	
	  function baseState(type, stream, state) {
	    if (type == "openTag") {
	      state.tagStart = stream.column();
	      return tagNameState;
	    } else if (type == "closeTag") {
	      return closeTagNameState;
	    } else {
	      return baseState;
	    }
	  }
	  function tagNameState(type, stream, state) {
	    if (type == "word") {
	      state.tagName = stream.current();
	      setStyle = "tag";
	      return attrState;
	    } else {
	      setStyle = "error";
	      return tagNameState;
	    }
	  }
	  function closeTagNameState(type, stream, state) {
	    if (type == "word") {
	      var tagName = stream.current();
	      if (state.context && state.context.tagName != tagName &&
	          config.implicitlyClosed.hasOwnProperty(state.context.tagName))
	        popContext(state);
	      if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
	        setStyle = "tag";
	        return closeState;
	      } else {
	        setStyle = "tag error";
	        return closeStateErr;
	      }
	    } else {
	      setStyle = "error";
	      return closeStateErr;
	    }
	  }
	
	  function closeState(type, _stream, state) {
	    if (type != "endTag") {
	      setStyle = "error";
	      return closeState;
	    }
	    popContext(state);
	    return baseState;
	  }
	  function closeStateErr(type, stream, state) {
	    setStyle = "error";
	    return closeState(type, stream, state);
	  }
	
	  function attrState(type, _stream, state) {
	    if (type == "word") {
	      setStyle = "attribute";
	      return attrEqState;
	    } else if (type == "endTag" || type == "selfcloseTag") {
	      var tagName = state.tagName, tagStart = state.tagStart;
	      state.tagName = state.tagStart = null;
	      if (type == "selfcloseTag" ||
	          config.autoSelfClosers.hasOwnProperty(tagName)) {
	        maybePopContext(state, tagName);
	      } else {
	        maybePopContext(state, tagName);
	        state.context = new Context(state, tagName, tagStart == state.indented);
	      }
	      return baseState;
	    }
	    setStyle = "error";
	    return attrState;
	  }
	  function attrEqState(type, stream, state) {
	    if (type == "equals") return attrValueState;
	    if (!config.allowMissing) setStyle = "error";
	    return attrState(type, stream, state);
	  }
	  function attrValueState(type, stream, state) {
	    if (type == "string") return attrContinuedState;
	    if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
	    setStyle = "error";
	    return attrState(type, stream, state);
	  }
	  function attrContinuedState(type, stream, state) {
	    if (type == "string") return attrContinuedState;
	    return attrState(type, stream, state);
	  }
	
	  return {
	    startState: function(baseIndent) {
	      var state = {tokenize: inText,
	                   state: baseState,
	                   indented: baseIndent || 0,
	                   tagName: null, tagStart: null,
	                   context: null}
	      if (baseIndent != null) state.baseIndent = baseIndent
	      return state
	    },
	
	    token: function(stream, state) {
	      if (!state.tagName && stream.sol())
	        state.indented = stream.indentation();
	
	      if (stream.eatSpace()) return null;
	      type = null;
	      var style = state.tokenize(stream, state);
	      if ((style || type) && style != "comment") {
	        setStyle = null;
	        state.state = state.state(type || style, stream, state);
	        if (setStyle)
	          style = setStyle == "error" ? style + " error" : setStyle;
	      }
	      return style;
	    },
	
	    indent: function(state, textAfter, fullLine) {
	      var context = state.context;
	      // Indent multi-line strings (e.g. css).
	      if (state.tokenize.isInAttribute) {
	        if (state.tagStart == state.indented)
	          return state.stringStartCol + 1;
	        else
	          return state.indented + indentUnit;
	      }
	      if (context && context.noIndent) return CodeMirror.Pass;
	      if (state.tokenize != inTag && state.tokenize != inText)
	        return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
	      // Indent the starts of attribute names.
	      if (state.tagName) {
	        if (config.multilineTagIndentPastTag !== false)
	          return state.tagStart + state.tagName.length + 2;
	        else
	          return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
	      }
	      if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
	      var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
	      if (tagAfter && tagAfter[1]) { // Closing tag spotted
	        while (context) {
	          if (context.tagName == tagAfter[2]) {
	            context = context.prev;
	            break;
	          } else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) {
	            context = context.prev;
	          } else {
	            break;
	          }
	        }
	      } else if (tagAfter) { // Opening tag spotted
	        while (context) {
	          var grabbers = config.contextGrabbers[context.tagName];
	          if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
	            context = context.prev;
	          else
	            break;
	        }
	      }
	      while (context && context.prev && !context.startOfLine)
	        context = context.prev;
	      if (context) return context.indent + indentUnit;
	      else return state.baseIndent || 0;
	    },
	
	    electricInput: /<\/[\s\w:]+>$/,
	    blockCommentStart: "<!--",
	    blockCommentEnd: "-->",
	
	    configuration: config.htmlMode ? "html" : "xml",
	    helperType: config.htmlMode ? "html" : "xml",
	
	    skipAttribute: function(state) {
	      if (state.state == attrValueState)
	        state.state = attrState
	    }
	  };
	});
	
	CodeMirror.defineMIME("text/xml", "xml");
	CodeMirror.defineMIME("application/xml", "xml");
	if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
	  CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/xml/xml.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/addon/mode/overlay.js **/
jupyter.define('codemirror@5.23.0/addon/mode/overlay.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	// Utility function that allows modes to be combined. The mode given
	// as the base argument takes care of most of the normal mode
	// functionality, but a second (typically simple) mode is used, which
	// can override the style of text. Both modes get to parse all of the
	// text, but when both assign a non-null style to a piece of code, the
	// overlay wins, unless the combine argument was true and not overridden,
	// or state.overlay.combineTokens was true, in which case the styles are
	// combined.
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	CodeMirror.overlayMode = function(base, overlay, combine) {
	  return {
	    startState: function() {
	      return {
	        base: CodeMirror.startState(base),
	        overlay: CodeMirror.startState(overlay),
	        basePos: 0, baseCur: null,
	        overlayPos: 0, overlayCur: null,
	        streamSeen: null
	      };
	    },
	    copyState: function(state) {
	      return {
	        base: CodeMirror.copyState(base, state.base),
	        overlay: CodeMirror.copyState(overlay, state.overlay),
	        basePos: state.basePos, baseCur: null,
	        overlayPos: state.overlayPos, overlayCur: null
	      };
	    },
	
	    token: function(stream, state) {
	      if (stream != state.streamSeen ||
	          Math.min(state.basePos, state.overlayPos) < stream.start) {
	        state.streamSeen = stream;
	        state.basePos = state.overlayPos = stream.start;
	      }
	
	      if (stream.start == state.basePos) {
	        state.baseCur = base.token(stream, state.base);
	        state.basePos = stream.pos;
	      }
	      if (stream.start == state.overlayPos) {
	        stream.pos = stream.start;
	        state.overlayCur = overlay.token(stream, state.overlay);
	        state.overlayPos = stream.pos;
	      }
	      stream.pos = Math.min(state.basePos, state.overlayPos);
	
	      // state.overlay.combineTokens always takes precedence over combine,
	      // unless set to null
	      if (state.overlayCur == null) return state.baseCur;
	      else if (state.baseCur != null &&
	               state.overlay.combineTokens ||
	               combine && state.overlay.combineTokens == null)
	        return state.baseCur + " " + state.overlayCur;
	      else return state.overlayCur;
	    },
	
	    indent: base.indent && function(state, textAfter) {
	      return base.indent(state.base, textAfter);
	    },
	    electricChars: base.electricChars,
	
	    innerMode: function(state) { return {state: state.base, mode: base}; },
	
	    blankLine: function(state) {
	      var baseToken, overlayToken;
	      if (base.blankLine) baseToken = base.blankLine(state.base);
	      if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay);
	
	      return overlayToken == null ?
	        baseToken :
	        (combine && baseToken != null ? baseToken + " " + overlayToken : overlayToken);
	    }
	  };
	};
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/addon/mode/overlay.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/addon/mode/multiplex.js **/
jupyter.define('codemirror@5.23.0/addon/mode/multiplex.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	CodeMirror.multiplexingMode = function(outer /*, others */) {
	  // Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
	  var others = Array.prototype.slice.call(arguments, 1);
	
	  function indexOf(string, pattern, from, returnEnd) {
	    if (typeof pattern == "string") {
	      var found = string.indexOf(pattern, from);
	      return returnEnd && found > -1 ? found + pattern.length : found;
	    }
	    var m = pattern.exec(from ? string.slice(from) : string);
	    return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
	  }
	
	  return {
	    startState: function() {
	      return {
	        outer: CodeMirror.startState(outer),
	        innerActive: null,
	        inner: null
	      };
	    },
	
	    copyState: function(state) {
	      return {
	        outer: CodeMirror.copyState(outer, state.outer),
	        innerActive: state.innerActive,
	        inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
	      };
	    },
	
	    token: function(stream, state) {
	      if (!state.innerActive) {
	        var cutOff = Infinity, oldContent = stream.string;
	        for (var i = 0; i < others.length; ++i) {
	          var other = others[i];
	          var found = indexOf(oldContent, other.open, stream.pos);
	          if (found == stream.pos) {
	            if (!other.parseDelimiters) stream.match(other.open);
	            state.innerActive = other;
	            state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
	            return other.delimStyle && (other.delimStyle + " " + other.delimStyle + "-open");
	          } else if (found != -1 && found < cutOff) {
	            cutOff = found;
	          }
	        }
	        if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
	        var outerToken = outer.token(stream, state.outer);
	        if (cutOff != Infinity) stream.string = oldContent;
	        return outerToken;
	      } else {
	        var curInner = state.innerActive, oldContent = stream.string;
	        if (!curInner.close && stream.sol()) {
	          state.innerActive = state.inner = null;
	          return this.token(stream, state);
	        }
	        var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
	        if (found == stream.pos && !curInner.parseDelimiters) {
	          stream.match(curInner.close);
	          state.innerActive = state.inner = null;
	          return curInner.delimStyle && (curInner.delimStyle + " " + curInner.delimStyle + "-close");
	        }
	        if (found > -1) stream.string = oldContent.slice(0, found);
	        var innerToken = curInner.mode.token(stream, state.inner);
	        if (found > -1) stream.string = oldContent;
	
	        if (found == stream.pos && curInner.parseDelimiters)
	          state.innerActive = state.inner = null;
	
	        if (curInner.innerStyle) {
	          if (innerToken) innerToken = innerToken + " " + curInner.innerStyle;
	          else innerToken = curInner.innerStyle;
	        }
	
	        return innerToken;
	      }
	    },
	
	    indent: function(state, textAfter) {
	      var mode = state.innerActive ? state.innerActive.mode : outer;
	      if (!mode.indent) return CodeMirror.Pass;
	      return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
	    },
	
	    blankLine: function(state) {
	      var mode = state.innerActive ? state.innerActive.mode : outer;
	      if (mode.blankLine) {
	        mode.blankLine(state.innerActive ? state.inner : state.outer);
	      }
	      if (!state.innerActive) {
	        for (var i = 0; i < others.length; ++i) {
	          var other = others[i];
	          if (other.open === "\n") {
	            state.innerActive = other;
	            state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
	          }
	        }
	      } else if (state.innerActive.close === "\n") {
	        state.innerActive = state.inner = null;
	      }
	    },
	
	    electricChars: outer.electricChars,
	
	    innerMode: function(state) {
	      return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
	    }
	  };
	};
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/addon/mode/multiplex.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/javascript/javascript.js **/
jupyter.define('codemirror@5.23.0/mode/javascript/javascript.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	function expressionAllowed(stream, state, backUp) {
	  return /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
	    (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
	}
	
	CodeMirror.defineMode("javascript", function(config, parserConfig) {
	  var indentUnit = config.indentUnit;
	  var statementIndent = parserConfig.statementIndent;
	  var jsonldMode = parserConfig.jsonld;
	  var jsonMode = parserConfig.json || jsonldMode;
	  var isTS = parserConfig.typescript;
	  var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
	
	  // Tokenizer
	
	  var keywords = function(){
	    function kw(type) {return {type: type, style: "keyword"};}
	    var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
	    var operator = kw("operator"), atom = {type: "atom", style: "atom"};
	
	    var jsKeywords = {
	      "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
	      "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C,
	      "var": kw("var"), "const": kw("var"), "let": kw("var"),
	      "function": kw("function"), "catch": kw("catch"),
	      "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
	      "in": operator, "typeof": operator, "instanceof": operator,
	      "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
	      "this": kw("this"), "class": kw("class"), "super": kw("atom"),
	      "yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
	      "await": C, "async": kw("async")
	    };
	
	    // Extend the 'normal' keywords with the TypeScript language extensions
	    if (isTS) {
	      var type = {type: "variable", style: "variable-3"};
	      var tsKeywords = {
	        // object-like things
	        "interface": kw("class"),
	        "implements": C,
	        "namespace": C,
	        "module": kw("module"),
	        "enum": kw("module"),
	        "type": kw("type"),
	
	        // scope modifiers
	        "public": kw("modifier"),
	        "private": kw("modifier"),
	        "protected": kw("modifier"),
	        "abstract": kw("modifier"),
	
	        // operators
	        "as": operator,
	
	        // types
	        "string": type, "number": type, "boolean": type, "any": type
	      };
	
	      for (var attr in tsKeywords) {
	        jsKeywords[attr] = tsKeywords[attr];
	      }
	    }
	
	    return jsKeywords;
	  }();
	
	  var isOperatorChar = /[+\-*&%=<>!?|~^]/;
	  var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
	
	  function readRegexp(stream) {
	    var escaped = false, next, inSet = false;
	    while ((next = stream.next()) != null) {
	      if (!escaped) {
	        if (next == "/" && !inSet) return;
	        if (next == "[") inSet = true;
	        else if (inSet && next == "]") inSet = false;
	      }
	      escaped = !escaped && next == "\\";
	    }
	  }
	
	  // Used as scratch variables to communicate multiple values without
	  // consing up tons of objects.
	  var type, content;
	  function ret(tp, style, cont) {
	    type = tp; content = cont;
	    return style;
	  }
	  function tokenBase(stream, state) {
	    var ch = stream.next();
	    if (ch == '"' || ch == "'") {
	      state.tokenize = tokenString(ch);
	      return state.tokenize(stream, state);
	    } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
	      return ret("number", "number");
	    } else if (ch == "." && stream.match("..")) {
	      return ret("spread", "meta");
	    } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
	      return ret(ch);
	    } else if (ch == "=" && stream.eat(">")) {
	      return ret("=>", "operator");
	    } else if (ch == "0" && stream.eat(/x/i)) {
	      stream.eatWhile(/[\da-f]/i);
	      return ret("number", "number");
	    } else if (ch == "0" && stream.eat(/o/i)) {
	      stream.eatWhile(/[0-7]/i);
	      return ret("number", "number");
	    } else if (ch == "0" && stream.eat(/b/i)) {
	      stream.eatWhile(/[01]/i);
	      return ret("number", "number");
	    } else if (/\d/.test(ch)) {
	      stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
	      return ret("number", "number");
	    } else if (ch == "/") {
	      if (stream.eat("*")) {
	        state.tokenize = tokenComment;
	        return tokenComment(stream, state);
	      } else if (stream.eat("/")) {
	        stream.skipToEnd();
	        return ret("comment", "comment");
	      } else if (expressionAllowed(stream, state, 1)) {
	        readRegexp(stream);
	        stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
	        return ret("regexp", "string-2");
	      } else {
	        stream.eatWhile(isOperatorChar);
	        return ret("operator", "operator", stream.current());
	      }
	    } else if (ch == "`") {
	      state.tokenize = tokenQuasi;
	      return tokenQuasi(stream, state);
	    } else if (ch == "#") {
	      stream.skipToEnd();
	      return ret("error", "error");
	    } else if (isOperatorChar.test(ch)) {
	      if (ch != ">" || !state.lexical || state.lexical.type != ">")
	        stream.eatWhile(isOperatorChar);
	      return ret("operator", "operator", stream.current());
	    } else if (wordRE.test(ch)) {
	      stream.eatWhile(wordRE);
	      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
	      return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
	                     ret("variable", "variable", word);
	    }
	  }
	
	  function tokenString(quote) {
	    return function(stream, state) {
	      var escaped = false, next;
	      if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
	        state.tokenize = tokenBase;
	        return ret("jsonld-keyword", "meta");
	      }
	      while ((next = stream.next()) != null) {
	        if (next == quote && !escaped) break;
	        escaped = !escaped && next == "\\";
	      }
	      if (!escaped) state.tokenize = tokenBase;
	      return ret("string", "string");
	    };
	  }
	
	  function tokenComment(stream, state) {
	    var maybeEnd = false, ch;
	    while (ch = stream.next()) {
	      if (ch == "/" && maybeEnd) {
	        state.tokenize = tokenBase;
	        break;
	      }
	      maybeEnd = (ch == "*");
	    }
	    return ret("comment", "comment");
	  }
	
	  function tokenQuasi(stream, state) {
	    var escaped = false, next;
	    while ((next = stream.next()) != null) {
	      if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
	        state.tokenize = tokenBase;
	        break;
	      }
	      escaped = !escaped && next == "\\";
	    }
	    return ret("quasi", "string-2", stream.current());
	  }
	
	  var brackets = "([{}])";
	  // This is a crude lookahead trick to try and notice that we're
	  // parsing the argument patterns for a fat-arrow function before we
	  // actually hit the arrow token. It only works if the arrow is on
	  // the same line as the arguments and there's no strange noise
	  // (comments) in between. Fallback is to only notice when we hit the
	  // arrow, and not declare the arguments as locals for the arrow
	  // body.
	  function findFatArrow(stream, state) {
	    if (state.fatArrowAt) state.fatArrowAt = null;
	    var arrow = stream.string.indexOf("=>", stream.start);
	    if (arrow < 0) return;
	
	    if (isTS) { // Try to skip TypeScript return type declarations after the arguments
	      var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow))
	      if (m) arrow = m.index
	    }
	
	    var depth = 0, sawSomething = false;
	    for (var pos = arrow - 1; pos >= 0; --pos) {
	      var ch = stream.string.charAt(pos);
	      var bracket = brackets.indexOf(ch);
	      if (bracket >= 0 && bracket < 3) {
	        if (!depth) { ++pos; break; }
	        if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
	      } else if (bracket >= 3 && bracket < 6) {
	        ++depth;
	      } else if (wordRE.test(ch)) {
	        sawSomething = true;
	      } else if (/["'\/]/.test(ch)) {
	        return;
	      } else if (sawSomething && !depth) {
	        ++pos;
	        break;
	      }
	    }
	    if (sawSomething && !depth) state.fatArrowAt = pos;
	  }
	
	  // Parser
	
	  var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
	
	  function JSLexical(indented, column, type, align, prev, info) {
	    this.indented = indented;
	    this.column = column;
	    this.type = type;
	    this.prev = prev;
	    this.info = info;
	    if (align != null) this.align = align;
	  }
	
	  function inScope(state, varname) {
	    for (var v = state.localVars; v; v = v.next)
	      if (v.name == varname) return true;
	    for (var cx = state.context; cx; cx = cx.prev) {
	      for (var v = cx.vars; v; v = v.next)
	        if (v.name == varname) return true;
	    }
	  }
	
	  function parseJS(state, style, type, content, stream) {
	    var cc = state.cc;
	    // Communicate our context to the combinators.
	    // (Less wasteful than consing up a hundred closures on every call.)
	    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
	
	    if (!state.lexical.hasOwnProperty("align"))
	      state.lexical.align = true;
	
	    while(true) {
	      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
	      if (combinator(type, content)) {
	        while(cc.length && cc[cc.length - 1].lex)
	          cc.pop()();
	        if (cx.marked) return cx.marked;
	        if (type == "variable" && inScope(state, content)) return "variable-2";
	        return style;
	      }
	    }
	  }
	
	  // Combinator utils
	
	  var cx = {state: null, column: null, marked: null, cc: null};
	  function pass() {
	    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
	  }
	  function cont() {
	    pass.apply(null, arguments);
	    return true;
	  }
	  function register(varname) {
	    function inList(list) {
	      for (var v = list; v; v = v.next)
	        if (v.name == varname) return true;
	      return false;
	    }
	    var state = cx.state;
	    cx.marked = "def";
	    if (state.context) {
	      if (inList(state.localVars)) return;
	      state.localVars = {name: varname, next: state.localVars};
	    } else {
	      if (inList(state.globalVars)) return;
	      if (parserConfig.globalVars)
	        state.globalVars = {name: varname, next: state.globalVars};
	    }
	  }
	
	  // Combinators
	
	  var defaultVars = {name: "this", next: {name: "arguments"}};
	  function pushcontext() {
	    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
	    cx.state.localVars = defaultVars;
	  }
	  function popcontext() {
	    cx.state.localVars = cx.state.context.vars;
	    cx.state.context = cx.state.context.prev;
	  }
	  function pushlex(type, info) {
	    var result = function() {
	      var state = cx.state, indent = state.indented;
	      if (state.lexical.type == "stat") indent = state.lexical.indented;
	      else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
	        indent = outer.indented;
	      state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
	    };
	    result.lex = true;
	    return result;
	  }
	  function poplex() {
	    var state = cx.state;
	    if (state.lexical.prev) {
	      if (state.lexical.type == ")")
	        state.indented = state.lexical.indented;
	      state.lexical = state.lexical.prev;
	    }
	  }
	  poplex.lex = true;
	
	  function expect(wanted) {
	    function exp(type) {
	      if (type == wanted) return cont();
	      else if (wanted == ";") return pass();
	      else return cont(exp);
	    };
	    return exp;
	  }
	
	  function statement(type, value) {
	    if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
	    if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
	    if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
	    if (type == "{") return cont(pushlex("}"), block, poplex);
	    if (type == ";") return cont();
	    if (type == "if") {
	      if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
	        cx.state.cc.pop()();
	      return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
	    }
	    if (type == "function") return cont(functiondef);
	    if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
	    if (type == "variable") return cont(pushlex("stat"), maybelabel);
	    if (type == "switch") return cont(pushlex("form"), parenExpr, pushlex("}", "switch"), expect("{"),
	                                      block, poplex, poplex);
	    if (type == "case") return cont(expression, expect(":"));
	    if (type == "default") return cont(expect(":"));
	    if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
	                                     statement, poplex, popcontext);
	    if (type == "class") return cont(pushlex("form"), className, poplex);
	    if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
	    if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
	    if (type == "module") return cont(pushlex("form"), pattern, pushlex("}"), expect("{"), block, poplex, poplex)
	    if (type == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";"));
	    if (type == "async") return cont(statement)
	    return pass(pushlex("stat"), expression, expect(";"), poplex);
	  }
	  function expression(type) {
	    return expressionInner(type, false);
	  }
	  function expressionNoComma(type) {
	    return expressionInner(type, true);
	  }
	  function parenExpr(type) {
	    if (type != "(") return pass()
	    return cont(pushlex(")"), expression, expect(")"), poplex)
	  }
	  function expressionInner(type, noComma) {
	    if (cx.state.fatArrowAt == cx.stream.start) {
	      var body = noComma ? arrowBodyNoComma : arrowBody;
	      if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
	      else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
	    }
	
	    var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
	    if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
	    if (type == "function") return cont(functiondef, maybeop);
	    if (type == "class") return cont(pushlex("form"), classExpression, poplex);
	    if (type == "keyword c" || type == "async") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
	    if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
	    if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
	    if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
	    if (type == "{") return contCommasep(objprop, "}", null, maybeop);
	    if (type == "quasi") return pass(quasi, maybeop);
	    if (type == "new") return cont(maybeTarget(noComma));
	    return cont();
	  }
	  function maybeexpression(type) {
	    if (type.match(/[;\}\)\],]/)) return pass();
	    return pass(expression);
	  }
	  function maybeexpressionNoComma(type) {
	    if (type.match(/[;\}\)\],]/)) return pass();
	    return pass(expressionNoComma);
	  }
	
	  function maybeoperatorComma(type, value) {
	    if (type == ",") return cont(expression);
	    return maybeoperatorNoComma(type, value, false);
	  }
	  function maybeoperatorNoComma(type, value, noComma) {
	    var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
	    var expr = noComma == false ? expression : expressionNoComma;
	    if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
	    if (type == "operator") {
	      if (/\+\+|--/.test(value)) return cont(me);
	      if (value == "?") return cont(expression, expect(":"), expr);
	      return cont(expr);
	    }
	    if (type == "quasi") { return pass(quasi, me); }
	    if (type == ";") return;
	    if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
	    if (type == ".") return cont(property, me);
	    if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
	  }
	  function quasi(type, value) {
	    if (type != "quasi") return pass();
	    if (value.slice(value.length - 2) != "${") return cont(quasi);
	    return cont(expression, continueQuasi);
	  }
	  function continueQuasi(type) {
	    if (type == "}") {
	      cx.marked = "string-2";
	      cx.state.tokenize = tokenQuasi;
	      return cont(quasi);
	    }
	  }
	  function arrowBody(type) {
	    findFatArrow(cx.stream, cx.state);
	    return pass(type == "{" ? statement : expression);
	  }
	  function arrowBodyNoComma(type) {
	    findFatArrow(cx.stream, cx.state);
	    return pass(type == "{" ? statement : expressionNoComma);
	  }
	  function maybeTarget(noComma) {
	    return function(type) {
	      if (type == ".") return cont(noComma ? targetNoComma : target);
	      else return pass(noComma ? expressionNoComma : expression);
	    };
	  }
	  function target(_, value) {
	    if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
	  }
	  function targetNoComma(_, value) {
	    if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
	  }
	  function maybelabel(type) {
	    if (type == ":") return cont(poplex, statement);
	    return pass(maybeoperatorComma, expect(";"), poplex);
	  }
	  function property(type) {
	    if (type == "variable") {cx.marked = "property"; return cont();}
	  }
	  function objprop(type, value) {
	    if (type == "async") {
	      cx.marked = "property";
	      return cont(objprop);
	    } else if (type == "variable" || cx.style == "keyword") {
	      cx.marked = "property";
	      if (value == "get" || value == "set") return cont(getterSetter);
	      return cont(afterprop);
	    } else if (type == "number" || type == "string") {
	      cx.marked = jsonldMode ? "property" : (cx.style + " property");
	      return cont(afterprop);
	    } else if (type == "jsonld-keyword") {
	      return cont(afterprop);
	    } else if (type == "modifier") {
	      return cont(objprop)
	    } else if (type == "[") {
	      return cont(expression, expect("]"), afterprop);
	    } else if (type == "spread") {
	      return cont(expression);
	    } else if (type == ":") {
	      return pass(afterprop)
	    }
	  }
	  function getterSetter(type) {
	    if (type != "variable") return pass(afterprop);
	    cx.marked = "property";
	    return cont(functiondef);
	  }
	  function afterprop(type) {
	    if (type == ":") return cont(expressionNoComma);
	    if (type == "(") return pass(functiondef);
	  }
	  function commasep(what, end, sep) {
	    function proceed(type, value) {
	      if (sep ? sep.indexOf(type) > -1 : type == ",") {
	        var lex = cx.state.lexical;
	        if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
	        return cont(function(type, value) {
	          if (type == end || value == end) return pass()
	          return pass(what)
	        }, proceed);
	      }
	      if (type == end || value == end) return cont();
	      return cont(expect(end));
	    }
	    return function(type, value) {
	      if (type == end || value == end) return cont();
	      return pass(what, proceed);
	    };
	  }
	  function contCommasep(what, end, info) {
	    for (var i = 3; i < arguments.length; i++)
	      cx.cc.push(arguments[i]);
	    return cont(pushlex(end, info), commasep(what, end), poplex);
	  }
	  function block(type) {
	    if (type == "}") return cont();
	    return pass(statement, block);
	  }
	  function maybetype(type, value) {
	    if (isTS) {
	      if (type == ":") return cont(typeexpr);
	      if (value == "?") return cont(maybetype);
	    }
	  }
	  function typeexpr(type) {
	    if (type == "variable") {cx.marked = "variable-3"; return cont(afterType);}
	    if (type == "string" || type == "number" || type == "atom") return cont(afterType);
	    if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex)
	    if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
	  }
	  function maybeReturnType(type) {
	    if (type == "=>") return cont(typeexpr)
	  }
	  function typeprop(type, value) {
	    if (type == "variable" || cx.style == "keyword") {
	      cx.marked = "property"
	      return cont(typeprop)
	    } else if (value == "?") {
	      return cont(typeprop)
	    } else if (type == ":") {
	      return cont(typeexpr)
	    }
	  }
	  function typearg(type) {
	    if (type == "variable") return cont(typearg)
	    else if (type == ":") return cont(typeexpr)
	  }
	  function afterType(type, value) {
	    if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
	    if (value == "|" || type == ".") return cont(typeexpr)
	    if (type == "[") return cont(expect("]"), afterType)
	  }
	  function vardef() {
	    return pass(pattern, maybetype, maybeAssign, vardefCont);
	  }
	  function pattern(type, value) {
	    if (type == "modifier") return cont(pattern)
	    if (type == "variable") { register(value); return cont(); }
	    if (type == "spread") return cont(pattern);
	    if (type == "[") return contCommasep(pattern, "]");
	    if (type == "{") return contCommasep(proppattern, "}");
	  }
	  function proppattern(type, value) {
	    if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
	      register(value);
	      return cont(maybeAssign);
	    }
	    if (type == "variable") cx.marked = "property";
	    if (type == "spread") return cont(pattern);
	    if (type == "}") return pass();
	    return cont(expect(":"), pattern, maybeAssign);
	  }
	  function maybeAssign(_type, value) {
	    if (value == "=") return cont(expressionNoComma);
	  }
	  function vardefCont(type) {
	    if (type == ",") return cont(vardef);
	  }
	  function maybeelse(type, value) {
	    if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
	  }
	  function forspec(type) {
	    if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
	  }
	  function forspec1(type) {
	    if (type == "var") return cont(vardef, expect(";"), forspec2);
	    if (type == ";") return cont(forspec2);
	    if (type == "variable") return cont(formaybeinof);
	    return pass(expression, expect(";"), forspec2);
	  }
	  function formaybeinof(_type, value) {
	    if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
	    return cont(maybeoperatorComma, forspec2);
	  }
	  function forspec2(type, value) {
	    if (type == ";") return cont(forspec3);
	    if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
	    return pass(expression, expect(";"), forspec3);
	  }
	  function forspec3(type) {
	    if (type != ")") cont(expression);
	  }
	  function functiondef(type, value) {
	    if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
	    if (type == "variable") {register(value); return cont(functiondef);}
	    if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, maybetype, statement, popcontext);
	  }
	  function funarg(type) {
	    if (type == "spread") return cont(funarg);
	    return pass(pattern, maybetype, maybeAssign);
	  }
	  function classExpression(type, value) {
	    // Class expressions may have an optional name.
	    if (type == "variable") return className(type, value);
	    return classNameAfter(type, value);
	  }
	  function className(type, value) {
	    if (type == "variable") {register(value); return cont(classNameAfter);}
	  }
	  function classNameAfter(type, value) {
	    if (value == "extends" || value == "implements") return cont(isTS ? typeexpr : expression, classNameAfter);
	    if (type == "{") return cont(pushlex("}"), classBody, poplex);
	  }
	  function classBody(type, value) {
	    if (type == "variable" || cx.style == "keyword") {
	      if ((value == "static" || value == "get" || value == "set" ||
	           (isTS && (value == "public" || value == "private" || value == "protected" || value == "readonly" || value == "abstract"))) &&
	          cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false)) {
	        cx.marked = "keyword";
	        return cont(classBody);
	      }
	      cx.marked = "property";
	      return cont(isTS ? classfield : functiondef, classBody);
	    }
	    if (value == "*") {
	      cx.marked = "keyword";
	      return cont(classBody);
	    }
	    if (type == ";") return cont(classBody);
	    if (type == "}") return cont();
	  }
	  function classfield(type, value) {
	    if (value == "?") return cont(classfield)
	    if (type == ":") return cont(typeexpr, maybeAssign)
	    return pass(functiondef)
	  }
	  function afterExport(type, value) {
	    if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
	    if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
	    if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
	    return pass(statement);
	  }
	  function exportField(type, value) {
	    if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
	    if (type == "variable") return pass(expressionNoComma, exportField);
	  }
	  function afterImport(type) {
	    if (type == "string") return cont();
	    return pass(importSpec, maybeMoreImports, maybeFrom);
	  }
	  function importSpec(type, value) {
	    if (type == "{") return contCommasep(importSpec, "}");
	    if (type == "variable") register(value);
	    if (value == "*") cx.marked = "keyword";
	    return cont(maybeAs);
	  }
	  function maybeMoreImports(type) {
	    if (type == ",") return cont(importSpec, maybeMoreImports)
	  }
	  function maybeAs(_type, value) {
	    if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
	  }
	  function maybeFrom(_type, value) {
	    if (value == "from") { cx.marked = "keyword"; return cont(expression); }
	  }
	  function arrayLiteral(type) {
	    if (type == "]") return cont();
	    return pass(commasep(expressionNoComma, "]"));
	  }
	
	  function isContinuedStatement(state, textAfter) {
	    return state.lastType == "operator" || state.lastType == "," ||
	      isOperatorChar.test(textAfter.charAt(0)) ||
	      /[,.]/.test(textAfter.charAt(0));
	  }
	
	  // Interface
	
	  return {
	    startState: function(basecolumn) {
	      var state = {
	        tokenize: tokenBase,
	        lastType: "sof",
	        cc: [],
	        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
	        localVars: parserConfig.localVars,
	        context: parserConfig.localVars && {vars: parserConfig.localVars},
	        indented: basecolumn || 0
	      };
	      if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
	        state.globalVars = parserConfig.globalVars;
	      return state;
	    },
	
	    token: function(stream, state) {
	      if (stream.sol()) {
	        if (!state.lexical.hasOwnProperty("align"))
	          state.lexical.align = false;
	        state.indented = stream.indentation();
	        findFatArrow(stream, state);
	      }
	      if (state.tokenize != tokenComment && stream.eatSpace()) return null;
	      var style = state.tokenize(stream, state);
	      if (type == "comment") return style;
	      state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
	      return parseJS(state, style, type, content, stream);
	    },
	
	    indent: function(state, textAfter) {
	      if (state.tokenize == tokenComment) return CodeMirror.Pass;
	      if (state.tokenize != tokenBase) return 0;
	      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
	      // Kludge to prevent 'maybelse' from blocking lexical scope pops
	      if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
	        var c = state.cc[i];
	        if (c == poplex) lexical = lexical.prev;
	        else if (c != maybeelse) break;
	      }
	      while ((lexical.type == "stat" || lexical.type == "form") &&
	             (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
	                                   (top == maybeoperatorComma || top == maybeoperatorNoComma) &&
	                                   !/^[,\.=+\-*:?[\(]/.test(textAfter))))
	        lexical = lexical.prev;
	      if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
	        lexical = lexical.prev;
	      var type = lexical.type, closing = firstChar == type;
	
	      if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
	      else if (type == "form" && firstChar == "{") return lexical.indented;
	      else if (type == "form") return lexical.indented + indentUnit;
	      else if (type == "stat")
	        return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
	      else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
	        return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
	      else if (lexical.align) return lexical.column + (closing ? 0 : 1);
	      else return lexical.indented + (closing ? 0 : indentUnit);
	    },
	
	    electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
	    blockCommentStart: jsonMode ? null : "/*",
	    blockCommentEnd: jsonMode ? null : "*/",
	    lineComment: jsonMode ? null : "//",
	    fold: "brace",
	    closeBrackets: "()[]{}''\"\"``",
	
	    helperType: jsonMode ? "json" : "javascript",
	    jsonldMode: jsonldMode,
	    jsonMode: jsonMode,
	
	    expressionAllowed: expressionAllowed,
	    skipExpression: function(state) {
	      var top = state.cc[state.cc.length - 1]
	      if (top == expression || top == expressionNoComma) state.cc.pop()
	    }
	  };
	});
	
	CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
	
	CodeMirror.defineMIME("text/javascript", "javascript");
	CodeMirror.defineMIME("text/ecmascript", "javascript");
	CodeMirror.defineMIME("application/javascript", "javascript");
	CodeMirror.defineMIME("application/x-javascript", "javascript");
	CodeMirror.defineMIME("application/ecmascript", "javascript");
	CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
	CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
	CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
	CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
	CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/javascript/javascript.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/css/css.js **/
jupyter.define('codemirror@5.23.0/mode/css/css.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	CodeMirror.defineMode("css", function(config, parserConfig) {
	  var inline = parserConfig.inline
	  if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
	
	  var indentUnit = config.indentUnit,
	      tokenHooks = parserConfig.tokenHooks,
	      documentTypes = parserConfig.documentTypes || {},
	      mediaTypes = parserConfig.mediaTypes || {},
	      mediaFeatures = parserConfig.mediaFeatures || {},
	      mediaValueKeywords = parserConfig.mediaValueKeywords || {},
	      propertyKeywords = parserConfig.propertyKeywords || {},
	      nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
	      fontProperties = parserConfig.fontProperties || {},
	      counterDescriptors = parserConfig.counterDescriptors || {},
	      colorKeywords = parserConfig.colorKeywords || {},
	      valueKeywords = parserConfig.valueKeywords || {},
	      allowNested = parserConfig.allowNested,
	      supportsAtComponent = parserConfig.supportsAtComponent === true;
	
	  var type, override;
	  function ret(style, tp) { type = tp; return style; }
	
	  // Tokenizers
	
	  function tokenBase(stream, state) {
	    var ch = stream.next();
	    if (tokenHooks[ch]) {
	      var result = tokenHooks[ch](stream, state);
	      if (result !== false) return result;
	    }
	    if (ch == "@") {
	      stream.eatWhile(/[\w\\\-]/);
	      return ret("def", stream.current());
	    } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
	      return ret(null, "compare");
	    } else if (ch == "\"" || ch == "'") {
	      state.tokenize = tokenString(ch);
	      return state.tokenize(stream, state);
	    } else if (ch == "#") {
	      stream.eatWhile(/[\w\\\-]/);
	      return ret("atom", "hash");
	    } else if (ch == "!") {
	      stream.match(/^\s*\w*/);
	      return ret("keyword", "important");
	    } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
	      stream.eatWhile(/[\w.%]/);
	      return ret("number", "unit");
	    } else if (ch === "-") {
	      if (/[\d.]/.test(stream.peek())) {
	        stream.eatWhile(/[\w.%]/);
	        return ret("number", "unit");
	      } else if (stream.match(/^-[\w\\\-]+/)) {
	        stream.eatWhile(/[\w\\\-]/);
	        if (stream.match(/^\s*:/, false))
	          return ret("variable-2", "variable-definition");
	        return ret("variable-2", "variable");
	      } else if (stream.match(/^\w+-/)) {
	        return ret("meta", "meta");
	      }
	    } else if (/[,+>*\/]/.test(ch)) {
	      return ret(null, "select-op");
	    } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
	      return ret("qualifier", "qualifier");
	    } else if (/[:;{}\[\]\(\)]/.test(ch)) {
	      return ret(null, ch);
	    } else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
	               (ch == "d" && stream.match("omain(")) ||
	               (ch == "r" && stream.match("egexp("))) {
	      stream.backUp(1);
	      state.tokenize = tokenParenthesized;
	      return ret("property", "word");
	    } else if (/[\w\\\-]/.test(ch)) {
	      stream.eatWhile(/[\w\\\-]/);
	      return ret("property", "word");
	    } else {
	      return ret(null, null);
	    }
	  }
	
	  function tokenString(quote) {
	    return function(stream, state) {
	      var escaped = false, ch;
	      while ((ch = stream.next()) != null) {
	        if (ch == quote && !escaped) {
	          if (quote == ")") stream.backUp(1);
	          break;
	        }
	        escaped = !escaped && ch == "\\";
	      }
	      if (ch == quote || !escaped && quote != ")") state.tokenize = null;
	      return ret("string", "string");
	    };
	  }
	
	  function tokenParenthesized(stream, state) {
	    stream.next(); // Must be '('
	    if (!stream.match(/\s*[\"\')]/, false))
	      state.tokenize = tokenString(")");
	    else
	      state.tokenize = null;
	    return ret(null, "(");
	  }
	
	  // Context management
	
	  function Context(type, indent, prev) {
	    this.type = type;
	    this.indent = indent;
	    this.prev = prev;
	  }
	
	  function pushContext(state, stream, type, indent) {
	    state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
	    return type;
	  }
	
	  function popContext(state) {
	    if (state.context.prev)
	      state.context = state.context.prev;
	    return state.context.type;
	  }
	
	  function pass(type, stream, state) {
	    return states[state.context.type](type, stream, state);
	  }
	  function popAndPass(type, stream, state, n) {
	    for (var i = n || 1; i > 0; i--)
	      state.context = state.context.prev;
	    return pass(type, stream, state);
	  }
	
	  // Parser
	
	  function wordAsValue(stream) {
	    var word = stream.current().toLowerCase();
	    if (valueKeywords.hasOwnProperty(word))
	      override = "atom";
	    else if (colorKeywords.hasOwnProperty(word))
	      override = "keyword";
	    else
	      override = "variable";
	  }
	
	  var states = {};
	
	  states.top = function(type, stream, state) {
	    if (type == "{") {
	      return pushContext(state, stream, "block");
	    } else if (type == "}" && state.context.prev) {
	      return popContext(state);
	    } else if (supportsAtComponent && /@component/.test(type)) {
	      return pushContext(state, stream, "atComponentBlock");
	    } else if (/^@(-moz-)?document$/.test(type)) {
	      return pushContext(state, stream, "documentTypes");
	    } else if (/^@(media|supports|(-moz-)?document|import)$/.test(type)) {
	      return pushContext(state, stream, "atBlock");
	    } else if (/^@(font-face|counter-style)/.test(type)) {
	      state.stateArg = type;
	      return "restricted_atBlock_before";
	    } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
	      return "keyframes";
	    } else if (type && type.charAt(0) == "@") {
	      return pushContext(state, stream, "at");
	    } else if (type == "hash") {
	      override = "builtin";
	    } else if (type == "word") {
	      override = "tag";
	    } else if (type == "variable-definition") {
	      return "maybeprop";
	    } else if (type == "interpolation") {
	      return pushContext(state, stream, "interpolation");
	    } else if (type == ":") {
	      return "pseudo";
	    } else if (allowNested && type == "(") {
	      return pushContext(state, stream, "parens");
	    }
	    return state.context.type;
	  };
	
	  states.block = function(type, stream, state) {
	    if (type == "word") {
	      var word = stream.current().toLowerCase();
	      if (propertyKeywords.hasOwnProperty(word)) {
	        override = "property";
	        return "maybeprop";
	      } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
	        override = "string-2";
	        return "maybeprop";
	      } else if (allowNested) {
	        override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
	        return "block";
	      } else {
	        override += " error";
	        return "maybeprop";
	      }
	    } else if (type == "meta") {
	      return "block";
	    } else if (!allowNested && (type == "hash" || type == "qualifier")) {
	      override = "error";
	      return "block";
	    } else {
	      return states.top(type, stream, state);
	    }
	  };
	
	  states.maybeprop = function(type, stream, state) {
	    if (type == ":") return pushContext(state, stream, "prop");
	    return pass(type, stream, state);
	  };
	
	  states.prop = function(type, stream, state) {
	    if (type == ";") return popContext(state);
	    if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
	    if (type == "}" || type == "{") return popAndPass(type, stream, state);
	    if (type == "(") return pushContext(state, stream, "parens");
	
	    if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) {
	      override += " error";
	    } else if (type == "word") {
	      wordAsValue(stream);
	    } else if (type == "interpolation") {
	      return pushContext(state, stream, "interpolation");
	    }
	    return "prop";
	  };
	
	  states.propBlock = function(type, _stream, state) {
	    if (type == "}") return popContext(state);
	    if (type == "word") { override = "property"; return "maybeprop"; }
	    return state.context.type;
	  };
	
	  states.parens = function(type, stream, state) {
	    if (type == "{" || type == "}") return popAndPass(type, stream, state);
	    if (type == ")") return popContext(state);
	    if (type == "(") return pushContext(state, stream, "parens");
	    if (type == "interpolation") return pushContext(state, stream, "interpolation");
	    if (type == "word") wordAsValue(stream);
	    return "parens";
	  };
	
	  states.pseudo = function(type, stream, state) {
	    if (type == "word") {
	      override = "variable-3";
	      return state.context.type;
	    }
	    return pass(type, stream, state);
	  };
	
	  states.documentTypes = function(type, stream, state) {
	    if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
	      override = "tag";
	      return state.context.type;
	    } else {
	      return states.atBlock(type, stream, state);
	    }
	  };
	
	  states.atBlock = function(type, stream, state) {
	    if (type == "(") return pushContext(state, stream, "atBlock_parens");
	    if (type == "}" || type == ";") return popAndPass(type, stream, state);
	    if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
	
	    if (type == "interpolation") return pushContext(state, stream, "interpolation");
	
	    if (type == "word") {
	      var word = stream.current().toLowerCase();
	      if (word == "only" || word == "not" || word == "and" || word == "or")
	        override = "keyword";
	      else if (mediaTypes.hasOwnProperty(word))
	        override = "attribute";
	      else if (mediaFeatures.hasOwnProperty(word))
	        override = "property";
	      else if (mediaValueKeywords.hasOwnProperty(word))
	        override = "keyword";
	      else if (propertyKeywords.hasOwnProperty(word))
	        override = "property";
	      else if (nonStandardPropertyKeywords.hasOwnProperty(word))
	        override = "string-2";
	      else if (valueKeywords.hasOwnProperty(word))
	        override = "atom";
	      else if (colorKeywords.hasOwnProperty(word))
	        override = "keyword";
	      else
	        override = "error";
	    }
	    return state.context.type;
	  };
	
	  states.atComponentBlock = function(type, stream, state) {
	    if (type == "}")
	      return popAndPass(type, stream, state);
	    if (type == "{")
	      return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
	    if (type == "word")
	      override = "error";
	    return state.context.type;
	  };
	
	  states.atBlock_parens = function(type, stream, state) {
	    if (type == ")") return popContext(state);
	    if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
	    return states.atBlock(type, stream, state);
	  };
	
	  states.restricted_atBlock_before = function(type, stream, state) {
	    if (type == "{")
	      return pushContext(state, stream, "restricted_atBlock");
	    if (type == "word" && state.stateArg == "@counter-style") {
	      override = "variable";
	      return "restricted_atBlock_before";
	    }
	    return pass(type, stream, state);
	  };
	
	  states.restricted_atBlock = function(type, stream, state) {
	    if (type == "}") {
	      state.stateArg = null;
	      return popContext(state);
	    }
	    if (type == "word") {
	      if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
	          (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
	        override = "error";
	      else
	        override = "property";
	      return "maybeprop";
	    }
	    return "restricted_atBlock";
	  };
	
	  states.keyframes = function(type, stream, state) {
	    if (type == "word") { override = "variable"; return "keyframes"; }
	    if (type == "{") return pushContext(state, stream, "top");
	    return pass(type, stream, state);
	  };
	
	  states.at = function(type, stream, state) {
	    if (type == ";") return popContext(state);
	    if (type == "{" || type == "}") return popAndPass(type, stream, state);
	    if (type == "word") override = "tag";
	    else if (type == "hash") override = "builtin";
	    return "at";
	  };
	
	  states.interpolation = function(type, stream, state) {
	    if (type == "}") return popContext(state);
	    if (type == "{" || type == ";") return popAndPass(type, stream, state);
	    if (type == "word") override = "variable";
	    else if (type != "variable" && type != "(" && type != ")") override = "error";
	    return "interpolation";
	  };
	
	  return {
	    startState: function(base) {
	      return {tokenize: null,
	              state: inline ? "block" : "top",
	              stateArg: null,
	              context: new Context(inline ? "block" : "top", base || 0, null)};
	    },
	
	    token: function(stream, state) {
	      if (!state.tokenize && stream.eatSpace()) return null;
	      var style = (state.tokenize || tokenBase)(stream, state);
	      if (style && typeof style == "object") {
	        type = style[1];
	        style = style[0];
	      }
	      override = style;
	      state.state = states[state.state](type, stream, state);
	      return override;
	    },
	
	    indent: function(state, textAfter) {
	      var cx = state.context, ch = textAfter && textAfter.charAt(0);
	      var indent = cx.indent;
	      if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
	      if (cx.prev) {
	        if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
	                          cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
	          // Resume indentation from parent context.
	          cx = cx.prev;
	          indent = cx.indent;
	        } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
	            ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
	          // Dedent relative to current context.
	          indent = Math.max(0, cx.indent - indentUnit);
	          cx = cx.prev;
	        }
	      }
	      return indent;
	    },
	
	    electricChars: "}",
	    blockCommentStart: "/*",
	    blockCommentEnd: "*/",
	    fold: "brace"
	  };
	});
	
	  function keySet(array) {
	    var keys = {};
	    for (var i = 0; i < array.length; ++i) {
	      keys[array[i].toLowerCase()] = true;
	    }
	    return keys;
	  }
	
	  var documentTypes_ = [
	    "domain", "regexp", "url", "url-prefix"
	  ], documentTypes = keySet(documentTypes_);
	
	  var mediaTypes_ = [
	    "all", "aural", "braille", "handheld", "print", "projection", "screen",
	    "tty", "tv", "embossed"
	  ], mediaTypes = keySet(mediaTypes_);
	
	  var mediaFeatures_ = [
	    "width", "min-width", "max-width", "height", "min-height", "max-height",
	    "device-width", "min-device-width", "max-device-width", "device-height",
	    "min-device-height", "max-device-height", "aspect-ratio",
	    "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
	    "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
	    "max-color", "color-index", "min-color-index", "max-color-index",
	    "monochrome", "min-monochrome", "max-monochrome", "resolution",
	    "min-resolution", "max-resolution", "scan", "grid", "orientation",
	    "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
	    "pointer", "any-pointer", "hover", "any-hover"
	  ], mediaFeatures = keySet(mediaFeatures_);
	
	  var mediaValueKeywords_ = [
	    "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
	    "interlace", "progressive"
	  ], mediaValueKeywords = keySet(mediaValueKeywords_);
	
	  var propertyKeywords_ = [
	    "align-content", "align-items", "align-self", "alignment-adjust",
	    "alignment-baseline", "anchor-point", "animation", "animation-delay",
	    "animation-direction", "animation-duration", "animation-fill-mode",
	    "animation-iteration-count", "animation-name", "animation-play-state",
	    "animation-timing-function", "appearance", "azimuth", "backface-visibility",
	    "background", "background-attachment", "background-blend-mode", "background-clip",
	    "background-color", "background-image", "background-origin", "background-position",
	    "background-repeat", "background-size", "baseline-shift", "binding",
	    "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
	    "bookmark-target", "border", "border-bottom", "border-bottom-color",
	    "border-bottom-left-radius", "border-bottom-right-radius",
	    "border-bottom-style", "border-bottom-width", "border-collapse",
	    "border-color", "border-image", "border-image-outset",
	    "border-image-repeat", "border-image-slice", "border-image-source",
	    "border-image-width", "border-left", "border-left-color",
	    "border-left-style", "border-left-width", "border-radius", "border-right",
	    "border-right-color", "border-right-style", "border-right-width",
	    "border-spacing", "border-style", "border-top", "border-top-color",
	    "border-top-left-radius", "border-top-right-radius", "border-top-style",
	    "border-top-width", "border-width", "bottom", "box-decoration-break",
	    "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
	    "caption-side", "clear", "clip", "color", "color-profile", "column-count",
	    "column-fill", "column-gap", "column-rule", "column-rule-color",
	    "column-rule-style", "column-rule-width", "column-span", "column-width",
	    "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
	    "cue-after", "cue-before", "cursor", "direction", "display",
	    "dominant-baseline", "drop-initial-after-adjust",
	    "drop-initial-after-align", "drop-initial-before-adjust",
	    "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
	    "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
	    "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
	    "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
	    "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
	    "font-stretch", "font-style", "font-synthesis", "font-variant",
	    "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
	    "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
	    "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
	    "grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap",
	    "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap",
	    "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns",
	    "grid-template-rows", "hanging-punctuation", "height", "hyphens",
	    "icon", "image-orientation", "image-rendering", "image-resolution",
	    "inline-box-align", "justify-content", "left", "letter-spacing",
	    "line-break", "line-height", "line-stacking", "line-stacking-ruby",
	    "line-stacking-shift", "line-stacking-strategy", "list-style",
	    "list-style-image", "list-style-position", "list-style-type", "margin",
	    "margin-bottom", "margin-left", "margin-right", "margin-top",
	    "marks", "marquee-direction", "marquee-loop",
	    "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
	    "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
	    "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
	    "opacity", "order", "orphans", "outline",
	    "outline-color", "outline-offset", "outline-style", "outline-width",
	    "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
	    "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
	    "page", "page-break-after", "page-break-before", "page-break-inside",
	    "page-policy", "pause", "pause-after", "pause-before", "perspective",
	    "perspective-origin", "pitch", "pitch-range", "play-during", "position",
	    "presentation-level", "punctuation-trim", "quotes", "region-break-after",
	    "region-break-before", "region-break-inside", "region-fragment",
	    "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
	    "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
	    "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
	    "shape-outside", "size", "speak", "speak-as", "speak-header",
	    "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
	    "tab-size", "table-layout", "target", "target-name", "target-new",
	    "target-position", "text-align", "text-align-last", "text-decoration",
	    "text-decoration-color", "text-decoration-line", "text-decoration-skip",
	    "text-decoration-style", "text-emphasis", "text-emphasis-color",
	    "text-emphasis-position", "text-emphasis-style", "text-height",
	    "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
	    "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
	    "text-wrap", "top", "transform", "transform-origin", "transform-style",
	    "transition", "transition-delay", "transition-duration",
	    "transition-property", "transition-timing-function", "unicode-bidi",
	    "user-select", "vertical-align", "visibility", "voice-balance", "voice-duration",
	    "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
	    "voice-volume", "volume", "white-space", "widows", "width", "will-change", "word-break",
	    "word-spacing", "word-wrap", "z-index",
	    // SVG-specific
	    "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
	    "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
	    "color-interpolation", "color-interpolation-filters",
	    "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
	    "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
	    "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
	    "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
	    "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
	    "glyph-orientation-vertical", "text-anchor", "writing-mode"
	  ], propertyKeywords = keySet(propertyKeywords_);
	
	  var nonStandardPropertyKeywords_ = [
	    "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
	    "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
	    "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
	    "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
	    "searchfield-results-decoration", "zoom"
	  ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
	
	  var fontProperties_ = [
	    "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
	    "font-stretch", "font-weight", "font-style"
	  ], fontProperties = keySet(fontProperties_);
	
	  var counterDescriptors_ = [
	    "additive-symbols", "fallback", "negative", "pad", "prefix", "range",
	    "speak-as", "suffix", "symbols", "system"
	  ], counterDescriptors = keySet(counterDescriptors_);
	
	  var colorKeywords_ = [
	    "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
	    "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
	    "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
	    "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
	    "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
	    "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
	    "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
	    "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
	    "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
	    "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
	    "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
	    "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
	    "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
	    "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
	    "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
	    "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
	    "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
	    "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
	    "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
	    "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
	    "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
	    "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
	    "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
	    "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
	    "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
	    "whitesmoke", "yellow", "yellowgreen"
	  ], colorKeywords = keySet(colorKeywords_);
	
	  var valueKeywords_ = [
	    "above", "absolute", "activeborder", "additive", "activecaption", "afar",
	    "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
	    "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
	    "arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page",
	    "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
	    "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
	    "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
	    "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
	    "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
	    "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
	    "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
	    "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
	    "compact", "condensed", "contain", "content", "contents",
	    "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
	    "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
	    "decimal-leading-zero", "default", "default-button", "dense", "destination-atop",
	    "destination-in", "destination-out", "destination-over", "devanagari", "difference",
	    "disc", "discard", "disclosure-closed", "disclosure-open", "document",
	    "dot-dash", "dot-dot-dash",
	    "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
	    "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
	    "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
	    "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
	    "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
	    "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
	    "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
	    "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
	    "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
	    "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
	    "forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove",
	    "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
	    "help", "hidden", "hide", "higher", "highlight", "highlighttext",
	    "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore",
	    "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
	    "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
	    "inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert",
	    "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
	    "katakana", "katakana-iroha", "keep-all", "khmer",
	    "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
	    "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
	    "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
	    "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
	    "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
	    "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d",
	    "media-controls-background", "media-current-time-display",
	    "media-fullscreen-button", "media-mute-button", "media-play-button",
	    "media-return-to-realtime-button", "media-rewind-button",
	    "media-seek-back-button", "media-seek-forward-button", "media-slider",
	    "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
	    "media-volume-slider-container", "media-volume-sliderthumb", "medium",
	    "menu", "menulist", "menulist-button", "menulist-text",
	    "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
	    "mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize",
	    "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
	    "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
	    "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote",
	    "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
	    "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
	    "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
	    "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
	    "progress", "push-button", "radial-gradient", "radio", "read-only",
	    "read-write", "read-write-plaintext-only", "rectangle", "region",
	    "relative", "repeat", "repeating-linear-gradient",
	    "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
	    "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
	    "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
	    "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
	    "scroll", "scrollbar", "scroll-position", "se-resize", "searchfield",
	    "searchfield-cancel-button", "searchfield-decoration",
	    "searchfield-results-button", "searchfield-results-decoration",
	    "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
	    "simp-chinese-formal", "simp-chinese-informal", "single",
	    "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
	    "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
	    "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
	    "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
	    "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
	    "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
	    "table-caption", "table-cell", "table-column", "table-column-group",
	    "table-footer-group", "table-header-group", "table-row", "table-row-group",
	    "tamil",
	    "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
	    "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
	    "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
	    "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
	    "trad-chinese-formal", "trad-chinese-informal", "transform",
	    "translate", "translate3d", "translateX", "translateY", "translateZ",
	    "transparent", "ultra-condensed", "ultra-expanded", "underline", "unset", "up",
	    "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
	    "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
	    "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
	    "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
	    "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
	    "xx-large", "xx-small"
	  ], valueKeywords = keySet(valueKeywords_);
	
	  var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
	    .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
	    .concat(valueKeywords_);
	  CodeMirror.registerHelper("hintWords", "css", allWords);
	
	  function tokenCComment(stream, state) {
	    var maybeEnd = false, ch;
	    while ((ch = stream.next()) != null) {
	      if (maybeEnd && ch == "/") {
	        state.tokenize = null;
	        break;
	      }
	      maybeEnd = (ch == "*");
	    }
	    return ["comment", "comment"];
	  }
	
	  CodeMirror.defineMIME("text/css", {
	    documentTypes: documentTypes,
	    mediaTypes: mediaTypes,
	    mediaFeatures: mediaFeatures,
	    mediaValueKeywords: mediaValueKeywords,
	    propertyKeywords: propertyKeywords,
	    nonStandardPropertyKeywords: nonStandardPropertyKeywords,
	    fontProperties: fontProperties,
	    counterDescriptors: counterDescriptors,
	    colorKeywords: colorKeywords,
	    valueKeywords: valueKeywords,
	    tokenHooks: {
	      "/": function(stream, state) {
	        if (!stream.eat("*")) return false;
	        state.tokenize = tokenCComment;
	        return tokenCComment(stream, state);
	      }
	    },
	    name: "css"
	  });
	
	  CodeMirror.defineMIME("text/x-scss", {
	    mediaTypes: mediaTypes,
	    mediaFeatures: mediaFeatures,
	    mediaValueKeywords: mediaValueKeywords,
	    propertyKeywords: propertyKeywords,
	    nonStandardPropertyKeywords: nonStandardPropertyKeywords,
	    colorKeywords: colorKeywords,
	    valueKeywords: valueKeywords,
	    fontProperties: fontProperties,
	    allowNested: true,
	    tokenHooks: {
	      "/": function(stream, state) {
	        if (stream.eat("/")) {
	          stream.skipToEnd();
	          return ["comment", "comment"];
	        } else if (stream.eat("*")) {
	          state.tokenize = tokenCComment;
	          return tokenCComment(stream, state);
	        } else {
	          return ["operator", "operator"];
	        }
	      },
	      ":": function(stream) {
	        if (stream.match(/\s*\{/))
	          return [null, "{"];
	        return false;
	      },
	      "$": function(stream) {
	        stream.match(/^[\w-]+/);
	        if (stream.match(/^\s*:/, false))
	          return ["variable-2", "variable-definition"];
	        return ["variable-2", "variable"];
	      },
	      "#": function(stream) {
	        if (!stream.eat("{")) return false;
	        return [null, "interpolation"];
	      }
	    },
	    name: "css",
	    helperType: "scss"
	  });
	
	  CodeMirror.defineMIME("text/x-less", {
	    mediaTypes: mediaTypes,
	    mediaFeatures: mediaFeatures,
	    mediaValueKeywords: mediaValueKeywords,
	    propertyKeywords: propertyKeywords,
	    nonStandardPropertyKeywords: nonStandardPropertyKeywords,
	    colorKeywords: colorKeywords,
	    valueKeywords: valueKeywords,
	    fontProperties: fontProperties,
	    allowNested: true,
	    tokenHooks: {
	      "/": function(stream, state) {
	        if (stream.eat("/")) {
	          stream.skipToEnd();
	          return ["comment", "comment"];
	        } else if (stream.eat("*")) {
	          state.tokenize = tokenCComment;
	          return tokenCComment(stream, state);
	        } else {
	          return ["operator", "operator"];
	        }
	      },
	      "@": function(stream) {
	        if (stream.eat("{")) return [null, "interpolation"];
	        if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
	        stream.eatWhile(/[\w\\\-]/);
	        if (stream.match(/^\s*:/, false))
	          return ["variable-2", "variable-definition"];
	        return ["variable-2", "variable"];
	      },
	      "&": function() {
	        return ["atom", "atom"];
	      }
	    },
	    name: "css",
	    helperType: "less"
	  });
	
	  CodeMirror.defineMIME("text/x-gss", {
	    documentTypes: documentTypes,
	    mediaTypes: mediaTypes,
	    mediaFeatures: mediaFeatures,
	    propertyKeywords: propertyKeywords,
	    nonStandardPropertyKeywords: nonStandardPropertyKeywords,
	    fontProperties: fontProperties,
	    counterDescriptors: counterDescriptors,
	    colorKeywords: colorKeywords,
	    valueKeywords: valueKeywords,
	    supportsAtComponent: true,
	    tokenHooks: {
	      "/": function(stream, state) {
	        if (!stream.eat("*")) return false;
	        state.tokenize = tokenCComment;
	        return tokenCComment(stream, state);
	      }
	    },
	    name: "css",
	    helperType: "gss"
	  });
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/css/css.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/julia/julia.js **/
jupyter.define('codemirror@5.23.0/mode/julia/julia.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	CodeMirror.defineMode("julia", function(config, parserConf) {
	  function wordRegexp(words, end) {
	    if (typeof end === "undefined") { end = "\\b"; }
	    return new RegExp("^((" + words.join(")|(") + "))" + end);
	  }
	
	  var octChar = "\\\\[0-7]{1,3}";
	  var hexChar = "\\\\x[A-Fa-f0-9]{1,2}";
	  var sChar = "\\\\[abefnrtv0%?'\"\\\\]";
	  var uChar = "([^\\u0027\\u005C\\uD800-\\uDFFF]|[\\uD800-\\uDFFF][\\uDC00-\\uDFFF])";
	
	  var operators = parserConf.operators || wordRegexp([
	      "\\.?[\\\\%*+\\-<>!=\\/^]=?", "\\.?[|&\\u00F7\\u2260\\u2264\\u2265]",
	      "\\u00D7", "\\u2208", "\\u2209", "\\u220B", "\\u220C", "\\u2229",
	      "\\u222A", "\\u2286", "\\u2288", "\\u228A", "\\u22c5", "\\?", "~", ":",
	      "\\$", "\\.[<>]", "<<=?", ">>>?=?", "\\.[<>=]=", "->?", "\\/\\/", "=>",
	      "<:", "\\bin\\b(?!\\()"], "");
	  var delimiters = parserConf.delimiters || /^[;,()[\]{}]/;
	  var identifiers = parserConf.identifiers || /^[_A-Za-z\u00A1-\uFFFF][\w\u00A1-\uFFFF]*!*/;
	
	  var chars = wordRegexp([octChar, hexChar, sChar, uChar], "'");
	  var openers = wordRegexp(["begin", "function", "type", "immutable", "let",
	      "macro", "for", "while", "quote", "if", "else", "elseif", "try",
	      "finally", "catch", "do"]);
	  var closers = wordRegexp(["end", "else", "elseif", "catch", "finally"]);
	  var keywords = wordRegexp(["if", "else", "elseif", "while", "for", "begin",
	      "let", "end", "do", "try", "catch", "finally", "return", "break",
	      "continue", "global", "local", "const", "export", "import", "importall",
	      "using", "function", "macro", "module", "baremodule", "type",
	      "immutable", "quote", "typealias", "abstract", "bitstype"]);
	  var builtins = wordRegexp(["true", "false", "nothing", "NaN", "Inf"]);
	
	  var macro = /^@[_A-Za-z][\w]*/;
	  var symbol = /^:[_A-Za-z\u00A1-\uFFFF][\w\u00A1-\uFFFF]*!*/;
	  var stringPrefixes = /^(`|"{3}|([_A-Za-z\u00A1-\uFFFF]*"))/;
	
	  function inArray(state) {
	    return inGenerator(state, '[')
	  }
	
	  function inGenerator(state, bracket) {
	    var curr = currentScope(state),
	        prev = currentScope(state, 1);
	    if (typeof(bracket) === "undefined") { bracket = '('; }
	    if (curr === bracket || (prev === bracket && curr === "for")) {
	      return true;
	    }
	    return false;
	  }
	
	  function currentScope(state, n) {
	    if (typeof(n) === "undefined") { n = 0; }
	    if (state.scopes.length <= n) {
	      return null;
	    }
	    return state.scopes[state.scopes.length - (n + 1)];
	  }
	
	  // tokenizers
	  function tokenBase(stream, state) {
	    // Handle multiline comments
	    if (stream.match(/^#=/, false)) {
	      state.tokenize = tokenComment;
	      return state.tokenize(stream, state);
	    }
	
	    // Handle scope changes
	    var leavingExpr = state.leavingExpr;
	    if (stream.sol()) {
	      leavingExpr = false;
	    }
	    state.leavingExpr = false;
	
	    if (leavingExpr) {
	      if (stream.match(/^'+/)) {
	        return "operator";
	      }
	    }
	
	    if (stream.match(/^\.{2,3}/)) {
	      return "operator";
	    }
	
	    if (stream.eatSpace()) {
	      return null;
	    }
	
	    var ch = stream.peek();
	
	    // Handle single line comments
	    if (ch === '#') {
	      stream.skipToEnd();
	      return "comment";
	    }
	
	    if (ch === '[') {
	      state.scopes.push('[');
	    }
	
	    if (ch === '(') {
	      state.scopes.push('(');
	    }
	
	    var scope = currentScope(state);
	
	    if (inArray(state) && ch === ']') {
	      if (scope === "for") { state.scopes.pop(); }
	      state.scopes.pop();
	      state.leavingExpr = true;
	    }
	
	    if (inGenerator(state) && ch === ')') {
	      if (scope === "for") { state.scopes.pop(); }
	      state.scopes.pop();
	      state.leavingExpr = true;
	    }
	
	    var match;
	    if (match = stream.match(openers, false)) {
	      state.scopes.push(match[0]);
	    }
	
	    if (stream.match(closers, false)) {
	      state.scopes.pop();
	    }
	
	    if (inArray(state)) {
	      if (state.lastToken == "end" && stream.match(/^:/)) {
	        return "operator";
	      }
	      if (stream.match(/^end/)) {
	        return "number";
	      }
	    }
	
	    // Handle type annotations
	    if (stream.match(/^::(?![:\$])/)) {
	      state.tokenize = tokenAnnotation;
	      return state.tokenize(stream, state);
	    }
	
	    // Handle symbols
	    if (!leavingExpr && stream.match(symbol) || stream.match(/:\./)) {
	      return "builtin";
	    }
	
	    // Handle parametric types
	    if (stream.match(/^{[^}]*}(?=\()/)) {
	      return "builtin";
	    }
	
	    // Handle operators and Delimiters
	    if (stream.match(operators)) {
	      return "operator";
	    }
	
	    // Handle Number Literals
	    if (stream.match(/^[0-9\.]/, false)) {
	      var imMatcher = RegExp(/^im\b/);
	      var numberLiteral = false;
	      // Floats
	      if (stream.match(/^\d*\.(?!\.)\d*([Eef][\+\-]?\d+)?/i)) { numberLiteral = true; }
	      if (stream.match(/^\d+\.(?!\.)\d*/)) { numberLiteral = true; }
	      if (stream.match(/^\.\d+/)) { numberLiteral = true; }
	      if (stream.match(/^0x\.[0-9a-f]+p[\+\-]?\d+/i)) { numberLiteral = true; }
	      // Integers
	      if (stream.match(/^0x[0-9a-f]+/i)) { numberLiteral = true; } // Hex
	      if (stream.match(/^0b[01]+/i)) { numberLiteral = true; } // Binary
	      if (stream.match(/^0o[0-7]+/i)) { numberLiteral = true; } // Octal
	      if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) { numberLiteral = true; } // Decimal
	      // Zero by itself with no other piece of number.
	      if (stream.match(/^0(?![\dx])/i)) { numberLiteral = true; }
	      if (numberLiteral) {
	          // Integer literals may be "long"
	          stream.match(imMatcher);
	          state.leavingExpr = true;
	          return "number";
	      }
	    }
	
	    // Handle Chars
	    if (stream.match(/^'/)) {
	      state.tokenize = tokenChar;
	      return state.tokenize(stream, state);
	    }
	
	    // Handle Strings
	    if (stream.match(stringPrefixes)) {
	      state.tokenize = tokenStringFactory(stream.current());
	      return state.tokenize(stream, state);
	    }
	
	    if (stream.match(macro)) {
	      return "meta";
	    }
	
	    if (stream.match(delimiters)) {
	      return null;
	    }
	
	    if (stream.match(keywords)) {
	      return "keyword";
	    }
	
	    if (stream.match(builtins)) {
	      return "builtin";
	    }
	
	    var isDefinition = state.isDefinition || state.lastToken == "function" ||
	                       state.lastToken == "macro" || state.lastToken == "type" ||
	                       state.lastToken == "immutable";
	
	    if (stream.match(identifiers)) {
	      if (isDefinition) {
	        if (stream.peek() === '.') {
	          state.isDefinition = true;
	          return "variable";
	        }
	        state.isDefinition = false;
	        return "def";
	      }
	      if (stream.match(/^({[^}]*})*\(/, false)) {
	        return callOrDef(stream, state);
	      }
	      state.leavingExpr = true;
	      return "variable";
	    }
	
	    // Handle non-detected items
	    stream.next();
	    return "error";
	  }
	
	  function callOrDef(stream, state) {
	    var match = stream.match(/^(\(\s*)/);
	    if (match) {
	      if (state.firstParenPos < 0)
	        state.firstParenPos = state.scopes.length;
	      state.scopes.push('(');
	      state.charsAdvanced += match[1].length;
	    }
	    if (currentScope(state) == '(' && stream.match(/^\)/)) {
	      state.scopes.pop();
	      state.charsAdvanced += 1;
	      if (state.scopes.length <= state.firstParenPos) {
	        var isDefinition = stream.match(/^\s*?=(?!=)/, false);
	        stream.backUp(state.charsAdvanced);
	        state.firstParenPos = -1;
	        state.charsAdvanced = 0;
	        if (isDefinition)
	          return "def";
	        return "builtin";
	      }
	    }
	    // Unfortunately javascript does not support multiline strings, so we have
	    // to undo anything done upto here if a function call or definition splits
	    // over two or more lines.
	    if (stream.match(/^$/g, false)) {
	      stream.backUp(state.charsAdvanced);
	      while (state.scopes.length > state.firstParenPos)
	        state.scopes.pop();
	      state.firstParenPos = -1;
	      state.charsAdvanced = 0;
	      return "builtin";
	    }
	    state.charsAdvanced += stream.match(/^([^()]*)/)[1].length;
	    return callOrDef(stream, state);
	  }
	
	  function tokenAnnotation(stream, state) {
	    stream.match(/.*?(?=,|;|{|}|\(|\)|=|$|\s)/);
	    if (stream.match(/^{/)) {
	      state.nestedLevels++;
	    } else if (stream.match(/^}/)) {
	      state.nestedLevels--;
	    }
	    if (state.nestedLevels > 0) {
	      stream.match(/.*?(?={|})/);
	    } else if (state.nestedLevels == 0) {
	      state.tokenize = tokenBase;
	    }
	    return "builtin";
	  }
	
	  function tokenComment(stream, state) {
	    if (stream.match(/^#=/)) {
	      state.nestedLevels++;
	    }
	    if (!stream.match(/.*?(?=(#=|=#))/)) {
	      stream.skipToEnd();
	    }
	    if (stream.match(/^=#/)) {
	      state.nestedLevels--;
	      if (state.nestedLevels == 0)
	        state.tokenize = tokenBase;
	    }
	    return "comment";
	  }
	
	  function tokenChar(stream, state) {
	    var isChar = false, match;
	    if (stream.match(chars)) {
	      isChar = true;
	    } else if (match = stream.match(/\\u([a-f0-9]{1,4})(?=')/i)) {
	      var value = parseInt(match[1], 16);
	      if (value <= 55295 || value >= 57344) { // (U+0,U+D7FF), (U+E000,U+FFFF)
	        isChar = true;
	        stream.next();
	      }
	    } else if (match = stream.match(/\\U([A-Fa-f0-9]{5,8})(?=')/)) {
	      var value = parseInt(match[1], 16);
	      if (value <= 1114111) { // U+10FFFF
	        isChar = true;
	        stream.next();
	      }
	    }
	    if (isChar) {
	      state.leavingExpr = true;
	      state.tokenize = tokenBase;
	      return "string";
	    }
	    if (!stream.match(/^[^']+(?=')/)) { stream.skipToEnd(); }
	    if (stream.match(/^'/)) { state.tokenize = tokenBase; }
	    return "error";
	  }
	
	  function tokenStringFactory(delimiter) {
	    delimiter = (delimiter === '`' || delimiter === '"""') ? delimiter : '"';
	    function tokenString(stream, state) {
	      if (stream.eat('\\')) {
	        stream.next();
	      } else if (stream.match(delimiter)) {
	        state.tokenize = tokenBase;
	        state.leavingExpr = true;
	        return "string";
	      } else {
	        stream.eat(/[`"]/);
	      }
	      stream.eatWhile(/[^\\`"]/);
	      return "string";
	    }
	    return tokenString;
	  }
	
	  var external = {
	    startState: function() {
	      return {
	        tokenize: tokenBase,
	        scopes: [],
	        lastToken: null,
	        leavingExpr: false,
	        isDefinition: false,
	        nestedLevels: 0,
	        charsAdvanced: 0,
	        firstParenPos: -1
	      };
	    },
	
	    token: function(stream, state) {
	      var style = state.tokenize(stream, state);
	      var current = stream.current();
	
	      if (current && style) {
	        state.lastToken = current;
	      }
	
	      // Handle '.' connected identifiers
	      if (current === '.') {
	        style = stream.match(identifiers, false) || stream.match(macro, false) ||
	                stream.match(/\(/, false) ? "operator" : "error";
	      }
	      return style;
	    },
	
	    indent: function(state, textAfter) {
	      var delta = 0;
	      if ( textAfter === ']' || textAfter === ')' || textAfter === "end" ||
	           textAfter === "else" || textAfter === "catch" ||
	           textAfter === "finally" ) {
	        delta = -1;
	      }
	      return (state.scopes.length + delta) * config.indentUnit;
	    },
	
	    electricInput: /\b(end|else|catch|finally)\b/,
	    blockCommentStart: "#=",
	    blockCommentEnd: "=#",
	    lineComment: "#",
	    fold: "indent"
	  };
	  return external;
	});
	
	
	CodeMirror.defineMIME("text/x-julia", "julia");
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/julia/julia.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/mode/r/r.js **/
jupyter.define('codemirror@5.23.0/mode/r/r.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	CodeMirror.registerHelper("wordChars", "r", /[\w.]/);
	
	CodeMirror.defineMode("r", function(config) {
	  function wordObj(str) {
	    var words = str.split(" "), res = {};
	    for (var i = 0; i < words.length; ++i) res[words[i]] = true;
	    return res;
	  }
	  var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_");
	  var builtins = wordObj("list quote bquote eval return call parse deparse");
	  var keywords = wordObj("if else repeat while function for in next break");
	  var blockkeywords = wordObj("if else repeat while function for");
	  var opChars = /[+\-*\/^<>=!&|~$:]/;
	  var curPunc;
	
	  function tokenBase(stream, state) {
	    curPunc = null;
	    var ch = stream.next();
	    if (ch == "#") {
	      stream.skipToEnd();
	      return "comment";
	    } else if (ch == "0" && stream.eat("x")) {
	      stream.eatWhile(/[\da-f]/i);
	      return "number";
	    } else if (ch == "." && stream.eat(/\d/)) {
	      stream.match(/\d*(?:e[+\-]?\d+)?/);
	      return "number";
	    } else if (/\d/.test(ch)) {
	      stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/);
	      return "number";
	    } else if (ch == "'" || ch == '"') {
	      state.tokenize = tokenString(ch);
	      return "string";
	    } else if (ch == "`") {
	      stream.match(/[^`]+`/);
	      return "variable-3";
	    } else if (ch == "." && stream.match(/.[.\d]+/)) {
	      return "keyword";
	    } else if (/[\w\.]/.test(ch) && ch != "_") {
	      stream.eatWhile(/[\w\.]/);
	      var word = stream.current();
	      if (atoms.propertyIsEnumerable(word)) return "atom";
	      if (keywords.propertyIsEnumerable(word)) {
	        // Block keywords start new blocks, except 'else if', which only starts
	        // one new block for the 'if', no block for the 'else'.
	        if (blockkeywords.propertyIsEnumerable(word) &&
	            !stream.match(/\s*if(\s+|$)/, false))
	          curPunc = "block";
	        return "keyword";
	      }
	      if (builtins.propertyIsEnumerable(word)) return "builtin";
	      return "variable";
	    } else if (ch == "%") {
	      if (stream.skipTo("%")) stream.next();
	      return "operator variable-2";
	    } else if (
	        (ch == "<" && stream.eat("-")) ||
	        (ch == "<" && stream.match("<-")) ||
	        (ch == "-" && stream.match(/>>?/))
	      ) {
	      return "operator arrow";
	    } else if (ch == "=" && state.ctx.argList) {
	      return "arg-is";
	    } else if (opChars.test(ch)) {
	      if (ch == "$") return "operator dollar";
	      stream.eatWhile(opChars);
	      return "operator";
	    } else if (/[\(\){}\[\];]/.test(ch)) {
	      curPunc = ch;
	      if (ch == ";") return "semi";
	      return null;
	    } else {
	      return null;
	    }
	  }
	
	  function tokenString(quote) {
	    return function(stream, state) {
	      if (stream.eat("\\")) {
	        var ch = stream.next();
	        if (ch == "x") stream.match(/^[a-f0-9]{2}/i);
	        else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next();
	        else if (ch == "u") stream.match(/^[a-f0-9]{4}/i);
	        else if (ch == "U") stream.match(/^[a-f0-9]{8}/i);
	        else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/);
	        return "string-2";
	      } else {
	        var next;
	        while ((next = stream.next()) != null) {
	          if (next == quote) { state.tokenize = tokenBase; break; }
	          if (next == "\\") { stream.backUp(1); break; }
	        }
	        return "string";
	      }
	    };
	  }
	
	  function push(state, type, stream) {
	    state.ctx = {type: type,
	                 indent: state.indent,
	                 align: null,
	                 column: stream.column(),
	                 prev: state.ctx};
	  }
	  function pop(state) {
	    state.indent = state.ctx.indent;
	    state.ctx = state.ctx.prev;
	  }
	
	  return {
	    startState: function() {
	      return {tokenize: tokenBase,
	              ctx: {type: "top",
	                    indent: -config.indentUnit,
	                    align: false},
	              indent: 0,
	              afterIdent: false};
	    },
	
	    token: function(stream, state) {
	      if (stream.sol()) {
	        if (state.ctx.align == null) state.ctx.align = false;
	        state.indent = stream.indentation();
	      }
	      if (stream.eatSpace()) return null;
	      var style = state.tokenize(stream, state);
	      if (style != "comment" && state.ctx.align == null) state.ctx.align = true;
	
	      var ctype = state.ctx.type;
	      if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && ctype == "block") pop(state);
	      if (curPunc == "{") push(state, "}", stream);
	      else if (curPunc == "(") {
	        push(state, ")", stream);
	        if (state.afterIdent) state.ctx.argList = true;
	      }
	      else if (curPunc == "[") push(state, "]", stream);
	      else if (curPunc == "block") push(state, "block", stream);
	      else if (curPunc == ctype) pop(state);
	      state.afterIdent = style == "variable" || style == "keyword";
	      return style;
	    },
	
	    indent: function(state, textAfter) {
	      if (state.tokenize != tokenBase) return 0;
	      var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx,
	          closing = firstChar == ctx.type;
	      if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit);
	      else if (ctx.align) return ctx.column + (closing ? 0 : 1);
	      else return ctx.indent + (closing ? 0 : config.indentUnit);
	    },
	
	    lineComment: "#"
	  };
	});
	
	CodeMirror.defineMIME("text/x-rsrc", "r");
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/mode/r/r.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/commandlinker/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/commandlinker/plugin.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) Jupyter Development Team.
	| Distributed under the terms of the Modified BSD License.
	|----------------------------------------------------------------------------*/
	"use strict";
	var commandlinker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandlinker/commandlinker.js');
	/**
	 * The default commmand linker provider.
	 */
	var plugin = {
	    id: 'jupyter.services.command-linker',
	    provides: commandlinker_1.ICommandLinker,
	    activate: function (app) { return new commandlinker_1.CommandLinker({ commands: app.commands }); },
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/commandlinker/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/commandlinker/commandlinker.js **/
jupyter.define('jupyterlab@0.15.1/lib/commandlinker/commandlinker.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) Jupyter Development Team.
	| Distributed under the terms of the Modified BSD License.
	|----------------------------------------------------------------------------*/
	"use strict";
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	/**
	 * The command data attribute added to nodes that are connected.
	 */
	var COMMAND_ATTR = 'commandlinker-command';
	/**
	 * The args data attribute added to nodes that are connected.
	 */
	var ARGS_ATTR = 'commandlinker-args';
	/* tslint:disable */
	/**
	 * The command linker token.
	 */
	exports.ICommandLinker = new token_1.Token('jupyter.services.command-linker');
	/**
	 * A static class that provides helper methods to generate clickable nodes that
	 * execute registered commands with pre-populated arguments.
	 */
	var CommandLinker = (function () {
	    /**
	     * Instantiate a new command linker.
	     */
	    function CommandLinker(options) {
	        this._commands = null;
	        this._commands = options.commands;
	        document.body.addEventListener('click', this);
	    }
	    Object.defineProperty(CommandLinker.prototype, "isDisposed", {
	        /**
	         * Test whether the linker is disposed.
	         */
	        get: function () {
	            return this._commands === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the linker.
	     */
	    CommandLinker.prototype.dispose = function () {
	        if (this._commands === null) {
	            return;
	        }
	        this._commands = null;
	        document.body.removeEventListener('click', this);
	    };
	    /**
	     * Connect a command/argument pair to a given node so that when it is clicked,
	     * the command will execute.
	     *
	     * @param node - The node being connected.
	     *
	     * @param command - The command ID to execute upon click.
	     *
	     * @param args - The arguments with which to invoke the command.
	     *
	     * @returns The same node that was passed in, after it has been connected.
	     *
	     * #### Notes
	     * Only `click` events will execute the command on a connected node. So, there
	     * are two considerations that are relevant:
	     * 1. If a node is connected, the default click action will be prevented.
	     * 2. The `HTMLElement` passed in should be clickable.
	     */
	    CommandLinker.prototype.connectNode = function (node, command, args) {
	        var argsValue = JSON.stringify(args);
	        node.setAttribute("data-" + COMMAND_ATTR, command);
	        if (argsValue) {
	            node.setAttribute("data-" + ARGS_ATTR, argsValue);
	        }
	        return node;
	    };
	    /**
	     * Disconnect a node that has been connected to execute a command on click.
	     *
	     * @param node - The node being disconnected.
	     *
	     * @returns The same node that was passed in, after it has been disconnected.
	     *
	     * #### Notes
	     * This method is safe to call multiple times and is safe to call on nodes
	     * that were never connected.
	     *
	     * This method can be called on rendered virtual DOM nodes that were populated
	     * using the `populateVNodeAttributes` method in order to disconnect them from
	     * executing their command/argument pair.
	     */
	    CommandLinker.prototype.disconnectNode = function (node) {
	        node.removeAttribute("data-" + COMMAND_ATTR);
	        node.removeAttribute("data-" + ARGS_ATTR);
	        return node;
	    };
	    /**
	     * Handle the DOM events for the command linker helper class.
	     *
	     * @param event - The DOM event sent to the class.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the panel's DOM node. It should
	     * not be called directly by user code.
	     */
	    CommandLinker.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'click':
	                this._evtClick(event);
	                break;
	            default:
	                return;
	        }
	    };
	    /**
	     * Populate the attributes used to instantiate a virtual DOM node with the
	     * data set values necessary for its rendered DOM node to respond to clicks by
	     * executing a command/argument pair
	     *
	     * @param attrs - The attributes that will eventually be used to instantiate
	     * a virtual DOM node.
	     *
	     * @param command - The command ID to execute upon click.
	     *
	     * @param args - The arguments with which to invoke the command.
	     *
	     * @returns The same attributes that were passed in.
	     *
	     * #### Notes
	     * The attributes instance that is returned is identical to the attributes
	     * instance that was passed in, i.e., this method mutates the original.
	     */
	    CommandLinker.prototype.populateVNodeAttrs = function (attrs, command, args) {
	        var argsValue = JSON.stringify(args);
	        attrs.dataset = attrs.dataset || {};
	        attrs.dataset[COMMAND_ATTR] = command;
	        if (argsValue) {
	            attrs.dataset[ARGS_ATTR] = argsValue;
	        }
	        return attrs;
	    };
	    /**
	     * The global click handler that deploys commands/argument pairs that are
	     * attached to the node being clicked.
	     */
	    CommandLinker.prototype._evtClick = function (event) {
	        var target = event.target;
	        while (target && target.parentElement) {
	            if (target.hasAttribute("data-" + COMMAND_ATTR)) {
	                event.preventDefault();
	                var command = target.getAttribute("data-" + COMMAND_ATTR);
	                var argsValue = target.getAttribute("data-" + ARGS_ATTR);
	                var args = void 0;
	                if (argsValue) {
	                    args = JSON.parse(argsValue);
	                }
	                this._commands.execute(command, args);
	                return;
	            }
	            target = target.parentElement;
	        }
	    };
	    return CommandLinker;
	}());
	exports.CommandLinker = CommandLinker;
	//# sourceMappingURL=commandlinker.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/commandlinker/commandlinker.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/commandpalette/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/commandpalette/plugin.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) Jupyter Development Team.
	| Distributed under the terms of the Modified BSD License.
	|----------------------------------------------------------------------------*/
	"use strict";
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var commandpalette_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/commandpalette.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	/**
	 * A thin wrapper around the `CommandPalette` class to conform with the
	 * JupyterLab interface for the application-wide command palette.
	 */
	var Palette = (function () {
	    /**
	     * Create a palette instance.
	     */
	    function Palette(palette) {
	        this._palette = null;
	        this._palette = palette;
	    }
	    Object.defineProperty(Palette.prototype, "placeholder", {
	        get: function () {
	            return this._palette.inputNode.placeholder;
	        },
	        /**
	         * The placeholder text of the command palette's search input.
	         */
	        set: function (placeholder) {
	            this._palette.inputNode.placeholder = placeholder;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Activate the command palette for user input.
	     */
	    Palette.prototype.activate = function () {
	        this._palette.activate();
	    };
	    /**
	     * Add a command item to the command palette.
	     *
	     * @param options - The options for creating the command item.
	     *
	     * @returns A disposable that will remove the item from the palette.
	     */
	    Palette.prototype.addItem = function (options) {
	        var _this = this;
	        var item = this._palette.addItem(options);
	        return new disposable_1.DisposableDelegate(function () { return _this._palette.removeItem(item); });
	    };
	    return Palette;
	}());
	/**
	 * The default commmand palette extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.services.commandpalette',
	    provides: _1.ICommandPalette,
	    requires: [instancerestorer_1.IInstanceRestorer],
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the command palette.
	 */
	function activate(app, restorer) {
	    var commands = app.commands, keymap = app.keymap;
	    var palette = new commandpalette_1.CommandPalette({ commands: commands, keymap: keymap });
	    // Let the application restorer track the command palette for restoration of
	    // application state (e.g. setting the command palette as the current side bar
	    // widget).
	    restorer.add(palette, 'command-palette');
	    palette.id = 'command-palette';
	    palette.title.label = 'Commands';
	    app.commands.addCommand(_1.CommandIDs.activate, {
	        execute: function () { app.shell.activateLeft(palette.id); },
	        label: 'Activate Command Palette'
	    });
	    app.commands.addCommand(_1.CommandIDs.hide, {
	        execute: function () {
	            if (!palette.isHidden) {
	                app.shell.collapseLeft();
	            }
	        },
	        label: 'Hide Command Palette'
	    });
	    app.commands.addCommand(_1.CommandIDs.toggle, {
	        execute: function () {
	            if (palette.isHidden) {
	                return app.commands.execute(_1.CommandIDs.activate, void 0);
	            }
	            return app.commands.execute(_1.CommandIDs.hide, void 0);
	        },
	        label: 'Toggle Command Palette'
	    });
	    palette.inputNode.placeholder = 'SEARCH';
	    app.shell.addToLeftArea(palette);
	    return new Palette(palette);
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/commandpalette/plugin.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/commandpalette.js **/
jupyter.define('phosphor@0.7.0/lib/ui/commandpalette.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var searching_1 = __jupyter_require__('phosphor@0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@0.7.0/lib/collections/vector.js');
	var query_1 = __jupyter_require__('phosphor@0.7.0/lib/dom/query.js');
	var keymap_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/keymap.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to `CommandPalette` instances.
	 */
	var PALETTE_CLASS = 'p-CommandPalette';
	/**
	 * The class name added to the search section of the palette.
	 */
	var SEARCH_CLASS = 'p-CommandPalette-search';
	/**
	 * The class name added to the input wrapper in the search section.
	 */
	var WRAPPER_CLASS = 'p-CommandPalette-wrapper';
	/**
	 * The class name added to the input node in the search section.
	 */
	var INPUT_CLASS = 'p-CommandPalette-input';
	/**
	 * The class name added to the content section of the palette.
	 */
	var CONTENT_CLASS = 'p-CommandPalette-content';
	/**
	 * The class name added to a palette section header.
	 */
	var HEADER_CLASS = 'p-CommandPalette-header';
	/**
	 * The class name added to a palette item node.
	 */
	var ITEM_CLASS = 'p-CommandPalette-item';
	/**
	 * The class name added to a item label node.
	 */
	var LABEL_CLASS = 'p-CommandPalette-itemLabel';
	/**
	 * The class name added to a item shortcut node.
	 */
	var SHORTCUT_CLASS = 'p-CommandPalette-itemShortcut';
	/**
	 * The class name added to a item caption node.
	 */
	var CAPTION_CLASS = 'p-CommandPalette-itemCaption';
	/**
	 * The class name added to the active palette header or item.
	 */
	var ACTIVE_CLASS = 'p-mod-active';
	/**
	 * The class name added to a disabled command item.
	 */
	var DISABLED_CLASS = 'p-mod-disabled';
	/**
	 * The class name added to a toggled command item.
	 */
	var TOGGLED_CLASS = 'p-mod-toggled';
	/**
	 * A widget which displays command items as a searchable palette.
	 */
	var CommandPalette = (function (_super) {
	    __extends(CommandPalette, _super);
	    /**
	     * Construct a new command palette.
	     *
	     * @param options - The options for initializing the palette.
	     */
	    function CommandPalette(options) {
	        _super.call(this, { node: Private.createNode() });
	        this._activeIndex = 1;
	        this._itemNodes = new vector_1.Vector();
	        this._headerNodes = new vector_1.Vector();
	        this._items = new vector_1.Vector();
	        this._result = null;
	        this.addClass(PALETTE_CLASS);
	        this.setFlag(widget_1.WidgetFlag.DisallowLayout);
	        this._keymap = options.keymap;
	        this._commands = options.commands;
	        this._renderer = options.renderer || CommandPalette.defaultRenderer;
	        this._commands.commandChanged.connect(this._onGenericChange, this);
	        this._keymap.bindingChanged.connect(this._onGenericChange, this);
	    }
	    /**
	     * Dispose of the resources held by the command palette.
	     */
	    CommandPalette.prototype.dispose = function () {
	        this._items.clear();
	        this._itemNodes.clear();
	        this._headerNodes.clear();
	        this._result = null;
	        this._keymap = null;
	        this._commands = null;
	        this._renderer = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(CommandPalette.prototype, "searchNode", {
	        /**
	         * Get the command palette search node.
	         *
	         * #### Notes
	         * This is the node which contains the search-related elements.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.node.getElementsByClassName(SEARCH_CLASS)[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommandPalette.prototype, "inputNode", {
	        /**
	         * Get the command palette input node.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.node.getElementsByClassName(INPUT_CLASS)[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommandPalette.prototype, "contentNode", {
	        /**
	         * Get the command palette content node.
	         *
	         * #### Notes
	         * This is the node which holds the command item nodes.
	         *
	         * Modifying this node directly can lead to undefined behavior.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this.node.getElementsByClassName(CONTENT_CLASS)[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommandPalette.prototype, "items", {
	        /**
	         * A read-only sequence of the command items in the palette.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._items;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommandPalette.prototype, "commands", {
	        /**
	         * The command registry used by the command palette.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._commands;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommandPalette.prototype, "keymap", {
	        /**
	         * The keymap used by the command palette.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._keymap;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CommandPalette.prototype, "renderer", {
	        /**
	         * The renderer used by the command palette.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a command item to the command palette.
	     *
	     * @param options - The options for creating the command item.
	     *
	     * @returns The command item added to the palette.
	     */
	    CommandPalette.prototype.addItem = function (options) {
	        // Create a new command item for the options.
	        var item = Private.createItem(this._commands, this._keymap, options);
	        // Add the item to the vector.
	        this._items.pushBack(item);
	        // Schedule an update of the content.
	        if (this.isAttached)
	            this.update();
	        // Return the item added to the palette.
	        return item;
	    };
	    /**
	     * Remove an item from the command palette.
	     *
	     * @param item - The item to remove from the palette.
	     *
	     * @returns The index occupied by the item, or `-1` if the item
	     *   was not contained in the menu.
	     */
	    CommandPalette.prototype.removeItem = function (item) {
	        var index = searching_1.indexOf(this._items, item);
	        if (index !== -1)
	            this.removeItemAt(index);
	        return index;
	    };
	    /**
	     * Remove the item at a given index from the command palette.
	     *
	     * @param index - The index of the item to remove.
	     *
	     * @returns The item occupying the index, or `null` if the index
	     *   is out of range.
	     */
	    CommandPalette.prototype.removeItemAt = function (index) {
	        // Bail if the index is out of range.
	        var i = Math.floor(index);
	        if (i < 0 || i >= this._items.length) {
	            return null;
	        }
	        // Remove the item from the vector.
	        var item = this._items.removeAt(index);
	        // Schedule an update of the content.
	        if (this.isAttached)
	            this.update();
	        // Return the removed item.
	        return item;
	    };
	    /**
	     * Remove all command items from the command palette.
	     */
	    CommandPalette.prototype.clearItems = function () {
	        // Clear the vector of items.
	        this._items.clear();
	        // Schedule an update of the content.
	        if (this.isAttached)
	            this.update();
	    };
	    /**
	     * Handle the DOM events for the command palette.
	     *
	     * @param event - The DOM event sent to the command palette.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the command palette's DOM node.
	     * It should not be called directly by user code.
	     */
	    CommandPalette.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'click':
	                this._evtClick(event);
	                break;
	            case 'keydown':
	                this._evtKeyDown(event);
	                break;
	            case 'input':
	                this.update();
	                break;
	        }
	    };
	    /**
	     * A message handler invoked on a `'after-attach'` message.
	     */
	    CommandPalette.prototype.onAfterAttach = function (msg) {
	        this.node.addEventListener('click', this);
	        this.node.addEventListener('keydown', this);
	        this.node.addEventListener('input', this);
	        this.update();
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    CommandPalette.prototype.onBeforeDetach = function (msg) {
	        this.node.removeEventListener('click', this);
	        this.node.removeEventListener('keydown', this);
	        this.node.removeEventListener('input', this);
	    };
	    /**
	     * A message handler invoked on an `'activate-request'` message.
	     */
	    CommandPalette.prototype.onActivateRequest = function (msg) {
	        if (this.isAttached) {
	            var input = this.inputNode;
	            input.focus();
	            input.select();
	        }
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    CommandPalette.prototype.onUpdateRequest = function (msg) {
	        var _this = this;
	        // Clear the current content.
	        this.contentNode.textContent = '';
	        // Reset the active index and search result.
	        this._activeIndex = -1;
	        this._result = null;
	        // Bail early if there are no command items.
	        if (this._items.isEmpty) {
	            return;
	        }
	        // Split the query text into its category and text parts.
	        var _a = CommandPalette.splitQuery(this.inputNode.value), category = _a.category, text = _a.text;
	        // Search the command items for query matches.
	        var result = this._result = Private.search(this._items, category, text);
	        // If the result is empty, there is nothing left to do.
	        if (result.parts.length === 0) {
	            return;
	        }
	        // Fetch command variables.
	        var renderer = this._renderer;
	        var itemNodes = this._itemNodes;
	        var headerNodes = this._headerNodes;
	        // Ensure there are enough header nodes.
	        while (headerNodes.length < result.headerCount) {
	            headerNodes.pushBack(renderer.createHeaderNode());
	        }
	        // Ensure there are enough item nodes.
	        while (itemNodes.length < result.itemCount) {
	            itemNodes.pushBack(renderer.createItemNode());
	        }
	        // Setup the index counters and document fragment.
	        var itemIndex = 0;
	        var headerIndex = 0;
	        var fragment = document.createDocumentFragment();
	        // Render the search result into the fragment.
	        for (var _i = 0, _b = result.parts; _i < _b.length; _i++) {
	            var part = _b[_i];
	            var node = void 0;
	            if (part.item === null) {
	                node = headerNodes.at(headerIndex++);
	                renderer.updateHeaderNode(node, part.markup);
	            }
	            else {
	                node = itemNodes.at(itemIndex++);
	                renderer.updateItemNode(node, part.item, part.markup);
	            }
	            fragment.appendChild(node);
	        }
	        // Add the fragment to the content node.
	        this.contentNode.appendChild(fragment);
	        // If there is query text, activate the first command item.
	        // Otherwise, reset the content scroll position to the top.
	        if (category || text) {
	            this._activateNext('item');
	        }
	        else {
	            requestAnimationFrame(function () { _this.contentNode.scrollTop = 0; });
	        }
	    };
	    /**
	     * Handle the `'click'` event for the command palette.
	     */
	    CommandPalette.prototype._evtClick = function (event) {
	        // Bail if the click is not the left button.
	        if (event.button !== 0) {
	            return;
	        }
	        // Bail if the click was not on a content item.
	        var target = event.target;
	        var children = this.contentNode.children;
	        var i = searching_1.findIndex(children, function (child) { return child.contains(target); });
	        if (i === -1) {
	            return;
	        }
	        // Kill the event when a content item is clicked.
	        event.preventDefault();
	        event.stopPropagation();
	        // Bail if there is no search result.
	        if (!this._result) {
	            return;
	        }
	        // Bail if the index is out of range.
	        var part = this._result.parts[i];
	        if (!part) {
	            return;
	        }
	        // Bail if the part has a disabled item.
	        if (part.item && !part.item.isEnabled) {
	            return;
	        }
	        // Activate the index and trigger the part.
	        this._activate(i);
	        this._triggerActive();
	    };
	    /**
	     * Handle the `'keydown'` event for the command palette.
	     */
	    CommandPalette.prototype._evtKeyDown = function (event) {
	        if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
	            return;
	        }
	        switch (event.keyCode) {
	            case 13:
	                event.preventDefault();
	                event.stopPropagation();
	                this._triggerActive();
	                break;
	            case 38:
	                event.preventDefault();
	                event.stopPropagation();
	                this._activatePrev('any');
	                break;
	            case 40:
	                event.preventDefault();
	                event.stopPropagation();
	                this._activateNext('any');
	                break;
	        }
	    };
	    /**
	     * Activate the node at the given render index.
	     *
	     * If the node is scrolled out of view, it will be scrolled into
	     * view and aligned according to the `alignTop` parameter.
	     */
	    CommandPalette.prototype._activate = function (index) {
	        // Fetch common variables.
	        var content = this.contentNode;
	        var children = content.children;
	        // Ensure the index is valid.
	        if (index < 0 || index >= children.length) {
	            index = -1;
	        }
	        // Bail if there is no effective change.
	        if (this._activeIndex === index) {
	            return;
	        }
	        // Look up the relevant nodes.
	        var oldNode = children[this._activeIndex];
	        var newNode = children[index];
	        // Update the internal active index.
	        this._activeIndex = index;
	        // Deactivate the old node.
	        if (oldNode) {
	            oldNode.classList.remove(ACTIVE_CLASS);
	        }
	        // Activate the new node and scroll it into view.
	        if (newNode) {
	            newNode.classList.add(ACTIVE_CLASS);
	            requestAnimationFrame(function () {
	                query_1.scrollIntoViewIfNeeded(content, newNode);
	            });
	        }
	    };
	    /**
	     * Activate the next enabled index of the given kind.
	     */
	    CommandPalette.prototype._activateNext = function (kind) {
	        // Bail if there are no current search results.
	        if (!this._result) {
	            return;
	        }
	        // Bail if the search results are empty.
	        var parts = this._result.parts;
	        if (parts.length === 0) {
	            return;
	        }
	        // Activate the next enabled index of the specified kind.
	        var start = this._activeIndex + 1;
	        for (var i = 0, n = parts.length; i < n; ++i) {
	            var k = (start + i) % n;
	            var item = parts[k].item;
	            if (kind === 'item' && item && item.isEnabled) {
	                this._activate(k);
	                return;
	            }
	            if (kind === 'header' && !item) {
	                this._activate(k);
	                return;
	            }
	            if (kind === 'any' && (!item || item.isEnabled)) {
	                this._activate(k);
	                return;
	            }
	        }
	        // Otherwise, deactivate the current item.
	        this._activate(-1);
	    };
	    /**
	     * Activate the previous enabled index of the given kind.
	     */
	    CommandPalette.prototype._activatePrev = function (kind) {
	        // Bail if there are no current search results.
	        if (!this._result) {
	            return;
	        }
	        // Bail if the search results are empty.
	        var parts = this._result.parts;
	        if (parts.length === 0) {
	            return;
	        }
	        // Activate the previous enabled index of the specified kind.
	        var ai = this._activeIndex;
	        var start = ai <= 0 ? parts.length - 1 : ai - 1;
	        for (var i = 0, n = parts.length; i < n; ++i) {
	            var k = (start - i + n) % n;
	            var item = parts[k].item;
	            if (kind === 'item' && item && item.isEnabled) {
	                this._activate(k);
	                return;
	            }
	            if (kind === 'header' && !item) {
	                this._activate(k);
	                return;
	            }
	            if (kind === 'any' && (!item || item.isEnabled)) {
	                this._activate(k);
	                return;
	            }
	        }
	        // Otherwise, deactivate the current item.
	        this._activate(-1);
	    };
	    /**
	     * Trigger the result part at the active index.
	     *
	     * If the part is an enabled command it will be executed. If the
	     * part is a header, the category search term will be toggled.
	     */
	    CommandPalette.prototype._triggerActive = function () {
	        // Bail if there is no search result.
	        if (!this._result) {
	            return;
	        }
	        // Bail if the active index is out of range.
	        var part = this._result.parts[this._activeIndex];
	        if (!part) {
	            return;
	        }
	        // Bail if the part has a disabled item.
	        if (part.item && !part.item.isEnabled) {
	            return;
	        }
	        // Look up the input node.
	        var input = this.inputNode;
	        // If the part has an item, focus the input field, select the
	        // text, and execute the command.
	        if (part.item) {
	            input.focus();
	            input.select();
	            this._commands.execute(part.item.command, part.item.args);
	            return;
	        }
	        // Otherwise, toggle the category text...
	        // Parse the current input value.
	        var _a = CommandPalette.splitQuery(input.value), category = _a.category, text = _a.text;
	        // Extract the raw category text.
	        var desired = part.markup.replace(/<mark>|<\/mark>/g, '');
	        // Create a new query with the toggled category.
	        var computed = desired === category ? '' : desired;
	        var query = CommandPalette.joinQuery(computed, text);
	        // Update the input text and refocus the field.
	        input.value = query;
	        input.focus();
	        // Schedule an update to render the new search results.
	        this.update();
	    };
	    /**
	     * A signal handler for commands and keymap changes.
	     */
	    CommandPalette.prototype._onGenericChange = function () {
	        if (this.isAttached)
	            this.update();
	    };
	    return CommandPalette;
	}(widget_1.Widget));
	exports.CommandPalette = CommandPalette;
	/**
	 * The namespace for the `CommandPalette` class statics.
	 */
	var CommandPalette;
	(function (CommandPalette) {
	    /**
	     * The default implementation of `IRenderer`.
	     */
	    var Renderer = (function () {
	        function Renderer() {
	        }
	        /**
	         * Create a node for a section header.
	         *
	         * @returns A new node for a section header.
	         */
	        Renderer.prototype.createHeaderNode = function () {
	            var node = document.createElement('li');
	            node.className = HEADER_CLASS;
	            return node;
	        };
	        /**
	         * Create a node for a command item.
	         *
	         * @returns A new node for a command item.
	         */
	        Renderer.prototype.createItemNode = function () {
	            var node = document.createElement('li');
	            var label = document.createElement('div');
	            var caption = document.createElement('div');
	            var shortcut = document.createElement('div');
	            node.className = ITEM_CLASS;
	            label.className = LABEL_CLASS;
	            caption.className = CAPTION_CLASS;
	            shortcut.className = SHORTCUT_CLASS;
	            node.appendChild(shortcut); // will float: right
	            node.appendChild(label);
	            node.appendChild(caption);
	            return node;
	        };
	        /**
	         * Update a header node to reflect the given data.
	         *
	         * @param node - A node created by a call to `createHeaderNode`.
	         *
	         * @param markup - The markup for the header text. This is the
	         *   section category text interpolated with `<mark>` tags for
	         *   the matching search characters.
	         */
	        Renderer.prototype.updateHeaderNode = function (node, markup) {
	            node.className = HEADER_CLASS;
	            node.innerHTML = markup;
	        };
	        /**
	         * Update an item node to reflect the state of a command item.
	         *
	         * @param node - A node created by a call to `createItemNode`.
	         *
	         * @param item - The command item holding the data for the node.
	         *
	         * @param markup - The markup for the item label. This is the
	         *   item label text interpolated with `<mark>` tags for the
	         *   matching search characters.
	         */
	        Renderer.prototype.updateItemNode = function (node, item, markup) {
	            // Setup the initial item class.
	            var itemClass = ITEM_CLASS;
	            // Add the boolean states to the item class.
	            //
	            // Note: non-visible items are not rendered by the palette, so
	            // there is no need to check the visibility flag of the item.
	            if (!item.isEnabled) {
	                itemClass += " " + DISABLED_CLASS;
	            }
	            if (item.isToggled) {
	                itemClass += " " + TOGGLED_CLASS;
	            }
	            // Add the extra class name(s) to the item class.
	            var extraItemClass = item.className;
	            if (extraItemClass) {
	                itemClass += " " + extraItemClass;
	            }
	            // Generate the formatted shortcut text.
	            var shortcutText = this.formatShortcut(item.keyBinding);
	            // Extract the relevant child nodes.
	            var shortcut = node.firstChild;
	            var label = shortcut.nextSibling;
	            var caption = label.nextSibling;
	            // Set the command ID in the data set.
	            node.dataset['command'] = item.command;
	            // Update the rest of the node state.
	            node.className = itemClass;
	            label.innerHTML = markup;
	            caption.textContent = item.caption;
	            shortcut.textContent = shortcutText;
	        };
	        /**
	         * Format a key binding into shortcut text for display.
	         *
	         * @param binding - The key binding to format. This may be `null`.
	         *
	         * @returns The formatted shortcut text for display.
	         */
	        Renderer.prototype.formatShortcut = function (binding) {
	            return binding ? binding.keys.map(keymap_1.Keymap.formatKeystroke).join(' ') : '';
	        };
	        return Renderer;
	    }());
	    CommandPalette.Renderer = Renderer;
	    /**
	     * The default `Renderer` instance.
	     */
	    CommandPalette.defaultRenderer = new Renderer();
	    /**
	     * Split a query string into its category and text components.
	     *
	     * @param query - A query string of the form `(:<category>:)?<text>`.
	     *
	     * @returns The `category` and `text` components of the query with
	     *   leading and trailing whitespace removed.
	     */
	    function splitQuery(query) {
	        query = query.trim();
	        var i = query.indexOf(':');
	        if (i === -1) {
	            return { category: '', text: query };
	        }
	        var category = query.slice(0, i).trim();
	        var text = query.slice(i + 1).trim();
	        return { category: category, text: text };
	    }
	    CommandPalette.splitQuery = splitQuery;
	    /**
	     * Join category and text components into a query string.
	     *
	     * @param category - The category for the query or an empty string.
	     *
	     * @param text - The text for the query or an empty string.
	     *
	     * @returns The joined query string for the components.
	     */
	    function joinQuery(category, text) {
	        var query;
	        if (category && text) {
	            query = category.trim() + ": " + text.trim();
	        }
	        else if (category) {
	            query = category.trim() + ": ";
	        }
	        else if (text) {
	            query = text.trim();
	        }
	        else {
	            query = '';
	        }
	        return query;
	    }
	    CommandPalette.joinQuery = joinQuery;
	})(CommandPalette = exports.CommandPalette || (exports.CommandPalette = {}));
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create the DOM node for a command palette.
	     */
	    function createNode() {
	        var node = document.createElement('div');
	        var search = document.createElement('div');
	        var wrapper = document.createElement('div');
	        var input = document.createElement('input');
	        var content = document.createElement('ul');
	        search.className = SEARCH_CLASS;
	        wrapper.className = WRAPPER_CLASS;
	        input.className = INPUT_CLASS;
	        content.className = CONTENT_CLASS;
	        input.spellcheck = false;
	        wrapper.appendChild(input);
	        search.appendChild(wrapper);
	        node.appendChild(search);
	        node.appendChild(content);
	        return node;
	    }
	    Private.createNode = createNode;
	    /**
	     * Create a new command item from a keymap, commands, and options.
	     */
	    function createItem(commands, keymap, options) {
	        return new CommandItem(commands, keymap, options);
	    }
	    Private.createItem = createItem;
	    /**
	     * Search the a sequence of command items for fuzzy matches.
	     *
	     * @param category - The category to match against the command items.
	     *   If this is an empty string, all item categories will be matched.
	     *
	     * @param text - The text to match against the command items.
	     *   If this is an empty string, all items will be matched.
	     *
	     * @returns The result of the search.
	     */
	    function search(items, category, text) {
	        // Collect a mapping of the matching categories. The mapping will
	        // only contain categories which match the provided query text.
	        // If the category is an empty string, all categories will be
	        // matched with a score of `0` and a `null` indices array.
	        var catmap = matchCategory(items, category);
	        // Filter the items for matching labels. Only items which have a
	        // category in the given map are considered. The category score
	        // is added to the label score to create the final item score.
	        // If the text is an empty string, all items will be matched
	        // with a label score of `0` and `null` indices array.
	        var scores = matchLabel(items, text, catmap);
	        // Sort the items based on their total item score. Ties are
	        // broken by locale order of the category followed by label.
	        scores.sort(scoreCmp);
	        // Group the item scores by category. The categories are added
	        // to the map in the order they appear in the scores array.
	        var groups = groupScores(scores);
	        // Return the result for the search. The headers are created in
	        // the order of key iteration of the map. On all major browsers,
	        // this is insertion order. This means that headers are created
	        // in the order of first appearance in the sorted scores array.
	        return createSearchResult(groups, catmap);
	    }
	    Private.search = search;
	    /**
	     * A concrete implementation of `CommandPalette.IItem`.
	     */
	    var CommandItem = (function () {
	        /**
	         * Construct a new command item.
	         */
	        function CommandItem(commands, keymap, options) {
	            this._commands = commands;
	            this._keymap = keymap;
	            this._command = options.command;
	            this._args = options.args || null;
	            this._category = normalizeCategory(options.category || 'general');
	        }
	        Object.defineProperty(CommandItem.prototype, "command", {
	            /**
	             * The command to execute when the item is triggered.
	             */
	            get: function () {
	                return this._command;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(CommandItem.prototype, "args", {
	            /**
	             * The arguments for the command.
	             */
	            get: function () {
	                return this._args;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(CommandItem.prototype, "category", {
	            /**
	             * The category for the command item.
	             */
	            get: function () {
	                return this._category;
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(CommandItem.prototype, "label", {
	            /**
	             * The display label for the command item.
	             */
	            get: function () {
	                return this._commands.label(this._command, this._args);
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(CommandItem.prototype, "caption", {
	            /**
	             * The display caption for the command item.
	             */
	            get: function () {
	                return this._commands.caption(this._command, this._args);
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(CommandItem.prototype, "className", {
	            /**
	             * The extra class name for the command item.
	             */
	            get: function () {
	                return this._commands.className(this._command, this._args);
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(CommandItem.prototype, "isEnabled", {
	            /**
	             * Whether the command item is enabled.
	             */
	            get: function () {
	                return this._commands.isEnabled(this._command, this._args);
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(CommandItem.prototype, "isToggled", {
	            /**
	             * Whether the command item is toggled.
	             */
	            get: function () {
	                return this._commands.isToggled(this._command, this._args);
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(CommandItem.prototype, "isVisible", {
	            /**
	             * Whether the command item is visible.
	             */
	            get: function () {
	                return this._commands.isVisible(this._command, this._args);
	            },
	            enumerable: true,
	            configurable: true
	        });
	        Object.defineProperty(CommandItem.prototype, "keyBinding", {
	            /**
	             * The key binding for the command item.
	             */
	            get: function () {
	                return this._keymap.findBinding(this._command, this._args);
	            },
	            enumerable: true,
	            configurable: true
	        });
	        return CommandItem;
	    }());
	    /**
	     * Normalize a category for a command item.
	     */
	    function normalizeCategory(category) {
	        return category.trim().replace(/\s+/g, ' ').toLowerCase();
	    }
	    /**
	     * Normalize the query text for a command item.
	     *
	     * @param text - The category or text portion of a query.
	     *
	     * @returns The normalized query text.
	     *
	     * #### Notes
	     * The text is normalized by converting to lower case and removing
	     * all whitespace.
	     */
	    function normalizeQueryText(text) {
	        return text.replace(/\s+/g, '').toLowerCase();
	    }
	    /**
	     * Collect a mapping of the categories which match the given query.
	     *
	     * @param items - The command items to search.
	     *
	     * @param query - The category portion of the query.
	     *
	     * @returns A mapping of matched category to match score.
	     *
	     * #### Notes
	     * The query string will be normalized by lower casing and removing
	     * all whitespace. If the normalized query is an empty string, all
	     * categories will be matched with a `0` score and `null` indices.
	     *
	     * Non-visible items will be ignored.
	     */
	    function matchCategory(items, query) {
	        // Normalize the query text to lower case with no whitespace.
	        query = normalizeQueryText(query);
	        // Create the maps needed to track the match state.
	        var seen = Object.create(null);
	        var matched = Object.create(null);
	        // Iterate over the items and match the categories.
	        for (var i = 0, n = items.length; i < n; ++i) {
	            // Ignore items which are not visible.
	            var item = items.at(i);
	            if (!item.isVisible) {
	                continue;
	            }
	            // If a category has already been seen, no more work is needed.
	            var category = item.category;
	            if (category in seen) {
	                continue;
	            }
	            // Mark the category as seen so it is only processed once.
	            seen[category] = true;
	            // If the query is empty, all categories match by default.
	            if (!query) {
	                matched[category] = { score: 0, indices: null };
	                continue;
	            }
	            // Run the matcher for the query and skip if no match.
	            var match = searching_1.StringSearch.sumOfSquares(category, query);
	            if (!match) {
	                continue;
	            }
	            // Store the match score in the results.
	            matched[category] = match;
	        }
	        // Return the final mapping of matched categories.
	        return matched;
	    }
	    /**
	     * Filter command items for those with matching label and category.
	     *
	     * @param items - The command items to search.
	     *
	     * @param query - The text portion of the query.
	     *
	     * @param categories - A mapping of the valid item categories.
	     *
	     * @returns An array of item scores for the matching items.
	     *
	     * #### Notes
	     * The query string will be normalized by lower casing and removing
	     * all whitespace. If the normalized query is an empty string, all
	     * items will be matched with a `0` label score and `null` indices.
	     *
	     * Items which have a category which is not present in the category
	     * map will be ignored.
	     *
	     * Non-visible items will be ignored.
	     *
	     * The final item score is the sum of the item label score and the
	     * relevant category score.
	     */
	    function matchLabel(items, query, categories) {
	        // Normalize the query text to lower case with no whitespace.
	        query = normalizeQueryText(query);
	        // Create the array to hold the resulting scores.
	        var scores = [];
	        // Iterate over the items and match the text with the query.
	        for (var i = 0, n = items.length; i < n; ++i) {
	            // Ignore items which are not visible.
	            var item = items.at(i);
	            if (!item.isVisible) {
	                continue;
	            }
	            // Look up the category score for the item category.
	            var cs = categories[item.category];
	            // If the category was not matched, the item is skipped.
	            if (!cs) {
	                continue;
	            }
	            // If the query is empty, all items are matched by default.
	            if (!query) {
	                scores.push({ score: cs.score, indices: null, item: item });
	                continue;
	            }
	            // Run the matcher for the query and skip if no match.
	            var match = searching_1.StringSearch.sumOfSquares(item.label.toLowerCase(), query);
	            if (!match) {
	                continue;
	            }
	            // Create the match score for the item.
	            var score = cs.score + match.score;
	            scores.push({ score: score, indices: match.indices, item: item });
	        }
	        // Return the final array of matched item scores.
	        return scores;
	    }
	    /**
	     * A sort comparison function for a command item match score.
	     *
	     * This orders the items first based on score (lower is better), then
	     * by locale order of the item category followed by the item text.
	     */
	    function scoreCmp(a, b) {
	        var d1 = a.score - b.score;
	        if (d1 !== 0) {
	            return d1;
	        }
	        var d2 = a.item.category.localeCompare(b.item.category);
	        if (d2 !== 0) {
	            return d2;
	        }
	        return a.item.label.localeCompare(b.item.label);
	    }
	    /**
	     * Group item scores by item category.
	     *
	     * @param scores - The items to group by category.
	     *
	     * @returns A mapping of category name to group of items.
	     *
	     * #### Notes
	     * The categories are added to the map in the order of first
	     * appearance in the `scores` array.
	     */
	    function groupScores(scores) {
	        var result = Object.create(null);
	        for (var _i = 0, scores_1 = scores; _i < scores_1.length; _i++) {
	            var score = scores_1[_i];
	            var cat = score.item.category;
	            (result[cat] || (result[cat] = [])).push(score);
	        }
	        return result;
	    }
	    /**
	     * Create the search results for a collection of item scores.
	     *
	     * @param groups - The item scores, grouped by category.
	     *
	     * @param categories - A mapping of category scores.
	     *
	     * @returns New search results for the given scores.
	     *
	     * #### Notes
	     * This function renders the groups in iteration order, which on
	     * all major browsers is the order of insertion (by convention).
	     */
	    function createSearchResult(groups, categories) {
	        var itemCount = 0;
	        var headerCount = 0;
	        var parts = [];
	        for (var cat in groups) {
	            headerCount++;
	            parts.push(createHeaderPart(cat, categories[cat]));
	            for (var _i = 0, _a = groups[cat]; _i < _a.length; _i++) {
	                var score = _a[_i];
	                itemCount++;
	                parts.push(createItemPart(score));
	            }
	        }
	        return { itemCount: itemCount, headerCount: headerCount, parts: parts };
	    }
	    /**
	     * Create a header result part for the given data.
	     *
	     * @param category - The category name for the header.
	     *
	     * @param score - The score for the category match.
	     *
	     * @returns A header result part for the given data.
	     */
	    function createHeaderPart(category, score) {
	        var markup = highlightText(category, score.indices);
	        return { markup: markup, item: null };
	    }
	    /**
	     * Create an item result part for the given data.
	     *
	     * @param score - The score for the item match.
	     *
	     * @returns An item result part for the given data.
	     */
	    function createItemPart(score) {
	        var markup = highlightText(score.item.label, score.indices);
	        return { markup: markup, item: score.item };
	    }
	    /**
	     * Highlight the matching character of the given text.
	     *
	     * @param text - The text to highlight.
	     *
	     * @param indices - The character indices to highlight, or `null`.
	     *
	     * @returns The text interpolated with `<mark>` tags as needed.
	     */
	    function highlightText(text, indices) {
	        return indices ? searching_1.StringSearch.highlight(text, indices) : text;
	    }
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/commandpalette.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/console/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/console/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var menu_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/menu.js');
	var codeeditor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/index.js');
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var dates_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dates.js');
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var inspector_1 = __jupyter_require__('jupyterlab@0.15.1/lib/inspector/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var mainmenu_1 = __jupyter_require__('jupyterlab@0.15.1/lib/mainmenu/index.js');
	var rendermime_1 = __jupyter_require__('jupyterlab@0.15.1/lib/rendermime/index.js');
	var services_2 = __jupyter_require__('jupyterlab@0.15.1/lib/services/index.js');
	var index_1 = __jupyter_require__('jupyterlab@0.15.1/lib/console/index.js');
	/**
	 * The console widget tracker provider.
	 */
	exports.trackerPlugin = {
	    id: 'jupyter.services.console-tracker',
	    provides: index_1.IConsoleTracker,
	    requires: [
	        services_2.IServiceManager,
	        rendermime_1.IRenderMime,
	        mainmenu_1.IMainMenu,
	        inspector_1.IInspector,
	        commandpalette_1.ICommandPalette,
	        filebrowser_1.IPathTracker,
	        index_1.ConsolePanel.IContentFactory,
	        codeeditor_1.IEditorServices,
	        instancerestorer_1.IInstanceRestorer
	    ],
	    activate: activateConsole,
	    autoStart: true
	};
	/**
	 * The console widget content factory.
	 */
	exports.contentFactoryPlugin = {
	    id: 'jupyter.services.console-renderer',
	    provides: index_1.ConsolePanel.IContentFactory,
	    requires: [codeeditor_1.IEditorServices],
	    autoStart: true,
	    activate: function (app, editorServices) {
	        var editorFactory = editorServices.factoryService.newInlineEditor;
	        return new index_1.ConsolePanel.ContentFactory({ editorFactory: editorFactory });
	    }
	};
	/**
	 * Export the plugins as the default.
	 */
	var plugins = [exports.contentFactoryPlugin, exports.trackerPlugin];
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugins;
	/**
	 * The class name for all main area landscape tab icons.
	 */
	var LANDSCAPE_ICON_CLASS = 'jp-MainAreaLandscapeIcon';
	/**
	 * The class name for the console icon from the default theme.
	 */
	var CONSOLE_ICON_CLASS = 'jp-ImageCodeConsole';
	/**
	 * A regex for console names.
	 */
	var CONSOLE_REGEX = /^console-(\d)+-[0-9a-f]+$/;
	/**
	 * Activate the console extension.
	 */
	function activateConsole(app, services, rendermime, mainMenu, inspector, palette, pathTracker, contentFactory, editorServices, restorer) {
	    var manager = services.sessions;
	    var commands = app.commands, keymap = app.keymap;
	    var category = 'Console';
	    var command;
	    var count = 0;
	    var menu = new menu_1.Menu({ commands: commands, keymap: keymap });
	    // Create an instance tracker for all console panels.
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: 'console' });
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: index_1.CommandIDs.create,
	        args: function (panel) { return ({ id: panel.console.session.id }); },
	        name: function (panel) { return panel.console.session && panel.console.session.id; },
	        when: manager.ready
	    });
	    // Set the source of the code inspector.
	    tracker.currentChanged.connect(function (sender, widget) {
	        if (widget) {
	            inspector.source = widget.inspectionHandler;
	        }
	    });
	    // Set the main menu title.
	    menu.title.label = category;
	    command = index_1.CommandIDs.create;
	    commands.addCommand(command, {
	        label: 'Start New Console',
	        execute: function (args) {
	            var name = "Console " + ++count;
	            args = args || {};
	            // If we get a session, use it.
	            if (args.id) {
	                return manager.ready.then(function () { return manager.connectTo(args.id); })
	                    .then(function (session) {
	                    name = session.path.split('/').pop();
	                    name = "Console " + name.match(CONSOLE_REGEX)[1];
	                    createConsole(session, name);
	                    return session.id;
	                });
	            }
	            // Find the correct path for the new session.
	            // Use the given path or the cwd.
	            var path = args.path || pathTracker.path;
	            if (services_1.ContentsManager.extname(path)) {
	                path = services_1.ContentsManager.dirname(path);
	            }
	            path = path + "/console-" + count + "-" + services_1.utils.uuid();
	            // Get the kernel model.
	            return manager.ready.then(function () { return getKernel(args, name); }).then(function (kernel) {
	                if (!kernel || (kernel && !kernel.id && !kernel.name)) {
	                    return;
	                }
	                // Start the session.
	                var options = {
	                    path: path,
	                    kernelName: kernel.name,
	                    kernelId: kernel.id
	                };
	                return manager.startNew(options).then(function (session) {
	                    createConsole(session, name);
	                    return session.id;
	                });
	            });
	        }
	    });
	    palette.addItem({ command: command, category: category });
	    menu.addItem({ command: command });
	    command = index_1.CommandIDs.clear;
	    commands.addCommand(command, {
	        label: 'Clear Cells',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                current.console.clear();
	            }
	        }
	    });
	    palette.addItem({ command: command, category: category });
	    menu.addItem({ command: command });
	    command = index_1.CommandIDs.run;
	    commands.addCommand(command, {
	        label: 'Run Cell',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                current.console.execute();
	            }
	        }
	    });
	    palette.addItem({ command: command, category: category });
	    menu.addItem({ command: command });
	    command = index_1.CommandIDs.runForced;
	    commands.addCommand(command, {
	        label: 'Run Cell (forced)',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                current.console.execute(true);
	            }
	        }
	    });
	    palette.addItem({ command: command, category: category });
	    menu.addItem({ command: command });
	    command = index_1.CommandIDs.linebreak;
	    commands.addCommand(command, {
	        label: 'Insert Line Break',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                current.console.insertLinebreak();
	            }
	        }
	    });
	    palette.addItem({ command: command, category: category });
	    menu.addItem({ command: command });
	    command = index_1.CommandIDs.interrupt;
	    commands.addCommand(command, {
	        label: 'Interrupt Kernel',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                var kernel = current.console.session.kernel;
	                if (kernel) {
	                    return kernel.interrupt();
	                }
	            }
	        }
	    });
	    palette.addItem({ command: command, category: category });
	    menu.addItem({ command: command });
	    command = index_1.CommandIDs.inject;
	    commands.addCommand(command, {
	        execute: function (args) {
	            var id = args['id'];
	            tracker.find(function (widget) {
	                if (widget.console.session.id === id) {
	                    widget.console.inject(args['code']);
	                    return true;
	                }
	            });
	        }
	    });
	    command = index_1.CommandIDs.open;
	    commands.addCommand(command, {
	        execute: function (args) {
	            var id = args['id'];
	            var widget = tracker.find(function (value) {
	                if (value.console.session.id === id) {
	                    return true;
	                }
	            });
	            if (widget) {
	                app.shell.activateMain(widget.id);
	            }
	            else {
	                app.commands.execute(index_1.CommandIDs.create, { id: id });
	            }
	        }
	    });
	    /**
	     * Get the kernel given the create args.
	     */
	    function getKernel(args, name) {
	        if (args.kernel) {
	            return Promise.resolve(args.kernel);
	        }
	        return manager.ready.then(function () {
	            var options = {
	                name: name,
	                specs: manager.specs,
	                sessions: manager.running(),
	                preferredLanguage: args.preferredLanguage || '',
	                host: document.body
	            };
	            return docregistry_1.selectKernel(options);
	        });
	    }
	    var id = 0; // The ID counter for notebook panels.
	    /**
	     * Create a console for a given session.
	     *
	     * #### Notes
	     * The manager must be ready before calling this function.
	     */
	    function createConsole(session, name) {
	        var options = {
	            rendermime: rendermime.clone(),
	            session: session,
	            contentFactory: contentFactory,
	            mimeTypeService: editorServices.mimeTypeService
	        };
	        var panel = new index_1.ConsolePanel(options);
	        var resolver = new rendermime_1.RenderMime.UrlResolver({
	            session: session,
	            contents: services.contents
	        });
	        panel.console.rendermime.resolver = resolver;
	        var specs = manager.specs;
	        var displayName = specs.kernelspecs[session.kernel.name].display_name;
	        var captionOptions = {
	            label: name,
	            displayName: displayName,
	            path: session.path,
	            connected: new Date()
	        };
	        // If the console panel does not have an ID, assign it one.
	        panel.id = panel.id || "console-" + ++id;
	        panel.title.label = name;
	        panel.title.caption = Private.caption(captionOptions);
	        panel.title.icon = LANDSCAPE_ICON_CLASS + " " + CONSOLE_ICON_CLASS;
	        panel.title.closable = true;
	        // Update the caption of the tab with the last execution time.
	        panel.console.executed.connect(function (sender, executed) {
	            captionOptions.executed = executed;
	            panel.title.caption = Private.caption(captionOptions);
	        });
	        // Update the caption of the tab when the kernel changes.
	        panel.console.session.kernelChanged.connect(function () {
	            var newName = panel.console.session.kernel.name;
	            name = specs.kernelspecs[name].display_name;
	            captionOptions.displayName = newName;
	            captionOptions.connected = new Date();
	            captionOptions.executed = null;
	            panel.title.caption = Private.caption(captionOptions);
	        });
	        // Immediately set the inspector source to the current console.
	        inspector.source = panel.inspectionHandler;
	        // Add the console panel to the tracker.
	        tracker.add(panel);
	        app.shell.addToMainArea(panel);
	        app.shell.activateMain(panel.id);
	    }
	    command = index_1.CommandIDs.switchKernel;
	    commands.addCommand(command, {
	        label: 'Switch Kernel',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (!current) {
	                return;
	            }
	            var widget = current.console;
	            var session = widget.session;
	            var lang = '';
	            manager.ready.then(function () {
	                var specs = manager.specs;
	                if (session.kernel) {
	                    lang = specs.kernelspecs[session.kernel.name].language;
	                }
	                var options = {
	                    name: widget.parent.title.label,
	                    specs: specs,
	                    sessions: manager.running(),
	                    preferredLanguage: lang,
	                    kernel: session.kernel.model,
	                    host: widget.parent.node
	                };
	                return docregistry_1.selectKernel(options);
	            }).then(function (kernelId) {
	                // If the user cancels, kernelId will be void and should be ignored.
	                if (kernelId) {
	                    return session.changeKernel(kernelId);
	                }
	            });
	        }
	    });
	    palette.addItem({ command: command, category: category });
	    menu.addItem({ command: command });
	    mainMenu.addMenu(menu, { rank: 50 });
	    return tracker;
	}
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Generate a caption for a console's title.
	     */
	    function caption(options) {
	        var label = options.label, path = options.path, displayName = options.displayName, connected = options.connected, executed = options.executed;
	        var caption = (("Name: " + label + "\n") +
	            ("Directory: " + services_1.ContentsManager.dirname(path) + "\n") +
	            ("Kernel: " + displayName + "\n") +
	            ("Connected: " + dates_1.dateTime(connected.toISOString())));
	        if (executed) {
	            caption += "\nLast Execution: " + dates_1.dateTime(executed.toISOString());
	        }
	        return caption;
	    }
	    Private.caption = caption;
	})(Private || (Private = {}));
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/console/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/dates.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/dates.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var moment = __jupyter_require__('moment@^2.11.2/moment.js');
	/**
	 * Convert a timestring to a human readable string (e.g. 'two minutes ago').
	 *
	 * @param value - The date timestring.
	 *
	 * @returns A formatted date.
	 */
	function humanTime(value) {
	    var time = moment(value).fromNow();
	    time = time === 'a few seconds ago' ? 'seconds ago' : time;
	    return time;
	}
	exports.humanTime = humanTime;
	/**
	 * Convert a timestring to a date format.
	 *
	 * @param value - The date timestring.
	 *
	 * @param format - The format string.
	 *
	 * @returns A formatted date.
	 */
	function dateTime(value, format) {
	    if (format === void 0) { format = 'YYYY-MM-DD HH:mm'; }
	    return moment(value).format(format);
	}
	exports.dateTime = dateTime;
	//# sourceMappingURL=dates.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/dates.js **/


/** START DEFINE BLOCK for moment@2.17.1/moment.js **/
jupyter.define('moment@2.17.1/moment.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(module) {//! moment.js
	//! version : 2.17.1
	//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
	//! license : MIT
	//! momentjs.com
	
	;(function (global, factory) {
	     true ? module.exports = factory() :
	    typeof define === 'function' && define.amd ? define(factory) :
	    global.moment = factory()
	}(this, (function () { 'use strict';
	
	var hookCallback;
	
	function hooks () {
	    return hookCallback.apply(null, arguments);
	}
	
	// This is done to register the method called with moment()
	// without creating circular dependencies.
	function setHookCallback (callback) {
	    hookCallback = callback;
	}
	
	function isArray(input) {
	    return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
	}
	
	function isObject(input) {
	    // IE8 will treat undefined and null as object if it wasn't for
	    // input != null
	    return input != null && Object.prototype.toString.call(input) === '[object Object]';
	}
	
	function isObjectEmpty(obj) {
	    var k;
	    for (k in obj) {
	        // even if its not own property I'd still call it non-empty
	        return false;
	    }
	    return true;
	}
	
	function isNumber(input) {
	    return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
	}
	
	function isDate(input) {
	    return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
	}
	
	function map(arr, fn) {
	    var res = [], i;
	    for (i = 0; i < arr.length; ++i) {
	        res.push(fn(arr[i], i));
	    }
	    return res;
	}
	
	function hasOwnProp(a, b) {
	    return Object.prototype.hasOwnProperty.call(a, b);
	}
	
	function extend(a, b) {
	    for (var i in b) {
	        if (hasOwnProp(b, i)) {
	            a[i] = b[i];
	        }
	    }
	
	    if (hasOwnProp(b, 'toString')) {
	        a.toString = b.toString;
	    }
	
	    if (hasOwnProp(b, 'valueOf')) {
	        a.valueOf = b.valueOf;
	    }
	
	    return a;
	}
	
	function createUTC (input, format, locale, strict) {
	    return createLocalOrUTC(input, format, locale, strict, true).utc();
	}
	
	function defaultParsingFlags() {
	    // We need to deep clone this object.
	    return {
	        empty           : false,
	        unusedTokens    : [],
	        unusedInput     : [],
	        overflow        : -2,
	        charsLeftOver   : 0,
	        nullInput       : false,
	        invalidMonth    : null,
	        invalidFormat   : false,
	        userInvalidated : false,
	        iso             : false,
	        parsedDateParts : [],
	        meridiem        : null
	    };
	}
	
	function getParsingFlags(m) {
	    if (m._pf == null) {
	        m._pf = defaultParsingFlags();
	    }
	    return m._pf;
	}
	
	var some;
	if (Array.prototype.some) {
	    some = Array.prototype.some;
	} else {
	    some = function (fun) {
	        var t = Object(this);
	        var len = t.length >>> 0;
	
	        for (var i = 0; i < len; i++) {
	            if (i in t && fun.call(this, t[i], i, t)) {
	                return true;
	            }
	        }
	
	        return false;
	    };
	}
	
	var some$1 = some;
	
	function isValid(m) {
	    if (m._isValid == null) {
	        var flags = getParsingFlags(m);
	        var parsedParts = some$1.call(flags.parsedDateParts, function (i) {
	            return i != null;
	        });
	        var isNowValid = !isNaN(m._d.getTime()) &&
	            flags.overflow < 0 &&
	            !flags.empty &&
	            !flags.invalidMonth &&
	            !flags.invalidWeekday &&
	            !flags.nullInput &&
	            !flags.invalidFormat &&
	            !flags.userInvalidated &&
	            (!flags.meridiem || (flags.meridiem && parsedParts));
	
	        if (m._strict) {
	            isNowValid = isNowValid &&
	                flags.charsLeftOver === 0 &&
	                flags.unusedTokens.length === 0 &&
	                flags.bigHour === undefined;
	        }
	
	        if (Object.isFrozen == null || !Object.isFrozen(m)) {
	            m._isValid = isNowValid;
	        }
	        else {
	            return isNowValid;
	        }
	    }
	    return m._isValid;
	}
	
	function createInvalid (flags) {
	    var m = createUTC(NaN);
	    if (flags != null) {
	        extend(getParsingFlags(m), flags);
	    }
	    else {
	        getParsingFlags(m).userInvalidated = true;
	    }
	
	    return m;
	}
	
	function isUndefined(input) {
	    return input === void 0;
	}
	
	// Plugins that add properties should also add the key here (null value),
	// so we can properly clone ourselves.
	var momentProperties = hooks.momentProperties = [];
	
	function copyConfig(to, from) {
	    var i, prop, val;
	
	    if (!isUndefined(from._isAMomentObject)) {
	        to._isAMomentObject = from._isAMomentObject;
	    }
	    if (!isUndefined(from._i)) {
	        to._i = from._i;
	    }
	    if (!isUndefined(from._f)) {
	        to._f = from._f;
	    }
	    if (!isUndefined(from._l)) {
	        to._l = from._l;
	    }
	    if (!isUndefined(from._strict)) {
	        to._strict = from._strict;
	    }
	    if (!isUndefined(from._tzm)) {
	        to._tzm = from._tzm;
	    }
	    if (!isUndefined(from._isUTC)) {
	        to._isUTC = from._isUTC;
	    }
	    if (!isUndefined(from._offset)) {
	        to._offset = from._offset;
	    }
	    if (!isUndefined(from._pf)) {
	        to._pf = getParsingFlags(from);
	    }
	    if (!isUndefined(from._locale)) {
	        to._locale = from._locale;
	    }
	
	    if (momentProperties.length > 0) {
	        for (i in momentProperties) {
	            prop = momentProperties[i];
	            val = from[prop];
	            if (!isUndefined(val)) {
	                to[prop] = val;
	            }
	        }
	    }
	
	    return to;
	}
	
	var updateInProgress = false;
	
	// Moment prototype object
	function Moment(config) {
	    copyConfig(this, config);
	    this._d = new Date(config._d != null ? config._d.getTime() : NaN);
	    if (!this.isValid()) {
	        this._d = new Date(NaN);
	    }
	    // Prevent infinite loop in case updateOffset creates new moment
	    // objects.
	    if (updateInProgress === false) {
	        updateInProgress = true;
	        hooks.updateOffset(this);
	        updateInProgress = false;
	    }
	}
	
	function isMoment (obj) {
	    return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
	}
	
	function absFloor (number) {
	    if (number < 0) {
	        // -0 -> 0
	        return Math.ceil(number) || 0;
	    } else {
	        return Math.floor(number);
	    }
	}
	
	function toInt(argumentForCoercion) {
	    var coercedNumber = +argumentForCoercion,
	        value = 0;
	
	    if (coercedNumber !== 0 && isFinite(coercedNumber)) {
	        value = absFloor(coercedNumber);
	    }
	
	    return value;
	}
	
	// compare two arrays, return the number of differences
	function compareArrays(array1, array2, dontConvert) {
	    var len = Math.min(array1.length, array2.length),
	        lengthDiff = Math.abs(array1.length - array2.length),
	        diffs = 0,
	        i;
	    for (i = 0; i < len; i++) {
	        if ((dontConvert && array1[i] !== array2[i]) ||
	            (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
	            diffs++;
	        }
	    }
	    return diffs + lengthDiff;
	}
	
	function warn(msg) {
	    if (hooks.suppressDeprecationWarnings === false &&
	            (typeof console !==  'undefined') && console.warn) {
	        console.warn('Deprecation warning: ' + msg);
	    }
	}
	
	function deprecate(msg, fn) {
	    var firstTime = true;
	
	    return extend(function () {
	        if (hooks.deprecationHandler != null) {
	            hooks.deprecationHandler(null, msg);
	        }
	        if (firstTime) {
	            var args = [];
	            var arg;
	            for (var i = 0; i < arguments.length; i++) {
	                arg = '';
	                if (typeof arguments[i] === 'object') {
	                    arg += '\n[' + i + '] ';
	                    for (var key in arguments[0]) {
	                        arg += key + ': ' + arguments[0][key] + ', ';
	                    }
	                    arg = arg.slice(0, -2); // Remove trailing comma and space
	                } else {
	                    arg = arguments[i];
	                }
	                args.push(arg);
	            }
	            warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
	            firstTime = false;
	        }
	        return fn.apply(this, arguments);
	    }, fn);
	}
	
	var deprecations = {};
	
	function deprecateSimple(name, msg) {
	    if (hooks.deprecationHandler != null) {
	        hooks.deprecationHandler(name, msg);
	    }
	    if (!deprecations[name]) {
	        warn(msg);
	        deprecations[name] = true;
	    }
	}
	
	hooks.suppressDeprecationWarnings = false;
	hooks.deprecationHandler = null;
	
	function isFunction(input) {
	    return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
	}
	
	function set (config) {
	    var prop, i;
	    for (i in config) {
	        prop = config[i];
	        if (isFunction(prop)) {
	            this[i] = prop;
	        } else {
	            this['_' + i] = prop;
	        }
	    }
	    this._config = config;
	    // Lenient ordinal parsing accepts just a number in addition to
	    // number + (possibly) stuff coming from _ordinalParseLenient.
	    this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
	}
	
	function mergeConfigs(parentConfig, childConfig) {
	    var res = extend({}, parentConfig), prop;
	    for (prop in childConfig) {
	        if (hasOwnProp(childConfig, prop)) {
	            if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
	                res[prop] = {};
	                extend(res[prop], parentConfig[prop]);
	                extend(res[prop], childConfig[prop]);
	            } else if (childConfig[prop] != null) {
	                res[prop] = childConfig[prop];
	            } else {
	                delete res[prop];
	            }
	        }
	    }
	    for (prop in parentConfig) {
	        if (hasOwnProp(parentConfig, prop) &&
	                !hasOwnProp(childConfig, prop) &&
	                isObject(parentConfig[prop])) {
	            // make sure changes to properties don't modify parent config
	            res[prop] = extend({}, res[prop]);
	        }
	    }
	    return res;
	}
	
	function Locale(config) {
	    if (config != null) {
	        this.set(config);
	    }
	}
	
	var keys;
	
	if (Object.keys) {
	    keys = Object.keys;
	} else {
	    keys = function (obj) {
	        var i, res = [];
	        for (i in obj) {
	            if (hasOwnProp(obj, i)) {
	                res.push(i);
	            }
	        }
	        return res;
	    };
	}
	
	var keys$1 = keys;
	
	var defaultCalendar = {
	    sameDay : '[Today at] LT',
	    nextDay : '[Tomorrow at] LT',
	    nextWeek : 'dddd [at] LT',
	    lastDay : '[Yesterday at] LT',
	    lastWeek : '[Last] dddd [at] LT',
	    sameElse : 'L'
	};
	
	function calendar (key, mom, now) {
	    var output = this._calendar[key] || this._calendar['sameElse'];
	    return isFunction(output) ? output.call(mom, now) : output;
	}
	
	var defaultLongDateFormat = {
	    LTS  : 'h:mm:ss A',
	    LT   : 'h:mm A',
	    L    : 'MM/DD/YYYY',
	    LL   : 'MMMM D, YYYY',
	    LLL  : 'MMMM D, YYYY h:mm A',
	    LLLL : 'dddd, MMMM D, YYYY h:mm A'
	};
	
	function longDateFormat (key) {
	    var format = this._longDateFormat[key],
	        formatUpper = this._longDateFormat[key.toUpperCase()];
	
	    if (format || !formatUpper) {
	        return format;
	    }
	
	    this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
	        return val.slice(1);
	    });
	
	    return this._longDateFormat[key];
	}
	
	var defaultInvalidDate = 'Invalid date';
	
	function invalidDate () {
	    return this._invalidDate;
	}
	
	var defaultOrdinal = '%d';
	var defaultOrdinalParse = /\d{1,2}/;
	
	function ordinal (number) {
	    return this._ordinal.replace('%d', number);
	}
	
	var defaultRelativeTime = {
	    future : 'in %s',
	    past   : '%s ago',
	    s  : 'a few seconds',
	    m  : 'a minute',
	    mm : '%d minutes',
	    h  : 'an hour',
	    hh : '%d hours',
	    d  : 'a day',
	    dd : '%d days',
	    M  : 'a month',
	    MM : '%d months',
	    y  : 'a year',
	    yy : '%d years'
	};
	
	function relativeTime (number, withoutSuffix, string, isFuture) {
	    var output = this._relativeTime[string];
	    return (isFunction(output)) ?
	        output(number, withoutSuffix, string, isFuture) :
	        output.replace(/%d/i, number);
	}
	
	function pastFuture (diff, output) {
	    var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
	    return isFunction(format) ? format(output) : format.replace(/%s/i, output);
	}
	
	var aliases = {};
	
	function addUnitAlias (unit, shorthand) {
	    var lowerCase = unit.toLowerCase();
	    aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
	}
	
	function normalizeUnits(units) {
	    return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
	}
	
	function normalizeObjectUnits(inputObject) {
	    var normalizedInput = {},
	        normalizedProp,
	        prop;
	
	    for (prop in inputObject) {
	        if (hasOwnProp(inputObject, prop)) {
	            normalizedProp = normalizeUnits(prop);
	            if (normalizedProp) {
	                normalizedInput[normalizedProp] = inputObject[prop];
	            }
	        }
	    }
	
	    return normalizedInput;
	}
	
	var priorities = {};
	
	function addUnitPriority(unit, priority) {
	    priorities[unit] = priority;
	}
	
	function getPrioritizedUnits(unitsObj) {
	    var units = [];
	    for (var u in unitsObj) {
	        units.push({unit: u, priority: priorities[u]});
	    }
	    units.sort(function (a, b) {
	        return a.priority - b.priority;
	    });
	    return units;
	}
	
	function makeGetSet (unit, keepTime) {
	    return function (value) {
	        if (value != null) {
	            set$1(this, unit, value);
	            hooks.updateOffset(this, keepTime);
	            return this;
	        } else {
	            return get(this, unit);
	        }
	    };
	}
	
	function get (mom, unit) {
	    return mom.isValid() ?
	        mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
	}
	
	function set$1 (mom, unit, value) {
	    if (mom.isValid()) {
	        mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
	    }
	}
	
	// MOMENTS
	
	function stringGet (units) {
	    units = normalizeUnits(units);
	    if (isFunction(this[units])) {
	        return this[units]();
	    }
	    return this;
	}
	
	
	function stringSet (units, value) {
	    if (typeof units === 'object') {
	        units = normalizeObjectUnits(units);
	        var prioritized = getPrioritizedUnits(units);
	        for (var i = 0; i < prioritized.length; i++) {
	            this[prioritized[i].unit](units[prioritized[i].unit]);
	        }
	    } else {
	        units = normalizeUnits(units);
	        if (isFunction(this[units])) {
	            return this[units](value);
	        }
	    }
	    return this;
	}
	
	function zeroFill(number, targetLength, forceSign) {
	    var absNumber = '' + Math.abs(number),
	        zerosToFill = targetLength - absNumber.length,
	        sign = number >= 0;
	    return (sign ? (forceSign ? '+' : '') : '-') +
	        Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
	}
	
	var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
	
	var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
	
	var formatFunctions = {};
	
	var formatTokenFunctions = {};
	
	// token:    'M'
	// padded:   ['MM', 2]
	// ordinal:  'Mo'
	// callback: function () { this.month() + 1 }
	function addFormatToken (token, padded, ordinal, callback) {
	    var func = callback;
	    if (typeof callback === 'string') {
	        func = function () {
	            return this[callback]();
	        };
	    }
	    if (token) {
	        formatTokenFunctions[token] = func;
	    }
	    if (padded) {
	        formatTokenFunctions[padded[0]] = function () {
	            return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
	        };
	    }
	    if (ordinal) {
	        formatTokenFunctions[ordinal] = function () {
	            return this.localeData().ordinal(func.apply(this, arguments), token);
	        };
	    }
	}
	
	function removeFormattingTokens(input) {
	    if (input.match(/\[[\s\S]/)) {
	        return input.replace(/^\[|\]$/g, '');
	    }
	    return input.replace(/\\/g, '');
	}
	
	function makeFormatFunction(format) {
	    var array = format.match(formattingTokens), i, length;
	
	    for (i = 0, length = array.length; i < length; i++) {
	        if (formatTokenFunctions[array[i]]) {
	            array[i] = formatTokenFunctions[array[i]];
	        } else {
	            array[i] = removeFormattingTokens(array[i]);
	        }
	    }
	
	    return function (mom) {
	        var output = '', i;
	        for (i = 0; i < length; i++) {
	            output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
	        }
	        return output;
	    };
	}
	
	// format date using native date object
	function formatMoment(m, format) {
	    if (!m.isValid()) {
	        return m.localeData().invalidDate();
	    }
	
	    format = expandFormat(format, m.localeData());
	    formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
	
	    return formatFunctions[format](m);
	}
	
	function expandFormat(format, locale) {
	    var i = 5;
	
	    function replaceLongDateFormatTokens(input) {
	        return locale.longDateFormat(input) || input;
	    }
	
	    localFormattingTokens.lastIndex = 0;
	    while (i >= 0 && localFormattingTokens.test(format)) {
	        format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
	        localFormattingTokens.lastIndex = 0;
	        i -= 1;
	    }
	
	    return format;
	}
	
	var match1         = /\d/;            //       0 - 9
	var match2         = /\d\d/;          //      00 - 99
	var match3         = /\d{3}/;         //     000 - 999
	var match4         = /\d{4}/;         //    0000 - 9999
	var match6         = /[+-]?\d{6}/;    // -999999 - 999999
	var match1to2      = /\d\d?/;         //       0 - 99
	var match3to4      = /\d\d\d\d?/;     //     999 - 9999
	var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
	var match1to3      = /\d{1,3}/;       //       0 - 999
	var match1to4      = /\d{1,4}/;       //       0 - 9999
	var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
	
	var matchUnsigned  = /\d+/;           //       0 - inf
	var matchSigned    = /[+-]?\d+/;      //    -inf - inf
	
	var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
	var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
	
	var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
	
	// any word (or two) characters or numbers including two/three word month in arabic.
	// includes scottish gaelic two word and hyphenated months
	var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
	
	
	var regexes = {};
	
	function addRegexToken (token, regex, strictRegex) {
	    regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
	        return (isStrict && strictRegex) ? strictRegex : regex;
	    };
	}
	
	function getParseRegexForToken (token, config) {
	    if (!hasOwnProp(regexes, token)) {
	        return new RegExp(unescapeFormat(token));
	    }
	
	    return regexes[token](config._strict, config._locale);
	}
	
	// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
	function unescapeFormat(s) {
	    return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
	        return p1 || p2 || p3 || p4;
	    }));
	}
	
	function regexEscape(s) {
	    return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
	}
	
	var tokens = {};
	
	function addParseToken (token, callback) {
	    var i, func = callback;
	    if (typeof token === 'string') {
	        token = [token];
	    }
	    if (isNumber(callback)) {
	        func = function (input, array) {
	            array[callback] = toInt(input);
	        };
	    }
	    for (i = 0; i < token.length; i++) {
	        tokens[token[i]] = func;
	    }
	}
	
	function addWeekParseToken (token, callback) {
	    addParseToken(token, function (input, array, config, token) {
	        config._w = config._w || {};
	        callback(input, config._w, config, token);
	    });
	}
	
	function addTimeToArrayFromToken(token, input, config) {
	    if (input != null && hasOwnProp(tokens, token)) {
	        tokens[token](input, config._a, config, token);
	    }
	}
	
	var YEAR = 0;
	var MONTH = 1;
	var DATE = 2;
	var HOUR = 3;
	var MINUTE = 4;
	var SECOND = 5;
	var MILLISECOND = 6;
	var WEEK = 7;
	var WEEKDAY = 8;
	
	var indexOf;
	
	if (Array.prototype.indexOf) {
	    indexOf = Array.prototype.indexOf;
	} else {
	    indexOf = function (o) {
	        // I know
	        var i;
	        for (i = 0; i < this.length; ++i) {
	            if (this[i] === o) {
	                return i;
	            }
	        }
	        return -1;
	    };
	}
	
	var indexOf$1 = indexOf;
	
	function daysInMonth(year, month) {
	    return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
	}
	
	// FORMATTING
	
	addFormatToken('M', ['MM', 2], 'Mo', function () {
	    return this.month() + 1;
	});
	
	addFormatToken('MMM', 0, 0, function (format) {
	    return this.localeData().monthsShort(this, format);
	});
	
	addFormatToken('MMMM', 0, 0, function (format) {
	    return this.localeData().months(this, format);
	});
	
	// ALIASES
	
	addUnitAlias('month', 'M');
	
	// PRIORITY
	
	addUnitPriority('month', 8);
	
	// PARSING
	
	addRegexToken('M',    match1to2);
	addRegexToken('MM',   match1to2, match2);
	addRegexToken('MMM',  function (isStrict, locale) {
	    return locale.monthsShortRegex(isStrict);
	});
	addRegexToken('MMMM', function (isStrict, locale) {
	    return locale.monthsRegex(isStrict);
	});
	
	addParseToken(['M', 'MM'], function (input, array) {
	    array[MONTH] = toInt(input) - 1;
	});
	
	addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
	    var month = config._locale.monthsParse(input, token, config._strict);
	    // if we didn't find a month name, mark the date as invalid.
	    if (month != null) {
	        array[MONTH] = month;
	    } else {
	        getParsingFlags(config).invalidMonth = input;
	    }
	});
	
	// LOCALES
	
	var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
	var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
	function localeMonths (m, format) {
	    if (!m) {
	        return this._months;
	    }
	    return isArray(this._months) ? this._months[m.month()] :
	        this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
	}
	
	var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
	function localeMonthsShort (m, format) {
	    if (!m) {
	        return this._monthsShort;
	    }
	    return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
	        this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
	}
	
	function handleStrictParse(monthName, format, strict) {
	    var i, ii, mom, llc = monthName.toLocaleLowerCase();
	    if (!this._monthsParse) {
	        // this is not used
	        this._monthsParse = [];
	        this._longMonthsParse = [];
	        this._shortMonthsParse = [];
	        for (i = 0; i < 12; ++i) {
	            mom = createUTC([2000, i]);
	            this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
	            this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
	        }
	    }
	
	    if (strict) {
	        if (format === 'MMM') {
	            ii = indexOf$1.call(this._shortMonthsParse, llc);
	            return ii !== -1 ? ii : null;
	        } else {
	            ii = indexOf$1.call(this._longMonthsParse, llc);
	            return ii !== -1 ? ii : null;
	        }
	    } else {
	        if (format === 'MMM') {
	            ii = indexOf$1.call(this._shortMonthsParse, llc);
	            if (ii !== -1) {
	                return ii;
	            }
	            ii = indexOf$1.call(this._longMonthsParse, llc);
	            return ii !== -1 ? ii : null;
	        } else {
	            ii = indexOf$1.call(this._longMonthsParse, llc);
	            if (ii !== -1) {
	                return ii;
	            }
	            ii = indexOf$1.call(this._shortMonthsParse, llc);
	            return ii !== -1 ? ii : null;
	        }
	    }
	}
	
	function localeMonthsParse (monthName, format, strict) {
	    var i, mom, regex;
	
	    if (this._monthsParseExact) {
	        return handleStrictParse.call(this, monthName, format, strict);
	    }
	
	    if (!this._monthsParse) {
	        this._monthsParse = [];
	        this._longMonthsParse = [];
	        this._shortMonthsParse = [];
	    }
	
	    // TODO: add sorting
	    // Sorting makes sure if one month (or abbr) is a prefix of another
	    // see sorting in computeMonthsParse
	    for (i = 0; i < 12; i++) {
	        // make the regex if we don't have it already
	        mom = createUTC([2000, i]);
	        if (strict && !this._longMonthsParse[i]) {
	            this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
	            this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
	        }
	        if (!strict && !this._monthsParse[i]) {
	            regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
	            this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
	        }
	        // test the regex
	        if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
	            return i;
	        } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
	            return i;
	        } else if (!strict && this._monthsParse[i].test(monthName)) {
	            return i;
	        }
	    }
	}
	
	// MOMENTS
	
	function setMonth (mom, value) {
	    var dayOfMonth;
	
	    if (!mom.isValid()) {
	        // No op
	        return mom;
	    }
	
	    if (typeof value === 'string') {
	        if (/^\d+$/.test(value)) {
	            value = toInt(value);
	        } else {
	            value = mom.localeData().monthsParse(value);
	            // TODO: Another silent failure?
	            if (!isNumber(value)) {
	                return mom;
	            }
	        }
	    }
	
	    dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
	    mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
	    return mom;
	}
	
	function getSetMonth (value) {
	    if (value != null) {
	        setMonth(this, value);
	        hooks.updateOffset(this, true);
	        return this;
	    } else {
	        return get(this, 'Month');
	    }
	}
	
	function getDaysInMonth () {
	    return daysInMonth(this.year(), this.month());
	}
	
	var defaultMonthsShortRegex = matchWord;
	function monthsShortRegex (isStrict) {
	    if (this._monthsParseExact) {
	        if (!hasOwnProp(this, '_monthsRegex')) {
	            computeMonthsParse.call(this);
	        }
	        if (isStrict) {
	            return this._monthsShortStrictRegex;
	        } else {
	            return this._monthsShortRegex;
	        }
	    } else {
	        if (!hasOwnProp(this, '_monthsShortRegex')) {
	            this._monthsShortRegex = defaultMonthsShortRegex;
	        }
	        return this._monthsShortStrictRegex && isStrict ?
	            this._monthsShortStrictRegex : this._monthsShortRegex;
	    }
	}
	
	var defaultMonthsRegex = matchWord;
	function monthsRegex (isStrict) {
	    if (this._monthsParseExact) {
	        if (!hasOwnProp(this, '_monthsRegex')) {
	            computeMonthsParse.call(this);
	        }
	        if (isStrict) {
	            return this._monthsStrictRegex;
	        } else {
	            return this._monthsRegex;
	        }
	    } else {
	        if (!hasOwnProp(this, '_monthsRegex')) {
	            this._monthsRegex = defaultMonthsRegex;
	        }
	        return this._monthsStrictRegex && isStrict ?
	            this._monthsStrictRegex : this._monthsRegex;
	    }
	}
	
	function computeMonthsParse () {
	    function cmpLenRev(a, b) {
	        return b.length - a.length;
	    }
	
	    var shortPieces = [], longPieces = [], mixedPieces = [],
	        i, mom;
	    for (i = 0; i < 12; i++) {
	        // make the regex if we don't have it already
	        mom = createUTC([2000, i]);
	        shortPieces.push(this.monthsShort(mom, ''));
	        longPieces.push(this.months(mom, ''));
	        mixedPieces.push(this.months(mom, ''));
	        mixedPieces.push(this.monthsShort(mom, ''));
	    }
	    // Sorting makes sure if one month (or abbr) is a prefix of another it
	    // will match the longer piece.
	    shortPieces.sort(cmpLenRev);
	    longPieces.sort(cmpLenRev);
	    mixedPieces.sort(cmpLenRev);
	    for (i = 0; i < 12; i++) {
	        shortPieces[i] = regexEscape(shortPieces[i]);
	        longPieces[i] = regexEscape(longPieces[i]);
	    }
	    for (i = 0; i < 24; i++) {
	        mixedPieces[i] = regexEscape(mixedPieces[i]);
	    }
	
	    this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
	    this._monthsShortRegex = this._monthsRegex;
	    this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
	    this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
	}
	
	// FORMATTING
	
	addFormatToken('Y', 0, 0, function () {
	    var y = this.year();
	    return y <= 9999 ? '' + y : '+' + y;
	});
	
	addFormatToken(0, ['YY', 2], 0, function () {
	    return this.year() % 100;
	});
	
	addFormatToken(0, ['YYYY',   4],       0, 'year');
	addFormatToken(0, ['YYYYY',  5],       0, 'year');
	addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
	
	// ALIASES
	
	addUnitAlias('year', 'y');
	
	// PRIORITIES
	
	addUnitPriority('year', 1);
	
	// PARSING
	
	addRegexToken('Y',      matchSigned);
	addRegexToken('YY',     match1to2, match2);
	addRegexToken('YYYY',   match1to4, match4);
	addRegexToken('YYYYY',  match1to6, match6);
	addRegexToken('YYYYYY', match1to6, match6);
	
	addParseToken(['YYYYY', 'YYYYYY'], YEAR);
	addParseToken('YYYY', function (input, array) {
	    array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
	});
	addParseToken('YY', function (input, array) {
	    array[YEAR] = hooks.parseTwoDigitYear(input);
	});
	addParseToken('Y', function (input, array) {
	    array[YEAR] = parseInt(input, 10);
	});
	
	// HELPERS
	
	function daysInYear(year) {
	    return isLeapYear(year) ? 366 : 365;
	}
	
	function isLeapYear(year) {
	    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
	}
	
	// HOOKS
	
	hooks.parseTwoDigitYear = function (input) {
	    return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
	};
	
	// MOMENTS
	
	var getSetYear = makeGetSet('FullYear', true);
	
	function getIsLeapYear () {
	    return isLeapYear(this.year());
	}
	
	function createDate (y, m, d, h, M, s, ms) {
	    //can't just apply() to create a date:
	    //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
	    var date = new Date(y, m, d, h, M, s, ms);
	
	    //the date constructor remaps years 0-99 to 1900-1999
	    if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
	        date.setFullYear(y);
	    }
	    return date;
	}
	
	function createUTCDate (y) {
	    var date = new Date(Date.UTC.apply(null, arguments));
	
	    //the Date.UTC function remaps years 0-99 to 1900-1999
	    if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
	        date.setUTCFullYear(y);
	    }
	    return date;
	}
	
	// start-of-first-week - start-of-year
	function firstWeekOffset(year, dow, doy) {
	    var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
	        fwd = 7 + dow - doy,
	        // first-week day local weekday -- which local weekday is fwd
	        fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
	
	    return -fwdlw + fwd - 1;
	}
	
	//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
	function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
	    var localWeekday = (7 + weekday - dow) % 7,
	        weekOffset = firstWeekOffset(year, dow, doy),
	        dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
	        resYear, resDayOfYear;
	
	    if (dayOfYear <= 0) {
	        resYear = year - 1;
	        resDayOfYear = daysInYear(resYear) + dayOfYear;
	    } else if (dayOfYear > daysInYear(year)) {
	        resYear = year + 1;
	        resDayOfYear = dayOfYear - daysInYear(year);
	    } else {
	        resYear = year;
	        resDayOfYear = dayOfYear;
	    }
	
	    return {
	        year: resYear,
	        dayOfYear: resDayOfYear
	    };
	}
	
	function weekOfYear(mom, dow, doy) {
	    var weekOffset = firstWeekOffset(mom.year(), dow, doy),
	        week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
	        resWeek, resYear;
	
	    if (week < 1) {
	        resYear = mom.year() - 1;
	        resWeek = week + weeksInYear(resYear, dow, doy);
	    } else if (week > weeksInYear(mom.year(), dow, doy)) {
	        resWeek = week - weeksInYear(mom.year(), dow, doy);
	        resYear = mom.year() + 1;
	    } else {
	        resYear = mom.year();
	        resWeek = week;
	    }
	
	    return {
	        week: resWeek,
	        year: resYear
	    };
	}
	
	function weeksInYear(year, dow, doy) {
	    var weekOffset = firstWeekOffset(year, dow, doy),
	        weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
	    return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
	}
	
	// FORMATTING
	
	addFormatToken('w', ['ww', 2], 'wo', 'week');
	addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
	
	// ALIASES
	
	addUnitAlias('week', 'w');
	addUnitAlias('isoWeek', 'W');
	
	// PRIORITIES
	
	addUnitPriority('week', 5);
	addUnitPriority('isoWeek', 5);
	
	// PARSING
	
	addRegexToken('w',  match1to2);
	addRegexToken('ww', match1to2, match2);
	addRegexToken('W',  match1to2);
	addRegexToken('WW', match1to2, match2);
	
	addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
	    week[token.substr(0, 1)] = toInt(input);
	});
	
	// HELPERS
	
	// LOCALES
	
	function localeWeek (mom) {
	    return weekOfYear(mom, this._week.dow, this._week.doy).week;
	}
	
	var defaultLocaleWeek = {
	    dow : 0, // Sunday is the first day of the week.
	    doy : 6  // The week that contains Jan 1st is the first week of the year.
	};
	
	function localeFirstDayOfWeek () {
	    return this._week.dow;
	}
	
	function localeFirstDayOfYear () {
	    return this._week.doy;
	}
	
	// MOMENTS
	
	function getSetWeek (input) {
	    var week = this.localeData().week(this);
	    return input == null ? week : this.add((input - week) * 7, 'd');
	}
	
	function getSetISOWeek (input) {
	    var week = weekOfYear(this, 1, 4).week;
	    return input == null ? week : this.add((input - week) * 7, 'd');
	}
	
	// FORMATTING
	
	addFormatToken('d', 0, 'do', 'day');
	
	addFormatToken('dd', 0, 0, function (format) {
	    return this.localeData().weekdaysMin(this, format);
	});
	
	addFormatToken('ddd', 0, 0, function (format) {
	    return this.localeData().weekdaysShort(this, format);
	});
	
	addFormatToken('dddd', 0, 0, function (format) {
	    return this.localeData().weekdays(this, format);
	});
	
	addFormatToken('e', 0, 0, 'weekday');
	addFormatToken('E', 0, 0, 'isoWeekday');
	
	// ALIASES
	
	addUnitAlias('day', 'd');
	addUnitAlias('weekday', 'e');
	addUnitAlias('isoWeekday', 'E');
	
	// PRIORITY
	addUnitPriority('day', 11);
	addUnitPriority('weekday', 11);
	addUnitPriority('isoWeekday', 11);
	
	// PARSING
	
	addRegexToken('d',    match1to2);
	addRegexToken('e',    match1to2);
	addRegexToken('E',    match1to2);
	addRegexToken('dd',   function (isStrict, locale) {
	    return locale.weekdaysMinRegex(isStrict);
	});
	addRegexToken('ddd',   function (isStrict, locale) {
	    return locale.weekdaysShortRegex(isStrict);
	});
	addRegexToken('dddd',   function (isStrict, locale) {
	    return locale.weekdaysRegex(isStrict);
	});
	
	addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
	    var weekday = config._locale.weekdaysParse(input, token, config._strict);
	    // if we didn't get a weekday name, mark the date as invalid
	    if (weekday != null) {
	        week.d = weekday;
	    } else {
	        getParsingFlags(config).invalidWeekday = input;
	    }
	});
	
	addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
	    week[token] = toInt(input);
	});
	
	// HELPERS
	
	function parseWeekday(input, locale) {
	    if (typeof input !== 'string') {
	        return input;
	    }
	
	    if (!isNaN(input)) {
	        return parseInt(input, 10);
	    }
	
	    input = locale.weekdaysParse(input);
	    if (typeof input === 'number') {
	        return input;
	    }
	
	    return null;
	}
	
	function parseIsoWeekday(input, locale) {
	    if (typeof input === 'string') {
	        return locale.weekdaysParse(input) % 7 || 7;
	    }
	    return isNaN(input) ? null : input;
	}
	
	// LOCALES
	
	var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
	function localeWeekdays (m, format) {
	    if (!m) {
	        return this._weekdays;
	    }
	    return isArray(this._weekdays) ? this._weekdays[m.day()] :
	        this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
	}
	
	var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
	function localeWeekdaysShort (m) {
	    return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
	}
	
	var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
	function localeWeekdaysMin (m) {
	    return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
	}
	
	function handleStrictParse$1(weekdayName, format, strict) {
	    var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
	    if (!this._weekdaysParse) {
	        this._weekdaysParse = [];
	        this._shortWeekdaysParse = [];
	        this._minWeekdaysParse = [];
	
	        for (i = 0; i < 7; ++i) {
	            mom = createUTC([2000, 1]).day(i);
	            this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
	            this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
	            this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
	        }
	    }
	
	    if (strict) {
	        if (format === 'dddd') {
	            ii = indexOf$1.call(this._weekdaysParse, llc);
	            return ii !== -1 ? ii : null;
	        } else if (format === 'ddd') {
	            ii = indexOf$1.call(this._shortWeekdaysParse, llc);
	            return ii !== -1 ? ii : null;
	        } else {
	            ii = indexOf$1.call(this._minWeekdaysParse, llc);
	            return ii !== -1 ? ii : null;
	        }
	    } else {
	        if (format === 'dddd') {
	            ii = indexOf$1.call(this._weekdaysParse, llc);
	            if (ii !== -1) {
	                return ii;
	            }
	            ii = indexOf$1.call(this._shortWeekdaysParse, llc);
	            if (ii !== -1) {
	                return ii;
	            }
	            ii = indexOf$1.call(this._minWeekdaysParse, llc);
	            return ii !== -1 ? ii : null;
	        } else if (format === 'ddd') {
	            ii = indexOf$1.call(this._shortWeekdaysParse, llc);
	            if (ii !== -1) {
	                return ii;
	            }
	            ii = indexOf$1.call(this._weekdaysParse, llc);
	            if (ii !== -1) {
	                return ii;
	            }
	            ii = indexOf$1.call(this._minWeekdaysParse, llc);
	            return ii !== -1 ? ii : null;
	        } else {
	            ii = indexOf$1.call(this._minWeekdaysParse, llc);
	            if (ii !== -1) {
	                return ii;
	            }
	            ii = indexOf$1.call(this._weekdaysParse, llc);
	            if (ii !== -1) {
	                return ii;
	            }
	            ii = indexOf$1.call(this._shortWeekdaysParse, llc);
	            return ii !== -1 ? ii : null;
	        }
	    }
	}
	
	function localeWeekdaysParse (weekdayName, format, strict) {
	    var i, mom, regex;
	
	    if (this._weekdaysParseExact) {
	        return handleStrictParse$1.call(this, weekdayName, format, strict);
	    }
	
	    if (!this._weekdaysParse) {
	        this._weekdaysParse = [];
	        this._minWeekdaysParse = [];
	        this._shortWeekdaysParse = [];
	        this._fullWeekdaysParse = [];
	    }
	
	    for (i = 0; i < 7; i++) {
	        // make the regex if we don't have it already
	
	        mom = createUTC([2000, 1]).day(i);
	        if (strict && !this._fullWeekdaysParse[i]) {
	            this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
	            this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
	            this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
	        }
	        if (!this._weekdaysParse[i]) {
	            regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
	            this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
	        }
	        // test the regex
	        if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
	            return i;
	        } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
	            return i;
	        } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
	            return i;
	        } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
	            return i;
	        }
	    }
	}
	
	// MOMENTS
	
	function getSetDayOfWeek (input) {
	    if (!this.isValid()) {
	        return input != null ? this : NaN;
	    }
	    var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
	    if (input != null) {
	        input = parseWeekday(input, this.localeData());
	        return this.add(input - day, 'd');
	    } else {
	        return day;
	    }
	}
	
	function getSetLocaleDayOfWeek (input) {
	    if (!this.isValid()) {
	        return input != null ? this : NaN;
	    }
	    var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
	    return input == null ? weekday : this.add(input - weekday, 'd');
	}
	
	function getSetISODayOfWeek (input) {
	    if (!this.isValid()) {
	        return input != null ? this : NaN;
	    }
	
	    // behaves the same as moment#day except
	    // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
	    // as a setter, sunday should belong to the previous week.
	
	    if (input != null) {
	        var weekday = parseIsoWeekday(input, this.localeData());
	        return this.day(this.day() % 7 ? weekday : weekday - 7);
	    } else {
	        return this.day() || 7;
	    }
	}
	
	var defaultWeekdaysRegex = matchWord;
	function weekdaysRegex (isStrict) {
	    if (this._weekdaysParseExact) {
	        if (!hasOwnProp(this, '_weekdaysRegex')) {
	            computeWeekdaysParse.call(this);
	        }
	        if (isStrict) {
	            return this._weekdaysStrictRegex;
	        } else {
	            return this._weekdaysRegex;
	        }
	    } else {
	        if (!hasOwnProp(this, '_weekdaysRegex')) {
	            this._weekdaysRegex = defaultWeekdaysRegex;
	        }
	        return this._weekdaysStrictRegex && isStrict ?
	            this._weekdaysStrictRegex : this._weekdaysRegex;
	    }
	}
	
	var defaultWeekdaysShortRegex = matchWord;
	function weekdaysShortRegex (isStrict) {
	    if (this._weekdaysParseExact) {
	        if (!hasOwnProp(this, '_weekdaysRegex')) {
	            computeWeekdaysParse.call(this);
	        }
	        if (isStrict) {
	            return this._weekdaysShortStrictRegex;
	        } else {
	            return this._weekdaysShortRegex;
	        }
	    } else {
	        if (!hasOwnProp(this, '_weekdaysShortRegex')) {
	            this._weekdaysShortRegex = defaultWeekdaysShortRegex;
	        }
	        return this._weekdaysShortStrictRegex && isStrict ?
	            this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
	    }
	}
	
	var defaultWeekdaysMinRegex = matchWord;
	function weekdaysMinRegex (isStrict) {
	    if (this._weekdaysParseExact) {
	        if (!hasOwnProp(this, '_weekdaysRegex')) {
	            computeWeekdaysParse.call(this);
	        }
	        if (isStrict) {
	            return this._weekdaysMinStrictRegex;
	        } else {
	            return this._weekdaysMinRegex;
	        }
	    } else {
	        if (!hasOwnProp(this, '_weekdaysMinRegex')) {
	            this._weekdaysMinRegex = defaultWeekdaysMinRegex;
	        }
	        return this._weekdaysMinStrictRegex && isStrict ?
	            this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
	    }
	}
	
	
	function computeWeekdaysParse () {
	    function cmpLenRev(a, b) {
	        return b.length - a.length;
	    }
	
	    var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
	        i, mom, minp, shortp, longp;
	    for (i = 0; i < 7; i++) {
	        // make the regex if we don't have it already
	        mom = createUTC([2000, 1]).day(i);
	        minp = this.weekdaysMin(mom, '');
	        shortp = this.weekdaysShort(mom, '');
	        longp = this.weekdays(mom, '');
	        minPieces.push(minp);
	        shortPieces.push(shortp);
	        longPieces.push(longp);
	        mixedPieces.push(minp);
	        mixedPieces.push(shortp);
	        mixedPieces.push(longp);
	    }
	    // Sorting makes sure if one weekday (or abbr) is a prefix of another it
	    // will match the longer piece.
	    minPieces.sort(cmpLenRev);
	    shortPieces.sort(cmpLenRev);
	    longPieces.sort(cmpLenRev);
	    mixedPieces.sort(cmpLenRev);
	    for (i = 0; i < 7; i++) {
	        shortPieces[i] = regexEscape(shortPieces[i]);
	        longPieces[i] = regexEscape(longPieces[i]);
	        mixedPieces[i] = regexEscape(mixedPieces[i]);
	    }
	
	    this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
	    this._weekdaysShortRegex = this._weekdaysRegex;
	    this._weekdaysMinRegex = this._weekdaysRegex;
	
	    this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
	    this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
	    this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
	}
	
	// FORMATTING
	
	function hFormat() {
	    return this.hours() % 12 || 12;
	}
	
	function kFormat() {
	    return this.hours() || 24;
	}
	
	addFormatToken('H', ['HH', 2], 0, 'hour');
	addFormatToken('h', ['hh', 2], 0, hFormat);
	addFormatToken('k', ['kk', 2], 0, kFormat);
	
	addFormatToken('hmm', 0, 0, function () {
	    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
	});
	
	addFormatToken('hmmss', 0, 0, function () {
	    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
	        zeroFill(this.seconds(), 2);
	});
	
	addFormatToken('Hmm', 0, 0, function () {
	    return '' + this.hours() + zeroFill(this.minutes(), 2);
	});
	
	addFormatToken('Hmmss', 0, 0, function () {
	    return '' + this.hours() + zeroFill(this.minutes(), 2) +
	        zeroFill(this.seconds(), 2);
	});
	
	function meridiem (token, lowercase) {
	    addFormatToken(token, 0, 0, function () {
	        return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
	    });
	}
	
	meridiem('a', true);
	meridiem('A', false);
	
	// ALIASES
	
	addUnitAlias('hour', 'h');
	
	// PRIORITY
	addUnitPriority('hour', 13);
	
	// PARSING
	
	function matchMeridiem (isStrict, locale) {
	    return locale._meridiemParse;
	}
	
	addRegexToken('a',  matchMeridiem);
	addRegexToken('A',  matchMeridiem);
	addRegexToken('H',  match1to2);
	addRegexToken('h',  match1to2);
	addRegexToken('HH', match1to2, match2);
	addRegexToken('hh', match1to2, match2);
	
	addRegexToken('hmm', match3to4);
	addRegexToken('hmmss', match5to6);
	addRegexToken('Hmm', match3to4);
	addRegexToken('Hmmss', match5to6);
	
	addParseToken(['H', 'HH'], HOUR);
	addParseToken(['a', 'A'], function (input, array, config) {
	    config._isPm = config._locale.isPM(input);
	    config._meridiem = input;
	});
	addParseToken(['h', 'hh'], function (input, array, config) {
	    array[HOUR] = toInt(input);
	    getParsingFlags(config).bigHour = true;
	});
	addParseToken('hmm', function (input, array, config) {
	    var pos = input.length - 2;
	    array[HOUR] = toInt(input.substr(0, pos));
	    array[MINUTE] = toInt(input.substr(pos));
	    getParsingFlags(config).bigHour = true;
	});
	addParseToken('hmmss', function (input, array, config) {
	    var pos1 = input.length - 4;
	    var pos2 = input.length - 2;
	    array[HOUR] = toInt(input.substr(0, pos1));
	    array[MINUTE] = toInt(input.substr(pos1, 2));
	    array[SECOND] = toInt(input.substr(pos2));
	    getParsingFlags(config).bigHour = true;
	});
	addParseToken('Hmm', function (input, array, config) {
	    var pos = input.length - 2;
	    array[HOUR] = toInt(input.substr(0, pos));
	    array[MINUTE] = toInt(input.substr(pos));
	});
	addParseToken('Hmmss', function (input, array, config) {
	    var pos1 = input.length - 4;
	    var pos2 = input.length - 2;
	    array[HOUR] = toInt(input.substr(0, pos1));
	    array[MINUTE] = toInt(input.substr(pos1, 2));
	    array[SECOND] = toInt(input.substr(pos2));
	});
	
	// LOCALES
	
	function localeIsPM (input) {
	    // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
	    // Using charAt should be more compatible.
	    return ((input + '').toLowerCase().charAt(0) === 'p');
	}
	
	var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
	function localeMeridiem (hours, minutes, isLower) {
	    if (hours > 11) {
	        return isLower ? 'pm' : 'PM';
	    } else {
	        return isLower ? 'am' : 'AM';
	    }
	}
	
	
	// MOMENTS
	
	// Setting the hour should keep the time, because the user explicitly
	// specified which hour he wants. So trying to maintain the same hour (in
	// a new timezone) makes sense. Adding/subtracting hours does not follow
	// this rule.
	var getSetHour = makeGetSet('Hours', true);
	
	// months
	// week
	// weekdays
	// meridiem
	var baseConfig = {
	    calendar: defaultCalendar,
	    longDateFormat: defaultLongDateFormat,
	    invalidDate: defaultInvalidDate,
	    ordinal: defaultOrdinal,
	    ordinalParse: defaultOrdinalParse,
	    relativeTime: defaultRelativeTime,
	
	    months: defaultLocaleMonths,
	    monthsShort: defaultLocaleMonthsShort,
	
	    week: defaultLocaleWeek,
	
	    weekdays: defaultLocaleWeekdays,
	    weekdaysMin: defaultLocaleWeekdaysMin,
	    weekdaysShort: defaultLocaleWeekdaysShort,
	
	    meridiemParse: defaultLocaleMeridiemParse
	};
	
	// internal storage for locale config files
	var locales = {};
	var localeFamilies = {};
	var globalLocale;
	
	function normalizeLocale(key) {
	    return key ? key.toLowerCase().replace('_', '-') : key;
	}
	
	// pick the locale from the array
	// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
	// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
	function chooseLocale(names) {
	    var i = 0, j, next, locale, split;
	
	    while (i < names.length) {
	        split = normalizeLocale(names[i]).split('-');
	        j = split.length;
	        next = normalizeLocale(names[i + 1]);
	        next = next ? next.split('-') : null;
	        while (j > 0) {
	            locale = loadLocale(split.slice(0, j).join('-'));
	            if (locale) {
	                return locale;
	            }
	            if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
	                //the next array item is better than a shallower substring of this one
	                break;
	            }
	            j--;
	        }
	        i++;
	    }
	    return null;
	}
	
	function loadLocale(name) {
	    var oldLocale = null;
	    // TODO: Find a better way to register and load all the locales in Node
	    if (!locales[name] && (typeof module !== 'undefined') &&
	            module && module.exports) {
	        try {
	            oldLocale = globalLocale._abbr;
	            __jupyter_require__('moment@2.17.1/locale')("./" + name);
	            // because defineLocale currently also sets the global locale, we
	            // want to undo that for lazy loaded locales
	            getSetGlobalLocale(oldLocale);
	        } catch (e) { }
	    }
	    return locales[name];
	}
	
	// This function will load locale and then set the global locale.  If
	// no arguments are passed in, it will simply return the current global
	// locale key.
	function getSetGlobalLocale (key, values) {
	    var data;
	    if (key) {
	        if (isUndefined(values)) {
	            data = getLocale(key);
	        }
	        else {
	            data = defineLocale(key, values);
	        }
	
	        if (data) {
	            // moment.duration._locale = moment._locale = data;
	            globalLocale = data;
	        }
	    }
	
	    return globalLocale._abbr;
	}
	
	function defineLocale (name, config) {
	    if (config !== null) {
	        var parentConfig = baseConfig;
	        config.abbr = name;
	        if (locales[name] != null) {
	            deprecateSimple('defineLocaleOverride',
	                    'use moment.updateLocale(localeName, config) to change ' +
	                    'an existing locale. moment.defineLocale(localeName, ' +
	                    'config) should only be used for creating a new locale ' +
	                    'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
	            parentConfig = locales[name]._config;
	        } else if (config.parentLocale != null) {
	            if (locales[config.parentLocale] != null) {
	                parentConfig = locales[config.parentLocale]._config;
	            } else {
	                if (!localeFamilies[config.parentLocale]) {
	                    localeFamilies[config.parentLocale] = [];
	                }
	                localeFamilies[config.parentLocale].push({
	                    name: name,
	                    config: config
	                });
	                return null;
	            }
	        }
	        locales[name] = new Locale(mergeConfigs(parentConfig, config));
	
	        if (localeFamilies[name]) {
	            localeFamilies[name].forEach(function (x) {
	                defineLocale(x.name, x.config);
	            });
	        }
	
	        // backwards compat for now: also set the locale
	        // make sure we set the locale AFTER all child locales have been
	        // created, so we won't end up with the child locale set.
	        getSetGlobalLocale(name);
	
	
	        return locales[name];
	    } else {
	        // useful for testing
	        delete locales[name];
	        return null;
	    }
	}
	
	function updateLocale(name, config) {
	    if (config != null) {
	        var locale, parentConfig = baseConfig;
	        // MERGE
	        if (locales[name] != null) {
	            parentConfig = locales[name]._config;
	        }
	        config = mergeConfigs(parentConfig, config);
	        locale = new Locale(config);
	        locale.parentLocale = locales[name];
	        locales[name] = locale;
	
	        // backwards compat for now: also set the locale
	        getSetGlobalLocale(name);
	    } else {
	        // pass null for config to unupdate, useful for tests
	        if (locales[name] != null) {
	            if (locales[name].parentLocale != null) {
	                locales[name] = locales[name].parentLocale;
	            } else if (locales[name] != null) {
	                delete locales[name];
	            }
	        }
	    }
	    return locales[name];
	}
	
	// returns locale data
	function getLocale (key) {
	    var locale;
	
	    if (key && key._locale && key._locale._abbr) {
	        key = key._locale._abbr;
	    }
	
	    if (!key) {
	        return globalLocale;
	    }
	
	    if (!isArray(key)) {
	        //short-circuit everything else
	        locale = loadLocale(key);
	        if (locale) {
	            return locale;
	        }
	        key = [key];
	    }
	
	    return chooseLocale(key);
	}
	
	function listLocales() {
	    return keys$1(locales);
	}
	
	function checkOverflow (m) {
	    var overflow;
	    var a = m._a;
	
	    if (a && getParsingFlags(m).overflow === -2) {
	        overflow =
	            a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
	            a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
	            a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
	            a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
	            a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
	            a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
	            -1;
	
	        if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
	            overflow = DATE;
	        }
	        if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
	            overflow = WEEK;
	        }
	        if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
	            overflow = WEEKDAY;
	        }
	
	        getParsingFlags(m).overflow = overflow;
	    }
	
	    return m;
	}
	
	// iso 8601 regex
	// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
	var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
	var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
	
	var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
	
	var isoDates = [
	    ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
	    ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
	    ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
	    ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
	    ['YYYY-DDD', /\d{4}-\d{3}/],
	    ['YYYY-MM', /\d{4}-\d\d/, false],
	    ['YYYYYYMMDD', /[+-]\d{10}/],
	    ['YYYYMMDD', /\d{8}/],
	    // YYYYMM is NOT allowed by the standard
	    ['GGGG[W]WWE', /\d{4}W\d{3}/],
	    ['GGGG[W]WW', /\d{4}W\d{2}/, false],
	    ['YYYYDDD', /\d{7}/]
	];
	
	// iso time formats and regexes
	var isoTimes = [
	    ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
	    ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
	    ['HH:mm:ss', /\d\d:\d\d:\d\d/],
	    ['HH:mm', /\d\d:\d\d/],
	    ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
	    ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
	    ['HHmmss', /\d\d\d\d\d\d/],
	    ['HHmm', /\d\d\d\d/],
	    ['HH', /\d\d/]
	];
	
	var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
	
	// date from iso format
	function configFromISO(config) {
	    var i, l,
	        string = config._i,
	        match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
	        allowTime, dateFormat, timeFormat, tzFormat;
	
	    if (match) {
	        getParsingFlags(config).iso = true;
	
	        for (i = 0, l = isoDates.length; i < l; i++) {
	            if (isoDates[i][1].exec(match[1])) {
	                dateFormat = isoDates[i][0];
	                allowTime = isoDates[i][2] !== false;
	                break;
	            }
	        }
	        if (dateFormat == null) {
	            config._isValid = false;
	            return;
	        }
	        if (match[3]) {
	            for (i = 0, l = isoTimes.length; i < l; i++) {
	                if (isoTimes[i][1].exec(match[3])) {
	                    // match[2] should be 'T' or space
	                    timeFormat = (match[2] || ' ') + isoTimes[i][0];
	                    break;
	                }
	            }
	            if (timeFormat == null) {
	                config._isValid = false;
	                return;
	            }
	        }
	        if (!allowTime && timeFormat != null) {
	            config._isValid = false;
	            return;
	        }
	        if (match[4]) {
	            if (tzRegex.exec(match[4])) {
	                tzFormat = 'Z';
	            } else {
	                config._isValid = false;
	                return;
	            }
	        }
	        config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
	        configFromStringAndFormat(config);
	    } else {
	        config._isValid = false;
	    }
	}
	
	// date from iso format or fallback
	function configFromString(config) {
	    var matched = aspNetJsonRegex.exec(config._i);
	
	    if (matched !== null) {
	        config._d = new Date(+matched[1]);
	        return;
	    }
	
	    configFromISO(config);
	    if (config._isValid === false) {
	        delete config._isValid;
	        hooks.createFromInputFallback(config);
	    }
	}
	
	hooks.createFromInputFallback = deprecate(
	    'value provided is not in a recognized ISO format. moment construction falls back to js Date(), ' +
	    'which is not reliable across all browsers and versions. Non ISO date formats are ' +
	    'discouraged and will be removed in an upcoming major release. Please refer to ' +
	    'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
	    function (config) {
	        config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
	    }
	);
	
	// Pick the first defined of two or three arguments.
	function defaults(a, b, c) {
	    if (a != null) {
	        return a;
	    }
	    if (b != null) {
	        return b;
	    }
	    return c;
	}
	
	function currentDateArray(config) {
	    // hooks is actually the exported moment object
	    var nowValue = new Date(hooks.now());
	    if (config._useUTC) {
	        return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
	    }
	    return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
	}
	
	// convert an array to a date.
	// the array should mirror the parameters below
	// note: all values past the year are optional and will default to the lowest possible value.
	// [year, month, day , hour, minute, second, millisecond]
	function configFromArray (config) {
	    var i, date, input = [], currentDate, yearToUse;
	
	    if (config._d) {
	        return;
	    }
	
	    currentDate = currentDateArray(config);
	
	    //compute day of the year from weeks and weekdays
	    if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
	        dayOfYearFromWeekInfo(config);
	    }
	
	    //if the day of the year is set, figure out what it is
	    if (config._dayOfYear) {
	        yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
	
	        if (config._dayOfYear > daysInYear(yearToUse)) {
	            getParsingFlags(config)._overflowDayOfYear = true;
	        }
	
	        date = createUTCDate(yearToUse, 0, config._dayOfYear);
	        config._a[MONTH] = date.getUTCMonth();
	        config._a[DATE] = date.getUTCDate();
	    }
	
	    // Default to current date.
	    // * if no year, month, day of month are given, default to today
	    // * if day of month is given, default month and year
	    // * if month is given, default only year
	    // * if year is given, don't default anything
	    for (i = 0; i < 3 && config._a[i] == null; ++i) {
	        config._a[i] = input[i] = currentDate[i];
	    }
	
	    // Zero out whatever was not defaulted, including time
	    for (; i < 7; i++) {
	        config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
	    }
	
	    // Check for 24:00:00.000
	    if (config._a[HOUR] === 24 &&
	            config._a[MINUTE] === 0 &&
	            config._a[SECOND] === 0 &&
	            config._a[MILLISECOND] === 0) {
	        config._nextDay = true;
	        config._a[HOUR] = 0;
	    }
	
	    config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
	    // Apply timezone offset from input. The actual utcOffset can be changed
	    // with parseZone.
	    if (config._tzm != null) {
	        config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
	    }
	
	    if (config._nextDay) {
	        config._a[HOUR] = 24;
	    }
	}
	
	function dayOfYearFromWeekInfo(config) {
	    var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
	
	    w = config._w;
	    if (w.GG != null || w.W != null || w.E != null) {
	        dow = 1;
	        doy = 4;
	
	        // TODO: We need to take the current isoWeekYear, but that depends on
	        // how we interpret now (local, utc, fixed offset). So create
	        // a now version of current config (take local/utc/offset flags, and
	        // create now).
	        weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
	        week = defaults(w.W, 1);
	        weekday = defaults(w.E, 1);
	        if (weekday < 1 || weekday > 7) {
	            weekdayOverflow = true;
	        }
	    } else {
	        dow = config._locale._week.dow;
	        doy = config._locale._week.doy;
	
	        var curWeek = weekOfYear(createLocal(), dow, doy);
	
	        weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
	
	        // Default to current week.
	        week = defaults(w.w, curWeek.week);
	
	        if (w.d != null) {
	            // weekday -- low day numbers are considered next week
	            weekday = w.d;
	            if (weekday < 0 || weekday > 6) {
	                weekdayOverflow = true;
	            }
	        } else if (w.e != null) {
	            // local weekday -- counting starts from begining of week
	            weekday = w.e + dow;
	            if (w.e < 0 || w.e > 6) {
	                weekdayOverflow = true;
	            }
	        } else {
	            // default to begining of week
	            weekday = dow;
	        }
	    }
	    if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
	        getParsingFlags(config)._overflowWeeks = true;
	    } else if (weekdayOverflow != null) {
	        getParsingFlags(config)._overflowWeekday = true;
	    } else {
	        temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
	        config._a[YEAR] = temp.year;
	        config._dayOfYear = temp.dayOfYear;
	    }
	}
	
	// constant that refers to the ISO standard
	hooks.ISO_8601 = function () {};
	
	// date from string and format string
	function configFromStringAndFormat(config) {
	    // TODO: Move this to another part of the creation flow to prevent circular deps
	    if (config._f === hooks.ISO_8601) {
	        configFromISO(config);
	        return;
	    }
	
	    config._a = [];
	    getParsingFlags(config).empty = true;
	
	    // This array is used to make a Date, either with `new Date` or `Date.UTC`
	    var string = '' + config._i,
	        i, parsedInput, tokens, token, skipped,
	        stringLength = string.length,
	        totalParsedInputLength = 0;
	
	    tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
	
	    for (i = 0; i < tokens.length; i++) {
	        token = tokens[i];
	        parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
	        // console.log('token', token, 'parsedInput', parsedInput,
	        //         'regex', getParseRegexForToken(token, config));
	        if (parsedInput) {
	            skipped = string.substr(0, string.indexOf(parsedInput));
	            if (skipped.length > 0) {
	                getParsingFlags(config).unusedInput.push(skipped);
	            }
	            string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
	            totalParsedInputLength += parsedInput.length;
	        }
	        // don't parse if it's not a known token
	        if (formatTokenFunctions[token]) {
	            if (parsedInput) {
	                getParsingFlags(config).empty = false;
	            }
	            else {
	                getParsingFlags(config).unusedTokens.push(token);
	            }
	            addTimeToArrayFromToken(token, parsedInput, config);
	        }
	        else if (config._strict && !parsedInput) {
	            getParsingFlags(config).unusedTokens.push(token);
	        }
	    }
	
	    // add remaining unparsed input length to the string
	    getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
	    if (string.length > 0) {
	        getParsingFlags(config).unusedInput.push(string);
	    }
	
	    // clear _12h flag if hour is <= 12
	    if (config._a[HOUR] <= 12 &&
	        getParsingFlags(config).bigHour === true &&
	        config._a[HOUR] > 0) {
	        getParsingFlags(config).bigHour = undefined;
	    }
	
	    getParsingFlags(config).parsedDateParts = config._a.slice(0);
	    getParsingFlags(config).meridiem = config._meridiem;
	    // handle meridiem
	    config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
	
	    configFromArray(config);
	    checkOverflow(config);
	}
	
	
	function meridiemFixWrap (locale, hour, meridiem) {
	    var isPm;
	
	    if (meridiem == null) {
	        // nothing to do
	        return hour;
	    }
	    if (locale.meridiemHour != null) {
	        return locale.meridiemHour(hour, meridiem);
	    } else if (locale.isPM != null) {
	        // Fallback
	        isPm = locale.isPM(meridiem);
	        if (isPm && hour < 12) {
	            hour += 12;
	        }
	        if (!isPm && hour === 12) {
	            hour = 0;
	        }
	        return hour;
	    } else {
	        // this is not supposed to happen
	        return hour;
	    }
	}
	
	// date from string and array of format strings
	function configFromStringAndArray(config) {
	    var tempConfig,
	        bestMoment,
	
	        scoreToBeat,
	        i,
	        currentScore;
	
	    if (config._f.length === 0) {
	        getParsingFlags(config).invalidFormat = true;
	        config._d = new Date(NaN);
	        return;
	    }
	
	    for (i = 0; i < config._f.length; i++) {
	        currentScore = 0;
	        tempConfig = copyConfig({}, config);
	        if (config._useUTC != null) {
	            tempConfig._useUTC = config._useUTC;
	        }
	        tempConfig._f = config._f[i];
	        configFromStringAndFormat(tempConfig);
	
	        if (!isValid(tempConfig)) {
	            continue;
	        }
	
	        // if there is any input that was not parsed add a penalty for that format
	        currentScore += getParsingFlags(tempConfig).charsLeftOver;
	
	        //or tokens
	        currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
	
	        getParsingFlags(tempConfig).score = currentScore;
	
	        if (scoreToBeat == null || currentScore < scoreToBeat) {
	            scoreToBeat = currentScore;
	            bestMoment = tempConfig;
	        }
	    }
	
	    extend(config, bestMoment || tempConfig);
	}
	
	function configFromObject(config) {
	    if (config._d) {
	        return;
	    }
	
	    var i = normalizeObjectUnits(config._i);
	    config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
	        return obj && parseInt(obj, 10);
	    });
	
	    configFromArray(config);
	}
	
	function createFromConfig (config) {
	    var res = new Moment(checkOverflow(prepareConfig(config)));
	    if (res._nextDay) {
	        // Adding is smart enough around DST
	        res.add(1, 'd');
	        res._nextDay = undefined;
	    }
	
	    return res;
	}
	
	function prepareConfig (config) {
	    var input = config._i,
	        format = config._f;
	
	    config._locale = config._locale || getLocale(config._l);
	
	    if (input === null || (format === undefined && input === '')) {
	        return createInvalid({nullInput: true});
	    }
	
	    if (typeof input === 'string') {
	        config._i = input = config._locale.preparse(input);
	    }
	
	    if (isMoment(input)) {
	        return new Moment(checkOverflow(input));
	    } else if (isDate(input)) {
	        config._d = input;
	    } else if (isArray(format)) {
	        configFromStringAndArray(config);
	    } else if (format) {
	        configFromStringAndFormat(config);
	    }  else {
	        configFromInput(config);
	    }
	
	    if (!isValid(config)) {
	        config._d = null;
	    }
	
	    return config;
	}
	
	function configFromInput(config) {
	    var input = config._i;
	    if (input === undefined) {
	        config._d = new Date(hooks.now());
	    } else if (isDate(input)) {
	        config._d = new Date(input.valueOf());
	    } else if (typeof input === 'string') {
	        configFromString(config);
	    } else if (isArray(input)) {
	        config._a = map(input.slice(0), function (obj) {
	            return parseInt(obj, 10);
	        });
	        configFromArray(config);
	    } else if (typeof(input) === 'object') {
	        configFromObject(config);
	    } else if (isNumber(input)) {
	        // from milliseconds
	        config._d = new Date(input);
	    } else {
	        hooks.createFromInputFallback(config);
	    }
	}
	
	function createLocalOrUTC (input, format, locale, strict, isUTC) {
	    var c = {};
	
	    if (locale === true || locale === false) {
	        strict = locale;
	        locale = undefined;
	    }
	
	    if ((isObject(input) && isObjectEmpty(input)) ||
	            (isArray(input) && input.length === 0)) {
	        input = undefined;
	    }
	    // object construction must be done this way.
	    // https://github.com/moment/moment/issues/1423
	    c._isAMomentObject = true;
	    c._useUTC = c._isUTC = isUTC;
	    c._l = locale;
	    c._i = input;
	    c._f = format;
	    c._strict = strict;
	
	    return createFromConfig(c);
	}
	
	function createLocal (input, format, locale, strict) {
	    return createLocalOrUTC(input, format, locale, strict, false);
	}
	
	var prototypeMin = deprecate(
	    'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
	    function () {
	        var other = createLocal.apply(null, arguments);
	        if (this.isValid() && other.isValid()) {
	            return other < this ? this : other;
	        } else {
	            return createInvalid();
	        }
	    }
	);
	
	var prototypeMax = deprecate(
	    'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
	    function () {
	        var other = createLocal.apply(null, arguments);
	        if (this.isValid() && other.isValid()) {
	            return other > this ? this : other;
	        } else {
	            return createInvalid();
	        }
	    }
	);
	
	// Pick a moment m from moments so that m[fn](other) is true for all
	// other. This relies on the function fn to be transitive.
	//
	// moments should either be an array of moment objects or an array, whose
	// first element is an array of moment objects.
	function pickBy(fn, moments) {
	    var res, i;
	    if (moments.length === 1 && isArray(moments[0])) {
	        moments = moments[0];
	    }
	    if (!moments.length) {
	        return createLocal();
	    }
	    res = moments[0];
	    for (i = 1; i < moments.length; ++i) {
	        if (!moments[i].isValid() || moments[i][fn](res)) {
	            res = moments[i];
	        }
	    }
	    return res;
	}
	
	// TODO: Use [].sort instead?
	function min () {
	    var args = [].slice.call(arguments, 0);
	
	    return pickBy('isBefore', args);
	}
	
	function max () {
	    var args = [].slice.call(arguments, 0);
	
	    return pickBy('isAfter', args);
	}
	
	var now = function () {
	    return Date.now ? Date.now() : +(new Date());
	};
	
	function Duration (duration) {
	    var normalizedInput = normalizeObjectUnits(duration),
	        years = normalizedInput.year || 0,
	        quarters = normalizedInput.quarter || 0,
	        months = normalizedInput.month || 0,
	        weeks = normalizedInput.week || 0,
	        days = normalizedInput.day || 0,
	        hours = normalizedInput.hour || 0,
	        minutes = normalizedInput.minute || 0,
	        seconds = normalizedInput.second || 0,
	        milliseconds = normalizedInput.millisecond || 0;
	
	    // representation for dateAddRemove
	    this._milliseconds = +milliseconds +
	        seconds * 1e3 + // 1000
	        minutes * 6e4 + // 1000 * 60
	        hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
	    // Because of dateAddRemove treats 24 hours as different from a
	    // day when working around DST, we need to store them separately
	    this._days = +days +
	        weeks * 7;
	    // It is impossible translate months into days without knowing
	    // which months you are are talking about, so we have to store
	    // it separately.
	    this._months = +months +
	        quarters * 3 +
	        years * 12;
	
	    this._data = {};
	
	    this._locale = getLocale();
	
	    this._bubble();
	}
	
	function isDuration (obj) {
	    return obj instanceof Duration;
	}
	
	function absRound (number) {
	    if (number < 0) {
	        return Math.round(-1 * number) * -1;
	    } else {
	        return Math.round(number);
	    }
	}
	
	// FORMATTING
	
	function offset (token, separator) {
	    addFormatToken(token, 0, 0, function () {
	        var offset = this.utcOffset();
	        var sign = '+';
	        if (offset < 0) {
	            offset = -offset;
	            sign = '-';
	        }
	        return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
	    });
	}
	
	offset('Z', ':');
	offset('ZZ', '');
	
	// PARSING
	
	addRegexToken('Z',  matchShortOffset);
	addRegexToken('ZZ', matchShortOffset);
	addParseToken(['Z', 'ZZ'], function (input, array, config) {
	    config._useUTC = true;
	    config._tzm = offsetFromString(matchShortOffset, input);
	});
	
	// HELPERS
	
	// timezone chunker
	// '+10:00' > ['10',  '00']
	// '-1530'  > ['-15', '30']
	var chunkOffset = /([\+\-]|\d\d)/gi;
	
	function offsetFromString(matcher, string) {
	    var matches = (string || '').match(matcher);
	
	    if (matches === null) {
	        return null;
	    }
	
	    var chunk   = matches[matches.length - 1] || [];
	    var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
	    var minutes = +(parts[1] * 60) + toInt(parts[2]);
	
	    return minutes === 0 ?
	      0 :
	      parts[0] === '+' ? minutes : -minutes;
	}
	
	// Return a moment from input, that is local/utc/zone equivalent to model.
	function cloneWithOffset(input, model) {
	    var res, diff;
	    if (model._isUTC) {
	        res = model.clone();
	        diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
	        // Use low-level api, because this fn is low-level api.
	        res._d.setTime(res._d.valueOf() + diff);
	        hooks.updateOffset(res, false);
	        return res;
	    } else {
	        return createLocal(input).local();
	    }
	}
	
	function getDateOffset (m) {
	    // On Firefox.24 Date#getTimezoneOffset returns a floating point.
	    // https://github.com/moment/moment/pull/1871
	    return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
	}
	
	// HOOKS
	
	// This function will be called whenever a moment is mutated.
	// It is intended to keep the offset in sync with the timezone.
	hooks.updateOffset = function () {};
	
	// MOMENTS
	
	// keepLocalTime = true means only change the timezone, without
	// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
	// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
	// +0200, so we adjust the time as needed, to be valid.
	//
	// Keeping the time actually adds/subtracts (one hour)
	// from the actual represented time. That is why we call updateOffset
	// a second time. In case it wants us to change the offset again
	// _changeInProgress == true case, then we have to adjust, because
	// there is no such time in the given timezone.
	function getSetOffset (input, keepLocalTime) {
	    var offset = this._offset || 0,
	        localAdjust;
	    if (!this.isValid()) {
	        return input != null ? this : NaN;
	    }
	    if (input != null) {
	        if (typeof input === 'string') {
	            input = offsetFromString(matchShortOffset, input);
	            if (input === null) {
	                return this;
	            }
	        } else if (Math.abs(input) < 16) {
	            input = input * 60;
	        }
	        if (!this._isUTC && keepLocalTime) {
	            localAdjust = getDateOffset(this);
	        }
	        this._offset = input;
	        this._isUTC = true;
	        if (localAdjust != null) {
	            this.add(localAdjust, 'm');
	        }
	        if (offset !== input) {
	            if (!keepLocalTime || this._changeInProgress) {
	                addSubtract(this, createDuration(input - offset, 'm'), 1, false);
	            } else if (!this._changeInProgress) {
	                this._changeInProgress = true;
	                hooks.updateOffset(this, true);
	                this._changeInProgress = null;
	            }
	        }
	        return this;
	    } else {
	        return this._isUTC ? offset : getDateOffset(this);
	    }
	}
	
	function getSetZone (input, keepLocalTime) {
	    if (input != null) {
	        if (typeof input !== 'string') {
	            input = -input;
	        }
	
	        this.utcOffset(input, keepLocalTime);
	
	        return this;
	    } else {
	        return -this.utcOffset();
	    }
	}
	
	function setOffsetToUTC (keepLocalTime) {
	    return this.utcOffset(0, keepLocalTime);
	}
	
	function setOffsetToLocal (keepLocalTime) {
	    if (this._isUTC) {
	        this.utcOffset(0, keepLocalTime);
	        this._isUTC = false;
	
	        if (keepLocalTime) {
	            this.subtract(getDateOffset(this), 'm');
	        }
	    }
	    return this;
	}
	
	function setOffsetToParsedOffset () {
	    if (this._tzm != null) {
	        this.utcOffset(this._tzm);
	    } else if (typeof this._i === 'string') {
	        var tZone = offsetFromString(matchOffset, this._i);
	        if (tZone != null) {
	            this.utcOffset(tZone);
	        }
	        else {
	            this.utcOffset(0, true);
	        }
	    }
	    return this;
	}
	
	function hasAlignedHourOffset (input) {
	    if (!this.isValid()) {
	        return false;
	    }
	    input = input ? createLocal(input).utcOffset() : 0;
	
	    return (this.utcOffset() - input) % 60 === 0;
	}
	
	function isDaylightSavingTime () {
	    return (
	        this.utcOffset() > this.clone().month(0).utcOffset() ||
	        this.utcOffset() > this.clone().month(5).utcOffset()
	    );
	}
	
	function isDaylightSavingTimeShifted () {
	    if (!isUndefined(this._isDSTShifted)) {
	        return this._isDSTShifted;
	    }
	
	    var c = {};
	
	    copyConfig(c, this);
	    c = prepareConfig(c);
	
	    if (c._a) {
	        var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
	        this._isDSTShifted = this.isValid() &&
	            compareArrays(c._a, other.toArray()) > 0;
	    } else {
	        this._isDSTShifted = false;
	    }
	
	    return this._isDSTShifted;
	}
	
	function isLocal () {
	    return this.isValid() ? !this._isUTC : false;
	}
	
	function isUtcOffset () {
	    return this.isValid() ? this._isUTC : false;
	}
	
	function isUtc () {
	    return this.isValid() ? this._isUTC && this._offset === 0 : false;
	}
	
	// ASP.NET json date format regex
	var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
	
	// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
	// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
	// and further modified to allow for strings containing both week and day
	var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;
	
	function createDuration (input, key) {
	    var duration = input,
	        // matching against regexp is expensive, do it on demand
	        match = null,
	        sign,
	        ret,
	        diffRes;
	
	    if (isDuration(input)) {
	        duration = {
	            ms : input._milliseconds,
	            d  : input._days,
	            M  : input._months
	        };
	    } else if (isNumber(input)) {
	        duration = {};
	        if (key) {
	            duration[key] = input;
	        } else {
	            duration.milliseconds = input;
	        }
	    } else if (!!(match = aspNetRegex.exec(input))) {
	        sign = (match[1] === '-') ? -1 : 1;
	        duration = {
	            y  : 0,
	            d  : toInt(match[DATE])                         * sign,
	            h  : toInt(match[HOUR])                         * sign,
	            m  : toInt(match[MINUTE])                       * sign,
	            s  : toInt(match[SECOND])                       * sign,
	            ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
	        };
	    } else if (!!(match = isoRegex.exec(input))) {
	        sign = (match[1] === '-') ? -1 : 1;
	        duration = {
	            y : parseIso(match[2], sign),
	            M : parseIso(match[3], sign),
	            w : parseIso(match[4], sign),
	            d : parseIso(match[5], sign),
	            h : parseIso(match[6], sign),
	            m : parseIso(match[7], sign),
	            s : parseIso(match[8], sign)
	        };
	    } else if (duration == null) {// checks for null or undefined
	        duration = {};
	    } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
	        diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
	
	        duration = {};
	        duration.ms = diffRes.milliseconds;
	        duration.M = diffRes.months;
	    }
	
	    ret = new Duration(duration);
	
	    if (isDuration(input) && hasOwnProp(input, '_locale')) {
	        ret._locale = input._locale;
	    }
	
	    return ret;
	}
	
	createDuration.fn = Duration.prototype;
	
	function parseIso (inp, sign) {
	    // We'd normally use ~~inp for this, but unfortunately it also
	    // converts floats to ints.
	    // inp may be undefined, so careful calling replace on it.
	    var res = inp && parseFloat(inp.replace(',', '.'));
	    // apply sign while we're at it
	    return (isNaN(res) ? 0 : res) * sign;
	}
	
	function positiveMomentsDifference(base, other) {
	    var res = {milliseconds: 0, months: 0};
	
	    res.months = other.month() - base.month() +
	        (other.year() - base.year()) * 12;
	    if (base.clone().add(res.months, 'M').isAfter(other)) {
	        --res.months;
	    }
	
	    res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
	
	    return res;
	}
	
	function momentsDifference(base, other) {
	    var res;
	    if (!(base.isValid() && other.isValid())) {
	        return {milliseconds: 0, months: 0};
	    }
	
	    other = cloneWithOffset(other, base);
	    if (base.isBefore(other)) {
	        res = positiveMomentsDifference(base, other);
	    } else {
	        res = positiveMomentsDifference(other, base);
	        res.milliseconds = -res.milliseconds;
	        res.months = -res.months;
	    }
	
	    return res;
	}
	
	// TODO: remove 'name' arg after deprecation is removed
	function createAdder(direction, name) {
	    return function (val, period) {
	        var dur, tmp;
	        //invert the arguments, but complain about it
	        if (period !== null && !isNaN(+period)) {
	            deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
	            'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
	            tmp = val; val = period; period = tmp;
	        }
	
	        val = typeof val === 'string' ? +val : val;
	        dur = createDuration(val, period);
	        addSubtract(this, dur, direction);
	        return this;
	    };
	}
	
	function addSubtract (mom, duration, isAdding, updateOffset) {
	    var milliseconds = duration._milliseconds,
	        days = absRound(duration._days),
	        months = absRound(duration._months);
	
	    if (!mom.isValid()) {
	        // No op
	        return;
	    }
	
	    updateOffset = updateOffset == null ? true : updateOffset;
	
	    if (milliseconds) {
	        mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
	    }
	    if (days) {
	        set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
	    }
	    if (months) {
	        setMonth(mom, get(mom, 'Month') + months * isAdding);
	    }
	    if (updateOffset) {
	        hooks.updateOffset(mom, days || months);
	    }
	}
	
	var add      = createAdder(1, 'add');
	var subtract = createAdder(-1, 'subtract');
	
	function getCalendarFormat(myMoment, now) {
	    var diff = myMoment.diff(now, 'days', true);
	    return diff < -6 ? 'sameElse' :
	            diff < -1 ? 'lastWeek' :
	            diff < 0 ? 'lastDay' :
	            diff < 1 ? 'sameDay' :
	            diff < 2 ? 'nextDay' :
	            diff < 7 ? 'nextWeek' : 'sameElse';
	}
	
	function calendar$1 (time, formats) {
	    // We want to compare the start of today, vs this.
	    // Getting start-of-today depends on whether we're local/utc/offset or not.
	    var now = time || createLocal(),
	        sod = cloneWithOffset(now, this).startOf('day'),
	        format = hooks.calendarFormat(this, sod) || 'sameElse';
	
	    var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
	
	    return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
	}
	
	function clone () {
	    return new Moment(this);
	}
	
	function isAfter (input, units) {
	    var localInput = isMoment(input) ? input : createLocal(input);
	    if (!(this.isValid() && localInput.isValid())) {
	        return false;
	    }
	    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
	    if (units === 'millisecond') {
	        return this.valueOf() > localInput.valueOf();
	    } else {
	        return localInput.valueOf() < this.clone().startOf(units).valueOf();
	    }
	}
	
	function isBefore (input, units) {
	    var localInput = isMoment(input) ? input : createLocal(input);
	    if (!(this.isValid() && localInput.isValid())) {
	        return false;
	    }
	    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
	    if (units === 'millisecond') {
	        return this.valueOf() < localInput.valueOf();
	    } else {
	        return this.clone().endOf(units).valueOf() < localInput.valueOf();
	    }
	}
	
	function isBetween (from, to, units, inclusivity) {
	    inclusivity = inclusivity || '()';
	    return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
	        (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
	}
	
	function isSame (input, units) {
	    var localInput = isMoment(input) ? input : createLocal(input),
	        inputMs;
	    if (!(this.isValid() && localInput.isValid())) {
	        return false;
	    }
	    units = normalizeUnits(units || 'millisecond');
	    if (units === 'millisecond') {
	        return this.valueOf() === localInput.valueOf();
	    } else {
	        inputMs = localInput.valueOf();
	        return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
	    }
	}
	
	function isSameOrAfter (input, units) {
	    return this.isSame(input, units) || this.isAfter(input,units);
	}
	
	function isSameOrBefore (input, units) {
	    return this.isSame(input, units) || this.isBefore(input,units);
	}
	
	function diff (input, units, asFloat) {
	    var that,
	        zoneDelta,
	        delta, output;
	
	    if (!this.isValid()) {
	        return NaN;
	    }
	
	    that = cloneWithOffset(input, this);
	
	    if (!that.isValid()) {
	        return NaN;
	    }
	
	    zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
	
	    units = normalizeUnits(units);
	
	    if (units === 'year' || units === 'month' || units === 'quarter') {
	        output = monthDiff(this, that);
	        if (units === 'quarter') {
	            output = output / 3;
	        } else if (units === 'year') {
	            output = output / 12;
	        }
	    } else {
	        delta = this - that;
	        output = units === 'second' ? delta / 1e3 : // 1000
	            units === 'minute' ? delta / 6e4 : // 1000 * 60
	            units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
	            units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
	            units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
	            delta;
	    }
	    return asFloat ? output : absFloor(output);
	}
	
	function monthDiff (a, b) {
	    // difference in months
	    var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
	        // b is in (anchor - 1 month, anchor + 1 month)
	        anchor = a.clone().add(wholeMonthDiff, 'months'),
	        anchor2, adjust;
	
	    if (b - anchor < 0) {
	        anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
	        // linear across the month
	        adjust = (b - anchor) / (anchor - anchor2);
	    } else {
	        anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
	        // linear across the month
	        adjust = (b - anchor) / (anchor2 - anchor);
	    }
	
	    //check for negative zero, return zero if negative zero
	    return -(wholeMonthDiff + adjust) || 0;
	}
	
	hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
	hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
	
	function toString () {
	    return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
	}
	
	function toISOString () {
	    var m = this.clone().utc();
	    if (0 < m.year() && m.year() <= 9999) {
	        if (isFunction(Date.prototype.toISOString)) {
	            // native implementation is ~50x faster, use it when we can
	            return this.toDate().toISOString();
	        } else {
	            return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
	        }
	    } else {
	        return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
	    }
	}
	
	/**
	 * Return a human readable representation of a moment that can
	 * also be evaluated to get a new moment which is the same
	 *
	 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
	 */
	function inspect () {
	    if (!this.isValid()) {
	        return 'moment.invalid(/* ' + this._i + ' */)';
	    }
	    var func = 'moment';
	    var zone = '';
	    if (!this.isLocal()) {
	        func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
	        zone = 'Z';
	    }
	    var prefix = '[' + func + '("]';
	    var year = (0 < this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
	    var datetime = '-MM-DD[T]HH:mm:ss.SSS';
	    var suffix = zone + '[")]';
	
	    return this.format(prefix + year + datetime + suffix);
	}
	
	function format (inputString) {
	    if (!inputString) {
	        inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
	    }
	    var output = formatMoment(this, inputString);
	    return this.localeData().postformat(output);
	}
	
	function from (time, withoutSuffix) {
	    if (this.isValid() &&
	            ((isMoment(time) && time.isValid()) ||
	             createLocal(time).isValid())) {
	        return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
	    } else {
	        return this.localeData().invalidDate();
	    }
	}
	
	function fromNow (withoutSuffix) {
	    return this.from(createLocal(), withoutSuffix);
	}
	
	function to (time, withoutSuffix) {
	    if (this.isValid() &&
	            ((isMoment(time) && time.isValid()) ||
	             createLocal(time).isValid())) {
	        return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
	    } else {
	        return this.localeData().invalidDate();
	    }
	}
	
	function toNow (withoutSuffix) {
	    return this.to(createLocal(), withoutSuffix);
	}
	
	// If passed a locale key, it will set the locale for this
	// instance.  Otherwise, it will return the locale configuration
	// variables for this instance.
	function locale (key) {
	    var newLocaleData;
	
	    if (key === undefined) {
	        return this._locale._abbr;
	    } else {
	        newLocaleData = getLocale(key);
	        if (newLocaleData != null) {
	            this._locale = newLocaleData;
	        }
	        return this;
	    }
	}
	
	var lang = deprecate(
	    'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
	    function (key) {
	        if (key === undefined) {
	            return this.localeData();
	        } else {
	            return this.locale(key);
	        }
	    }
	);
	
	function localeData () {
	    return this._locale;
	}
	
	function startOf (units) {
	    units = normalizeUnits(units);
	    // the following switch intentionally omits break keywords
	    // to utilize falling through the cases.
	    switch (units) {
	        case 'year':
	            this.month(0);
	            /* falls through */
	        case 'quarter':
	        case 'month':
	            this.date(1);
	            /* falls through */
	        case 'week':
	        case 'isoWeek':
	        case 'day':
	        case 'date':
	            this.hours(0);
	            /* falls through */
	        case 'hour':
	            this.minutes(0);
	            /* falls through */
	        case 'minute':
	            this.seconds(0);
	            /* falls through */
	        case 'second':
	            this.milliseconds(0);
	    }
	
	    // weeks are a special case
	    if (units === 'week') {
	        this.weekday(0);
	    }
	    if (units === 'isoWeek') {
	        this.isoWeekday(1);
	    }
	
	    // quarters are also special
	    if (units === 'quarter') {
	        this.month(Math.floor(this.month() / 3) * 3);
	    }
	
	    return this;
	}
	
	function endOf (units) {
	    units = normalizeUnits(units);
	    if (units === undefined || units === 'millisecond') {
	        return this;
	    }
	
	    // 'date' is an alias for 'day', so it should be considered as such.
	    if (units === 'date') {
	        units = 'day';
	    }
	
	    return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
	}
	
	function valueOf () {
	    return this._d.valueOf() - ((this._offset || 0) * 60000);
	}
	
	function unix () {
	    return Math.floor(this.valueOf() / 1000);
	}
	
	function toDate () {
	    return new Date(this.valueOf());
	}
	
	function toArray () {
	    var m = this;
	    return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
	}
	
	function toObject () {
	    var m = this;
	    return {
	        years: m.year(),
	        months: m.month(),
	        date: m.date(),
	        hours: m.hours(),
	        minutes: m.minutes(),
	        seconds: m.seconds(),
	        milliseconds: m.milliseconds()
	    };
	}
	
	function toJSON () {
	    // new Date(NaN).toJSON() === null
	    return this.isValid() ? this.toISOString() : null;
	}
	
	function isValid$1 () {
	    return isValid(this);
	}
	
	function parsingFlags () {
	    return extend({}, getParsingFlags(this));
	}
	
	function invalidAt () {
	    return getParsingFlags(this).overflow;
	}
	
	function creationData() {
	    return {
	        input: this._i,
	        format: this._f,
	        locale: this._locale,
	        isUTC: this._isUTC,
	        strict: this._strict
	    };
	}
	
	// FORMATTING
	
	addFormatToken(0, ['gg', 2], 0, function () {
	    return this.weekYear() % 100;
	});
	
	addFormatToken(0, ['GG', 2], 0, function () {
	    return this.isoWeekYear() % 100;
	});
	
	function addWeekYearFormatToken (token, getter) {
	    addFormatToken(0, [token, token.length], 0, getter);
	}
	
	addWeekYearFormatToken('gggg',     'weekYear');
	addWeekYearFormatToken('ggggg',    'weekYear');
	addWeekYearFormatToken('GGGG',  'isoWeekYear');
	addWeekYearFormatToken('GGGGG', 'isoWeekYear');
	
	// ALIASES
	
	addUnitAlias('weekYear', 'gg');
	addUnitAlias('isoWeekYear', 'GG');
	
	// PRIORITY
	
	addUnitPriority('weekYear', 1);
	addUnitPriority('isoWeekYear', 1);
	
	
	// PARSING
	
	addRegexToken('G',      matchSigned);
	addRegexToken('g',      matchSigned);
	addRegexToken('GG',     match1to2, match2);
	addRegexToken('gg',     match1to2, match2);
	addRegexToken('GGGG',   match1to4, match4);
	addRegexToken('gggg',   match1to4, match4);
	addRegexToken('GGGGG',  match1to6, match6);
	addRegexToken('ggggg',  match1to6, match6);
	
	addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
	    week[token.substr(0, 2)] = toInt(input);
	});
	
	addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
	    week[token] = hooks.parseTwoDigitYear(input);
	});
	
	// MOMENTS
	
	function getSetWeekYear (input) {
	    return getSetWeekYearHelper.call(this,
	            input,
	            this.week(),
	            this.weekday(),
	            this.localeData()._week.dow,
	            this.localeData()._week.doy);
	}
	
	function getSetISOWeekYear (input) {
	    return getSetWeekYearHelper.call(this,
	            input, this.isoWeek(), this.isoWeekday(), 1, 4);
	}
	
	function getISOWeeksInYear () {
	    return weeksInYear(this.year(), 1, 4);
	}
	
	function getWeeksInYear () {
	    var weekInfo = this.localeData()._week;
	    return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
	}
	
	function getSetWeekYearHelper(input, week, weekday, dow, doy) {
	    var weeksTarget;
	    if (input == null) {
	        return weekOfYear(this, dow, doy).year;
	    } else {
	        weeksTarget = weeksInYear(input, dow, doy);
	        if (week > weeksTarget) {
	            week = weeksTarget;
	        }
	        return setWeekAll.call(this, input, week, weekday, dow, doy);
	    }
	}
	
	function setWeekAll(weekYear, week, weekday, dow, doy) {
	    var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
	        date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
	
	    this.year(date.getUTCFullYear());
	    this.month(date.getUTCMonth());
	    this.date(date.getUTCDate());
	    return this;
	}
	
	// FORMATTING
	
	addFormatToken('Q', 0, 'Qo', 'quarter');
	
	// ALIASES
	
	addUnitAlias('quarter', 'Q');
	
	// PRIORITY
	
	addUnitPriority('quarter', 7);
	
	// PARSING
	
	addRegexToken('Q', match1);
	addParseToken('Q', function (input, array) {
	    array[MONTH] = (toInt(input) - 1) * 3;
	});
	
	// MOMENTS
	
	function getSetQuarter (input) {
	    return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
	}
	
	// FORMATTING
	
	addFormatToken('D', ['DD', 2], 'Do', 'date');
	
	// ALIASES
	
	addUnitAlias('date', 'D');
	
	// PRIOROITY
	addUnitPriority('date', 9);
	
	// PARSING
	
	addRegexToken('D',  match1to2);
	addRegexToken('DD', match1to2, match2);
	addRegexToken('Do', function (isStrict, locale) {
	    return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
	});
	
	addParseToken(['D', 'DD'], DATE);
	addParseToken('Do', function (input, array) {
	    array[DATE] = toInt(input.match(match1to2)[0], 10);
	});
	
	// MOMENTS
	
	var getSetDayOfMonth = makeGetSet('Date', true);
	
	// FORMATTING
	
	addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
	
	// ALIASES
	
	addUnitAlias('dayOfYear', 'DDD');
	
	// PRIORITY
	addUnitPriority('dayOfYear', 4);
	
	// PARSING
	
	addRegexToken('DDD',  match1to3);
	addRegexToken('DDDD', match3);
	addParseToken(['DDD', 'DDDD'], function (input, array, config) {
	    config._dayOfYear = toInt(input);
	});
	
	// HELPERS
	
	// MOMENTS
	
	function getSetDayOfYear (input) {
	    var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
	    return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
	}
	
	// FORMATTING
	
	addFormatToken('m', ['mm', 2], 0, 'minute');
	
	// ALIASES
	
	addUnitAlias('minute', 'm');
	
	// PRIORITY
	
	addUnitPriority('minute', 14);
	
	// PARSING
	
	addRegexToken('m',  match1to2);
	addRegexToken('mm', match1to2, match2);
	addParseToken(['m', 'mm'], MINUTE);
	
	// MOMENTS
	
	var getSetMinute = makeGetSet('Minutes', false);
	
	// FORMATTING
	
	addFormatToken('s', ['ss', 2], 0, 'second');
	
	// ALIASES
	
	addUnitAlias('second', 's');
	
	// PRIORITY
	
	addUnitPriority('second', 15);
	
	// PARSING
	
	addRegexToken('s',  match1to2);
	addRegexToken('ss', match1to2, match2);
	addParseToken(['s', 'ss'], SECOND);
	
	// MOMENTS
	
	var getSetSecond = makeGetSet('Seconds', false);
	
	// FORMATTING
	
	addFormatToken('S', 0, 0, function () {
	    return ~~(this.millisecond() / 100);
	});
	
	addFormatToken(0, ['SS', 2], 0, function () {
	    return ~~(this.millisecond() / 10);
	});
	
	addFormatToken(0, ['SSS', 3], 0, 'millisecond');
	addFormatToken(0, ['SSSS', 4], 0, function () {
	    return this.millisecond() * 10;
	});
	addFormatToken(0, ['SSSSS', 5], 0, function () {
	    return this.millisecond() * 100;
	});
	addFormatToken(0, ['SSSSSS', 6], 0, function () {
	    return this.millisecond() * 1000;
	});
	addFormatToken(0, ['SSSSSSS', 7], 0, function () {
	    return this.millisecond() * 10000;
	});
	addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
	    return this.millisecond() * 100000;
	});
	addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
	    return this.millisecond() * 1000000;
	});
	
	
	// ALIASES
	
	addUnitAlias('millisecond', 'ms');
	
	// PRIORITY
	
	addUnitPriority('millisecond', 16);
	
	// PARSING
	
	addRegexToken('S',    match1to3, match1);
	addRegexToken('SS',   match1to3, match2);
	addRegexToken('SSS',  match1to3, match3);
	
	var token;
	for (token = 'SSSS'; token.length <= 9; token += 'S') {
	    addRegexToken(token, matchUnsigned);
	}
	
	function parseMs(input, array) {
	    array[MILLISECOND] = toInt(('0.' + input) * 1000);
	}
	
	for (token = 'S'; token.length <= 9; token += 'S') {
	    addParseToken(token, parseMs);
	}
	// MOMENTS
	
	var getSetMillisecond = makeGetSet('Milliseconds', false);
	
	// FORMATTING
	
	addFormatToken('z',  0, 0, 'zoneAbbr');
	addFormatToken('zz', 0, 0, 'zoneName');
	
	// MOMENTS
	
	function getZoneAbbr () {
	    return this._isUTC ? 'UTC' : '';
	}
	
	function getZoneName () {
	    return this._isUTC ? 'Coordinated Universal Time' : '';
	}
	
	var proto = Moment.prototype;
	
	proto.add               = add;
	proto.calendar          = calendar$1;
	proto.clone             = clone;
	proto.diff              = diff;
	proto.endOf             = endOf;
	proto.format            = format;
	proto.from              = from;
	proto.fromNow           = fromNow;
	proto.to                = to;
	proto.toNow             = toNow;
	proto.get               = stringGet;
	proto.invalidAt         = invalidAt;
	proto.isAfter           = isAfter;
	proto.isBefore          = isBefore;
	proto.isBetween         = isBetween;
	proto.isSame            = isSame;
	proto.isSameOrAfter     = isSameOrAfter;
	proto.isSameOrBefore    = isSameOrBefore;
	proto.isValid           = isValid$1;
	proto.lang              = lang;
	proto.locale            = locale;
	proto.localeData        = localeData;
	proto.max               = prototypeMax;
	proto.min               = prototypeMin;
	proto.parsingFlags      = parsingFlags;
	proto.set               = stringSet;
	proto.startOf           = startOf;
	proto.subtract          = subtract;
	proto.toArray           = toArray;
	proto.toObject          = toObject;
	proto.toDate            = toDate;
	proto.toISOString       = toISOString;
	proto.inspect           = inspect;
	proto.toJSON            = toJSON;
	proto.toString          = toString;
	proto.unix              = unix;
	proto.valueOf           = valueOf;
	proto.creationData      = creationData;
	
	// Year
	proto.year       = getSetYear;
	proto.isLeapYear = getIsLeapYear;
	
	// Week Year
	proto.weekYear    = getSetWeekYear;
	proto.isoWeekYear = getSetISOWeekYear;
	
	// Quarter
	proto.quarter = proto.quarters = getSetQuarter;
	
	// Month
	proto.month       = getSetMonth;
	proto.daysInMonth = getDaysInMonth;
	
	// Week
	proto.week           = proto.weeks        = getSetWeek;
	proto.isoWeek        = proto.isoWeeks     = getSetISOWeek;
	proto.weeksInYear    = getWeeksInYear;
	proto.isoWeeksInYear = getISOWeeksInYear;
	
	// Day
	proto.date       = getSetDayOfMonth;
	proto.day        = proto.days             = getSetDayOfWeek;
	proto.weekday    = getSetLocaleDayOfWeek;
	proto.isoWeekday = getSetISODayOfWeek;
	proto.dayOfYear  = getSetDayOfYear;
	
	// Hour
	proto.hour = proto.hours = getSetHour;
	
	// Minute
	proto.minute = proto.minutes = getSetMinute;
	
	// Second
	proto.second = proto.seconds = getSetSecond;
	
	// Millisecond
	proto.millisecond = proto.milliseconds = getSetMillisecond;
	
	// Offset
	proto.utcOffset            = getSetOffset;
	proto.utc                  = setOffsetToUTC;
	proto.local                = setOffsetToLocal;
	proto.parseZone            = setOffsetToParsedOffset;
	proto.hasAlignedHourOffset = hasAlignedHourOffset;
	proto.isDST                = isDaylightSavingTime;
	proto.isLocal              = isLocal;
	proto.isUtcOffset          = isUtcOffset;
	proto.isUtc                = isUtc;
	proto.isUTC                = isUtc;
	
	// Timezone
	proto.zoneAbbr = getZoneAbbr;
	proto.zoneName = getZoneName;
	
	// Deprecations
	proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
	proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
	proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
	proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
	proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
	
	function createUnix (input) {
	    return createLocal(input * 1000);
	}
	
	function createInZone () {
	    return createLocal.apply(null, arguments).parseZone();
	}
	
	function preParsePostFormat (string) {
	    return string;
	}
	
	var proto$1 = Locale.prototype;
	
	proto$1.calendar        = calendar;
	proto$1.longDateFormat  = longDateFormat;
	proto$1.invalidDate     = invalidDate;
	proto$1.ordinal         = ordinal;
	proto$1.preparse        = preParsePostFormat;
	proto$1.postformat      = preParsePostFormat;
	proto$1.relativeTime    = relativeTime;
	proto$1.pastFuture      = pastFuture;
	proto$1.set             = set;
	
	// Month
	proto$1.months            =        localeMonths;
	proto$1.monthsShort       =        localeMonthsShort;
	proto$1.monthsParse       =        localeMonthsParse;
	proto$1.monthsRegex       = monthsRegex;
	proto$1.monthsShortRegex  = monthsShortRegex;
	
	// Week
	proto$1.week = localeWeek;
	proto$1.firstDayOfYear = localeFirstDayOfYear;
	proto$1.firstDayOfWeek = localeFirstDayOfWeek;
	
	// Day of Week
	proto$1.weekdays       =        localeWeekdays;
	proto$1.weekdaysMin    =        localeWeekdaysMin;
	proto$1.weekdaysShort  =        localeWeekdaysShort;
	proto$1.weekdaysParse  =        localeWeekdaysParse;
	
	proto$1.weekdaysRegex       =        weekdaysRegex;
	proto$1.weekdaysShortRegex  =        weekdaysShortRegex;
	proto$1.weekdaysMinRegex    =        weekdaysMinRegex;
	
	// Hours
	proto$1.isPM = localeIsPM;
	proto$1.meridiem = localeMeridiem;
	
	function get$1 (format, index, field, setter) {
	    var locale = getLocale();
	    var utc = createUTC().set(setter, index);
	    return locale[field](utc, format);
	}
	
	function listMonthsImpl (format, index, field) {
	    if (isNumber(format)) {
	        index = format;
	        format = undefined;
	    }
	
	    format = format || '';
	
	    if (index != null) {
	        return get$1(format, index, field, 'month');
	    }
	
	    var i;
	    var out = [];
	    for (i = 0; i < 12; i++) {
	        out[i] = get$1(format, i, field, 'month');
	    }
	    return out;
	}
	
	// ()
	// (5)
	// (fmt, 5)
	// (fmt)
	// (true)
	// (true, 5)
	// (true, fmt, 5)
	// (true, fmt)
	function listWeekdaysImpl (localeSorted, format, index, field) {
	    if (typeof localeSorted === 'boolean') {
	        if (isNumber(format)) {
	            index = format;
	            format = undefined;
	        }
	
	        format = format || '';
	    } else {
	        format = localeSorted;
	        index = format;
	        localeSorted = false;
	
	        if (isNumber(format)) {
	            index = format;
	            format = undefined;
	        }
	
	        format = format || '';
	    }
	
	    var locale = getLocale(),
	        shift = localeSorted ? locale._week.dow : 0;
	
	    if (index != null) {
	        return get$1(format, (index + shift) % 7, field, 'day');
	    }
	
	    var i;
	    var out = [];
	    for (i = 0; i < 7; i++) {
	        out[i] = get$1(format, (i + shift) % 7, field, 'day');
	    }
	    return out;
	}
	
	function listMonths (format, index) {
	    return listMonthsImpl(format, index, 'months');
	}
	
	function listMonthsShort (format, index) {
	    return listMonthsImpl(format, index, 'monthsShort');
	}
	
	function listWeekdays (localeSorted, format, index) {
	    return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
	}
	
	function listWeekdaysShort (localeSorted, format, index) {
	    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
	}
	
	function listWeekdaysMin (localeSorted, format, index) {
	    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
	}
	
	getSetGlobalLocale('en', {
	    ordinalParse: /\d{1,2}(th|st|nd|rd)/,
	    ordinal : function (number) {
	        var b = number % 10,
	            output = (toInt(number % 100 / 10) === 1) ? 'th' :
	            (b === 1) ? 'st' :
	            (b === 2) ? 'nd' :
	            (b === 3) ? 'rd' : 'th';
	        return number + output;
	    }
	});
	
	// Side effect imports
	hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
	hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
	
	var mathAbs = Math.abs;
	
	function abs () {
	    var data           = this._data;
	
	    this._milliseconds = mathAbs(this._milliseconds);
	    this._days         = mathAbs(this._days);
	    this._months       = mathAbs(this._months);
	
	    data.milliseconds  = mathAbs(data.milliseconds);
	    data.seconds       = mathAbs(data.seconds);
	    data.minutes       = mathAbs(data.minutes);
	    data.hours         = mathAbs(data.hours);
	    data.months        = mathAbs(data.months);
	    data.years         = mathAbs(data.years);
	
	    return this;
	}
	
	function addSubtract$1 (duration, input, value, direction) {
	    var other = createDuration(input, value);
	
	    duration._milliseconds += direction * other._milliseconds;
	    duration._days         += direction * other._days;
	    duration._months       += direction * other._months;
	
	    return duration._bubble();
	}
	
	// supports only 2.0-style add(1, 's') or add(duration)
	function add$1 (input, value) {
	    return addSubtract$1(this, input, value, 1);
	}
	
	// supports only 2.0-style subtract(1, 's') or subtract(duration)
	function subtract$1 (input, value) {
	    return addSubtract$1(this, input, value, -1);
	}
	
	function absCeil (number) {
	    if (number < 0) {
	        return Math.floor(number);
	    } else {
	        return Math.ceil(number);
	    }
	}
	
	function bubble () {
	    var milliseconds = this._milliseconds;
	    var days         = this._days;
	    var months       = this._months;
	    var data         = this._data;
	    var seconds, minutes, hours, years, monthsFromDays;
	
	    // if we have a mix of positive and negative values, bubble down first
	    // check: https://github.com/moment/moment/issues/2166
	    if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
	            (milliseconds <= 0 && days <= 0 && months <= 0))) {
	        milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
	        days = 0;
	        months = 0;
	    }
	
	    // The following code bubbles up values, see the tests for
	    // examples of what that means.
	    data.milliseconds = milliseconds % 1000;
	
	    seconds           = absFloor(milliseconds / 1000);
	    data.seconds      = seconds % 60;
	
	    minutes           = absFloor(seconds / 60);
	    data.minutes      = minutes % 60;
	
	    hours             = absFloor(minutes / 60);
	    data.hours        = hours % 24;
	
	    days += absFloor(hours / 24);
	
	    // convert days to months
	    monthsFromDays = absFloor(daysToMonths(days));
	    months += monthsFromDays;
	    days -= absCeil(monthsToDays(monthsFromDays));
	
	    // 12 months -> 1 year
	    years = absFloor(months / 12);
	    months %= 12;
	
	    data.days   = days;
	    data.months = months;
	    data.years  = years;
	
	    return this;
	}
	
	function daysToMonths (days) {
	    // 400 years have 146097 days (taking into account leap year rules)
	    // 400 years have 12 months === 4800
	    return days * 4800 / 146097;
	}
	
	function monthsToDays (months) {
	    // the reverse of daysToMonths
	    return months * 146097 / 4800;
	}
	
	function as (units) {
	    var days;
	    var months;
	    var milliseconds = this._milliseconds;
	
	    units = normalizeUnits(units);
	
	    if (units === 'month' || units === 'year') {
	        days   = this._days   + milliseconds / 864e5;
	        months = this._months + daysToMonths(days);
	        return units === 'month' ? months : months / 12;
	    } else {
	        // handle milliseconds separately because of floating point math errors (issue #1867)
	        days = this._days + Math.round(monthsToDays(this._months));
	        switch (units) {
	            case 'week'   : return days / 7     + milliseconds / 6048e5;
	            case 'day'    : return days         + milliseconds / 864e5;
	            case 'hour'   : return days * 24    + milliseconds / 36e5;
	            case 'minute' : return days * 1440  + milliseconds / 6e4;
	            case 'second' : return days * 86400 + milliseconds / 1000;
	            // Math.floor prevents floating point math errors here
	            case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
	            default: throw new Error('Unknown unit ' + units);
	        }
	    }
	}
	
	// TODO: Use this.as('ms')?
	function valueOf$1 () {
	    return (
	        this._milliseconds +
	        this._days * 864e5 +
	        (this._months % 12) * 2592e6 +
	        toInt(this._months / 12) * 31536e6
	    );
	}
	
	function makeAs (alias) {
	    return function () {
	        return this.as(alias);
	    };
	}
	
	var asMilliseconds = makeAs('ms');
	var asSeconds      = makeAs('s');
	var asMinutes      = makeAs('m');
	var asHours        = makeAs('h');
	var asDays         = makeAs('d');
	var asWeeks        = makeAs('w');
	var asMonths       = makeAs('M');
	var asYears        = makeAs('y');
	
	function get$2 (units) {
	    units = normalizeUnits(units);
	    return this[units + 's']();
	}
	
	function makeGetter(name) {
	    return function () {
	        return this._data[name];
	    };
	}
	
	var milliseconds = makeGetter('milliseconds');
	var seconds      = makeGetter('seconds');
	var minutes      = makeGetter('minutes');
	var hours        = makeGetter('hours');
	var days         = makeGetter('days');
	var months       = makeGetter('months');
	var years        = makeGetter('years');
	
	function weeks () {
	    return absFloor(this.days() / 7);
	}
	
	var round = Math.round;
	var thresholds = {
	    s: 45,  // seconds to minute
	    m: 45,  // minutes to hour
	    h: 22,  // hours to day
	    d: 26,  // days to month
	    M: 11   // months to year
	};
	
	// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
	function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
	    return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
	}
	
	function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
	    var duration = createDuration(posNegDuration).abs();
	    var seconds  = round(duration.as('s'));
	    var minutes  = round(duration.as('m'));
	    var hours    = round(duration.as('h'));
	    var days     = round(duration.as('d'));
	    var months   = round(duration.as('M'));
	    var years    = round(duration.as('y'));
	
	    var a = seconds < thresholds.s && ['s', seconds]  ||
	            minutes <= 1           && ['m']           ||
	            minutes < thresholds.m && ['mm', minutes] ||
	            hours   <= 1           && ['h']           ||
	            hours   < thresholds.h && ['hh', hours]   ||
	            days    <= 1           && ['d']           ||
	            days    < thresholds.d && ['dd', days]    ||
	            months  <= 1           && ['M']           ||
	            months  < thresholds.M && ['MM', months]  ||
	            years   <= 1           && ['y']           || ['yy', years];
	
	    a[2] = withoutSuffix;
	    a[3] = +posNegDuration > 0;
	    a[4] = locale;
	    return substituteTimeAgo.apply(null, a);
	}
	
	// This function allows you to set the rounding function for relative time strings
	function getSetRelativeTimeRounding (roundingFunction) {
	    if (roundingFunction === undefined) {
	        return round;
	    }
	    if (typeof(roundingFunction) === 'function') {
	        round = roundingFunction;
	        return true;
	    }
	    return false;
	}
	
	// This function allows you to set a threshold for relative time strings
	function getSetRelativeTimeThreshold (threshold, limit) {
	    if (thresholds[threshold] === undefined) {
	        return false;
	    }
	    if (limit === undefined) {
	        return thresholds[threshold];
	    }
	    thresholds[threshold] = limit;
	    return true;
	}
	
	function humanize (withSuffix) {
	    var locale = this.localeData();
	    var output = relativeTime$1(this, !withSuffix, locale);
	
	    if (withSuffix) {
	        output = locale.pastFuture(+this, output);
	    }
	
	    return locale.postformat(output);
	}
	
	var abs$1 = Math.abs;
	
	function toISOString$1() {
	    // for ISO strings we do not use the normal bubbling rules:
	    //  * milliseconds bubble up until they become hours
	    //  * days do not bubble at all
	    //  * months bubble up until they become years
	    // This is because there is no context-free conversion between hours and days
	    // (think of clock changes)
	    // and also not between days and months (28-31 days per month)
	    var seconds = abs$1(this._milliseconds) / 1000;
	    var days         = abs$1(this._days);
	    var months       = abs$1(this._months);
	    var minutes, hours, years;
	
	    // 3600 seconds -> 60 minutes -> 1 hour
	    minutes           = absFloor(seconds / 60);
	    hours             = absFloor(minutes / 60);
	    seconds %= 60;
	    minutes %= 60;
	
	    // 12 months -> 1 year
	    years  = absFloor(months / 12);
	    months %= 12;
	
	
	    // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
	    var Y = years;
	    var M = months;
	    var D = days;
	    var h = hours;
	    var m = minutes;
	    var s = seconds;
	    var total = this.asSeconds();
	
	    if (!total) {
	        // this is the same as C#'s (Noda) and python (isodate)...
	        // but not other JS (goog.date)
	        return 'P0D';
	    }
	
	    return (total < 0 ? '-' : '') +
	        'P' +
	        (Y ? Y + 'Y' : '') +
	        (M ? M + 'M' : '') +
	        (D ? D + 'D' : '') +
	        ((h || m || s) ? 'T' : '') +
	        (h ? h + 'H' : '') +
	        (m ? m + 'M' : '') +
	        (s ? s + 'S' : '');
	}
	
	var proto$2 = Duration.prototype;
	
	proto$2.abs            = abs;
	proto$2.add            = add$1;
	proto$2.subtract       = subtract$1;
	proto$2.as             = as;
	proto$2.asMilliseconds = asMilliseconds;
	proto$2.asSeconds      = asSeconds;
	proto$2.asMinutes      = asMinutes;
	proto$2.asHours        = asHours;
	proto$2.asDays         = asDays;
	proto$2.asWeeks        = asWeeks;
	proto$2.asMonths       = asMonths;
	proto$2.asYears        = asYears;
	proto$2.valueOf        = valueOf$1;
	proto$2._bubble        = bubble;
	proto$2.get            = get$2;
	proto$2.milliseconds   = milliseconds;
	proto$2.seconds        = seconds;
	proto$2.minutes        = minutes;
	proto$2.hours          = hours;
	proto$2.days           = days;
	proto$2.weeks          = weeks;
	proto$2.months         = months;
	proto$2.years          = years;
	proto$2.humanize       = humanize;
	proto$2.toISOString    = toISOString$1;
	proto$2.toString       = toISOString$1;
	proto$2.toJSON         = toISOString$1;
	proto$2.locale         = locale;
	proto$2.localeData     = localeData;
	
	// Deprecations
	proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
	proto$2.lang = lang;
	
	// Side effect imports
	
	// FORMATTING
	
	addFormatToken('X', 0, 0, 'unix');
	addFormatToken('x', 0, 0, 'valueOf');
	
	// PARSING
	
	addRegexToken('x', matchSigned);
	addRegexToken('X', matchTimestamp);
	addParseToken('X', function (input, array, config) {
	    config._d = new Date(parseFloat(input, 10) * 1000);
	});
	addParseToken('x', function (input, array, config) {
	    config._d = new Date(toInt(input));
	});
	
	// Side effect imports
	
	
	hooks.version = '2.17.1';
	
	setHookCallback(createLocal);
	
	hooks.fn                    = proto;
	hooks.min                   = min;
	hooks.max                   = max;
	hooks.now                   = now;
	hooks.utc                   = createUTC;
	hooks.unix                  = createUnix;
	hooks.months                = listMonths;
	hooks.isDate                = isDate;
	hooks.locale                = getSetGlobalLocale;
	hooks.invalid               = createInvalid;
	hooks.duration              = createDuration;
	hooks.isMoment              = isMoment;
	hooks.weekdays              = listWeekdays;
	hooks.parseZone             = createInZone;
	hooks.localeData            = getLocale;
	hooks.isDuration            = isDuration;
	hooks.monthsShort           = listMonthsShort;
	hooks.weekdaysMin           = listWeekdaysMin;
	hooks.defineLocale          = defineLocale;
	hooks.updateLocale          = updateLocale;
	hooks.locales               = listLocales;
	hooks.weekdaysShort         = listWeekdaysShort;
	hooks.normalizeUnits        = normalizeUnits;
	hooks.relativeTimeRounding = getSetRelativeTimeRounding;
	hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
	hooks.calendarFormat        = getCalendarFormat;
	hooks.prototype             = proto;
	
	return hooks;
	
	})));
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('webpack@1.14.0/buildin/module.js')(module)))
})
/** END DEFINE BLOCK for moment@2.17.1/moment.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale **/
jupyter.define('moment@2.17.1/locale', function (module, exports, __jupyter_require__) {
	
	      var map = {
		"./af": "moment@2.17.1/locale/af.js",
		"./af.js": "moment@2.17.1/locale/af.js",
		"./ar": "moment@2.17.1/locale/ar.js",
		"./ar-dz": "moment@2.17.1/locale/ar-dz.js",
		"./ar-dz.js": "moment@2.17.1/locale/ar-dz.js",
		"./ar-ly": "moment@2.17.1/locale/ar-ly.js",
		"./ar-ly.js": "moment@2.17.1/locale/ar-ly.js",
		"./ar-ma": "moment@2.17.1/locale/ar-ma.js",
		"./ar-ma.js": "moment@2.17.1/locale/ar-ma.js",
		"./ar-sa": "moment@2.17.1/locale/ar-sa.js",
		"./ar-sa.js": "moment@2.17.1/locale/ar-sa.js",
		"./ar-tn": "moment@2.17.1/locale/ar-tn.js",
		"./ar-tn.js": "moment@2.17.1/locale/ar-tn.js",
		"./ar.js": "moment@2.17.1/locale/ar.js",
		"./az": "moment@2.17.1/locale/az.js",
		"./az.js": "moment@2.17.1/locale/az.js",
		"./be": "moment@2.17.1/locale/be.js",
		"./be.js": "moment@2.17.1/locale/be.js",
		"./bg": "moment@2.17.1/locale/bg.js",
		"./bg.js": "moment@2.17.1/locale/bg.js",
		"./bn": "moment@2.17.1/locale/bn.js",
		"./bn.js": "moment@2.17.1/locale/bn.js",
		"./bo": "moment@2.17.1/locale/bo.js",
		"./bo.js": "moment@2.17.1/locale/bo.js",
		"./br": "moment@2.17.1/locale/br.js",
		"./br.js": "moment@2.17.1/locale/br.js",
		"./bs": "moment@2.17.1/locale/bs.js",
		"./bs.js": "moment@2.17.1/locale/bs.js",
		"./ca": "moment@2.17.1/locale/ca.js",
		"./ca.js": "moment@2.17.1/locale/ca.js",
		"./cs": "moment@2.17.1/locale/cs.js",
		"./cs.js": "moment@2.17.1/locale/cs.js",
		"./cv": "moment@2.17.1/locale/cv.js",
		"./cv.js": "moment@2.17.1/locale/cv.js",
		"./cy": "moment@2.17.1/locale/cy.js",
		"./cy.js": "moment@2.17.1/locale/cy.js",
		"./da": "moment@2.17.1/locale/da.js",
		"./da.js": "moment@2.17.1/locale/da.js",
		"./de": "moment@2.17.1/locale/de.js",
		"./de-at": "moment@2.17.1/locale/de-at.js",
		"./de-at.js": "moment@2.17.1/locale/de-at.js",
		"./de.js": "moment@2.17.1/locale/de.js",
		"./dv": "moment@2.17.1/locale/dv.js",
		"./dv.js": "moment@2.17.1/locale/dv.js",
		"./el": "moment@2.17.1/locale/el.js",
		"./el.js": "moment@2.17.1/locale/el.js",
		"./en-au": "moment@2.17.1/locale/en-au.js",
		"./en-au.js": "moment@2.17.1/locale/en-au.js",
		"./en-ca": "moment@2.17.1/locale/en-ca.js",
		"./en-ca.js": "moment@2.17.1/locale/en-ca.js",
		"./en-gb": "moment@2.17.1/locale/en-gb.js",
		"./en-gb.js": "moment@2.17.1/locale/en-gb.js",
		"./en-ie": "moment@2.17.1/locale/en-ie.js",
		"./en-ie.js": "moment@2.17.1/locale/en-ie.js",
		"./en-nz": "moment@2.17.1/locale/en-nz.js",
		"./en-nz.js": "moment@2.17.1/locale/en-nz.js",
		"./eo": "moment@2.17.1/locale/eo.js",
		"./eo.js": "moment@2.17.1/locale/eo.js",
		"./es": "moment@2.17.1/locale/es.js",
		"./es-do": "moment@2.17.1/locale/es-do.js",
		"./es-do.js": "moment@2.17.1/locale/es-do.js",
		"./es.js": "moment@2.17.1/locale/es.js",
		"./et": "moment@2.17.1/locale/et.js",
		"./et.js": "moment@2.17.1/locale/et.js",
		"./eu": "moment@2.17.1/locale/eu.js",
		"./eu.js": "moment@2.17.1/locale/eu.js",
		"./fa": "moment@2.17.1/locale/fa.js",
		"./fa.js": "moment@2.17.1/locale/fa.js",
		"./fi": "moment@2.17.1/locale/fi.js",
		"./fi.js": "moment@2.17.1/locale/fi.js",
		"./fo": "moment@2.17.1/locale/fo.js",
		"./fo.js": "moment@2.17.1/locale/fo.js",
		"./fr": "moment@2.17.1/locale/fr.js",
		"./fr-ca": "moment@2.17.1/locale/fr-ca.js",
		"./fr-ca.js": "moment@2.17.1/locale/fr-ca.js",
		"./fr-ch": "moment@2.17.1/locale/fr-ch.js",
		"./fr-ch.js": "moment@2.17.1/locale/fr-ch.js",
		"./fr.js": "moment@2.17.1/locale/fr.js",
		"./fy": "moment@2.17.1/locale/fy.js",
		"./fy.js": "moment@2.17.1/locale/fy.js",
		"./gd": "moment@2.17.1/locale/gd.js",
		"./gd.js": "moment@2.17.1/locale/gd.js",
		"./gl": "moment@2.17.1/locale/gl.js",
		"./gl.js": "moment@2.17.1/locale/gl.js",
		"./he": "moment@2.17.1/locale/he.js",
		"./he.js": "moment@2.17.1/locale/he.js",
		"./hi": "moment@2.17.1/locale/hi.js",
		"./hi.js": "moment@2.17.1/locale/hi.js",
		"./hr": "moment@2.17.1/locale/hr.js",
		"./hr.js": "moment@2.17.1/locale/hr.js",
		"./hu": "moment@2.17.1/locale/hu.js",
		"./hu.js": "moment@2.17.1/locale/hu.js",
		"./hy-am": "moment@2.17.1/locale/hy-am.js",
		"./hy-am.js": "moment@2.17.1/locale/hy-am.js",
		"./id": "moment@2.17.1/locale/id.js",
		"./id.js": "moment@2.17.1/locale/id.js",
		"./is": "moment@2.17.1/locale/is.js",
		"./is.js": "moment@2.17.1/locale/is.js",
		"./it": "moment@2.17.1/locale/it.js",
		"./it.js": "moment@2.17.1/locale/it.js",
		"./ja": "moment@2.17.1/locale/ja.js",
		"./ja.js": "moment@2.17.1/locale/ja.js",
		"./jv": "moment@2.17.1/locale/jv.js",
		"./jv.js": "moment@2.17.1/locale/jv.js",
		"./ka": "moment@2.17.1/locale/ka.js",
		"./ka.js": "moment@2.17.1/locale/ka.js",
		"./kk": "moment@2.17.1/locale/kk.js",
		"./kk.js": "moment@2.17.1/locale/kk.js",
		"./km": "moment@2.17.1/locale/km.js",
		"./km.js": "moment@2.17.1/locale/km.js",
		"./ko": "moment@2.17.1/locale/ko.js",
		"./ko.js": "moment@2.17.1/locale/ko.js",
		"./ky": "moment@2.17.1/locale/ky.js",
		"./ky.js": "moment@2.17.1/locale/ky.js",
		"./lb": "moment@2.17.1/locale/lb.js",
		"./lb.js": "moment@2.17.1/locale/lb.js",
		"./lo": "moment@2.17.1/locale/lo.js",
		"./lo.js": "moment@2.17.1/locale/lo.js",
		"./lt": "moment@2.17.1/locale/lt.js",
		"./lt.js": "moment@2.17.1/locale/lt.js",
		"./lv": "moment@2.17.1/locale/lv.js",
		"./lv.js": "moment@2.17.1/locale/lv.js",
		"./me": "moment@2.17.1/locale/me.js",
		"./me.js": "moment@2.17.1/locale/me.js",
		"./mi": "moment@2.17.1/locale/mi.js",
		"./mi.js": "moment@2.17.1/locale/mi.js",
		"./mk": "moment@2.17.1/locale/mk.js",
		"./mk.js": "moment@2.17.1/locale/mk.js",
		"./ml": "moment@2.17.1/locale/ml.js",
		"./ml.js": "moment@2.17.1/locale/ml.js",
		"./mr": "moment@2.17.1/locale/mr.js",
		"./mr.js": "moment@2.17.1/locale/mr.js",
		"./ms": "moment@2.17.1/locale/ms.js",
		"./ms-my": "moment@2.17.1/locale/ms-my.js",
		"./ms-my.js": "moment@2.17.1/locale/ms-my.js",
		"./ms.js": "moment@2.17.1/locale/ms.js",
		"./my": "moment@2.17.1/locale/my.js",
		"./my.js": "moment@2.17.1/locale/my.js",
		"./nb": "moment@2.17.1/locale/nb.js",
		"./nb.js": "moment@2.17.1/locale/nb.js",
		"./ne": "moment@2.17.1/locale/ne.js",
		"./ne.js": "moment@2.17.1/locale/ne.js",
		"./nl": "moment@2.17.1/locale/nl.js",
		"./nl-be": "moment@2.17.1/locale/nl-be.js",
		"./nl-be.js": "moment@2.17.1/locale/nl-be.js",
		"./nl.js": "moment@2.17.1/locale/nl.js",
		"./nn": "moment@2.17.1/locale/nn.js",
		"./nn.js": "moment@2.17.1/locale/nn.js",
		"./pa-in": "moment@2.17.1/locale/pa-in.js",
		"./pa-in.js": "moment@2.17.1/locale/pa-in.js",
		"./pl": "moment@2.17.1/locale/pl.js",
		"./pl.js": "moment@2.17.1/locale/pl.js",
		"./pt": "moment@2.17.1/locale/pt.js",
		"./pt-br": "moment@2.17.1/locale/pt-br.js",
		"./pt-br.js": "moment@2.17.1/locale/pt-br.js",
		"./pt.js": "moment@2.17.1/locale/pt.js",
		"./ro": "moment@2.17.1/locale/ro.js",
		"./ro.js": "moment@2.17.1/locale/ro.js",
		"./ru": "moment@2.17.1/locale/ru.js",
		"./ru.js": "moment@2.17.1/locale/ru.js",
		"./se": "moment@2.17.1/locale/se.js",
		"./se.js": "moment@2.17.1/locale/se.js",
		"./si": "moment@2.17.1/locale/si.js",
		"./si.js": "moment@2.17.1/locale/si.js",
		"./sk": "moment@2.17.1/locale/sk.js",
		"./sk.js": "moment@2.17.1/locale/sk.js",
		"./sl": "moment@2.17.1/locale/sl.js",
		"./sl.js": "moment@2.17.1/locale/sl.js",
		"./sq": "moment@2.17.1/locale/sq.js",
		"./sq.js": "moment@2.17.1/locale/sq.js",
		"./sr": "moment@2.17.1/locale/sr.js",
		"./sr-cyrl": "moment@2.17.1/locale/sr-cyrl.js",
		"./sr-cyrl.js": "moment@2.17.1/locale/sr-cyrl.js",
		"./sr.js": "moment@2.17.1/locale/sr.js",
		"./ss": "moment@2.17.1/locale/ss.js",
		"./ss.js": "moment@2.17.1/locale/ss.js",
		"./sv": "moment@2.17.1/locale/sv.js",
		"./sv.js": "moment@2.17.1/locale/sv.js",
		"./sw": "moment@2.17.1/locale/sw.js",
		"./sw.js": "moment@2.17.1/locale/sw.js",
		"./ta": "moment@2.17.1/locale/ta.js",
		"./ta.js": "moment@2.17.1/locale/ta.js",
		"./te": "moment@2.17.1/locale/te.js",
		"./te.js": "moment@2.17.1/locale/te.js",
		"./tet": "moment@2.17.1/locale/tet.js",
		"./tet.js": "moment@2.17.1/locale/tet.js",
		"./th": "moment@2.17.1/locale/th.js",
		"./th.js": "moment@2.17.1/locale/th.js",
		"./tl-ph": "moment@2.17.1/locale/tl-ph.js",
		"./tl-ph.js": "moment@2.17.1/locale/tl-ph.js",
		"./tlh": "moment@2.17.1/locale/tlh.js",
		"./tlh.js": "moment@2.17.1/locale/tlh.js",
		"./tr": "moment@2.17.1/locale/tr.js",
		"./tr.js": "moment@2.17.1/locale/tr.js",
		"./tzl": "moment@2.17.1/locale/tzl.js",
		"./tzl.js": "moment@2.17.1/locale/tzl.js",
		"./tzm": "moment@2.17.1/locale/tzm.js",
		"./tzm-latn": "moment@2.17.1/locale/tzm-latn.js",
		"./tzm-latn.js": "moment@2.17.1/locale/tzm-latn.js",
		"./tzm.js": "moment@2.17.1/locale/tzm.js",
		"./uk": "moment@2.17.1/locale/uk.js",
		"./uk.js": "moment@2.17.1/locale/uk.js",
		"./uz": "moment@2.17.1/locale/uz.js",
		"./uz.js": "moment@2.17.1/locale/uz.js",
		"./vi": "moment@2.17.1/locale/vi.js",
		"./vi.js": "moment@2.17.1/locale/vi.js",
		"./x-pseudo": "moment@2.17.1/locale/x-pseudo.js",
		"./x-pseudo.js": "moment@2.17.1/locale/x-pseudo.js",
		"./yo": "moment@2.17.1/locale/yo.js",
		"./yo.js": "moment@2.17.1/locale/yo.js",
		"./zh-cn": "moment@2.17.1/locale/zh-cn.js",
		"./zh-cn.js": "moment@2.17.1/locale/zh-cn.js",
		"./zh-hk": "moment@2.17.1/locale/zh-hk.js",
		"./zh-hk.js": "moment@2.17.1/locale/zh-hk.js",
		"./zh-tw": "moment@2.17.1/locale/zh-tw.js",
		"./zh-tw.js": "moment@2.17.1/locale/zh-tw.js"
	};
	      function jupyterContext(req) {
	        return __jupyter_require__(jupyterContextResolve(req));
	      };
	      function jupyterContextResolve(req) {
	        return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }());
	      };
	      jupyterContext.keys = function jupyterContextKeys() {
	        return Object.keys(map);
	      };
	      jupyterContext.resolve = jupyterContextResolve;
	      module.exports = jupyterContext;
	      jupyterContext.id = "moment@2.17.1/locale";
	    
})
/** END DEFINE BLOCK for moment@2.17.1/locale **/


/** START DEFINE BLOCK for moment@2.17.1/locale/af.js **/
jupyter.define('moment@2.17.1/locale/af.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Afrikaans [af]
	//! author : Werner Mollentze : https://github.com/wernerm
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var af = moment.defineLocale('af', {
	    months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
	    monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
	    weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
	    weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
	    weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
	    meridiemParse: /vm|nm/i,
	    isPM : function (input) {
	        return /^nm$/i.test(input);
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours < 12) {
	            return isLower ? 'vm' : 'VM';
	        } else {
	            return isLower ? 'nm' : 'NM';
	        }
	    },
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[Vandag om] LT',
	        nextDay : '[Môre om] LT',
	        nextWeek : 'dddd [om] LT',
	        lastDay : '[Gister om] LT',
	        lastWeek : '[Laas] dddd [om] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'oor %s',
	        past : '%s gelede',
	        s : '\'n paar sekondes',
	        m : '\'n minuut',
	        mm : '%d minute',
	        h : '\'n uur',
	        hh : '%d ure',
	        d : '\'n dag',
	        dd : '%d dae',
	        M : '\'n maand',
	        MM : '%d maande',
	        y : '\'n jaar',
	        yy : '%d jaar'
	    },
	    ordinalParse: /\d{1,2}(ste|de)/,
	    ordinal : function (number) {
	        return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
	    },
	    week : {
	        dow : 1, // Maandag is die eerste dag van die week.
	        doy : 4  // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
	    }
	});
	
	return af;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/af.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ar.js **/
jupyter.define('moment@2.17.1/locale/ar.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Arabic [ar]
	//! author : Abdel Said: https://github.com/abdelsaid
	//! author : Ahmed Elkhatib
	//! author : forabi https://github.com/forabi
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '١',
	    '2': '٢',
	    '3': '٣',
	    '4': '٤',
	    '5': '٥',
	    '6': '٦',
	    '7': '٧',
	    '8': '٨',
	    '9': '٩',
	    '0': '٠'
	};
	var numberMap = {
	    '١': '1',
	    '٢': '2',
	    '٣': '3',
	    '٤': '4',
	    '٥': '5',
	    '٦': '6',
	    '٧': '7',
	    '٨': '8',
	    '٩': '9',
	    '٠': '0'
	};
	var pluralForm = function (n) {
	    return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
	};
	var plurals = {
	    s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
	    m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
	    h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
	    d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
	    M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
	    y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
	};
	var pluralize = function (u) {
	    return function (number, withoutSuffix, string, isFuture) {
	        var f = pluralForm(number),
	            str = plurals[u][pluralForm(number)];
	        if (f === 2) {
	            str = str[withoutSuffix ? 0 : 1];
	        }
	        return str.replace(/%d/i, number);
	    };
	};
	var months = [
	    'كانون الثاني يناير',
	    'شباط فبراير',
	    'آذار مارس',
	    'نيسان أبريل',
	    'أيار مايو',
	    'حزيران يونيو',
	    'تموز يوليو',
	    'آب أغسطس',
	    'أيلول سبتمبر',
	    'تشرين الأول أكتوبر',
	    'تشرين الثاني نوفمبر',
	    'كانون الأول ديسمبر'
	];
	
	var ar = moment.defineLocale('ar', {
	    months : months,
	    monthsShort : months,
	    weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	    weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
	    weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'D/\u200FM/\u200FYYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    meridiemParse: /ص|م/,
	    isPM : function (input) {
	        return 'م' === input;
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 12) {
	            return 'ص';
	        } else {
	            return 'م';
	        }
	    },
	    calendar : {
	        sameDay: '[اليوم عند الساعة] LT',
	        nextDay: '[غدًا عند الساعة] LT',
	        nextWeek: 'dddd [عند الساعة] LT',
	        lastDay: '[أمس عند الساعة] LT',
	        lastWeek: 'dddd [عند الساعة] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'بعد %s',
	        past : 'منذ %s',
	        s : pluralize('s'),
	        m : pluralize('m'),
	        mm : pluralize('m'),
	        h : pluralize('h'),
	        hh : pluralize('h'),
	        d : pluralize('d'),
	        dd : pluralize('d'),
	        M : pluralize('M'),
	        MM : pluralize('M'),
	        y : pluralize('y'),
	        yy : pluralize('y')
	    },
	    preparse: function (string) {
	        return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
	            return numberMap[match];
	        }).replace(/،/g, ',');
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        }).replace(/,/g, '،');
	    },
	    week : {
	        dow : 6, // Saturday is the first day of the week.
	        doy : 12  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return ar;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ar.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ar-dz.js **/
jupyter.define('moment@2.17.1/locale/ar-dz.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Arabic (Algeria) [ar-dz]
	//! author : Noureddine LOUAHEDJ : https://github.com/noureddineme
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var arDz = moment.defineLocale('ar-dz', {
	    months : 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	    monthsShort : 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	    weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	    weekdaysShort : 'احد_اثنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
	    weekdaysMin : 'أح_إث_ثلا_أر_خم_جم_سب'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[اليوم على الساعة] LT',
	        nextDay: '[غدا على الساعة] LT',
	        nextWeek: 'dddd [على الساعة] LT',
	        lastDay: '[أمس على الساعة] LT',
	        lastWeek: 'dddd [على الساعة] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'في %s',
	        past : 'منذ %s',
	        s : 'ثوان',
	        m : 'دقيقة',
	        mm : '%d دقائق',
	        h : 'ساعة',
	        hh : '%d ساعات',
	        d : 'يوم',
	        dd : '%d أيام',
	        M : 'شهر',
	        MM : '%d أشهر',
	        y : 'سنة',
	        yy : '%d سنوات'
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 4  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return arDz;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ar-dz.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ar-ly.js **/
jupyter.define('moment@2.17.1/locale/ar-ly.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Arabic (Lybia) [ar-ly]
	//! author : Ali Hmer: https://github.com/kikoanis
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '1',
	    '2': '2',
	    '3': '3',
	    '4': '4',
	    '5': '5',
	    '6': '6',
	    '7': '7',
	    '8': '8',
	    '9': '9',
	    '0': '0'
	};
	var pluralForm = function (n) {
	    return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
	};
	var plurals = {
	    s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
	    m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
	    h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
	    d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
	    M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
	    y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
	};
	var pluralize = function (u) {
	    return function (number, withoutSuffix, string, isFuture) {
	        var f = pluralForm(number),
	            str = plurals[u][pluralForm(number)];
	        if (f === 2) {
	            str = str[withoutSuffix ? 0 : 1];
	        }
	        return str.replace(/%d/i, number);
	    };
	};
	var months = [
	    'يناير',
	    'فبراير',
	    'مارس',
	    'أبريل',
	    'مايو',
	    'يونيو',
	    'يوليو',
	    'أغسطس',
	    'سبتمبر',
	    'أكتوبر',
	    'نوفمبر',
	    'ديسمبر'
	];
	
	var arLy = moment.defineLocale('ar-ly', {
	    months : months,
	    monthsShort : months,
	    weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	    weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
	    weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'D/\u200FM/\u200FYYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    meridiemParse: /ص|م/,
	    isPM : function (input) {
	        return 'م' === input;
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 12) {
	            return 'ص';
	        } else {
	            return 'م';
	        }
	    },
	    calendar : {
	        sameDay: '[اليوم عند الساعة] LT',
	        nextDay: '[غدًا عند الساعة] LT',
	        nextWeek: 'dddd [عند الساعة] LT',
	        lastDay: '[أمس عند الساعة] LT',
	        lastWeek: 'dddd [عند الساعة] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'بعد %s',
	        past : 'منذ %s',
	        s : pluralize('s'),
	        m : pluralize('m'),
	        mm : pluralize('m'),
	        h : pluralize('h'),
	        hh : pluralize('h'),
	        d : pluralize('d'),
	        dd : pluralize('d'),
	        M : pluralize('M'),
	        MM : pluralize('M'),
	        y : pluralize('y'),
	        yy : pluralize('y')
	    },
	    preparse: function (string) {
	        return string.replace(/\u200f/g, '').replace(/،/g, ',');
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        }).replace(/,/g, '،');
	    },
	    week : {
	        dow : 6, // Saturday is the first day of the week.
	        doy : 12  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return arLy;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ar-ly.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ar-ma.js **/
jupyter.define('moment@2.17.1/locale/ar-ma.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Arabic (Morocco) [ar-ma]
	//! author : ElFadili Yassine : https://github.com/ElFadiliY
	//! author : Abdel Said : https://github.com/abdelsaid
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var arMa = moment.defineLocale('ar-ma', {
	    months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
	    monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
	    weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	    weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
	    weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[اليوم على الساعة] LT',
	        nextDay: '[غدا على الساعة] LT',
	        nextWeek: 'dddd [على الساعة] LT',
	        lastDay: '[أمس على الساعة] LT',
	        lastWeek: 'dddd [على الساعة] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'في %s',
	        past : 'منذ %s',
	        s : 'ثوان',
	        m : 'دقيقة',
	        mm : '%d دقائق',
	        h : 'ساعة',
	        hh : '%d ساعات',
	        d : 'يوم',
	        dd : '%d أيام',
	        M : 'شهر',
	        MM : '%d أشهر',
	        y : 'سنة',
	        yy : '%d سنوات'
	    },
	    week : {
	        dow : 6, // Saturday is the first day of the week.
	        doy : 12  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return arMa;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ar-ma.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ar-sa.js **/
jupyter.define('moment@2.17.1/locale/ar-sa.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Arabic (Saudi Arabia) [ar-sa]
	//! author : Suhail Alkowaileet : https://github.com/xsoh
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '١',
	    '2': '٢',
	    '3': '٣',
	    '4': '٤',
	    '5': '٥',
	    '6': '٦',
	    '7': '٧',
	    '8': '٨',
	    '9': '٩',
	    '0': '٠'
	};
	var numberMap = {
	    '١': '1',
	    '٢': '2',
	    '٣': '3',
	    '٤': '4',
	    '٥': '5',
	    '٦': '6',
	    '٧': '7',
	    '٨': '8',
	    '٩': '9',
	    '٠': '0'
	};
	
	var arSa = moment.defineLocale('ar-sa', {
	    months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	    monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	    weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	    weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
	    weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    meridiemParse: /ص|م/,
	    isPM : function (input) {
	        return 'م' === input;
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 12) {
	            return 'ص';
	        } else {
	            return 'م';
	        }
	    },
	    calendar : {
	        sameDay: '[اليوم على الساعة] LT',
	        nextDay: '[غدا على الساعة] LT',
	        nextWeek: 'dddd [على الساعة] LT',
	        lastDay: '[أمس على الساعة] LT',
	        lastWeek: 'dddd [على الساعة] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'في %s',
	        past : 'منذ %s',
	        s : 'ثوان',
	        m : 'دقيقة',
	        mm : '%d دقائق',
	        h : 'ساعة',
	        hh : '%d ساعات',
	        d : 'يوم',
	        dd : '%d أيام',
	        M : 'شهر',
	        MM : '%d أشهر',
	        y : 'سنة',
	        yy : '%d سنوات'
	    },
	    preparse: function (string) {
	        return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
	            return numberMap[match];
	        }).replace(/،/g, ',');
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        }).replace(/,/g, '،');
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return arSa;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ar-sa.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ar-tn.js **/
jupyter.define('moment@2.17.1/locale/ar-tn.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale  :  Arabic (Tunisia) [ar-tn]
	//! author : Nader Toukabri : https://github.com/naderio
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var arTn = moment.defineLocale('ar-tn', {
	    months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	    monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
	    weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
	    weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
	    weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat: {
	        LT: 'HH:mm',
	        LTS: 'HH:mm:ss',
	        L: 'DD/MM/YYYY',
	        LL: 'D MMMM YYYY',
	        LLL: 'D MMMM YYYY HH:mm',
	        LLLL: 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar: {
	        sameDay: '[اليوم على الساعة] LT',
	        nextDay: '[غدا على الساعة] LT',
	        nextWeek: 'dddd [على الساعة] LT',
	        lastDay: '[أمس على الساعة] LT',
	        lastWeek: 'dddd [على الساعة] LT',
	        sameElse: 'L'
	    },
	    relativeTime: {
	        future: 'في %s',
	        past: 'منذ %s',
	        s: 'ثوان',
	        m: 'دقيقة',
	        mm: '%d دقائق',
	        h: 'ساعة',
	        hh: '%d ساعات',
	        d: 'يوم',
	        dd: '%d أيام',
	        M: 'شهر',
	        MM: '%d أشهر',
	        y: 'سنة',
	        yy: '%d سنوات'
	    },
	    week: {
	        dow: 1, // Monday is the first day of the week.
	        doy: 4 // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return arTn;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ar-tn.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/az.js **/
jupyter.define('moment@2.17.1/locale/az.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Azerbaijani [az]
	//! author : topchiyev : https://github.com/topchiyev
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var suffixes = {
	    1: '-inci',
	    5: '-inci',
	    8: '-inci',
	    70: '-inci',
	    80: '-inci',
	    2: '-nci',
	    7: '-nci',
	    20: '-nci',
	    50: '-nci',
	    3: '-üncü',
	    4: '-üncü',
	    100: '-üncü',
	    6: '-ncı',
	    9: '-uncu',
	    10: '-uncu',
	    30: '-uncu',
	    60: '-ıncı',
	    90: '-ıncı'
	};
	
	var az = moment.defineLocale('az', {
	    months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'),
	    monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
	    weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
	    weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
	    weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[bugün saat] LT',
	        nextDay : '[sabah saat] LT',
	        nextWeek : '[gələn həftə] dddd [saat] LT',
	        lastDay : '[dünən] LT',
	        lastWeek : '[keçən həftə] dddd [saat] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s sonra',
	        past : '%s əvvəl',
	        s : 'birneçə saniyyə',
	        m : 'bir dəqiqə',
	        mm : '%d dəqiqə',
	        h : 'bir saat',
	        hh : '%d saat',
	        d : 'bir gün',
	        dd : '%d gün',
	        M : 'bir ay',
	        MM : '%d ay',
	        y : 'bir il',
	        yy : '%d il'
	    },
	    meridiemParse: /gecə|səhər|gündüz|axşam/,
	    isPM : function (input) {
	        return /^(gündüz|axşam)$/.test(input);
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'gecə';
	        } else if (hour < 12) {
	            return 'səhər';
	        } else if (hour < 17) {
	            return 'gündüz';
	        } else {
	            return 'axşam';
	        }
	    },
	    ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
	    ordinal : function (number) {
	        if (number === 0) {  // special case for zero
	            return number + '-ıncı';
	        }
	        var a = number % 10,
	            b = number % 100 - a,
	            c = number >= 100 ? 100 : null;
	        return number + (suffixes[a] || suffixes[b] || suffixes[c]);
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return az;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/az.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/be.js **/
jupyter.define('moment@2.17.1/locale/be.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Belarusian [be]
	//! author : Dmitry Demidov : https://github.com/demidov91
	//! author: Praleska: http://praleska.pro/
	//! Author : Menelion Elensúle : https://github.com/Oire
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function plural(word, num) {
	    var forms = word.split('_');
	    return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
	}
	function relativeTimeWithPlural(number, withoutSuffix, key) {
	    var format = {
	        'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
	        'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
	        'dd': 'дзень_дні_дзён',
	        'MM': 'месяц_месяцы_месяцаў',
	        'yy': 'год_гады_гадоў'
	    };
	    if (key === 'm') {
	        return withoutSuffix ? 'хвіліна' : 'хвіліну';
	    }
	    else if (key === 'h') {
	        return withoutSuffix ? 'гадзіна' : 'гадзіну';
	    }
	    else {
	        return number + ' ' + plural(format[key], +number);
	    }
	}
	
	var be = moment.defineLocale('be', {
	    months : {
	        format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'),
	        standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_')
	    },
	    monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'),
	    weekdays : {
	        format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'),
	        standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'),
	        isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/
	    },
	    weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
	    weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY г.',
	        LLL : 'D MMMM YYYY г., HH:mm',
	        LLLL : 'dddd, D MMMM YYYY г., HH:mm'
	    },
	    calendar : {
	        sameDay: '[Сёння ў] LT',
	        nextDay: '[Заўтра ў] LT',
	        lastDay: '[Учора ў] LT',
	        nextWeek: function () {
	            return '[У] dddd [ў] LT';
	        },
	        lastWeek: function () {
	            switch (this.day()) {
	                case 0:
	                case 3:
	                case 5:
	                case 6:
	                    return '[У мінулую] dddd [ў] LT';
	                case 1:
	                case 2:
	                case 4:
	                    return '[У мінулы] dddd [ў] LT';
	            }
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'праз %s',
	        past : '%s таму',
	        s : 'некалькі секунд',
	        m : relativeTimeWithPlural,
	        mm : relativeTimeWithPlural,
	        h : relativeTimeWithPlural,
	        hh : relativeTimeWithPlural,
	        d : 'дзень',
	        dd : relativeTimeWithPlural,
	        M : 'месяц',
	        MM : relativeTimeWithPlural,
	        y : 'год',
	        yy : relativeTimeWithPlural
	    },
	    meridiemParse: /ночы|раніцы|дня|вечара/,
	    isPM : function (input) {
	        return /^(дня|вечара)$/.test(input);
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'ночы';
	        } else if (hour < 12) {
	            return 'раніцы';
	        } else if (hour < 17) {
	            return 'дня';
	        } else {
	            return 'вечара';
	        }
	    },
	    ordinalParse: /\d{1,2}-(і|ы|га)/,
	    ordinal: function (number, period) {
	        switch (period) {
	            case 'M':
	            case 'd':
	            case 'DDD':
	            case 'w':
	            case 'W':
	                return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы';
	            case 'D':
	                return number + '-га';
	            default:
	                return number;
	        }
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return be;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/be.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/bg.js **/
jupyter.define('moment@2.17.1/locale/bg.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Bulgarian [bg]
	//! author : Krasen Borisov : https://github.com/kraz
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var bg = moment.defineLocale('bg', {
	    months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
	    monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
	    weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
	    weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
	    weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'D.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY H:mm',
	        LLLL : 'dddd, D MMMM YYYY H:mm'
	    },
	    calendar : {
	        sameDay : '[Днес в] LT',
	        nextDay : '[Утре в] LT',
	        nextWeek : 'dddd [в] LT',
	        lastDay : '[Вчера в] LT',
	        lastWeek : function () {
	            switch (this.day()) {
	                case 0:
	                case 3:
	                case 6:
	                    return '[В изминалата] dddd [в] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[В изминалия] dddd [в] LT';
	            }
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'след %s',
	        past : 'преди %s',
	        s : 'няколко секунди',
	        m : 'минута',
	        mm : '%d минути',
	        h : 'час',
	        hh : '%d часа',
	        d : 'ден',
	        dd : '%d дни',
	        M : 'месец',
	        MM : '%d месеца',
	        y : 'година',
	        yy : '%d години'
	    },
	    ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
	    ordinal : function (number) {
	        var lastDigit = number % 10,
	            last2Digits = number % 100;
	        if (number === 0) {
	            return number + '-ев';
	        } else if (last2Digits === 0) {
	            return number + '-ен';
	        } else if (last2Digits > 10 && last2Digits < 20) {
	            return number + '-ти';
	        } else if (lastDigit === 1) {
	            return number + '-ви';
	        } else if (lastDigit === 2) {
	            return number + '-ри';
	        } else if (lastDigit === 7 || lastDigit === 8) {
	            return number + '-ми';
	        } else {
	            return number + '-ти';
	        }
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return bg;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/bg.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/bn.js **/
jupyter.define('moment@2.17.1/locale/bn.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Bengali [bn]
	//! author : Kaushik Gandhi : https://github.com/kaushikgandhi
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '১',
	    '2': '২',
	    '3': '৩',
	    '4': '৪',
	    '5': '৫',
	    '6': '৬',
	    '7': '৭',
	    '8': '৮',
	    '9': '৯',
	    '0': '০'
	};
	var numberMap = {
	    '১': '1',
	    '২': '2',
	    '৩': '3',
	    '৪': '4',
	    '৫': '5',
	    '৬': '6',
	    '৭': '7',
	    '৮': '8',
	    '৯': '9',
	    '০': '0'
	};
	
	var bn = moment.defineLocale('bn', {
	    months : 'জানুয়ারী_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'),
	    monthsShort : 'জানু_ফেব_মার্চ_এপ্র_মে_জুন_জুল_আগ_সেপ্ট_অক্টো_নভে_ডিসে'.split('_'),
	    weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার'.split('_'),
	    weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি'.split('_'),
	    weekdaysMin : 'রবি_সোম_মঙ্গ_বুধ_বৃহঃ_শুক্র_শনি'.split('_'),
	    longDateFormat : {
	        LT : 'A h:mm সময়',
	        LTS : 'A h:mm:ss সময়',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY, A h:mm সময়',
	        LLLL : 'dddd, D MMMM YYYY, A h:mm সময়'
	    },
	    calendar : {
	        sameDay : '[আজ] LT',
	        nextDay : '[আগামীকাল] LT',
	        nextWeek : 'dddd, LT',
	        lastDay : '[গতকাল] LT',
	        lastWeek : '[গত] dddd, LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s পরে',
	        past : '%s আগে',
	        s : 'কয়েক সেকেন্ড',
	        m : 'এক মিনিট',
	        mm : '%d মিনিট',
	        h : 'এক ঘন্টা',
	        hh : '%d ঘন্টা',
	        d : 'এক দিন',
	        dd : '%d দিন',
	        M : 'এক মাস',
	        MM : '%d মাস',
	        y : 'এক বছর',
	        yy : '%d বছর'
	    },
	    preparse: function (string) {
	        return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
	            return numberMap[match];
	        });
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        });
	    },
	    meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if ((meridiem === 'রাত' && hour >= 4) ||
	                (meridiem === 'দুপুর' && hour < 5) ||
	                meridiem === 'বিকাল') {
	            return hour + 12;
	        } else {
	            return hour;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'রাত';
	        } else if (hour < 10) {
	            return 'সকাল';
	        } else if (hour < 17) {
	            return 'দুপুর';
	        } else if (hour < 20) {
	            return 'বিকাল';
	        } else {
	            return 'রাত';
	        }
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return bn;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/bn.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/bo.js **/
jupyter.define('moment@2.17.1/locale/bo.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Tibetan [bo]
	//! author : Thupten N. Chakrishar : https://github.com/vajradog
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '༡',
	    '2': '༢',
	    '3': '༣',
	    '4': '༤',
	    '5': '༥',
	    '6': '༦',
	    '7': '༧',
	    '8': '༨',
	    '9': '༩',
	    '0': '༠'
	};
	var numberMap = {
	    '༡': '1',
	    '༢': '2',
	    '༣': '3',
	    '༤': '4',
	    '༥': '5',
	    '༦': '6',
	    '༧': '7',
	    '༨': '8',
	    '༩': '9',
	    '༠': '0'
	};
	
	var bo = moment.defineLocale('bo', {
	    months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
	    monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
	    weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'),
	    weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
	    weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
	    longDateFormat : {
	        LT : 'A h:mm',
	        LTS : 'A h:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY, A h:mm',
	        LLLL : 'dddd, D MMMM YYYY, A h:mm'
	    },
	    calendar : {
	        sameDay : '[དི་རིང] LT',
	        nextDay : '[སང་ཉིན] LT',
	        nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT',
	        lastDay : '[ཁ་སང] LT',
	        lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s ལ་',
	        past : '%s སྔན་ལ',
	        s : 'ལམ་སང',
	        m : 'སྐར་མ་གཅིག',
	        mm : '%d སྐར་མ',
	        h : 'ཆུ་ཚོད་གཅིག',
	        hh : '%d ཆུ་ཚོད',
	        d : 'ཉིན་གཅིག',
	        dd : '%d ཉིན་',
	        M : 'ཟླ་བ་གཅིག',
	        MM : '%d ཟླ་བ',
	        y : 'ལོ་གཅིག',
	        yy : '%d ལོ'
	    },
	    preparse: function (string) {
	        return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
	            return numberMap[match];
	        });
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        });
	    },
	    meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if ((meridiem === 'མཚན་མོ' && hour >= 4) ||
	                (meridiem === 'ཉིན་གུང' && hour < 5) ||
	                meridiem === 'དགོང་དག') {
	            return hour + 12;
	        } else {
	            return hour;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'མཚན་མོ';
	        } else if (hour < 10) {
	            return 'ཞོགས་ཀས';
	        } else if (hour < 17) {
	            return 'ཉིན་གུང';
	        } else if (hour < 20) {
	            return 'དགོང་དག';
	        } else {
	            return 'མཚན་མོ';
	        }
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return bo;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/bo.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/br.js **/
jupyter.define('moment@2.17.1/locale/br.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Breton [br]
	//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function relativeTimeWithMutation(number, withoutSuffix, key) {
	    var format = {
	        'mm': 'munutenn',
	        'MM': 'miz',
	        'dd': 'devezh'
	    };
	    return number + ' ' + mutation(format[key], number);
	}
	function specialMutationForYears(number) {
	    switch (lastNumber(number)) {
	        case 1:
	        case 3:
	        case 4:
	        case 5:
	        case 9:
	            return number + ' bloaz';
	        default:
	            return number + ' vloaz';
	    }
	}
	function lastNumber(number) {
	    if (number > 9) {
	        return lastNumber(number % 10);
	    }
	    return number;
	}
	function mutation(text, number) {
	    if (number === 2) {
	        return softMutation(text);
	    }
	    return text;
	}
	function softMutation(text) {
	    var mutationTable = {
	        'm': 'v',
	        'b': 'v',
	        'd': 'z'
	    };
	    if (mutationTable[text.charAt(0)] === undefined) {
	        return text;
	    }
	    return mutationTable[text.charAt(0)] + text.substring(1);
	}
	
	var br = moment.defineLocale('br', {
	    months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'),
	    monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
	    weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'),
	    weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
	    weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'h[e]mm A',
	        LTS : 'h[e]mm:ss A',
	        L : 'DD/MM/YYYY',
	        LL : 'D [a viz] MMMM YYYY',
	        LLL : 'D [a viz] MMMM YYYY h[e]mm A',
	        LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A'
	    },
	    calendar : {
	        sameDay : '[Hiziv da] LT',
	        nextDay : '[Warc\'hoazh da] LT',
	        nextWeek : 'dddd [da] LT',
	        lastDay : '[Dec\'h da] LT',
	        lastWeek : 'dddd [paset da] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'a-benn %s',
	        past : '%s \'zo',
	        s : 'un nebeud segondennoù',
	        m : 'ur vunutenn',
	        mm : relativeTimeWithMutation,
	        h : 'un eur',
	        hh : '%d eur',
	        d : 'un devezh',
	        dd : relativeTimeWithMutation,
	        M : 'ur miz',
	        MM : relativeTimeWithMutation,
	        y : 'ur bloaz',
	        yy : specialMutationForYears
	    },
	    ordinalParse: /\d{1,2}(añ|vet)/,
	    ordinal : function (number) {
	        var output = (number === 1) ? 'añ' : 'vet';
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return br;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/br.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/bs.js **/
jupyter.define('moment@2.17.1/locale/bs.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Bosnian [bs]
	//! author : Nedim Cholich : https://github.com/frontyard
	//! based on (hr) translation by Bojan Marković
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function translate(number, withoutSuffix, key) {
	    var result = number + ' ';
	    switch (key) {
	        case 'm':
	            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
	        case 'mm':
	            if (number === 1) {
	                result += 'minuta';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'minute';
	            } else {
	                result += 'minuta';
	            }
	            return result;
	        case 'h':
	            return withoutSuffix ? 'jedan sat' : 'jednog sata';
	        case 'hh':
	            if (number === 1) {
	                result += 'sat';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'sata';
	            } else {
	                result += 'sati';
	            }
	            return result;
	        case 'dd':
	            if (number === 1) {
	                result += 'dan';
	            } else {
	                result += 'dana';
	            }
	            return result;
	        case 'MM':
	            if (number === 1) {
	                result += 'mjesec';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'mjeseca';
	            } else {
	                result += 'mjeseci';
	            }
	            return result;
	        case 'yy':
	            if (number === 1) {
	                result += 'godina';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'godine';
	            } else {
	                result += 'godina';
	            }
	            return result;
	    }
	}
	
	var bs = moment.defineLocale('bs', {
	    months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'),
	    monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'),
	    monthsParseExact: true,
	    weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
	    weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
	    weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY H:mm',
	        LLLL : 'dddd, D. MMMM YYYY H:mm'
	    },
	    calendar : {
	        sameDay  : '[danas u] LT',
	        nextDay  : '[sutra u] LT',
	        nextWeek : function () {
	            switch (this.day()) {
	                case 0:
	                    return '[u] [nedjelju] [u] LT';
	                case 3:
	                    return '[u] [srijedu] [u] LT';
	                case 6:
	                    return '[u] [subotu] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[u] dddd [u] LT';
	            }
	        },
	        lastDay  : '[jučer u] LT',
	        lastWeek : function () {
	            switch (this.day()) {
	                case 0:
	                case 3:
	                    return '[prošlu] dddd [u] LT';
	                case 6:
	                    return '[prošle] [subote] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[prošli] dddd [u] LT';
	            }
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'za %s',
	        past   : 'prije %s',
	        s      : 'par sekundi',
	        m      : translate,
	        mm     : translate,
	        h      : translate,
	        hh     : translate,
	        d      : 'dan',
	        dd     : translate,
	        M      : 'mjesec',
	        MM     : translate,
	        y      : 'godinu',
	        yy     : translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return bs;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/bs.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ca.js **/
jupyter.define('moment@2.17.1/locale/ca.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Catalan [ca]
	//! author : Juan G. Hurtado : https://github.com/juanghurtado
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var ca = moment.defineLocale('ca', {
	    months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
	    monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
	    weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
	    weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY H:mm',
	        LLLL : 'dddd D MMMM YYYY H:mm'
	    },
	    calendar : {
	        sameDay : function () {
	            return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	        },
	        nextDay : function () {
	            return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	        },
	        nextWeek : function () {
	            return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	        },
	        lastDay : function () {
	            return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	        },
	        lastWeek : function () {
	            return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'd\'aquí %s',
	        past : 'fa %s',
	        s : 'uns segons',
	        m : 'un minut',
	        mm : '%d minuts',
	        h : 'una hora',
	        hh : '%d hores',
	        d : 'un dia',
	        dd : '%d dies',
	        M : 'un mes',
	        MM : '%d mesos',
	        y : 'un any',
	        yy : '%d anys'
	    },
	    ordinalParse: /\d{1,2}(r|n|t|è|a)/,
	    ordinal : function (number, period) {
	        var output = (number === 1) ? 'r' :
	            (number === 2) ? 'n' :
	            (number === 3) ? 'r' :
	            (number === 4) ? 't' : 'è';
	        if (period === 'w' || period === 'W') {
	            output = 'a';
	        }
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return ca;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ca.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/cs.js **/
jupyter.define('moment@2.17.1/locale/cs.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Czech [cs]
	//! author : petrbela : https://github.com/petrbela
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_');
	var monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_');
	function plural(n) {
	    return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
	}
	function translate(number, withoutSuffix, key, isFuture) {
	    var result = number + ' ';
	    switch (key) {
	        case 's':  // a few seconds / in a few seconds / a few seconds ago
	            return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami';
	        case 'm':  // a minute / in a minute / a minute ago
	            return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
	        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'minuty' : 'minut');
	            } else {
	                return result + 'minutami';
	            }
	            break;
	        case 'h':  // an hour / in an hour / an hour ago
	            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
	        case 'hh': // 9 hours / in 9 hours / 9 hours ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'hodiny' : 'hodin');
	            } else {
	                return result + 'hodinami';
	            }
	            break;
	        case 'd':  // a day / in a day / a day ago
	            return (withoutSuffix || isFuture) ? 'den' : 'dnem';
	        case 'dd': // 9 days / in 9 days / 9 days ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'dny' : 'dní');
	            } else {
	                return result + 'dny';
	            }
	            break;
	        case 'M':  // a month / in a month / a month ago
	            return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
	        case 'MM': // 9 months / in 9 months / 9 months ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'měsíce' : 'měsíců');
	            } else {
	                return result + 'měsíci';
	            }
	            break;
	        case 'y':  // a year / in a year / a year ago
	            return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
	        case 'yy': // 9 years / in 9 years / 9 years ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'roky' : 'let');
	            } else {
	                return result + 'lety';
	            }
	            break;
	    }
	}
	
	var cs = moment.defineLocale('cs', {
	    months : months,
	    monthsShort : monthsShort,
	    monthsParse : (function (months, monthsShort) {
	        var i, _monthsParse = [];
	        for (i = 0; i < 12; i++) {
	            // use custom parser to solve problem with July (červenec)
	            _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
	        }
	        return _monthsParse;
	    }(months, monthsShort)),
	    shortMonthsParse : (function (monthsShort) {
	        var i, _shortMonthsParse = [];
	        for (i = 0; i < 12; i++) {
	            _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i');
	        }
	        return _shortMonthsParse;
	    }(monthsShort)),
	    longMonthsParse : (function (months) {
	        var i, _longMonthsParse = [];
	        for (i = 0; i < 12; i++) {
	            _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i');
	        }
	        return _longMonthsParse;
	    }(months)),
	    weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'),
	    weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'),
	    weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'),
	    longDateFormat : {
	        LT: 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY H:mm',
	        LLLL : 'dddd D. MMMM YYYY H:mm',
	        l : 'D. M. YYYY'
	    },
	    calendar : {
	        sameDay: '[dnes v] LT',
	        nextDay: '[zítra v] LT',
	        nextWeek: function () {
	            switch (this.day()) {
	                case 0:
	                    return '[v neděli v] LT';
	                case 1:
	                case 2:
	                    return '[v] dddd [v] LT';
	                case 3:
	                    return '[ve středu v] LT';
	                case 4:
	                    return '[ve čtvrtek v] LT';
	                case 5:
	                    return '[v pátek v] LT';
	                case 6:
	                    return '[v sobotu v] LT';
	            }
	        },
	        lastDay: '[včera v] LT',
	        lastWeek: function () {
	            switch (this.day()) {
	                case 0:
	                    return '[minulou neděli v] LT';
	                case 1:
	                case 2:
	                    return '[minulé] dddd [v] LT';
	                case 3:
	                    return '[minulou středu v] LT';
	                case 4:
	                case 5:
	                    return '[minulý] dddd [v] LT';
	                case 6:
	                    return '[minulou sobotu v] LT';
	            }
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'za %s',
	        past : 'před %s',
	        s : translate,
	        m : translate,
	        mm : translate,
	        h : translate,
	        hh : translate,
	        d : translate,
	        dd : translate,
	        M : translate,
	        MM : translate,
	        y : translate,
	        yy : translate
	    },
	    ordinalParse : /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return cs;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/cs.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/cv.js **/
jupyter.define('moment@2.17.1/locale/cv.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Chuvash [cv]
	//! author : Anatoly Mironov : https://github.com/mirontoli
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var cv = moment.defineLocale('cv', {
	    months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'),
	    monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'),
	    weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'),
	    weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'),
	    weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD-MM-YYYY',
	        LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
	        LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
	        LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm'
	    },
	    calendar : {
	        sameDay: '[Паян] LT [сехетре]',
	        nextDay: '[Ыран] LT [сехетре]',
	        lastDay: '[Ӗнер] LT [сехетре]',
	        nextWeek: '[Ҫитес] dddd LT [сехетре]',
	        lastWeek: '[Иртнӗ] dddd LT [сехетре]',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : function (output) {
	            var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран';
	            return output + affix;
	        },
	        past : '%s каялла',
	        s : 'пӗр-ик ҫеккунт',
	        m : 'пӗр минут',
	        mm : '%d минут',
	        h : 'пӗр сехет',
	        hh : '%d сехет',
	        d : 'пӗр кун',
	        dd : '%d кун',
	        M : 'пӗр уйӑх',
	        MM : '%d уйӑх',
	        y : 'пӗр ҫул',
	        yy : '%d ҫул'
	    },
	    ordinalParse: /\d{1,2}-мӗш/,
	    ordinal : '%d-мӗш',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return cv;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/cv.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/cy.js **/
jupyter.define('moment@2.17.1/locale/cy.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Welsh [cy]
	//! author : Robert Allen : https://github.com/robgallen
	//! author : https://github.com/ryangreaves
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var cy = moment.defineLocale('cy', {
	    months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'),
	    monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'),
	    weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'),
	    weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'),
	    weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'),
	    weekdaysParseExact : true,
	    // time formats are the same as en-gb
	    longDateFormat: {
	        LT: 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L: 'DD/MM/YYYY',
	        LL: 'D MMMM YYYY',
	        LLL: 'D MMMM YYYY HH:mm',
	        LLLL: 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar: {
	        sameDay: '[Heddiw am] LT',
	        nextDay: '[Yfory am] LT',
	        nextWeek: 'dddd [am] LT',
	        lastDay: '[Ddoe am] LT',
	        lastWeek: 'dddd [diwethaf am] LT',
	        sameElse: 'L'
	    },
	    relativeTime: {
	        future: 'mewn %s',
	        past: '%s yn ôl',
	        s: 'ychydig eiliadau',
	        m: 'munud',
	        mm: '%d munud',
	        h: 'awr',
	        hh: '%d awr',
	        d: 'diwrnod',
	        dd: '%d diwrnod',
	        M: 'mis',
	        MM: '%d mis',
	        y: 'blwyddyn',
	        yy: '%d flynedd'
	    },
	    ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,
	    // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
	    ordinal: function (number) {
	        var b = number,
	            output = '',
	            lookup = [
	                '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
	                'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
	            ];
	        if (b > 20) {
	            if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
	                output = 'fed'; // not 30ain, 70ain or 90ain
	            } else {
	                output = 'ain';
	            }
	        } else if (b > 0) {
	            output = lookup[b];
	        }
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return cy;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/cy.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/da.js **/
jupyter.define('moment@2.17.1/locale/da.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Danish [da]
	//! author : Ulrik Nielsen : https://github.com/mrbase
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var da = moment.defineLocale('da', {
	    months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'),
	    monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
	    weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
	    weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'),
	    weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY HH:mm',
	        LLLL : 'dddd [d.] D. MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[I dag kl.] LT',
	        nextDay : '[I morgen kl.] LT',
	        nextWeek : 'dddd [kl.] LT',
	        lastDay : '[I går kl.] LT',
	        lastWeek : '[sidste] dddd [kl] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'om %s',
	        past : '%s siden',
	        s : 'få sekunder',
	        m : 'et minut',
	        mm : '%d minutter',
	        h : 'en time',
	        hh : '%d timer',
	        d : 'en dag',
	        dd : '%d dage',
	        M : 'en måned',
	        MM : '%d måneder',
	        y : 'et år',
	        yy : '%d år'
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return da;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/da.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/de.js **/
jupyter.define('moment@2.17.1/locale/de.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : German [de]
	//! author : lluchs : https://github.com/lluchs
	//! author: Menelion Elensúle: https://github.com/Oire
	//! author : Mikolaj Dadela : https://github.com/mik01aj
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function processRelativeTime(number, withoutSuffix, key, isFuture) {
	    var format = {
	        'm': ['eine Minute', 'einer Minute'],
	        'h': ['eine Stunde', 'einer Stunde'],
	        'd': ['ein Tag', 'einem Tag'],
	        'dd': [number + ' Tage', number + ' Tagen'],
	        'M': ['ein Monat', 'einem Monat'],
	        'MM': [number + ' Monate', number + ' Monaten'],
	        'y': ['ein Jahr', 'einem Jahr'],
	        'yy': [number + ' Jahre', number + ' Jahren']
	    };
	    return withoutSuffix ? format[key][0] : format[key][1];
	}
	
	var de = moment.defineLocale('de', {
	    months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
	    monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
	    weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
	    weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT: 'HH:mm',
	        LTS: 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY HH:mm',
	        LLLL : 'dddd, D. MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[heute um] LT [Uhr]',
	        sameElse: 'L',
	        nextDay: '[morgen um] LT [Uhr]',
	        nextWeek: 'dddd [um] LT [Uhr]',
	        lastDay: '[gestern um] LT [Uhr]',
	        lastWeek: '[letzten] dddd [um] LT [Uhr]'
	    },
	    relativeTime : {
	        future : 'in %s',
	        past : 'vor %s',
	        s : 'ein paar Sekunden',
	        m : processRelativeTime,
	        mm : '%d Minuten',
	        h : processRelativeTime,
	        hh : '%d Stunden',
	        d : processRelativeTime,
	        dd : processRelativeTime,
	        M : processRelativeTime,
	        MM : processRelativeTime,
	        y : processRelativeTime,
	        yy : processRelativeTime
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return de;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/de.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/de-at.js **/
jupyter.define('moment@2.17.1/locale/de-at.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : German (Austria) [de-at]
	//! author : lluchs : https://github.com/lluchs
	//! author: Menelion Elensúle: https://github.com/Oire
	//! author : Martin Groller : https://github.com/MadMG
	//! author : Mikolaj Dadela : https://github.com/mik01aj
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function processRelativeTime(number, withoutSuffix, key, isFuture) {
	    var format = {
	        'm': ['eine Minute', 'einer Minute'],
	        'h': ['eine Stunde', 'einer Stunde'],
	        'd': ['ein Tag', 'einem Tag'],
	        'dd': [number + ' Tage', number + ' Tagen'],
	        'M': ['ein Monat', 'einem Monat'],
	        'MM': [number + ' Monate', number + ' Monaten'],
	        'y': ['ein Jahr', 'einem Jahr'],
	        'yy': [number + ' Jahre', number + ' Jahren']
	    };
	    return withoutSuffix ? format[key][0] : format[key][1];
	}
	
	var deAt = moment.defineLocale('de-at', {
	    months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
	    monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
	    weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
	    weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT: 'HH:mm',
	        LTS: 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY HH:mm',
	        LLLL : 'dddd, D. MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[heute um] LT [Uhr]',
	        sameElse: 'L',
	        nextDay: '[morgen um] LT [Uhr]',
	        nextWeek: 'dddd [um] LT [Uhr]',
	        lastDay: '[gestern um] LT [Uhr]',
	        lastWeek: '[letzten] dddd [um] LT [Uhr]'
	    },
	    relativeTime : {
	        future : 'in %s',
	        past : 'vor %s',
	        s : 'ein paar Sekunden',
	        m : processRelativeTime,
	        mm : '%d Minuten',
	        h : processRelativeTime,
	        hh : '%d Stunden',
	        d : processRelativeTime,
	        dd : processRelativeTime,
	        M : processRelativeTime,
	        MM : processRelativeTime,
	        y : processRelativeTime,
	        yy : processRelativeTime
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return deAt;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/de-at.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/dv.js **/
jupyter.define('moment@2.17.1/locale/dv.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Maldivian [dv]
	//! author : Jawish Hameed : https://github.com/jawish
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var months = [
	    'ޖެނުއަރީ',
	    'ފެބްރުއަރީ',
	    'މާރިޗު',
	    'އޭޕްރީލު',
	    'މޭ',
	    'ޖޫން',
	    'ޖުލައި',
	    'އޯގަސްޓު',
	    'ސެޕްޓެމްބަރު',
	    'އޮކްޓޯބަރު',
	    'ނޮވެމްބަރު',
	    'ޑިސެމްބަރު'
	];
	var weekdays = [
	    'އާދިއްތަ',
	    'ހޯމަ',
	    'އަންގާރަ',
	    'ބުދަ',
	    'ބުރާސްފަތި',
	    'ހުކުރު',
	    'ހޮނިހިރު'
	];
	
	var dv = moment.defineLocale('dv', {
	    months : months,
	    monthsShort : months,
	    weekdays : weekdays,
	    weekdaysShort : weekdays,
	    weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'),
	    longDateFormat : {
	
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'D/M/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    meridiemParse: /މކ|މފ/,
	    isPM : function (input) {
	        return 'މފ' === input;
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 12) {
	            return 'މކ';
	        } else {
	            return 'މފ';
	        }
	    },
	    calendar : {
	        sameDay : '[މިއަދު] LT',
	        nextDay : '[މާދަމާ] LT',
	        nextWeek : 'dddd LT',
	        lastDay : '[އިއްޔެ] LT',
	        lastWeek : '[ފާއިތުވި] dddd LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'ތެރޭގައި %s',
	        past : 'ކުރިން %s',
	        s : 'ސިކުންތުކޮޅެއް',
	        m : 'މިނިޓެއް',
	        mm : 'މިނިޓު %d',
	        h : 'ގަޑިއިރެއް',
	        hh : 'ގަޑިއިރު %d',
	        d : 'ދުވަހެއް',
	        dd : 'ދުވަސް %d',
	        M : 'މަހެއް',
	        MM : 'މަސް %d',
	        y : 'އަހަރެއް',
	        yy : 'އަހަރު %d'
	    },
	    preparse: function (string) {
	        return string.replace(/،/g, ',');
	    },
	    postformat: function (string) {
	        return string.replace(/,/g, '،');
	    },
	    week : {
	        dow : 7,  // Sunday is the first day of the week.
	        doy : 12  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return dv;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/dv.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/el.js **/
jupyter.define('moment@2.17.1/locale/el.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Greek [el]
	//! author : Aggelos Karalias : https://github.com/mehiel
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	function isFunction(input) {
	    return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
	}
	
	
	var el = moment.defineLocale('el', {
	    monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'),
	    monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'),
	    months : function (momentToFormat, format) {
	        if (/D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM'
	            return this._monthsGenitiveEl[momentToFormat.month()];
	        } else {
	            return this._monthsNominativeEl[momentToFormat.month()];
	        }
	    },
	    monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'),
	    weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'),
	    weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'),
	    weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'),
	    meridiem : function (hours, minutes, isLower) {
	        if (hours > 11) {
	            return isLower ? 'μμ' : 'ΜΜ';
	        } else {
	            return isLower ? 'πμ' : 'ΠΜ';
	        }
	    },
	    isPM : function (input) {
	        return ((input + '').toLowerCase()[0] === 'μ');
	    },
	    meridiemParse : /[ΠΜ]\.?Μ?\.?/i,
	    longDateFormat : {
	        LT : 'h:mm A',
	        LTS : 'h:mm:ss A',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY h:mm A',
	        LLLL : 'dddd, D MMMM YYYY h:mm A'
	    },
	    calendarEl : {
	        sameDay : '[Σήμερα {}] LT',
	        nextDay : '[Αύριο {}] LT',
	        nextWeek : 'dddd [{}] LT',
	        lastDay : '[Χθες {}] LT',
	        lastWeek : function () {
	            switch (this.day()) {
	                case 6:
	                    return '[το προηγούμενο] dddd [{}] LT';
	                default:
	                    return '[την προηγούμενη] dddd [{}] LT';
	            }
	        },
	        sameElse : 'L'
	    },
	    calendar : function (key, mom) {
	        var output = this._calendarEl[key],
	            hours = mom && mom.hours();
	        if (isFunction(output)) {
	            output = output.apply(mom);
	        }
	        return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις'));
	    },
	    relativeTime : {
	        future : 'σε %s',
	        past : '%s πριν',
	        s : 'λίγα δευτερόλεπτα',
	        m : 'ένα λεπτό',
	        mm : '%d λεπτά',
	        h : 'μία ώρα',
	        hh : '%d ώρες',
	        d : 'μία μέρα',
	        dd : '%d μέρες',
	        M : 'ένας μήνας',
	        MM : '%d μήνες',
	        y : 'ένας χρόνος',
	        yy : '%d χρόνια'
	    },
	    ordinalParse: /\d{1,2}η/,
	    ordinal: '%dη',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4st is the first week of the year.
	    }
	});
	
	return el;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/el.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/en-au.js **/
jupyter.define('moment@2.17.1/locale/en-au.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : English (Australia) [en-au]
	//! author : Jared Morse : https://github.com/jarcoal
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var enAu = moment.defineLocale('en-au', {
	    months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	    monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	    weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	    weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	    weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	    longDateFormat : {
	        LT : 'h:mm A',
	        LTS : 'h:mm:ss A',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY h:mm A',
	        LLLL : 'dddd, D MMMM YYYY h:mm A'
	    },
	    calendar : {
	        sameDay : '[Today at] LT',
	        nextDay : '[Tomorrow at] LT',
	        nextWeek : 'dddd [at] LT',
	        lastDay : '[Yesterday at] LT',
	        lastWeek : '[Last] dddd [at] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'in %s',
	        past : '%s ago',
	        s : 'a few seconds',
	        m : 'a minute',
	        mm : '%d minutes',
	        h : 'an hour',
	        hh : '%d hours',
	        d : 'a day',
	        dd : '%d days',
	        M : 'a month',
	        MM : '%d months',
	        y : 'a year',
	        yy : '%d years'
	    },
	    ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	    ordinal : function (number) {
	        var b = number % 10,
	            output = (~~(number % 100 / 10) === 1) ? 'th' :
	            (b === 1) ? 'st' :
	            (b === 2) ? 'nd' :
	            (b === 3) ? 'rd' : 'th';
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return enAu;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/en-au.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/en-ca.js **/
jupyter.define('moment@2.17.1/locale/en-ca.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : English (Canada) [en-ca]
	//! author : Jonathan Abourbih : https://github.com/jonbca
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var enCa = moment.defineLocale('en-ca', {
	    months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	    monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	    weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	    weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	    weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	    longDateFormat : {
	        LT : 'h:mm A',
	        LTS : 'h:mm:ss A',
	        L : 'YYYY-MM-DD',
	        LL : 'MMMM D, YYYY',
	        LLL : 'MMMM D, YYYY h:mm A',
	        LLLL : 'dddd, MMMM D, YYYY h:mm A'
	    },
	    calendar : {
	        sameDay : '[Today at] LT',
	        nextDay : '[Tomorrow at] LT',
	        nextWeek : 'dddd [at] LT',
	        lastDay : '[Yesterday at] LT',
	        lastWeek : '[Last] dddd [at] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'in %s',
	        past : '%s ago',
	        s : 'a few seconds',
	        m : 'a minute',
	        mm : '%d minutes',
	        h : 'an hour',
	        hh : '%d hours',
	        d : 'a day',
	        dd : '%d days',
	        M : 'a month',
	        MM : '%d months',
	        y : 'a year',
	        yy : '%d years'
	    },
	    ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	    ordinal : function (number) {
	        var b = number % 10,
	            output = (~~(number % 100 / 10) === 1) ? 'th' :
	            (b === 1) ? 'st' :
	            (b === 2) ? 'nd' :
	            (b === 3) ? 'rd' : 'th';
	        return number + output;
	    }
	});
	
	return enCa;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/en-ca.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/en-gb.js **/
jupyter.define('moment@2.17.1/locale/en-gb.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : English (United Kingdom) [en-gb]
	//! author : Chris Gedrim : https://github.com/chrisgedrim
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var enGb = moment.defineLocale('en-gb', {
	    months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	    monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	    weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	    weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	    weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[Today at] LT',
	        nextDay : '[Tomorrow at] LT',
	        nextWeek : 'dddd [at] LT',
	        lastDay : '[Yesterday at] LT',
	        lastWeek : '[Last] dddd [at] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'in %s',
	        past : '%s ago',
	        s : 'a few seconds',
	        m : 'a minute',
	        mm : '%d minutes',
	        h : 'an hour',
	        hh : '%d hours',
	        d : 'a day',
	        dd : '%d days',
	        M : 'a month',
	        MM : '%d months',
	        y : 'a year',
	        yy : '%d years'
	    },
	    ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	    ordinal : function (number) {
	        var b = number % 10,
	            output = (~~(number % 100 / 10) === 1) ? 'th' :
	            (b === 1) ? 'st' :
	            (b === 2) ? 'nd' :
	            (b === 3) ? 'rd' : 'th';
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return enGb;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/en-gb.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/en-ie.js **/
jupyter.define('moment@2.17.1/locale/en-ie.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : English (Ireland) [en-ie]
	//! author : Chris Cartlidge : https://github.com/chriscartlidge
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var enIe = moment.defineLocale('en-ie', {
	    months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	    monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	    weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	    weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	    weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD-MM-YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[Today at] LT',
	        nextDay : '[Tomorrow at] LT',
	        nextWeek : 'dddd [at] LT',
	        lastDay : '[Yesterday at] LT',
	        lastWeek : '[Last] dddd [at] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'in %s',
	        past : '%s ago',
	        s : 'a few seconds',
	        m : 'a minute',
	        mm : '%d minutes',
	        h : 'an hour',
	        hh : '%d hours',
	        d : 'a day',
	        dd : '%d days',
	        M : 'a month',
	        MM : '%d months',
	        y : 'a year',
	        yy : '%d years'
	    },
	    ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	    ordinal : function (number) {
	        var b = number % 10,
	            output = (~~(number % 100 / 10) === 1) ? 'th' :
	            (b === 1) ? 'st' :
	            (b === 2) ? 'nd' :
	            (b === 3) ? 'rd' : 'th';
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return enIe;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/en-ie.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/en-nz.js **/
jupyter.define('moment@2.17.1/locale/en-nz.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : English (New Zealand) [en-nz]
	//! author : Luke McGregor : https://github.com/lukemcgregor
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var enNz = moment.defineLocale('en-nz', {
	    months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
	    monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
	    weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
	    weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
	    weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
	    longDateFormat : {
	        LT : 'h:mm A',
	        LTS : 'h:mm:ss A',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY h:mm A',
	        LLLL : 'dddd, D MMMM YYYY h:mm A'
	    },
	    calendar : {
	        sameDay : '[Today at] LT',
	        nextDay : '[Tomorrow at] LT',
	        nextWeek : 'dddd [at] LT',
	        lastDay : '[Yesterday at] LT',
	        lastWeek : '[Last] dddd [at] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'in %s',
	        past : '%s ago',
	        s : 'a few seconds',
	        m : 'a minute',
	        mm : '%d minutes',
	        h : 'an hour',
	        hh : '%d hours',
	        d : 'a day',
	        dd : '%d days',
	        M : 'a month',
	        MM : '%d months',
	        y : 'a year',
	        yy : '%d years'
	    },
	    ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	    ordinal : function (number) {
	        var b = number % 10,
	            output = (~~(number % 100 / 10) === 1) ? 'th' :
	            (b === 1) ? 'st' :
	            (b === 2) ? 'nd' :
	            (b === 3) ? 'rd' : 'th';
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return enNz;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/en-nz.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/eo.js **/
jupyter.define('moment@2.17.1/locale/eo.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Esperanto [eo]
	//! author : Colin Dean : https://github.com/colindean
	//! komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko.
	//!          Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni!
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var eo = moment.defineLocale('eo', {
	    months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'),
	    monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'),
	    weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'),
	    weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'),
	    weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'YYYY-MM-DD',
	        LL : 'D[-an de] MMMM, YYYY',
	        LLL : 'D[-an de] MMMM, YYYY HH:mm',
	        LLLL : 'dddd, [la] D[-an de] MMMM, YYYY HH:mm'
	    },
	    meridiemParse: /[ap]\.t\.m/i,
	    isPM: function (input) {
	        return input.charAt(0).toLowerCase() === 'p';
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours > 11) {
	            return isLower ? 'p.t.m.' : 'P.T.M.';
	        } else {
	            return isLower ? 'a.t.m.' : 'A.T.M.';
	        }
	    },
	    calendar : {
	        sameDay : '[Hodiaŭ je] LT',
	        nextDay : '[Morgaŭ je] LT',
	        nextWeek : 'dddd [je] LT',
	        lastDay : '[Hieraŭ je] LT',
	        lastWeek : '[pasinta] dddd [je] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'je %s',
	        past : 'antaŭ %s',
	        s : 'sekundoj',
	        m : 'minuto',
	        mm : '%d minutoj',
	        h : 'horo',
	        hh : '%d horoj',
	        d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo
	        dd : '%d tagoj',
	        M : 'monato',
	        MM : '%d monatoj',
	        y : 'jaro',
	        yy : '%d jaroj'
	    },
	    ordinalParse: /\d{1,2}a/,
	    ordinal : '%da',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return eo;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/eo.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/es.js **/
jupyter.define('moment@2.17.1/locale/es.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Spanish [es]
	//! author : Julio Napurí : https://github.com/julionc
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
	var monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
	
	var es = moment.defineLocale('es', {
	    months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
	    monthsShort : function (m, format) {
	        if (/-MMM-/.test(format)) {
	            return monthsShort[m.month()];
	        } else {
	            return monthsShortDot[m.month()];
	        }
	    },
	    monthsParseExact : true,
	    weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
	    weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
	    weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D [de] MMMM [de] YYYY',
	        LLL : 'D [de] MMMM [de] YYYY H:mm',
	        LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm'
	    },
	    calendar : {
	        sameDay : function () {
	            return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        nextDay : function () {
	            return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        nextWeek : function () {
	            return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        lastDay : function () {
	            return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        lastWeek : function () {
	            return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'en %s',
	        past : 'hace %s',
	        s : 'unos segundos',
	        m : 'un minuto',
	        mm : '%d minutos',
	        h : 'una hora',
	        hh : '%d horas',
	        d : 'un día',
	        dd : '%d días',
	        M : 'un mes',
	        MM : '%d meses',
	        y : 'un año',
	        yy : '%d años'
	    },
	    ordinalParse : /\d{1,2}º/,
	    ordinal : '%dº',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return es;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/es.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/es-do.js **/
jupyter.define('moment@2.17.1/locale/es-do.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Spanish (Dominican Republic) [es-do]
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
	var monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
	
	var esDo = moment.defineLocale('es-do', {
	    months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
	    monthsShort : function (m, format) {
	        if (/-MMM-/.test(format)) {
	            return monthsShort[m.month()];
	        } else {
	            return monthsShortDot[m.month()];
	        }
	    },
	    monthsParseExact : true,
	    weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
	    weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
	    weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'h:mm A',
	        LTS : 'h:mm:ss A',
	        L : 'DD/MM/YYYY',
	        LL : 'D [de] MMMM [de] YYYY',
	        LLL : 'D [de] MMMM [de] YYYY h:mm A',
	        LLLL : 'dddd, D [de] MMMM [de] YYYY h:mm A'
	    },
	    calendar : {
	        sameDay : function () {
	            return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        nextDay : function () {
	            return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        nextWeek : function () {
	            return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        lastDay : function () {
	            return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        lastWeek : function () {
	            return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'en %s',
	        past : 'hace %s',
	        s : 'unos segundos',
	        m : 'un minuto',
	        mm : '%d minutos',
	        h : 'una hora',
	        hh : '%d horas',
	        d : 'un día',
	        dd : '%d días',
	        M : 'un mes',
	        MM : '%d meses',
	        y : 'un año',
	        yy : '%d años'
	    },
	    ordinalParse : /\d{1,2}º/,
	    ordinal : '%dº',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return esDo;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/es-do.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/et.js **/
jupyter.define('moment@2.17.1/locale/et.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Estonian [et]
	//! author : Henry Kehlmann : https://github.com/madhenry
	//! improvements : Illimar Tambek : https://github.com/ragulka
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function processRelativeTime(number, withoutSuffix, key, isFuture) {
	    var format = {
	        's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
	        'm' : ['ühe minuti', 'üks minut'],
	        'mm': [number + ' minuti', number + ' minutit'],
	        'h' : ['ühe tunni', 'tund aega', 'üks tund'],
	        'hh': [number + ' tunni', number + ' tundi'],
	        'd' : ['ühe päeva', 'üks päev'],
	        'M' : ['kuu aja', 'kuu aega', 'üks kuu'],
	        'MM': [number + ' kuu', number + ' kuud'],
	        'y' : ['ühe aasta', 'aasta', 'üks aasta'],
	        'yy': [number + ' aasta', number + ' aastat']
	    };
	    if (withoutSuffix) {
	        return format[key][2] ? format[key][2] : format[key][1];
	    }
	    return isFuture ? format[key][0] : format[key][1];
	}
	
	var et = moment.defineLocale('et', {
	    months        : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'),
	    monthsShort   : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'),
	    weekdays      : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'),
	    weekdaysShort : 'P_E_T_K_N_R_L'.split('_'),
	    weekdaysMin   : 'P_E_T_K_N_R_L'.split('_'),
	    longDateFormat : {
	        LT   : 'H:mm',
	        LTS : 'H:mm:ss',
	        L    : 'DD.MM.YYYY',
	        LL   : 'D. MMMM YYYY',
	        LLL  : 'D. MMMM YYYY H:mm',
	        LLLL : 'dddd, D. MMMM YYYY H:mm'
	    },
	    calendar : {
	        sameDay  : '[Täna,] LT',
	        nextDay  : '[Homme,] LT',
	        nextWeek : '[Järgmine] dddd LT',
	        lastDay  : '[Eile,] LT',
	        lastWeek : '[Eelmine] dddd LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s pärast',
	        past   : '%s tagasi',
	        s      : processRelativeTime,
	        m      : processRelativeTime,
	        mm     : processRelativeTime,
	        h      : processRelativeTime,
	        hh     : processRelativeTime,
	        d      : processRelativeTime,
	        dd     : '%d päeva',
	        M      : processRelativeTime,
	        MM     : processRelativeTime,
	        y      : processRelativeTime,
	        yy     : processRelativeTime
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return et;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/et.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/eu.js **/
jupyter.define('moment@2.17.1/locale/eu.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Basque [eu]
	//! author : Eneko Illarramendi : https://github.com/eillarra
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var eu = moment.defineLocale('eu', {
	    months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'),
	    monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'),
	    weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'),
	    weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'YYYY-MM-DD',
	        LL : 'YYYY[ko] MMMM[ren] D[a]',
	        LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm',
	        LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
	        l : 'YYYY-M-D',
	        ll : 'YYYY[ko] MMM D[a]',
	        lll : 'YYYY[ko] MMM D[a] HH:mm',
	        llll : 'ddd, YYYY[ko] MMM D[a] HH:mm'
	    },
	    calendar : {
	        sameDay : '[gaur] LT[etan]',
	        nextDay : '[bihar] LT[etan]',
	        nextWeek : 'dddd LT[etan]',
	        lastDay : '[atzo] LT[etan]',
	        lastWeek : '[aurreko] dddd LT[etan]',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s barru',
	        past : 'duela %s',
	        s : 'segundo batzuk',
	        m : 'minutu bat',
	        mm : '%d minutu',
	        h : 'ordu bat',
	        hh : '%d ordu',
	        d : 'egun bat',
	        dd : '%d egun',
	        M : 'hilabete bat',
	        MM : '%d hilabete',
	        y : 'urte bat',
	        yy : '%d urte'
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return eu;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/eu.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/fa.js **/
jupyter.define('moment@2.17.1/locale/fa.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Persian [fa]
	//! author : Ebrahim Byagowi : https://github.com/ebraminio
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '۱',
	    '2': '۲',
	    '3': '۳',
	    '4': '۴',
	    '5': '۵',
	    '6': '۶',
	    '7': '۷',
	    '8': '۸',
	    '9': '۹',
	    '0': '۰'
	};
	var numberMap = {
	    '۱': '1',
	    '۲': '2',
	    '۳': '3',
	    '۴': '4',
	    '۵': '5',
	    '۶': '6',
	    '۷': '7',
	    '۸': '8',
	    '۹': '9',
	    '۰': '0'
	};
	
	var fa = moment.defineLocale('fa', {
	    months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
	    monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
	    weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
	    weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
	    weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    meridiemParse: /قبل از ظهر|بعد از ظهر/,
	    isPM: function (input) {
	        return /بعد از ظهر/.test(input);
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 12) {
	            return 'قبل از ظهر';
	        } else {
	            return 'بعد از ظهر';
	        }
	    },
	    calendar : {
	        sameDay : '[امروز ساعت] LT',
	        nextDay : '[فردا ساعت] LT',
	        nextWeek : 'dddd [ساعت] LT',
	        lastDay : '[دیروز ساعت] LT',
	        lastWeek : 'dddd [پیش] [ساعت] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'در %s',
	        past : '%s پیش',
	        s : 'چندین ثانیه',
	        m : 'یک دقیقه',
	        mm : '%d دقیقه',
	        h : 'یک ساعت',
	        hh : '%d ساعت',
	        d : 'یک روز',
	        dd : '%d روز',
	        M : 'یک ماه',
	        MM : '%d ماه',
	        y : 'یک سال',
	        yy : '%d سال'
	    },
	    preparse: function (string) {
	        return string.replace(/[۰-۹]/g, function (match) {
	            return numberMap[match];
	        }).replace(/،/g, ',');
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        }).replace(/,/g, '،');
	    },
	    ordinalParse: /\d{1,2}م/,
	    ordinal : '%dم',
	    week : {
	        dow : 6, // Saturday is the first day of the week.
	        doy : 12 // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return fa;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/fa.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/fi.js **/
jupyter.define('moment@2.17.1/locale/fi.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Finnish [fi]
	//! author : Tarmo Aidantausta : https://github.com/bleadof
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' ');
	var numbersFuture = [
	        'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
	        numbersPast[7], numbersPast[8], numbersPast[9]
	    ];
	function translate(number, withoutSuffix, key, isFuture) {
	    var result = '';
	    switch (key) {
	        case 's':
	            return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
	        case 'm':
	            return isFuture ? 'minuutin' : 'minuutti';
	        case 'mm':
	            result = isFuture ? 'minuutin' : 'minuuttia';
	            break;
	        case 'h':
	            return isFuture ? 'tunnin' : 'tunti';
	        case 'hh':
	            result = isFuture ? 'tunnin' : 'tuntia';
	            break;
	        case 'd':
	            return isFuture ? 'päivän' : 'päivä';
	        case 'dd':
	            result = isFuture ? 'päivän' : 'päivää';
	            break;
	        case 'M':
	            return isFuture ? 'kuukauden' : 'kuukausi';
	        case 'MM':
	            result = isFuture ? 'kuukauden' : 'kuukautta';
	            break;
	        case 'y':
	            return isFuture ? 'vuoden' : 'vuosi';
	        case 'yy':
	            result = isFuture ? 'vuoden' : 'vuotta';
	            break;
	    }
	    result = verbalNumber(number, isFuture) + ' ' + result;
	    return result;
	}
	function verbalNumber(number, isFuture) {
	    return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number;
	}
	
	var fi = moment.defineLocale('fi', {
	    months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'),
	    monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'),
	    weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'),
	    weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'),
	    weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'),
	    longDateFormat : {
	        LT : 'HH.mm',
	        LTS : 'HH.mm.ss',
	        L : 'DD.MM.YYYY',
	        LL : 'Do MMMM[ta] YYYY',
	        LLL : 'Do MMMM[ta] YYYY, [klo] HH.mm',
	        LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm',
	        l : 'D.M.YYYY',
	        ll : 'Do MMM YYYY',
	        lll : 'Do MMM YYYY, [klo] HH.mm',
	        llll : 'ddd, Do MMM YYYY, [klo] HH.mm'
	    },
	    calendar : {
	        sameDay : '[tänään] [klo] LT',
	        nextDay : '[huomenna] [klo] LT',
	        nextWeek : 'dddd [klo] LT',
	        lastDay : '[eilen] [klo] LT',
	        lastWeek : '[viime] dddd[na] [klo] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s päästä',
	        past : '%s sitten',
	        s : translate,
	        m : translate,
	        mm : translate,
	        h : translate,
	        hh : translate,
	        d : translate,
	        dd : translate,
	        M : translate,
	        MM : translate,
	        y : translate,
	        yy : translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return fi;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/fi.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/fo.js **/
jupyter.define('moment@2.17.1/locale/fo.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Faroese [fo]
	//! author : Ragnar Johannesen : https://github.com/ragnar123
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var fo = moment.defineLocale('fo', {
	    months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
	    monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
	    weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'),
	    weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'),
	    weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D. MMMM, YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[Í dag kl.] LT',
	        nextDay : '[Í morgin kl.] LT',
	        nextWeek : 'dddd [kl.] LT',
	        lastDay : '[Í gjár kl.] LT',
	        lastWeek : '[síðstu] dddd [kl] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'um %s',
	        past : '%s síðani',
	        s : 'fá sekund',
	        m : 'ein minutt',
	        mm : '%d minuttir',
	        h : 'ein tími',
	        hh : '%d tímar',
	        d : 'ein dagur',
	        dd : '%d dagar',
	        M : 'ein mánaði',
	        MM : '%d mánaðir',
	        y : 'eitt ár',
	        yy : '%d ár'
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return fo;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/fo.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/fr.js **/
jupyter.define('moment@2.17.1/locale/fr.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : French [fr]
	//! author : John Fischer : https://github.com/jfroffice
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var fr = moment.defineLocale('fr', {
	    months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
	    monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
	    weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
	    weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[Aujourd\'hui à] LT',
	        nextDay: '[Demain à] LT',
	        nextWeek: 'dddd [à] LT',
	        lastDay: '[Hier à] LT',
	        lastWeek: 'dddd [dernier à] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'dans %s',
	        past : 'il y a %s',
	        s : 'quelques secondes',
	        m : 'une minute',
	        mm : '%d minutes',
	        h : 'une heure',
	        hh : '%d heures',
	        d : 'un jour',
	        dd : '%d jours',
	        M : 'un mois',
	        MM : '%d mois',
	        y : 'un an',
	        yy : '%d ans'
	    },
	    ordinalParse: /\d{1,2}(er|)/,
	    ordinal : function (number) {
	        return number + (number === 1 ? 'er' : '');
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return fr;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/fr.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/fr-ca.js **/
jupyter.define('moment@2.17.1/locale/fr-ca.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : French (Canada) [fr-ca]
	//! author : Jonathan Abourbih : https://github.com/jonbca
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var frCa = moment.defineLocale('fr-ca', {
	    months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
	    monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
	    weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
	    weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'YYYY-MM-DD',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[Aujourd\'hui à] LT',
	        nextDay: '[Demain à] LT',
	        nextWeek: 'dddd [à] LT',
	        lastDay: '[Hier à] LT',
	        lastWeek: 'dddd [dernier à] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'dans %s',
	        past : 'il y a %s',
	        s : 'quelques secondes',
	        m : 'une minute',
	        mm : '%d minutes',
	        h : 'une heure',
	        hh : '%d heures',
	        d : 'un jour',
	        dd : '%d jours',
	        M : 'un mois',
	        MM : '%d mois',
	        y : 'un an',
	        yy : '%d ans'
	    },
	    ordinalParse: /\d{1,2}(er|e)/,
	    ordinal : function (number) {
	        return number + (number === 1 ? 'er' : 'e');
	    }
	});
	
	return frCa;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/fr-ca.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/fr-ch.js **/
jupyter.define('moment@2.17.1/locale/fr-ch.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : French (Switzerland) [fr-ch]
	//! author : Gaspard Bucher : https://github.com/gaspard
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var frCh = moment.defineLocale('fr-ch', {
	    months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
	    monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
	    weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
	    weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[Aujourd\'hui à] LT',
	        nextDay: '[Demain à] LT',
	        nextWeek: 'dddd [à] LT',
	        lastDay: '[Hier à] LT',
	        lastWeek: 'dddd [dernier à] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'dans %s',
	        past : 'il y a %s',
	        s : 'quelques secondes',
	        m : 'une minute',
	        mm : '%d minutes',
	        h : 'une heure',
	        hh : '%d heures',
	        d : 'un jour',
	        dd : '%d jours',
	        M : 'un mois',
	        MM : '%d mois',
	        y : 'un an',
	        yy : '%d ans'
	    },
	    ordinalParse: /\d{1,2}(er|e)/,
	    ordinal : function (number) {
	        return number + (number === 1 ? 'er' : 'e');
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return frCh;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/fr-ch.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/fy.js **/
jupyter.define('moment@2.17.1/locale/fy.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Frisian [fy]
	//! author : Robin van der Vliet : https://github.com/robin0van0der0v
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_');
	var monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_');
	
	var fy = moment.defineLocale('fy', {
	    months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'),
	    monthsShort : function (m, format) {
	        if (/-MMM-/.test(format)) {
	            return monthsShortWithoutDots[m.month()];
	        } else {
	            return monthsShortWithDots[m.month()];
	        }
	    },
	    monthsParseExact : true,
	    weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'),
	    weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'),
	    weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD-MM-YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[hjoed om] LT',
	        nextDay: '[moarn om] LT',
	        nextWeek: 'dddd [om] LT',
	        lastDay: '[juster om] LT',
	        lastWeek: '[ôfrûne] dddd [om] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'oer %s',
	        past : '%s lyn',
	        s : 'in pear sekonden',
	        m : 'ien minút',
	        mm : '%d minuten',
	        h : 'ien oere',
	        hh : '%d oeren',
	        d : 'ien dei',
	        dd : '%d dagen',
	        M : 'ien moanne',
	        MM : '%d moannen',
	        y : 'ien jier',
	        yy : '%d jierren'
	    },
	    ordinalParse: /\d{1,2}(ste|de)/,
	    ordinal : function (number) {
	        return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return fy;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/fy.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/gd.js **/
jupyter.define('moment@2.17.1/locale/gd.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Scottish Gaelic [gd]
	//! author : Jon Ashdown : https://github.com/jonashdown
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var months = [
	    'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'
	];
	
	var monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'];
	
	var weekdays = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'];
	
	var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'];
	
	var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'];
	
	var gd = moment.defineLocale('gd', {
	    months : months,
	    monthsShort : monthsShort,
	    monthsParseExact : true,
	    weekdays : weekdays,
	    weekdaysShort : weekdaysShort,
	    weekdaysMin : weekdaysMin,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[An-diugh aig] LT',
	        nextDay : '[A-màireach aig] LT',
	        nextWeek : 'dddd [aig] LT',
	        lastDay : '[An-dè aig] LT',
	        lastWeek : 'dddd [seo chaidh] [aig] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'ann an %s',
	        past : 'bho chionn %s',
	        s : 'beagan diogan',
	        m : 'mionaid',
	        mm : '%d mionaidean',
	        h : 'uair',
	        hh : '%d uairean',
	        d : 'latha',
	        dd : '%d latha',
	        M : 'mìos',
	        MM : '%d mìosan',
	        y : 'bliadhna',
	        yy : '%d bliadhna'
	    },
	    ordinalParse : /\d{1,2}(d|na|mh)/,
	    ordinal : function (number) {
	        var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh';
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return gd;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/gd.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/gl.js **/
jupyter.define('moment@2.17.1/locale/gl.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Galician [gl]
	//! author : Juan G. Hurtado : https://github.com/juanghurtado
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var gl = moment.defineLocale('gl', {
	    months : 'xaneiro_febreiro_marzo_abril_maio_xuño_xullo_agosto_setembro_outubro_novembro_decembro'.split('_'),
	    monthsShort : 'xan._feb._mar._abr._mai._xuñ._xul._ago._set._out._nov._dec.'.split('_'),
	    monthsParseExact: true,
	    weekdays : 'domingo_luns_martes_mércores_xoves_venres_sábado'.split('_'),
	    weekdaysShort : 'dom._lun._mar._mér._xov._ven._sáb.'.split('_'),
	    weekdaysMin : 'do_lu_ma_mé_xo_ve_sá'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D [de] MMMM [de] YYYY',
	        LLL : 'D [de] MMMM [de] YYYY H:mm',
	        LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm'
	    },
	    calendar : {
	        sameDay : function () {
	            return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
	        },
	        nextDay : function () {
	            return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
	        },
	        nextWeek : function () {
	            return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
	        },
	        lastDay : function () {
	            return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
	        },
	        lastWeek : function () {
	            return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : function (str) {
	            if (str.indexOf('un') === 0) {
	                return 'n' + str;
	            }
	            return 'en ' + str;
	        },
	        past : 'hai %s',
	        s : 'uns segundos',
	        m : 'un minuto',
	        mm : '%d minutos',
	        h : 'unha hora',
	        hh : '%d horas',
	        d : 'un día',
	        dd : '%d días',
	        M : 'un mes',
	        MM : '%d meses',
	        y : 'un ano',
	        yy : '%d anos'
	    },
	    ordinalParse : /\d{1,2}º/,
	    ordinal : '%dº',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return gl;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/gl.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/he.js **/
jupyter.define('moment@2.17.1/locale/he.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Hebrew [he]
	//! author : Tomer Cohen : https://github.com/tomer
	//! author : Moshe Simantov : https://github.com/DevelopmentIL
	//! author : Tal Ater : https://github.com/TalAter
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var he = moment.defineLocale('he', {
	    months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'),
	    monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'),
	    weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'),
	    weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'),
	    weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D [ב]MMMM YYYY',
	        LLL : 'D [ב]MMMM YYYY HH:mm',
	        LLLL : 'dddd, D [ב]MMMM YYYY HH:mm',
	        l : 'D/M/YYYY',
	        ll : 'D MMM YYYY',
	        lll : 'D MMM YYYY HH:mm',
	        llll : 'ddd, D MMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[היום ב־]LT',
	        nextDay : '[מחר ב־]LT',
	        nextWeek : 'dddd [בשעה] LT',
	        lastDay : '[אתמול ב־]LT',
	        lastWeek : '[ביום] dddd [האחרון בשעה] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'בעוד %s',
	        past : 'לפני %s',
	        s : 'מספר שניות',
	        m : 'דקה',
	        mm : '%d דקות',
	        h : 'שעה',
	        hh : function (number) {
	            if (number === 2) {
	                return 'שעתיים';
	            }
	            return number + ' שעות';
	        },
	        d : 'יום',
	        dd : function (number) {
	            if (number === 2) {
	                return 'יומיים';
	            }
	            return number + ' ימים';
	        },
	        M : 'חודש',
	        MM : function (number) {
	            if (number === 2) {
	                return 'חודשיים';
	            }
	            return number + ' חודשים';
	        },
	        y : 'שנה',
	        yy : function (number) {
	            if (number === 2) {
	                return 'שנתיים';
	            } else if (number % 10 === 0 && number !== 10) {
	                return number + ' שנה';
	            }
	            return number + ' שנים';
	        }
	    },
	    meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,
	    isPM : function (input) {
	        return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input);
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 5) {
	            return 'לפנות בוקר';
	        } else if (hour < 10) {
	            return 'בבוקר';
	        } else if (hour < 12) {
	            return isLower ? 'לפנה"צ' : 'לפני הצהריים';
	        } else if (hour < 18) {
	            return isLower ? 'אחה"צ' : 'אחרי הצהריים';
	        } else {
	            return 'בערב';
	        }
	    }
	});
	
	return he;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/he.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/hi.js **/
jupyter.define('moment@2.17.1/locale/hi.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Hindi [hi]
	//! author : Mayank Singhal : https://github.com/mayanksinghal
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '१',
	    '2': '२',
	    '3': '३',
	    '4': '४',
	    '5': '५',
	    '6': '६',
	    '7': '७',
	    '8': '८',
	    '9': '९',
	    '0': '०'
	};
	var numberMap = {
	    '१': '1',
	    '२': '2',
	    '३': '3',
	    '४': '4',
	    '५': '5',
	    '६': '6',
	    '७': '7',
	    '८': '8',
	    '९': '9',
	    '०': '0'
	};
	
	var hi = moment.defineLocale('hi', {
	    months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'),
	    monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'),
	    monthsParseExact: true,
	    weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
	    weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'),
	    weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
	    longDateFormat : {
	        LT : 'A h:mm बजे',
	        LTS : 'A h:mm:ss बजे',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY, A h:mm बजे',
	        LLLL : 'dddd, D MMMM YYYY, A h:mm बजे'
	    },
	    calendar : {
	        sameDay : '[आज] LT',
	        nextDay : '[कल] LT',
	        nextWeek : 'dddd, LT',
	        lastDay : '[कल] LT',
	        lastWeek : '[पिछले] dddd, LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s में',
	        past : '%s पहले',
	        s : 'कुछ ही क्षण',
	        m : 'एक मिनट',
	        mm : '%d मिनट',
	        h : 'एक घंटा',
	        hh : '%d घंटे',
	        d : 'एक दिन',
	        dd : '%d दिन',
	        M : 'एक महीने',
	        MM : '%d महीने',
	        y : 'एक वर्ष',
	        yy : '%d वर्ष'
	    },
	    preparse: function (string) {
	        return string.replace(/[१२३४५६७८९०]/g, function (match) {
	            return numberMap[match];
	        });
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        });
	    },
	    // Hindi notation for meridiems are quite fuzzy in practice. While there exists
	    // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
	    meridiemParse: /रात|सुबह|दोपहर|शाम/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'रात') {
	            return hour < 4 ? hour : hour + 12;
	        } else if (meridiem === 'सुबह') {
	            return hour;
	        } else if (meridiem === 'दोपहर') {
	            return hour >= 10 ? hour : hour + 12;
	        } else if (meridiem === 'शाम') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'रात';
	        } else if (hour < 10) {
	            return 'सुबह';
	        } else if (hour < 17) {
	            return 'दोपहर';
	        } else if (hour < 20) {
	            return 'शाम';
	        } else {
	            return 'रात';
	        }
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return hi;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/hi.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/hr.js **/
jupyter.define('moment@2.17.1/locale/hr.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Croatian [hr]
	//! author : Bojan Marković : https://github.com/bmarkovic
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function translate(number, withoutSuffix, key) {
	    var result = number + ' ';
	    switch (key) {
	        case 'm':
	            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
	        case 'mm':
	            if (number === 1) {
	                result += 'minuta';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'minute';
	            } else {
	                result += 'minuta';
	            }
	            return result;
	        case 'h':
	            return withoutSuffix ? 'jedan sat' : 'jednog sata';
	        case 'hh':
	            if (number === 1) {
	                result += 'sat';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'sata';
	            } else {
	                result += 'sati';
	            }
	            return result;
	        case 'dd':
	            if (number === 1) {
	                result += 'dan';
	            } else {
	                result += 'dana';
	            }
	            return result;
	        case 'MM':
	            if (number === 1) {
	                result += 'mjesec';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'mjeseca';
	            } else {
	                result += 'mjeseci';
	            }
	            return result;
	        case 'yy':
	            if (number === 1) {
	                result += 'godina';
	            } else if (number === 2 || number === 3 || number === 4) {
	                result += 'godine';
	            } else {
	                result += 'godina';
	            }
	            return result;
	    }
	}
	
	var hr = moment.defineLocale('hr', {
	    months : {
	        format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split('_'),
	        standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_')
	    },
	    monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'),
	    monthsParseExact: true,
	    weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
	    weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
	    weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY H:mm',
	        LLLL : 'dddd, D. MMMM YYYY H:mm'
	    },
	    calendar : {
	        sameDay  : '[danas u] LT',
	        nextDay  : '[sutra u] LT',
	        nextWeek : function () {
	            switch (this.day()) {
	                case 0:
	                    return '[u] [nedjelju] [u] LT';
	                case 3:
	                    return '[u] [srijedu] [u] LT';
	                case 6:
	                    return '[u] [subotu] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[u] dddd [u] LT';
	            }
	        },
	        lastDay  : '[jučer u] LT',
	        lastWeek : function () {
	            switch (this.day()) {
	                case 0:
	                case 3:
	                    return '[prošlu] dddd [u] LT';
	                case 6:
	                    return '[prošle] [subote] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[prošli] dddd [u] LT';
	            }
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'za %s',
	        past   : 'prije %s',
	        s      : 'par sekundi',
	        m      : translate,
	        mm     : translate,
	        h      : translate,
	        hh     : translate,
	        d      : 'dan',
	        dd     : translate,
	        M      : 'mjesec',
	        MM     : translate,
	        y      : 'godinu',
	        yy     : translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return hr;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/hr.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/hu.js **/
jupyter.define('moment@2.17.1/locale/hu.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Hungarian [hu]
	//! author : Adam Brunner : https://github.com/adambrunner
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
	function translate(number, withoutSuffix, key, isFuture) {
	    var num = number,
	        suffix;
	    switch (key) {
	        case 's':
	            return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
	        case 'm':
	            return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
	        case 'mm':
	            return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
	        case 'h':
	            return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
	        case 'hh':
	            return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
	        case 'd':
	            return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
	        case 'dd':
	            return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
	        case 'M':
	            return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
	        case 'MM':
	            return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
	        case 'y':
	            return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
	        case 'yy':
	            return num + (isFuture || withoutSuffix ? ' év' : ' éve');
	    }
	    return '';
	}
	function week(isFuture) {
	    return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
	}
	
	var hu = moment.defineLocale('hu', {
	    months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'),
	    monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'),
	    weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'),
	    weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'),
	    weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'),
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'YYYY.MM.DD.',
	        LL : 'YYYY. MMMM D.',
	        LLL : 'YYYY. MMMM D. H:mm',
	        LLLL : 'YYYY. MMMM D., dddd H:mm'
	    },
	    meridiemParse: /de|du/i,
	    isPM: function (input) {
	        return input.charAt(1).toLowerCase() === 'u';
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours < 12) {
	            return isLower === true ? 'de' : 'DE';
	        } else {
	            return isLower === true ? 'du' : 'DU';
	        }
	    },
	    calendar : {
	        sameDay : '[ma] LT[-kor]',
	        nextDay : '[holnap] LT[-kor]',
	        nextWeek : function () {
	            return week.call(this, true);
	        },
	        lastDay : '[tegnap] LT[-kor]',
	        lastWeek : function () {
	            return week.call(this, false);
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s múlva',
	        past : '%s',
	        s : translate,
	        m : translate,
	        mm : translate,
	        h : translate,
	        hh : translate,
	        d : translate,
	        dd : translate,
	        M : translate,
	        MM : translate,
	        y : translate,
	        yy : translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return hu;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/hu.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/hy-am.js **/
jupyter.define('moment@2.17.1/locale/hy-am.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Armenian [hy-am]
	//! author : Armendarabyan : https://github.com/armendarabyan
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var hyAm = moment.defineLocale('hy-am', {
	    months : {
	        format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_'),
	        standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_')
	    },
	    monthsShort : 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'),
	    weekdays : 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'),
	    weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
	    weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY թ.',
	        LLL : 'D MMMM YYYY թ., HH:mm',
	        LLLL : 'dddd, D MMMM YYYY թ., HH:mm'
	    },
	    calendar : {
	        sameDay: '[այսօր] LT',
	        nextDay: '[վաղը] LT',
	        lastDay: '[երեկ] LT',
	        nextWeek: function () {
	            return 'dddd [օրը ժամը] LT';
	        },
	        lastWeek: function () {
	            return '[անցած] dddd [օրը ժամը] LT';
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : '%s հետո',
	        past : '%s առաջ',
	        s : 'մի քանի վայրկյան',
	        m : 'րոպե',
	        mm : '%d րոպե',
	        h : 'ժամ',
	        hh : '%d ժամ',
	        d : 'օր',
	        dd : '%d օր',
	        M : 'ամիս',
	        MM : '%d ամիս',
	        y : 'տարի',
	        yy : '%d տարի'
	    },
	    meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,
	    isPM: function (input) {
	        return /^(ցերեկվա|երեկոյան)$/.test(input);
	    },
	    meridiem : function (hour) {
	        if (hour < 4) {
	            return 'գիշերվա';
	        } else if (hour < 12) {
	            return 'առավոտվա';
	        } else if (hour < 17) {
	            return 'ցերեկվա';
	        } else {
	            return 'երեկոյան';
	        }
	    },
	    ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/,
	    ordinal: function (number, period) {
	        switch (period) {
	            case 'DDD':
	            case 'w':
	            case 'W':
	            case 'DDDo':
	                if (number === 1) {
	                    return number + '-ին';
	                }
	                return number + '-րդ';
	            default:
	                return number;
	        }
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return hyAm;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/hy-am.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/id.js **/
jupyter.define('moment@2.17.1/locale/id.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Indonesian [id]
	//! author : Mohammad Satrio Utomo : https://github.com/tyok
	//! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var id = moment.defineLocale('id', {
	    months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'),
	    monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'),
	    weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'),
	    weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'),
	    weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'),
	    longDateFormat : {
	        LT : 'HH.mm',
	        LTS : 'HH.mm.ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY [pukul] HH.mm',
	        LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
	    },
	    meridiemParse: /pagi|siang|sore|malam/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'pagi') {
	            return hour;
	        } else if (meridiem === 'siang') {
	            return hour >= 11 ? hour : hour + 12;
	        } else if (meridiem === 'sore' || meridiem === 'malam') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours < 11) {
	            return 'pagi';
	        } else if (hours < 15) {
	            return 'siang';
	        } else if (hours < 19) {
	            return 'sore';
	        } else {
	            return 'malam';
	        }
	    },
	    calendar : {
	        sameDay : '[Hari ini pukul] LT',
	        nextDay : '[Besok pukul] LT',
	        nextWeek : 'dddd [pukul] LT',
	        lastDay : '[Kemarin pukul] LT',
	        lastWeek : 'dddd [lalu pukul] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'dalam %s',
	        past : '%s yang lalu',
	        s : 'beberapa detik',
	        m : 'semenit',
	        mm : '%d menit',
	        h : 'sejam',
	        hh : '%d jam',
	        d : 'sehari',
	        dd : '%d hari',
	        M : 'sebulan',
	        MM : '%d bulan',
	        y : 'setahun',
	        yy : '%d tahun'
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return id;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/id.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/is.js **/
jupyter.define('moment@2.17.1/locale/is.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Icelandic [is]
	//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function plural(n) {
	    if (n % 100 === 11) {
	        return true;
	    } else if (n % 10 === 1) {
	        return false;
	    }
	    return true;
	}
	function translate(number, withoutSuffix, key, isFuture) {
	    var result = number + ' ';
	    switch (key) {
	        case 's':
	            return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum';
	        case 'm':
	            return withoutSuffix ? 'mínúta' : 'mínútu';
	        case 'mm':
	            if (plural(number)) {
	                return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum');
	            } else if (withoutSuffix) {
	                return result + 'mínúta';
	            }
	            return result + 'mínútu';
	        case 'hh':
	            if (plural(number)) {
	                return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum');
	            }
	            return result + 'klukkustund';
	        case 'd':
	            if (withoutSuffix) {
	                return 'dagur';
	            }
	            return isFuture ? 'dag' : 'degi';
	        case 'dd':
	            if (plural(number)) {
	                if (withoutSuffix) {
	                    return result + 'dagar';
	                }
	                return result + (isFuture ? 'daga' : 'dögum');
	            } else if (withoutSuffix) {
	                return result + 'dagur';
	            }
	            return result + (isFuture ? 'dag' : 'degi');
	        case 'M':
	            if (withoutSuffix) {
	                return 'mánuður';
	            }
	            return isFuture ? 'mánuð' : 'mánuði';
	        case 'MM':
	            if (plural(number)) {
	                if (withoutSuffix) {
	                    return result + 'mánuðir';
	                }
	                return result + (isFuture ? 'mánuði' : 'mánuðum');
	            } else if (withoutSuffix) {
	                return result + 'mánuður';
	            }
	            return result + (isFuture ? 'mánuð' : 'mánuði');
	        case 'y':
	            return withoutSuffix || isFuture ? 'ár' : 'ári';
	        case 'yy':
	            if (plural(number)) {
	                return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
	            }
	            return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
	    }
	}
	
	var is = moment.defineLocale('is', {
	    months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'),
	    monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'),
	    weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'),
	    weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'),
	    weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'),
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY [kl.] H:mm',
	        LLLL : 'dddd, D. MMMM YYYY [kl.] H:mm'
	    },
	    calendar : {
	        sameDay : '[í dag kl.] LT',
	        nextDay : '[á morgun kl.] LT',
	        nextWeek : 'dddd [kl.] LT',
	        lastDay : '[í gær kl.] LT',
	        lastWeek : '[síðasta] dddd [kl.] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'eftir %s',
	        past : 'fyrir %s síðan',
	        s : translate,
	        m : translate,
	        mm : translate,
	        h : 'klukkustund',
	        hh : translate,
	        d : translate,
	        dd : translate,
	        M : translate,
	        MM : translate,
	        y : translate,
	        yy : translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return is;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/is.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/it.js **/
jupyter.define('moment@2.17.1/locale/it.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Italian [it]
	//! author : Lorenzo : https://github.com/aliem
	//! author: Mattia Larentis: https://github.com/nostalgiaz
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var it = moment.defineLocale('it', {
	    months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'),
	    monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'),
	    weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'),
	    weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'),
	    weekdaysMin : 'Do_Lu_Ma_Me_Gi_Ve_Sa'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[Oggi alle] LT',
	        nextDay: '[Domani alle] LT',
	        nextWeek: 'dddd [alle] LT',
	        lastDay: '[Ieri alle] LT',
	        lastWeek: function () {
	            switch (this.day()) {
	                case 0:
	                    return '[la scorsa] dddd [alle] LT';
	                default:
	                    return '[lo scorso] dddd [alle] LT';
	            }
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : function (s) {
	            return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s;
	        },
	        past : '%s fa',
	        s : 'alcuni secondi',
	        m : 'un minuto',
	        mm : '%d minuti',
	        h : 'un\'ora',
	        hh : '%d ore',
	        d : 'un giorno',
	        dd : '%d giorni',
	        M : 'un mese',
	        MM : '%d mesi',
	        y : 'un anno',
	        yy : '%d anni'
	    },
	    ordinalParse : /\d{1,2}º/,
	    ordinal: '%dº',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return it;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/it.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ja.js **/
jupyter.define('moment@2.17.1/locale/ja.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Japanese [ja]
	//! author : LI Long : https://github.com/baryon
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var ja = moment.defineLocale('ja', {
	    months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
	    monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
	    weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'),
	    weekdaysShort : '日_月_火_水_木_金_土'.split('_'),
	    weekdaysMin : '日_月_火_水_木_金_土'.split('_'),
	    longDateFormat : {
	        LT : 'Ah時m分',
	        LTS : 'Ah時m分s秒',
	        L : 'YYYY/MM/DD',
	        LL : 'YYYY年M月D日',
	        LLL : 'YYYY年M月D日Ah時m分',
	        LLLL : 'YYYY年M月D日Ah時m分 dddd'
	    },
	    meridiemParse: /午前|午後/i,
	    isPM : function (input) {
	        return input === '午後';
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 12) {
	            return '午前';
	        } else {
	            return '午後';
	        }
	    },
	    calendar : {
	        sameDay : '[今日] LT',
	        nextDay : '[明日] LT',
	        nextWeek : '[来週]dddd LT',
	        lastDay : '[昨日] LT',
	        lastWeek : '[前週]dddd LT',
	        sameElse : 'L'
	    },
	    ordinalParse : /\d{1,2}日/,
	    ordinal : function (number, period) {
	        switch (period) {
	            case 'd':
	            case 'D':
	            case 'DDD':
	                return number + '日';
	            default:
	                return number;
	        }
	    },
	    relativeTime : {
	        future : '%s後',
	        past : '%s前',
	        s : '数秒',
	        m : '1分',
	        mm : '%d分',
	        h : '1時間',
	        hh : '%d時間',
	        d : '1日',
	        dd : '%d日',
	        M : '1ヶ月',
	        MM : '%dヶ月',
	        y : '1年',
	        yy : '%d年'
	    }
	});
	
	return ja;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ja.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/jv.js **/
jupyter.define('moment@2.17.1/locale/jv.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Javanese [jv]
	//! author : Rony Lantip : https://github.com/lantip
	//! reference: http://jv.wikipedia.org/wiki/Basa_Jawa
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var jv = moment.defineLocale('jv', {
	    months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'),
	    monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'),
	    weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'),
	    weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'),
	    weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'),
	    longDateFormat : {
	        LT : 'HH.mm',
	        LTS : 'HH.mm.ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY [pukul] HH.mm',
	        LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
	    },
	    meridiemParse: /enjing|siyang|sonten|ndalu/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'enjing') {
	            return hour;
	        } else if (meridiem === 'siyang') {
	            return hour >= 11 ? hour : hour + 12;
	        } else if (meridiem === 'sonten' || meridiem === 'ndalu') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours < 11) {
	            return 'enjing';
	        } else if (hours < 15) {
	            return 'siyang';
	        } else if (hours < 19) {
	            return 'sonten';
	        } else {
	            return 'ndalu';
	        }
	    },
	    calendar : {
	        sameDay : '[Dinten puniko pukul] LT',
	        nextDay : '[Mbenjang pukul] LT',
	        nextWeek : 'dddd [pukul] LT',
	        lastDay : '[Kala wingi pukul] LT',
	        lastWeek : 'dddd [kepengker pukul] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'wonten ing %s',
	        past : '%s ingkang kepengker',
	        s : 'sawetawis detik',
	        m : 'setunggal menit',
	        mm : '%d menit',
	        h : 'setunggal jam',
	        hh : '%d jam',
	        d : 'sedinten',
	        dd : '%d dinten',
	        M : 'sewulan',
	        MM : '%d wulan',
	        y : 'setaun',
	        yy : '%d taun'
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return jv;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/jv.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ka.js **/
jupyter.define('moment@2.17.1/locale/ka.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Georgian [ka]
	//! author : Irakli Janiashvili : https://github.com/irakli-janiashvili
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var ka = moment.defineLocale('ka', {
	    months : {
	        standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
	        format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
	    },
	    monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'),
	    weekdays : {
	        standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
	        format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'),
	        isFormat: /(წინა|შემდეგ)/
	    },
	    weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'),
	    weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'),
	    longDateFormat : {
	        LT : 'h:mm A',
	        LTS : 'h:mm:ss A',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY h:mm A',
	        LLLL : 'dddd, D MMMM YYYY h:mm A'
	    },
	    calendar : {
	        sameDay : '[დღეს] LT[-ზე]',
	        nextDay : '[ხვალ] LT[-ზე]',
	        lastDay : '[გუშინ] LT[-ზე]',
	        nextWeek : '[შემდეგ] dddd LT[-ზე]',
	        lastWeek : '[წინა] dddd LT-ზე',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : function (s) {
	            return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
	                s.replace(/ი$/, 'ში') :
	                s + 'ში';
	        },
	        past : function (s) {
	            if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
	                return s.replace(/(ი|ე)$/, 'ის წინ');
	            }
	            if ((/წელი/).test(s)) {
	                return s.replace(/წელი$/, 'წლის წინ');
	            }
	        },
	        s : 'რამდენიმე წამი',
	        m : 'წუთი',
	        mm : '%d წუთი',
	        h : 'საათი',
	        hh : '%d საათი',
	        d : 'დღე',
	        dd : '%d დღე',
	        M : 'თვე',
	        MM : '%d თვე',
	        y : 'წელი',
	        yy : '%d წელი'
	    },
	    ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,
	    ordinal : function (number) {
	        if (number === 0) {
	            return number;
	        }
	        if (number === 1) {
	            return number + '-ლი';
	        }
	        if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) {
	            return 'მე-' + number;
	        }
	        return number + '-ე';
	    },
	    week : {
	        dow : 1,
	        doy : 7
	    }
	});
	
	return ka;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ka.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/kk.js **/
jupyter.define('moment@2.17.1/locale/kk.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Kazakh [kk]
	//! authors : Nurlan Rakhimzhanov : https://github.com/nurlan
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var suffixes = {
	    0: '-ші',
	    1: '-ші',
	    2: '-ші',
	    3: '-ші',
	    4: '-ші',
	    5: '-ші',
	    6: '-шы',
	    7: '-ші',
	    8: '-ші',
	    9: '-шы',
	    10: '-шы',
	    20: '-шы',
	    30: '-шы',
	    40: '-шы',
	    50: '-ші',
	    60: '-шы',
	    70: '-ші',
	    80: '-ші',
	    90: '-шы',
	    100: '-ші'
	};
	
	var kk = moment.defineLocale('kk', {
	    months : 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split('_'),
	    monthsShort : 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'),
	    weekdays : 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split('_'),
	    weekdaysShort : 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'),
	    weekdaysMin : 'жк_дй_сй_ср_бй_жм_сн'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[Бүгін сағат] LT',
	        nextDay : '[Ертең сағат] LT',
	        nextWeek : 'dddd [сағат] LT',
	        lastDay : '[Кеше сағат] LT',
	        lastWeek : '[Өткен аптаның] dddd [сағат] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s ішінде',
	        past : '%s бұрын',
	        s : 'бірнеше секунд',
	        m : 'бір минут',
	        mm : '%d минут',
	        h : 'бір сағат',
	        hh : '%d сағат',
	        d : 'бір күн',
	        dd : '%d күн',
	        M : 'бір ай',
	        MM : '%d ай',
	        y : 'бір жыл',
	        yy : '%d жыл'
	    },
	    ordinalParse: /\d{1,2}-(ші|шы)/,
	    ordinal : function (number) {
	        var a = number % 10,
	            b = number >= 100 ? 100 : null;
	        return number + (suffixes[number] || suffixes[a] || suffixes[b]);
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return kk;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/kk.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/km.js **/
jupyter.define('moment@2.17.1/locale/km.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Cambodian [km]
	//! author : Kruy Vanna : https://github.com/kruyvanna
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var km = moment.defineLocale('km', {
	    months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
	    monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
	    weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
	    weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
	    weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
	    longDateFormat: {
	        LT: 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L: 'DD/MM/YYYY',
	        LL: 'D MMMM YYYY',
	        LLL: 'D MMMM YYYY HH:mm',
	        LLLL: 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar: {
	        sameDay: '[ថ្ងៃនេះ ម៉ោង] LT',
	        nextDay: '[ស្អែក ម៉ោង] LT',
	        nextWeek: 'dddd [ម៉ោង] LT',
	        lastDay: '[ម្សិលមិញ ម៉ោង] LT',
	        lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
	        sameElse: 'L'
	    },
	    relativeTime: {
	        future: '%sទៀត',
	        past: '%sមុន',
	        s: 'ប៉ុន្មានវិនាទី',
	        m: 'មួយនាទី',
	        mm: '%d នាទី',
	        h: 'មួយម៉ោង',
	        hh: '%d ម៉ោង',
	        d: 'មួយថ្ងៃ',
	        dd: '%d ថ្ងៃ',
	        M: 'មួយខែ',
	        MM: '%d ខែ',
	        y: 'មួយឆ្នាំ',
	        yy: '%d ឆ្នាំ'
	    },
	    week: {
	        dow: 1, // Monday is the first day of the week.
	        doy: 4 // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return km;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/km.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ko.js **/
jupyter.define('moment@2.17.1/locale/ko.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Korean [ko]
	//! author : Kyungwook, Park : https://github.com/kyungw00k
	//! author : Jeeeyul Lee <jeeeyul@gmail.com>
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var ko = moment.defineLocale('ko', {
	    months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
	    monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
	    weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'),
	    weekdaysShort : '일_월_화_수_목_금_토'.split('_'),
	    weekdaysMin : '일_월_화_수_목_금_토'.split('_'),
	    longDateFormat : {
	        LT : 'A h시 m분',
	        LTS : 'A h시 m분 s초',
	        L : 'YYYY.MM.DD',
	        LL : 'YYYY년 MMMM D일',
	        LLL : 'YYYY년 MMMM D일 A h시 m분',
	        LLLL : 'YYYY년 MMMM D일 dddd A h시 m분'
	    },
	    calendar : {
	        sameDay : '오늘 LT',
	        nextDay : '내일 LT',
	        nextWeek : 'dddd LT',
	        lastDay : '어제 LT',
	        lastWeek : '지난주 dddd LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s 후',
	        past : '%s 전',
	        s : '몇 초',
	        ss : '%d초',
	        m : '일분',
	        mm : '%d분',
	        h : '한 시간',
	        hh : '%d시간',
	        d : '하루',
	        dd : '%d일',
	        M : '한 달',
	        MM : '%d달',
	        y : '일 년',
	        yy : '%d년'
	    },
	    ordinalParse : /\d{1,2}일/,
	    ordinal : '%d일',
	    meridiemParse : /오전|오후/,
	    isPM : function (token) {
	        return token === '오후';
	    },
	    meridiem : function (hour, minute, isUpper) {
	        return hour < 12 ? '오전' : '오후';
	    }
	});
	
	return ko;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ko.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ky.js **/
jupyter.define('moment@2.17.1/locale/ky.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Kyrgyz [ky]
	//! author : Chyngyz Arystan uulu : https://github.com/chyngyz
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	
	var suffixes = {
	    0: '-чү',
	    1: '-чи',
	    2: '-чи',
	    3: '-чү',
	    4: '-чү',
	    5: '-чи',
	    6: '-чы',
	    7: '-чи',
	    8: '-чи',
	    9: '-чу',
	    10: '-чу',
	    20: '-чы',
	    30: '-чу',
	    40: '-чы',
	    50: '-чү',
	    60: '-чы',
	    70: '-чи',
	    80: '-чи',
	    90: '-чу',
	    100: '-чү'
	};
	
	var ky = moment.defineLocale('ky', {
	    months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
	    monthsShort : 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
	    weekdays : 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split('_'),
	    weekdaysShort : 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'),
	    weekdaysMin : 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[Бүгүн саат] LT',
	        nextDay : '[Эртең саат] LT',
	        nextWeek : 'dddd [саат] LT',
	        lastDay : '[Кече саат] LT',
	        lastWeek : '[Өткен аптанын] dddd [күнү] [саат] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s ичинде',
	        past : '%s мурун',
	        s : 'бирнече секунд',
	        m : 'бир мүнөт',
	        mm : '%d мүнөт',
	        h : 'бир саат',
	        hh : '%d саат',
	        d : 'бир күн',
	        dd : '%d күн',
	        M : 'бир ай',
	        MM : '%d ай',
	        y : 'бир жыл',
	        yy : '%d жыл'
	    },
	    ordinalParse: /\d{1,2}-(чи|чы|чү|чу)/,
	    ordinal : function (number) {
	        var a = number % 10,
	            b = number >= 100 ? 100 : null;
	        return number + (suffixes[number] || suffixes[a] || suffixes[b]);
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return ky;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ky.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/lb.js **/
jupyter.define('moment@2.17.1/locale/lb.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Luxembourgish [lb]
	//! author : mweimerskirch : https://github.com/mweimerskirch
	//! author : David Raison : https://github.com/kwisatz
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function processRelativeTime(number, withoutSuffix, key, isFuture) {
	    var format = {
	        'm': ['eng Minutt', 'enger Minutt'],
	        'h': ['eng Stonn', 'enger Stonn'],
	        'd': ['een Dag', 'engem Dag'],
	        'M': ['ee Mount', 'engem Mount'],
	        'y': ['ee Joer', 'engem Joer']
	    };
	    return withoutSuffix ? format[key][0] : format[key][1];
	}
	function processFutureTime(string) {
	    var number = string.substr(0, string.indexOf(' '));
	    if (eifelerRegelAppliesToNumber(number)) {
	        return 'a ' + string;
	    }
	    return 'an ' + string;
	}
	function processPastTime(string) {
	    var number = string.substr(0, string.indexOf(' '));
	    if (eifelerRegelAppliesToNumber(number)) {
	        return 'viru ' + string;
	    }
	    return 'virun ' + string;
	}
	/**
	 * Returns true if the word before the given number loses the '-n' ending.
	 * e.g. 'an 10 Deeg' but 'a 5 Deeg'
	 *
	 * @param number {integer}
	 * @returns {boolean}
	 */
	function eifelerRegelAppliesToNumber(number) {
	    number = parseInt(number, 10);
	    if (isNaN(number)) {
	        return false;
	    }
	    if (number < 0) {
	        // Negative Number --> always true
	        return true;
	    } else if (number < 10) {
	        // Only 1 digit
	        if (4 <= number && number <= 7) {
	            return true;
	        }
	        return false;
	    } else if (number < 100) {
	        // 2 digits
	        var lastDigit = number % 10, firstDigit = number / 10;
	        if (lastDigit === 0) {
	            return eifelerRegelAppliesToNumber(firstDigit);
	        }
	        return eifelerRegelAppliesToNumber(lastDigit);
	    } else if (number < 10000) {
	        // 3 or 4 digits --> recursively check first digit
	        while (number >= 10) {
	            number = number / 10;
	        }
	        return eifelerRegelAppliesToNumber(number);
	    } else {
	        // Anything larger than 4 digits: recursively check first n-3 digits
	        number = number / 1000;
	        return eifelerRegelAppliesToNumber(number);
	    }
	}
	
	var lb = moment.defineLocale('lb', {
	    months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
	    monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
	    monthsParseExact : true,
	    weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'),
	    weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'),
	    weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat: {
	        LT: 'H:mm [Auer]',
	        LTS: 'H:mm:ss [Auer]',
	        L: 'DD.MM.YYYY',
	        LL: 'D. MMMM YYYY',
	        LLL: 'D. MMMM YYYY H:mm [Auer]',
	        LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]'
	    },
	    calendar: {
	        sameDay: '[Haut um] LT',
	        sameElse: 'L',
	        nextDay: '[Muer um] LT',
	        nextWeek: 'dddd [um] LT',
	        lastDay: '[Gëschter um] LT',
	        lastWeek: function () {
	            // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
	            switch (this.day()) {
	                case 2:
	                case 4:
	                    return '[Leschten] dddd [um] LT';
	                default:
	                    return '[Leschte] dddd [um] LT';
	            }
	        }
	    },
	    relativeTime : {
	        future : processFutureTime,
	        past : processPastTime,
	        s : 'e puer Sekonnen',
	        m : processRelativeTime,
	        mm : '%d Minutten',
	        h : processRelativeTime,
	        hh : '%d Stonnen',
	        d : processRelativeTime,
	        dd : '%d Deeg',
	        M : processRelativeTime,
	        MM : '%d Méint',
	        y : processRelativeTime,
	        yy : '%d Joer'
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal: '%d.',
	    week: {
	        dow: 1, // Monday is the first day of the week.
	        doy: 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return lb;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/lb.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/lo.js **/
jupyter.define('moment@2.17.1/locale/lo.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Lao [lo]
	//! author : Ryan Hart : https://github.com/ryanhart2
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var lo = moment.defineLocale('lo', {
	    months : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
	    monthsShort : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
	    weekdays : 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
	    weekdaysShort : 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
	    weekdaysMin : 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'ວັນdddd D MMMM YYYY HH:mm'
	    },
	    meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/,
	    isPM: function (input) {
	        return input === 'ຕອນແລງ';
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 12) {
	            return 'ຕອນເຊົ້າ';
	        } else {
	            return 'ຕອນແລງ';
	        }
	    },
	    calendar : {
	        sameDay : '[ມື້ນີ້ເວລາ] LT',
	        nextDay : '[ມື້ອື່ນເວລາ] LT',
	        nextWeek : '[ວັນ]dddd[ໜ້າເວລາ] LT',
	        lastDay : '[ມື້ວານນີ້ເວລາ] LT',
	        lastWeek : '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'ອີກ %s',
	        past : '%sຜ່ານມາ',
	        s : 'ບໍ່ເທົ່າໃດວິນາທີ',
	        m : '1 ນາທີ',
	        mm : '%d ນາທີ',
	        h : '1 ຊົ່ວໂມງ',
	        hh : '%d ຊົ່ວໂມງ',
	        d : '1 ມື້',
	        dd : '%d ມື້',
	        M : '1 ເດືອນ',
	        MM : '%d ເດືອນ',
	        y : '1 ປີ',
	        yy : '%d ປີ'
	    },
	    ordinalParse: /(ທີ່)\d{1,2}/,
	    ordinal : function (number) {
	        return 'ທີ່' + number;
	    }
	});
	
	return lo;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/lo.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/lt.js **/
jupyter.define('moment@2.17.1/locale/lt.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Lithuanian [lt]
	//! author : Mindaugas Mozūras : https://github.com/mmozuras
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var units = {
	    'm' : 'minutė_minutės_minutę',
	    'mm': 'minutės_minučių_minutes',
	    'h' : 'valanda_valandos_valandą',
	    'hh': 'valandos_valandų_valandas',
	    'd' : 'diena_dienos_dieną',
	    'dd': 'dienos_dienų_dienas',
	    'M' : 'mėnuo_mėnesio_mėnesį',
	    'MM': 'mėnesiai_mėnesių_mėnesius',
	    'y' : 'metai_metų_metus',
	    'yy': 'metai_metų_metus'
	};
	function translateSeconds(number, withoutSuffix, key, isFuture) {
	    if (withoutSuffix) {
	        return 'kelios sekundės';
	    } else {
	        return isFuture ? 'kelių sekundžių' : 'kelias sekundes';
	    }
	}
	function translateSingular(number, withoutSuffix, key, isFuture) {
	    return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]);
	}
	function special(number) {
	    return number % 10 === 0 || (number > 10 && number < 20);
	}
	function forms(key) {
	    return units[key].split('_');
	}
	function translate(number, withoutSuffix, key, isFuture) {
	    var result = number + ' ';
	    if (number === 1) {
	        return result + translateSingular(number, withoutSuffix, key[0], isFuture);
	    } else if (withoutSuffix) {
	        return result + (special(number) ? forms(key)[1] : forms(key)[0]);
	    } else {
	        if (isFuture) {
	            return result + forms(key)[1];
	        } else {
	            return result + (special(number) ? forms(key)[1] : forms(key)[2]);
	        }
	    }
	}
	var lt = moment.defineLocale('lt', {
	    months : {
	        format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'),
	        standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split('_'),
	        isFormat: /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?/
	    },
	    monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'),
	    weekdays : {
	        format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split('_'),
	        standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'),
	        isFormat: /dddd HH:mm/
	    },
	    weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'),
	    weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'YYYY-MM-DD',
	        LL : 'YYYY [m.] MMMM D [d.]',
	        LLL : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
	        LLLL : 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]',
	        l : 'YYYY-MM-DD',
	        ll : 'YYYY [m.] MMMM D [d.]',
	        lll : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
	        llll : 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]'
	    },
	    calendar : {
	        sameDay : '[Šiandien] LT',
	        nextDay : '[Rytoj] LT',
	        nextWeek : 'dddd LT',
	        lastDay : '[Vakar] LT',
	        lastWeek : '[Praėjusį] dddd LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'po %s',
	        past : 'prieš %s',
	        s : translateSeconds,
	        m : translateSingular,
	        mm : translate,
	        h : translateSingular,
	        hh : translate,
	        d : translateSingular,
	        dd : translate,
	        M : translateSingular,
	        MM : translate,
	        y : translateSingular,
	        yy : translate
	    },
	    ordinalParse: /\d{1,2}-oji/,
	    ordinal : function (number) {
	        return number + '-oji';
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return lt;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/lt.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/lv.js **/
jupyter.define('moment@2.17.1/locale/lv.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Latvian [lv]
	//! author : Kristaps Karlsons : https://github.com/skakri
	//! author : Jānis Elmeris : https://github.com/JanisE
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var units = {
	    'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
	    'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
	    'h': 'stundas_stundām_stunda_stundas'.split('_'),
	    'hh': 'stundas_stundām_stunda_stundas'.split('_'),
	    'd': 'dienas_dienām_diena_dienas'.split('_'),
	    'dd': 'dienas_dienām_diena_dienas'.split('_'),
	    'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
	    'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
	    'y': 'gada_gadiem_gads_gadi'.split('_'),
	    'yy': 'gada_gadiem_gads_gadi'.split('_')
	};
	/**
	 * @param withoutSuffix boolean true = a length of time; false = before/after a period of time.
	 */
	function format(forms, number, withoutSuffix) {
	    if (withoutSuffix) {
	        // E.g. "21 minūte", "3 minūtes".
	        return number % 10 === 1 && number % 100 !== 11 ? forms[2] : forms[3];
	    } else {
	        // E.g. "21 minūtes" as in "pēc 21 minūtes".
	        // E.g. "3 minūtēm" as in "pēc 3 minūtēm".
	        return number % 10 === 1 && number % 100 !== 11 ? forms[0] : forms[1];
	    }
	}
	function relativeTimeWithPlural(number, withoutSuffix, key) {
	    return number + ' ' + format(units[key], number, withoutSuffix);
	}
	function relativeTimeWithSingular(number, withoutSuffix, key) {
	    return format(units[key], number, withoutSuffix);
	}
	function relativeSeconds(number, withoutSuffix) {
	    return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm';
	}
	
	var lv = moment.defineLocale('lv', {
	    months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'),
	    monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'),
	    weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'),
	    weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'),
	    weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY.',
	        LL : 'YYYY. [gada] D. MMMM',
	        LLL : 'YYYY. [gada] D. MMMM, HH:mm',
	        LLLL : 'YYYY. [gada] D. MMMM, dddd, HH:mm'
	    },
	    calendar : {
	        sameDay : '[Šodien pulksten] LT',
	        nextDay : '[Rīt pulksten] LT',
	        nextWeek : 'dddd [pulksten] LT',
	        lastDay : '[Vakar pulksten] LT',
	        lastWeek : '[Pagājušā] dddd [pulksten] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'pēc %s',
	        past : 'pirms %s',
	        s : relativeSeconds,
	        m : relativeTimeWithSingular,
	        mm : relativeTimeWithPlural,
	        h : relativeTimeWithSingular,
	        hh : relativeTimeWithPlural,
	        d : relativeTimeWithSingular,
	        dd : relativeTimeWithPlural,
	        M : relativeTimeWithSingular,
	        MM : relativeTimeWithPlural,
	        y : relativeTimeWithSingular,
	        yy : relativeTimeWithPlural
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return lv;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/lv.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/me.js **/
jupyter.define('moment@2.17.1/locale/me.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Montenegrin [me]
	//! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var translator = {
	    words: { //Different grammatical cases
	        m: ['jedan minut', 'jednog minuta'],
	        mm: ['minut', 'minuta', 'minuta'],
	        h: ['jedan sat', 'jednog sata'],
	        hh: ['sat', 'sata', 'sati'],
	        dd: ['dan', 'dana', 'dana'],
	        MM: ['mjesec', 'mjeseca', 'mjeseci'],
	        yy: ['godina', 'godine', 'godina']
	    },
	    correctGrammaticalCase: function (number, wordKey) {
	        return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
	    },
	    translate: function (number, withoutSuffix, key) {
	        var wordKey = translator.words[key];
	        if (key.length === 1) {
	            return withoutSuffix ? wordKey[0] : wordKey[1];
	        } else {
	            return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
	        }
	    }
	};
	
	var me = moment.defineLocale('me', {
	    months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'),
	    monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'),
	    monthsParseExact : true,
	    weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
	    weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
	    weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat: {
	        LT: 'H:mm',
	        LTS : 'H:mm:ss',
	        L: 'DD.MM.YYYY',
	        LL: 'D. MMMM YYYY',
	        LLL: 'D. MMMM YYYY H:mm',
	        LLLL: 'dddd, D. MMMM YYYY H:mm'
	    },
	    calendar: {
	        sameDay: '[danas u] LT',
	        nextDay: '[sjutra u] LT',
	
	        nextWeek: function () {
	            switch (this.day()) {
	                case 0:
	                    return '[u] [nedjelju] [u] LT';
	                case 3:
	                    return '[u] [srijedu] [u] LT';
	                case 6:
	                    return '[u] [subotu] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[u] dddd [u] LT';
	            }
	        },
	        lastDay  : '[juče u] LT',
	        lastWeek : function () {
	            var lastWeekDays = [
	                '[prošle] [nedjelje] [u] LT',
	                '[prošlog] [ponedjeljka] [u] LT',
	                '[prošlog] [utorka] [u] LT',
	                '[prošle] [srijede] [u] LT',
	                '[prošlog] [četvrtka] [u] LT',
	                '[prošlog] [petka] [u] LT',
	                '[prošle] [subote] [u] LT'
	            ];
	            return lastWeekDays[this.day()];
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'za %s',
	        past   : 'prije %s',
	        s      : 'nekoliko sekundi',
	        m      : translator.translate,
	        mm     : translator.translate,
	        h      : translator.translate,
	        hh     : translator.translate,
	        d      : 'dan',
	        dd     : translator.translate,
	        M      : 'mjesec',
	        MM     : translator.translate,
	        y      : 'godinu',
	        yy     : translator.translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return me;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/me.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/mi.js **/
jupyter.define('moment@2.17.1/locale/mi.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Maori [mi]
	//! author : John Corrigan <robbiecloset@gmail.com> : https://github.com/johnideal
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var mi = moment.defineLocale('mi', {
	    months: 'Kohi-tāte_Hui-tanguru_Poutū-te-rangi_Paenga-whāwhā_Haratua_Pipiri_Hōngoingoi_Here-turi-kōkā_Mahuru_Whiringa-ā-nuku_Whiringa-ā-rangi_Hakihea'.split('_'),
	    monthsShort: 'Kohi_Hui_Pou_Pae_Hara_Pipi_Hōngoi_Here_Mahu_Whi-nu_Whi-ra_Haki'.split('_'),
	    monthsRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
	    monthsStrictRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
	    monthsShortRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
	    monthsShortStrictRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,2}/i,
	    weekdays: 'Rātapu_Mane_Tūrei_Wenerei_Tāite_Paraire_Hātarei'.split('_'),
	    weekdaysShort: 'Ta_Ma_Tū_We_Tāi_Pa_Hā'.split('_'),
	    weekdaysMin: 'Ta_Ma_Tū_We_Tāi_Pa_Hā'.split('_'),
	    longDateFormat: {
	        LT: 'HH:mm',
	        LTS: 'HH:mm:ss',
	        L: 'DD/MM/YYYY',
	        LL: 'D MMMM YYYY',
	        LLL: 'D MMMM YYYY [i] HH:mm',
	        LLLL: 'dddd, D MMMM YYYY [i] HH:mm'
	    },
	    calendar: {
	        sameDay: '[i teie mahana, i] LT',
	        nextDay: '[apopo i] LT',
	        nextWeek: 'dddd [i] LT',
	        lastDay: '[inanahi i] LT',
	        lastWeek: 'dddd [whakamutunga i] LT',
	        sameElse: 'L'
	    },
	    relativeTime: {
	        future: 'i roto i %s',
	        past: '%s i mua',
	        s: 'te hēkona ruarua',
	        m: 'he meneti',
	        mm: '%d meneti',
	        h: 'te haora',
	        hh: '%d haora',
	        d: 'he ra',
	        dd: '%d ra',
	        M: 'he marama',
	        MM: '%d marama',
	        y: 'he tau',
	        yy: '%d tau'
	    },
	    ordinalParse: /\d{1,2}º/,
	    ordinal: '%dº',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return mi;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/mi.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/mk.js **/
jupyter.define('moment@2.17.1/locale/mk.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Macedonian [mk]
	//! author : Borislav Mickov : https://github.com/B0k0
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var mk = moment.defineLocale('mk', {
	    months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'),
	    monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'),
	    weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'),
	    weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'),
	    weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'),
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'D.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY H:mm',
	        LLLL : 'dddd, D MMMM YYYY H:mm'
	    },
	    calendar : {
	        sameDay : '[Денес во] LT',
	        nextDay : '[Утре во] LT',
	        nextWeek : '[Во] dddd [во] LT',
	        lastDay : '[Вчера во] LT',
	        lastWeek : function () {
	            switch (this.day()) {
	                case 0:
	                case 3:
	                case 6:
	                    return '[Изминатата] dddd [во] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[Изминатиот] dddd [во] LT';
	            }
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'после %s',
	        past : 'пред %s',
	        s : 'неколку секунди',
	        m : 'минута',
	        mm : '%d минути',
	        h : 'час',
	        hh : '%d часа',
	        d : 'ден',
	        dd : '%d дена',
	        M : 'месец',
	        MM : '%d месеци',
	        y : 'година',
	        yy : '%d години'
	    },
	    ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
	    ordinal : function (number) {
	        var lastDigit = number % 10,
	            last2Digits = number % 100;
	        if (number === 0) {
	            return number + '-ев';
	        } else if (last2Digits === 0) {
	            return number + '-ен';
	        } else if (last2Digits > 10 && last2Digits < 20) {
	            return number + '-ти';
	        } else if (lastDigit === 1) {
	            return number + '-ви';
	        } else if (lastDigit === 2) {
	            return number + '-ри';
	        } else if (lastDigit === 7 || lastDigit === 8) {
	            return number + '-ми';
	        } else {
	            return number + '-ти';
	        }
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return mk;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/mk.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ml.js **/
jupyter.define('moment@2.17.1/locale/ml.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Malayalam [ml]
	//! author : Floyd Pink : https://github.com/floydpink
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var ml = moment.defineLocale('ml', {
	    months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'),
	    monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'),
	    weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'),
	    weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'),
	    longDateFormat : {
	        LT : 'A h:mm -നു',
	        LTS : 'A h:mm:ss -നു',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY, A h:mm -നു',
	        LLLL : 'dddd, D MMMM YYYY, A h:mm -നു'
	    },
	    calendar : {
	        sameDay : '[ഇന്ന്] LT',
	        nextDay : '[നാളെ] LT',
	        nextWeek : 'dddd, LT',
	        lastDay : '[ഇന്നലെ] LT',
	        lastWeek : '[കഴിഞ്ഞ] dddd, LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s കഴിഞ്ഞ്',
	        past : '%s മുൻപ്',
	        s : 'അൽപ നിമിഷങ്ങൾ',
	        m : 'ഒരു മിനിറ്റ്',
	        mm : '%d മിനിറ്റ്',
	        h : 'ഒരു മണിക്കൂർ',
	        hh : '%d മണിക്കൂർ',
	        d : 'ഒരു ദിവസം',
	        dd : '%d ദിവസം',
	        M : 'ഒരു മാസം',
	        MM : '%d മാസം',
	        y : 'ഒരു വർഷം',
	        yy : '%d വർഷം'
	    },
	    meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if ((meridiem === 'രാത്രി' && hour >= 4) ||
	                meridiem === 'ഉച്ച കഴിഞ്ഞ്' ||
	                meridiem === 'വൈകുന്നേരം') {
	            return hour + 12;
	        } else {
	            return hour;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'രാത്രി';
	        } else if (hour < 12) {
	            return 'രാവിലെ';
	        } else if (hour < 17) {
	            return 'ഉച്ച കഴിഞ്ഞ്';
	        } else if (hour < 20) {
	            return 'വൈകുന്നേരം';
	        } else {
	            return 'രാത്രി';
	        }
	    }
	});
	
	return ml;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ml.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/mr.js **/
jupyter.define('moment@2.17.1/locale/mr.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Marathi [mr]
	//! author : Harshad Kale : https://github.com/kalehv
	//! author : Vivek Athalye : https://github.com/vnathalye
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '१',
	    '2': '२',
	    '3': '३',
	    '4': '४',
	    '5': '५',
	    '6': '६',
	    '7': '७',
	    '8': '८',
	    '9': '९',
	    '0': '०'
	};
	var numberMap = {
	    '१': '1',
	    '२': '2',
	    '३': '3',
	    '४': '4',
	    '५': '5',
	    '६': '6',
	    '७': '7',
	    '८': '8',
	    '९': '9',
	    '०': '0'
	};
	
	function relativeTimeMr(number, withoutSuffix, string, isFuture)
	{
	    var output = '';
	    if (withoutSuffix) {
	        switch (string) {
	            case 's': output = 'काही सेकंद'; break;
	            case 'm': output = 'एक मिनिट'; break;
	            case 'mm': output = '%d मिनिटे'; break;
	            case 'h': output = 'एक तास'; break;
	            case 'hh': output = '%d तास'; break;
	            case 'd': output = 'एक दिवस'; break;
	            case 'dd': output = '%d दिवस'; break;
	            case 'M': output = 'एक महिना'; break;
	            case 'MM': output = '%d महिने'; break;
	            case 'y': output = 'एक वर्ष'; break;
	            case 'yy': output = '%d वर्षे'; break;
	        }
	    }
	    else {
	        switch (string) {
	            case 's': output = 'काही सेकंदां'; break;
	            case 'm': output = 'एका मिनिटा'; break;
	            case 'mm': output = '%d मिनिटां'; break;
	            case 'h': output = 'एका तासा'; break;
	            case 'hh': output = '%d तासां'; break;
	            case 'd': output = 'एका दिवसा'; break;
	            case 'dd': output = '%d दिवसां'; break;
	            case 'M': output = 'एका महिन्या'; break;
	            case 'MM': output = '%d महिन्यां'; break;
	            case 'y': output = 'एका वर्षा'; break;
	            case 'yy': output = '%d वर्षां'; break;
	        }
	    }
	    return output.replace(/%d/i, number);
	}
	
	var mr = moment.defineLocale('mr', {
	    months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'),
	    monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
	    weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'),
	    weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
	    longDateFormat : {
	        LT : 'A h:mm वाजता',
	        LTS : 'A h:mm:ss वाजता',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY, A h:mm वाजता',
	        LLLL : 'dddd, D MMMM YYYY, A h:mm वाजता'
	    },
	    calendar : {
	        sameDay : '[आज] LT',
	        nextDay : '[उद्या] LT',
	        nextWeek : 'dddd, LT',
	        lastDay : '[काल] LT',
	        lastWeek: '[मागील] dddd, LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future: '%sमध्ये',
	        past: '%sपूर्वी',
	        s: relativeTimeMr,
	        m: relativeTimeMr,
	        mm: relativeTimeMr,
	        h: relativeTimeMr,
	        hh: relativeTimeMr,
	        d: relativeTimeMr,
	        dd: relativeTimeMr,
	        M: relativeTimeMr,
	        MM: relativeTimeMr,
	        y: relativeTimeMr,
	        yy: relativeTimeMr
	    },
	    preparse: function (string) {
	        return string.replace(/[१२३४५६७८९०]/g, function (match) {
	            return numberMap[match];
	        });
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        });
	    },
	    meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'रात्री') {
	            return hour < 4 ? hour : hour + 12;
	        } else if (meridiem === 'सकाळी') {
	            return hour;
	        } else if (meridiem === 'दुपारी') {
	            return hour >= 10 ? hour : hour + 12;
	        } else if (meridiem === 'सायंकाळी') {
	            return hour + 12;
	        }
	    },
	    meridiem: function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'रात्री';
	        } else if (hour < 10) {
	            return 'सकाळी';
	        } else if (hour < 17) {
	            return 'दुपारी';
	        } else if (hour < 20) {
	            return 'सायंकाळी';
	        } else {
	            return 'रात्री';
	        }
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return mr;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/mr.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ms.js **/
jupyter.define('moment@2.17.1/locale/ms.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Malay [ms]
	//! author : Weldan Jamili : https://github.com/weldan
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var ms = moment.defineLocale('ms', {
	    months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
	    monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
	    weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
	    weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
	    weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
	    longDateFormat : {
	        LT : 'HH.mm',
	        LTS : 'HH.mm.ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY [pukul] HH.mm',
	        LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
	    },
	    meridiemParse: /pagi|tengahari|petang|malam/,
	    meridiemHour: function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'pagi') {
	            return hour;
	        } else if (meridiem === 'tengahari') {
	            return hour >= 11 ? hour : hour + 12;
	        } else if (meridiem === 'petang' || meridiem === 'malam') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours < 11) {
	            return 'pagi';
	        } else if (hours < 15) {
	            return 'tengahari';
	        } else if (hours < 19) {
	            return 'petang';
	        } else {
	            return 'malam';
	        }
	    },
	    calendar : {
	        sameDay : '[Hari ini pukul] LT',
	        nextDay : '[Esok pukul] LT',
	        nextWeek : 'dddd [pukul] LT',
	        lastDay : '[Kelmarin pukul] LT',
	        lastWeek : 'dddd [lepas pukul] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'dalam %s',
	        past : '%s yang lepas',
	        s : 'beberapa saat',
	        m : 'seminit',
	        mm : '%d minit',
	        h : 'sejam',
	        hh : '%d jam',
	        d : 'sehari',
	        dd : '%d hari',
	        M : 'sebulan',
	        MM : '%d bulan',
	        y : 'setahun',
	        yy : '%d tahun'
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return ms;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ms.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ms-my.js **/
jupyter.define('moment@2.17.1/locale/ms-my.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Malay [ms-my]
	//! note : DEPRECATED, the correct one is [ms]
	//! author : Weldan Jamili : https://github.com/weldan
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var msMy = moment.defineLocale('ms-my', {
	    months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
	    monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
	    weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
	    weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
	    weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
	    longDateFormat : {
	        LT : 'HH.mm',
	        LTS : 'HH.mm.ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY [pukul] HH.mm',
	        LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
	    },
	    meridiemParse: /pagi|tengahari|petang|malam/,
	    meridiemHour: function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'pagi') {
	            return hour;
	        } else if (meridiem === 'tengahari') {
	            return hour >= 11 ? hour : hour + 12;
	        } else if (meridiem === 'petang' || meridiem === 'malam') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours < 11) {
	            return 'pagi';
	        } else if (hours < 15) {
	            return 'tengahari';
	        } else if (hours < 19) {
	            return 'petang';
	        } else {
	            return 'malam';
	        }
	    },
	    calendar : {
	        sameDay : '[Hari ini pukul] LT',
	        nextDay : '[Esok pukul] LT',
	        nextWeek : 'dddd [pukul] LT',
	        lastDay : '[Kelmarin pukul] LT',
	        lastWeek : 'dddd [lepas pukul] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'dalam %s',
	        past : '%s yang lepas',
	        s : 'beberapa saat',
	        m : 'seminit',
	        mm : '%d minit',
	        h : 'sejam',
	        hh : '%d jam',
	        d : 'sehari',
	        dd : '%d hari',
	        M : 'sebulan',
	        MM : '%d bulan',
	        y : 'setahun',
	        yy : '%d tahun'
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return msMy;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ms-my.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/my.js **/
jupyter.define('moment@2.17.1/locale/my.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Burmese [my]
	//! author : Squar team, mysquar.com
	//! author : David Rossellat : https://github.com/gholadr
	//! author : Tin Aung Lin : https://github.com/thanyawzinmin
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '၁',
	    '2': '၂',
	    '3': '၃',
	    '4': '၄',
	    '5': '၅',
	    '6': '၆',
	    '7': '၇',
	    '8': '၈',
	    '9': '၉',
	    '0': '၀'
	};
	var numberMap = {
	    '၁': '1',
	    '၂': '2',
	    '၃': '3',
	    '၄': '4',
	    '၅': '5',
	    '၆': '6',
	    '၇': '7',
	    '၈': '8',
	    '၉': '9',
	    '၀': '0'
	};
	
	var my = moment.defineLocale('my', {
	    months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'),
	    monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'),
	    weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'),
	    weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
	    weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
	
	    longDateFormat: {
	        LT: 'HH:mm',
	        LTS: 'HH:mm:ss',
	        L: 'DD/MM/YYYY',
	        LL: 'D MMMM YYYY',
	        LLL: 'D MMMM YYYY HH:mm',
	        LLLL: 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar: {
	        sameDay: '[ယနေ.] LT [မှာ]',
	        nextDay: '[မနက်ဖြန်] LT [မှာ]',
	        nextWeek: 'dddd LT [မှာ]',
	        lastDay: '[မနေ.က] LT [မှာ]',
	        lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]',
	        sameElse: 'L'
	    },
	    relativeTime: {
	        future: 'လာမည့် %s မှာ',
	        past: 'လွန်ခဲ့သော %s က',
	        s: 'စက္ကန်.အနည်းငယ်',
	        m: 'တစ်မိနစ်',
	        mm: '%d မိနစ်',
	        h: 'တစ်နာရီ',
	        hh: '%d နာရီ',
	        d: 'တစ်ရက်',
	        dd: '%d ရက်',
	        M: 'တစ်လ',
	        MM: '%d လ',
	        y: 'တစ်နှစ်',
	        yy: '%d နှစ်'
	    },
	    preparse: function (string) {
	        return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) {
	            return numberMap[match];
	        });
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        });
	    },
	    week: {
	        dow: 1, // Monday is the first day of the week.
	        doy: 4 // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return my;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/my.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/nb.js **/
jupyter.define('moment@2.17.1/locale/nb.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Norwegian Bokmål [nb]
	//! authors : Espen Hovlandsdal : https://github.com/rexxars
	//!           Sigurd Gartmann : https://github.com/sigurdga
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var nb = moment.defineLocale('nb', {
	    months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
	    monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
	    weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'),
	    weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY [kl.] HH:mm',
	        LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
	    },
	    calendar : {
	        sameDay: '[i dag kl.] LT',
	        nextDay: '[i morgen kl.] LT',
	        nextWeek: 'dddd [kl.] LT',
	        lastDay: '[i går kl.] LT',
	        lastWeek: '[forrige] dddd [kl.] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'om %s',
	        past : '%s siden',
	        s : 'noen sekunder',
	        m : 'ett minutt',
	        mm : '%d minutter',
	        h : 'en time',
	        hh : '%d timer',
	        d : 'en dag',
	        dd : '%d dager',
	        M : 'en måned',
	        MM : '%d måneder',
	        y : 'ett år',
	        yy : '%d år'
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return nb;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/nb.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ne.js **/
jupyter.define('moment@2.17.1/locale/ne.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Nepalese [ne]
	//! author : suvash : https://github.com/suvash
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '१',
	    '2': '२',
	    '3': '३',
	    '4': '४',
	    '5': '५',
	    '6': '६',
	    '7': '७',
	    '8': '८',
	    '9': '९',
	    '0': '०'
	};
	var numberMap = {
	    '१': '1',
	    '२': '2',
	    '३': '3',
	    '४': '4',
	    '५': '5',
	    '६': '6',
	    '७': '7',
	    '८': '8',
	    '९': '9',
	    '०': '0'
	};
	
	var ne = moment.defineLocale('ne', {
	    months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'),
	    monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'),
	    weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'),
	    weekdaysMin : 'आ._सो._मं._बु._बि._शु._श.'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'Aको h:mm बजे',
	        LTS : 'Aको h:mm:ss बजे',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY, Aको h:mm बजे',
	        LLLL : 'dddd, D MMMM YYYY, Aको h:mm बजे'
	    },
	    preparse: function (string) {
	        return string.replace(/[१२३४५६७८९०]/g, function (match) {
	            return numberMap[match];
	        });
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        });
	    },
	    meridiemParse: /राति|बिहान|दिउँसो|साँझ/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'राति') {
	            return hour < 4 ? hour : hour + 12;
	        } else if (meridiem === 'बिहान') {
	            return hour;
	        } else if (meridiem === 'दिउँसो') {
	            return hour >= 10 ? hour : hour + 12;
	        } else if (meridiem === 'साँझ') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 3) {
	            return 'राति';
	        } else if (hour < 12) {
	            return 'बिहान';
	        } else if (hour < 16) {
	            return 'दिउँसो';
	        } else if (hour < 20) {
	            return 'साँझ';
	        } else {
	            return 'राति';
	        }
	    },
	    calendar : {
	        sameDay : '[आज] LT',
	        nextDay : '[भोलि] LT',
	        nextWeek : '[आउँदो] dddd[,] LT',
	        lastDay : '[हिजो] LT',
	        lastWeek : '[गएको] dddd[,] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%sमा',
	        past : '%s अगाडि',
	        s : 'केही क्षण',
	        m : 'एक मिनेट',
	        mm : '%d मिनेट',
	        h : 'एक घण्टा',
	        hh : '%d घण्टा',
	        d : 'एक दिन',
	        dd : '%d दिन',
	        M : 'एक महिना',
	        MM : '%d महिना',
	        y : 'एक बर्ष',
	        yy : '%d बर्ष'
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return ne;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ne.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/nl.js **/
jupyter.define('moment@2.17.1/locale/nl.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Dutch [nl]
	//! author : Joris Röling : https://github.com/jorisroling
	//! author : Jacob Middag : https://github.com/middagj
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_');
	var monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
	
	var monthsParse = [/^jan/i, /^feb/i, /^maart|mrt.?$/i, /^apr/i, /^mei$/i, /^jun[i.]?$/i, /^jul[i.]?$/i, /^aug/i, /^sep/i, /^okt/i, /^nov/i, /^dec/i];
	var monthsRegex = /^(januari|februari|maart|april|mei|april|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;
	
	var nl = moment.defineLocale('nl', {
	    months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'),
	    monthsShort : function (m, format) {
	        if (/-MMM-/.test(format)) {
	            return monthsShortWithoutDots[m.month()];
	        } else {
	            return monthsShortWithDots[m.month()];
	        }
	    },
	
	    monthsRegex: monthsRegex,
	    monthsShortRegex: monthsRegex,
	    monthsStrictRegex: /^(januari|februari|maart|mei|ju[nl]i|april|augustus|september|oktober|november|december)/i,
	    monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
	
	    monthsParse : monthsParse,
	    longMonthsParse : monthsParse,
	    shortMonthsParse : monthsParse,
	
	    weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'),
	    weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'),
	    weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD-MM-YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[vandaag om] LT',
	        nextDay: '[morgen om] LT',
	        nextWeek: 'dddd [om] LT',
	        lastDay: '[gisteren om] LT',
	        lastWeek: '[afgelopen] dddd [om] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'over %s',
	        past : '%s geleden',
	        s : 'een paar seconden',
	        m : 'één minuut',
	        mm : '%d minuten',
	        h : 'één uur',
	        hh : '%d uur',
	        d : 'één dag',
	        dd : '%d dagen',
	        M : 'één maand',
	        MM : '%d maanden',
	        y : 'één jaar',
	        yy : '%d jaar'
	    },
	    ordinalParse: /\d{1,2}(ste|de)/,
	    ordinal : function (number) {
	        return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return nl;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/nl.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/nl-be.js **/
jupyter.define('moment@2.17.1/locale/nl-be.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Dutch (Belgium) [nl-be]
	//! author : Joris Röling : https://github.com/jorisroling
	//! author : Jacob Middag : https://github.com/middagj
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_');
	var monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
	
	var monthsParse = [/^jan/i, /^feb/i, /^maart|mrt.?$/i, /^apr/i, /^mei$/i, /^jun[i.]?$/i, /^jul[i.]?$/i, /^aug/i, /^sep/i, /^okt/i, /^nov/i, /^dec/i];
	var monthsRegex = /^(januari|februari|maart|april|mei|april|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;
	
	var nlBe = moment.defineLocale('nl-be', {
	    months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'),
	    monthsShort : function (m, format) {
	        if (/-MMM-/.test(format)) {
	            return monthsShortWithoutDots[m.month()];
	        } else {
	            return monthsShortWithDots[m.month()];
	        }
	    },
	
	    monthsRegex: monthsRegex,
	    monthsShortRegex: monthsRegex,
	    monthsStrictRegex: /^(januari|februari|maart|mei|ju[nl]i|april|augustus|september|oktober|november|december)/i,
	    monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
	
	    monthsParse : monthsParse,
	    longMonthsParse : monthsParse,
	    shortMonthsParse : monthsParse,
	
	    weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'),
	    weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'),
	    weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[vandaag om] LT',
	        nextDay: '[morgen om] LT',
	        nextWeek: 'dddd [om] LT',
	        lastDay: '[gisteren om] LT',
	        lastWeek: '[afgelopen] dddd [om] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'over %s',
	        past : '%s geleden',
	        s : 'een paar seconden',
	        m : 'één minuut',
	        mm : '%d minuten',
	        h : 'één uur',
	        hh : '%d uur',
	        d : 'één dag',
	        dd : '%d dagen',
	        M : 'één maand',
	        MM : '%d maanden',
	        y : 'één jaar',
	        yy : '%d jaar'
	    },
	    ordinalParse: /\d{1,2}(ste|de)/,
	    ordinal : function (number) {
	        return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return nlBe;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/nl-be.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/nn.js **/
jupyter.define('moment@2.17.1/locale/nn.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Nynorsk [nn]
	//! author : https://github.com/mechuwind
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var nn = moment.defineLocale('nn', {
	    months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
	    monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
	    weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'),
	    weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'),
	    weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY [kl.] H:mm',
	        LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
	    },
	    calendar : {
	        sameDay: '[I dag klokka] LT',
	        nextDay: '[I morgon klokka] LT',
	        nextWeek: 'dddd [klokka] LT',
	        lastDay: '[I går klokka] LT',
	        lastWeek: '[Føregåande] dddd [klokka] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'om %s',
	        past : '%s sidan',
	        s : 'nokre sekund',
	        m : 'eit minutt',
	        mm : '%d minutt',
	        h : 'ein time',
	        hh : '%d timar',
	        d : 'ein dag',
	        dd : '%d dagar',
	        M : 'ein månad',
	        MM : '%d månader',
	        y : 'eit år',
	        yy : '%d år'
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return nn;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/nn.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/pa-in.js **/
jupyter.define('moment@2.17.1/locale/pa-in.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Punjabi (India) [pa-in]
	//! author : Harpreet Singh : https://github.com/harpreetkhalsagtbit
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '੧',
	    '2': '੨',
	    '3': '੩',
	    '4': '੪',
	    '5': '੫',
	    '6': '੬',
	    '7': '੭',
	    '8': '੮',
	    '9': '੯',
	    '0': '੦'
	};
	var numberMap = {
	    '੧': '1',
	    '੨': '2',
	    '੩': '3',
	    '੪': '4',
	    '੫': '5',
	    '੬': '6',
	    '੭': '7',
	    '੮': '8',
	    '੯': '9',
	    '੦': '0'
	};
	
	var paIn = moment.defineLocale('pa-in', {
	    // There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi.
	    months : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
	    monthsShort : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
	    weekdays : 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split('_'),
	    weekdaysShort : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
	    weekdaysMin : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
	    longDateFormat : {
	        LT : 'A h:mm ਵਜੇ',
	        LTS : 'A h:mm:ss ਵਜੇ',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY, A h:mm ਵਜੇ',
	        LLLL : 'dddd, D MMMM YYYY, A h:mm ਵਜੇ'
	    },
	    calendar : {
	        sameDay : '[ਅਜ] LT',
	        nextDay : '[ਕਲ] LT',
	        nextWeek : 'dddd, LT',
	        lastDay : '[ਕਲ] LT',
	        lastWeek : '[ਪਿਛਲੇ] dddd, LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s ਵਿੱਚ',
	        past : '%s ਪਿਛਲੇ',
	        s : 'ਕੁਝ ਸਕਿੰਟ',
	        m : 'ਇਕ ਮਿੰਟ',
	        mm : '%d ਮਿੰਟ',
	        h : 'ਇੱਕ ਘੰਟਾ',
	        hh : '%d ਘੰਟੇ',
	        d : 'ਇੱਕ ਦਿਨ',
	        dd : '%d ਦਿਨ',
	        M : 'ਇੱਕ ਮਹੀਨਾ',
	        MM : '%d ਮਹੀਨੇ',
	        y : 'ਇੱਕ ਸਾਲ',
	        yy : '%d ਸਾਲ'
	    },
	    preparse: function (string) {
	        return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) {
	            return numberMap[match];
	        });
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        });
	    },
	    // Punjabi notation for meridiems are quite fuzzy in practice. While there exists
	    // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi.
	    meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'ਰਾਤ') {
	            return hour < 4 ? hour : hour + 12;
	        } else if (meridiem === 'ਸਵੇਰ') {
	            return hour;
	        } else if (meridiem === 'ਦੁਪਹਿਰ') {
	            return hour >= 10 ? hour : hour + 12;
	        } else if (meridiem === 'ਸ਼ਾਮ') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'ਰਾਤ';
	        } else if (hour < 10) {
	            return 'ਸਵੇਰ';
	        } else if (hour < 17) {
	            return 'ਦੁਪਹਿਰ';
	        } else if (hour < 20) {
	            return 'ਸ਼ਾਮ';
	        } else {
	            return 'ਰਾਤ';
	        }
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return paIn;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/pa-in.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/pl.js **/
jupyter.define('moment@2.17.1/locale/pl.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Polish [pl]
	//! author : Rafal Hirsz : https://github.com/evoL
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_');
	var monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_');
	function plural(n) {
	    return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
	}
	function translate(number, withoutSuffix, key) {
	    var result = number + ' ';
	    switch (key) {
	        case 'm':
	            return withoutSuffix ? 'minuta' : 'minutę';
	        case 'mm':
	            return result + (plural(number) ? 'minuty' : 'minut');
	        case 'h':
	            return withoutSuffix  ? 'godzina'  : 'godzinę';
	        case 'hh':
	            return result + (plural(number) ? 'godziny' : 'godzin');
	        case 'MM':
	            return result + (plural(number) ? 'miesiące' : 'miesięcy');
	        case 'yy':
	            return result + (plural(number) ? 'lata' : 'lat');
	    }
	}
	
	var pl = moment.defineLocale('pl', {
	    months : function (momentToFormat, format) {
	        if (format === '') {
	            // Hack: if format empty we know this is used to generate
	            // RegExp by moment. Give then back both valid forms of months
	            // in RegExp ready format.
	            return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')';
	        } else if (/D MMMM/.test(format)) {
	            return monthsSubjective[momentToFormat.month()];
	        } else {
	            return monthsNominative[momentToFormat.month()];
	        }
	    },
	    monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'),
	    weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'),
	    weekdaysShort : 'ndz_pon_wt_śr_czw_pt_sob'.split('_'),
	    weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[Dziś o] LT',
	        nextDay: '[Jutro o] LT',
	        nextWeek: '[W] dddd [o] LT',
	        lastDay: '[Wczoraj o] LT',
	        lastWeek: function () {
	            switch (this.day()) {
	                case 0:
	                    return '[W zeszłą niedzielę o] LT';
	                case 3:
	                    return '[W zeszłą środę o] LT';
	                case 6:
	                    return '[W zeszłą sobotę o] LT';
	                default:
	                    return '[W zeszły] dddd [o] LT';
	            }
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'za %s',
	        past : '%s temu',
	        s : 'kilka sekund',
	        m : translate,
	        mm : translate,
	        h : translate,
	        hh : translate,
	        d : '1 dzień',
	        dd : '%d dni',
	        M : 'miesiąc',
	        MM : translate,
	        y : 'rok',
	        yy : translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return pl;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/pl.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/pt.js **/
jupyter.define('moment@2.17.1/locale/pt.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Portuguese [pt]
	//! author : Jefferson : https://github.com/jalex79
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var pt = moment.defineLocale('pt', {
	    months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'),
	    monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'),
	    weekdays : 'Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado'.split('_'),
	    weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
	    weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D [de] MMMM [de] YYYY',
	        LLL : 'D [de] MMMM [de] YYYY HH:mm',
	        LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[Hoje às] LT',
	        nextDay: '[Amanhã às] LT',
	        nextWeek: 'dddd [às] LT',
	        lastDay: '[Ontem às] LT',
	        lastWeek: function () {
	            return (this.day() === 0 || this.day() === 6) ?
	                '[Último] dddd [às] LT' : // Saturday + Sunday
	                '[Última] dddd [às] LT'; // Monday - Friday
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'em %s',
	        past : 'há %s',
	        s : 'segundos',
	        m : 'um minuto',
	        mm : '%d minutos',
	        h : 'uma hora',
	        hh : '%d horas',
	        d : 'um dia',
	        dd : '%d dias',
	        M : 'um mês',
	        MM : '%d meses',
	        y : 'um ano',
	        yy : '%d anos'
	    },
	    ordinalParse: /\d{1,2}º/,
	    ordinal : '%dº',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return pt;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/pt.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/pt-br.js **/
jupyter.define('moment@2.17.1/locale/pt-br.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Portuguese (Brazil) [pt-br]
	//! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var ptBr = moment.defineLocale('pt-br', {
	    months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'),
	    monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'),
	    weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
	    weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
	    weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D [de] MMMM [de] YYYY',
	        LLL : 'D [de] MMMM [de] YYYY [às] HH:mm',
	        LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm'
	    },
	    calendar : {
	        sameDay: '[Hoje às] LT',
	        nextDay: '[Amanhã às] LT',
	        nextWeek: 'dddd [às] LT',
	        lastDay: '[Ontem às] LT',
	        lastWeek: function () {
	            return (this.day() === 0 || this.day() === 6) ?
	                '[Último] dddd [às] LT' : // Saturday + Sunday
	                '[Última] dddd [às] LT'; // Monday - Friday
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'em %s',
	        past : '%s atrás',
	        s : 'poucos segundos',
	        m : 'um minuto',
	        mm : '%d minutos',
	        h : 'uma hora',
	        hh : '%d horas',
	        d : 'um dia',
	        dd : '%d dias',
	        M : 'um mês',
	        MM : '%d meses',
	        y : 'um ano',
	        yy : '%d anos'
	    },
	    ordinalParse: /\d{1,2}º/,
	    ordinal : '%dº'
	});
	
	return ptBr;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/pt-br.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ro.js **/
jupyter.define('moment@2.17.1/locale/ro.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Romanian [ro]
	//! author : Vlad Gurdiga : https://github.com/gurdiga
	//! author : Valentin Agachi : https://github.com/avaly
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function relativeTimeWithPlural(number, withoutSuffix, key) {
	    var format = {
	            'mm': 'minute',
	            'hh': 'ore',
	            'dd': 'zile',
	            'MM': 'luni',
	            'yy': 'ani'
	        },
	        separator = ' ';
	    if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
	        separator = ' de ';
	    }
	    return number + separator + format[key];
	}
	
	var ro = moment.defineLocale('ro', {
	    months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'),
	    monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'),
	    monthsParseExact: true,
	    weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'),
	    weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'),
	    weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'),
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY H:mm',
	        LLLL : 'dddd, D MMMM YYYY H:mm'
	    },
	    calendar : {
	        sameDay: '[azi la] LT',
	        nextDay: '[mâine la] LT',
	        nextWeek: 'dddd [la] LT',
	        lastDay: '[ieri la] LT',
	        lastWeek: '[fosta] dddd [la] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'peste %s',
	        past : '%s în urmă',
	        s : 'câteva secunde',
	        m : 'un minut',
	        mm : relativeTimeWithPlural,
	        h : 'o oră',
	        hh : relativeTimeWithPlural,
	        d : 'o zi',
	        dd : relativeTimeWithPlural,
	        M : 'o lună',
	        MM : relativeTimeWithPlural,
	        y : 'un an',
	        yy : relativeTimeWithPlural
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return ro;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ro.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ru.js **/
jupyter.define('moment@2.17.1/locale/ru.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Russian [ru]
	//! author : Viktorminator : https://github.com/Viktorminator
	//! Author : Menelion Elensúle : https://github.com/Oire
	//! author : Коренберг Марк : https://github.com/socketpair
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function plural(word, num) {
	    var forms = word.split('_');
	    return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
	}
	function relativeTimeWithPlural(number, withoutSuffix, key) {
	    var format = {
	        'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
	        'hh': 'час_часа_часов',
	        'dd': 'день_дня_дней',
	        'MM': 'месяц_месяца_месяцев',
	        'yy': 'год_года_лет'
	    };
	    if (key === 'm') {
	        return withoutSuffix ? 'минута' : 'минуту';
	    }
	    else {
	        return number + ' ' + plural(format[key], +number);
	    }
	}
	var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i];
	
	// http://new.gramota.ru/spravka/rules/139-prop : § 103
	// Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637
	// CLDR data:          http://www.unicode.org/cldr/charts/28/summary/ru.html#1753
	var ru = moment.defineLocale('ru', {
	    months : {
	        format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'),
	        standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_')
	    },
	    monthsShort : {
	        // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ?
	        format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'),
	        standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_')
	    },
	    weekdays : {
	        standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
	        format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'),
	        isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/
	    },
	    weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
	    weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
	    monthsParse : monthsParse,
	    longMonthsParse : monthsParse,
	    shortMonthsParse : monthsParse,
	
	    // полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки
	    monthsRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
	
	    // копия предыдущего
	    monthsShortRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
	
	    // полные названия с падежами
	    monthsStrictRegex: /^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,
	
	    // Выражение, которое соотвествует только сокращённым формам
	    monthsShortStrictRegex: /^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY г.',
	        LLL : 'D MMMM YYYY г., HH:mm',
	        LLLL : 'dddd, D MMMM YYYY г., HH:mm'
	    },
	    calendar : {
	        sameDay: '[Сегодня в] LT',
	        nextDay: '[Завтра в] LT',
	        lastDay: '[Вчера в] LT',
	        nextWeek: function (now) {
	            if (now.week() !== this.week()) {
	                switch (this.day()) {
	                    case 0:
	                        return '[В следующее] dddd [в] LT';
	                    case 1:
	                    case 2:
	                    case 4:
	                        return '[В следующий] dddd [в] LT';
	                    case 3:
	                    case 5:
	                    case 6:
	                        return '[В следующую] dddd [в] LT';
	                }
	            } else {
	                if (this.day() === 2) {
	                    return '[Во] dddd [в] LT';
	                } else {
	                    return '[В] dddd [в] LT';
	                }
	            }
	        },
	        lastWeek: function (now) {
	            if (now.week() !== this.week()) {
	                switch (this.day()) {
	                    case 0:
	                        return '[В прошлое] dddd [в] LT';
	                    case 1:
	                    case 2:
	                    case 4:
	                        return '[В прошлый] dddd [в] LT';
	                    case 3:
	                    case 5:
	                    case 6:
	                        return '[В прошлую] dddd [в] LT';
	                }
	            } else {
	                if (this.day() === 2) {
	                    return '[Во] dddd [в] LT';
	                } else {
	                    return '[В] dddd [в] LT';
	                }
	            }
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'через %s',
	        past : '%s назад',
	        s : 'несколько секунд',
	        m : relativeTimeWithPlural,
	        mm : relativeTimeWithPlural,
	        h : 'час',
	        hh : relativeTimeWithPlural,
	        d : 'день',
	        dd : relativeTimeWithPlural,
	        M : 'месяц',
	        MM : relativeTimeWithPlural,
	        y : 'год',
	        yy : relativeTimeWithPlural
	    },
	    meridiemParse: /ночи|утра|дня|вечера/i,
	    isPM : function (input) {
	        return /^(дня|вечера)$/.test(input);
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'ночи';
	        } else if (hour < 12) {
	            return 'утра';
	        } else if (hour < 17) {
	            return 'дня';
	        } else {
	            return 'вечера';
	        }
	    },
	    ordinalParse: /\d{1,2}-(й|го|я)/,
	    ordinal: function (number, period) {
	        switch (period) {
	            case 'M':
	            case 'd':
	            case 'DDD':
	                return number + '-й';
	            case 'D':
	                return number + '-го';
	            case 'w':
	            case 'W':
	                return number + '-я';
	            default:
	                return number;
	        }
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return ru;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ru.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/se.js **/
jupyter.define('moment@2.17.1/locale/se.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Northern Sami [se]
	//! authors : Bård Rolstad Henriksen : https://github.com/karamell
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	
	var se = moment.defineLocale('se', {
	    months : 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split('_'),
	    monthsShort : 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split('_'),
	    weekdays : 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split('_'),
	    weekdaysShort : 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'),
	    weekdaysMin : 's_v_m_g_d_b_L'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'MMMM D. [b.] YYYY',
	        LLL : 'MMMM D. [b.] YYYY [ti.] HH:mm',
	        LLLL : 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm'
	    },
	    calendar : {
	        sameDay: '[otne ti] LT',
	        nextDay: '[ihttin ti] LT',
	        nextWeek: 'dddd [ti] LT',
	        lastDay: '[ikte ti] LT',
	        lastWeek: '[ovddit] dddd [ti] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : '%s geažes',
	        past : 'maŋit %s',
	        s : 'moadde sekunddat',
	        m : 'okta minuhta',
	        mm : '%d minuhtat',
	        h : 'okta diimmu',
	        hh : '%d diimmut',
	        d : 'okta beaivi',
	        dd : '%d beaivvit',
	        M : 'okta mánnu',
	        MM : '%d mánut',
	        y : 'okta jahki',
	        yy : '%d jagit'
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return se;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/se.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/si.js **/
jupyter.define('moment@2.17.1/locale/si.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Sinhalese [si]
	//! author : Sampath Sitinamaluwa : https://github.com/sampathsris
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	/*jshint -W100*/
	var si = moment.defineLocale('si', {
	    months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්‍රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'),
	    monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'),
	    weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්‍රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'),
	    weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්‍රහ_සිකු_සෙන'.split('_'),
	    weekdaysMin : 'ඉ_ස_අ_බ_බ්‍ර_සි_සෙ'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'a h:mm',
	        LTS : 'a h:mm:ss',
	        L : 'YYYY/MM/DD',
	        LL : 'YYYY MMMM D',
	        LLL : 'YYYY MMMM D, a h:mm',
	        LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss'
	    },
	    calendar : {
	        sameDay : '[අද] LT[ට]',
	        nextDay : '[හෙට] LT[ට]',
	        nextWeek : 'dddd LT[ට]',
	        lastDay : '[ඊයේ] LT[ට]',
	        lastWeek : '[පසුගිය] dddd LT[ට]',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%sකින්',
	        past : '%sකට පෙර',
	        s : 'තත්පර කිහිපය',
	        m : 'මිනිත්තුව',
	        mm : 'මිනිත්තු %d',
	        h : 'පැය',
	        hh : 'පැය %d',
	        d : 'දිනය',
	        dd : 'දින %d',
	        M : 'මාසය',
	        MM : 'මාස %d',
	        y : 'වසර',
	        yy : 'වසර %d'
	    },
	    ordinalParse: /\d{1,2} වැනි/,
	    ordinal : function (number) {
	        return number + ' වැනි';
	    },
	    meridiemParse : /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,
	    isPM : function (input) {
	        return input === 'ප.ව.' || input === 'පස් වරු';
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours > 11) {
	            return isLower ? 'ප.ව.' : 'පස් වරු';
	        } else {
	            return isLower ? 'පෙ.ව.' : 'පෙර වරු';
	        }
	    }
	});
	
	return si;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/si.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/sk.js **/
jupyter.define('moment@2.17.1/locale/sk.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Slovak [sk]
	//! author : Martin Minka : https://github.com/k2s
	//! based on work of petrbela : https://github.com/petrbela
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_');
	var monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_');
	function plural(n) {
	    return (n > 1) && (n < 5);
	}
	function translate(number, withoutSuffix, key, isFuture) {
	    var result = number + ' ';
	    switch (key) {
	        case 's':  // a few seconds / in a few seconds / a few seconds ago
	            return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami';
	        case 'm':  // a minute / in a minute / a minute ago
	            return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou');
	        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'minúty' : 'minút');
	            } else {
	                return result + 'minútami';
	            }
	            break;
	        case 'h':  // an hour / in an hour / an hour ago
	            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
	        case 'hh': // 9 hours / in 9 hours / 9 hours ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'hodiny' : 'hodín');
	            } else {
	                return result + 'hodinami';
	            }
	            break;
	        case 'd':  // a day / in a day / a day ago
	            return (withoutSuffix || isFuture) ? 'deň' : 'dňom';
	        case 'dd': // 9 days / in 9 days / 9 days ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'dni' : 'dní');
	            } else {
	                return result + 'dňami';
	            }
	            break;
	        case 'M':  // a month / in a month / a month ago
	            return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom';
	        case 'MM': // 9 months / in 9 months / 9 months ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'mesiace' : 'mesiacov');
	            } else {
	                return result + 'mesiacmi';
	            }
	            break;
	        case 'y':  // a year / in a year / a year ago
	            return (withoutSuffix || isFuture) ? 'rok' : 'rokom';
	        case 'yy': // 9 years / in 9 years / 9 years ago
	            if (withoutSuffix || isFuture) {
	                return result + (plural(number) ? 'roky' : 'rokov');
	            } else {
	                return result + 'rokmi';
	            }
	            break;
	    }
	}
	
	var sk = moment.defineLocale('sk', {
	    months : months,
	    monthsShort : monthsShort,
	    weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'),
	    weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'),
	    weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'),
	    longDateFormat : {
	        LT: 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY H:mm',
	        LLLL : 'dddd D. MMMM YYYY H:mm'
	    },
	    calendar : {
	        sameDay: '[dnes o] LT',
	        nextDay: '[zajtra o] LT',
	        nextWeek: function () {
	            switch (this.day()) {
	                case 0:
	                    return '[v nedeľu o] LT';
	                case 1:
	                case 2:
	                    return '[v] dddd [o] LT';
	                case 3:
	                    return '[v stredu o] LT';
	                case 4:
	                    return '[vo štvrtok o] LT';
	                case 5:
	                    return '[v piatok o] LT';
	                case 6:
	                    return '[v sobotu o] LT';
	            }
	        },
	        lastDay: '[včera o] LT',
	        lastWeek: function () {
	            switch (this.day()) {
	                case 0:
	                    return '[minulú nedeľu o] LT';
	                case 1:
	                case 2:
	                    return '[minulý] dddd [o] LT';
	                case 3:
	                    return '[minulú stredu o] LT';
	                case 4:
	                case 5:
	                    return '[minulý] dddd [o] LT';
	                case 6:
	                    return '[minulú sobotu o] LT';
	            }
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'za %s',
	        past : 'pred %s',
	        s : translate,
	        m : translate,
	        mm : translate,
	        h : translate,
	        hh : translate,
	        d : translate,
	        dd : translate,
	        M : translate,
	        MM : translate,
	        y : translate,
	        yy : translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return sk;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/sk.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/sl.js **/
jupyter.define('moment@2.17.1/locale/sl.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Slovenian [sl]
	//! author : Robert Sedovšek : https://github.com/sedovsek
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function processRelativeTime(number, withoutSuffix, key, isFuture) {
	    var result = number + ' ';
	    switch (key) {
	        case 's':
	            return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami';
	        case 'm':
	            return withoutSuffix ? 'ena minuta' : 'eno minuto';
	        case 'mm':
	            if (number === 1) {
	                result += withoutSuffix ? 'minuta' : 'minuto';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'minuti' : 'minutama';
	            } else if (number < 5) {
	                result += withoutSuffix || isFuture ? 'minute' : 'minutami';
	            } else {
	                result += withoutSuffix || isFuture ? 'minut' : 'minutami';
	            }
	            return result;
	        case 'h':
	            return withoutSuffix ? 'ena ura' : 'eno uro';
	        case 'hh':
	            if (number === 1) {
	                result += withoutSuffix ? 'ura' : 'uro';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'uri' : 'urama';
	            } else if (number < 5) {
	                result += withoutSuffix || isFuture ? 'ure' : 'urami';
	            } else {
	                result += withoutSuffix || isFuture ? 'ur' : 'urami';
	            }
	            return result;
	        case 'd':
	            return withoutSuffix || isFuture ? 'en dan' : 'enim dnem';
	        case 'dd':
	            if (number === 1) {
	                result += withoutSuffix || isFuture ? 'dan' : 'dnem';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'dni' : 'dnevoma';
	            } else {
	                result += withoutSuffix || isFuture ? 'dni' : 'dnevi';
	            }
	            return result;
	        case 'M':
	            return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem';
	        case 'MM':
	            if (number === 1) {
	                result += withoutSuffix || isFuture ? 'mesec' : 'mesecem';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'meseca' : 'mesecema';
	            } else if (number < 5) {
	                result += withoutSuffix || isFuture ? 'mesece' : 'meseci';
	            } else {
	                result += withoutSuffix || isFuture ? 'mesecev' : 'meseci';
	            }
	            return result;
	        case 'y':
	            return withoutSuffix || isFuture ? 'eno leto' : 'enim letom';
	        case 'yy':
	            if (number === 1) {
	                result += withoutSuffix || isFuture ? 'leto' : 'letom';
	            } else if (number === 2) {
	                result += withoutSuffix || isFuture ? 'leti' : 'letoma';
	            } else if (number < 5) {
	                result += withoutSuffix || isFuture ? 'leta' : 'leti';
	            } else {
	                result += withoutSuffix || isFuture ? 'let' : 'leti';
	            }
	            return result;
	    }
	}
	
	var sl = moment.defineLocale('sl', {
	    months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'),
	    monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'),
	    monthsParseExact: true,
	    weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'),
	    weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'),
	    weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM YYYY',
	        LLL : 'D. MMMM YYYY H:mm',
	        LLLL : 'dddd, D. MMMM YYYY H:mm'
	    },
	    calendar : {
	        sameDay  : '[danes ob] LT',
	        nextDay  : '[jutri ob] LT',
	
	        nextWeek : function () {
	            switch (this.day()) {
	                case 0:
	                    return '[v] [nedeljo] [ob] LT';
	                case 3:
	                    return '[v] [sredo] [ob] LT';
	                case 6:
	                    return '[v] [soboto] [ob] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[v] dddd [ob] LT';
	            }
	        },
	        lastDay  : '[včeraj ob] LT',
	        lastWeek : function () {
	            switch (this.day()) {
	                case 0:
	                    return '[prejšnjo] [nedeljo] [ob] LT';
	                case 3:
	                    return '[prejšnjo] [sredo] [ob] LT';
	                case 6:
	                    return '[prejšnjo] [soboto] [ob] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[prejšnji] dddd [ob] LT';
	            }
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'čez %s',
	        past   : 'pred %s',
	        s      : processRelativeTime,
	        m      : processRelativeTime,
	        mm     : processRelativeTime,
	        h      : processRelativeTime,
	        hh     : processRelativeTime,
	        d      : processRelativeTime,
	        dd     : processRelativeTime,
	        M      : processRelativeTime,
	        MM     : processRelativeTime,
	        y      : processRelativeTime,
	        yy     : processRelativeTime
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return sl;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/sl.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/sq.js **/
jupyter.define('moment@2.17.1/locale/sq.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Albanian [sq]
	//! author : Flakërim Ismani : https://github.com/flakerimi
	//! author : Menelion Elensúle : https://github.com/Oire
	//! author : Oerd Cukalla : https://github.com/oerd
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var sq = moment.defineLocale('sq', {
	    months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'),
	    monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'),
	    weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'),
	    weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'),
	    weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'),
	    weekdaysParseExact : true,
	    meridiemParse: /PD|MD/,
	    isPM: function (input) {
	        return input.charAt(0) === 'M';
	    },
	    meridiem : function (hours, minutes, isLower) {
	        return hours < 12 ? 'PD' : 'MD';
	    },
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[Sot në] LT',
	        nextDay : '[Nesër në] LT',
	        nextWeek : 'dddd [në] LT',
	        lastDay : '[Dje në] LT',
	        lastWeek : 'dddd [e kaluar në] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'në %s',
	        past : '%s më parë',
	        s : 'disa sekonda',
	        m : 'një minutë',
	        mm : '%d minuta',
	        h : 'një orë',
	        hh : '%d orë',
	        d : 'një ditë',
	        dd : '%d ditë',
	        M : 'një muaj',
	        MM : '%d muaj',
	        y : 'një vit',
	        yy : '%d vite'
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return sq;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/sq.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/sr.js **/
jupyter.define('moment@2.17.1/locale/sr.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Serbian [sr]
	//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var translator = {
	    words: { //Different grammatical cases
	        m: ['jedan minut', 'jedne minute'],
	        mm: ['minut', 'minute', 'minuta'],
	        h: ['jedan sat', 'jednog sata'],
	        hh: ['sat', 'sata', 'sati'],
	        dd: ['dan', 'dana', 'dana'],
	        MM: ['mesec', 'meseca', 'meseci'],
	        yy: ['godina', 'godine', 'godina']
	    },
	    correctGrammaticalCase: function (number, wordKey) {
	        return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
	    },
	    translate: function (number, withoutSuffix, key) {
	        var wordKey = translator.words[key];
	        if (key.length === 1) {
	            return withoutSuffix ? wordKey[0] : wordKey[1];
	        } else {
	            return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
	        }
	    }
	};
	
	var sr = moment.defineLocale('sr', {
	    months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'),
	    monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'),
	    monthsParseExact: true,
	    weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split('_'),
	    weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'),
	    weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat: {
	        LT: 'H:mm',
	        LTS : 'H:mm:ss',
	        L: 'DD.MM.YYYY',
	        LL: 'D. MMMM YYYY',
	        LLL: 'D. MMMM YYYY H:mm',
	        LLLL: 'dddd, D. MMMM YYYY H:mm'
	    },
	    calendar: {
	        sameDay: '[danas u] LT',
	        nextDay: '[sutra u] LT',
	        nextWeek: function () {
	            switch (this.day()) {
	                case 0:
	                    return '[u] [nedelju] [u] LT';
	                case 3:
	                    return '[u] [sredu] [u] LT';
	                case 6:
	                    return '[u] [subotu] [u] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[u] dddd [u] LT';
	            }
	        },
	        lastDay  : '[juče u] LT',
	        lastWeek : function () {
	            var lastWeekDays = [
	                '[prošle] [nedelje] [u] LT',
	                '[prošlog] [ponedeljka] [u] LT',
	                '[prošlog] [utorka] [u] LT',
	                '[prošle] [srede] [u] LT',
	                '[prošlog] [četvrtka] [u] LT',
	                '[prošlog] [petka] [u] LT',
	                '[prošle] [subote] [u] LT'
	            ];
	            return lastWeekDays[this.day()];
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'za %s',
	        past   : 'pre %s',
	        s      : 'nekoliko sekundi',
	        m      : translator.translate,
	        mm     : translator.translate,
	        h      : translator.translate,
	        hh     : translator.translate,
	        d      : 'dan',
	        dd     : translator.translate,
	        M      : 'mesec',
	        MM     : translator.translate,
	        y      : 'godinu',
	        yy     : translator.translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return sr;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/sr.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/sr-cyrl.js **/
jupyter.define('moment@2.17.1/locale/sr-cyrl.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Serbian Cyrillic [sr-cyrl]
	//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var translator = {
	    words: { //Different grammatical cases
	        m: ['један минут', 'једне минуте'],
	        mm: ['минут', 'минуте', 'минута'],
	        h: ['један сат', 'једног сата'],
	        hh: ['сат', 'сата', 'сати'],
	        dd: ['дан', 'дана', 'дана'],
	        MM: ['месец', 'месеца', 'месеци'],
	        yy: ['година', 'године', 'година']
	    },
	    correctGrammaticalCase: function (number, wordKey) {
	        return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
	    },
	    translate: function (number, withoutSuffix, key) {
	        var wordKey = translator.words[key];
	        if (key.length === 1) {
	            return withoutSuffix ? wordKey[0] : wordKey[1];
	        } else {
	            return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
	        }
	    }
	};
	
	var srCyrl = moment.defineLocale('sr-cyrl', {
	    months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split('_'),
	    monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split('_'),
	    monthsParseExact: true,
	    weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'),
	    weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'),
	    weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat: {
	        LT: 'H:mm',
	        LTS : 'H:mm:ss',
	        L: 'DD.MM.YYYY',
	        LL: 'D. MMMM YYYY',
	        LLL: 'D. MMMM YYYY H:mm',
	        LLLL: 'dddd, D. MMMM YYYY H:mm'
	    },
	    calendar: {
	        sameDay: '[данас у] LT',
	        nextDay: '[сутра у] LT',
	        nextWeek: function () {
	            switch (this.day()) {
	                case 0:
	                    return '[у] [недељу] [у] LT';
	                case 3:
	                    return '[у] [среду] [у] LT';
	                case 6:
	                    return '[у] [суботу] [у] LT';
	                case 1:
	                case 2:
	                case 4:
	                case 5:
	                    return '[у] dddd [у] LT';
	            }
	        },
	        lastDay  : '[јуче у] LT',
	        lastWeek : function () {
	            var lastWeekDays = [
	                '[прошле] [недеље] [у] LT',
	                '[прошлог] [понедељка] [у] LT',
	                '[прошлог] [уторка] [у] LT',
	                '[прошле] [среде] [у] LT',
	                '[прошлог] [четвртка] [у] LT',
	                '[прошлог] [петка] [у] LT',
	                '[прошле] [суботе] [у] LT'
	            ];
	            return lastWeekDays[this.day()];
	        },
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'за %s',
	        past   : 'пре %s',
	        s      : 'неколико секунди',
	        m      : translator.translate,
	        mm     : translator.translate,
	        h      : translator.translate,
	        hh     : translator.translate,
	        d      : 'дан',
	        dd     : translator.translate,
	        M      : 'месец',
	        MM     : translator.translate,
	        y      : 'годину',
	        yy     : translator.translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return srCyrl;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/sr-cyrl.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ss.js **/
jupyter.define('moment@2.17.1/locale/ss.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : siSwati [ss]
	//! author : Nicolai Davies<mail@nicolai.io> : https://github.com/nicolaidavies
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	
	var ss = moment.defineLocale('ss', {
	    months : "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split('_'),
	    monthsShort : 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'),
	    weekdays : 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split('_'),
	    weekdaysShort : 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'),
	    weekdaysMin : 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'h:mm A',
	        LTS : 'h:mm:ss A',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY h:mm A',
	        LLLL : 'dddd, D MMMM YYYY h:mm A'
	    },
	    calendar : {
	        sameDay : '[Namuhla nga] LT',
	        nextDay : '[Kusasa nga] LT',
	        nextWeek : 'dddd [nga] LT',
	        lastDay : '[Itolo nga] LT',
	        lastWeek : 'dddd [leliphelile] [nga] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'nga %s',
	        past : 'wenteka nga %s',
	        s : 'emizuzwana lomcane',
	        m : 'umzuzu',
	        mm : '%d emizuzu',
	        h : 'lihora',
	        hh : '%d emahora',
	        d : 'lilanga',
	        dd : '%d emalanga',
	        M : 'inyanga',
	        MM : '%d tinyanga',
	        y : 'umnyaka',
	        yy : '%d iminyaka'
	    },
	    meridiemParse: /ekuseni|emini|entsambama|ebusuku/,
	    meridiem : function (hours, minutes, isLower) {
	        if (hours < 11) {
	            return 'ekuseni';
	        } else if (hours < 15) {
	            return 'emini';
	        } else if (hours < 19) {
	            return 'entsambama';
	        } else {
	            return 'ebusuku';
	        }
	    },
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'ekuseni') {
	            return hour;
	        } else if (meridiem === 'emini') {
	            return hour >= 11 ? hour : hour + 12;
	        } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') {
	            if (hour === 0) {
	                return 0;
	            }
	            return hour + 12;
	        }
	    },
	    ordinalParse: /\d{1,2}/,
	    ordinal : '%d',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return ss;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ss.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/sv.js **/
jupyter.define('moment@2.17.1/locale/sv.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Swedish [sv]
	//! author : Jens Alm : https://github.com/ulmus
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var sv = moment.defineLocale('sv', {
	    months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'),
	    monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
	    weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'),
	    weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'),
	    weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'YYYY-MM-DD',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY [kl.] HH:mm',
	        LLLL : 'dddd D MMMM YYYY [kl.] HH:mm',
	        lll : 'D MMM YYYY HH:mm',
	        llll : 'ddd D MMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[Idag] LT',
	        nextDay: '[Imorgon] LT',
	        lastDay: '[Igår] LT',
	        nextWeek: '[På] dddd LT',
	        lastWeek: '[I] dddd[s] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'om %s',
	        past : 'för %s sedan',
	        s : 'några sekunder',
	        m : 'en minut',
	        mm : '%d minuter',
	        h : 'en timme',
	        hh : '%d timmar',
	        d : 'en dag',
	        dd : '%d dagar',
	        M : 'en månad',
	        MM : '%d månader',
	        y : 'ett år',
	        yy : '%d år'
	    },
	    ordinalParse: /\d{1,2}(e|a)/,
	    ordinal : function (number) {
	        var b = number % 10,
	            output = (~~(number % 100 / 10) === 1) ? 'e' :
	            (b === 1) ? 'a' :
	            (b === 2) ? 'a' :
	            (b === 3) ? 'e' : 'e';
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return sv;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/sv.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/sw.js **/
jupyter.define('moment@2.17.1/locale/sw.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Swahili [sw]
	//! author : Fahad Kassim : https://github.com/fadsel
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var sw = moment.defineLocale('sw', {
	    months : 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split('_'),
	    monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'),
	    weekdays : 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split('_'),
	    weekdaysShort : 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'),
	    weekdaysMin : 'J2_J3_J4_J5_Al_Ij_J1'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[leo saa] LT',
	        nextDay : '[kesho saa] LT',
	        nextWeek : '[wiki ijayo] dddd [saat] LT',
	        lastDay : '[jana] LT',
	        lastWeek : '[wiki iliyopita] dddd [saat] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s baadaye',
	        past : 'tokea %s',
	        s : 'hivi punde',
	        m : 'dakika moja',
	        mm : 'dakika %d',
	        h : 'saa limoja',
	        hh : 'masaa %d',
	        d : 'siku moja',
	        dd : 'masiku %d',
	        M : 'mwezi mmoja',
	        MM : 'miezi %d',
	        y : 'mwaka mmoja',
	        yy : 'miaka %d'
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return sw;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/sw.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/ta.js **/
jupyter.define('moment@2.17.1/locale/ta.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Tamil [ta]
	//! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var symbolMap = {
	    '1': '௧',
	    '2': '௨',
	    '3': '௩',
	    '4': '௪',
	    '5': '௫',
	    '6': '௬',
	    '7': '௭',
	    '8': '௮',
	    '9': '௯',
	    '0': '௦'
	};
	var numberMap = {
	    '௧': '1',
	    '௨': '2',
	    '௩': '3',
	    '௪': '4',
	    '௫': '5',
	    '௬': '6',
	    '௭': '7',
	    '௮': '8',
	    '௯': '9',
	    '௦': '0'
	};
	
	var ta = moment.defineLocale('ta', {
	    months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
	    monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
	    weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'),
	    weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'),
	    weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY, HH:mm',
	        LLLL : 'dddd, D MMMM YYYY, HH:mm'
	    },
	    calendar : {
	        sameDay : '[இன்று] LT',
	        nextDay : '[நாளை] LT',
	        nextWeek : 'dddd, LT',
	        lastDay : '[நேற்று] LT',
	        lastWeek : '[கடந்த வாரம்] dddd, LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s இல்',
	        past : '%s முன்',
	        s : 'ஒரு சில விநாடிகள்',
	        m : 'ஒரு நிமிடம்',
	        mm : '%d நிமிடங்கள்',
	        h : 'ஒரு மணி நேரம்',
	        hh : '%d மணி நேரம்',
	        d : 'ஒரு நாள்',
	        dd : '%d நாட்கள்',
	        M : 'ஒரு மாதம்',
	        MM : '%d மாதங்கள்',
	        y : 'ஒரு வருடம்',
	        yy : '%d ஆண்டுகள்'
	    },
	    ordinalParse: /\d{1,2}வது/,
	    ordinal : function (number) {
	        return number + 'வது';
	    },
	    preparse: function (string) {
	        return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
	            return numberMap[match];
	        });
	    },
	    postformat: function (string) {
	        return string.replace(/\d/g, function (match) {
	            return symbolMap[match];
	        });
	    },
	    // refer http://ta.wikipedia.org/s/1er1
	    meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 2) {
	            return ' யாமம்';
	        } else if (hour < 6) {
	            return ' வைகறை';  // வைகறை
	        } else if (hour < 10) {
	            return ' காலை'; // காலை
	        } else if (hour < 14) {
	            return ' நண்பகல்'; // நண்பகல்
	        } else if (hour < 18) {
	            return ' எற்பாடு'; // எற்பாடு
	        } else if (hour < 22) {
	            return ' மாலை'; // மாலை
	        } else {
	            return ' யாமம்';
	        }
	    },
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'யாமம்') {
	            return hour < 2 ? hour : hour + 12;
	        } else if (meridiem === 'வைகறை' || meridiem === 'காலை') {
	            return hour;
	        } else if (meridiem === 'நண்பகல்') {
	            return hour >= 10 ? hour : hour + 12;
	        } else {
	            return hour + 12;
	        }
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return ta;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/ta.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/te.js **/
jupyter.define('moment@2.17.1/locale/te.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Telugu [te]
	//! author : Krishna Chaitanya Thota : https://github.com/kcthota
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var te = moment.defineLocale('te', {
	    months : 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split('_'),
	    monthsShort : 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split('_'),
	    weekdaysShort : 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'),
	    weekdaysMin : 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'),
	    longDateFormat : {
	        LT : 'A h:mm',
	        LTS : 'A h:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY, A h:mm',
	        LLLL : 'dddd, D MMMM YYYY, A h:mm'
	    },
	    calendar : {
	        sameDay : '[నేడు] LT',
	        nextDay : '[రేపు] LT',
	        nextWeek : 'dddd, LT',
	        lastDay : '[నిన్న] LT',
	        lastWeek : '[గత] dddd, LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s లో',
	        past : '%s క్రితం',
	        s : 'కొన్ని క్షణాలు',
	        m : 'ఒక నిమిషం',
	        mm : '%d నిమిషాలు',
	        h : 'ఒక గంట',
	        hh : '%d గంటలు',
	        d : 'ఒక రోజు',
	        dd : '%d రోజులు',
	        M : 'ఒక నెల',
	        MM : '%d నెలలు',
	        y : 'ఒక సంవత్సరం',
	        yy : '%d సంవత్సరాలు'
	    },
	    ordinalParse : /\d{1,2}వ/,
	    ordinal : '%dవ',
	    meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === 'రాత్రి') {
	            return hour < 4 ? hour : hour + 12;
	        } else if (meridiem === 'ఉదయం') {
	            return hour;
	        } else if (meridiem === 'మధ్యాహ్నం') {
	            return hour >= 10 ? hour : hour + 12;
	        } else if (meridiem === 'సాయంత్రం') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'రాత్రి';
	        } else if (hour < 10) {
	            return 'ఉదయం';
	        } else if (hour < 17) {
	            return 'మధ్యాహ్నం';
	        } else if (hour < 20) {
	            return 'సాయంత్రం';
	        } else {
	            return 'రాత్రి';
	        }
	    },
	    week : {
	        dow : 0, // Sunday is the first day of the week.
	        doy : 6  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return te;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/te.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/tet.js **/
jupyter.define('moment@2.17.1/locale/tet.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Tetun Dili (East Timor) [tet]
	//! author : Joshua Brooks : https://github.com/joshbrooks
	//! author : Onorio De J. Afonso : https://github.com/marobo
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var tet = moment.defineLocale('tet', {
	    months : 'Janeiru_Fevereiru_Marsu_Abril_Maiu_Juniu_Juliu_Augustu_Setembru_Outubru_Novembru_Dezembru'.split('_'),
	    monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Aug_Set_Out_Nov_Dez'.split('_'),
	    weekdays : 'Domingu_Segunda_Tersa_Kuarta_Kinta_Sexta_Sabadu'.split('_'),
	    weekdaysShort : 'Dom_Seg_Ters_Kua_Kint_Sext_Sab'.split('_'),
	    weekdaysMin : 'Do_Seg_Te_Ku_Ki_Sex_Sa'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[Ohin iha] LT',
	        nextDay: '[Aban iha] LT',
	        nextWeek: 'dddd [iha] LT',
	        lastDay: '[Horiseik iha] LT',
	        lastWeek: 'dddd [semana kotuk] [iha] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'iha %s',
	        past : '%s liuba',
	        s : 'minutu balun',
	        m : 'minutu ida',
	        mm : 'minutus %d',
	        h : 'horas ida',
	        hh : 'horas %d',
	        d : 'loron ida',
	        dd : 'loron %d',
	        M : 'fulan ida',
	        MM : 'fulan %d',
	        y : 'tinan ida',
	        yy : 'tinan %d'
	    },
	    ordinalParse: /\d{1,2}(st|nd|rd|th)/,
	    ordinal : function (number) {
	        var b = number % 10,
	            output = (~~(number % 100 / 10) === 1) ? 'th' :
	            (b === 1) ? 'st' :
	            (b === 2) ? 'nd' :
	            (b === 3) ? 'rd' : 'th';
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return tet;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/tet.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/th.js **/
jupyter.define('moment@2.17.1/locale/th.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Thai [th]
	//! author : Kridsada Thanabulpong : https://github.com/sirn
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var th = moment.defineLocale('th', {
	    months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'),
	    monthsShort : 'ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.'.split('_'),
	    monthsParseExact: true,
	    weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'),
	    weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference
	    weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'H:mm',
	        LTS : 'H:mm:ss',
	        L : 'YYYY/MM/DD',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY เวลา H:mm',
	        LLLL : 'วันddddที่ D MMMM YYYY เวลา H:mm'
	    },
	    meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/,
	    isPM: function (input) {
	        return input === 'หลังเที่ยง';
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 12) {
	            return 'ก่อนเที่ยง';
	        } else {
	            return 'หลังเที่ยง';
	        }
	    },
	    calendar : {
	        sameDay : '[วันนี้ เวลา] LT',
	        nextDay : '[พรุ่งนี้ เวลา] LT',
	        nextWeek : 'dddd[หน้า เวลา] LT',
	        lastDay : '[เมื่อวานนี้ เวลา] LT',
	        lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'อีก %s',
	        past : '%sที่แล้ว',
	        s : 'ไม่กี่วินาที',
	        m : '1 นาที',
	        mm : '%d นาที',
	        h : '1 ชั่วโมง',
	        hh : '%d ชั่วโมง',
	        d : '1 วัน',
	        dd : '%d วัน',
	        M : '1 เดือน',
	        MM : '%d เดือน',
	        y : '1 ปี',
	        yy : '%d ปี'
	    }
	});
	
	return th;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/th.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/tl-ph.js **/
jupyter.define('moment@2.17.1/locale/tl-ph.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Tagalog (Philippines) [tl-ph]
	//! author : Dan Hagman : https://github.com/hagmandan
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var tlPh = moment.defineLocale('tl-ph', {
	    months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'),
	    monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'),
	    weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'),
	    weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'),
	    weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'MM/D/YYYY',
	        LL : 'MMMM D, YYYY',
	        LLL : 'MMMM D, YYYY HH:mm',
	        LLLL : 'dddd, MMMM DD, YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: 'LT [ngayong araw]',
	        nextDay: '[Bukas ng] LT',
	        nextWeek: 'LT [sa susunod na] dddd',
	        lastDay: 'LT [kahapon]',
	        lastWeek: 'LT [noong nakaraang] dddd',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'sa loob ng %s',
	        past : '%s ang nakalipas',
	        s : 'ilang segundo',
	        m : 'isang minuto',
	        mm : '%d minuto',
	        h : 'isang oras',
	        hh : '%d oras',
	        d : 'isang araw',
	        dd : '%d araw',
	        M : 'isang buwan',
	        MM : '%d buwan',
	        y : 'isang taon',
	        yy : '%d taon'
	    },
	    ordinalParse: /\d{1,2}/,
	    ordinal : function (number) {
	        return number;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return tlPh;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/tl-ph.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/tlh.js **/
jupyter.define('moment@2.17.1/locale/tlh.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Klingon [tlh]
	//! author : Dominika Kruk : https://github.com/amaranthrose
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var numbersNouns = 'pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut'.split('_');
	
	function translateFuture(output) {
	    var time = output;
	    time = (output.indexOf('jaj') !== -1) ?
	    time.slice(0, -3) + 'leS' :
	    (output.indexOf('jar') !== -1) ?
	    time.slice(0, -3) + 'waQ' :
	    (output.indexOf('DIS') !== -1) ?
	    time.slice(0, -3) + 'nem' :
	    time + ' pIq';
	    return time;
	}
	
	function translatePast(output) {
	    var time = output;
	    time = (output.indexOf('jaj') !== -1) ?
	    time.slice(0, -3) + 'Hu’' :
	    (output.indexOf('jar') !== -1) ?
	    time.slice(0, -3) + 'wen' :
	    (output.indexOf('DIS') !== -1) ?
	    time.slice(0, -3) + 'ben' :
	    time + ' ret';
	    return time;
	}
	
	function translate(number, withoutSuffix, string, isFuture) {
	    var numberNoun = numberAsNoun(number);
	    switch (string) {
	        case 'mm':
	            return numberNoun + ' tup';
	        case 'hh':
	            return numberNoun + ' rep';
	        case 'dd':
	            return numberNoun + ' jaj';
	        case 'MM':
	            return numberNoun + ' jar';
	        case 'yy':
	            return numberNoun + ' DIS';
	    }
	}
	
	function numberAsNoun(number) {
	    var hundred = Math.floor((number % 1000) / 100),
	    ten = Math.floor((number % 100) / 10),
	    one = number % 10,
	    word = '';
	    if (hundred > 0) {
	        word += numbersNouns[hundred] + 'vatlh';
	    }
	    if (ten > 0) {
	        word += ((word !== '') ? ' ' : '') + numbersNouns[ten] + 'maH';
	    }
	    if (one > 0) {
	        word += ((word !== '') ? ' ' : '') + numbersNouns[one];
	    }
	    return (word === '') ? 'pagh' : word;
	}
	
	var tlh = moment.defineLocale('tlh', {
	    months : 'tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’'.split('_'),
	    monthsShort : 'jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
	    weekdaysShort : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
	    weekdaysMin : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[DaHjaj] LT',
	        nextDay: '[wa’leS] LT',
	        nextWeek: 'LLL',
	        lastDay: '[wa’Hu’] LT',
	        lastWeek: 'LLL',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : translateFuture,
	        past : translatePast,
	        s : 'puS lup',
	        m : 'wa’ tup',
	        mm : translate,
	        h : 'wa’ rep',
	        hh : translate,
	        d : 'wa’ jaj',
	        dd : translate,
	        M : 'wa’ jar',
	        MM : translate,
	        y : 'wa’ DIS',
	        yy : translate
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return tlh;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/tlh.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/tr.js **/
jupyter.define('moment@2.17.1/locale/tr.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Turkish [tr]
	//! authors : Erhan Gundogan : https://github.com/erhangundogan,
	//!           Burak Yiğit Kaya: https://github.com/BYK
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var suffixes = {
	    1: '\'inci',
	    5: '\'inci',
	    8: '\'inci',
	    70: '\'inci',
	    80: '\'inci',
	    2: '\'nci',
	    7: '\'nci',
	    20: '\'nci',
	    50: '\'nci',
	    3: '\'üncü',
	    4: '\'üncü',
	    100: '\'üncü',
	    6: '\'ncı',
	    9: '\'uncu',
	    10: '\'uncu',
	    30: '\'uncu',
	    60: '\'ıncı',
	    90: '\'ıncı'
	};
	
	var tr = moment.defineLocale('tr', {
	    months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
	    monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
	    weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
	    weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
	    weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[bugün saat] LT',
	        nextDay : '[yarın saat] LT',
	        nextWeek : '[haftaya] dddd [saat] LT',
	        lastDay : '[dün] LT',
	        lastWeek : '[geçen hafta] dddd [saat] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : '%s sonra',
	        past : '%s önce',
	        s : 'birkaç saniye',
	        m : 'bir dakika',
	        mm : '%d dakika',
	        h : 'bir saat',
	        hh : '%d saat',
	        d : 'bir gün',
	        dd : '%d gün',
	        M : 'bir ay',
	        MM : '%d ay',
	        y : 'bir yıl',
	        yy : '%d yıl'
	    },
	    ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
	    ordinal : function (number) {
	        if (number === 0) {  // special case for zero
	            return number + '\'ıncı';
	        }
	        var a = number % 10,
	            b = number % 100 - a,
	            c = number >= 100 ? 100 : null;
	        return number + (suffixes[a] || suffixes[b] || suffixes[c]);
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return tr;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/tr.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/tzl.js **/
jupyter.define('moment@2.17.1/locale/tzl.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Talossan [tzl]
	//! author : Robin van der Vliet : https://github.com/robin0van0der0v
	//! author : Iustì Canun
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	// After the year there should be a slash and the amount of years since December 26, 1979 in Roman numerals.
	// This is currently too difficult (maybe even impossible) to add.
	var tzl = moment.defineLocale('tzl', {
	    months : 'Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar'.split('_'),
	    monthsShort : 'Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec'.split('_'),
	    weekdays : 'Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi'.split('_'),
	    weekdaysShort : 'Súl_Lún_Mai_Már_Xhú_Vié_Sát'.split('_'),
	    weekdaysMin : 'Sú_Lú_Ma_Má_Xh_Vi_Sá'.split('_'),
	    longDateFormat : {
	        LT : 'HH.mm',
	        LTS : 'HH.mm.ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D. MMMM [dallas] YYYY',
	        LLL : 'D. MMMM [dallas] YYYY HH.mm',
	        LLLL : 'dddd, [li] D. MMMM [dallas] YYYY HH.mm'
	    },
	    meridiemParse: /d\'o|d\'a/i,
	    isPM : function (input) {
	        return 'd\'o' === input.toLowerCase();
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours > 11) {
	            return isLower ? 'd\'o' : 'D\'O';
	        } else {
	            return isLower ? 'd\'a' : 'D\'A';
	        }
	    },
	    calendar : {
	        sameDay : '[oxhi à] LT',
	        nextDay : '[demà à] LT',
	        nextWeek : 'dddd [à] LT',
	        lastDay : '[ieiri à] LT',
	        lastWeek : '[sür el] dddd [lasteu à] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'osprei %s',
	        past : 'ja%s',
	        s : processRelativeTime,
	        m : processRelativeTime,
	        mm : processRelativeTime,
	        h : processRelativeTime,
	        hh : processRelativeTime,
	        d : processRelativeTime,
	        dd : processRelativeTime,
	        M : processRelativeTime,
	        MM : processRelativeTime,
	        y : processRelativeTime,
	        yy : processRelativeTime
	    },
	    ordinalParse: /\d{1,2}\./,
	    ordinal : '%d.',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	function processRelativeTime(number, withoutSuffix, key, isFuture) {
	    var format = {
	        's': ['viensas secunds', '\'iensas secunds'],
	        'm': ['\'n míut', '\'iens míut'],
	        'mm': [number + ' míuts', '' + number + ' míuts'],
	        'h': ['\'n þora', '\'iensa þora'],
	        'hh': [number + ' þoras', '' + number + ' þoras'],
	        'd': ['\'n ziua', '\'iensa ziua'],
	        'dd': [number + ' ziuas', '' + number + ' ziuas'],
	        'M': ['\'n mes', '\'iens mes'],
	        'MM': [number + ' mesen', '' + number + ' mesen'],
	        'y': ['\'n ar', '\'iens ar'],
	        'yy': [number + ' ars', '' + number + ' ars']
	    };
	    return isFuture ? format[key][0] : (withoutSuffix ? format[key][0] : format[key][1]);
	}
	
	return tzl;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/tzl.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/tzm.js **/
jupyter.define('moment@2.17.1/locale/tzm.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Central Atlas Tamazight [tzm]
	//! author : Abdel Said : https://github.com/abdelsaid
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var tzm = moment.defineLocale('tzm', {
	    months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
	    monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
	    weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
	    weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
	    weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS: 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[ⴰⵙⴷⵅ ⴴ] LT',
	        nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
	        nextWeek: 'dddd [ⴴ] LT',
	        lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
	        lastWeek: 'dddd [ⴴ] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s',
	        past : 'ⵢⴰⵏ %s',
	        s : 'ⵉⵎⵉⴽ',
	        m : 'ⵎⵉⵏⵓⴺ',
	        mm : '%d ⵎⵉⵏⵓⴺ',
	        h : 'ⵙⴰⵄⴰ',
	        hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ',
	        d : 'ⴰⵙⵙ',
	        dd : '%d oⵙⵙⴰⵏ',
	        M : 'ⴰⵢoⵓⵔ',
	        MM : '%d ⵉⵢⵢⵉⵔⵏ',
	        y : 'ⴰⵙⴳⴰⵙ',
	        yy : '%d ⵉⵙⴳⴰⵙⵏ'
	    },
	    week : {
	        dow : 6, // Saturday is the first day of the week.
	        doy : 12  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return tzm;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/tzm.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/tzm-latn.js **/
jupyter.define('moment@2.17.1/locale/tzm-latn.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Central Atlas Tamazight Latin [tzm-latn]
	//! author : Abdel Said : https://github.com/abdelsaid
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var tzmLatn = moment.defineLocale('tzm-latn', {
	    months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
	    monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
	    weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
	    weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
	    weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[asdkh g] LT',
	        nextDay: '[aska g] LT',
	        nextWeek: 'dddd [g] LT',
	        lastDay: '[assant g] LT',
	        lastWeek: 'dddd [g] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'dadkh s yan %s',
	        past : 'yan %s',
	        s : 'imik',
	        m : 'minuḍ',
	        mm : '%d minuḍ',
	        h : 'saɛa',
	        hh : '%d tassaɛin',
	        d : 'ass',
	        dd : '%d ossan',
	        M : 'ayowr',
	        MM : '%d iyyirn',
	        y : 'asgas',
	        yy : '%d isgasn'
	    },
	    week : {
	        dow : 6, // Saturday is the first day of the week.
	        doy : 12  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return tzmLatn;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/tzm-latn.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/uk.js **/
jupyter.define('moment@2.17.1/locale/uk.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Ukrainian [uk]
	//! author : zemlanin : https://github.com/zemlanin
	//! Author : Menelion Elensúle : https://github.com/Oire
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	function plural(word, num) {
	    var forms = word.split('_');
	    return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
	}
	function relativeTimeWithPlural(number, withoutSuffix, key) {
	    var format = {
	        'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин',
	        'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин',
	        'dd': 'день_дні_днів',
	        'MM': 'місяць_місяці_місяців',
	        'yy': 'рік_роки_років'
	    };
	    if (key === 'm') {
	        return withoutSuffix ? 'хвилина' : 'хвилину';
	    }
	    else if (key === 'h') {
	        return withoutSuffix ? 'година' : 'годину';
	    }
	    else {
	        return number + ' ' + plural(format[key], +number);
	    }
	}
	function weekdaysCaseReplace(m, format) {
	    var weekdays = {
	        'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
	        'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
	        'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
	    },
	    nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
	        'accusative' :
	        ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
	            'genitive' :
	            'nominative');
	    return weekdays[nounCase][m.day()];
	}
	function processHoursFunction(str) {
	    return function () {
	        return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
	    };
	}
	
	var uk = moment.defineLocale('uk', {
	    months : {
	        'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'),
	        'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_')
	    },
	    monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'),
	    weekdays : weekdaysCaseReplace,
	    weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
	    weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD.MM.YYYY',
	        LL : 'D MMMM YYYY р.',
	        LLL : 'D MMMM YYYY р., HH:mm',
	        LLLL : 'dddd, D MMMM YYYY р., HH:mm'
	    },
	    calendar : {
	        sameDay: processHoursFunction('[Сьогодні '),
	        nextDay: processHoursFunction('[Завтра '),
	        lastDay: processHoursFunction('[Вчора '),
	        nextWeek: processHoursFunction('[У] dddd ['),
	        lastWeek: function () {
	            switch (this.day()) {
	                case 0:
	                case 3:
	                case 5:
	                case 6:
	                    return processHoursFunction('[Минулої] dddd [').call(this);
	                case 1:
	                case 2:
	                case 4:
	                    return processHoursFunction('[Минулого] dddd [').call(this);
	            }
	        },
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : 'за %s',
	        past : '%s тому',
	        s : 'декілька секунд',
	        m : relativeTimeWithPlural,
	        mm : relativeTimeWithPlural,
	        h : 'годину',
	        hh : relativeTimeWithPlural,
	        d : 'день',
	        dd : relativeTimeWithPlural,
	        M : 'місяць',
	        MM : relativeTimeWithPlural,
	        y : 'рік',
	        yy : relativeTimeWithPlural
	    },
	    // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
	    meridiemParse: /ночі|ранку|дня|вечора/,
	    isPM: function (input) {
	        return /^(дня|вечора)$/.test(input);
	    },
	    meridiem : function (hour, minute, isLower) {
	        if (hour < 4) {
	            return 'ночі';
	        } else if (hour < 12) {
	            return 'ранку';
	        } else if (hour < 17) {
	            return 'дня';
	        } else {
	            return 'вечора';
	        }
	    },
	    ordinalParse: /\d{1,2}-(й|го)/,
	    ordinal: function (number, period) {
	        switch (period) {
	            case 'M':
	            case 'd':
	            case 'DDD':
	            case 'w':
	            case 'W':
	                return number + '-й';
	            case 'D':
	                return number + '-го';
	            default:
	                return number;
	        }
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 1st is the first week of the year.
	    }
	});
	
	return uk;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/uk.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/uz.js **/
jupyter.define('moment@2.17.1/locale/uz.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Uzbek [uz]
	//! author : Sardor Muminov : https://github.com/muminoff
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var uz = moment.defineLocale('uz', {
	    months : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split('_'),
	    monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'),
	    weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'),
	    weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'),
	    weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'),
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'D MMMM YYYY, dddd HH:mm'
	    },
	    calendar : {
	        sameDay : '[Бугун соат] LT [да]',
	        nextDay : '[Эртага] LT [да]',
	        nextWeek : 'dddd [куни соат] LT [да]',
	        lastDay : '[Кеча соат] LT [да]',
	        lastWeek : '[Утган] dddd [куни соат] LT [да]',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'Якин %s ичида',
	        past : 'Бир неча %s олдин',
	        s : 'фурсат',
	        m : 'бир дакика',
	        mm : '%d дакика',
	        h : 'бир соат',
	        hh : '%d соат',
	        d : 'бир кун',
	        dd : '%d кун',
	        M : 'бир ой',
	        MM : '%d ой',
	        y : 'бир йил',
	        yy : '%d йил'
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 7  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return uz;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/uz.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/vi.js **/
jupyter.define('moment@2.17.1/locale/vi.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Vietnamese [vi]
	//! author : Bang Nguyen : https://github.com/bangnk
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var vi = moment.defineLocale('vi', {
	    months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'),
	    monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'),
	    weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
	    weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
	    weekdaysParseExact : true,
	    meridiemParse: /sa|ch/i,
	    isPM : function (input) {
	        return /^ch$/i.test(input);
	    },
	    meridiem : function (hours, minutes, isLower) {
	        if (hours < 12) {
	            return isLower ? 'sa' : 'SA';
	        } else {
	            return isLower ? 'ch' : 'CH';
	        }
	    },
	    longDateFormat : {
	        LT : 'HH:mm',
	        LTS : 'HH:mm:ss',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM [năm] YYYY',
	        LLL : 'D MMMM [năm] YYYY HH:mm',
	        LLLL : 'dddd, D MMMM [năm] YYYY HH:mm',
	        l : 'DD/M/YYYY',
	        ll : 'D MMM YYYY',
	        lll : 'D MMM YYYY HH:mm',
	        llll : 'ddd, D MMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay: '[Hôm nay lúc] LT',
	        nextDay: '[Ngày mai lúc] LT',
	        nextWeek: 'dddd [tuần tới lúc] LT',
	        lastDay: '[Hôm qua lúc] LT',
	        lastWeek: 'dddd [tuần rồi lúc] LT',
	        sameElse: 'L'
	    },
	    relativeTime : {
	        future : '%s tới',
	        past : '%s trước',
	        s : 'vài giây',
	        m : 'một phút',
	        mm : '%d phút',
	        h : 'một giờ',
	        hh : '%d giờ',
	        d : 'một ngày',
	        dd : '%d ngày',
	        M : 'một tháng',
	        MM : '%d tháng',
	        y : 'một năm',
	        yy : '%d năm'
	    },
	    ordinalParse: /\d{1,2}/,
	    ordinal : function (number) {
	        return number;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return vi;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/vi.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/x-pseudo.js **/
jupyter.define('moment@2.17.1/locale/x-pseudo.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Pseudo [x-pseudo]
	//! author : Andrew Hood : https://github.com/andrewhood125
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var xPseudo = moment.defineLocale('x-pseudo', {
	    months : 'J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér'.split('_'),
	    monthsShort : 'J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc'.split('_'),
	    monthsParseExact : true,
	    weekdays : 'S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý'.split('_'),
	    weekdaysShort : 'S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát'.split('_'),
	    weekdaysMin : 'S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá'.split('_'),
	    weekdaysParseExact : true,
	    longDateFormat : {
	        LT : 'HH:mm',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY HH:mm',
	        LLLL : 'dddd, D MMMM YYYY HH:mm'
	    },
	    calendar : {
	        sameDay : '[T~ódá~ý át] LT',
	        nextDay : '[T~ómó~rró~w át] LT',
	        nextWeek : 'dddd [át] LT',
	        lastDay : '[Ý~ést~érdá~ý át] LT',
	        lastWeek : '[L~ást] dddd [át] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'í~ñ %s',
	        past : '%s á~gó',
	        s : 'á ~féw ~sécó~ñds',
	        m : 'á ~míñ~úté',
	        mm : '%d m~íñú~tés',
	        h : 'á~ñ hó~úr',
	        hh : '%d h~óúrs',
	        d : 'á ~dáý',
	        dd : '%d d~áýs',
	        M : 'á ~móñ~th',
	        MM : '%d m~óñt~hs',
	        y : 'á ~ýéár',
	        yy : '%d ý~éárs'
	    },
	    ordinalParse: /\d{1,2}(th|st|nd|rd)/,
	    ordinal : function (number) {
	        var b = number % 10,
	            output = (~~(number % 100 / 10) === 1) ? 'th' :
	            (b === 1) ? 'st' :
	            (b === 2) ? 'nd' :
	            (b === 3) ? 'rd' : 'th';
	        return number + output;
	    },
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return xPseudo;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/x-pseudo.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/yo.js **/
jupyter.define('moment@2.17.1/locale/yo.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Yoruba Nigeria [yo]
	//! author : Atolagbe Abisoye : https://github.com/andela-batolagbe
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var yo = moment.defineLocale('yo', {
	    months : 'Sẹ́rẹ́_Èrèlè_Ẹrẹ̀nà_Ìgbé_Èbibi_Òkùdu_Agẹmo_Ògún_Owewe_Ọ̀wàrà_Bélú_Ọ̀pẹ̀̀'.split('_'),
	    monthsShort : 'Sẹ́r_Èrl_Ẹrn_Ìgb_Èbi_Òkù_Agẹ_Ògú_Owe_Ọ̀wà_Bél_Ọ̀pẹ̀̀'.split('_'),
	    weekdays : 'Àìkú_Ajé_Ìsẹ́gun_Ọjọ́rú_Ọjọ́bọ_Ẹtì_Àbámẹ́ta'.split('_'),
	    weekdaysShort : 'Àìk_Ajé_Ìsẹ́_Ọjr_Ọjb_Ẹtì_Àbá'.split('_'),
	    weekdaysMin : 'Àì_Aj_Ìs_Ọr_Ọb_Ẹt_Àb'.split('_'),
	    longDateFormat : {
	        LT : 'h:mm A',
	        LTS : 'h:mm:ss A',
	        L : 'DD/MM/YYYY',
	        LL : 'D MMMM YYYY',
	        LLL : 'D MMMM YYYY h:mm A',
	        LLLL : 'dddd, D MMMM YYYY h:mm A'
	    },
	    calendar : {
	        sameDay : '[Ònì ni] LT',
	        nextDay : '[Ọ̀la ni] LT',
	        nextWeek : 'dddd [Ọsẹ̀ tón\'bọ] [ni] LT',
	        lastDay : '[Àna ni] LT',
	        lastWeek : 'dddd [Ọsẹ̀ tólọ́] [ni] LT',
	        sameElse : 'L'
	    },
	    relativeTime : {
	        future : 'ní %s',
	        past : '%s kọjá',
	        s : 'ìsẹjú aayá die',
	        m : 'ìsẹjú kan',
	        mm : 'ìsẹjú %d',
	        h : 'wákati kan',
	        hh : 'wákati %d',
	        d : 'ọjọ́ kan',
	        dd : 'ọjọ́ %d',
	        M : 'osù kan',
	        MM : 'osù %d',
	        y : 'ọdún kan',
	        yy : 'ọdún %d'
	    },
	    ordinalParse : /ọjọ́\s\d{1,2}/,
	    ordinal : 'ọjọ́ %d',
	    week : {
	        dow : 1, // Monday is the first day of the week.
	        doy : 4 // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return yo;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/yo.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/zh-cn.js **/
jupyter.define('moment@2.17.1/locale/zh-cn.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Chinese (China) [zh-cn]
	//! author : suupic : https://github.com/suupic
	//! author : Zeno Zeng : https://github.com/zenozeng
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var zhCn = moment.defineLocale('zh-cn', {
	    months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
	    monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
	    weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
	    weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'),
	    weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
	    longDateFormat : {
	        LT : 'Ah点mm分',
	        LTS : 'Ah点m分s秒',
	        L : 'YYYY-MM-DD',
	        LL : 'YYYY年MMMD日',
	        LLL : 'YYYY年MMMD日Ah点mm分',
	        LLLL : 'YYYY年MMMD日ddddAh点mm分',
	        l : 'YYYY-MM-DD',
	        ll : 'YYYY年MMMD日',
	        lll : 'YYYY年MMMD日Ah点mm分',
	        llll : 'YYYY年MMMD日ddddAh点mm分'
	    },
	    meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
	    meridiemHour: function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === '凌晨' || meridiem === '早上' ||
	                meridiem === '上午') {
	            return hour;
	        } else if (meridiem === '下午' || meridiem === '晚上') {
	            return hour + 12;
	        } else {
	            // '中午'
	            return hour >= 11 ? hour : hour + 12;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        var hm = hour * 100 + minute;
	        if (hm < 600) {
	            return '凌晨';
	        } else if (hm < 900) {
	            return '早上';
	        } else if (hm < 1130) {
	            return '上午';
	        } else if (hm < 1230) {
	            return '中午';
	        } else if (hm < 1800) {
	            return '下午';
	        } else {
	            return '晚上';
	        }
	    },
	    calendar : {
	        sameDay : function () {
	            return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT';
	        },
	        nextDay : function () {
	            return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT';
	        },
	        lastDay : function () {
	            return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT';
	        },
	        nextWeek : function () {
	            var startOfWeek, prefix;
	            startOfWeek = moment().startOf('week');
	            prefix = this.diff(startOfWeek, 'days') >= 7 ? '[下]' : '[本]';
	            return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
	        },
	        lastWeek : function () {
	            var startOfWeek, prefix;
	            startOfWeek = moment().startOf('week');
	            prefix = this.unix() < startOfWeek.unix()  ? '[上]' : '[本]';
	            return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
	        },
	        sameElse : 'LL'
	    },
	    ordinalParse: /\d{1,2}(日|月|周)/,
	    ordinal : function (number, period) {
	        switch (period) {
	            case 'd':
	            case 'D':
	            case 'DDD':
	                return number + '日';
	            case 'M':
	                return number + '月';
	            case 'w':
	            case 'W':
	                return number + '周';
	            default:
	                return number;
	        }
	    },
	    relativeTime : {
	        future : '%s内',
	        past : '%s前',
	        s : '几秒',
	        m : '1 分钟',
	        mm : '%d 分钟',
	        h : '1 小时',
	        hh : '%d 小时',
	        d : '1 天',
	        dd : '%d 天',
	        M : '1 个月',
	        MM : '%d 个月',
	        y : '1 年',
	        yy : '%d 年'
	    },
	    week : {
	        // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
	        dow : 1, // Monday is the first day of the week.
	        doy : 4  // The week that contains Jan 4th is the first week of the year.
	    }
	});
	
	return zhCn;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/zh-cn.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/zh-hk.js **/
jupyter.define('moment@2.17.1/locale/zh-hk.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Chinese (Hong Kong) [zh-hk]
	//! author : Ben : https://github.com/ben-lin
	//! author : Chris Lam : https://github.com/hehachris
	//! author : Konstantin : https://github.com/skfd
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var zhHk = moment.defineLocale('zh-hk', {
	    months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
	    monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
	    weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
	    weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
	    weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
	    longDateFormat : {
	        LT : 'Ah點mm分',
	        LTS : 'Ah點m分s秒',
	        L : 'YYYY年MMMD日',
	        LL : 'YYYY年MMMD日',
	        LLL : 'YYYY年MMMD日Ah點mm分',
	        LLLL : 'YYYY年MMMD日ddddAh點mm分',
	        l : 'YYYY年MMMD日',
	        ll : 'YYYY年MMMD日',
	        lll : 'YYYY年MMMD日Ah點mm分',
	        llll : 'YYYY年MMMD日ddddAh點mm分'
	    },
	    meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
	            return hour;
	        } else if (meridiem === '中午') {
	            return hour >= 11 ? hour : hour + 12;
	        } else if (meridiem === '下午' || meridiem === '晚上') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        var hm = hour * 100 + minute;
	        if (hm < 600) {
	            return '凌晨';
	        } else if (hm < 900) {
	            return '早上';
	        } else if (hm < 1130) {
	            return '上午';
	        } else if (hm < 1230) {
	            return '中午';
	        } else if (hm < 1800) {
	            return '下午';
	        } else {
	            return '晚上';
	        }
	    },
	    calendar : {
	        sameDay : '[今天]LT',
	        nextDay : '[明天]LT',
	        nextWeek : '[下]ddddLT',
	        lastDay : '[昨天]LT',
	        lastWeek : '[上]ddddLT',
	        sameElse : 'L'
	    },
	    ordinalParse: /\d{1,2}(日|月|週)/,
	    ordinal : function (number, period) {
	        switch (period) {
	            case 'd' :
	            case 'D' :
	            case 'DDD' :
	                return number + '日';
	            case 'M' :
	                return number + '月';
	            case 'w' :
	            case 'W' :
	                return number + '週';
	            default :
	                return number;
	        }
	    },
	    relativeTime : {
	        future : '%s內',
	        past : '%s前',
	        s : '幾秒',
	        m : '1 分鐘',
	        mm : '%d 分鐘',
	        h : '1 小時',
	        hh : '%d 小時',
	        d : '1 天',
	        dd : '%d 天',
	        M : '1 個月',
	        MM : '%d 個月',
	        y : '1 年',
	        yy : '%d 年'
	    }
	});
	
	return zhHk;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/zh-hk.js **/


/** START DEFINE BLOCK for moment@2.17.1/locale/zh-tw.js **/
jupyter.define('moment@2.17.1/locale/zh-tw.js', function (module, exports, __jupyter_require__) {
	//! moment.js locale configuration
	//! locale : Chinese (Taiwan) [zh-tw]
	//! author : Ben : https://github.com/ben-lin
	//! author : Chris Lam : https://github.com/hehachris
	
	;(function (global, factory) {
	    true ? factory(__jupyter_require__('moment@2.17.1/moment.js')) :
	   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
	   factory(global.moment)
	}(this, (function (moment) { 'use strict';
	
	
	var zhTw = moment.defineLocale('zh-tw', {
	    months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
	    monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
	    weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
	    weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
	    weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
	    longDateFormat : {
	        LT : 'Ah點mm分',
	        LTS : 'Ah點m分s秒',
	        L : 'YYYY年MMMD日',
	        LL : 'YYYY年MMMD日',
	        LLL : 'YYYY年MMMD日Ah點mm分',
	        LLLL : 'YYYY年MMMD日ddddAh點mm分',
	        l : 'YYYY年MMMD日',
	        ll : 'YYYY年MMMD日',
	        lll : 'YYYY年MMMD日Ah點mm分',
	        llll : 'YYYY年MMMD日ddddAh點mm分'
	    },
	    meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
	    meridiemHour : function (hour, meridiem) {
	        if (hour === 12) {
	            hour = 0;
	        }
	        if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
	            return hour;
	        } else if (meridiem === '中午') {
	            return hour >= 11 ? hour : hour + 12;
	        } else if (meridiem === '下午' || meridiem === '晚上') {
	            return hour + 12;
	        }
	    },
	    meridiem : function (hour, minute, isLower) {
	        var hm = hour * 100 + minute;
	        if (hm < 600) {
	            return '凌晨';
	        } else if (hm < 900) {
	            return '早上';
	        } else if (hm < 1130) {
	            return '上午';
	        } else if (hm < 1230) {
	            return '中午';
	        } else if (hm < 1800) {
	            return '下午';
	        } else {
	            return '晚上';
	        }
	    },
	    calendar : {
	        sameDay : '[今天]LT',
	        nextDay : '[明天]LT',
	        nextWeek : '[下]ddddLT',
	        lastDay : '[昨天]LT',
	        lastWeek : '[上]ddddLT',
	        sameElse : 'L'
	    },
	    ordinalParse: /\d{1,2}(日|月|週)/,
	    ordinal : function (number, period) {
	        switch (period) {
	            case 'd' :
	            case 'D' :
	            case 'DDD' :
	                return number + '日';
	            case 'M' :
	                return number + '月';
	            case 'w' :
	            case 'W' :
	                return number + '週';
	            default :
	                return number;
	        }
	    },
	    relativeTime : {
	        future : '%s內',
	        past : '%s前',
	        s : '幾秒',
	        m : '1 分鐘',
	        mm : '%d 分鐘',
	        h : '1 小時',
	        hh : '%d 小時',
	        d : '1 天',
	        dd : '%d 天',
	        M : '1 個月',
	        MM : '%d 個月',
	        y : '1 年',
	        yy : '%d 年'
	    }
	});
	
	return zhTw;
	
	})));
	
})
/** END DEFINE BLOCK for moment@2.17.1/locale/zh-tw.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/browser.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/buttons.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/crumbs.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/listing.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/model.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/tracker.js'));
	/**
	 * The command IDs used by the file browser plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.save = 'file-operations:save';
	    CommandIDs.restoreCheckpoint = 'file-operations:restore-checkpoint';
	    CommandIDs.saveAs = 'file-operations:save-as';
	    CommandIDs.close = 'file-operations:close';
	    CommandIDs.closeAllFiles = 'file-operations:close-all-files';
	    CommandIDs.open = 'file-operations:open';
	    CommandIDs.newTextFile = 'file-operations:new-text-file';
	    CommandIDs.newNotebook = 'file-operations:new-notebook';
	    CommandIDs.showBrowser = 'file-browser:activate';
	    CommandIDs.hideBrowser = 'file-browser:hide';
	    CommandIDs.toggleBrowser = 'file-browser:toggle';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/browser.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/browser.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var buttons_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/buttons.js');
	var crumbs_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/crumbs.js');
	var listing_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/listing.js');
	var utils_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/utils.js');
	/**
	 * The class name added to the filebrowser crumbs node.
	 */
	var CRUMBS_CLASS = 'jp-FileBrowser-crumbs';
	/**
	 * The class name added to the filebrowser buttons node.
	 */
	var BUTTON_CLASS = 'jp-FileBrowser-buttons';
	/**
	 * The class name added to the filebrowser listing node.
	 */
	var LISTING_CLASS = 'jp-FileBrowser-listing';
	/**
	 * A widget which hosts a file browser.
	 *
	 * The widget uses the Jupyter Contents API to retreive contents,
	 * and presents itself as a flat list of files and directories with
	 * breadcrumbs.
	 */
	var FileBrowser = (function (_super) {
	    __extends(FileBrowser, _super);
	    /**
	     * Construct a new file browser.
	     *
	     * @param model - The file browser view model.
	     */
	    function FileBrowser(options) {
	        _super.call(this);
	        this._buttons = null;
	        this._commands = null;
	        this._crumbs = null;
	        this._keymap = null;
	        this._listing = null;
	        this._manager = null;
	        this._model = null;
	        this._showingError = false;
	        this.addClass(utils_1.FILE_BROWSER_CLASS);
	        var commands = this._commands = options.commands;
	        var keymap = this._keymap = options.keymap;
	        var manager = this._manager = options.manager;
	        var model = this._model = options.model;
	        var renderer = options.renderer;
	        model.connectionFailure.connect(this._onConnectionFailure, this);
	        this._crumbs = new crumbs_1.BreadCrumbs({ model: model });
	        this._buttons = new buttons_1.FileButtons({
	            commands: commands, keymap: keymap, manager: manager, model: model
	        });
	        this._listing = new listing_1.DirListing({ manager: manager, model: model, renderer: renderer });
	        this._crumbs.addClass(CRUMBS_CLASS);
	        this._buttons.addClass(BUTTON_CLASS);
	        this._listing.addClass(LISTING_CLASS);
	        var layout = new panel_1.PanelLayout();
	        layout.addWidget(this._buttons);
	        layout.addWidget(this._crumbs);
	        layout.addWidget(this._listing);
	        this.layout = layout;
	    }
	    Object.defineProperty(FileBrowser.prototype, "commands", {
	        /**
	         * Get the command registry used by the file browser.
	         */
	        get: function () {
	            return this._commands;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FileBrowser.prototype, "keymap", {
	        /**
	         * Get the keymap manager used by the file browser.
	         */
	        get: function () {
	            return this._keymap;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FileBrowser.prototype, "model", {
	        /**
	         * Get the model used by the file browser.
	         */
	        get: function () {
	            return this._model;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the file browser.
	     */
	    FileBrowser.prototype.dispose = function () {
	        this._model = null;
	        this._crumbs = null;
	        this._buttons = null;
	        this._listing = null;
	        this._manager = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Open the currently selected item(s).
	     *
	     * Changes to the first directory encountered.
	     */
	    FileBrowser.prototype.open = function () {
	        var _this = this;
	        var foundDir = false;
	        iteration_1.each(this._model.items(), function (item) {
	            if (!_this._listing.isSelected(item.name)) {
	                return;
	            }
	            if (item.type === 'directory') {
	                if (!foundDir) {
	                    foundDir = true;
	                    _this._model.cd(item.name);
	                }
	            }
	            else {
	                _this.openPath(item.path);
	            }
	        });
	    };
	    /**
	     * Open a file by path.
	     *
	     * @param path - The path to of the file to open.
	     *
	     * @param widgetName - The name of the widget factory to use.
	     *
	     * @returns The widget for the file.
	     */
	    FileBrowser.prototype.openPath = function (path, widgetName) {
	        if (widgetName === void 0) { widgetName = 'default'; }
	        return this._buttons.open(path, widgetName);
	    };
	    /**
	     * Create a file from a creator.
	     *
	     * @param creatorName - The name of the widget creator.
	     *
	     * @returns A promise that resolves with the created widget.
	     */
	    FileBrowser.prototype.createFrom = function (creatorName) {
	        return this._buttons.createFrom(creatorName);
	    };
	    /**
	     * Create a new untitled file in the current directory.
	     *
	     * @param options - The options used to create the file.
	     *
	     * @returns A promise that resolves with the created widget.
	     */
	    FileBrowser.prototype.createNew = function (options) {
	        var _this = this;
	        var model = this.model;
	        return model.newUntitled(options).then(function (contents) {
	            if (!_this.isDisposed) {
	                return _this._buttons.createNew(contents.path);
	            }
	        });
	    };
	    /**
	     * Rename the first currently selected item.
	     *
	     * @returns A promise that resolves with the new name of the item.
	     */
	    FileBrowser.prototype.rename = function () {
	        return this._listing.rename();
	    };
	    /**
	     * Cut the selected items.
	     */
	    FileBrowser.prototype.cut = function () {
	        this._listing.cut();
	    };
	    /**
	     * Copy the selected items.
	     */
	    FileBrowser.prototype.copy = function () {
	        this._listing.copy();
	    };
	    /**
	     * Paste the items from the clipboard.
	     *
	     * @returns A promise that resolves when the operation is complete.
	     */
	    FileBrowser.prototype.paste = function () {
	        return this._listing.paste();
	    };
	    /**
	     * Delete the currently selected item(s).
	     *
	     * @returns A promise that resolves when the operation is complete.
	     */
	    FileBrowser.prototype.delete = function () {
	        return this._listing.delete();
	    };
	    /**
	     * Duplicate the currently selected item(s).
	     *
	     * @returns A promise that resolves when the operation is complete.
	     */
	    FileBrowser.prototype.duplicate = function () {
	        return this._listing.duplicate();
	    };
	    /**
	     * Download the currently selected item(s).
	     */
	    FileBrowser.prototype.download = function () {
	        this._listing.download();
	    };
	    /**
	     * Shut down kernels on the applicable currently selected items.
	     *
	     * @returns A promise that resolves when the operation is complete.
	     */
	    FileBrowser.prototype.shutdownKernels = function () {
	        return this._listing.shutdownKernels();
	    };
	    /**
	     * Select next item.
	     */
	    FileBrowser.prototype.selectNext = function () {
	        this._listing.selectNext();
	    };
	    /**
	     * Select previous item.
	     */
	    FileBrowser.prototype.selectPrevious = function () {
	        this._listing.selectPrevious();
	    };
	    /**
	     * Find a path given a click.
	     *
	     * @param event - The mouse event.
	     *
	     * @returns The path to the selected file.
	     */
	    FileBrowser.prototype.pathForClick = function (event) {
	        return this._listing.pathForClick(event);
	    };
	    /**
	     * Handle a connection lost signal from the model.
	     */
	    FileBrowser.prototype._onConnectionFailure = function (sender, args) {
	        var _this = this;
	        if (this._showingError) {
	            return;
	        }
	        this._showingError = true;
	        utils_1.showErrorMessage('Server Connection Error', args).then(function () {
	            _this._showingError = false;
	        });
	    };
	    return FileBrowser;
	}(widget_1.Widget));
	exports.FileBrowser = FileBrowser;
	//# sourceMappingURL=browser.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/browser.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/buttons.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/buttons.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var menu_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/menu.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	var dialogs_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/dialogs.js');
	var utils = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/utils.js');
	/**
	 * The class name added to a file buttons widget.
	 */
	var FILE_BUTTONS_CLASS = 'jp-FileButtons';
	/**
	 * The class name added to a button node.
	 */
	var BUTTON_CLASS = 'jp-FileButtons-button';
	/**
	 * The class name added to a button content node.
	 */
	var CONTENT_CLASS = 'jp-FileButtons-buttonContent';
	/**
	 * The class name added to a button icon node.
	 */
	var ICON_CLASS = 'jp-FileButtons-buttonIcon';
	/**
	 * The class name added to the create button.
	 */
	var CREATE_CLASS = 'jp-id-create';
	/**
	 * The class name added to the add button.
	 */
	var MATERIAL_CREATE = 'jp-AddIcon';
	/**
	 * The class name added to the upload button.
	 */
	var MATERIAL_UPLOAD = 'jp-UploadIcon';
	/**
	 * The class name added to the refresh button.
	 */
	var MATERIAL_REFRESH = 'jp-RefreshIcon';
	/**
	 * The class name added to the down caret.
	 */
	var MATERIAL_DOWNCARET = 'jp-DownCaretIcon';
	/**
	 * The class name added to a material icon button.
	 */
	var MATERIAL_CLASS = 'jp-MaterialIcon';
	/**
	 * The class name added to the upload button.
	 */
	var UPLOAD_CLASS = 'jp-id-upload';
	/**
	 * The class name added to the refresh button.
	 */
	var REFRESH_CLASS = 'jp-id-refresh';
	/**
	 * The class name added to an active create button.
	 */
	var ACTIVE_CLASS = 'jp-mod-active';
	/**
	 * The class name added to a dropdown icon.
	 */
	var DROPDOWN_CLASS = 'jp-FileButtons-dropdownIcon';
	/**
	 * A widget which hosts the file browser buttons.
	 */
	var FileButtons = (function (_super) {
	    __extends(FileButtons, _super);
	    /**
	     * Construct a new file browser buttons widget.
	     */
	    function FileButtons(options) {
	        _super.call(this);
	        this._buttons = Private.createButtons();
	        this._commands = null;
	        this._input = Private.createUploadInput();
	        this._keymap = null;
	        this._manager = null;
	        this.addClass(FILE_BUTTONS_CLASS);
	        this._model = options.model;
	        this._buttons.create.onmousedown = this._onCreateButtonPressed.bind(this);
	        this._buttons.upload.onclick = this._onUploadButtonClicked.bind(this);
	        this._buttons.refresh.onclick = this._onRefreshButtonClicked.bind(this);
	        this._input.onchange = this._onInputChanged.bind(this);
	        var node = this.node;
	        node.appendChild(this._buttons.create);
	        node.appendChild(this._buttons.upload);
	        node.appendChild(this._buttons.refresh);
	        this._commands = options.commands;
	        this._keymap = options.keymap;
	        this._manager = options.manager;
	    }
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    FileButtons.prototype.dispose = function () {
	        this._buttons = null;
	        this._commands = null;
	        this._input = null;
	        this._keymap = null;
	        this._manager = null;
	        this._model = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(FileButtons.prototype, "model", {
	        /**
	         * Get the model used by the widget.
	         */
	        get: function () {
	            return this._model;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FileButtons.prototype, "manager", {
	        /**
	         * Get the document manager used by the widget.
	         */
	        get: function () {
	            return this._manager;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FileButtons.prototype, "createNode", {
	        /**
	         * Get the create button node.
	         */
	        get: function () {
	            return this._buttons.create;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FileButtons.prototype, "uploadNode", {
	        /**
	         * Get the upload button node.
	         */
	        get: function () {
	            return this._buttons.upload;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FileButtons.prototype, "refreshNode", {
	        /**
	         * Get the refresh button node.
	         */
	        get: function () {
	            return this._buttons.refresh;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create a file from a creator.
	     *
	     * @param creatorName - The name of the file creator.
	     *
	     * @returns A promise that resolves with the created widget.
	     */
	    FileButtons.prototype.createFrom = function (creatorName) {
	        return dialogs_1.createFromDialog(this.model, this.manager, creatorName);
	    };
	    /**
	     * Open a file by path.
	     *
	     * @param path - The path of the file.
	     *
	     * @param widgetName - The name of the widget factory to use.
	     *
	     * @param kernel - The kernel model to use.
	     *
	     * @return The widget for the path.
	     */
	    FileButtons.prototype.open = function (path, widgetName, kernel) {
	        if (widgetName === void 0) { widgetName = 'default'; }
	        var widget = this._manager.openOrReveal(path, widgetName, kernel);
	        return widget;
	    };
	    /**
	     * Create a new file by path.
	     *
	     * @param path - The path of the file.
	     *
	     * @param widgetName - The name of the widget factory to use.
	     *
	     * @param kernel - The kernel model to use.
	     *
	     * @return The widget for the path.
	     */
	    FileButtons.prototype.createNew = function (path, widgetName, kernel) {
	        if (widgetName === void 0) { widgetName = 'default'; }
	        return this._manager.createNew(path, widgetName, kernel);
	    };
	    /**
	     * The 'mousedown' handler for the create button.
	     */
	    FileButtons.prototype._onCreateButtonPressed = function (event) {
	        // Do nothing if nothing if it's not a left press.
	        if (event.button !== 0) {
	            return;
	        }
	        // Do nothing if the create button is already active.
	        var button = this._buttons.create;
	        if (button.classList.contains(ACTIVE_CLASS)) {
	            return;
	        }
	        // Create a new dropdown menu and snap the button geometry.
	        var commands = this._commands;
	        var keymap = this._keymap;
	        var dropdown = Private.createDropdownMenu(this, commands, keymap);
	        var rect = button.getBoundingClientRect();
	        // Mark the button as active.
	        button.classList.add(ACTIVE_CLASS);
	        // Setup the `aboutToClose` signal handler. The menu is disposed on an
	        // animation frame to allow a mouse press event which closed the
	        // menu to run its course. This keeps the button from re-opening.
	        dropdown.aboutToClose.connect(this._onDropDownAboutToClose, this);
	        // Setup the `disposed` signal handler. This restores the button
	        // to the non-active state and allows a new menu to be opened.
	        dropdown.disposed.connect(this._onDropDownDisposed, this);
	        // Popup the menu aligned with the bottom of the create button.
	        dropdown.open(rect.left, rect.bottom, { forceX: false, forceY: false });
	    };
	    ;
	    /**
	     * Handle a dropdwon about to close.
	     */
	    FileButtons.prototype._onDropDownAboutToClose = function (sender) {
	        requestAnimationFrame(function () { sender.dispose(); });
	    };
	    /**
	     * Handle a dropdown disposal.
	     */
	    FileButtons.prototype._onDropDownDisposed = function (sender) {
	        this._buttons.create.classList.remove(ACTIVE_CLASS);
	    };
	    /**
	     * The 'click' handler for the upload button.
	     */
	    FileButtons.prototype._onUploadButtonClicked = function (event) {
	        if (event.button !== 0) {
	            return;
	        }
	        this._input.click();
	    };
	    /**
	     * The 'click' handler for the refresh button.
	     */
	    FileButtons.prototype._onRefreshButtonClicked = function (event) {
	        if (event.button !== 0) {
	            return;
	        }
	        // Force a refresh of the current directory.
	        this._model.refresh();
	    };
	    /**
	     * The 'change' handler for the input field.
	     */
	    FileButtons.prototype._onInputChanged = function () {
	        var files = Array.prototype.slice.call(this._input.files);
	        Private.uploadFiles(this, files);
	    };
	    return FileButtons;
	}(widget_1.Widget));
	exports.FileButtons = FileButtons;
	/**
	 * The namespace for the `FileButtons` private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * The ID counter prefix for new commands.
	     *
	     * #### Notes
	     * Even though the commands are disposed when the dropdown menu is disposed,
	     * in order to guarantee there are no race conditions with other `FileButtons`
	     * instances, each set of commands is prefixed.
	     */
	    var id = 0;
	    /**
	     * Create the button group for a file buttons widget.
	     */
	    function createButtons() {
	        var create = document.createElement('button');
	        var upload = document.createElement('button');
	        var refresh = document.createElement('button');
	        var createContent = document.createElement('span');
	        var uploadContent = document.createElement('span');
	        var refreshContent = document.createElement('span');
	        var createIcon = document.createElement('span');
	        var uploadIcon = document.createElement('span');
	        var refreshIcon = document.createElement('span');
	        var dropdownIcon = document.createElement('span');
	        create.type = 'button';
	        upload.type = 'button';
	        refresh.type = 'button';
	        create.title = 'Create New...';
	        upload.title = 'Upload File(s)';
	        refresh.title = 'Refresh File List';
	        create.className = BUTTON_CLASS + " " + CREATE_CLASS;
	        upload.className = BUTTON_CLASS + " " + UPLOAD_CLASS;
	        refresh.className = BUTTON_CLASS + " " + REFRESH_CLASS;
	        createContent.className = CONTENT_CLASS;
	        uploadContent.className = CONTENT_CLASS;
	        refreshContent.className = CONTENT_CLASS;
	        // TODO make these icons configurable.
	        createIcon.className = ICON_CLASS + ' ' + MATERIAL_CLASS + ' ' + MATERIAL_CREATE;
	        uploadIcon.className = ICON_CLASS + ' ' + MATERIAL_CLASS + ' ' + MATERIAL_UPLOAD;
	        refreshIcon.className = ICON_CLASS + ' ' + MATERIAL_CLASS + ' ' + MATERIAL_REFRESH;
	        dropdownIcon.className = DROPDOWN_CLASS + ' ' + MATERIAL_CLASS + ' ' + MATERIAL_DOWNCARET;
	        createContent.appendChild(createIcon);
	        createContent.appendChild(dropdownIcon);
	        uploadContent.appendChild(uploadIcon);
	        refreshContent.appendChild(refreshIcon);
	        create.appendChild(createContent);
	        upload.appendChild(uploadContent);
	        refresh.appendChild(refreshContent);
	        return { create: create, upload: upload, refresh: refresh };
	    }
	    Private.createButtons = createButtons;
	    /**
	     * Create the upload input node for a file buttons widget.
	     */
	    function createUploadInput() {
	        var input = document.createElement('input');
	        input.type = 'file';
	        input.multiple = true;
	        return input;
	    }
	    Private.createUploadInput = createUploadInput;
	    /**
	     * Create a new folder.
	     */
	    function createNewFolder(widget) {
	        widget.model.newUntitled({ type: 'directory' }).catch(function (error) {
	            utils.showErrorMessage('New Folder Error', error);
	        });
	    }
	    Private.createNewFolder = createNewFolder;
	    /**
	     * Create a new dropdown menu for the create new button.
	     */
	    function createDropdownMenu(widget, commands, keymap) {
	        var menu = new menu_1.Menu({ commands: commands, keymap: keymap });
	        var prefix = "file-buttons-" + ++id;
	        var disposables = new disposable_1.DisposableSet();
	        var registry = widget.manager.registry;
	        var command;
	        // Remove all the commands associated with this menu upon disposal.
	        menu.disposed.connect(function () { return disposables.dispose(); });
	        command = prefix + ":new-text-folder";
	        disposables.add(commands.addCommand(command, {
	            execute: function () { createNewFolder(widget); },
	            label: 'Folder'
	        }));
	        menu.addItem({ command: command });
	        iteration_1.each(registry.creators(), function (creator) {
	            command = prefix + ":new-" + creator.name;
	            disposables.add(commands.addCommand(command, {
	                execute: function () {
	                    widget.createFrom(creator.name);
	                },
	                label: creator.name
	            }));
	            menu.addItem({ command: command });
	        });
	        return menu;
	    }
	    Private.createDropdownMenu = createDropdownMenu;
	    /**
	     * Upload an array of files to the server.
	     */
	    function uploadFiles(widget, files) {
	        var pending = files.map(function (file) { return uploadFile(widget, file); });
	        Promise.all(pending).catch(function (error) {
	            utils.showErrorMessage('Upload Error', error);
	        });
	    }
	    Private.uploadFiles = uploadFiles;
	    /**
	     * Upload a file to the server.
	     */
	    function uploadFile(widget, file) {
	        return widget.model.upload(file).catch(function (error) {
	            var exists = error.message.indexOf('already exists') !== -1;
	            if (exists) {
	                return uploadFileOverride(widget, file);
	            }
	            throw error;
	        });
	    }
	    /**
	     * Upload a file to the server checking for override.
	     */
	    function uploadFileOverride(widget, file) {
	        var options = {
	            title: 'Overwrite File?',
	            body: "\"" + file.name + "\" already exists, overwrite?"
	        };
	        return dialog_1.showDialog(options).then(function (button) {
	            if (widget.isDisposed || button.text !== 'Ok') {
	                return;
	            }
	            return widget.model.upload(file, true);
	        });
	    }
	})(Private || (Private = {}));
	//# sourceMappingURL=buttons.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/buttons.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/dialogs.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/dialogs.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	/**
	 * The class name added to file dialogs.
	 */
	var FILE_DIALOG_CLASS = 'jp-FileDialog';
	/**
	 * The class name added for a file conflict.
	 */
	var FILE_CONFLICT_CLASS = 'jp-mod-conflict';
	/**
	 * Create a file using a file creator.
	 */
	function createFromDialog(model, manager, creatorName) {
	    var handler = new CreateFromHandler(model, manager, creatorName);
	    return manager.services.ready.then(function () {
	        return handler.populate();
	    }).then(function () {
	        return handler.showDialog();
	    });
	}
	exports.createFromDialog = createFromDialog;
	/**
	 * Open a file using a dialog.
	 */
	function openWithDialog(path, manager, host) {
	    var handler;
	    return manager.services.ready.then(function () {
	        handler = new OpenWithHandler(path, manager);
	        return dialog_1.showDialog({
	            title: 'Open File',
	            body: handler.node,
	            primary: handler.inputNode,
	            okText: 'OPEN'
	        });
	    }).then(function (result) {
	        if (result.text === 'OPEN') {
	            return handler.open();
	        }
	    });
	}
	exports.openWithDialog = openWithDialog;
	/**
	 * Create a new file using a dialog.
	 */
	function createNewDialog(model, manager, host) {
	    var handler;
	    return manager.services.ready.then(function () {
	        handler = new CreateNewHandler(model, manager);
	        return dialog_1.showDialog({
	            title: 'Create New File',
	            host: host,
	            body: handler.node,
	            primary: handler.inputNode,
	            okText: 'CREATE'
	        });
	    }).then(function (result) {
	        if (result.text === 'CREATE') {
	            return handler.open();
	        }
	    });
	}
	exports.createNewDialog = createNewDialog;
	/**
	 * Rename a file with optional dialog.
	 */
	function renameFile(model, oldPath, newPath) {
	    return model.rename(oldPath, newPath).catch(function (error) {
	        if (error.xhr) {
	            error.message = error.xhr.statusText + " " + error.xhr.status;
	        }
	        if (error.message.indexOf('409') !== -1) {
	            var options = {
	                title: 'Overwrite file?',
	                body: "\"" + newPath + "\" already exists, overwrite?",
	                okText: 'OVERWRITE'
	            };
	            return dialog_1.showDialog(options).then(function (button) {
	                if (button.text === 'OVERWRITE') {
	                    return model.deleteFile(newPath).then(function () {
	                        return model.rename(oldPath, newPath);
	                    });
	                }
	            });
	        }
	        else {
	            throw error;
	        }
	    });
	}
	exports.renameFile = renameFile;
	/**
	 * A widget used to open files with a specific widget/kernel.
	 */
	var OpenWithHandler = (function (_super) {
	    __extends(OpenWithHandler, _super);
	    /**
	     * Construct a new "open with" dialog.
	     */
	    function OpenWithHandler(path, manager) {
	        _super.call(this, { node: Private.createOpenWithNode() });
	        this._ext = '';
	        this._manager = null;
	        this._manager = manager;
	        this.inputNode.textContent = path;
	        this._ext = docregistry_1.DocumentRegistry.extname(path);
	        this.populateFactories();
	        this.widgetDropdown.onchange = this.widgetChanged.bind(this);
	    }
	    /**
	     * Dispose of the resources used by the widget.
	     */
	    OpenWithHandler.prototype.dispose = function () {
	        this._manager = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(OpenWithHandler.prototype, "inputNode", {
	        /**
	         * Get the input text node.
	         */
	        get: function () {
	            return this.node.firstChild;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(OpenWithHandler.prototype, "widgetDropdown", {
	        /**
	         * Get the widget dropdown node.
	         */
	        get: function () {
	            return this.node.children[1];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(OpenWithHandler.prototype, "kernelDropdownNode", {
	        /**
	         * Get the kernel dropdown node.
	         */
	        get: function () {
	            return this.node.children[2];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Open the file and return the document widget.
	     */
	    OpenWithHandler.prototype.open = function () {
	        var path = this.inputNode.textContent;
	        var widgetName = this.widgetDropdown.value;
	        var kernelValue = this.kernelDropdownNode.value;
	        var kernelId;
	        if (kernelValue !== 'null') {
	            kernelId = JSON.parse(kernelValue);
	        }
	        return this._manager.open(path, widgetName, kernelId);
	    };
	    /**
	     * Populate the widget factories.
	     */
	    OpenWithHandler.prototype.populateFactories = function () {
	        var factories = this._manager.registry.preferredWidgetFactories(this._ext);
	        var widgetDropdown = this.widgetDropdown;
	        iteration_1.each(factories, function (factory) {
	            var option = document.createElement('option');
	            option.text = factory.name;
	            widgetDropdown.appendChild(option);
	        });
	        this.widgetChanged();
	    };
	    /**
	     * Handle a change to the widget.
	     */
	    OpenWithHandler.prototype.widgetChanged = function () {
	        var widgetName = this.widgetDropdown.value;
	        var preference = this._manager.registry.getKernelPreference(this._ext, widgetName);
	        var specs = this._manager.services.specs;
	        var sessions = this._manager.services.sessions.running();
	        Private.updateKernels(this.kernelDropdownNode, { preference: preference, specs: specs, sessions: sessions });
	    };
	    return OpenWithHandler;
	}(widget_1.Widget));
	/**
	 * A widget used to create a file using a creator.
	 */
	var CreateFromHandler = (function (_super) {
	    __extends(CreateFromHandler, _super);
	    /**
	     * Construct a new "create from" dialog.
	     */
	    function CreateFromHandler(model, manager, creatorName) {
	        var _this = this;
	        _super.call(this, { node: Private.createCreateFromNode() });
	        this._model = null;
	        this._orig = null;
	        this.addClass(FILE_DIALOG_CLASS);
	        this._model = model;
	        this._manager = manager;
	        this._creatorName = creatorName;
	        // Check for name conflicts when the inputNode changes.
	        this.inputNode.addEventListener('input', function () {
	            var value = _this.inputNode.value;
	            if (value !== _this._orig) {
	                iteration_1.each(_this._model.items(), function (item) {
	                    if (item.name === value) {
	                        _this.addClass(FILE_CONFLICT_CLASS);
	                        return;
	                    }
	                });
	            }
	            _this.removeClass(FILE_CONFLICT_CLASS);
	        });
	    }
	    /**
	     * Dispose of the resources used by the widget.
	     */
	    CreateFromHandler.prototype.dispose = function () {
	        this._model = null;
	        this._manager = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(CreateFromHandler.prototype, "inputNode", {
	        /**
	         * Get the input text node.
	         */
	        get: function () {
	            return this.node.getElementsByTagName('input')[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CreateFromHandler.prototype, "kernelDropdownNode", {
	        /**
	         * Get the kernel dropdown node.
	         */
	        get: function () {
	            return this.node.getElementsByTagName('select')[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Show the createNew dialog.
	     */
	    CreateFromHandler.prototype.showDialog = function () {
	        var _this = this;
	        return dialog_1.showDialog({
	            title: "Create New " + this._creatorName,
	            body: this.node,
	            primary: this.inputNode,
	            okText: 'CREATE'
	        }).then(function (result) {
	            if (result.text === 'CREATE') {
	                return _this._open().then(function (widget) {
	                    if (!widget) {
	                        return _this.showDialog();
	                    }
	                    return widget;
	                });
	            }
	            _this._model.deleteFile('/' + _this._orig.path);
	            return null;
	        });
	    };
	    /**
	     * Populate the create from widget.
	     */
	    CreateFromHandler.prototype.populate = function () {
	        var _this = this;
	        var model = this._model;
	        var manager = this._manager;
	        var registry = manager.registry;
	        var creator = registry.getCreator(this._creatorName);
	        if (!creator) {
	            return Promise.reject("Creator not registered: " + this._creatorName);
	        }
	        var fileType = creator.fileType, widgetName = creator.widgetName, kernelName = creator.kernelName;
	        var fType = registry.getFileType(fileType);
	        var ext = '.txt';
	        var type = 'file';
	        if (fType) {
	            ext = fType.extension;
	            type = fType.contentType || 'file';
	        }
	        if (!widgetName || widgetName === 'default') {
	            this._widgetName = widgetName = registry.defaultWidgetFactory(ext).name;
	        }
	        // Handle the kernel preferences.
	        var preference = registry.getKernelPreference(ext, widgetName);
	        if (preference.canStartKernel) {
	            var specs = this._manager.services.specs;
	            var sessions = this._manager.services.sessions.running();
	            var preferredKernel = kernelName;
	            Private.updateKernels(this.kernelDropdownNode, { specs: specs, sessions: sessions, preferredKernel: preferredKernel, preference: preference });
	        }
	        else {
	            this.node.removeChild(this.kernelDropdownNode.previousSibling);
	            this.node.removeChild(this.kernelDropdownNode);
	        }
	        return model.newUntitled({ ext: ext, type: type }).then(function (contents) {
	            var value = _this.inputNode.value = contents.name;
	            _this.inputNode.setSelectionRange(0, value.length - ext.length);
	            _this._orig = contents;
	        });
	    };
	    /**
	     * Open the file and return the document widget.
	     */
	    CreateFromHandler.prototype._open = function () {
	        var _this = this;
	        var file = this.inputNode.value;
	        var widgetName = this._widgetName;
	        var kernelValue = this.kernelDropdownNode ? this.kernelDropdownNode.value
	            : 'null';
	        var kernelId;
	        if (kernelValue !== 'null') {
	            kernelId = JSON.parse(kernelValue);
	        }
	        if (file !== this._orig.name) {
	            var promise = renameFile(this._model, this._orig.name, file);
	            return promise.then(function (contents) {
	                if (!contents) {
	                    return null;
	                }
	                return _this._manager.open(contents.path, widgetName, kernelId);
	            });
	        }
	        var path = this._orig.path;
	        return Promise.resolve(this._manager.createNew(path, widgetName, kernelId));
	    };
	    return CreateFromHandler;
	}(widget_1.Widget));
	/**
	 * A widget used to create new files.
	 */
	var CreateNewHandler = (function (_super) {
	    __extends(CreateNewHandler, _super);
	    /**
	     * Construct a new "create new" dialog.
	     */
	    function CreateNewHandler(model, manager) {
	        var _this = this;
	        _super.call(this, { node: Private.createCreateNewNode() });
	        this._model = null;
	        this._manager = null;
	        this._sentinel = 'UNKNOWN_EXTENSION';
	        this._prevExt = '';
	        this._extensions = [];
	        this._model = model;
	        this._manager = manager;
	        // Create a file name based on the current time.
	        var time = new Date();
	        time.setMinutes(time.getMinutes() - time.getTimezoneOffset());
	        var name = time.toJSON().slice(0, 10);
	        name += '-' + time.getHours() + time.getMinutes() + time.getSeconds();
	        this.inputNode.value = name + '.txt';
	        this.inputNode.setSelectionRange(0, name.length);
	        // Check for name conflicts when the inputNode changes.
	        this.inputNode.addEventListener('input', function () {
	            _this.inputNodeChanged();
	        });
	        // Update the widget choices when the file type changes.
	        this.fileTypeDropdown.addEventListener('change', function () {
	            _this.fileTypeChanged();
	        });
	        // Update the kernel choices when the widget changes.
	        this.widgetDropdown.addEventListener('change', function () {
	            _this.widgetDropdownChanged();
	        });
	        // Populate the lists of file types and widget factories.
	        this.populateFileTypes();
	        this.populateFactories();
	    }
	    /**
	     * Dispose of the resources used by the widget.
	     */
	    CreateNewHandler.prototype.dispose = function () {
	        this._model = null;
	        this._manager = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(CreateNewHandler.prototype, "inputNode", {
	        /**
	         * Get the input text node.
	         */
	        get: function () {
	            return this.node.firstChild;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CreateNewHandler.prototype, "fileTypeDropdown", {
	        /**
	         * Get the file type dropdown node.
	         */
	        get: function () {
	            return this.node.children[1];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CreateNewHandler.prototype, "widgetDropdown", {
	        /**
	         * Get the widget dropdown node.
	         */
	        get: function () {
	            return this.node.children[2];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CreateNewHandler.prototype, "kernelDropdownNode", {
	        /**
	         * Get the kernel dropdown node.
	         */
	        get: function () {
	            return this.node.children[3];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CreateNewHandler.prototype, "ext", {
	        /**
	         * Get the current extension for the file.
	         */
	        get: function () {
	            return docregistry_1.DocumentRegistry.extname(this.inputNode.value);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Open the file and return the document widget.
	     */
	    CreateNewHandler.prototype.open = function () {
	        var path = this.inputNode.textContent;
	        var widgetName = this.widgetDropdown.value;
	        var kernelValue = this.kernelDropdownNode.value;
	        var kernelId;
	        if (kernelValue !== 'null') {
	            kernelId = JSON.parse(kernelValue);
	        }
	        return this._manager.createNew(path, widgetName, kernelId);
	    };
	    /**
	     * Handle a change to the inputNode.
	     */
	    CreateNewHandler.prototype.inputNodeChanged = function () {
	        var _this = this;
	        var path = this.inputNode.value;
	        iteration_1.each(this._model.items(), function (item) {
	            if (item.path === path) {
	                _this.addClass(FILE_CONFLICT_CLASS);
	                return;
	            }
	        });
	        var ext = this.ext;
	        if (ext === this._prevExt) {
	            return;
	        }
	        // Update the file type dropdown and the factories.
	        if (this._extensions.indexOf(ext) === -1) {
	            this.fileTypeDropdown.value = this._sentinel;
	        }
	        else {
	            this.fileTypeDropdown.value = ext;
	        }
	        this.populateFactories();
	    };
	    /**
	     * Populate the file types.
	     */
	    CreateNewHandler.prototype.populateFileTypes = function () {
	        var _this = this;
	        var dropdown = this.fileTypeDropdown;
	        var option = document.createElement('option');
	        option.text = 'File';
	        option.value = this._sentinel;
	        iteration_1.each(this._manager.registry.fileTypes(), function (ft) {
	            option = document.createElement('option');
	            option.text = ft.name + " (" + ft.extension + ")";
	            option.value = ft.extension;
	            dropdown.appendChild(option);
	            _this._extensions.push(ft.extension);
	        });
	        if (this.ext in this._extensions) {
	            dropdown.value = this.ext;
	        }
	        else {
	            dropdown.value = this._sentinel;
	        }
	    };
	    /**
	     * Populate the widget factories.
	     */
	    CreateNewHandler.prototype.populateFactories = function () {
	        var ext = this.ext;
	        var factories = this._manager.registry.preferredWidgetFactories(ext);
	        var widgetDropdown = this.widgetDropdown;
	        iteration_1.each(factories, function (factory) {
	            var option = document.createElement('option');
	            option.text = factory.name;
	            widgetDropdown.appendChild(option);
	        });
	        this.widgetDropdownChanged();
	        this._prevExt = ext;
	    };
	    /**
	     * Handle changes to the file type dropdown.
	     */
	    CreateNewHandler.prototype.fileTypeChanged = function () {
	        // Update the current inputNode.
	        var oldExt = this.ext;
	        var newExt = this.fileTypeDropdown.value;
	        if (oldExt === newExt || newExt === '') {
	            return;
	        }
	        var oldName = this.inputNode.value;
	        var base = oldName.slice(0, oldName.length - oldExt.length - 1);
	        this.inputNode.value = base + newExt;
	    };
	    /**
	     * Handle a change to the widget dropdown.
	     */
	    CreateNewHandler.prototype.widgetDropdownChanged = function () {
	        var ext = this.ext;
	        var widgetName = this.widgetDropdown.value;
	        var manager = this._manager;
	        var preference = manager.registry.getKernelPreference(ext, widgetName);
	        var specs = manager.services.specs;
	        var sessions = manager.services.sessions.running();
	        Private.updateKernels(this.kernelDropdownNode, { preference: preference, sessions: sessions, specs: specs });
	    };
	    return CreateNewHandler;
	}(widget_1.Widget));
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create the node for an open with handler.
	     */
	    function createOpenWithNode() {
	        var body = document.createElement('div');
	        var nameTitle = document.createElement('label');
	        nameTitle.textContent = 'File Name';
	        var name = document.createElement('div');
	        var widgetTitle = document.createElement('label');
	        widgetTitle.textContent = 'Widget Type';
	        var widgetDropdown = document.createElement('select');
	        var kernelTitle = document.createElement('label');
	        kernelTitle.textContent = 'Kernel';
	        var kernelDropdownNode = document.createElement('select');
	        body.appendChild(nameTitle);
	        body.appendChild(name);
	        body.appendChild(widgetTitle);
	        body.appendChild(widgetDropdown);
	        body.appendChild(kernelTitle);
	        body.appendChild(kernelDropdownNode);
	        return body;
	    }
	    Private.createOpenWithNode = createOpenWithNode;
	    /**
	     * Create the node for a create new handler.
	     */
	    function createCreateNewNode() {
	        var body = document.createElement('div');
	        var nameTitle = document.createElement('label');
	        nameTitle.textContent = 'File Name';
	        var name = document.createElement('input');
	        var typeTitle = document.createElement('label');
	        typeTitle.textContent = 'File Type';
	        var fileTypeDropdown = document.createElement('select');
	        var widgetTitle = document.createElement('label');
	        widgetTitle.textContent = 'Widget Type';
	        var widgetDropdown = document.createElement('select');
	        var kernelTitle = document.createElement('label');
	        kernelTitle.textContent = 'Kernel';
	        var kernelDropdownNode = document.createElement('select');
	        body.appendChild(nameTitle);
	        body.appendChild(name);
	        body.appendChild(typeTitle);
	        body.appendChild(fileTypeDropdown);
	        body.appendChild(widgetTitle);
	        body.appendChild(widgetDropdown);
	        body.appendChild(kernelTitle);
	        body.appendChild(kernelDropdownNode);
	        return body;
	    }
	    Private.createCreateNewNode = createCreateNewNode;
	    /**
	     * Create the node for a create from handler.
	     */
	    function createCreateFromNode() {
	        var body = document.createElement('div');
	        var nameTitle = document.createElement('label');
	        nameTitle.textContent = 'File Name';
	        var name = document.createElement('input');
	        var kernelTitle = document.createElement('label');
	        kernelTitle.textContent = 'Kernel';
	        var kernelDropdownNode = document.createElement('select');
	        body.appendChild(nameTitle);
	        body.appendChild(name);
	        body.appendChild(kernelTitle);
	        body.appendChild(kernelDropdownNode);
	        return body;
	    }
	    Private.createCreateFromNode = createCreateFromNode;
	    /**
	     * Update a kernel listing based on a kernel preference.
	     */
	    function updateKernels(node, options) {
	        var preference = options.preference, specs = options.specs, sessions = options.sessions, preferredKernel = options.preferredKernel;
	        if (!preference.canStartKernel) {
	            while (node.firstChild) {
	                node.removeChild(node.firstChild);
	            }
	            node.disabled = true;
	            return;
	        }
	        // Bail if there are no kernel specs.
	        if (!specs) {
	            return;
	        }
	        var preferredLanguage = preference.language;
	        node.disabled = false;
	        docregistry_1.populateKernels(node, { specs: specs, sessions: sessions, preferredLanguage: preferredLanguage, preferredKernel: preferredKernel });
	        // Select the "null" valued kernel if we do not prefer a kernel.
	        if (!preference.preferKernel) {
	            node.value = 'null';
	        }
	    }
	    Private.updateKernels = updateKernels;
	})(Private || (Private = {}));
	//# sourceMappingURL=dialogs.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/dialogs.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/utils.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/utils.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/common/dom.js'));
	/**
	 * The class name added to FileBrowser instances.
	 */
	exports.FILE_BROWSER_CLASS = 'jp-FileBrowser';
	/**
	 * The class name added to drop targets.
	 */
	exports.DROP_TARGET_CLASS = 'jp-mod-dropTarget';
	/**
	 * The class name added to selected rows.
	 */
	exports.SELECTED_CLASS = 'jp-mod-selected';
	/**
	 * The mime type for a contents drag object.
	 */
	exports.CONTENTS_MIME = 'application/x-jupyter-icontents';
	/**
	 * An error message dialog to show in the filebrowser widget.
	 */
	function showErrorMessage(title, error) {
	    console.error(error);
	    var options = {
	        title: title,
	        body: error.message || "File " + title,
	        buttons: [dialog_1.okButton],
	        okText: 'DISMISS'
	    };
	    return dialog_1.showDialog(options).then(function () { });
	}
	exports.showErrorMessage = showErrorMessage;
	//# sourceMappingURL=utils.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/utils.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/dom.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/dom.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var query_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/query.js');
	/**
	 * Get the index of the node at a client position, or `-1`.
	 */
	function hitTestNodes(nodes, x, y) {
	    for (var i = 0, n = nodes.length; i < n; ++i) {
	        if (query_1.hitTest(nodes[i], x, y)) {
	            return i;
	        }
	    }
	    return -1;
	}
	exports.hitTestNodes = hitTestNodes;
	/**
	 * Find the first element matching a class name.
	 */
	function findElement(parent, className) {
	    var elements = parent.getElementsByClassName(className);
	    if (elements.length) {
	        return elements[0];
	    }
	}
	exports.findElement = findElement;
	//# sourceMappingURL=dom.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/dom.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/crumbs.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/crumbs.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var query_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/query.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	var utils = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/utils.js');
	/**
	 * The class name added to material icons
	 */
	var MATERIAL_CLASS = 'jp-MaterialIcon';
	/**
	 * The class name added to the breadcrumb node.
	 */
	var BREADCRUMB_CLASS = 'jp-BreadCrumbs';
	/**
	 * The class name added to add the home icon for the breadcrumbs
	 */
	var BREADCRUMB_HOME = 'jp-HomeIcon';
	/**
	 * The class named associated to the ellipses icon
	 */
	var BREADCRUMB_ELLIPSES = 'jp-EllipsesIcon';
	/**
	 * The class name added to the breadcrumb node.
	 */
	var BREADCRUMB_ITEM_CLASS = 'jp-BreadCrumbs-item';
	/**
	 * Bread crumb paths.
	 */
	var BREAD_CRUMB_PATHS = ['/', '../../', '../', ''];
	/**
	 * A class which hosts folder breadcrumbs.
	 */
	var BreadCrumbs = (function (_super) {
	    __extends(BreadCrumbs, _super);
	    /**
	     * Construct a new file browser crumb widget.
	     *
	     * @param model - The file browser view model.
	     */
	    function BreadCrumbs(options) {
	        _super.call(this);
	        this._model = null;
	        this._crumbs = null;
	        this._crumbSeps = null;
	        this._model = options.model;
	        this.addClass(BREADCRUMB_CLASS);
	        this._crumbs = Private.createCrumbs();
	        this._crumbSeps = Private.createCrumbSeparators();
	        this.node.appendChild(this._crumbs.at(Private.Crumb.Home));
	        this._model.refreshed.connect(this.update, this);
	    }
	    /**
	     * Handle the DOM events for the bread crumbs.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the panel's DOM node. It should
	     * not be called directly by user code.
	     */
	    BreadCrumbs.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'click':
	                this._evtClick(event);
	                break;
	            case 'p-dragenter':
	                this._evtDragEnter(event);
	                break;
	            case 'p-dragleave':
	                this._evtDragLeave(event);
	                break;
	            case 'p-dragover':
	                this._evtDragOver(event);
	                break;
	            case 'p-drop':
	                this._evtDrop(event);
	                break;
	            default:
	                return;
	        }
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    BreadCrumbs.prototype.onAfterAttach = function (msg) {
	        _super.prototype.onAfterAttach.call(this, msg);
	        this.update();
	        var node = this.node;
	        node.addEventListener('click', this);
	        node.addEventListener('p-dragenter', this);
	        node.addEventListener('p-dragleave', this);
	        node.addEventListener('p-dragover', this);
	        node.addEventListener('p-drop', this);
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    BreadCrumbs.prototype.onBeforeDetach = function (msg) {
	        _super.prototype.onBeforeDetach.call(this, msg);
	        var node = this.node;
	        node.removeEventListener('click', this);
	        node.removeEventListener('p-dragenter', this);
	        node.removeEventListener('p-dragleave', this);
	        node.removeEventListener('p-dragover', this);
	        node.removeEventListener('p-drop', this);
	    };
	    /**
	     * A handler invoked on an `'update-request'` message.
	     */
	    BreadCrumbs.prototype.onUpdateRequest = function (msg) {
	        // Update the breadcrumb list.
	        Private.updateCrumbs(this._crumbs, this._crumbSeps, this._model.path);
	    };
	    /**
	     * Handle the `'click'` event for the widget.
	     */
	    BreadCrumbs.prototype._evtClick = function (event) {
	        // Do nothing if it's not a left mouse press.
	        if (event.button !== 0) {
	            return;
	        }
	        // Find a valid click target.
	        var node = event.target;
	        while (node && node !== this.node) {
	            if (node.classList.contains(BREADCRUMB_ITEM_CLASS)) {
	                var index = searching_1.findIndex(this._crumbs, function (value) { return value === node; });
	                this._model.cd(BREAD_CRUMB_PATHS[index]).catch(function (error) {
	                    return utils.showErrorMessage('Open Error', error);
	                });
	                // Stop the event propagation.
	                event.preventDefault();
	                event.stopPropagation();
	                return;
	            }
	            node = node.parentElement;
	        }
	    };
	    /**
	     * Handle the `'p-dragenter'` event for the widget.
	     */
	    BreadCrumbs.prototype._evtDragEnter = function (event) {
	        if (event.mimeData.hasData(utils.CONTENTS_MIME)) {
	            var index = searching_1.findIndex(this._crumbs, function (node) { return query_1.hitTest(node, event.clientX, event.clientY); });
	            if (index !== -1) {
	                if (index !== Private.Crumb.Current) {
	                    this._crumbs.at(index).classList.add(utils.DROP_TARGET_CLASS);
	                    event.preventDefault();
	                    event.stopPropagation();
	                }
	            }
	        }
	    };
	    /**
	     * Handle the `'p-dragleave'` event for the widget.
	     */
	    BreadCrumbs.prototype._evtDragLeave = function (event) {
	        event.preventDefault();
	        event.stopPropagation();
	        var dropTarget = utils.findElement(this.node, utils.DROP_TARGET_CLASS);
	        if (dropTarget) {
	            dropTarget.classList.remove(utils.DROP_TARGET_CLASS);
	        }
	    };
	    /**
	     * Handle the `'p-dragover'` event for the widget.
	     */
	    BreadCrumbs.prototype._evtDragOver = function (event) {
	        event.preventDefault();
	        event.stopPropagation();
	        event.dropAction = event.proposedAction;
	        var dropTarget = utils.findElement(this.node, utils.DROP_TARGET_CLASS);
	        if (dropTarget) {
	            dropTarget.classList.remove(utils.DROP_TARGET_CLASS);
	        }
	        var index = searching_1.findIndex(this._crumbs, function (node) { return query_1.hitTest(node, event.clientX, event.clientY); });
	        if (index !== -1) {
	            this._crumbs.at(index).classList.add(utils.DROP_TARGET_CLASS);
	        }
	    };
	    /**
	     * Handle the `'p-drop'` event for the widget.
	     */
	    BreadCrumbs.prototype._evtDrop = function (event) {
	        var _this = this;
	        event.preventDefault();
	        event.stopPropagation();
	        if (event.proposedAction === 'none') {
	            event.dropAction = 'none';
	            return;
	        }
	        if (!event.mimeData.hasData(utils.CONTENTS_MIME)) {
	            return;
	        }
	        event.dropAction = event.proposedAction;
	        var target = event.target;
	        while (target && target.parentElement) {
	            if (target.classList.contains(utils.DROP_TARGET_CLASS)) {
	                target.classList.remove(utils.DROP_TARGET_CLASS);
	                break;
	            }
	            target = target.parentElement;
	        }
	        // Get the path based on the target node.
	        var index = searching_1.findIndex(this._crumbs, function (node) { return node === target; });
	        if (index === -1) {
	            return;
	        }
	        var path = BREAD_CRUMB_PATHS[index];
	        var model = this._model;
	        // Move all of the items.
	        var promises = [];
	        var names = event.mimeData.getData(utils.CONTENTS_MIME);
	        var _loop_1 = function(name_1) {
	            var newPath = path + name_1;
	            promises.push(this_1._model.rename(name_1, newPath).catch(function (error) {
	                if (error.xhr) {
	                    error.message = error.xhr.status + ": error.statusText";
	                }
	                if (error.message.indexOf('409') !== -1) {
	                    var options = {
	                        title: 'Overwrite file?',
	                        body: "\"" + newPath + "\" already exists, overwrite?",
	                        okText: 'OVERWRITE'
	                    };
	                    return dialog_1.showDialog(options).then(function (button) {
	                        if (!model.isDisposed && button.text === 'OVERWRITE') {
	                            return model.deleteFile(newPath).then(function () {
	                                if (!model.isDisposed) {
	                                    return _this._model.rename(name_1, newPath);
	                                }
	                            });
	                        }
	                    });
	                }
	            }));
	        };
	        var this_1 = this;
	        for (var _i = 0, names_1 = names; _i < names_1.length; _i++) {
	            var name_1 = names_1[_i];
	            _loop_1(name_1);
	        }
	        Promise.all(promises).catch(function (err) {
	            utils.showErrorMessage('Move Error', err);
	        });
	    };
	    return BreadCrumbs;
	}(widget_1.Widget));
	exports.BreadCrumbs = BreadCrumbs;
	/**
	 * The namespace for the crumbs private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Breadcrumb item list enum.
	     */
	    (function (Crumb) {
	        Crumb[Crumb["Home"] = 0] = "Home";
	        Crumb[Crumb["Ellipsis"] = 1] = "Ellipsis";
	        Crumb[Crumb["Parent"] = 2] = "Parent";
	        Crumb[Crumb["Current"] = 3] = "Current";
	    })(Private.Crumb || (Private.Crumb = {}));
	    var Crumb = Private.Crumb;
	    /**
	     * Populate the breadcrumb node.
	     */
	    function updateCrumbs(breadcrumbs, separators, path) {
	        var node = breadcrumbs.at(0).parentNode;
	        // Remove all but the home node.
	        while (node.firstChild.nextSibling) {
	            node.removeChild(node.firstChild.nextSibling);
	        }
	        var parts = path.split('/');
	        if (parts.length > 2) {
	            node.appendChild(separators.at(0));
	            node.appendChild(breadcrumbs.at(Crumb.Ellipsis));
	            var grandParent = parts.slice(0, parts.length - 2).join('/');
	            breadcrumbs.at(Crumb.Ellipsis).title = grandParent;
	        }
	        if (path) {
	            if (parts.length >= 2) {
	                node.appendChild(separators.at(1));
	                breadcrumbs.at(Crumb.Parent).textContent = parts[parts.length - 2];
	                node.appendChild(breadcrumbs.at(Crumb.Parent));
	                var parent_1 = parts.slice(0, parts.length - 1).join('/');
	                breadcrumbs.at(Crumb.Parent).title = parent_1;
	            }
	            node.appendChild(separators.at(2));
	            breadcrumbs.at(Crumb.Current).textContent = parts[parts.length - 1];
	            node.appendChild(breadcrumbs.at(Crumb.Current));
	            breadcrumbs.at(Crumb.Current).title = path;
	        }
	    }
	    Private.updateCrumbs = updateCrumbs;
	    /**
	     * Create the breadcrumb nodes.
	     */
	    function createCrumbs() {
	        var home = document.createElement('span');
	        home.className = MATERIAL_CLASS + ' ' + BREADCRUMB_HOME + ' ' + BREADCRUMB_ITEM_CLASS;
	        var ellipsis = document.createElement('span');
	        ellipsis.className = MATERIAL_CLASS + ' ' + BREADCRUMB_ELLIPSES + ' ' + BREADCRUMB_ITEM_CLASS;
	        var parent = document.createElement('span');
	        parent.className = BREADCRUMB_ITEM_CLASS;
	        var current = document.createElement('span');
	        current.className = BREADCRUMB_ITEM_CLASS;
	        return new vector_1.Vector([home, ellipsis, parent, current]);
	    }
	    Private.createCrumbs = createCrumbs;
	    /**
	     * Create the breadcrumb separator nodes.
	     */
	    function createCrumbSeparators() {
	        var items = new vector_1.Vector();
	        for (var i = 0; i < 3; i++) {
	            var item = document.createElement('i');
	            item.className = 'fa fa-angle-right';
	            items.pushBack(item);
	        }
	        return items;
	    }
	    Private.createCrumbSeparators = createCrumbSeparators;
	})(Private || (Private = {}));
	//# sourceMappingURL=crumbs.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/crumbs.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/listing.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/listing.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var messaging_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/messaging.js');
	var mimedata_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/mimedata.js');
	var dragdrop_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/dragdrop.js');
	var query_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/query.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var dates_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dates.js');
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	var dialogs_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/dialogs.js');
	var utils = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/utils.js');
	var utils_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/utils.js');
	/**
	 * The class name added to DirListing widget.
	 */
	var DIR_LISTING_CLASS = 'jp-DirListing';
	/**
	 * The class name added to a dir listing header node.
	 */
	var HEADER_CLASS = 'jp-DirListing-header';
	/**
	 * The class name added to a dir listing list header cell.
	 */
	var HEADER_ITEM_CLASS = 'jp-DirListing-headerItem';
	/**
	 * The class name added to a header cell text node.
	 */
	var HEADER_ITEM_TEXT_CLASS = 'jp-DirListing-headerItemText';
	/**
	 * The class name added to a header cell icon node.
	 */
	var HEADER_ITEM_ICON_CLASS = 'jp-DirListing-headerItemIcon';
	/**
	 * The class name added to the dir listing content node.
	 */
	var CONTENT_CLASS = 'jp-DirListing-content';
	/**
	 * The class name added to dir listing content item.
	 */
	var ITEM_CLASS = 'jp-DirListing-item';
	/**
	 * The class name added to the listing item text cell.
	 */
	var ITEM_TEXT_CLASS = 'jp-DirListing-itemText';
	/**
	 * The class name added to the listing item icon cell.
	 */
	var ITEM_ICON_CLASS = 'jp-DirListing-itemIcon';
	/**
	 * The class name added to the listing item modified cell.
	 */
	var ITEM_MODIFIED_CLASS = 'jp-DirListing-itemModified';
	/**
	 * The class name added to the dir listing editor node.
	 */
	var EDITOR_CLASS = 'jp-DirListing-editor';
	/**
	 * The class name added to the name column header cell.
	 */
	var NAME_ID_CLASS = 'jp-id-name';
	/**
	 * The class name added to the modified column header cell.
	 */
	var MODIFIED_ID_CLASS = 'jp-id-modified';
	/**
	 * The class name added to a file type content item.
	 */
	var FILE_TYPE_CLASS = 'jp-FileIcon';
	/**
	 * The class name added to a folder type content item.
	 */
	var FOLDER_TYPE_CLASS = 'jp-type-folder';
	var FOLDER_MATERIAL_ICON_CLASS = 'jp-OpenFolderIcon';
	var NOTEBOOK_MATERIAL_ICON_CLASS = 'jp-NotebookIcon';
	var MATERIAL_ICON_CLASS = 'jp-MaterialIcon';
	/**
	 * The class name added to a notebook type content item.
	 */
	var NOTEBOOK_TYPE_CLASS = 'jp-type-notebook';
	/**
	 * The class name added to the widget when there are items on the clipboard.
	 */
	var CLIPBOARD_CLASS = 'jp-mod-clipboard';
	/**
	 * The class name added to cut rows.
	 */
	var CUT_CLASS = 'jp-mod-cut';
	/**
	 * The class name added when there are more than one selected rows.
	 */
	var MULTI_SELECTED_CLASS = 'jp-mod-multiSelected';
	/**
	 * The class name added to indicate running notebook.
	 */
	var RUNNING_CLASS = 'jp-mod-running';
	/**
	 * The class name added for a decending sort.
	 */
	var DESCENDING_CLASS = 'jp-mod-descending';
	/**
	 * The minimum duration for a rename select in ms.
	 */
	var RENAME_DURATION = 1000;
	/**
	 * The threshold in pixels to start a drag event.
	 */
	var DRAG_THRESHOLD = 5;
	/**
	 * A boolean indicating whether the platform is Mac.
	 */
	var IS_MAC = !!navigator.platform.match(/Mac/i);
	/**
	 * The factory MIME type supported by phosphor dock panels.
	 */
	var FACTORY_MIME = 'application/vnd.phosphor.widget-factory';
	/**
	 * A widget which hosts a file list area.
	 */
	var DirListing = (function (_super) {
	    __extends(DirListing, _super);
	    /**
	     * Construct a new file browser directory listing widget.
	     *
	     * @param model - The file browser view model.
	     */
	    function DirListing(options) {
	        _super.call(this, {
	            node: (options.renderer || DirListing.defaultRenderer).createNode()
	        });
	        this._model = null;
	        this._editNode = null;
	        this._items = new vector_1.Vector();
	        this._sortedItems = null;
	        this._sortState = { direction: 'ascending', key: 'name' };
	        this._drag = null;
	        this._dragData = null;
	        this._selectTimer = -1;
	        this._noSelectTimer = -1;
	        this._isCut = false;
	        this._prevPath = '';
	        this._clipboard = new vector_1.Vector();
	        this._manager = null;
	        this._softSelection = '';
	        this._inContext = false;
	        this._selection = Object.create(null);
	        this._renderer = null;
	        this.addClass(DIR_LISTING_CLASS);
	        this._model = options.model;
	        this._model.fileChanged.connect(this._onFileChanged, this);
	        this._model.refreshed.connect(this._onModelRefreshed, this);
	        this._model.pathChanged.connect(this._onPathChanged, this);
	        this._editNode = document.createElement('input');
	        this._editNode.className = EDITOR_CLASS;
	        this._manager = options.manager;
	        this._renderer = options.renderer || DirListing.defaultRenderer;
	        var headerNode = utils.findElement(this.node, HEADER_CLASS);
	        this._renderer.populateHeaderNode(headerNode);
	    }
	    /**
	     * Dispose of the resources held by the directory listing.
	     */
	    DirListing.prototype.dispose = function () {
	        this._model = null;
	        this._items = null;
	        this._editNode = null;
	        this._drag = null;
	        this._dragData = null;
	        this._manager = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(DirListing.prototype, "model", {
	        /**
	         * Get the model used by the listing.
	         */
	        get: function () {
	            return this._model;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DirListing.prototype, "headerNode", {
	        /**
	         * Get the dir listing header node.
	         *
	         * #### Notes
	         * This is the node which holds the header cells.
	         *
	         * Modifying this node directly can lead to undefined behavior.
	         */
	        get: function () {
	            return utils.findElement(this.node, HEADER_CLASS);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DirListing.prototype, "contentNode", {
	        /**
	         * Get the dir listing content node.
	         *
	         * #### Notes
	         * This is the node which holds the item nodes.
	         *
	         * Modifying this node directly can lead to undefined behavior.
	         */
	        get: function () {
	            return utils.findElement(this.node, CONTENT_CLASS);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DirListing.prototype, "renderer", {
	        /**
	         * The renderer instance used by the directory listing.
	         */
	        get: function () {
	            return this._renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DirListing.prototype, "sortState", {
	        /**
	         * The current sort state.
	         */
	        get: function () {
	            return this._sortState;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Create an iterator over the listing's sorted items.
	     *
	     * @returns A new iterator over the listing's sorted items.
	     */
	    DirListing.prototype.sortedItems = function () {
	        return this._sortedItems.iter();
	    };
	    /**
	     * Sort the items using a sort condition.
	     */
	    DirListing.prototype.sort = function (state) {
	        this._sortedItems = new vector_1.Vector(Private.sort(this.model.items(), state));
	        this._sortState = state;
	        this.update();
	    };
	    /**
	     * Rename the first currently selected item.
	     *
	     * @returns A promise that resolves with the new name of the item.
	     */
	    DirListing.prototype.rename = function () {
	        return this._doRename();
	    };
	    /**
	     * Cut the selected items.
	     */
	    DirListing.prototype.cut = function () {
	        this._isCut = true;
	        this._copy();
	    };
	    /**
	     * Copy the selected items.
	     */
	    DirListing.prototype.copy = function () {
	        this._copy();
	    };
	    /**
	     * Paste the items from the clipboard.
	     *
	     * @returns A promise that resolves when the operation is complete.
	     */
	    DirListing.prototype.paste = function () {
	        var _this = this;
	        if (!this._clipboard.length) {
	            return;
	        }
	        var promises = [];
	        iteration_1.each(this._clipboard, function (path) {
	            if (_this._isCut) {
	                var parts = path.split('/');
	                var name_1 = parts[parts.length - 1];
	                promises.push(_this._model.rename(path, name_1));
	            }
	            else {
	                promises.push(_this._model.copy(path, '.'));
	            }
	        });
	        // Remove any cut modifiers.
	        iteration_1.each(this._items, function (item) {
	            item.classList.remove(CUT_CLASS);
	        });
	        this._clipboard.clear();
	        this._isCut = false;
	        this.removeClass(CLIPBOARD_CLASS);
	        return Promise.all(promises).catch(function (error) {
	            utils.showErrorMessage('Paste Error', error);
	        });
	    };
	    /**
	     * Delete the currently selected item(s).
	     *
	     * @returns A promise that resolves when the operation is complete.
	     */
	    DirListing.prototype.delete = function () {
	        var _this = this;
	        var names = [];
	        iteration_1.each(this._sortedItems, function (item) {
	            if (_this._selection[item.name]) {
	                names.push(item.name);
	            }
	        });
	        var message = "Permanently delete these " + names.length + " files?";
	        if (names.length === 1) {
	            message = "Permanently delete file \"" + names[0] + "\"?";
	        }
	        if (names.length) {
	            return dialog_1.showDialog({
	                title: 'Delete file?',
	                body: message,
	                okText: 'DELETE',
	                buttons: [dialog_1.cancelButton, dialog_1.deleteButton]
	            }).then(function (result) {
	                if (!_this.isDisposed && result.text === 'DELETE') {
	                    return _this._delete(names);
	                }
	            });
	        }
	        return Promise.resolve(void 0);
	    };
	    /**
	     * Duplicate the currently selected item(s).
	     *
	     * @returns A promise that resolves when the operation is complete.
	     */
	    DirListing.prototype.duplicate = function () {
	        var promises = [];
	        for (var _i = 0, _a = this._getSelectedItems(); _i < _a.length; _i++) {
	            var item = _a[_i];
	            if (item.type !== 'directory') {
	                promises.push(this._model.copy(item.name, '.'));
	            }
	        }
	        return Promise.all(promises).catch(function (error) {
	            if (error.throwError) {
	                error.message = error.throwError;
	            }
	            utils.showErrorMessage('Duplicate file', error);
	        });
	    };
	    /**
	     * Download the currently selected item(s).
	     */
	    DirListing.prototype.download = function () {
	        for (var _i = 0, _a = this._getSelectedItems(); _i < _a.length; _i++) {
	            var item = _a[_i];
	            if (item.type !== 'directory') {
	                this._model.download(item.path);
	            }
	        }
	    };
	    /**
	     * Shut down kernels on the applicable currently selected items.
	     *
	     * @returns A promise that resolves when the operation is complete.
	     */
	    DirListing.prototype.shutdownKernels = function () {
	        var _this = this;
	        var promises = [];
	        var items = this._sortedItems;
	        var paths = iteration_1.toArray(iteration_1.map(items, function (item) { return item.path; }));
	        iteration_1.each(this._model.sessions(), function (session) {
	            var index = searching_1.indexOf(paths, session.notebook.path);
	            if (_this._selection[items.at(index).name]) {
	                promises.push(_this._model.shutdown(session.id));
	            }
	        });
	        return Promise.all(promises).catch(function (error) {
	            utils.showErrorMessage('Shutdown kernel', error);
	        });
	    };
	    /**
	     * Select next item.
	     *
	     * @param keepExisting - Whether to keep the current selection and add to it.
	     */
	    DirListing.prototype.selectNext = function (keepExisting) {
	        if (keepExisting === void 0) { keepExisting = false; }
	        var index = -1;
	        var selected = Object.keys(this._selection);
	        var items = this._sortedItems;
	        if (selected.length === 1 || keepExisting) {
	            // Select the next item.
	            var name_2 = selected[selected.length - 1];
	            index = searching_1.findIndex(items, function (value) { return value.name === name_2; });
	            index += 1;
	            if (index === this._items.length) {
	                index = 0;
	            }
	        }
	        else if (selected.length === 0) {
	            // Select the first item.
	            index = 0;
	        }
	        else {
	            // Select the last selected item.
	            var name_3 = selected[selected.length - 1];
	            index = searching_1.findIndex(items, function (value) { return value.name === name_3; });
	        }
	        if (index !== -1) {
	            this._selectItem(index, keepExisting);
	            query_1.scrollIntoViewIfNeeded(this.contentNode, this._items.at(index));
	        }
	    };
	    /**
	     * Select previous item.
	     *
	     * @param keepExisting - Whether to keep the current selection and add to it.
	     */
	    DirListing.prototype.selectPrevious = function (keepExisting) {
	        if (keepExisting === void 0) { keepExisting = false; }
	        var index = -1;
	        var selected = Object.keys(this._selection);
	        var items = this._sortedItems;
	        if (selected.length === 1 || keepExisting) {
	            // Select the previous item.
	            var name_4 = selected[0];
	            index = searching_1.findIndex(items, function (value) { return value.name === name_4; });
	            index -= 1;
	            if (index === -1) {
	                index = this._items.length - 1;
	            }
	        }
	        else if (selected.length === 0) {
	            // Select the last item.
	            index = this._items.length - 1;
	        }
	        else {
	            // Select the first selected item.
	            var name_5 = selected[0];
	            index = searching_1.findIndex(items, function (value) { return value.name === name_5; });
	        }
	        if (index !== -1) {
	            this._selectItem(index, keepExisting);
	            query_1.scrollIntoViewIfNeeded(this.contentNode, this._items.at(index));
	        }
	    };
	    /**
	     * Get whether an item is selected by name.
	     *
	     * @param name - The name of of the item.
	     *
	     * @returns Whether the item is selected.
	     */
	    DirListing.prototype.isSelected = function (name) {
	        return this._selection[name] === true;
	    };
	    /**
	     * Find a path given a click.
	     *
	     * @param event - The mouse event.
	     *
	     * @returns The path to the selected file.
	     */
	    DirListing.prototype.pathForClick = function (event) {
	        var items = this._sortedItems;
	        var index = Private.hitTestNodes(this._items, event.clientX, event.clientY);
	        if (index !== -1) {
	            return items.at(index).path;
	        }
	    };
	    /**
	     * Handle the DOM events for the directory listing.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the panel's DOM node. It should
	     * not be called directly by user code.
	     */
	    DirListing.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'mousedown':
	                this._evtMousedown(event);
	                break;
	            case 'mouseup':
	                this._evtMouseup(event);
	                break;
	            case 'mousemove':
	                this._evtMousemove(event);
	                break;
	            case 'keydown':
	                this._evtKeydown(event);
	                break;
	            case 'click':
	                this._evtClick(event);
	                break;
	            case 'dblclick':
	                this._evtDblClick(event);
	                break;
	            case 'contextmenu':
	                this._evtContextMenu(event);
	                break;
	            case 'scroll':
	                this._evtScroll(event);
	                break;
	            case 'p-dragenter':
	                this._evtDragEnter(event);
	                break;
	            case 'p-dragleave':
	                this._evtDragLeave(event);
	                break;
	            case 'p-dragover':
	                this._evtDragOver(event);
	                break;
	            case 'p-drop':
	                this._evtDrop(event);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    DirListing.prototype.onAfterAttach = function (msg) {
	        _super.prototype.onAfterAttach.call(this, msg);
	        var node = this.node;
	        var content = utils.findElement(node, CONTENT_CLASS);
	        node.addEventListener('mousedown', this);
	        node.addEventListener('keydown', this);
	        node.addEventListener('click', this);
	        node.addEventListener('dblclick', this);
	        node.addEventListener('contextmenu', this);
	        content.addEventListener('scroll', this);
	        content.addEventListener('p-dragenter', this);
	        content.addEventListener('p-dragleave', this);
	        content.addEventListener('p-dragover', this);
	        content.addEventListener('p-drop', this);
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    DirListing.prototype.onBeforeDetach = function (msg) {
	        _super.prototype.onBeforeDetach.call(this, msg);
	        var node = this.node;
	        var content = utils.findElement(node, CONTENT_CLASS);
	        node.removeEventListener('mousedown', this);
	        node.removeEventListener('keydown', this);
	        node.removeEventListener('click', this);
	        node.removeEventListener('dblclick', this);
	        node.removeEventListener('contextmenu', this);
	        content.removeEventListener('scroll', this);
	        content.removeEventListener('p-dragenter', this);
	        content.removeEventListener('p-dragleave', this);
	        content.removeEventListener('p-dragover', this);
	        content.removeEventListener('p-drop', this);
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('mouseup', this, true);
	    };
	    /**
	     * A handler invoked on an `'update-request'` message.
	     */
	    DirListing.prototype.onUpdateRequest = function (msg) {
	        var _this = this;
	        // Fetch common variables.
	        var items = this._sortedItems;
	        var nodes = this._items;
	        var content = utils.findElement(this.node, CONTENT_CLASS);
	        var renderer = this._renderer;
	        this.removeClass(MULTI_SELECTED_CLASS);
	        this.removeClass(utils_1.SELECTED_CLASS);
	        // Remove any excess item nodes.
	        while (nodes.length > items.length) {
	            var node = nodes.popBack();
	            content.removeChild(node);
	        }
	        // Add any missing item nodes.
	        while (nodes.length < items.length) {
	            var node = renderer.createItemNode();
	            node.classList.add(ITEM_CLASS);
	            nodes.pushBack(node);
	            content.appendChild(node);
	        }
	        // Remove extra classes from the nodes.
	        iteration_1.each(nodes, function (item) {
	            item.classList.remove(utils_1.SELECTED_CLASS);
	            item.classList.remove(RUNNING_CLASS);
	            item.classList.remove(CUT_CLASS);
	        });
	        // Add extra classes to item nodes based on widget state.
	        for (var i = 0, n = items.length; i < n; ++i) {
	            var node = nodes.at(i);
	            var item = items.at(i);
	            renderer.updateItemNode(node, item);
	            if (this._selection[item.name]) {
	                node.classList.add(utils_1.SELECTED_CLASS);
	                if (this._isCut && this._model.path === this._prevPath) {
	                    node.classList.add(CUT_CLASS);
	                }
	            }
	        }
	        // Handle the selectors on the widget node.
	        var selectedNames = Object.keys(this._selection);
	        if (selectedNames.length > 1) {
	            this.addClass(MULTI_SELECTED_CLASS);
	        }
	        if (selectedNames.length) {
	            this.addClass(utils_1.SELECTED_CLASS);
	        }
	        // Handle notebook session statuses.
	        var paths = iteration_1.toArray(iteration_1.map(items, function (item) { return item.path; }));
	        iteration_1.each(this._model.sessions(), function (session) {
	            var index = searching_1.indexOf(paths, session.notebook.path);
	            var node = nodes.at(index);
	            node.classList.add(RUNNING_CLASS);
	            var name = session.kernel.name;
	            var specs = _this._model.specs;
	            if (specs) {
	                name = specs.kernelspecs[name].display_name;
	            }
	            node.title = name;
	        });
	        this._prevPath = this._model.path;
	    };
	    /**
	     * Handle the `'click'` event for the widget.
	     */
	    DirListing.prototype._evtClick = function (event) {
	        var target = event.target;
	        var header = this.headerNode;
	        if (header.contains(target)) {
	            var state = this.renderer.handleHeaderClick(header, event);
	            if (state) {
	                this.sort(state);
	            }
	            return;
	        }
	    };
	    /**
	     * Handle the `'scroll'` event for the widget.
	     */
	    DirListing.prototype._evtScroll = function (event) {
	        this.headerNode.scrollLeft = this.contentNode.scrollLeft;
	    };
	    /**
	     * Handle the `'contextmenu'` event for the widget.
	     */
	    DirListing.prototype._evtContextMenu = function (event) {
	        this._inContext = true;
	    };
	    /**
	     * Handle the `'mousedown'` event for the widget.
	     */
	    DirListing.prototype._evtMousedown = function (event) {
	        // Bail if clicking within the edit node
	        if (event.target === this._editNode) {
	            return;
	        }
	        // Blur the edit node if necessary.
	        if (this._editNode.parentNode) {
	            if (this._editNode !== event.target) {
	                this._editNode.focus();
	                this._editNode.blur();
	                clearTimeout(this._selectTimer);
	            }
	            else {
	                return;
	            }
	        }
	        // Check for clearing a context menu.
	        var newContext = (IS_MAC && event.ctrlKey) || (event.button === 2);
	        if (this._inContext && !newContext) {
	            this._inContext = false;
	            return;
	        }
	        this._inContext = false;
	        var index = Private.hitTestNodes(this._items, event.clientX, event.clientY);
	        if (index === -1) {
	            return;
	        }
	        this._handleFileSelect(event);
	        // Left mouse press for drag start.
	        if (event.button === 0) {
	            this._dragData = { pressX: event.clientX, pressY: event.clientY,
	                index: index };
	            document.addEventListener('mouseup', this, true);
	            document.addEventListener('mousemove', this, true);
	        }
	        if (event.button !== 0) {
	            clearTimeout(this._selectTimer);
	        }
	    };
	    /**
	     * Handle the `'mouseup'` event for the widget.
	     */
	    DirListing.prototype._evtMouseup = function (event) {
	        // Handle any soft selection from the previous mouse down.
	        if (this._softSelection) {
	            var altered = event.metaKey || event.shiftKey || event.ctrlKey;
	            // See if we need to clear the other selection.
	            if (!altered && event.button === 0) {
	                this._selection = Object.create(null);
	                this._selection[this._softSelection] = true;
	                this.update();
	            }
	            this._softSelection = '';
	        }
	        // Remove the drag listeners if necessary.
	        if (event.button !== 0 || !this._drag) {
	            document.removeEventListener('mousemove', this, true);
	            document.removeEventListener('mouseup', this, true);
	            return;
	        }
	        event.preventDefault();
	        event.stopPropagation();
	    };
	    /**
	     * Handle the `'mousemove'` event for the widget.
	     */
	    DirListing.prototype._evtMousemove = function (event) {
	        event.preventDefault();
	        event.stopPropagation();
	        // Bail if we are the one dragging.
	        if (this._drag) {
	            return;
	        }
	        // Check for a drag initialization.
	        var data = this._dragData;
	        var dx = Math.abs(event.clientX - data.pressX);
	        var dy = Math.abs(event.clientY - data.pressY);
	        if (dx < DRAG_THRESHOLD && dy < DRAG_THRESHOLD) {
	            return;
	        }
	        this._startDrag(data.index, event.clientX, event.clientY);
	    };
	    /**
	     * Handle the `'keydown'` event for the widget.
	     */
	    DirListing.prototype._evtKeydown = function (event) {
	        switch (event.keyCode) {
	            case 38:
	                this.selectPrevious(event.shiftKey);
	                event.stopPropagation();
	                event.preventDefault();
	                break;
	            case 40:
	                this.selectNext(event.shiftKey);
	                event.stopPropagation();
	                event.preventDefault();
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle the `'dblclick'` event for the widget.
	     */
	    DirListing.prototype._evtDblClick = function (event) {
	        var _this = this;
	        // Do nothing if it's not a left mouse press.
	        if (event.button !== 0) {
	            return;
	        }
	        // Do nothing if any modifier keys are pressed.
	        if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
	            return;
	        }
	        // Stop the event propagation.
	        event.preventDefault();
	        event.stopPropagation();
	        clearTimeout(this._selectTimer);
	        this._noSelectTimer = setTimeout(function () {
	            _this._noSelectTimer = -1;
	        }, RENAME_DURATION);
	        this._editNode.blur();
	        // Find a valid double click target.
	        var target = event.target;
	        var i = searching_1.findIndex(this._items, function (node) { return node.contains(target); });
	        if (i === -1) {
	            return;
	        }
	        var model = this._model;
	        var item = this._sortedItems.at(i);
	        if (item.type === 'directory') {
	            model.cd(item.name).catch(function (error) {
	                return utils_1.showErrorMessage('Open directory', error);
	            });
	        }
	        else {
	            var path = item.path;
	            this._manager.openOrReveal(path);
	        }
	    };
	    /**
	     * Handle the `'p-dragenter'` event for the widget.
	     */
	    DirListing.prototype._evtDragEnter = function (event) {
	        if (event.mimeData.hasData(utils.CONTENTS_MIME)) {
	            var index = Private.hitTestNodes(this._items, event.clientX, event.clientY);
	            if (index === -1) {
	                return;
	            }
	            var item = this._sortedItems.at(index);
	            if (item.type !== 'directory' || this._selection[item.name]) {
	                return;
	            }
	            var target = event.target;
	            target.classList.add(utils.DROP_TARGET_CLASS);
	            event.preventDefault();
	            event.stopPropagation();
	        }
	    };
	    /**
	     * Handle the `'p-dragleave'` event for the widget.
	     */
	    DirListing.prototype._evtDragLeave = function (event) {
	        event.preventDefault();
	        event.stopPropagation();
	        var dropTarget = utils.findElement(this.node, utils.DROP_TARGET_CLASS);
	        if (dropTarget) {
	            dropTarget.classList.remove(utils.DROP_TARGET_CLASS);
	        }
	    };
	    /**
	     * Handle the `'p-dragover'` event for the widget.
	     */
	    DirListing.prototype._evtDragOver = function (event) {
	        event.preventDefault();
	        event.stopPropagation();
	        event.dropAction = event.proposedAction;
	        var dropTarget = utils.findElement(this.node, utils.DROP_TARGET_CLASS);
	        if (dropTarget) {
	            dropTarget.classList.remove(utils.DROP_TARGET_CLASS);
	        }
	        var index = Private.hitTestNodes(this._items, event.clientX, event.clientY);
	        this._items.at(index).classList.add(utils.DROP_TARGET_CLASS);
	    };
	    /**
	     * Handle the `'p-drop'` event for the widget.
	     */
	    DirListing.prototype._evtDrop = function (event) {
	        event.preventDefault();
	        event.stopPropagation();
	        clearTimeout(this._selectTimer);
	        if (event.proposedAction === 'none') {
	            event.dropAction = 'none';
	            return;
	        }
	        if (!event.mimeData.hasData(utils.CONTENTS_MIME)) {
	            return;
	        }
	        event.dropAction = event.proposedAction;
	        var target = event.target;
	        while (target && target.parentElement) {
	            if (target.classList.contains(utils.DROP_TARGET_CLASS)) {
	                target.classList.remove(utils.DROP_TARGET_CLASS);
	                break;
	            }
	            target = target.parentElement;
	        }
	        // Get the path based on the target node.
	        var index = searching_1.indexOf(this._items, target);
	        var items = this._sortedItems;
	        var path = items.at(index).name + '/';
	        // Move all of the items.
	        var promises = [];
	        var names = event.mimeData.getData(utils.CONTENTS_MIME);
	        for (var _i = 0, names_1 = names; _i < names_1.length; _i++) {
	            var name_6 = names_1[_i];
	            var newPath = path + name_6;
	            promises.push(dialogs_1.renameFile(this._model, name_6, newPath));
	        }
	        Promise.all(promises).catch(function (error) {
	            utils.showErrorMessage('Move Error', error);
	        });
	    };
	    /**
	     * Start a drag event.
	     */
	    DirListing.prototype._startDrag = function (index, clientX, clientY) {
	        var _this = this;
	        var selectedNames = Object.keys(this._selection);
	        var source = this._items.at(index);
	        var items = this._sortedItems;
	        var item = null;
	        // If the source node is not selected, use just that node.
	        if (!source.classList.contains(utils_1.SELECTED_CLASS)) {
	            item = items.at(index);
	            selectedNames = [item.name];
	        }
	        else if (selectedNames.length === 1) {
	            var name_7 = selectedNames[0];
	            item = searching_1.find(items, function (value) { return value.name === name_7; });
	        }
	        // Create the drag image.
	        var dragImage = this.renderer.createDragImage(source, selectedNames.length);
	        // Set up the drag event.
	        this._drag = new dragdrop_1.Drag({
	            dragImage: dragImage,
	            mimeData: new mimedata_1.MimeData(),
	            supportedActions: 'move',
	            proposedAction: 'move'
	        });
	        this._drag.mimeData.setData(utils.CONTENTS_MIME, selectedNames);
	        if (item && item.type !== 'directory') {
	            this._drag.mimeData.setData(FACTORY_MIME, function () {
	                var path = item.path;
	                var widget = _this._manager.findWidget(path);
	                if (!widget) {
	                    widget = _this._manager.open(item.path);
	                }
	                return widget;
	            });
	        }
	        // Start the drag and remove the mousemove and mouseup listeners.
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('mouseup', this, true);
	        clearTimeout(this._selectTimer);
	        this._drag.start(clientX, clientY).then(function (action) {
	            _this._drag = null;
	            clearTimeout(_this._selectTimer);
	        });
	    };
	    /**
	     * Handle selection on a file node.
	     */
	    DirListing.prototype._handleFileSelect = function (event) {
	        var _this = this;
	        // Fetch common variables.
	        var items = this._sortedItems;
	        var index = Private.hitTestNodes(this._items, event.clientX, event.clientY);
	        var target = event.target;
	        var inText = target.classList.contains(ITEM_TEXT_CLASS);
	        clearTimeout(this._selectTimer);
	        if (index === -1) {
	            return;
	        }
	        // Clear any existing soft selection.
	        this._softSelection = '';
	        var name = items.at(index).name;
	        var selected = Object.keys(this._selection);
	        // Handle toggling.
	        if ((IS_MAC && event.metaKey) || (!IS_MAC && event.ctrlKey)) {
	            if (this._selection[name]) {
	                delete this._selection[name];
	            }
	            else {
	                this._selection[name] = true;
	            }
	        }
	        else if (event.shiftKey) {
	            this._handleMultiSelect(selected, index);
	        }
	        else if (name in this._selection && selected.length > 1) {
	            this._softSelection = name;
	        }
	        else {
	            // Handle a rename.
	            if (inText && selected.length === 1 && selected[0] === name) {
	                this._selectTimer = setTimeout(function () {
	                    if (_this._noSelectTimer === -1) {
	                        _this._doRename();
	                    }
	                }, RENAME_DURATION);
	            }
	            // Select only the given item.
	            this._selection = Object.create(null);
	            this._selection[name] = true;
	        }
	        this._isCut = false;
	        this.update();
	    };
	    /**
	     * Select an item by name.
	     *
	     * @parem name - The name of the item to select.
	     *
	     * @returns A promise that resolves when the name is selected.
	     */
	    DirListing.prototype._selectItemByName = function (name) {
	        var _this = this;
	        // Make sure the file is available.
	        return this.model.refresh().then(function () {
	            if (_this.isDisposed) {
	                return;
	            }
	            var items = _this._sortedItems;
	            var index = searching_1.findIndex(items, function (value) { return value.name === name; });
	            _this._selectItem(index, false);
	            messaging_1.sendMessage(_this, widget_1.WidgetMessage.UpdateRequest);
	            query_1.scrollIntoViewIfNeeded(_this.contentNode, _this._items.at(index));
	        });
	    };
	    /**
	     * Handle a multiple select on a file item node.
	     */
	    DirListing.prototype._handleMultiSelect = function (selected, index) {
	        // Find the "nearest selected".
	        var items = this._sortedItems;
	        var nearestIndex = -1;
	        for (var i = 0; i < this._items.length; i++) {
	            if (i === index) {
	                continue;
	            }
	            var name_8 = items.at(i).name;
	            if (selected.indexOf(name_8) !== -1) {
	                if (nearestIndex === -1) {
	                    nearestIndex = i;
	                }
	                else {
	                    if (Math.abs(index - i) < Math.abs(nearestIndex - i)) {
	                        nearestIndex = i;
	                    }
	                }
	            }
	        }
	        // Default to the first element (and fill down).
	        if (nearestIndex === -1) {
	            nearestIndex = 0;
	        }
	        // Select the rows between the current and the nearest selected.
	        for (var i = 0; i < this._items.length; i++) {
	            if (nearestIndex >= i && index <= i ||
	                nearestIndex <= i && index >= i) {
	                this._selection[items.at(i).name] = true;
	            }
	        }
	    };
	    /**
	     * Get the currently selected items.
	     */
	    DirListing.prototype._getSelectedItems = function () {
	        var _this = this;
	        var items = this._sortedItems;
	        return iteration_1.toArray(iteration_1.filter(items, function (item) { return _this._selection[item.name]; }));
	    };
	    /**
	     * Copy the selected items, and optionally cut as well.
	     */
	    DirListing.prototype._copy = function () {
	        this._clipboard.clear();
	        for (var _i = 0, _a = this._getSelectedItems(); _i < _a.length; _i++) {
	            var item = _a[_i];
	            if (item.type !== 'directory') {
	                // Store the absolute path of the item.
	                this._clipboard.pushBack('/' + item.path);
	            }
	        }
	        this.update();
	    };
	    /**
	     * Delete the files with the given names.
	     */
	    DirListing.prototype._delete = function (names) {
	        var promises = [];
	        for (var _i = 0, names_2 = names; _i < names_2.length; _i++) {
	            var name_9 = names_2[_i];
	            promises.push(this._model.deleteFile(name_9));
	        }
	        return Promise.all(promises).catch(function (error) {
	            utils.showErrorMessage('Delete file', error);
	        });
	    };
	    /**
	     * Allow the user to rename item on a given row.
	     */
	    DirListing.prototype._doRename = function () {
	        var _this = this;
	        var items = this._sortedItems;
	        var name = Object.keys(this._selection)[0];
	        var index = searching_1.findIndex(items, function (value) { return value.name === name; });
	        var row = this._items.at(index);
	        var item = items.at(index);
	        var nameNode = this.renderer.getNameNode(row);
	        var original = item.name;
	        this._editNode.value = original;
	        this._selectItem(index, false);
	        return Private.doRename(nameNode, this._editNode).then(function (newName) {
	            if (newName === original) {
	                return original;
	            }
	            if (_this.isDisposed) {
	                return;
	            }
	            return dialogs_1.renameFile(_this._model, original, newName).catch(function (error) {
	                utils.showErrorMessage('Rename Error', error);
	                return original;
	            }).then(function () {
	                if (_this.isDisposed) {
	                    return;
	                }
	                _this._selectItemByName(newName);
	                return newName;
	            });
	        });
	    };
	    /**
	     * Select a given item.
	     */
	    DirListing.prototype._selectItem = function (index, keepExisting) {
	        // Selected the given row(s)
	        var items = this._sortedItems;
	        if (!keepExisting) {
	            this._selection = Object.create(null);
	        }
	        var name = items.at(index).name;
	        this._selection[name] = true;
	        this._isCut = false;
	    };
	    /**
	     * Handle the `refreshed` signal from the model.
	     */
	    DirListing.prototype._onModelRefreshed = function () {
	        var _this = this;
	        // Update the selection.
	        var existing = Object.keys(this._selection);
	        this._selection = Object.create(null);
	        iteration_1.each(this._model.items(), function (item) {
	            var name = item.name;
	            if (existing.indexOf(name) !== -1) {
	                _this._selection[name] = true;
	            }
	        });
	        // Update the sorted items.
	        this.sort(this.sortState);
	    };
	    /**
	     * Handle a `pathChanged` signal from the model.
	     */
	    DirListing.prototype._onPathChanged = function () {
	        // Reset the selection.
	        this._selection = Object.create(null);
	        // Update the sorted items.
	        this.sort(this.sortState);
	    };
	    /**
	     * Handle a `fileChanged` signal from the model.
	     */
	    DirListing.prototype._onFileChanged = function (sender, args) {
	        var _this = this;
	        if (args.type === 'new') {
	            this._selectItemByName(args.newValue.name).then(function () {
	                if (!_this.isDisposed && args.newValue === 'directory') {
	                    _this._doRename();
	                }
	            });
	        }
	    };
	    return DirListing;
	}(widget_1.Widget));
	exports.DirListing = DirListing;
	/**
	 * The namespace for the `DirListing` class statics.
	 */
	var DirListing;
	(function (DirListing) {
	    /**
	     * The default implementation of an `IRenderer`.
	     */
	    var Renderer = (function () {
	        function Renderer() {
	        }
	        /**
	         * Create the DOM node for a dir listing.
	         */
	        Renderer.prototype.createNode = function () {
	            var node = document.createElement('div');
	            var header = document.createElement('div');
	            var content = document.createElement('ul');
	            content.className = CONTENT_CLASS;
	            header.className = HEADER_CLASS;
	            node.appendChild(header);
	            node.appendChild(content);
	            node.tabIndex = 1;
	            return node;
	        };
	        /**
	         * Populate and empty header node for a dir listing.
	         *
	         * @param node - The header node to populate.
	         */
	        Renderer.prototype.populateHeaderNode = function (node) {
	            var name = this._createHeaderItemNode('Name');
	            var modified = this._createHeaderItemNode('Last Modified');
	            name.classList.add(NAME_ID_CLASS);
	            name.classList.add(utils_1.SELECTED_CLASS);
	            modified.classList.add(MODIFIED_ID_CLASS);
	            node.appendChild(name);
	            node.appendChild(modified);
	        };
	        /**
	         * Handle a header click.
	         *
	         * @param node - A node populated by [[populateHeaderNode]].
	         *
	         * @param event - A click event on the node.
	         *
	         * @returns The sort state of the header after the click event.
	         */
	        Renderer.prototype.handleHeaderClick = function (node, event) {
	            var name = utils.findElement(node, NAME_ID_CLASS);
	            var modified = utils.findElement(node, MODIFIED_ID_CLASS);
	            var state = { direction: 'ascending', key: 'name' };
	            var target = event.target;
	            if (name.contains(target)) {
	                if (name.classList.contains(utils_1.SELECTED_CLASS)) {
	                    if (!name.classList.contains(DESCENDING_CLASS)) {
	                        state.direction = 'descending';
	                        name.classList.add(DESCENDING_CLASS);
	                    }
	                    else {
	                        name.classList.remove(DESCENDING_CLASS);
	                    }
	                }
	                else {
	                    name.classList.remove(DESCENDING_CLASS);
	                }
	                name.classList.add(utils_1.SELECTED_CLASS);
	                modified.classList.remove(utils_1.SELECTED_CLASS);
	                modified.classList.remove(DESCENDING_CLASS);
	                return state;
	            }
	            if (modified.contains(target)) {
	                state.key = 'last_modified';
	                if (modified.classList.contains(utils_1.SELECTED_CLASS)) {
	                    if (!modified.classList.contains(DESCENDING_CLASS)) {
	                        state.direction = 'descending';
	                        modified.classList.add(DESCENDING_CLASS);
	                    }
	                    else {
	                        modified.classList.remove(DESCENDING_CLASS);
	                    }
	                }
	                else {
	                    modified.classList.remove(DESCENDING_CLASS);
	                }
	                modified.classList.add(utils_1.SELECTED_CLASS);
	                name.classList.remove(utils_1.SELECTED_CLASS);
	                name.classList.remove(DESCENDING_CLASS);
	                return state;
	            }
	            return void 0;
	        };
	        /**
	         * Create a new item node for a dir listing.
	         *
	         * @returns A new DOM node to use as a content item.
	         */
	        Renderer.prototype.createItemNode = function () {
	            var node = document.createElement('li');
	            var icon = document.createElement('span');
	            var text = document.createElement('span');
	            var modified = document.createElement('span');
	            icon.className = ITEM_ICON_CLASS;
	            text.className = ITEM_TEXT_CLASS;
	            modified.className = ITEM_MODIFIED_CLASS;
	            node.appendChild(icon);
	            node.appendChild(text);
	            node.appendChild(modified);
	            return node;
	        };
	        /**
	         * Update an item node to reflect the current state of a model.
	         *
	         * @param node - A node created by [[createItemNode]].
	         *
	         * @param model - The model object to use for the item state.
	         */
	        Renderer.prototype.updateItemNode = function (node, model) {
	            var icon = utils.findElement(node, ITEM_ICON_CLASS);
	            var text = utils.findElement(node, ITEM_TEXT_CLASS);
	            var modified = utils.findElement(node, ITEM_MODIFIED_CLASS);
	            icon.className = ITEM_ICON_CLASS + ' ' + MATERIAL_ICON_CLASS;
	            switch (model.type) {
	                case 'directory':
	                    icon.classList.add(FOLDER_MATERIAL_ICON_CLASS);
	                    break;
	                case 'notebook':
	                    icon.classList.add(NOTEBOOK_MATERIAL_ICON_CLASS);
	                    break;
	                default:
	                    icon.classList.add(MATERIAL_ICON_CLASS);
	                    icon.classList.add(FILE_TYPE_CLASS);
	                    break;
	            }
	            var modText = '';
	            var modTitle = '';
	            if (model.last_modified) {
	                modText = dates_1.humanTime(model.last_modified);
	                modTitle = dates_1.dateTime(model.last_modified);
	            }
	            // If an item is being edited currently, its text node is unavailable.
	            if (text) {
	                text.textContent = model.name;
	            }
	            modified.textContent = modText;
	            modified.title = modTitle;
	        };
	        /**
	         * Get the node containing the file name.
	         *
	         * @param node - A node created by [[createItemNode]].
	         *
	         * @returns The node containing the file name.
	         */
	        Renderer.prototype.getNameNode = function (node) {
	            return utils.findElement(node, ITEM_TEXT_CLASS);
	        };
	        /**
	         * Create a drag image for an item.
	         *
	         * @param node - A node created by [[createItemNode]].
	         *
	         * @param count - The number of items being dragged.
	         *
	         * @returns An element to use as the drag image.
	         */
	        Renderer.prototype.createDragImage = function (node, count) {
	            var dragImage = node.cloneNode(true);
	            var modified = utils.findElement(dragImage, ITEM_MODIFIED_CLASS);
	            dragImage.removeChild(modified);
	            if (count > 1) {
	                var nameNode = utils.findElement(dragImage, ITEM_TEXT_CLASS);
	                nameNode.textContent = '(' + count + ')';
	                var iconNode = utils.findElement(dragImage, ITEM_ICON_CLASS);
	                iconNode.className = ITEM_ICON_CLASS + " " + FILE_TYPE_CLASS;
	            }
	            return dragImage;
	        };
	        /**
	         * Create a node for a header item.
	         */
	        Renderer.prototype._createHeaderItemNode = function (label) {
	            var node = document.createElement('div');
	            var text = document.createElement('span');
	            var icon = document.createElement('span');
	            node.className = HEADER_ITEM_CLASS;
	            text.className = HEADER_ITEM_TEXT_CLASS;
	            icon.className = HEADER_ITEM_ICON_CLASS;
	            text.textContent = label;
	            node.appendChild(text);
	            node.appendChild(icon);
	            return node;
	        };
	        return Renderer;
	    }());
	    DirListing.Renderer = Renderer;
	    /**
	     * The default `IRenderer` instance.
	     */
	    DirListing.defaultRenderer = new Renderer();
	})(DirListing = exports.DirListing || (exports.DirListing = {}));
	/**
	 * The namespace for the listing private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Handle editing text on a node.
	     *
	     * @returns Boolean indicating whether the name changed.
	     */
	    function doRename(text, edit) {
	        var changed = true;
	        var parent = text.parentElement;
	        parent.replaceChild(edit, text);
	        edit.focus();
	        var index = edit.value.lastIndexOf('.');
	        if (index === -1) {
	            edit.setSelectionRange(0, edit.value.length);
	        }
	        else {
	            edit.setSelectionRange(0, index);
	        }
	        return new Promise(function (resolve, reject) {
	            edit.onblur = function () {
	                parent.replaceChild(text, edit);
	                resolve(edit.value);
	            };
	            edit.onkeydown = function (event) {
	                switch (event.keyCode) {
	                    case 13:
	                        event.stopPropagation();
	                        event.preventDefault();
	                        edit.blur();
	                        break;
	                    case 27:
	                        event.stopPropagation();
	                        event.preventDefault();
	                        changed = false;
	                        edit.blur();
	                        break;
	                    case 38:
	                        event.stopPropagation();
	                        event.preventDefault();
	                        if (edit.selectionStart !== edit.selectionEnd) {
	                            edit.selectionStart = edit.selectionEnd = 0;
	                        }
	                        break;
	                    case 40:
	                        event.stopPropagation();
	                        event.preventDefault();
	                        if (edit.selectionStart !== edit.selectionEnd) {
	                            edit.selectionStart = edit.selectionEnd = edit.value.length;
	                        }
	                        break;
	                    default:
	                        break;
	                }
	            };
	        });
	    }
	    Private.doRename = doRename;
	    /**
	     * Sort a list of items by sort state as a new array.
	     */
	    function sort(items, state) {
	        // Shortcut for unmodified.
	        if (state.key !== 'last_modified' && state.direction === 'ascending') {
	            return new vector_1.Vector(items);
	        }
	        var copy = iteration_1.toArray(items);
	        if (state.key === 'last_modified') {
	            copy.sort(function (a, b) {
	                var valA = new Date(a.last_modified).getTime();
	                var valB = new Date(b.last_modified).getTime();
	                return valB - valA;
	            });
	        }
	        // Reverse the order if descending.
	        if (state.direction === 'descending') {
	            copy.reverse();
	        }
	        return new vector_1.Vector(copy);
	    }
	    Private.sort = sort;
	    /**
	     * Get the index of the node at a client position, or `-1`.
	     */
	    function hitTestNodes(nodes, x, y) {
	        return searching_1.findIndex(nodes, function (node) { return query_1.hitTest(node, x, y); });
	    }
	    Private.hitTestNodes = hitTestNodes;
	})(Private || (Private = {}));
	//# sourceMappingURL=listing.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/listing.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/model.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/model.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	/**
	 * The duration of auto-refresh in ms.
	 */
	var REFRESH_DURATION = 10000;
	/**
	 * The enforced time between refreshes in ms.
	 */
	var MIN_REFRESH = 1000;
	/**
	 * An implementation of a file browser model.
	 *
	 * #### Notes
	 * All paths parameters without a leading `'/'` are interpreted as relative to
	 * the current directory.  Supports `'../'` syntax.
	 */
	var FileBrowserModel = (function () {
	    /**
	     * Construct a new file browser model.
	     */
	    function FileBrowserModel(options) {
	        var _this = this;
	        this._maxUploadSizeMb = 15;
	        this._manager = null;
	        this._sessions = new vector_1.Vector();
	        this._items = new vector_1.Vector();
	        this._paths = new Set();
	        this._pendingPath = null;
	        this._pending = null;
	        this._timeoutId = -1;
	        this._refreshId = -1;
	        this._blackoutId = -1;
	        this._requested = false;
	        this._manager = options.manager;
	        this._model = { path: '', name: '/', type: 'directory' };
	        this._manager.contents.fileChanged.connect(this._onFileChanged, this);
	        this._manager.sessions.runningChanged.connect(this._onRunningChanged, this);
	        this._scheduleUpdate();
	        this._refreshId = setInterval(function () {
	            _this._scheduleUpdate();
	        }, REFRESH_DURATION);
	    }
	    Object.defineProperty(FileBrowserModel.prototype, "path", {
	        /**
	         * Get the current path.
	         */
	        get: function () {
	            return this._model ? this._model.path : '';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FileBrowserModel.prototype, "specs", {
	        /**
	         * Get the kernel spec models.
	         */
	        get: function () {
	            return this._manager.sessions.specs;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(FileBrowserModel.prototype, "isDisposed", {
	        /**
	         * Get whether the model is disposed.
	         */
	        get: function () {
	            return this._model === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the model.
	     */
	    FileBrowserModel.prototype.dispose = function () {
	        if (this._model === null) {
	            return;
	        }
	        this._model = null;
	        this._manager = null;
	        clearTimeout(this._timeoutId);
	        clearInterval(this._refreshId);
	        clearTimeout(this._blackoutId);
	        this._sessions.clear();
	        this._items.clear();
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Create an iterator over the model's items.
	     *
	     * @returns A new iterator over the model's items.
	     */
	    FileBrowserModel.prototype.items = function () {
	        return this._items.iter();
	    };
	    /**
	     * Create an iterator over the active sessions in the directory.
	     *
	     * @returns A new iterator over the model's active sessions.
	     */
	    FileBrowserModel.prototype.sessions = function () {
	        return this._sessions.iter();
	    };
	    /**
	     * Force a refresh of the directory contents.
	     */
	    FileBrowserModel.prototype.refresh = function () {
	        return this.cd('.');
	    };
	    /**
	     * Change directory.
	     *
	     * @param path - The path to the file or directory.
	     *
	     * @returns A promise with the contents of the directory.
	     */
	    FileBrowserModel.prototype.cd = function (newValue) {
	        var _this = this;
	        if (newValue === void 0) { newValue = '.'; }
	        if (newValue !== '.') {
	            newValue = Private.normalizePath(this._model.path, newValue);
	        }
	        else {
	            newValue = this._pendingPath || this._model.path;
	        }
	        // Collapse requests to the same directory.
	        if (newValue === this._pendingPath) {
	            return this._pending;
	        }
	        var oldValue = this.path;
	        var options = { content: true };
	        this._pendingPath = newValue;
	        if (oldValue !== newValue) {
	            this._sessions.clear();
	        }
	        var manager = this._manager;
	        this._pending = manager.contents.get(newValue, options).then(function (contents) {
	            if (_this.isDisposed) {
	                return;
	            }
	            _this._handleContents(contents);
	            _this._pendingPath = null;
	            if (oldValue !== newValue) {
	                _this.pathChanged.emit({
	                    name: 'path',
	                    oldValue: oldValue,
	                    newValue: newValue
	                });
	            }
	            _this._onRunningChanged(manager.sessions, manager.sessions.running());
	            _this.refreshed.emit(void 0);
	        }).catch(function (error) {
	            _this._pendingPath = null;
	            _this.connectionFailure.emit(error);
	        });
	        return this._pending;
	    };
	    /**
	     * Copy a file.
	     *
	     * @param fromFile - The path of the original file.
	     *
	     * @param toDir - The path to the target directory.
	     *
	     * @returns A promise which resolves to the contents of the file.
	     */
	    FileBrowserModel.prototype.copy = function (fromFile, toDir) {
	        var normalizePath = Private.normalizePath;
	        fromFile = normalizePath(this._model.path, fromFile);
	        toDir = normalizePath(this._model.path, toDir);
	        return this._manager.contents.copy(fromFile, toDir);
	    };
	    /**
	     * Delete a file.
	     *
	     * @param: path - The path to the file to be deleted.
	     *
	     * @returns A promise which resolves when the file is deleted.
	     *
	     * #### Notes
	     * If there is a running session associated with the file and no other
	     * sessions are using the kernel, the session will be shut down.
	     */
	    FileBrowserModel.prototype.deleteFile = function (path) {
	        var _this = this;
	        var normalizePath = Private.normalizePath;
	        path = normalizePath(this._model.path, path);
	        return this.stopIfNeeded(path).then(function () {
	            return _this._manager.contents.delete(path);
	        });
	    };
	    /**
	     * Download a file.
	     *
	     * @param - path - The path of the file to be downloaded.
	     *
	     * @returns A promise which resolves when the file has begun
	     *   downloading.
	     */
	    FileBrowserModel.prototype.download = function (path) {
	        return this._manager.contents.getDownloadUrl(path).then(function (url) {
	            var element = document.createElement('a');
	            element.setAttribute('href', url);
	            element.setAttribute('download', '');
	            element.click();
	            return void 0;
	        });
	    };
	    /**
	     * Create a new untitled file or directory in the current directory.
	     *
	     * @param type - The type of file object to create. One of
	     *  `['file', 'notebook', 'directory']`.
	     *
	     * @param ext - Optional extension for `'file'` types (defaults to `'.txt'`).
	     *
	     * @returns A promise containing the new file contents model.
	     */
	    FileBrowserModel.prototype.newUntitled = function (options) {
	        if (options.type === 'file') {
	            options.ext = options.ext || '.txt';
	        }
	        options.path = options.path || this._model.path;
	        return this._manager.contents.newUntitled(options);
	    };
	    /**
	     * Rename a file or directory.
	     *
	     * @param path - The path to the original file.
	     *
	     * @param newPath - The path to the new file.
	     *
	     * @returns A promise containing the new file contents model.
	     */
	    FileBrowserModel.prototype.rename = function (path, newPath) {
	        // Handle relative paths.
	        path = Private.normalizePath(this._model.path, path);
	        newPath = Private.normalizePath(this._model.path, newPath);
	        return this._manager.contents.rename(path, newPath);
	    };
	    /**
	     * Upload a `File` object.
	     *
	     * @param file - The `File` object to upload.
	     *
	     * @param overwrite - Whether to overwrite an existing file.
	     *
	     * @returns A promise containing the new file contents model.
	     *
	     * #### Notes
	     * This will fail to upload files that are too big to be sent in one
	     * request to the server.
	     */
	    FileBrowserModel.prototype.upload = function (file, overwrite) {
	        var _this = this;
	        // Skip large files with a warning.
	        if (file.size > this._maxUploadSizeMb * 1024 * 1024) {
	            var msg = "Cannot upload file (>" + this._maxUploadSizeMb + " MB) ";
	            msg += "\"" + file.name + "\"";
	            console.warn(msg);
	            return Promise.reject(new Error(msg));
	        }
	        if (overwrite) {
	            return this._upload(file);
	        }
	        var path = this._model.path;
	        path = path ? path + '/' + file.name : file.name;
	        return this._manager.contents.get(path, {}).then(function () {
	            var msg = "\"" + file.name + "\" already exists";
	            throw new Error(msg);
	        }, function () {
	            if (_this.isDisposed) {
	                return;
	            }
	            return _this._upload(file);
	        });
	    };
	    /**
	     * Shut down a session by session id.
	     *
	     * @param id - The id of the session.
	     *
	     * @returns A promise that resolves when the action is complete.
	     */
	    FileBrowserModel.prototype.shutdown = function (id) {
	        return this._manager.sessions.shutdown(id);
	    };
	    /**
	     * Find a session associated with a path and stop it is the only
	     * session using that kernel.
	     */
	    FileBrowserModel.prototype.stopIfNeeded = function (path) {
	        var sessions = iteration_1.toArray(this._sessions);
	        var index = searching_1.findIndex(sessions, function (value) { return value.notebook.path === path; });
	        if (index !== -1) {
	            var count_1 = 0;
	            var model_1 = sessions[index];
	            iteration_1.each(sessions, function (value) {
	                if (model_1.kernel.id === value.kernel.id) {
	                    count_1++;
	                }
	            });
	            if (count_1 === 1) {
	                // Try to delete the session, but succeed either way.
	                return this.shutdown(model_1.id).catch(function () { });
	            }
	        }
	        return Promise.resolve(void 0);
	    };
	    /**
	     * Perform the actual upload.
	     */
	    FileBrowserModel.prototype._upload = function (file) {
	        var _this = this;
	        // Gather the file model parameters.
	        var path = this._model.path;
	        path = path ? path + '/' + file.name : file.name;
	        var name = file.name;
	        var isNotebook = file.name.indexOf('.ipynb') !== -1;
	        var type = isNotebook ? 'notebook' : 'file';
	        var format = isNotebook ? 'json' : 'base64';
	        // Get the file content.
	        var reader = new FileReader();
	        if (isNotebook) {
	            reader.readAsText(file);
	        }
	        else {
	            reader.readAsArrayBuffer(file);
	        }
	        return new Promise(function (resolve, reject) {
	            reader.onload = function (event) {
	                var model = {
	                    type: type,
	                    format: format,
	                    name: name,
	                    content: Private.getContent(reader)
	                };
	                _this._manager.contents.save(path, model).then(function (contents) {
	                    resolve(contents);
	                }).catch(reject);
	            };
	            reader.onerror = function (event) {
	                reject(Error(("Failed to upload \"" + file.name + "\":") + event));
	            };
	        });
	    };
	    /**
	     * Handle an updated contents model.
	     */
	    FileBrowserModel.prototype._handleContents = function (contents) {
	        var _this = this;
	        // Update our internal data.
	        this._model = {
	            name: contents.name,
	            path: contents.path,
	            type: contents.type,
	            writable: contents.writable,
	            created: contents.created,
	            last_modified: contents.last_modified,
	            mimetype: contents.mimetype,
	            format: contents.format
	        };
	        this._items.clear();
	        this._paths.clear();
	        iteration_1.each(contents.content, function (model) {
	            _this._paths.add(model.path);
	        });
	        this._items = new vector_1.Vector(contents.content);
	    };
	    /**
	     * Handle a change to the running sessions.
	     */
	    FileBrowserModel.prototype._onRunningChanged = function (sender, models) {
	        var _this = this;
	        this._sessions.clear();
	        iteration_1.each(models, function (model) {
	            if (_this._paths.has(model.notebook.path)) {
	                _this._sessions.pushBack(model);
	            }
	        });
	        this.refreshed.emit(void 0);
	    };
	    /**
	     * Handle a change on the contents manager.
	     */
	    FileBrowserModel.prototype._onFileChanged = function (sender, change) {
	        var path = this._model.path || '.';
	        var value = change.oldValue;
	        if (value && value.path && services_1.ContentsManager.dirname(value.path) === path) {
	            this.fileChanged.emit(change);
	            this._scheduleUpdate();
	            return;
	        }
	        value = change.newValue;
	        if (value && value.path && services_1.ContentsManager.dirname(value.path) === path) {
	            this.fileChanged.emit(change);
	            this._scheduleUpdate();
	            return;
	        }
	    };
	    /**
	     * Handle internal model refresh logic.
	     */
	    FileBrowserModel.prototype._scheduleUpdate = function () {
	        var _this = this;
	        // Send immediately if there is no pending action, otherwise defer.
	        if (this._blackoutId !== -1) {
	            this._requested = true;
	            return;
	        }
	        this._timeoutId = setTimeout(function () {
	            _this.refresh();
	            if (_this._requested && _this._blackoutId !== -1) {
	                _this._requested = false;
	                clearTimeout(_this._blackoutId);
	                _this._blackoutId = -1;
	                _this._timeoutId = setTimeout(function () {
	                    _this._scheduleUpdate();
	                }, MIN_REFRESH);
	            }
	            else {
	                _this._blackoutId = setTimeout(function () {
	                    _this._blackoutId = -1;
	                    if (_this._requested) {
	                        _this._scheduleUpdate();
	                    }
	                }, MIN_REFRESH);
	            }
	        }, 0);
	    };
	    return FileBrowserModel;
	}());
	exports.FileBrowserModel = FileBrowserModel;
	// Define the signals for the `FileBrowserModel` class.
	signaling_1.defineSignal(FileBrowserModel.prototype, 'pathChanged');
	signaling_1.defineSignal(FileBrowserModel.prototype, 'refreshed');
	signaling_1.defineSignal(FileBrowserModel.prototype, 'fileChanged');
	signaling_1.defineSignal(FileBrowserModel.prototype, 'connectionFailure');
	/**
	 * The namespace for the file browser model private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Parse the content of a `FileReader`.
	     *
	     * If the result is an `ArrayBuffer`, return a Base64-encoded string.
	     * Otherwise, return the JSON parsed result.
	     */
	    function getContent(reader) {
	        if (reader.result instanceof ArrayBuffer) {
	            // Base64-encode binary file data.
	            var bytes = '';
	            var buf = new Uint8Array(reader.result);
	            var nbytes = buf.byteLength;
	            for (var i = 0; i < nbytes; i++) {
	                bytes += String.fromCharCode(buf[i]);
	            }
	            return btoa(bytes);
	        }
	        else {
	            return JSON.parse(reader.result);
	        }
	    }
	    Private.getContent = getContent;
	    /**
	     * Normalize a path based on a root directory, accounting for relative paths.
	     */
	    function normalizePath(root, path) {
	        return services_1.ContentsManager.getAbsolutePath(path, root);
	    }
	    Private.normalizePath = normalizePath;
	})(Private || (Private = {}));
	//# sourceMappingURL=model.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/model.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/tracker.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/tracker.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	/* tslint:disable */
	/**
	 * The path tracker token.
	 */
	exports.IPathTracker = new token_1.Token('jupyter.services.file-browser');
	//# sourceMappingURL=tracker.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/tracker.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/inspector/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/inspector/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/inspector/handler.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/inspector/inspector.js'));
	/**
	 * The command IDs used by the inspector plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.open = 'inspector:open';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/inspector/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/inspector/handler.js **/
jupyter.define('jupyterlab@0.15.1/lib/inspector/handler.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	/**
	 * An object that handles code inspection.
	 */
	var InspectionHandler = (function () {
	    /**
	     * Construct a new inspection handler for a widget.
	     */
	    function InspectionHandler(options) {
	        this._editor = null;
	        this._kernel = null;
	        this._pending = 0;
	        this._rendermime = null;
	        this._kernel = options.kernel || null;
	        this._rendermime = options.rendermime;
	    }
	    Object.defineProperty(InspectionHandler.prototype, "editor", {
	        /**
	         * The editor widget used by the inspection handler.
	         */
	        get: function () {
	            return this._editor;
	        },
	        set: function (newValue) {
	            if (newValue === this._editor) {
	                return;
	            }
	            if (this._editor && !this._editor.isDisposed) {
	                this._editor.model.value.changed.disconnect(this.onTextChanged, this);
	            }
	            var editor = this._editor = newValue;
	            if (editor) {
	                // Clear ephemeral inspectors in preparation for a new editor.
	                this.ephemeralCleared.emit(void 0);
	                editor.model.value.changed.connect(this.onTextChanged, this);
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(InspectionHandler.prototype, "kernel", {
	        /**
	         * The kernel used by the inspection handler.
	         */
	        get: function () {
	            return this._kernel;
	        },
	        set: function (value) {
	            this._kernel = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(InspectionHandler.prototype, "isDisposed", {
	        /**
	         * Get whether the inspection handler is disposed.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._editor === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the handler.
	     */
	    InspectionHandler.prototype.dispose = function () {
	        if (this._editor === null) {
	            return;
	        }
	        this._editor = null;
	        this._kernel = null;
	        this._rendermime = null;
	        this.disposed.emit(void 0);
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Handle a text changed signal from an editor.
	     *
	     * #### Notes
	     * Update the hints inspector based on a text change.
	     */
	    InspectionHandler.prototype.onTextChanged = function () {
	        var _this = this;
	        var update = {
	            content: null,
	            type: 'hints'
	        };
	        var editor = this.editor;
	        var code = editor.model.value.text;
	        var position = editor.getCursorPosition();
	        var offset = editor.getOffsetAt(position);
	        // Clear hints if the new text value is empty or kernel is unavailable.
	        if (!code || !this._kernel) {
	            this.inspected.emit(update);
	            return;
	        }
	        var contents = {
	            code: code,
	            cursor_pos: offset,
	            detail_level: 0
	        };
	        var pending = ++this._pending;
	        this._kernel.requestInspect(contents).then(function (msg) {
	            var value = msg.content;
	            // If handler has been disposed, bail.
	            if (_this.isDisposed) {
	                _this.inspected.emit(update);
	                return;
	            }
	            // If a newer text change has created a pending request, bail.
	            if (pending !== _this._pending) {
	                _this.inspected.emit(update);
	                return;
	            }
	            // Hint request failures or negative results fail silently.
	            if (value.status !== 'ok' || !value.found) {
	                _this.inspected.emit(update);
	                return;
	            }
	            var bundle = value.data;
	            var trusted = true;
	            var widget = _this._rendermime.render({ bundle: bundle, trusted: trusted });
	            update.content = widget;
	            _this.inspected.emit(update);
	        });
	    };
	    return InspectionHandler;
	}());
	exports.InspectionHandler = InspectionHandler;
	// Define the signals for the `InspectionHandler` class.
	signaling_1.defineSignal(InspectionHandler.prototype, 'ephemeralCleared');
	signaling_1.defineSignal(InspectionHandler.prototype, 'disposed');
	signaling_1.defineSignal(InspectionHandler.prototype, 'inspected');
	//# sourceMappingURL=handler.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/inspector/handler.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/inspector/inspector.js **/
jupyter.define('jupyterlab@0.15.1/lib/inspector/inspector.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var tabpanel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/tabpanel.js');
	var toolbar_1 = __jupyter_require__('jupyterlab@0.15.1/lib/toolbar/index.js');
	/**
	 * The class name added to inspector panels.
	 */
	var PANEL_CLASS = 'jp-Inspector';
	/**
	 * The class name added to inspector child item widgets.
	 */
	var ITEM_CLASS = 'jp-InspectorItem';
	/**
	 * The class name added to inspector child item widgets' content.
	 */
	var CONTENT_CLASS = 'jp-InspectorItem-content';
	/**
	 * The history clear button class name.
	 */
	var CLEAR_CLASS = 'jp-InspectorItem-clear';
	/**
	 * The back button class name.
	 */
	var BACK_CLASS = 'jp-InspectorItem-back';
	/**
	 * The forward button class name.
	 */
	var FORWARD_CLASS = 'jp-InspectorItem-forward';
	/* tslint:disable */
	/**
	 * The inspector panel token.
	 */
	exports.IInspector = new token_1.Token('jupyter.services.inspector');
	/**
	 * A panel which contains a set of inspectors.
	 */
	var Inspector = (function (_super) {
	    __extends(Inspector, _super);
	    /**
	     * Construct an inspector.
	     */
	    function Inspector(options) {
	        var _this = this;
	        _super.call(this);
	        this._items = Object.create(null);
	        this._source = null;
	        this.addClass(PANEL_CLASS);
	        var items = options.items || [];
	        // Create inspector child items and add them to the inspectors panel.
	        items.forEach(function (value) {
	            var widget = value.widget || new InspectorItem();
	            widget.rank = value.rank;
	            widget.remembers = !!value.remembers;
	            widget.title.closable = false;
	            widget.title.label = value.name;
	            if (value.className) {
	                widget.addClass(value.className);
	            }
	            _this._items[value.type] = widget;
	            _this.addWidget(widget);
	        });
	        if (items.length < 2) {
	            this.tabBar.hide();
	        }
	    }
	    Object.defineProperty(Inspector.prototype, "source", {
	        /**
	         * The source of events the inspector panel listens for.
	         */
	        get: function () {
	            return this._source;
	        },
	        set: function (source) {
	            var _this = this;
	            if (this._source === source) {
	                return;
	            }
	            // Disconnect old signal handler.
	            if (this._source) {
	                this._source.inspected.disconnect(this.onInspectorUpdate, this);
	                this._source.disposed.disconnect(this.onSourceDisposed, this);
	            }
	            // Clear the inspector child items (but maintain history) if necessary.
	            if (this._items) {
	                Object.keys(this._items).forEach(function (i) { return _this._items[i].content = null; });
	            }
	            this._source = source;
	            // Connect new signal handler.
	            if (this._source) {
	                this._source.inspected.connect(this.onInspectorUpdate, this);
	                this._source.disposed.connect(this.onSourceDisposed, this);
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    Inspector.prototype.dispose = function () {
	        if (this._items == null) {
	            return;
	        }
	        var items = this._items;
	        this._items = null;
	        this.source = null;
	        // Dispose the inspector child items.
	        Object.keys(items).forEach(function (i) { items[i].dispose(); });
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    Inspector.prototype.onActivateRequest = function (msg) {
	        this.node.tabIndex = -1;
	        this.node.focus();
	    };
	    /**
	     * Handle `'close-request'` messages.
	     */
	    Inspector.prototype.onCloseRequest = function (msg) {
	        _super.prototype.onCloseRequest.call(this, msg);
	        this.dispose();
	    };
	    /**
	     * Handle inspector update signals.
	     */
	    Inspector.prototype.onInspectorUpdate = function (sender, args) {
	        var widget = this._items[args.type];
	        if (!widget) {
	            return;
	        }
	        // Update the content of the inspector widget.
	        widget.content = args.content;
	        var items = this._items;
	        // If any inspector with a higher rank has content, do not change focus.
	        if (args.content) {
	            for (var type in items) {
	                var inspector = this._items[type];
	                if (inspector.rank < widget.rank && inspector.content) {
	                    return;
	                }
	            }
	            this.currentWidget = widget;
	            return;
	        }
	        // If the inspector was emptied, show the next best ranked inspector.
	        var lowest = Infinity;
	        widget = null;
	        for (var type in items) {
	            var inspector = this._items[type];
	            if (inspector.rank < lowest && inspector.content) {
	                lowest = inspector.rank;
	                widget = inspector;
	            }
	        }
	        if (widget) {
	            this.currentWidget = widget;
	        }
	    };
	    /**
	     * Handle source disposed signals.
	     */
	    Inspector.prototype.onSourceDisposed = function (sender, args) {
	        this.source = null;
	    };
	    return Inspector;
	}(tabpanel_1.TabPanel));
	exports.Inspector = Inspector;
	/**
	 * A code inspector child widget.
	 */
	var InspectorItem = (function (_super) {
	    __extends(InspectorItem, _super);
	    /**
	     * Construct an inspector widget.
	     */
	    function InspectorItem() {
	        _super.call(this);
	        this._content = null;
	        this._history = null;
	        this._index = -1;
	        this._rank = Infinity;
	        this._remembers = false;
	        this._toolbar = null;
	        this.addClass(ITEM_CLASS);
	        this._toolbar = this._createToolbar();
	        this.addWidget(this._toolbar);
	    }
	    Object.defineProperty(InspectorItem.prototype, "content", {
	        /**
	         * The text of the inspector.
	         */
	        get: function () {
	            return this._content;
	        },
	        set: function (newValue) {
	            if (newValue === this._content) {
	                return;
	            }
	            if (this._content) {
	                if (this._remembers) {
	                    this._content.hide();
	                }
	                else {
	                    this._content.dispose();
	                }
	            }
	            this._content = newValue;
	            if (this._content) {
	                this._content.addClass(CONTENT_CLASS);
	                this.addWidget(this._content);
	                if (this.remembers) {
	                    this._history.push(newValue);
	                    this._index++;
	                }
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(InspectorItem.prototype, "remembers", {
	        /**
	         * A flag that indicates whether the inspector remembers history.
	         */
	        get: function () {
	            return this._remembers;
	        },
	        set: function (newValue) {
	            if (newValue === this._remembers) {
	                return;
	            }
	            this._clear();
	            this._remembers = newValue;
	            if (!this._remembers) {
	                this._history = null;
	            }
	            this.update();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(InspectorItem.prototype, "rank", {
	        /**
	         * The display rank of the inspector.
	         */
	        get: function () {
	            return this._rank;
	        },
	        set: function (newValue) {
	            this._rank = newValue;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    InspectorItem.prototype.dispose = function () {
	        if (this._toolbar === null) {
	            return;
	        }
	        var toolbar = this._toolbar;
	        var history = this._history;
	        this._toolbar = null;
	        this._history = null;
	        history.forEach(function (widget) { return widget.dispose(); });
	        toolbar.dispose();
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Navigate back in history.
	     */
	    InspectorItem.prototype._back = function () {
	        if (this._history.length) {
	            this._navigateTo(Math.max(this._index - 1, 0));
	        }
	    };
	    /**
	     * Clear history.
	     */
	    InspectorItem.prototype._clear = function () {
	        if (this._history) {
	            this._history.forEach(function (widget) { return widget.dispose(); });
	        }
	        this._history = [];
	        this._index = -1;
	    };
	    /**
	     * Navigate forward in history.
	     */
	    InspectorItem.prototype._forward = function () {
	        if (this._history.length) {
	            this._navigateTo(Math.min(this._index + 1, this._history.length - 1));
	        }
	    };
	    /**
	     * Create a history toolbar.
	     */
	    InspectorItem.prototype._createToolbar = function () {
	        var _this = this;
	        var toolbar = new toolbar_1.Toolbar();
	        if (!this._remembers) {
	            return toolbar;
	        }
	        var clear = new toolbar_1.ToolbarButton({
	            className: CLEAR_CLASS,
	            onClick: function () { _this._clear(); },
	            tooltip: 'Clear history.'
	        });
	        toolbar.addItem('clear', clear);
	        var back = new toolbar_1.ToolbarButton({
	            className: BACK_CLASS,
	            onClick: function () { _this._back(); },
	            tooltip: 'Navigate back in history.'
	        });
	        toolbar.addItem('back', back);
	        var forward = new toolbar_1.ToolbarButton({
	            className: FORWARD_CLASS,
	            onClick: function () { _this._forward(); },
	            tooltip: 'Navigate forward in history.'
	        });
	        toolbar.addItem('forward', forward);
	        return toolbar;
	    };
	    /**
	     * Navigate to a known index in history.
	     */
	    InspectorItem.prototype._navigateTo = function (index) {
	        if (this._content) {
	            this._content.hide();
	        }
	        this._content = this._history[index];
	        this._index = index;
	        this._content.show();
	    };
	    return InspectorItem;
	}(panel_1.Panel));
	exports.InspectorItem = InspectorItem;
	//# sourceMappingURL=inspector.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/inspector/inspector.js **/


/** START DEFINE BLOCK for phosphor@0.7.0/lib/ui/tabpanel.js **/
jupyter.define('phosphor@0.7.0/lib/ui/tabpanel.js', function (module, exports, __jupyter_require__) {
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var signaling_1 = __jupyter_require__('phosphor@0.7.0/lib/core/signaling.js');
	var boxpanel_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/boxpanel.js');
	var stackedpanel_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/stackedpanel.js');
	var tabbar_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/tabbar.js');
	var widget_1 = __jupyter_require__('phosphor@0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to TabPanel instances.
	 */
	var TAB_PANEL_CLASS = 'p-TabPanel';
	/**
	 * The class name added to a TabPanel's tab bar.
	 */
	var TAB_BAR_CLASS = 'p-TabPanel-tabBar';
	/**
	 * The class name added to a TabPanel's stacked panel.
	 */
	var STACKED_PANEL_CLASS = 'p-TabPanel-stackedPanel';
	/**
	 * A widget which combines a `TabBar` and a `StackedPanel`.
	 *
	 * #### Notes
	 * This is a simple panel which handles the common case of a tab bar
	 * placed next to a content area. The selected tab controls the widget
	 * which is shown in the content area.
	 *
	 * For use cases which require more control than is provided by this
	 * panel, the `TabBar` widget may be used independently.
	 */
	var TabPanel = (function (_super) {
	    __extends(TabPanel, _super);
	    /**
	     * Construct a new tab panel.
	     *
	     * @param options - The options for initializing the tab panel.
	     */
	    function TabPanel(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this);
	        this.addClass(TAB_PANEL_CLASS);
	        // Create the tab bar and stacked panel.
	        this._tabBar = new tabbar_1.TabBar(options);
	        this._tabBar.addClass(TAB_BAR_CLASS);
	        this._stackedPanel = new stackedpanel_1.StackedPanel();
	        this._stackedPanel.addClass(STACKED_PANEL_CLASS);
	        // Connect the tab bar signal handlers.
	        this._tabBar.tabMoved.connect(this._onTabMoved, this);
	        this._tabBar.currentChanged.connect(this._onCurrentChanged, this);
	        this._tabBar.tabCloseRequested.connect(this._onTabCloseRequested, this);
	        // Connect the stacked panel signal handlers.
	        this._stackedPanel.widgetRemoved.connect(this._onWidgetRemoved, this);
	        // Get the data related to the placement.
	        this._tabPlacement = options.tabPlacement || 'top';
	        var direction = Private.directionFromPlacement(this._tabPlacement);
	        var orientation = Private.orientationFromPlacement(this._tabPlacement);
	        // Configure the tab bar for the placement.
	        this._tabBar.orientation = orientation;
	        this._tabBar.addClass("p-mod-" + this._tabPlacement);
	        // Create the box layout.
	        var layout = new boxpanel_1.BoxLayout({ direction: direction, spacing: 0 });
	        // Set the stretch factors for the child widgets.
	        boxpanel_1.BoxLayout.setStretch(this._tabBar, 0);
	        boxpanel_1.BoxLayout.setStretch(this._stackedPanel, 1);
	        // Add the child widgets to the layout.
	        layout.addWidget(this._tabBar);
	        layout.addWidget(this._stackedPanel);
	        // Install the layout on the tab panel.
	        this.layout = layout;
	    }
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    TabPanel.prototype.dispose = function () {
	        this._tabBar = null;
	        this._stackedPanel = null;
	        _super.prototype.dispose.call(this);
	    };
	    Object.defineProperty(TabPanel.prototype, "currentIndex", {
	        /**
	         * Get the index of the currently selected tab.
	         *
	         * #### Notes
	         * This will be `-1` if no tab is selected.
	         */
	        get: function () {
	            return this._tabBar.currentIndex;
	        },
	        /**
	         * Set the index of the currently selected tab.
	         *
	         * #### Notes
	         * If the index is out of range, it will be set to `-1`.
	         */
	        set: function (value) {
	            this._tabBar.currentIndex = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabPanel.prototype, "currentWidget", {
	        /**
	         * Get the currently selected widget.
	         *
	         * #### Notes
	         * This will be `null` if there is no selected tab.
	         */
	        get: function () {
	            var title = this._tabBar.currentTitle;
	            return title ? title.owner : null;
	        },
	        /**
	         * Set the currently selected widget.
	         *
	         * #### Notes
	         * If the widget is not in the panel, it will be set to `null`.
	         */
	        set: function (value) {
	            this._tabBar.currentTitle = value ? value.title : null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabPanel.prototype, "tabsMovable", {
	        /**
	         * Get the whether the tabs are movable by the user.
	         *
	         * #### Notes
	         * Tabs can always be moved programmatically.
	         */
	        get: function () {
	            return this._tabBar.tabsMovable;
	        },
	        /**
	         * Set the whether the tabs are movable by the user.
	         *
	         * #### Notes
	         * Tabs can always be moved programmatically.
	         */
	        set: function (value) {
	            this._tabBar.tabsMovable = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabPanel.prototype, "tabPlacement", {
	        /**
	         * Get the tab placement for the tab panel.
	         *
	         * #### Notes
	         * This controls the position of the tab bar relative to the content.
	         */
	        get: function () {
	            return this._tabPlacement;
	        },
	        /**
	         * Set the tab placement for the tab panel.
	         *
	         * #### Notes
	         * This controls the position of the tab bar relative to the content.
	         */
	        set: function (value) {
	            // Bail if the placement does not change.
	            if (this._tabPlacement === value) {
	                return;
	            }
	            // Swap the internal values.
	            var old = this._tabPlacement;
	            this._tabPlacement = value;
	            // Get the values related to the placement.
	            var direction = Private.directionFromPlacement(value);
	            var orientation = Private.orientationFromPlacement(value);
	            // Configure the tab bar for the placement.
	            this._tabBar.orientation = orientation;
	            this._tabBar.removeClass("p-mod-" + old);
	            this._tabBar.addClass("p-mod-" + value);
	            // Update the layout direction.
	            this.layout.direction = direction;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabPanel.prototype, "tabBar", {
	        /**
	         * The tab bar associated with the tab panel.
	         *
	         * #### Notes
	         * Modifying the tab bar directly can lead to undefined behavior.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._tabBar;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabPanel.prototype, "stackedPanel", {
	        /**
	         * The stacked panel associated with the tab panel.
	         *
	         * #### Notes
	         * Modifying the stack directly can lead to undefined behavior.
	         *
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._stackedPanel;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TabPanel.prototype, "widgets", {
	        /**
	         * A read-only sequence of the widgets in the panel.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._stackedPanel.widgets;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a widget to the end of the tab panel.
	     *
	     * @param widget - The widget to add to the tab panel.
	     *
	     * #### Notes
	     * If the widget is already contained in the panel, it will be moved.
	     *
	     * The widget's `title` is used to populate the tab.
	     */
	    TabPanel.prototype.addWidget = function (widget) {
	        this.insertWidget(this.widgets.length, widget);
	    };
	    /**
	     * Insert a widget into the tab panel at a specified index.
	     *
	     * @param index - The index at which to insert the widget.
	     *
	     * @param widget - The widget to insert into to the tab panel.
	     *
	     * #### Notes
	     * If the widget is already contained in the panel, it will be moved.
	     *
	     * The widget's `title` is used to populate the tab.
	     */
	    TabPanel.prototype.insertWidget = function (index, widget) {
	        if (widget !== this.currentWidget)
	            widget.hide();
	        this._stackedPanel.insertWidget(index, widget);
	        this._tabBar.insertTab(index, widget.title);
	    };
	    /**
	     * Handle the `currentChanged` signal from the tab bar.
	     */
	    TabPanel.prototype._onCurrentChanged = function (sender, args) {
	        // Extract the previous and current title from the args.
	        var previousIndex = args.previousIndex, previousTitle = args.previousTitle, currentIndex = args.currentIndex, currentTitle = args.currentTitle;
	        // Extract the widgets from the titles.
	        var previousWidget = previousTitle ? previousTitle.owner : null;
	        var currentWidget = currentTitle ? currentTitle.owner : null;
	        // Hide the previous widget.
	        if (previousWidget) {
	            previousWidget.hide();
	        }
	        // Show the current widget.
	        if (currentWidget) {
	            currentWidget.show();
	        }
	        // Emit the `currentChanged` signal for the tab panel.
	        this.currentChanged.emit({
	            previousIndex: previousIndex, previousWidget: previousWidget, currentIndex: currentIndex, currentWidget: currentWidget
	        });
	    };
	    /**
	     * Handle the `tabActivateRequested` signal from the tab bar.
	     */
	    TabPanel.prototype._onTabActivateRequested = function (sender, args) {
	        args.title.owner.activate();
	    };
	    /**
	     * Handle the `tabCloseRequested` signal from the tab bar.
	     */
	    TabPanel.prototype._onTabCloseRequested = function (sender, args) {
	        args.title.owner.close();
	    };
	    /**
	     * Handle the `tabMoved` signal from the tab bar.
	     */
	    TabPanel.prototype._onTabMoved = function (sender, args) {
	        this._stackedPanel.insertWidget(args.toIndex, args.title.owner);
	    };
	    /**
	     * Handle the `widgetRemoved` signal from the stacked panel.
	     */
	    TabPanel.prototype._onWidgetRemoved = function (sender, widget) {
	        this._tabBar.removeTab(widget.title);
	    };
	    return TabPanel;
	}(widget_1.Widget));
	exports.TabPanel = TabPanel;
	// Define the signals for the `TabPanel` class.
	signaling_1.defineSignal(TabPanel.prototype, 'currentChanged');
	/**
	 * The namespace for the private module data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Convert a tab placement to tab bar orientation.
	     */
	    function orientationFromPlacement(plc) {
	        return placementToOrientationMap[plc];
	    }
	    Private.orientationFromPlacement = orientationFromPlacement;
	    /**
	     * Convert a tab placement to a box layout direction.
	     */
	    function directionFromPlacement(plc) {
	        return placementToDirectionMap[plc];
	    }
	    Private.directionFromPlacement = directionFromPlacement;
	    /**
	     * A mapping of tab placement to tab bar orientation.
	     */
	    var placementToOrientationMap = {
	        'top': 'horizontal',
	        'left': 'vertical',
	        'right': 'vertical',
	        'bottom': 'horizontal'
	    };
	    /**
	     * A mapping of tab placement to box layout direction.
	     */
	    var placementToDirectionMap = {
	        'top': 'top-to-bottom',
	        'left': 'left-to-right',
	        'right': 'right-to-left',
	        'bottom': 'bottom-to-top'
	    };
	})(Private || (Private = {}));
	
})
/** END DEFINE BLOCK for phosphor@0.7.0/lib/ui/tabpanel.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/toolbar/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/toolbar/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var properties_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/properties.js');
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to toolbars.
	 */
	var TOOLBAR_CLASS = 'jp-Toolbar';
	/**
	 * The class name added to toolbar items.
	 */
	var TOOLBAR_ITEM_CLASS = 'jp-Toolbar-item';
	/**
	 * The class name added to toolbar buttons.
	 */
	var TOOLBAR_BUTTON_CLASS = 'jp-Toolbar-button';
	/**
	 * The class name added to a pressed button.
	 */
	var TOOLBAR_PRESSED_CLASS = 'jp-mod-pressed';
	/**
	 * A class which provides a toolbar widget.
	 */
	var Toolbar = (function (_super) {
	    __extends(Toolbar, _super);
	    /**
	     * Construct a new toolbar widget.
	     */
	    function Toolbar() {
	        _super.call(this);
	        this.addClass(TOOLBAR_CLASS);
	        this.layout = new panel_1.PanelLayout();
	    }
	    /**
	     * Get an iterator over the ordered toolbar item names.
	     *
	     * @returns An iterator over the toolbar item names.
	     */
	    Toolbar.prototype.names = function () {
	        var layout = this.layout;
	        return iteration_1.map(layout.widgets, function (widget) {
	            return Private.nameProperty.get(widget);
	        });
	    };
	    /**
	     * Add an item to the end of the toolbar.
	     *
	     * @param name - The name of the widget to add to the toolbar.
	     *
	     * @param widget - The widget to add to the toolbar.
	     *
	     * @param index - The optional name of the item to insert after.
	     *
	     * @returns Whether the item was added to toolbar.  Returns false if
	     *   an item of the same name is already in the toolbar.
	     */
	    Toolbar.prototype.addItem = function (name, widget) {
	        var layout = this.layout;
	        return this.insertItem(layout.widgets.length, name, widget);
	    };
	    /**
	     * Insert an item into the toolbar at the specified index.
	     *
	     * @param index - The index at which to insert the item.
	     *
	     * @param name - The name of the item.
	     *
	     * @param widget - The widget to add.
	     *
	     * @returns Whether the item was added to the toolbar. Returns false if
	     *   an item of the same name is already in the toolbar.
	     *
	     * #### Notes
	     * The index will be clamped to the bounds of the items.
	     */
	    Toolbar.prototype.insertItem = function (index, name, widget) {
	        var existing = searching_1.find(this.names(), function (value) { return value === name; });
	        if (existing) {
	            return false;
	        }
	        widget.addClass(TOOLBAR_ITEM_CLASS);
	        var layout = this.layout;
	        layout.insertWidget(index, widget);
	        Private.nameProperty.set(widget, name);
	        return true;
	    };
	    /**
	     * Remove an item in the toolbar by value.
	     *
	     *  @param name - The name of the widget to remove from the toolbar.
	     */
	    Toolbar.prototype.removeItem = function (widget) {
	        var layout = this.layout;
	        layout.removeWidget(widget);
	    };
	    return Toolbar;
	}(widget_1.Widget));
	exports.Toolbar = Toolbar;
	/**
	 * A widget which acts as a button in a toolbar.
	 */
	var ToolbarButton = (function (_super) {
	    __extends(ToolbarButton, _super);
	    /**
	     * Construct a new toolbar button.
	     */
	    function ToolbarButton(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this, { node: document.createElement('span') });
	        options = options || {};
	        this.addClass(TOOLBAR_BUTTON_CLASS);
	        this._onClick = options.onClick;
	        if (options.className) {
	            this.addClass(options.className);
	        }
	        this.node.title = options.tooltip || '';
	    }
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    ToolbarButton.prototype.dispose = function () {
	        this._onClick = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle the DOM events for the widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the dock panel's node. It should
	     * not be called directly by user code.
	     */
	    ToolbarButton.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'click':
	                if (this._onClick) {
	                    this._onClick();
	                }
	                break;
	            case 'mousedown':
	                this.addClass(TOOLBAR_PRESSED_CLASS);
	                break;
	            case 'mouseup':
	            case 'mouseout':
	                this.removeClass(TOOLBAR_PRESSED_CLASS);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle `after-attach` messages for the widget.
	     */
	    ToolbarButton.prototype.onAfterAttach = function (msg) {
	        this.node.addEventListener('click', this);
	        this.node.addEventListener('mousedown', this);
	        this.node.addEventListener('mouseup', this);
	        this.node.addEventListener('mouseout', this);
	    };
	    /**
	     * Handle `before_detach` messages for the widget.
	     */
	    ToolbarButton.prototype.onBeforeDetach = function (msg) {
	        this.node.removeEventListener('click', this);
	        this.node.removeEventListener('mousedown', this);
	        this.node.removeEventListener('mouseup', this);
	        this.node.removeEventListener('mouseout', this);
	    };
	    return ToolbarButton;
	}(widget_1.Widget));
	exports.ToolbarButton = ToolbarButton;
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * An attached property for the name of a toolbar item.
	     */
	    Private.nameProperty = new properties_1.AttachedProperty({ name: 'name' });
	})(Private || (Private = {}));
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/toolbar/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/rendermime/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/rendermime/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	var renderers_1 = __jupyter_require__('jupyterlab@0.15.1/lib/renderers/index.js');
	/* tslint:disable */
	/**
	 * The rendermime token.
	 */
	exports.IRenderMime = new token_1.Token('jupyter.services.rendermime');
	/**
	 * A composite renderer.
	 *
	 * #### Notes
	 * When rendering a mimebundle, a mimetype is selected from the mimetypes by
	 * searching through the `this.order` list. The first mimetype found in the
	 * bundle determines the renderer that will be used.
	 *
	 * You can add a renderer by adding it to the `renderers` object and
	 * registering the mimetype in the `order` array.
	 *
	 * Untrusted bundles are handled differently from trusted ones.  Untrusted
	 * bundles will only render outputs that can be rendered "safely"
	 * (see [[RenderMime.IRenderer.isSafe]]) or can be "sanitized"
	 * (see [[RenderMime.IRenderer.isSanitizable]]).
	 */
	var RenderMime = (function () {
	    /**
	     * Construct a renderer.
	     */
	    function RenderMime(options) {
	        this._renderers = Object.create(null);
	        this._sanitizer = null;
	        for (var mime in options.renderers) {
	            this._renderers[mime] = options.renderers[mime];
	        }
	        this._order = new vector_1.Vector(options.order);
	        this._sanitizer = options.sanitizer;
	        this._resolver = options.resolver || null;
	        this._handler = options.linkHandler || null;
	    }
	    Object.defineProperty(RenderMime.prototype, "resolver", {
	        /**
	         * The object used to resolve relative urls for the rendermime instance.
	         */
	        get: function () {
	            return this._resolver;
	        },
	        set: function (value) {
	            this._resolver = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(RenderMime.prototype, "linkHandler", {
	        /**
	         * The object used to handle path opening links.
	         */
	        get: function () {
	            return this._handler;
	        },
	        set: function (value) {
	            this._handler = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Get an iterator over the ordered list of mimetypes.
	     *
	     * #### Notes
	     * These mimetypes are searched from beginning to end, and the first matching
	     * mimetype is used.
	     */
	    RenderMime.prototype.mimetypes = function () {
	        return this._order.iter();
	    };
	    /**
	     * Render a mimebundle.
	     *
	     * @param bundle - the mimebundle to render.
	     *
	     * @param trusted - whether the bundle is trusted.
	     *
	     * #### Notes
	     * We select the preferred mimetype in bundle based on whether the output is
	     * trusted (see [[preferredMimetype]]), and then pass a sanitizer to the
	     * renderer if the output should be sanitized.
	     */
	    RenderMime.prototype.render = function (options) {
	        var trusted = options.trusted, bundle = options.bundle, injector = options.injector;
	        var mimetype = this.preferredMimetype(bundle, trusted);
	        if (!mimetype) {
	            return void 0;
	        }
	        var rendererOptions = {
	            mimetype: mimetype,
	            source: bundle[mimetype],
	            injector: injector,
	            resolver: this._resolver,
	            sanitizer: trusted ? null : this._sanitizer,
	            linkHandler: this._handler
	        };
	        return this._renderers[mimetype].render(rendererOptions);
	    };
	    /**
	     * Find the preferred mimetype in a mimebundle.
	     *
	     * @param bundle - the mimebundle giving available mimetype content.
	     *
	     * @param trusted - whether the bundle is trusted.
	     *
	     * #### Notes
	     * For untrusted bundles, only select mimetypes that can be rendered
	     * "safely"  (see [[RenderMime.IRenderer.isSafe]]) or can  be "sanitized"
	     * (see [[RenderMime.IRenderer.isSanitizable]]).
	     */
	    RenderMime.prototype.preferredMimetype = function (bundle, trusted) {
	        var _this = this;
	        if (trusted === void 0) { trusted = false; }
	        return searching_1.find(this._order, function (m) {
	            if (m in bundle) {
	                var renderer = _this._renderers[m];
	                if (trusted || renderer.isSafe(m) || renderer.isSanitizable(m)) {
	                    return true;
	                }
	            }
	        });
	    };
	    /**
	     * Clone the rendermime instance with shallow copies of data.
	     */
	    RenderMime.prototype.clone = function () {
	        return new RenderMime({
	            renderers: this._renderers,
	            order: this._order.iter(),
	            sanitizer: this._sanitizer,
	            linkHandler: this._handler
	        });
	    };
	    /**
	     * Add a renderer by mimetype.
	     *
	     * @param mimetype - The mimetype of the renderer.
	     * @param renderer - The renderer instance.
	     * @param index - The optional order index.
	     *
	     * ####Notes
	     * Negative indices count from the end, so -1 refers to the penultimate index.
	     * Use the index of `.order.length` to add to the end of the render precedence list,
	     * which would make the new renderer the last choice.
	     */
	    RenderMime.prototype.addRenderer = function (mimetype, renderer, index) {
	        if (index === void 0) { index = 0; }
	        this._renderers[mimetype] = renderer;
	        this._order.insert(index, mimetype);
	    };
	    /**
	     * Remove a renderer by mimetype.
	     *
	     * @param mimetype - The mimetype of the renderer.
	     */
	    RenderMime.prototype.removeRenderer = function (mimetype) {
	        delete this._renderers[mimetype];
	        this._order.remove(mimetype);
	    };
	    /**
	     * Get a renderer by mimetype.
	     *
	     * @param mimetype - The mimetype of the renderer.
	     *
	     * @returns The renderer for the given mimetype, or undefined if the mimetype is unknown.
	     */
	    RenderMime.prototype.getRenderer = function (mimetype) {
	        return this._renderers[mimetype];
	    };
	    return RenderMime;
	}());
	exports.RenderMime = RenderMime;
	/**
	 * The namespace for RenderMime statics.
	 */
	var RenderMime;
	(function (RenderMime) {
	    /**
	     * Default renderer order
	     */
	    function defaultRenderers() {
	        return [
	            new renderers_1.JavascriptRenderer(),
	            new renderers_1.HTMLRenderer(),
	            new renderers_1.MarkdownRenderer(),
	            new renderers_1.LatexRenderer(),
	            new renderers_1.SVGRenderer(),
	            new renderers_1.ImageRenderer(),
	            new renderers_1.PDFRenderer(),
	            new renderers_1.TextRenderer()
	        ];
	    }
	    RenderMime.defaultRenderers = defaultRenderers;
	    /**
	     * A default resolver that uses a session and a contents manager.
	     */
	    var UrlResolver = (function () {
	        /**
	         * Create a new url resolver for a console.
	         */
	        function UrlResolver(options) {
	            this._session = options.session;
	            this._contents = options.contents;
	        }
	        /**
	         * Resolve a relative url to a correct server path.
	         */
	        UrlResolver.prototype.resolveUrl = function (url) {
	            // Ignore urls that have a protocol.
	            if (services_1.utils.urlParse(url).protocol || url.indexOf('//') === 0) {
	                return Promise.resolve(url);
	            }
	            var path = this._session.path;
	            var cwd = services_1.ContentsManager.dirname(path);
	            path = services_1.ContentsManager.getAbsolutePath(url, cwd);
	            return Promise.resolve(path);
	        };
	        /**
	         * Get the download url of a given absolute server path.
	         */
	        UrlResolver.prototype.getDownloadUrl = function (path) {
	            // Ignore urls that have a protocol.
	            if (services_1.utils.urlParse(path).protocol || path.indexOf('//') === 0) {
	                return Promise.resolve(path);
	            }
	            return this._contents.getDownloadUrl(path);
	        };
	        return UrlResolver;
	    }());
	    RenderMime.UrlResolver = UrlResolver;
	})(RenderMime = exports.RenderMime || (exports.RenderMime = {}));
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/rendermime/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/renderers/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/renderers/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var widget_1 = __jupyter_require__('jupyterlab@0.15.1/lib/renderers/widget.js');
	/**
	 * A renderer for raw html.
	 */
	var HTMLRenderer = (function () {
	    function HTMLRenderer() {
	        /**
	         * The mimetypes this renderer accepts.
	         */
	        this.mimetypes = ['text/html'];
	    }
	    /**
	     * Whether the input can safely sanitized for a given mimetype.
	     */
	    HTMLRenderer.prototype.isSanitizable = function (mimetype) {
	        return this.mimetypes.indexOf(mimetype) !== -1;
	    };
	    /**
	     * Whether the input is safe without sanitization.
	     */
	    HTMLRenderer.prototype.isSafe = function (mimetype) {
	        return false;
	    };
	    /**
	     * Render the transformed mime bundle.
	     */
	    HTMLRenderer.prototype.render = function (options) {
	        return new widget_1.RenderedHTML(options);
	    };
	    return HTMLRenderer;
	}());
	exports.HTMLRenderer = HTMLRenderer;
	/**
	 * A renderer for `<img>` data.
	 */
	var ImageRenderer = (function () {
	    function ImageRenderer() {
	        /**
	         * The mimetypes this renderer accepts.
	         */
	        this.mimetypes = ['image/png', 'image/jpeg', 'image/gif'];
	    }
	    /**
	     * Whether the input can safely sanitized for a given mimetype.
	     */
	    ImageRenderer.prototype.isSanitizable = function (mimetype) {
	        return false;
	    };
	    /**
	     * Whether the input is safe without sanitization.
	     */
	    ImageRenderer.prototype.isSafe = function (mimetype) {
	        return this.mimetypes.indexOf(mimetype) !== -1;
	    };
	    /**
	     * Render the transformed mime bundle.
	     */
	    ImageRenderer.prototype.render = function (options) {
	        return new widget_1.RenderedImage(options);
	    };
	    return ImageRenderer;
	}());
	exports.ImageRenderer = ImageRenderer;
	/**
	 * A renderer for plain text and Jupyter console text data.
	 */
	var TextRenderer = (function () {
	    function TextRenderer() {
	        /**
	         * The mimetypes this renderer accepts.
	         */
	        this.mimetypes = ['text/plain', 'application/vnd.jupyter.console-text'];
	    }
	    /**
	     * Whether the input can safely sanitized for a given mimetype.
	     */
	    TextRenderer.prototype.isSanitizable = function (mimetype) {
	        return false;
	    };
	    /**
	     * Whether the input is safe without sanitization.
	     */
	    TextRenderer.prototype.isSafe = function (mimetype) {
	        return this.mimetypes.indexOf(mimetype) !== -1;
	    };
	    /**
	     * Render the transformed mime bundle.
	     */
	    TextRenderer.prototype.render = function (options) {
	        return new widget_1.RenderedText(options);
	    };
	    return TextRenderer;
	}());
	exports.TextRenderer = TextRenderer;
	/**
	 * A renderer for raw `<script>` data.
	 */
	var JavascriptRenderer = (function () {
	    function JavascriptRenderer() {
	        /**
	         * The mimetypes this renderer accepts.
	         */
	        this.mimetypes = ['text/javascript', 'application/javascript'];
	    }
	    /**
	     * Whether the input can safely sanitized for a given mimetype.
	     */
	    JavascriptRenderer.prototype.isSanitizable = function (mimetype) {
	        return false;
	    };
	    /**
	     * Whether the input is safe without sanitization.
	     */
	    JavascriptRenderer.prototype.isSafe = function (mimetype) {
	        return false;
	    };
	    /**
	     * Render the transformed mime bundle.
	     */
	    JavascriptRenderer.prototype.render = function (options) {
	        return new widget_1.RenderedJavascript(options);
	    };
	    return JavascriptRenderer;
	}());
	exports.JavascriptRenderer = JavascriptRenderer;
	/**
	 * A renderer for `<svg>` data.
	 */
	var SVGRenderer = (function () {
	    function SVGRenderer() {
	        /**
	         * The mimetypes this renderer accepts.
	         */
	        this.mimetypes = ['image/svg+xml'];
	    }
	    /**
	     * Whether the input can safely sanitized for a given mimetype.
	     */
	    SVGRenderer.prototype.isSanitizable = function (mimetype) {
	        return false;
	    };
	    /**
	     * Whether the input is safe without sanitization.
	     */
	    SVGRenderer.prototype.isSafe = function (mimetype) {
	        return false;
	    };
	    /**
	     * Render the transformed mime bundle.
	     */
	    SVGRenderer.prototype.render = function (options) {
	        return new widget_1.RenderedSVG(options);
	    };
	    return SVGRenderer;
	}());
	exports.SVGRenderer = SVGRenderer;
	/**
	 * A renderer for PDF data.
	 */
	var PDFRenderer = (function () {
	    function PDFRenderer() {
	        /**
	         * The mimetypes this renderer accepts.
	         */
	        this.mimetypes = ['application/pdf'];
	    }
	    /**
	     * Whether the input can safely sanitized for a given mimetype.
	     */
	    PDFRenderer.prototype.isSanitizable = function (mimetype) {
	        return false;
	    };
	    /**
	     * Whether the input is safe without sanitization.
	     */
	    PDFRenderer.prototype.isSafe = function (mimetype) {
	        return false;
	    };
	    /**
	     * Render the transformed mime bundle.
	     */
	    PDFRenderer.prototype.render = function (options) {
	        return new widget_1.RenderedPDF(options);
	    };
	    return PDFRenderer;
	}());
	exports.PDFRenderer = PDFRenderer;
	/**
	 * A renderer for LateX data.
	 */
	var LatexRenderer = (function () {
	    function LatexRenderer() {
	        /**
	         * The mimetypes this renderer accepts.
	         */
	        this.mimetypes = ['text/latex'];
	    }
	    /**
	     * Whether the input can safely sanitized for a given mimetype.
	     */
	    LatexRenderer.prototype.isSanitizable = function (mimetype) {
	        return false;
	    };
	    /**
	     * Whether the input is safe without sanitization.
	     */
	    LatexRenderer.prototype.isSafe = function (mimetype) {
	        return this.mimetypes.indexOf(mimetype) !== -1;
	    };
	    /**
	     * Render the mime bundle.
	     */
	    LatexRenderer.prototype.render = function (options) {
	        return new widget_1.RenderedLatex(options);
	    };
	    return LatexRenderer;
	}());
	exports.LatexRenderer = LatexRenderer;
	/**
	 * A renderer for Jupyter Markdown data.
	 */
	var MarkdownRenderer = (function () {
	    function MarkdownRenderer() {
	        /**
	         * The mimetypes this renderer accepts.
	         */
	        this.mimetypes = ['text/markdown'];
	    }
	    /**
	     * Whether the input can safely sanitized for a given mimetype.
	     */
	    MarkdownRenderer.prototype.isSanitizable = function (mimetype) {
	        return this.mimetypes.indexOf(mimetype) !== -1;
	    };
	    /**
	     * Whether the input is safe without sanitization.
	     */
	    MarkdownRenderer.prototype.isSafe = function (mimetype) {
	        return false;
	    };
	    /**
	     * Render the mime bundle.
	     */
	    MarkdownRenderer.prototype.render = function (options) {
	        return new widget_1.RenderedMarkdown(options);
	    };
	    return MarkdownRenderer;
	}());
	exports.MarkdownRenderer = MarkdownRenderer;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/renderers/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/renderers/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/renderers/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var ansi_up_1 = __jupyter_require__('ansi_up@^1.3.0/ansi_up.js');
	var CodeMirror = __jupyter_require__('codemirror@^5.20.2/lib/codemirror.js');
	__jupyter_require__('codemirror@^5.20.2/addon/runmode/runmode.js');
	var codemirror_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codemirror/index.js');
	var editor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codemirror/editor.js');
	var marked = __jupyter_require__('marked@^0.3.5/lib/marked.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var latex_1 = __jupyter_require__('jupyterlab@0.15.1/lib/renderers/latex.js');
	/*
	 * The class name added to common rendered HTML.
	 */
	exports.HTML_COMMON_CLASS = 'jp-RenderedHTMLCommon';
	/*
	 * The class name added to rendered HTML.
	 */
	var HTML_CLASS = 'jp-RenderedHTML';
	/*
	 * The class name added to rendered markdown.
	 */
	var MARKDOWN_CLASS = 'jp-RenderedMarkdown';
	/*
	 * The class name added to rendered Latex.
	 */
	var LATEX_CLASS = 'jp-RenderedLatex';
	/*
	 * The class name added to rendered images.
	 */
	var IMAGE_CLASS = 'jp-RenderedImage';
	/*
	 * The class name added to rendered text.
	 */
	var TEXT_CLASS = 'jp-RenderedText';
	/*
	 * The class name added to rendered javascript.
	 */
	var JAVASCRIPT_CLASS = 'jp-RenderedJavascript';
	/*
	 * The class name added to rendered SVG.
	 */
	var SVG_CLASS = 'jp-RenderedSVG';
	/*
	 * The class name added to rendered PDF.
	 */
	var PDF_CLASS = 'jp-RenderedPDF';
	// Support GitHub flavored Markdown, leave sanitizing to external library.
	marked.setOptions({
	    gfm: true,
	    sanitize: false,
	    tables: true,
	    // breaks: true; We can't use GFM breaks as it causes problems with HTML tables
	    langPrefix: "cm-s-" + editor_1.CodeMirrorEditor.DEFAULT_THEME + " language-",
	    highlight: function (code, lang, callback) {
	        if (!lang) {
	            // no language, no highlight
	            if (callback) {
	                callback(null, code);
	                return;
	            }
	            else {
	                return code;
	            }
	        }
	        codemirror_1.requireMode(lang).then(function (spec) {
	            var el = document.createElement('div');
	            if (!spec) {
	                console.log("No CodeMirror mode: " + lang);
	                callback(null, code);
	                return;
	            }
	            try {
	                CodeMirror.runMode(code, spec.mime, el);
	                callback(null, el.innerHTML);
	            }
	            catch (err) {
	                console.log("Failed to highlight " + lang + " code", err);
	                callback(err, code);
	            }
	        }).catch(function (err) {
	            console.log("No CodeMirror mode: " + lang);
	            console.log("Require CodeMirror mode error: " + err);
	            callback(null, code);
	        });
	    }
	});
	/*
	 * A widget for displaying any widget whoes representation is rendered HTML
	 * */
	var RenderedHTMLCommon = (function (_super) {
	    __extends(RenderedHTMLCommon, _super);
	    /* Construct a new rendered HTML common widget.*/
	    function RenderedHTMLCommon(options) {
	        _super.call(this);
	        this.addClass(exports.HTML_COMMON_CLASS);
	    }
	    return RenderedHTMLCommon;
	}(widget_1.Widget));
	exports.RenderedHTMLCommon = RenderedHTMLCommon;
	/**
	 * A widget for displaying HTML and rendering math.
	 */
	var RenderedHTML = (function (_super) {
	    __extends(RenderedHTML, _super);
	    /**
	     * Construct a new html widget.
	     */
	    function RenderedHTML(options) {
	        _super.call(this, options);
	        this._urlResolved = null;
	        this.addClass(HTML_CLASS);
	        var source = options.source;
	        if (options.sanitizer) {
	            source = options.sanitizer.sanitize(source);
	        }
	        appendHtml(this.node, source);
	        if (options.resolver) {
	            this._urlResolved = handleUrls(this.node, options.resolver, options.linkHandler);
	        }
	    }
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    RenderedHTML.prototype.onAfterAttach = function (msg) {
	        var _this = this;
	        this._urlResolved.then(function () { latex_1.typeset(_this.node); });
	    };
	    return RenderedHTML;
	}(RenderedHTMLCommon));
	exports.RenderedHTML = RenderedHTML;
	/**
	 * A widget for displaying Markdown with embeded latex.
	 */
	var RenderedMarkdown = (function (_super) {
	    __extends(RenderedMarkdown, _super);
	    /**
	     * Construct a new markdown widget.
	     */
	    function RenderedMarkdown(options) {
	        var _this = this;
	        _super.call(this, options);
	        this._rendered = false;
	        this._urlResolved = null;
	        this.addClass(MARKDOWN_CLASS);
	        var parts = latex_1.removeMath(options.source);
	        // Add the markdown content asynchronously.
	        marked(parts['text'], function (err, content) {
	            if (err) {
	                console.error(err);
	                return;
	            }
	            content = latex_1.replaceMath(content, parts['math']);
	            if (options.sanitizer) {
	                content = options.sanitizer.sanitize(content);
	            }
	            appendHtml(_this.node, content);
	            if (options.resolver) {
	                _this._urlResolved = handleUrls(_this.node, options.resolver, options.linkHandler);
	            }
	            _this.fit();
	            _this._rendered = true;
	            if (_this.isAttached) {
	                _this._urlResolved.then(function () { latex_1.typeset(_this.node); });
	            }
	        });
	    }
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    RenderedMarkdown.prototype.onAfterAttach = function (msg) {
	        if (this._rendered) {
	            latex_1.typeset(this.node);
	        }
	    };
	    return RenderedMarkdown;
	}(RenderedHTMLCommon));
	exports.RenderedMarkdown = RenderedMarkdown;
	/**
	 * A widget for displaying LaTeX output.
	 */
	var RenderedLatex = (function (_super) {
	    __extends(RenderedLatex, _super);
	    /**
	     * Construct a new latex widget.
	     */
	    function RenderedLatex(options) {
	        _super.call(this);
	        this.node.textContent = options.source;
	        this.addClass(LATEX_CLASS);
	    }
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    RenderedLatex.prototype.onAfterAttach = function (msg) {
	        latex_1.typeset(this.node);
	    };
	    return RenderedLatex;
	}(widget_1.Widget));
	exports.RenderedLatex = RenderedLatex;
	var RenderedImage = (function (_super) {
	    __extends(RenderedImage, _super);
	    function RenderedImage(options) {
	        _super.call(this);
	        var img = document.createElement('img');
	        img.src = "data:" + options.mimetype + ";base64," + options.source;
	        this.node.appendChild(img);
	        this.addClass(IMAGE_CLASS);
	    }
	    return RenderedImage;
	}(widget_1.Widget));
	exports.RenderedImage = RenderedImage;
	var RenderedText = (function (_super) {
	    __extends(RenderedText, _super);
	    function RenderedText(options) {
	        _super.call(this);
	        var data = ansi_up_1.escape_for_html(options.source);
	        var pre = document.createElement('pre');
	        pre.innerHTML = ansi_up_1.ansi_to_html(data);
	        this.node.appendChild(pre);
	        this.addClass(TEXT_CLASS);
	    }
	    return RenderedText;
	}(widget_1.Widget));
	exports.RenderedText = RenderedText;
	var RenderedJavascript = (function (_super) {
	    __extends(RenderedJavascript, _super);
	    function RenderedJavascript(options) {
	        _super.call(this);
	        var s = document.createElement('script');
	        s.type = options.mimetype;
	        s.textContent = options.source;
	        this.node.appendChild(s);
	        this.addClass(JAVASCRIPT_CLASS);
	    }
	    return RenderedJavascript;
	}(widget_1.Widget));
	exports.RenderedJavascript = RenderedJavascript;
	var RenderedSVG = (function (_super) {
	    __extends(RenderedSVG, _super);
	    function RenderedSVG(options) {
	        _super.call(this);
	        this._urlResolved = null;
	        this.node.innerHTML = options.source;
	        var svgElement = this.node.getElementsByTagName('svg')[0];
	        if (!svgElement) {
	            throw new Error('SVGRender: Error: Failed to create <svg> element');
	        }
	        if (options.resolver) {
	            this._urlResolved = handleUrls(this.node, options.resolver, options.linkHandler);
	        }
	        this.addClass(SVG_CLASS);
	    }
	    return RenderedSVG;
	}(widget_1.Widget));
	exports.RenderedSVG = RenderedSVG;
	var RenderedPDF = (function (_super) {
	    __extends(RenderedPDF, _super);
	    function RenderedPDF(options) {
	        _super.call(this);
	        var a = document.createElement('a');
	        a.target = '_blank';
	        a.textContent = 'View PDF';
	        a.href = 'data:application/pdf;base64,' + options.source;
	        this.node.appendChild(a);
	        this.addClass(PDF_CLASS);
	    }
	    return RenderedPDF;
	}(widget_1.Widget));
	exports.RenderedPDF = RenderedPDF;
	/**
	 * Resolve the relative urls in element `src` and `href` attributes.
	 *
	 * @param node - The head html element.
	 *
	 * @param resolver - A url resolver.
	 *
	 * @param linkHandler - An optional link handler for nodes.
	 *
	 * @returns a promise fulfilled when the relative urls have been resolved.
	 */
	function handleUrls(node, resolver, linkHandler) {
	    var promises = [];
	    // Handle HTML Elements with src attributes.
	    var nodes = node.querySelectorAll('*[src]');
	    for (var i = 0; i < nodes.length; i++) {
	        promises.push(handleAttr(nodes[i], 'src', resolver));
	    }
	    var anchors = node.getElementsByTagName('a');
	    for (var i = 0; i < anchors.length; i++) {
	        promises.push(handleAnchor(anchors[i], resolver, linkHandler || null));
	    }
	    var links = node.getElementsByTagName('link');
	    for (var i = 0; i < links.length; i++) {
	        promises.push(handleAttr(links[i], 'href', resolver));
	    }
	    return Promise.all(promises).then(function () { return void 0; });
	}
	exports.handleUrls = handleUrls;
	/**
	 * Handle a node with a `src` or `href` attribute.
	 */
	function handleAttr(node, name, resolver) {
	    var source = node.getAttribute(name);
	    if (!source) {
	        return Promise.resolve(void 0);
	    }
	    node.setAttribute(name, '');
	    return resolver.resolveUrl(source).then(function (path) {
	        return resolver.getDownloadUrl(path);
	    }).then(function (url) {
	        node.setAttribute(name, url);
	    });
	}
	/**
	 * Handle an anchor node.
	 */
	function handleAnchor(anchor, resolver, linkHandler) {
	    anchor.target = '_blank';
	    var href = anchor.getAttribute('href');
	    if (!href) {
	        return Promise.resolve(void 0);
	    }
	    return resolver.resolveUrl(href).then(function (path) {
	        if (linkHandler) {
	            linkHandler.handleLink(anchor, path);
	        }
	        return resolver.getDownloadUrl(path);
	    }).then(function (url) {
	        anchor.href = url;
	    });
	}
	/**
	 * Append trusted html to a node.
	 */
	function appendHtml(node, html) {
	    try {
	        var range = document.createRange();
	        node.appendChild(range.createContextualFragment(html));
	    }
	    catch (error) {
	        console.warn('Environment does not support Range ' +
	            'createContextualFragment, falling back on innerHTML');
	        node.innerHTML = html;
	    }
	}
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/renderers/widget.js **/


/** START DEFINE BLOCK for ansi_up@1.3.0/ansi_up.js **/
jupyter.define('ansi_up@1.3.0/ansi_up.js', function (module, exports, __jupyter_require__) {
	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// ansi_up.js
	// version : 1.3.0
	// author : Dru Nelson
	// license : MIT
	// http://github.com/drudru/ansi_up
	
	(function (Date, undefined) {
	
	    var ansi_up,
	        VERSION = "1.3.0",
	
	        // check for nodeJS
	        hasModule = (typeof module !== 'undefined'),
	
	        // Normal and then Bright
	        ANSI_COLORS = [
	          [
	            { color: "0, 0, 0",        'class': "ansi-black"   },
	            { color: "187, 0, 0",      'class': "ansi-red"     },
	            { color: "0, 187, 0",      'class': "ansi-green"   },
	            { color: "187, 187, 0",    'class': "ansi-yellow"  },
	            { color: "0, 0, 187",      'class': "ansi-blue"    },
	            { color: "187, 0, 187",    'class': "ansi-magenta" },
	            { color: "0, 187, 187",    'class': "ansi-cyan"    },
	            { color: "255,255,255",    'class': "ansi-white"   }
	          ],
	          [
	            { color: "85, 85, 85",     'class': "ansi-bright-black"   },
	            { color: "255, 85, 85",    'class': "ansi-bright-red"     },
	            { color: "0, 255, 0",      'class': "ansi-bright-green"   },
	            { color: "255, 255, 85",   'class': "ansi-bright-yellow"  },
	            { color: "85, 85, 255",    'class': "ansi-bright-blue"    },
	            { color: "255, 85, 255",   'class': "ansi-bright-magenta" },
	            { color: "85, 255, 255",   'class': "ansi-bright-cyan"    },
	            { color: "255, 255, 255",  'class': "ansi-bright-white"   }
	          ]
	        ],
	
	        // 256 Colors Palette
	        PALETTE_COLORS;
	
	    function Ansi_Up() {
	      this.fg = this.bg = this.fg_truecolor = this.bg_truecolor = null;
	      this.bright = 0;
	    }
	
	    Ansi_Up.prototype.setup_palette = function() {
	      PALETTE_COLORS = [];
	      // Index 0..15 : System color
	      (function() {
	        var i, j;
	        for (i = 0; i < 2; ++i) {
	          for (j = 0; j < 8; ++j) {
	            PALETTE_COLORS.push(ANSI_COLORS[i][j]['color']);
	          }
	        }
	      })();
	
	      // Index 16..231 : RGB 6x6x6
	      // https://gist.github.com/jasonm23/2868981#file-xterm-256color-yaml
	      (function() {
	        var levels = [0, 95, 135, 175, 215, 255];
	        var format = function (r, g, b) { return levels[r] + ', ' + levels[g] + ', ' + levels[b] };
	        var r, g, b;
	        for (r = 0; r < 6; ++r) {
	          for (g = 0; g < 6; ++g) {
	            for (b = 0; b < 6; ++b) {
	              PALETTE_COLORS.push(format.call(this, r, g, b));
	            }
	          }
	        }
	      })();
	
	      // Index 232..255 : Grayscale
	      (function() {
	        var level = 8;
	        var format = function(level) { return level + ', ' + level + ', ' + level };
	        var i;
	        for (i = 0; i < 24; ++i, level += 10) {
	          PALETTE_COLORS.push(format.call(this, level));
	        }
	      })();
	    };
	
	    Ansi_Up.prototype.escape_for_html = function (txt) {
	      return txt.replace(/[&<>]/gm, function(str) {
	        if (str == "&") return "&amp;";
	        if (str == "<") return "&lt;";
	        if (str == ">") return "&gt;";
	      });
	    };
	
	    Ansi_Up.prototype.linkify = function (txt) {
	      return txt.replace(/(https?:\/\/[^\s]+)/gm, function(str) {
	        return "<a href=\"" + str + "\">" + str + "</a>";
	      });
	    };
	
	    Ansi_Up.prototype.ansi_to_html = function (txt, options) {
	      return this.process(txt, options, true);
	    };
	
	    Ansi_Up.prototype.ansi_to_text = function (txt) {
	      var options = {};
	      return this.process(txt, options, false);
	    };
	
	    Ansi_Up.prototype.process = function (txt, options, markup) {
	      var self = this;
	      var raw_text_chunks = txt.split(/\033\[/);
	      var first_chunk = raw_text_chunks.shift(); // the first chunk is not the result of the split
	
	      var color_chunks = raw_text_chunks.map(function (chunk) {
	        return self.process_chunk(chunk, options, markup);
	      });
	
	      color_chunks.unshift(first_chunk);
	
	      return color_chunks.join('');
	    };
	
	    Ansi_Up.prototype.process_chunk = function (text, options, markup) {
	
	      // Are we using classes or styles?
	      options = typeof options == 'undefined' ? {} : options;
	      var use_classes = typeof options.use_classes != 'undefined' && options.use_classes;
	      var key = use_classes ? 'class' : 'color';
	
	      // Each 'chunk' is the text after the CSI (ESC + '[') and before the next CSI/EOF.
	      //
	      // This regex matches four groups within a chunk.
	      //
	      // The first and third groups match code type.
	      // We supported only SGR command. It has empty first group and 'm' in third.
	      //
	      // The second group matches all of the number+semicolon command sequences
	      // before the 'm' (or other trailing) character.
	      // These are the graphics or SGR commands.
	      //
	      // The last group is the text (including newlines) that is colored by
	      // the other group's commands.
	      var matches = text.match(/^([!\x3c-\x3f]*)([\d;]*)([\x20-\x2c]*[\x40-\x7e])([\s\S]*)/m);
	
	      if (!matches) return text;
	
	      var orig_txt = matches[4];
	      var nums = matches[2].split(';');
	
	      // We currently support only "SGR" (Select Graphic Rendition)
	      // Simply ignore if not a SGR command.
	      if (matches[1] !== '' || matches[3] !== 'm') {
	        return orig_txt;
	      }
	
	      if (!markup) {
	        return orig_txt;
	      }
	
	      var self = this;
	
	      while (nums.length > 0) {
	        var num_str = nums.shift();
	        var num = parseInt(num_str);
	
	        if (isNaN(num) || num === 0) {
	          self.fg = self.bg = null;
	          self.bright = 0;
	        } else if (num === 1) {
	          self.bright = 1;
	        } else if (num == 39) {
	          self.fg = null;
	        } else if (num == 49) {
	          self.bg = null;
	        } else if ((num >= 30) && (num < 38)) {
	          self.fg = ANSI_COLORS[self.bright][(num % 10)][key];
	        } else if ((num >= 90) && (num < 98)) {
	          self.fg = ANSI_COLORS[1][(num % 10)][key];
	        } else if ((num >= 40) && (num < 48)) {
	          self.bg = ANSI_COLORS[0][(num % 10)][key];
	        } else if ((num >= 100) && (num < 108)) {
	          self.bg = ANSI_COLORS[1][(num % 10)][key];
	        } else if (num === 38 || num === 48) { // extend color (38=fg, 48=bg)
	          (function() {
	            var is_foreground = (num === 38);
	            if (nums.length >= 1) {
	              var mode = nums.shift();
	              if (mode === '5' && nums.length >= 1) { // palette color
	                var palette_index = parseInt(nums.shift());
	                if (palette_index >= 0 && palette_index <= 255) {
	                  if (!use_classes) {
	                    if (!PALETTE_COLORS) {
	                      self.setup_palette.call(self);
	                    }
	                    if (is_foreground) {
	                      self.fg = PALETTE_COLORS[palette_index];
	                    } else {
	                      self.bg = PALETTE_COLORS[palette_index];
	                    }
	                  } else {
	                    var klass = (palette_index >= 16)
	                          ? ('ansi-palette-' + palette_index)
	                          : ANSI_COLORS[palette_index > 7 ? 1 : 0][palette_index % 8]['class'];
	                    if (is_foreground) {
	                      self.fg = klass;
	                    } else {
	                      self.bg = klass;
	                    }
	                  }
	                }
	              } else if(mode === '2' && nums.length >= 3) { // true color
	                var r = parseInt(nums.shift());
	                var g = parseInt(nums.shift());
	                var b = parseInt(nums.shift());
	                if ((r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255)) {
	                  var color = r + ', ' + g + ', ' + b;
	                  if (!use_classes) {
	                    if (is_foreground) {
	                      self.fg = color;
	                    } else {
	                      self.bg = color;
	                    }
	                  } else {
	                    if (is_foreground) {
	                      self.fg = 'ansi-truecolor';
	                      self.fg_truecolor = color;
	                    } else {
	                      self.bg = 'ansi-truecolor';
	                      self.bg_truecolor = color;
	                    }
	                  }
	                }
	              }
	            }
	          })();
	        }
	      }
	
	      if ((self.fg === null) && (self.bg === null)) {
	        return orig_txt;
	      } else {
	        var styles = [];
	        var classes = [];
	        var data = {};
	        var render_data = function (data) {
	          var fragments = [];
	          var key;
	          for (key in data) {
	            if (data.hasOwnProperty(key)) {
	              fragments.push('data-' + key + '="' + this.escape_for_html(data[key]) + '"');
	            }
	          }
	          return fragments.length > 0 ? ' ' + fragments.join(' ') : '';
	        };
	
	        if (self.fg) {
	          if (use_classes) {
	            classes.push(self.fg + "-fg");
	            if (self.fg_truecolor !== null) {
	              data['ansi-truecolor-fg'] = self.fg_truecolor;
	              self.fg_truecolor = null;
	            }
	          } else {
	            styles.push("color:rgb(" + self.fg + ")");
	          }
	        }
	        if (self.bg) {
	          if (use_classes) {
	            classes.push(self.bg + "-bg");
	            if (self.bg_truecolor !== null) {
	              data['ansi-truecolor-bg'] = self.bg_truecolor;
	              self.bg_truecolor = null;
	            }
	          } else {
	            styles.push("background-color:rgb(" + self.bg + ")");
	          }
	        }
	        if (use_classes) {
	          return '<span class="' + classes.join(' ') + '"' + render_data.call(self, data) + '>' + orig_txt + '</span>';
	        } else {
	          return '<span style="' + styles.join(';') + '"' + render_data.call(self, data) + '>' + orig_txt + '</span>';
	        }
	      }
	    };
	
	    // Module exports
	    ansi_up = {
	
	      escape_for_html: function (txt) {
	        var a2h = new Ansi_Up();
	        return a2h.escape_for_html(txt);
	      },
	
	      linkify: function (txt) {
	        var a2h = new Ansi_Up();
	        return a2h.linkify(txt);
	      },
	
	      ansi_to_html: function (txt, options) {
	        var a2h = new Ansi_Up();
	        return a2h.ansi_to_html(txt, options);
	      },
	
	      ansi_to_text: function (txt) {
	        var a2h = new Ansi_Up();
	        return a2h.ansi_to_text(txt);
	      },
	
	      ansi_to_html_obj: function () {
	        return new Ansi_Up();
	      }
	    };
	
	    // CommonJS module is defined
	    if (hasModule) {
	        module.exports = ansi_up;
	    }
	    /*global ender:false */
	    if (typeof window !== 'undefined' && typeof ender === 'undefined') {
	        window.ansi_up = ansi_up;
	    }
	    /*global define:false */
	    if (true) {
	        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function () {
	            return ansi_up;
	        }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	    }
	})(Date);
	
})
/** END DEFINE BLOCK for ansi_up@1.3.0/ansi_up.js **/


/** START DEFINE BLOCK for codemirror@5.23.0/addon/runmode/runmode.js **/
jupyter.define('codemirror@5.23.0/addon/runmode/runmode.js', function (module, exports, __jupyter_require__) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: http://codemirror.net/LICENSE
	
	(function(mod) {
	  if (true) // CommonJS
	    mod(__jupyter_require__('codemirror@5.23.0/lib/codemirror.js'));
	  else if (typeof define == "function" && define.amd) // AMD
	    define(["../../lib/codemirror"], mod);
	  else // Plain browser env
	    mod(CodeMirror);
	})(function(CodeMirror) {
	"use strict";
	
	CodeMirror.runMode = function(string, modespec, callback, options) {
	  var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
	  var ie = /MSIE \d/.test(navigator.userAgent);
	  var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
	
	  if (callback.appendChild) {
	    var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
	    var node = callback, col = 0;
	    node.innerHTML = "";
	    callback = function(text, style) {
	      if (text == "\n") {
	        // Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
	        // Emitting a carriage return makes everything ok.
	        node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
	        col = 0;
	        return;
	      }
	      var content = "";
	      // replace tabs
	      for (var pos = 0;;) {
	        var idx = text.indexOf("\t", pos);
	        if (idx == -1) {
	          content += text.slice(pos);
	          col += text.length - pos;
	          break;
	        } else {
	          col += idx - pos;
	          content += text.slice(pos, idx);
	          var size = tabSize - col % tabSize;
	          col += size;
	          for (var i = 0; i < size; ++i) content += " ";
	          pos = idx + 1;
	        }
	      }
	
	      if (style) {
	        var sp = node.appendChild(document.createElement("span"));
	        sp.className = "cm-" + style.replace(/ +/g, " cm-");
	        sp.appendChild(document.createTextNode(content));
	      } else {
	        node.appendChild(document.createTextNode(content));
	      }
	    };
	  }
	
	  var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
	  for (var i = 0, e = lines.length; i < e; ++i) {
	    if (i) callback("\n");
	    var stream = new CodeMirror.StringStream(lines[i]);
	    if (!stream.string && mode.blankLine) mode.blankLine(state);
	    while (!stream.eol()) {
	      var style = mode.token(stream, state);
	      callback(stream.current(), style, i, stream.start, state);
	      stream.start = stream.pos;
	    }
	  }
	};
	
	});
	
})
/** END DEFINE BLOCK for codemirror@5.23.0/addon/runmode/runmode.js **/


/** START DEFINE BLOCK for marked@0.3.6/lib/marked.js **/
jupyter.define('marked@0.3.6/lib/marked.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(global) {/**
	 * marked - a markdown parser
	 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
	 * https://github.com/chjj/marked
	 */
	
	;(function() {
	
	/**
	 * Block-Level Grammar
	 */
	
	var block = {
	  newline: /^\n+/,
	  code: /^( {4}[^\n]+\n*)+/,
	  fences: noop,
	  hr: /^( *[-*_]){3,} *(?:\n+|$)/,
	  heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
	  nptable: noop,
	  lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
	  blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
	  list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
	  html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
	  def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
	  table: noop,
	  paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
	  text: /^[^\n]+/
	};
	
	block.bullet = /(?:[*+-]|\d+\.)/;
	block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
	block.item = replace(block.item, 'gm')
	  (/bull/g, block.bullet)
	  ();
	
	block.list = replace(block.list)
	  (/bull/g, block.bullet)
	  ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
	  ('def', '\\n+(?=' + block.def.source + ')')
	  ();
	
	block.blockquote = replace(block.blockquote)
	  ('def', block.def)
	  ();
	
	block._tag = '(?!(?:'
	  + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
	  + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
	  + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
	
	block.html = replace(block.html)
	  ('comment', /<!--[\s\S]*?-->/)
	  ('closed', /<(tag)[\s\S]+?<\/\1>/)
	  ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
	  (/tag/g, block._tag)
	  ();
	
	block.paragraph = replace(block.paragraph)
	  ('hr', block.hr)
	  ('heading', block.heading)
	  ('lheading', block.lheading)
	  ('blockquote', block.blockquote)
	  ('tag', '<' + block._tag)
	  ('def', block.def)
	  ();
	
	/**
	 * Normal Block Grammar
	 */
	
	block.normal = merge({}, block);
	
	/**
	 * GFM Block Grammar
	 */
	
	block.gfm = merge({}, block.normal, {
	  fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
	  paragraph: /^/,
	  heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
	});
	
	block.gfm.paragraph = replace(block.paragraph)
	  ('(?!', '(?!'
	    + block.gfm.fences.source.replace('\\1', '\\2') + '|'
	    + block.list.source.replace('\\1', '\\3') + '|')
	  ();
	
	/**
	 * GFM + Tables Block Grammar
	 */
	
	block.tables = merge({}, block.gfm, {
	  nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
	  table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
	});
	
	/**
	 * Block Lexer
	 */
	
	function Lexer(options) {
	  this.tokens = [];
	  this.tokens.links = {};
	  this.options = options || marked.defaults;
	  this.rules = block.normal;
	
	  if (this.options.gfm) {
	    if (this.options.tables) {
	      this.rules = block.tables;
	    } else {
	      this.rules = block.gfm;
	    }
	  }
	}
	
	/**
	 * Expose Block Rules
	 */
	
	Lexer.rules = block;
	
	/**
	 * Static Lex Method
	 */
	
	Lexer.lex = function(src, options) {
	  var lexer = new Lexer(options);
	  return lexer.lex(src);
	};
	
	/**
	 * Preprocessing
	 */
	
	Lexer.prototype.lex = function(src) {
	  src = src
	    .replace(/\r\n|\r/g, '\n')
	    .replace(/\t/g, '    ')
	    .replace(/\u00a0/g, ' ')
	    .replace(/\u2424/g, '\n');
	
	  return this.token(src, true);
	};
	
	/**
	 * Lexing
	 */
	
	Lexer.prototype.token = function(src, top, bq) {
	  var src = src.replace(/^ +$/gm, '')
	    , next
	    , loose
	    , cap
	    , bull
	    , b
	    , item
	    , space
	    , i
	    , l;
	
	  while (src) {
	    // newline
	    if (cap = this.rules.newline.exec(src)) {
	      src = src.substring(cap[0].length);
	      if (cap[0].length > 1) {
	        this.tokens.push({
	          type: 'space'
	        });
	      }
	    }
	
	    // code
	    if (cap = this.rules.code.exec(src)) {
	      src = src.substring(cap[0].length);
	      cap = cap[0].replace(/^ {4}/gm, '');
	      this.tokens.push({
	        type: 'code',
	        text: !this.options.pedantic
	          ? cap.replace(/\n+$/, '')
	          : cap
	      });
	      continue;
	    }
	
	    // fences (gfm)
	    if (cap = this.rules.fences.exec(src)) {
	      src = src.substring(cap[0].length);
	      this.tokens.push({
	        type: 'code',
	        lang: cap[2],
	        text: cap[3] || ''
	      });
	      continue;
	    }
	
	    // heading
	    if (cap = this.rules.heading.exec(src)) {
	      src = src.substring(cap[0].length);
	      this.tokens.push({
	        type: 'heading',
	        depth: cap[1].length,
	        text: cap[2]
	      });
	      continue;
	    }
	
	    // table no leading pipe (gfm)
	    if (top && (cap = this.rules.nptable.exec(src))) {
	      src = src.substring(cap[0].length);
	
	      item = {
	        type: 'table',
	        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
	        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
	        cells: cap[3].replace(/\n$/, '').split('\n')
	      };
	
	      for (i = 0; i < item.align.length; i++) {
	        if (/^ *-+: *$/.test(item.align[i])) {
	          item.align[i] = 'right';
	        } else if (/^ *:-+: *$/.test(item.align[i])) {
	          item.align[i] = 'center';
	        } else if (/^ *:-+ *$/.test(item.align[i])) {
	          item.align[i] = 'left';
	        } else {
	          item.align[i] = null;
	        }
	      }
	
	      for (i = 0; i < item.cells.length; i++) {
	        item.cells[i] = item.cells[i].split(/ *\| */);
	      }
	
	      this.tokens.push(item);
	
	      continue;
	    }
	
	    // lheading
	    if (cap = this.rules.lheading.exec(src)) {
	      src = src.substring(cap[0].length);
	      this.tokens.push({
	        type: 'heading',
	        depth: cap[2] === '=' ? 1 : 2,
	        text: cap[1]
	      });
	      continue;
	    }
	
	    // hr
	    if (cap = this.rules.hr.exec(src)) {
	      src = src.substring(cap[0].length);
	      this.tokens.push({
	        type: 'hr'
	      });
	      continue;
	    }
	
	    // blockquote
	    if (cap = this.rules.blockquote.exec(src)) {
	      src = src.substring(cap[0].length);
	
	      this.tokens.push({
	        type: 'blockquote_start'
	      });
	
	      cap = cap[0].replace(/^ *> ?/gm, '');
	
	      // Pass `top` to keep the current
	      // "toplevel" state. This is exactly
	      // how markdown.pl works.
	      this.token(cap, top, true);
	
	      this.tokens.push({
	        type: 'blockquote_end'
	      });
	
	      continue;
	    }
	
	    // list
	    if (cap = this.rules.list.exec(src)) {
	      src = src.substring(cap[0].length);
	      bull = cap[2];
	
	      this.tokens.push({
	        type: 'list_start',
	        ordered: bull.length > 1
	      });
	
	      // Get each top-level item.
	      cap = cap[0].match(this.rules.item);
	
	      next = false;
	      l = cap.length;
	      i = 0;
	
	      for (; i < l; i++) {
	        item = cap[i];
	
	        // Remove the list item's bullet
	        // so it is seen as the next token.
	        space = item.length;
	        item = item.replace(/^ *([*+-]|\d+\.) +/, '');
	
	        // Outdent whatever the
	        // list item contains. Hacky.
	        if (~item.indexOf('\n ')) {
	          space -= item.length;
	          item = !this.options.pedantic
	            ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
	            : item.replace(/^ {1,4}/gm, '');
	        }
	
	        // Determine whether the next list item belongs here.
	        // Backpedal if it does not belong in this list.
	        if (this.options.smartLists && i !== l - 1) {
	          b = block.bullet.exec(cap[i + 1])[0];
	          if (bull !== b && !(bull.length > 1 && b.length > 1)) {
	            src = cap.slice(i + 1).join('\n') + src;
	            i = l - 1;
	          }
	        }
	
	        // Determine whether item is loose or not.
	        // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
	        // for discount behavior.
	        loose = next || /\n\n(?!\s*$)/.test(item);
	        if (i !== l - 1) {
	          next = item.charAt(item.length - 1) === '\n';
	          if (!loose) loose = next;
	        }
	
	        this.tokens.push({
	          type: loose
	            ? 'loose_item_start'
	            : 'list_item_start'
	        });
	
	        // Recurse.
	        this.token(item, false, bq);
	
	        this.tokens.push({
	          type: 'list_item_end'
	        });
	      }
	
	      this.tokens.push({
	        type: 'list_end'
	      });
	
	      continue;
	    }
	
	    // html
	    if (cap = this.rules.html.exec(src)) {
	      src = src.substring(cap[0].length);
	      this.tokens.push({
	        type: this.options.sanitize
	          ? 'paragraph'
	          : 'html',
	        pre: !this.options.sanitizer
	          && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
	        text: cap[0]
	      });
	      continue;
	    }
	
	    // def
	    if ((!bq && top) && (cap = this.rules.def.exec(src))) {
	      src = src.substring(cap[0].length);
	      this.tokens.links[cap[1].toLowerCase()] = {
	        href: cap[2],
	        title: cap[3]
	      };
	      continue;
	    }
	
	    // table (gfm)
	    if (top && (cap = this.rules.table.exec(src))) {
	      src = src.substring(cap[0].length);
	
	      item = {
	        type: 'table',
	        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
	        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
	        cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
	      };
	
	      for (i = 0; i < item.align.length; i++) {
	        if (/^ *-+: *$/.test(item.align[i])) {
	          item.align[i] = 'right';
	        } else if (/^ *:-+: *$/.test(item.align[i])) {
	          item.align[i] = 'center';
	        } else if (/^ *:-+ *$/.test(item.align[i])) {
	          item.align[i] = 'left';
	        } else {
	          item.align[i] = null;
	        }
	      }
	
	      for (i = 0; i < item.cells.length; i++) {
	        item.cells[i] = item.cells[i]
	          .replace(/^ *\| *| *\| *$/g, '')
	          .split(/ *\| */);
	      }
	
	      this.tokens.push(item);
	
	      continue;
	    }
	
	    // top-level paragraph
	    if (top && (cap = this.rules.paragraph.exec(src))) {
	      src = src.substring(cap[0].length);
	      this.tokens.push({
	        type: 'paragraph',
	        text: cap[1].charAt(cap[1].length - 1) === '\n'
	          ? cap[1].slice(0, -1)
	          : cap[1]
	      });
	      continue;
	    }
	
	    // text
	    if (cap = this.rules.text.exec(src)) {
	      // Top-level should never reach here.
	      src = src.substring(cap[0].length);
	      this.tokens.push({
	        type: 'text',
	        text: cap[0]
	      });
	      continue;
	    }
	
	    if (src) {
	      throw new
	        Error('Infinite loop on byte: ' + src.charCodeAt(0));
	    }
	  }
	
	  return this.tokens;
	};
	
	/**
	 * Inline-Level Grammar
	 */
	
	var inline = {
	  escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
	  autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
	  url: noop,
	  tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
	  link: /^!?\[(inside)\]\(href\)/,
	  reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
	  nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
	  strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
	  em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
	  code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
	  br: /^ {2,}\n(?!\s*$)/,
	  del: noop,
	  text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
	};
	
	inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
	inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
	
	inline.link = replace(inline.link)
	  ('inside', inline._inside)
	  ('href', inline._href)
	  ();
	
	inline.reflink = replace(inline.reflink)
	  ('inside', inline._inside)
	  ();
	
	/**
	 * Normal Inline Grammar
	 */
	
	inline.normal = merge({}, inline);
	
	/**
	 * Pedantic Inline Grammar
	 */
	
	inline.pedantic = merge({}, inline.normal, {
	  strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
	  em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
	});
	
	/**
	 * GFM Inline Grammar
	 */
	
	inline.gfm = merge({}, inline.normal, {
	  escape: replace(inline.escape)('])', '~|])')(),
	  url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
	  del: /^~~(?=\S)([\s\S]*?\S)~~/,
	  text: replace(inline.text)
	    (']|', '~]|')
	    ('|', '|https?://|')
	    ()
	});
	
	/**
	 * GFM + Line Breaks Inline Grammar
	 */
	
	inline.breaks = merge({}, inline.gfm, {
	  br: replace(inline.br)('{2,}', '*')(),
	  text: replace(inline.gfm.text)('{2,}', '*')()
	});
	
	/**
	 * Inline Lexer & Compiler
	 */
	
	function InlineLexer(links, options) {
	  this.options = options || marked.defaults;
	  this.links = links;
	  this.rules = inline.normal;
	  this.renderer = this.options.renderer || new Renderer;
	  this.renderer.options = this.options;
	
	  if (!this.links) {
	    throw new
	      Error('Tokens array requires a `links` property.');
	  }
	
	  if (this.options.gfm) {
	    if (this.options.breaks) {
	      this.rules = inline.breaks;
	    } else {
	      this.rules = inline.gfm;
	    }
	  } else if (this.options.pedantic) {
	    this.rules = inline.pedantic;
	  }
	}
	
	/**
	 * Expose Inline Rules
	 */
	
	InlineLexer.rules = inline;
	
	/**
	 * Static Lexing/Compiling Method
	 */
	
	InlineLexer.output = function(src, links, options) {
	  var inline = new InlineLexer(links, options);
	  return inline.output(src);
	};
	
	/**
	 * Lexing/Compiling
	 */
	
	InlineLexer.prototype.output = function(src) {
	  var out = ''
	    , link
	    , text
	    , href
	    , cap;
	
	  while (src) {
	    // escape
	    if (cap = this.rules.escape.exec(src)) {
	      src = src.substring(cap[0].length);
	      out += cap[1];
	      continue;
	    }
	
	    // autolink
	    if (cap = this.rules.autolink.exec(src)) {
	      src = src.substring(cap[0].length);
	      if (cap[2] === '@') {
	        text = cap[1].charAt(6) === ':'
	          ? this.mangle(cap[1].substring(7))
	          : this.mangle(cap[1]);
	        href = this.mangle('mailto:') + text;
	      } else {
	        text = escape(cap[1]);
	        href = text;
	      }
	      out += this.renderer.link(href, null, text);
	      continue;
	    }
	
	    // url (gfm)
	    if (!this.inLink && (cap = this.rules.url.exec(src))) {
	      src = src.substring(cap[0].length);
	      text = escape(cap[1]);
	      href = text;
	      out += this.renderer.link(href, null, text);
	      continue;
	    }
	
	    // tag
	    if (cap = this.rules.tag.exec(src)) {
	      if (!this.inLink && /^<a /i.test(cap[0])) {
	        this.inLink = true;
	      } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
	        this.inLink = false;
	      }
	      src = src.substring(cap[0].length);
	      out += this.options.sanitize
	        ? this.options.sanitizer
	          ? this.options.sanitizer(cap[0])
	          : escape(cap[0])
	        : cap[0]
	      continue;
	    }
	
	    // link
	    if (cap = this.rules.link.exec(src)) {
	      src = src.substring(cap[0].length);
	      this.inLink = true;
	      out += this.outputLink(cap, {
	        href: cap[2],
	        title: cap[3]
	      });
	      this.inLink = false;
	      continue;
	    }
	
	    // reflink, nolink
	    if ((cap = this.rules.reflink.exec(src))
	        || (cap = this.rules.nolink.exec(src))) {
	      src = src.substring(cap[0].length);
	      link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
	      link = this.links[link.toLowerCase()];
	      if (!link || !link.href) {
	        out += cap[0].charAt(0);
	        src = cap[0].substring(1) + src;
	        continue;
	      }
	      this.inLink = true;
	      out += this.outputLink(cap, link);
	      this.inLink = false;
	      continue;
	    }
	
	    // strong
	    if (cap = this.rules.strong.exec(src)) {
	      src = src.substring(cap[0].length);
	      out += this.renderer.strong(this.output(cap[2] || cap[1]));
	      continue;
	    }
	
	    // em
	    if (cap = this.rules.em.exec(src)) {
	      src = src.substring(cap[0].length);
	      out += this.renderer.em(this.output(cap[2] || cap[1]));
	      continue;
	    }
	
	    // code
	    if (cap = this.rules.code.exec(src)) {
	      src = src.substring(cap[0].length);
	      out += this.renderer.codespan(escape(cap[2], true));
	      continue;
	    }
	
	    // br
	    if (cap = this.rules.br.exec(src)) {
	      src = src.substring(cap[0].length);
	      out += this.renderer.br();
	      continue;
	    }
	
	    // del (gfm)
	    if (cap = this.rules.del.exec(src)) {
	      src = src.substring(cap[0].length);
	      out += this.renderer.del(this.output(cap[1]));
	      continue;
	    }
	
	    // text
	    if (cap = this.rules.text.exec(src)) {
	      src = src.substring(cap[0].length);
	      out += this.renderer.text(escape(this.smartypants(cap[0])));
	      continue;
	    }
	
	    if (src) {
	      throw new
	        Error('Infinite loop on byte: ' + src.charCodeAt(0));
	    }
	  }
	
	  return out;
	};
	
	/**
	 * Compile Link
	 */
	
	InlineLexer.prototype.outputLink = function(cap, link) {
	  var href = escape(link.href)
	    , title = link.title ? escape(link.title) : null;
	
	  return cap[0].charAt(0) !== '!'
	    ? this.renderer.link(href, title, this.output(cap[1]))
	    : this.renderer.image(href, title, escape(cap[1]));
	};
	
	/**
	 * Smartypants Transformations
	 */
	
	InlineLexer.prototype.smartypants = function(text) {
	  if (!this.options.smartypants) return text;
	  return text
	    // em-dashes
	    .replace(/---/g, '\u2014')
	    // en-dashes
	    .replace(/--/g, '\u2013')
	    // opening singles
	    .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
	    // closing singles & apostrophes
	    .replace(/'/g, '\u2019')
	    // opening doubles
	    .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
	    // closing doubles
	    .replace(/"/g, '\u201d')
	    // ellipses
	    .replace(/\.{3}/g, '\u2026');
	};
	
	/**
	 * Mangle Links
	 */
	
	InlineLexer.prototype.mangle = function(text) {
	  if (!this.options.mangle) return text;
	  var out = ''
	    , l = text.length
	    , i = 0
	    , ch;
	
	  for (; i < l; i++) {
	    ch = text.charCodeAt(i);
	    if (Math.random() > 0.5) {
	      ch = 'x' + ch.toString(16);
	    }
	    out += '&#' + ch + ';';
	  }
	
	  return out;
	};
	
	/**
	 * Renderer
	 */
	
	function Renderer(options) {
	  this.options = options || {};
	}
	
	Renderer.prototype.code = function(code, lang, escaped) {
	  if (this.options.highlight) {
	    var out = this.options.highlight(code, lang);
	    if (out != null && out !== code) {
	      escaped = true;
	      code = out;
	    }
	  }
	
	  if (!lang) {
	    return '<pre><code>'
	      + (escaped ? code : escape(code, true))
	      + '\n</code></pre>';
	  }
	
	  return '<pre><code class="'
	    + this.options.langPrefix
	    + escape(lang, true)
	    + '">'
	    + (escaped ? code : escape(code, true))
	    + '\n</code></pre>\n';
	};
	
	Renderer.prototype.blockquote = function(quote) {
	  return '<blockquote>\n' + quote + '</blockquote>\n';
	};
	
	Renderer.prototype.html = function(html) {
	  return html;
	};
	
	Renderer.prototype.heading = function(text, level, raw) {
	  return '<h'
	    + level
	    + ' id="'
	    + this.options.headerPrefix
	    + raw.toLowerCase().replace(/[^\w]+/g, '-')
	    + '">'
	    + text
	    + '</h'
	    + level
	    + '>\n';
	};
	
	Renderer.prototype.hr = function() {
	  return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
	};
	
	Renderer.prototype.list = function(body, ordered) {
	  var type = ordered ? 'ol' : 'ul';
	  return '<' + type + '>\n' + body + '</' + type + '>\n';
	};
	
	Renderer.prototype.listitem = function(text) {
	  return '<li>' + text + '</li>\n';
	};
	
	Renderer.prototype.paragraph = function(text) {
	  return '<p>' + text + '</p>\n';
	};
	
	Renderer.prototype.table = function(header, body) {
	  return '<table>\n'
	    + '<thead>\n'
	    + header
	    + '</thead>\n'
	    + '<tbody>\n'
	    + body
	    + '</tbody>\n'
	    + '</table>\n';
	};
	
	Renderer.prototype.tablerow = function(content) {
	  return '<tr>\n' + content + '</tr>\n';
	};
	
	Renderer.prototype.tablecell = function(content, flags) {
	  var type = flags.header ? 'th' : 'td';
	  var tag = flags.align
	    ? '<' + type + ' style="text-align:' + flags.align + '">'
	    : '<' + type + '>';
	  return tag + content + '</' + type + '>\n';
	};
	
	// span level renderer
	Renderer.prototype.strong = function(text) {
	  return '<strong>' + text + '</strong>';
	};
	
	Renderer.prototype.em = function(text) {
	  return '<em>' + text + '</em>';
	};
	
	Renderer.prototype.codespan = function(text) {
	  return '<code>' + text + '</code>';
	};
	
	Renderer.prototype.br = function() {
	  return this.options.xhtml ? '<br/>' : '<br>';
	};
	
	Renderer.prototype.del = function(text) {
	  return '<del>' + text + '</del>';
	};
	
	Renderer.prototype.link = function(href, title, text) {
	  if (this.options.sanitize) {
	    try {
	      var prot = decodeURIComponent(unescape(href))
	        .replace(/[^\w:]/g, '')
	        .toLowerCase();
	    } catch (e) {
	      return '';
	    }
	    if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
	      return '';
	    }
	  }
	  var out = '<a href="' + href + '"';
	  if (title) {
	    out += ' title="' + title + '"';
	  }
	  out += '>' + text + '</a>';
	  return out;
	};
	
	Renderer.prototype.image = function(href, title, text) {
	  var out = '<img src="' + href + '" alt="' + text + '"';
	  if (title) {
	    out += ' title="' + title + '"';
	  }
	  out += this.options.xhtml ? '/>' : '>';
	  return out;
	};
	
	Renderer.prototype.text = function(text) {
	  return text;
	};
	
	/**
	 * Parsing & Compiling
	 */
	
	function Parser(options) {
	  this.tokens = [];
	  this.token = null;
	  this.options = options || marked.defaults;
	  this.options.renderer = this.options.renderer || new Renderer;
	  this.renderer = this.options.renderer;
	  this.renderer.options = this.options;
	}
	
	/**
	 * Static Parse Method
	 */
	
	Parser.parse = function(src, options, renderer) {
	  var parser = new Parser(options, renderer);
	  return parser.parse(src);
	};
	
	/**
	 * Parse Loop
	 */
	
	Parser.prototype.parse = function(src) {
	  this.inline = new InlineLexer(src.links, this.options, this.renderer);
	  this.tokens = src.reverse();
	
	  var out = '';
	  while (this.next()) {
	    out += this.tok();
	  }
	
	  return out;
	};
	
	/**
	 * Next Token
	 */
	
	Parser.prototype.next = function() {
	  return this.token = this.tokens.pop();
	};
	
	/**
	 * Preview Next Token
	 */
	
	Parser.prototype.peek = function() {
	  return this.tokens[this.tokens.length - 1] || 0;
	};
	
	/**
	 * Parse Text Tokens
	 */
	
	Parser.prototype.parseText = function() {
	  var body = this.token.text;
	
	  while (this.peek().type === 'text') {
	    body += '\n' + this.next().text;
	  }
	
	  return this.inline.output(body);
	};
	
	/**
	 * Parse Current Token
	 */
	
	Parser.prototype.tok = function() {
	  switch (this.token.type) {
	    case 'space': {
	      return '';
	    }
	    case 'hr': {
	      return this.renderer.hr();
	    }
	    case 'heading': {
	      return this.renderer.heading(
	        this.inline.output(this.token.text),
	        this.token.depth,
	        this.token.text);
	    }
	    case 'code': {
	      return this.renderer.code(this.token.text,
	        this.token.lang,
	        this.token.escaped);
	    }
	    case 'table': {
	      var header = ''
	        , body = ''
	        , i
	        , row
	        , cell
	        , flags
	        , j;
	
	      // header
	      cell = '';
	      for (i = 0; i < this.token.header.length; i++) {
	        flags = { header: true, align: this.token.align[i] };
	        cell += this.renderer.tablecell(
	          this.inline.output(this.token.header[i]),
	          { header: true, align: this.token.align[i] }
	        );
	      }
	      header += this.renderer.tablerow(cell);
	
	      for (i = 0; i < this.token.cells.length; i++) {
	        row = this.token.cells[i];
	
	        cell = '';
	        for (j = 0; j < row.length; j++) {
	          cell += this.renderer.tablecell(
	            this.inline.output(row[j]),
	            { header: false, align: this.token.align[j] }
	          );
	        }
	
	        body += this.renderer.tablerow(cell);
	      }
	      return this.renderer.table(header, body);
	    }
	    case 'blockquote_start': {
	      var body = '';
	
	      while (this.next().type !== 'blockquote_end') {
	        body += this.tok();
	      }
	
	      return this.renderer.blockquote(body);
	    }
	    case 'list_start': {
	      var body = ''
	        , ordered = this.token.ordered;
	
	      while (this.next().type !== 'list_end') {
	        body += this.tok();
	      }
	
	      return this.renderer.list(body, ordered);
	    }
	    case 'list_item_start': {
	      var body = '';
	
	      while (this.next().type !== 'list_item_end') {
	        body += this.token.type === 'text'
	          ? this.parseText()
	          : this.tok();
	      }
	
	      return this.renderer.listitem(body);
	    }
	    case 'loose_item_start': {
	      var body = '';
	
	      while (this.next().type !== 'list_item_end') {
	        body += this.tok();
	      }
	
	      return this.renderer.listitem(body);
	    }
	    case 'html': {
	      var html = !this.token.pre && !this.options.pedantic
	        ? this.inline.output(this.token.text)
	        : this.token.text;
	      return this.renderer.html(html);
	    }
	    case 'paragraph': {
	      return this.renderer.paragraph(this.inline.output(this.token.text));
	    }
	    case 'text': {
	      return this.renderer.paragraph(this.parseText());
	    }
	  }
	};
	
	/**
	 * Helpers
	 */
	
	function escape(html, encode) {
	  return html
	    .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
	    .replace(/</g, '&lt;')
	    .replace(/>/g, '&gt;')
	    .replace(/"/g, '&quot;')
	    .replace(/'/g, '&#39;');
	}
	
	function unescape(html) {
		// explicitly match decimal, hex, and named HTML entities 
	  return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
	    n = n.toLowerCase();
	    if (n === 'colon') return ':';
	    if (n.charAt(0) === '#') {
	      return n.charAt(1) === 'x'
	        ? String.fromCharCode(parseInt(n.substring(2), 16))
	        : String.fromCharCode(+n.substring(1));
	    }
	    return '';
	  });
	}
	
	function replace(regex, opt) {
	  regex = regex.source;
	  opt = opt || '';
	  return function self(name, val) {
	    if (!name) return new RegExp(regex, opt);
	    val = val.source || val;
	    val = val.replace(/(^|[^\[])\^/g, '$1');
	    regex = regex.replace(name, val);
	    return self;
	  };
	}
	
	function noop() {}
	noop.exec = noop;
	
	function merge(obj) {
	  var i = 1
	    , target
	    , key;
	
	  for (; i < arguments.length; i++) {
	    target = arguments[i];
	    for (key in target) {
	      if (Object.prototype.hasOwnProperty.call(target, key)) {
	        obj[key] = target[key];
	      }
	    }
	  }
	
	  return obj;
	}
	
	
	/**
	 * Marked
	 */
	
	function marked(src, opt, callback) {
	  if (callback || typeof opt === 'function') {
	    if (!callback) {
	      callback = opt;
	      opt = null;
	    }
	
	    opt = merge({}, marked.defaults, opt || {});
	
	    var highlight = opt.highlight
	      , tokens
	      , pending
	      , i = 0;
	
	    try {
	      tokens = Lexer.lex(src, opt)
	    } catch (e) {
	      return callback(e);
	    }
	
	    pending = tokens.length;
	
	    var done = function(err) {
	      if (err) {
	        opt.highlight = highlight;
	        return callback(err);
	      }
	
	      var out;
	
	      try {
	        out = Parser.parse(tokens, opt);
	      } catch (e) {
	        err = e;
	      }
	
	      opt.highlight = highlight;
	
	      return err
	        ? callback(err)
	        : callback(null, out);
	    };
	
	    if (!highlight || highlight.length < 3) {
	      return done();
	    }
	
	    delete opt.highlight;
	
	    if (!pending) return done();
	
	    for (; i < tokens.length; i++) {
	      (function(token) {
	        if (token.type !== 'code') {
	          return --pending || done();
	        }
	        return highlight(token.text, token.lang, function(err, code) {
	          if (err) return done(err);
	          if (code == null || code === token.text) {
	            return --pending || done();
	          }
	          token.text = code;
	          token.escaped = true;
	          --pending || done();
	        });
	      })(tokens[i]);
	    }
	
	    return;
	  }
	  try {
	    if (opt) opt = merge({}, marked.defaults, opt);
	    return Parser.parse(Lexer.lex(src, opt), opt);
	  } catch (e) {
	    e.message += '\nPlease report this to https://github.com/chjj/marked.';
	    if ((opt || marked.defaults).silent) {
	      return '<p>An error occured:</p><pre>'
	        + escape(e.message + '', true)
	        + '</pre>';
	    }
	    throw e;
	  }
	}
	
	/**
	 * Options
	 */
	
	marked.options =
	marked.setOptions = function(opt) {
	  merge(marked.defaults, opt);
	  return marked;
	};
	
	marked.defaults = {
	  gfm: true,
	  tables: true,
	  breaks: false,
	  pedantic: false,
	  sanitize: false,
	  sanitizer: null,
	  mangle: true,
	  smartLists: false,
	  silent: false,
	  highlight: null,
	  langPrefix: 'lang-',
	  smartypants: false,
	  headerPrefix: '',
	  renderer: new Renderer,
	  xhtml: false
	};
	
	/**
	 * Expose
	 */
	
	marked.Parser = Parser;
	marked.parser = Parser.parse;
	
	marked.Renderer = Renderer;
	
	marked.Lexer = Lexer;
	marked.lexer = Lexer.lex;
	
	marked.InlineLexer = InlineLexer;
	marked.inlineLexer = InlineLexer.output;
	
	marked.parse = marked;
	
	if (true) {
	  module.exports = marked;
	} else if (typeof define === 'function' && define.amd) {
	  define(function() { return marked; });
	} else {
	  this.marked = marked;
	}
	
	}).call(function() {
	  return this || (typeof window !== 'undefined' ? window : global);
	}());
	
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
})
/** END DEFINE BLOCK for marked@0.3.6/lib/marked.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/renderers/latex.js **/
jupyter.define('jupyterlab@0.15.1/lib/renderers/latex.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	// Some magic for deferring mathematical expressions to MathJax
	// by hiding them from the Markdown parser.
	// Some of the code here is adapted with permission from Davide Cervone
	// under the terms of the Apache2 license governing the MathJax project.
	// Other minor modifications are also due to StackExchange and are used with
	// permission.
	var inline = '$'; // the inline math delimiter
	// MATHSPLIT contains the pattern for math delimiters and special symbols
	// needed for searching for math in the text input.
	var MATHSPLIT = /(\$\$?|\\(?:begin|end)\{[a-z]*\*?\}|\\[\\{}$]|[{}]|(?:\n\s*)+|@@\d+@@)/i;
	// A module-level initialization flag.
	var initialized = false;
	/**
	 *  Break up the text into its component parts and search
	 *    through them for math delimiters, braces, linebreaks, etc.
	 *  Math delimiters must match and braces must balance.
	 *  Don't allow math to pass through a double linebreak
	 *    (which will be a paragraph).
	 */
	function removeMath(text) {
	    var math = []; // stores math strings for later
	    var start;
	    var end;
	    var last;
	    var braces;
	    var deTilde;
	    if (!initialized) {
	        init();
	        initialized = true;
	    }
	    // Except for extreme edge cases, this should catch precisely those pieces of the markdown
	    // source that will later be turned into code spans. While MathJax will not TeXify code spans,
	    // we still have to consider them at this point; the following issue has happened several times:
	    //
	    //     `$foo` and `$bar` are variables.  -->  <code>$foo ` and `$bar</code> are variables.
	    var hasCodeSpans = /`/.test(text);
	    if (hasCodeSpans) {
	        text = text.replace(/~/g, '~T').replace(/(^|[^\\])(`+)([^\n]*?[^`\n])\2(?!`)/gm, function (wholematch) { return wholematch.replace(/\$/g, '~D'); });
	        deTilde = function (text) {
	            return text.replace(/~([TD])/g, function (wholematch, character) { return (character === 'T') ? '~' : '$'; });
	        };
	    }
	    else {
	        deTilde = function (text) { return text; };
	    }
	    var blocks = text.replace(/\r\n?/g, '\n').split(MATHSPLIT);
	    for (var i = 1, m = blocks.length; i < m; i += 2) {
	        var block = blocks[i];
	        if (block.charAt(0) === '@') {
	            //
	            //  Things that look like our math markers will get
	            //  stored and then retrieved along with the math.
	            //
	            blocks[i] = '@@' + math.length + '@@';
	            math.push(block);
	        }
	        else if (start) {
	            //
	            //  If we are in math, look for the end delimiter,
	            //    but don't go past double line breaks, and
	            //    and balance braces within the math.
	            //
	            if (block === end) {
	                if (braces) {
	                    last = i;
	                }
	                else {
	                    blocks = processMath(start, i, deTilde, math, blocks);
	                    start = null;
	                    end = null;
	                    last = null;
	                }
	            }
	            else if (block.match(/\n.*\n/)) {
	                if (last) {
	                    i = last;
	                    blocks = processMath(start, i, deTilde, math, blocks);
	                }
	                start = null;
	                end = null;
	                last = null;
	                braces = 0;
	            }
	            else if (block === '{') {
	                braces++;
	            }
	            else if (block === '}' && braces) {
	                braces--;
	            }
	        }
	        else {
	            //
	            //  Look for math start delimiters and when
	            //    found, set up the end delimiter.
	            //
	            if (block === inline || block === '$$') {
	                start = i;
	                end = block;
	                braces = 0;
	            }
	            else if (block.substr(1, 5) === 'begin') {
	                start = i;
	                end = '\\end' + block.substr(6);
	                braces = 0;
	            }
	        }
	    }
	    if (last) {
	        blocks = processMath(start, last, deTilde, math, blocks);
	        start = null;
	        end = null;
	        last = null;
	    }
	    return { text: deTilde(blocks.join('')), math: math };
	}
	exports.removeMath = removeMath;
	;
	/**
	 * Put back the math strings that were saved,
	 * and clear the math array (no need to keep it around).
	 */
	function replaceMath(text, math) {
	    text = text.replace(/@@(\d+)@@/g, function (match, n) { return math[n]; });
	    return text;
	}
	exports.replaceMath = replaceMath;
	;
	/**
	 * Typeset the math in a node.
	 */
	function typeset(node) {
	    if (!initialized) {
	        init();
	        initialized = true;
	    }
	    if (window.MathJax) {
	        MathJax.Hub.Queue(['Typeset', MathJax.Hub, node]);
	    }
	}
	exports.typeset = typeset;
	/**
	 * Initialize latex handling.
	 */
	function init() {
	    if (!window.MathJax) {
	        return;
	    }
	    MathJax.Hub.Config({
	        tex2jax: {
	            inlineMath: [['$', '$'], ['\\(', '\\)']],
	            displayMath: [['$$', '$$'], ['\\[', '\\]']],
	            processEscapes: true,
	            processEnvironments: true
	        },
	        // Center justify equations in code and markdown cells. Elsewhere
	        // we use CSS to left justify single line equations in code cells.
	        displayAlign: 'center',
	        CommonHTML: {
	            linebreaks: { automatic: true }
	        },
	        'HTML-CSS': {
	            availableFonts: [],
	            imageFont: null,
	            preferredFont: null,
	            webFont: 'STIX-Web',
	            styles: { '.MathJax_Display': { 'margin': 0 } },
	            linebreaks: { automatic: true }
	        },
	    });
	    MathJax.Hub.Configured();
	}
	/**
	 * Process math blocks.
	 *
	 * The math is in blocks i through j, so
	 *   collect it into one block and clear the others.
	 *  Replace &, <, and > by named entities.
	 *  For IE, put <br> at the ends of comments since IE removes \n.
	 *  Clear the current math positions and store the index of the
	 *   math, then push the math string onto the storage array.
	 *  The preProcess function is called on all blocks if it has been passed in
	 */
	function processMath(i, j, preProcess, math, blocks) {
	    var block = blocks.slice(i, j + 1).join('').replace(/&/g, '&amp;') // use HTML entity for &
	        .replace(/</g, '&lt;') // use HTML entity for <
	        .replace(/>/g, '&gt;');
	    if (navigator && navigator.appName === 'Microsoft Internet Explorer') {
	        block = block.replace(/(%[^\n]*)\n/g, '$1<br/>\n');
	    }
	    while (j > i) {
	        blocks[j] = '';
	        j--;
	    }
	    blocks[i] = '@@' + math.length + '@@'; // replace the current block text with a unique tag to find later
	    if (preProcess) {
	        block = preProcess(block);
	    }
	    math.push(block);
	    return blocks;
	}
	;
	//# sourceMappingURL=latex.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/renderers/latex.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/services/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/services/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	/* tslint:disable */
	/**
	 * The default services provider token.
	 */
	exports.IServiceManager = new token_1.Token('jupyter.services.services');
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/services/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/console/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/console/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/console/panel.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/console/tracker.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/console/widget.js'));
	/**
	 * The command IDs used by the console plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.create = 'console:create';
	    CommandIDs.clear = 'console:clear';
	    CommandIDs.run = 'console:run';
	    CommandIDs.runForced = 'console:run-forced';
	    CommandIDs.linebreak = 'console:linebreak';
	    CommandIDs.interrupt = 'console:interrupt-kernel';
	    CommandIDs.open = 'console:open';
	    CommandIDs.inject = 'console:inject';
	    CommandIDs.switchKernel = 'console:switch-kernel';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/console/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/console/panel.js **/
jupyter.define('jupyterlab@0.15.1/lib/console/panel.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var completer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/completer/index.js');
	var inspector_1 = __jupyter_require__('jupyterlab@0.15.1/lib/inspector/index.js');
	var widget_2 = __jupyter_require__('jupyterlab@0.15.1/lib/console/widget.js');
	/**
	 * The class name added to console panels.
	 */
	var PANEL_CLASS = 'jp-ConsolePanel';
	/**
	 * A panel which contains a console and the ability to add other children.
	 */
	var ConsolePanel = (function (_super) {
	    __extends(ConsolePanel, _super);
	    /**
	     * Construct a console panel.
	     */
	    function ConsolePanel(options) {
	        _super.call(this);
	        this._completer = null;
	        this._completerHandler = null;
	        this.addClass(PANEL_CLASS);
	        var factory = options.contentFactory;
	        var rendermime = options.rendermime, session = options.session, mimeTypeService = options.mimeTypeService;
	        var contentFactory = factory.consoleContentFactory;
	        var modelFactory = options.modelFactory;
	        var consoleOpts = {
	            rendermime: rendermime, session: session, mimeTypeService: mimeTypeService, contentFactory: contentFactory, modelFactory: modelFactory
	        };
	        this.console = factory.createConsole(consoleOpts);
	        this.addWidget(this.console);
	        // Set up the inspection handler.
	        this.inspectionHandler = factory.createInspectionHandler({
	            kernel: options.session.kernel,
	            rendermime: this.console.rendermime
	        });
	        // Instantiate the completer.
	        this._completer = factory.createCompleter({ model: new completer_1.CompleterModel() });
	        // Set the completer widget's anchor widget to peg its position.
	        this._completer.anchor = this.console;
	        widget_1.Widget.attach(this._completer, document.body);
	        // Instantiate the completer handler.
	        this._completerHandler = factory.createCompleterHandler({
	            completer: this._completer,
	            kernel: options.session.kernel
	        });
	        // Connect to change events.
	        this.console.promptCreated.connect(this._onPromptCreated, this);
	        options.session.kernelChanged.connect(this._onKernelChanged, this);
	    }
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    ConsolePanel.prototype.dispose = function () {
	        if (this._completer === null) {
	            return;
	        }
	        var completer = this._completer;
	        var completerHandler = this._completerHandler;
	        this._completer = null;
	        this._completerHandler = null;
	        completer.dispose();
	        completerHandler.dispose();
	        this.console.dispose();
	        this.inspectionHandler.dispose();
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    ConsolePanel.prototype.onActivateRequest = function (msg) {
	        this.console.prompt.editor.focus();
	    };
	    /**
	     * Handle `'close-request'` messages.
	     */
	    ConsolePanel.prototype.onCloseRequest = function (msg) {
	        _super.prototype.onCloseRequest.call(this, msg);
	        this.dispose();
	    };
	    /**
	     * Handle the creation of a new prompt.
	     */
	    ConsolePanel.prototype._onPromptCreated = function (sender, prompt) {
	        this._completer.reset();
	        // Associate the new prompt with the completer and inspection handlers.
	        this._completerHandler.editor = prompt.editor;
	        this.inspectionHandler.editor = prompt.editor;
	    };
	    /**
	     * Handle a change to the kernel.
	     */
	    ConsolePanel.prototype._onKernelChanged = function (sender, kernel) {
	        this._completerHandler.kernel = kernel;
	        this.inspectionHandler.kernel = kernel;
	    };
	    return ConsolePanel;
	}(panel_1.Panel));
	exports.ConsolePanel = ConsolePanel;
	/**
	 * A namespace for ConsolePanel statics.
	 */
	var ConsolePanel;
	(function (ConsolePanel) {
	    /**
	     * Default implementation of `IContentFactory`.
	     */
	    var ContentFactory = (function () {
	        /**
	         * Create a new content factory.
	         */
	        function ContentFactory(options) {
	            this.editorFactory = options.editorFactory;
	            this.consoleContentFactory = (options.consoleContentFactory ||
	                new widget_2.CodeConsole.ContentFactory({
	                    editorFactory: this.editorFactory,
	                    outputAreaContentFactory: options.outputAreaContentFactory,
	                    codeCellContentFactory: options.codeCellContentFactory,
	                    rawCellContentFactory: options.rawCellContentFactory
	                }));
	        }
	        /**
	         * Create a new console panel.
	         */
	        ContentFactory.prototype.createConsole = function (options) {
	            return new widget_2.CodeConsole(options);
	        };
	        /**
	         * The inspection handler for a console widget.
	         */
	        ContentFactory.prototype.createInspectionHandler = function (options) {
	            return new inspector_1.InspectionHandler(options);
	        };
	        /**
	         * The completer widget for a console widget.
	         */
	        ContentFactory.prototype.createCompleter = function (options) {
	            return new completer_1.CompleterWidget(options);
	        };
	        /**
	         * The completer handler for a console widget.
	         */
	        ContentFactory.prototype.createCompleterHandler = function (options) {
	            return new completer_1.CompletionHandler(options);
	        };
	        return ContentFactory;
	    }());
	    ConsolePanel.ContentFactory = ContentFactory;
	    /* tslint:disable */
	    /**
	     * The console renderer token.
	     */
	    ConsolePanel.IContentFactory = new token_1.Token('jupyter.services.console.content-factory');
	})(ConsolePanel = exports.ConsolePanel || (exports.ConsolePanel = {}));
	//# sourceMappingURL=panel.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/console/panel.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/completer/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/completer/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/completer/handler.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/completer/model.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/completer/widget.js'));
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/completer/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/completer/handler.js **/
jupyter.define('jupyterlab@0.15.1/lib/completer/handler.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * A completion handler for editors.
	 */
	var CompletionHandler = (function () {
	    /**
	     * Construct a new completion handler for a widget.
	     */
	    function CompletionHandler(options) {
	        this._editor = null;
	        this._completer = null;
	        this._kernel = null;
	        this._pending = 0;
	        this._completer = options.completer;
	        this._completer.selected.connect(this.onCompletionSelected, this);
	        this._completer.visibilityChanged.connect(this.onVisibilityChanged, this);
	        this._kernel = options.kernel || null;
	    }
	    Object.defineProperty(CompletionHandler.prototype, "kernel", {
	        /**
	         * The kernel used by the completion handler.
	         */
	        get: function () {
	            return this._kernel;
	        },
	        set: function (value) {
	            this._kernel = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CompletionHandler.prototype, "editor", {
	        /**
	         * The editor used by the completion handler.
	         */
	        get: function () {
	            return this._editor;
	        },
	        set: function (newValue) {
	            if (newValue === this._editor) {
	                return;
	            }
	            var editor = this._editor;
	            if (editor && !editor.isDisposed) {
	                editor.model.value.changed.disconnect(this.onTextChanged, this);
	                editor.completionRequested.disconnect(this.onCompletionRequested, this);
	            }
	            editor = this._editor = newValue;
	            if (editor) {
	                editor.model.value.changed.connect(this.onTextChanged, this);
	                editor.completionRequested.connect(this.onCompletionRequested, this);
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CompletionHandler.prototype, "isDisposed", {
	        /**
	         * Get whether the completion handler is disposed.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._completer === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the handler.
	     */
	    CompletionHandler.prototype.dispose = function () {
	        this._completer = null;
	        this._kernel = null;
	        this._editor = null;
	    };
	    /**
	     * Make a complete request using the kernel.
	     */
	    CompletionHandler.prototype.makeRequest = function (position) {
	        var _this = this;
	        if (!this._kernel) {
	            return Promise.reject(new Error('no kernel for completion request'));
	        }
	        var editor = this.editor;
	        if (!editor) {
	            return Promise.reject(new Error('No active editor'));
	        }
	        var offset = editor.getOffsetAt(position);
	        var content = {
	            code: editor.model.value.text,
	            cursor_pos: offset
	        };
	        var pending = ++this._pending;
	        var request = this.getState(position);
	        return this._kernel.requestComplete(content).then(function (msg) {
	            if (_this.isDisposed) {
	                return;
	            }
	            _this.onReply(pending, request, msg);
	        });
	    };
	    /**
	     * Get the state of the text editor at the given position.
	     */
	    CompletionHandler.prototype.getState = function (position) {
	        var editor = this.editor;
	        var coords = editor.getCoordinate(position);
	        return {
	            text: editor.model.value.text,
	            lineHeight: editor.lineHeight,
	            charWidth: editor.charWidth,
	            coords: coords,
	            line: position.line,
	            column: position.column
	        };
	    };
	    /**
	     * Receive a completion reply from the kernel.
	     */
	    CompletionHandler.prototype.onReply = function (pending, request, msg) {
	        // If we have been disposed, bail.
	        if (this.isDisposed) {
	            return;
	        }
	        // If a newer completion request has created a pending request, bail.
	        if (pending !== this._pending) {
	            return;
	        }
	        var value = msg.content;
	        var model = this._completer.model;
	        if (!model) {
	            return;
	        }
	        // Completion request failures or negative results fail silently.
	        if (value.status !== 'ok') {
	            model.reset();
	            return;
	        }
	        // Update the original request.
	        model.original = request;
	        // Update the options.
	        model.setOptions(value.matches || []);
	        // Update the cursor.
	        model.cursor = { start: value.cursor_start, end: value.cursor_end };
	    };
	    /**
	     * Handle a text changed signal from an editor.
	     */
	    CompletionHandler.prototype.onTextChanged = function () {
	        if (!this._completer.model) {
	            return;
	        }
	        var editor = this.editor;
	        var position = editor.getCursorPosition();
	        var request = this.getState(position);
	        this._completer.model.handleTextChange(request);
	    };
	    /**
	     * Handle a completion requested signal from an editor.
	     */
	    CompletionHandler.prototype.onCompletionRequested = function (editor, position) {
	        if (!this._kernel || !this._completer.model) {
	            return;
	        }
	        this.makeRequest(position);
	    };
	    /**
	     * Handle a visiblity change signal from a completion widget.
	     */
	    CompletionHandler.prototype.onVisibilityChanged = function (completion) {
	        if (completion.isDisposed || completion.isHidden) {
	            if (this._editor) {
	                this._editor.focus();
	            }
	        }
	    };
	    /**
	     * Handle a completion selected signal from the completion widget.
	     */
	    CompletionHandler.prototype.onCompletionSelected = function (widget, value) {
	        var model = this._completer.model;
	        var editor = this._editor;
	        if (!editor || !model) {
	            return;
	        }
	        var patch = model.createPatch(value);
	        if (!patch) {
	            return;
	        }
	        var offset = patch.offset, text = patch.text;
	        editor.model.value.text = text;
	        var position = editor.getPositionAt(offset);
	        editor.setCursorPosition(position);
	    };
	    return CompletionHandler;
	}());
	exports.CompletionHandler = CompletionHandler;
	//# sourceMappingURL=handler.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/completer/handler.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/completer/model.js **/
jupyter.define('jupyterlab@0.15.1/lib/completer/model.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var json_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/json.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	/**
	 * An implementation of a completer model.
	 */
	var CompleterModel = (function () {
	    function CompleterModel() {
	        this._current = null;
	        this._cursor = null;
	        this._isDisposed = false;
	        this._options = [];
	        this._original = null;
	        this._query = '';
	        this._subsetMatch = false;
	    }
	    Object.defineProperty(CompleterModel.prototype, "original", {
	        /**
	         * The original completion request details.
	         */
	        get: function () {
	            return this._original;
	        },
	        set: function (newValue) {
	            if (json_1.deepEqual(newValue, this._original)) {
	                return;
	            }
	            this._reset();
	            this._original = newValue;
	            this.stateChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CompleterModel.prototype, "current", {
	        /**
	         * The current text change details.
	         */
	        get: function () {
	            return this._current;
	        },
	        set: function (newValue) {
	            if (json_1.deepEqual(newValue, this._current)) {
	                return;
	            }
	            // Original request must always be set before a text change. If it isn't
	            // the model fails silently.
	            if (!this.original) {
	                return;
	            }
	            // Cursor must always be set before a text change. This happens
	            // automatically in the completer handler, but since `current` is a public
	            // attribute, this defensive check is necessary.
	            if (!this._cursor) {
	                return;
	            }
	            this._current = newValue;
	            if (!this._current) {
	                this.stateChanged.emit(void 0);
	                return;
	            }
	            var original = this._original;
	            var current = this._current;
	            var originalLine = original.text.split('\n')[original.line];
	            var currentLine = current.text.split('\n')[current.line];
	            // If the text change means that the original start point has been preceded,
	            // then the completion is no longer valid and should be reset.
	            if (currentLine.length < originalLine.length) {
	                this.reset();
	                return;
	            }
	            var _a = this._cursor, start = _a.start, end = _a.end;
	            // Clip the front of the current line.
	            var query = current.text.substring(start);
	            // Clip the back of the current line by calculating the end of the original.
	            var ending = original.text.substring(end);
	            query = query.substring(0, query.lastIndexOf(ending));
	            this._query = query;
	            this.stateChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CompleterModel.prototype, "cursor", {
	        /**
	         * The cursor details that the API has used to return matching options.
	         */
	        get: function () {
	            return this._cursor;
	        },
	        set: function (newValue) {
	            // Original request must always be set before a cursor change. If it isn't
	            // the model fails silently.
	            if (!this.original) {
	                return;
	            }
	            this._cursor = newValue;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CompleterModel.prototype, "query", {
	        /**
	         * The query against which items are filtered.
	         */
	        get: function () {
	            return this._query;
	        },
	        set: function (newValue) {
	            this._query = newValue;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CompleterModel.prototype, "subsetMatch", {
	        /**
	         * A flag that is true when the model value was modified by a subset match.
	         */
	        get: function () {
	            return this._subsetMatch;
	        },
	        set: function (newValue) {
	            this._subsetMatch = newValue;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CompleterModel.prototype, "isDisposed", {
	        /**
	         * Get whether the model is disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the model.
	     */
	    CompleterModel.prototype.dispose = function () {
	        // Do nothing if already disposed.
	        if (this._isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * The list of visible items in the completer menu.
	     *
	     * #### Notes
	     * This is a read-only property.
	     */
	    CompleterModel.prototype.items = function () {
	        return this._filter();
	    };
	    /**
	     * The unfiltered list of all available options in a completer menu.
	     */
	    CompleterModel.prototype.options = function () {
	        return iteration_1.iter(this._options);
	    };
	    /**
	     * Set the avilable options in the completer menu.
	     */
	    CompleterModel.prototype.setOptions = function (newValue) {
	        var values = iteration_1.toArray(newValue || []);
	        if (json_1.deepEqual(values, this._options)) {
	            return;
	        }
	        if (values.length) {
	            this._options = [];
	            (_a = this._options).push.apply(_a, values);
	            this._subsetMatch = true;
	        }
	        else {
	            this._options = [];
	        }
	        this.stateChanged.emit(void 0);
	        var _a;
	    };
	    /**
	     * Handle a text change.
	     */
	    CompleterModel.prototype.handleTextChange = function (request) {
	        // When the completer detects a common subset prefix for all options,
	        // it updates the model and sets the model source to that value, but this
	        // text change should be ignored.
	        if (this.subsetMatch) {
	            return;
	        }
	        var text = request.text, column = request.column;
	        // If last character entered is not whitespace, update completion.
	        if (text[column - 1] && text[column - 1].match(/\S/)) {
	            // If there is currently an active completion, update the current state.
	            if (this.original) {
	                this.current = request;
	            }
	        }
	        else {
	            // If final character is whitespace, reset completion.
	            this.reset();
	        }
	    };
	    /**
	     * Create a resolved patch between the original state and a patch string.
	     *
	     * @param patch - The patch string to apply to the original value.
	     *
	     * @returns A patched text change or null if original value did not exist.
	     */
	    CompleterModel.prototype.createPatch = function (patch) {
	        var original = this._original;
	        var cursor = this._cursor;
	        if (!original || !cursor) {
	            return null;
	        }
	        var prefix = original.text.substring(0, cursor.start);
	        var suffix = original.text.substring(cursor.end);
	        return { offset: (prefix + patch).length, text: prefix + patch + suffix };
	    };
	    /**
	     * Reset the state of the model and emit a state change signal.
	     */
	    CompleterModel.prototype.reset = function () {
	        this._reset();
	        this.stateChanged.emit(void 0);
	    };
	    /**
	     * Apply the query to the complete options list to return the matching subset.
	     */
	    CompleterModel.prototype._filter = function () {
	        var options = this._options || [];
	        var query = this._query;
	        if (!query) {
	            return iteration_1.map(options, function (option) { return ({ raw: option, text: option }); });
	        }
	        var results = [];
	        for (var _i = 0, options_1 = options; _i < options_1.length; _i++) {
	            var option = options_1[_i];
	            var match = searching_1.StringSearch.sumOfSquares(option, query);
	            if (match) {
	                results.push({
	                    raw: option,
	                    score: match.score,
	                    text: searching_1.StringSearch.highlight(option, match.indices)
	                });
	            }
	        }
	        return iteration_1.map(results.sort(Private.scoreCmp), function (result) {
	            return ({ text: result.text, raw: result.raw });
	        });
	    };
	    /**
	     * Reset the state of the model.
	     */
	    CompleterModel.prototype._reset = function () {
	        this._current = null;
	        this._cursor = null;
	        this._options = [];
	        this._original = null;
	        this._query = '';
	        this._subsetMatch = false;
	    };
	    return CompleterModel;
	}());
	exports.CompleterModel = CompleterModel;
	// Define the signals for the `CompleterModel` class.
	signaling_1.defineSignal(CompleterModel.prototype, 'stateChanged');
	/**
	 * A namespace for completer model private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * A sort comparison function for item match scores.
	     *
	     * #### Notes
	     * This orders the items first based on score (lower is better), then
	     * by locale order of the item text.
	     */
	    function scoreCmp(a, b) {
	        var delta = a.score - b.score;
	        if (delta !== 0) {
	            return delta;
	        }
	        return a.raw.localeCompare(b.raw);
	    }
	    Private.scoreCmp = scoreCmp;
	})(Private || (Private = {}));
	//# sourceMappingURL=model.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/completer/model.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/completer/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/completer/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var query_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/query.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var hoverbox_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/hoverbox.js');
	/**
	 * The class name added to completer menu widgets.
	 */
	var COMPLETER_CLASS = 'jp-Completer';
	/**
	 * The class name added to completer menu items.
	 */
	var ITEM_CLASS = 'jp-Completer-item';
	/**
	 * The class name added to an active completer menu item.
	 */
	var ACTIVE_CLASS = 'jp-mod-active';
	/**
	 * The minimum height of a completer widget.
	 */
	var MIN_HEIGHT = 20;
	/**
	 * The maximum height of a completer widget.
	 */
	var MAX_HEIGHT = 200;
	/**
	 * A flag to indicate that event handlers are caught in the capture phase.
	 */
	var USE_CAPTURE = true;
	/**
	 * A widget that enables text completion.
	 */
	var CompleterWidget = (function (_super) {
	    __extends(CompleterWidget, _super);
	    /**
	     * Construct a text completer menu widget.
	     */
	    function CompleterWidget(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this, { node: document.createElement('ul') });
	        this._anchor = null;
	        this._anchorPoint = 0;
	        this._activeIndex = 0;
	        this._model = null;
	        this._renderer = null;
	        this._renderer = options.renderer || CompleterWidget.defaultRenderer;
	        this.anchor = options.anchor || null;
	        this.model = options.model;
	        this.addClass(COMPLETER_CLASS);
	        // Completer widgets are hidden until they are populated.
	        this.hide();
	    }
	    Object.defineProperty(CompleterWidget.prototype, "model", {
	        /**
	         * The model used by the completer widget.
	         */
	        get: function () {
	            return this._model;
	        },
	        set: function (model) {
	            if (!model && !this._model || model === this._model) {
	                return;
	            }
	            if (this._model) {
	                this._model.stateChanged.disconnect(this.onModelStateChanged, this);
	            }
	            this._model = model;
	            if (this._model) {
	                this._model.stateChanged.connect(this.onModelStateChanged, this);
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CompleterWidget.prototype, "anchor", {
	        /**
	         * The semantic parent of the completer widget, its anchor widget.
	         *
	         * #### Notes
	         * An event listener will peg the position of the completer widget to the
	         * anchor's scroll position.
	         */
	        get: function () {
	            return this._anchor;
	        },
	        set: function (widget) {
	            if (this._anchor === widget) {
	                return;
	            }
	            // Clean up scroll listener if anchor is being replaced.
	            if (this._anchor && !this._anchor.isDisposed) {
	                this._anchor.node.removeEventListener('scroll', this, USE_CAPTURE);
	            }
	            this._anchor = widget;
	            // Add scroll listener to anchor element.
	            if (this._anchor) {
	                this._anchor.node.addEventListener('scroll', this, USE_CAPTURE);
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the completer widget.
	     */
	    CompleterWidget.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._model = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Reset the widget.
	     */
	    CompleterWidget.prototype.reset = function () {
	        this._reset();
	        if (this._model) {
	            this._model.reset();
	        }
	    };
	    /**
	     * Handle the DOM events for the widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the dock panel's node. It should
	     * not be called directly by user code.
	     */
	    CompleterWidget.prototype.handleEvent = function (event) {
	        if (this.isHidden || !this._anchor) {
	            return;
	        }
	        switch (event.type) {
	            case 'keydown':
	                this._evtKeydown(event);
	                break;
	            case 'mousedown':
	                this._evtMousedown(event);
	                break;
	            case 'scroll':
	                this._evtScroll(event);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle `after-attach` messages for the widget.
	     */
	    CompleterWidget.prototype.onAfterAttach = function (msg) {
	        document.addEventListener('keydown', this, USE_CAPTURE);
	        document.addEventListener('mousedown', this, USE_CAPTURE);
	    };
	    /**
	     * Handle `before_detach` messages for the widget.
	     */
	    CompleterWidget.prototype.onBeforeDetach = function (msg) {
	        document.removeEventListener('keydown', this, USE_CAPTURE);
	        document.removeEventListener('mousedown', this, USE_CAPTURE);
	        if (this._anchor && !this._anchor.isDisposed) {
	            this._anchor.node.removeEventListener('scroll', this, USE_CAPTURE);
	        }
	    };
	    /**
	     * Handle model state changes.
	     */
	    CompleterWidget.prototype.onModelStateChanged = function () {
	        if (this.isAttached) {
	            this.update();
	        }
	    };
	    /**
	     * Handle `update-request` messages.
	     */
	    CompleterWidget.prototype.onUpdateRequest = function (msg) {
	        var model = this._model;
	        var anchor = this._anchor;
	        if (!model || !anchor) {
	            return;
	        }
	        var items = iteration_1.toArray(model.items());
	        // If there are no items, reset and bail.
	        if (!items || !items.length) {
	            this._reset();
	            if (!this.isHidden) {
	                this.hide();
	                this.visibilityChanged.emit(void 0);
	            }
	            return;
	        }
	        // If there is only one item, signal and bail.
	        if (items.length === 1) {
	            this.selected.emit(items[0].raw);
	            this.reset();
	            return;
	        }
	        // Clear the node.
	        var node = this.node;
	        node.textContent = '';
	        // Populate the completer items.
	        for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
	            var item = items_1[_i];
	            var li = this._renderer.createItemNode(item);
	            // Set the raw, un-marked up value as a data attribute.
	            li.setAttribute('data-value', item.raw);
	            node.appendChild(li);
	        }
	        var active = node.querySelectorAll("." + ITEM_CLASS)[this._activeIndex];
	        active.classList.add(ACTIVE_CLASS);
	        if (this.isHidden) {
	            this.show();
	            this.visibilityChanged.emit(void 0);
	        }
	        this._anchorPoint = anchor.node.scrollTop;
	        this._setGeometry();
	        // If this is the first time the current completer session has loaded,
	        // populate any initial subset match.
	        if (this._model.subsetMatch) {
	            this._populateSubset();
	            this.model.subsetMatch = false;
	        }
	    };
	    /**
	     * Cycle through the available completer items.
	     */
	    CompleterWidget.prototype._cycle = function (direction) {
	        var items = this.node.querySelectorAll("." + ITEM_CLASS);
	        var index = this._activeIndex;
	        var active = this.node.querySelector("." + ACTIVE_CLASS);
	        active.classList.remove(ACTIVE_CLASS);
	        if (direction === 'up') {
	            this._activeIndex = index === 0 ? items.length - 1 : index - 1;
	        }
	        else {
	            this._activeIndex = index < items.length - 1 ? index + 1 : 0;
	        }
	        active = items[this._activeIndex];
	        active.classList.add(ACTIVE_CLASS);
	        query_1.scrollIntoViewIfNeeded(this.node, active);
	    };
	    /**
	     * Handle keydown events for the widget.
	     */
	    CompleterWidget.prototype._evtKeydown = function (event) {
	        if (this.isHidden || !this._anchor) {
	            return;
	        }
	        if (!this._anchor.node.contains(event.target)) {
	            this.reset();
	            return;
	        }
	        switch (event.keyCode) {
	            case 9:
	                event.preventDefault();
	                event.stopPropagation();
	                event.stopImmediatePropagation();
	                this._model.subsetMatch = true;
	                var populated = this._populateSubset();
	                this.model.subsetMatch = false;
	                if (populated) {
	                    return;
	                }
	                this._selectActive();
	                return;
	            case 13:
	                event.preventDefault();
	                event.stopPropagation();
	                event.stopImmediatePropagation();
	                this._selectActive();
	                return;
	            case 27:
	                event.preventDefault();
	                event.stopPropagation();
	                event.stopImmediatePropagation();
	                this.reset();
	                return;
	            case 38: // Up arrow key
	            case 40:
	                event.preventDefault();
	                event.stopPropagation();
	                event.stopImmediatePropagation();
	                this._cycle(event.keyCode === 38 ? 'up' : 'down');
	                return;
	            default:
	                return;
	        }
	    };
	    /**
	     * Handle mousedown events for the widget.
	     */
	    CompleterWidget.prototype._evtMousedown = function (event) {
	        if (this.isHidden || !this._anchor) {
	            return;
	        }
	        if (Private.nonstandardClick(event)) {
	            this.reset();
	            return;
	        }
	        var target = event.target;
	        while (target !== document.documentElement) {
	            // If the user has made a selection, emit its value and reset the widget.
	            if (target.classList.contains(ITEM_CLASS)) {
	                event.preventDefault();
	                event.stopPropagation();
	                event.stopImmediatePropagation();
	                this.selected.emit(target.getAttribute('data-value'));
	                this.reset();
	                return;
	            }
	            // If the mouse event happened anywhere else in the widget, bail.
	            if (target === this.node) {
	                event.preventDefault();
	                event.stopPropagation();
	                event.stopImmediatePropagation();
	                return;
	            }
	            target = target.parentElement;
	        }
	        this.reset();
	    };
	    /**
	     * Handle scroll events for the widget
	     */
	    CompleterWidget.prototype._evtScroll = function (event) {
	        if (this.isHidden || !this._anchor) {
	            return;
	        }
	        this._setGeometry();
	    };
	    /**
	     * Populate the completer up to the longest initial subset of items.
	     *
	     * @returns `true` if a subset match was found and populated.
	     */
	    CompleterWidget.prototype._populateSubset = function () {
	        var items = this.node.querySelectorAll("." + ITEM_CLASS);
	        var subset = Private.commonSubset(Private.itemValues(items));
	        var query = this.model.query;
	        if (subset && subset !== query && subset.indexOf(query) === 0) {
	            this.model.query = subset;
	            this.selected.emit(subset);
	            this.update();
	            return true;
	        }
	        return false;
	    };
	    /**
	     * Reset the internal flags to defaults.
	     */
	    CompleterWidget.prototype._reset = function () {
	        this._activeIndex = 0;
	        this._anchorPoint = 0;
	    };
	    /**
	     * Set the visible dimensions of the widget.
	     */
	    CompleterWidget.prototype._setGeometry = function () {
	        var model = this._model;
	        // This is an overly defensive test: `cursor` will always exist if
	        // `original` exists, except in contrived tests. But since it is possible
	        // to generate a runtime error, the check occurs here.
	        if (!model || !model.original || !model.cursor) {
	            return;
	        }
	        var node = this.node;
	        var _a = model.original, coords = _a.coords, charWidth = _a.charWidth, lineHeight = _a.lineHeight;
	        // Calculate the geometry of the completer.
	        hoverbox_1.HoverBox.setGeometry({
	            charWidth: charWidth, coords: coords, lineHeight: lineHeight, node: node,
	            anchor: this._anchor.node,
	            anchorPoint: this._anchorPoint,
	            cursor: this._model.cursor,
	            maxHeight: MAX_HEIGHT,
	            minHeight: MIN_HEIGHT
	        });
	    };
	    /**
	     * Emit the selected signal for the current active item and reset.
	     */
	    CompleterWidget.prototype._selectActive = function () {
	        var active = this.node.querySelector("." + ACTIVE_CLASS);
	        if (!active) {
	            this._reset();
	            return;
	        }
	        this.selected.emit(active.getAttribute('data-value'));
	        this.reset();
	    };
	    return CompleterWidget;
	}(widget_1.Widget));
	exports.CompleterWidget = CompleterWidget;
	// Define the signals for the `CompleterWidget` class.
	signaling_1.defineSignal(CompleterWidget.prototype, 'selected');
	signaling_1.defineSignal(CompleterWidget.prototype, 'visibilityChanged');
	var CompleterWidget;
	(function (CompleterWidget) {
	    /**
	     * The default implementation of an `IRenderer`.
	     */
	    var Renderer = (function () {
	        function Renderer() {
	        }
	        /**
	         * Create an item node for a text completer menu.
	         */
	        Renderer.prototype.createItemNode = function (item) {
	            var li = document.createElement('li');
	            var code = document.createElement('code');
	            // Use innerHTML because search results include <mark> tags.
	            code.innerHTML = item.text;
	            li.className = ITEM_CLASS;
	            li.appendChild(code);
	            return li;
	        };
	        return Renderer;
	    }());
	    CompleterWidget.Renderer = Renderer;
	    /**
	     * The default `IRenderer` instance.
	     */
	    CompleterWidget.defaultRenderer = new Renderer();
	})(CompleterWidget = exports.CompleterWidget || (exports.CompleterWidget = {}));
	/**
	 * A namespace for completer widget private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Returns the common subset string that a list of strings shares.
	     */
	    function commonSubset(values) {
	        var len = values.length;
	        var subset = '';
	        if (len < 2) {
	            return subset;
	        }
	        var strlen = values[0].length;
	        for (var i = 0; i < strlen; i++) {
	            var ch = values[0][i];
	            for (var j = 1; j < len; j++) {
	                if (values[j][i] !== ch) {
	                    return subset;
	                }
	            }
	            subset += ch;
	        }
	        return subset;
	    }
	    Private.commonSubset = commonSubset;
	    /**
	     * Returns the list of raw item values currently in the DOM.
	     */
	    function itemValues(items) {
	        var values = [];
	        for (var i = 0, len = items.length; i < len; i++) {
	            values.push(items[i].getAttribute('data-value'));
	        }
	        return values;
	    }
	    Private.itemValues = itemValues;
	    /**
	     * Returns true for any modified click event (i.e., not a left-click).
	     */
	    function nonstandardClick(event) {
	        return event.button !== 0 ||
	            event.altKey ||
	            event.ctrlKey ||
	            event.shiftKey ||
	            event.metaKey;
	    }
	    Private.nonstandardClick = nonstandardClick;
	})(Private || (Private = {}));
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/completer/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/hoverbox.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/hoverbox.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * The class name added to all hover boxes.
	 */
	var HOVERBOX_CLASS = 'jp-HoverBox';
	/**
	 * The class name added to a hovering node that is scrolled out of view.
	 */
	var OUTOFVIEW_CLASS = 'jp-mod-outofview';
	/**
	 * A namespace for `HoverBox` members.
	 */
	var HoverBox;
	(function (HoverBox) {
	    /**
	     * Set the visible dimensions of a hovering box anchored to a scrollable node.
	     *
	     * @param options - The hover box geometry calculation options.
	     */
	    function setGeometry(options) {
	        var anchor = options.anchor, anchorPoint = options.anchorPoint, charWidth = options.charWidth, coords = options.coords, cursor = options.cursor, lineHeight = options.lineHeight, node = options.node;
	        // Add hover box class if it does not exist.
	        node.classList.add(HOVERBOX_CLASS);
	        // Clear any previously set max-height.
	        node.style.maxHeight = '';
	        // Clear any programmatically set margin-top.
	        node.style.marginTop = '';
	        // Make sure the node is visible.
	        node.classList.remove(OUTOFVIEW_CLASS);
	        // Always use the original coordinates to calculate box position.
	        var style = window.getComputedStyle(node);
	        var innerHeight = window.innerHeight;
	        var scrollDelta = anchorPoint - anchor.scrollTop;
	        var spaceAbove = coords.top + scrollDelta;
	        var spaceBelow = innerHeight - coords.bottom - scrollDelta;
	        var marginTop = parseInt(style.marginTop, 10) || 0;
	        var maxHeight = parseInt(style.maxHeight, 10) || options.maxHeight;
	        var minHeight = parseInt(style.minHeight, 10) || options.minHeight;
	        var anchorRect = anchor.getBoundingClientRect();
	        var top;
	        // If the whole box fits below or if there is more space below, then
	        // rendering the box below the text being typed is privileged so that
	        // the code above is not obscured.
	        var renderBelow = spaceBelow >= maxHeight || spaceBelow >= spaceAbove;
	        if (renderBelow) {
	            maxHeight = Math.min(spaceBelow - marginTop, maxHeight);
	        }
	        else {
	            maxHeight = Math.min(spaceAbove, maxHeight);
	            // If the box renders above the text, its top margin is irrelevant.
	            node.style.marginTop = '0px';
	        }
	        node.style.maxHeight = maxHeight + "px";
	        // Make sure the box ought to be visible.
	        var withinBounds = maxHeight > minHeight &&
	            spaceBelow >= lineHeight &&
	            spaceAbove >= anchorRect.top;
	        if (!withinBounds) {
	            node.classList.add(OUTOFVIEW_CLASS);
	            return;
	        }
	        var borderLeftWidth = style.borderLeftWidth;
	        var left = coords.left + (parseInt(borderLeftWidth, 10) || 0);
	        var start = cursor.start, end = cursor.end;
	        var nodeRect = node.getBoundingClientRect();
	        // Position the box vertically.
	        top = renderBelow ? innerHeight - spaceBelow : spaceAbove - nodeRect.height;
	        node.style.top = Math.floor(top) + "px";
	        // Move box to the start of the blob of text in the referent editor.
	        left -= charWidth * (end - start);
	        node.style.left = Math.ceil(left) + "px";
	        node.style.width = 'auto';
	        // Expand the menu width by the scrollbar size, if present.
	        if (node.scrollHeight >= maxHeight) {
	            node.style.width = "" + (2 * node.offsetWidth - node.clientWidth);
	            node.scrollTop = 0;
	        }
	    }
	    HoverBox.setGeometry = setGeometry;
	})(HoverBox = exports.HoverBox || (exports.HoverBox = {}));
	//# sourceMappingURL=hoverbox.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/hoverbox.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/console/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/console/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var cells_1 = __jupyter_require__('jupyterlab@0.15.1/lib/cells/index.js');
	var outputarea_1 = __jupyter_require__('jupyterlab@0.15.1/lib/outputarea/index.js');
	var foreign_1 = __jupyter_require__('jupyterlab@0.15.1/lib/console/foreign.js');
	var history_1 = __jupyter_require__('jupyterlab@0.15.1/lib/console/history.js');
	var observablevector_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/observablevector.js');
	/**
	 * The class name added to console widgets.
	 */
	var CONSOLE_CLASS = 'jp-CodeConsole';
	/**
	 * The class name added to the console banner.
	 */
	var BANNER_CLASS = 'jp-CodeConsole-banner';
	/**
	 * The class name of a cell whose input originated from a foreign session.
	 */
	var FOREIGN_CELL_CLASS = 'jp-CodeConsole-foreignCell';
	/**
	 * The class name of the active prompt
	 */
	var PROMPT_CLASS = 'jp-CodeConsole-prompt';
	/**
	 * The class name of the panel that holds cell content.
	 */
	var CONTENT_CLASS = 'jp-CodeConsole-content';
	/**
	 * The class name of the panel that holds prompts.
	 */
	var INPUT_CLASS = 'jp-CodeConsole-input';
	/**
	 * The timeout in ms for execution requests to the kernel.
	 */
	var EXECUTION_TIMEOUT = 250;
	/**
	 * A widget containing a Jupyter console.
	 *
	 * #### Notes
	 * The CodeConsole class is intended to be used within a ConsolePanel
	 * instance. Under most circumstances, it is not instantiated by user code.
	 */
	var CodeConsole = (function (_super) {
	    __extends(CodeConsole, _super);
	    /**
	     * Construct a console widget.
	     */
	    function CodeConsole(options) {
	        var _this = this;
	        _super.call(this);
	        this._cells = null;
	        this._content = null;
	        this._foreignHandler = null;
	        this._history = null;
	        this._input = null;
	        this._mimetype = 'text/x-ipython';
	        this.addClass(CONSOLE_CLASS);
	        // Create the panels that hold the content and input.
	        var layout = this.layout = new panel_1.PanelLayout();
	        this._cells = new observablevector_1.ObservableVector();
	        this._content = new panel_1.Panel();
	        this._input = new panel_1.Panel();
	        var factory = this.contentFactory = options.contentFactory;
	        var modelFactory = this.modelFactory = (options.modelFactory || CodeConsole.defaultModelFactory);
	        this.rendermime = options.rendermime;
	        this.session = options.session;
	        this._mimeTypeService = options.mimeTypeService;
	        // Add top-level CSS classes.
	        this._content.addClass(CONTENT_CLASS);
	        this._input.addClass(INPUT_CLASS);
	        // Insert the content and input panes into the widget.
	        layout.addWidget(this._content);
	        layout.addWidget(this._input);
	        // Create the banner.
	        var model = modelFactory.createRawCell({});
	        model.value.text = '...';
	        var banner = this.banner = factory.createBanner({
	            model: model,
	            contentFactory: factory.rawCellContentFactory
	        }, this);
	        banner.addClass(BANNER_CLASS);
	        banner.readOnly = true;
	        this._content.addWidget(banner);
	        // Set the banner text and the mimetype.
	        this._initialize();
	        // Set up the foreign iopub handler.
	        this._foreignHandler = factory.createForeignHandler({
	            kernel: this.session.kernel,
	            parent: this,
	            cellFactory: function () { return _this._createForeignCell(); },
	        });
	        this._history = factory.createConsoleHistory({
	            kernel: this.session.kernel
	        });
	        this.session.kernelChanged.connect(this._onKernelChanged, this);
	    }
	    Object.defineProperty(CodeConsole.prototype, "cells", {
	        /**
	         * The list of content cells in the console.
	         *
	         * #### Notes
	         * This list does not include the banner or the prompt for a console.
	         */
	        get: function () {
	            return this._cells;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeConsole.prototype, "prompt", {
	        /*
	         * The console input prompt.
	         */
	        get: function () {
	            var inputLayout = this._input.layout;
	            return inputLayout.widgets.at(0) || null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a new cell to the content panel.
	     *
	     * @param cell - The cell widget being added to the content panel.
	     *
	     * #### Notes
	     * This method is meant for use by outside classes that want to inject content
	     * into a console. It is distinct from the `inject` method in that it requires
	     * rendered code cell widgets and does not execute them.
	     */
	    CodeConsole.prototype.addCell = function (cell) {
	        this._content.addWidget(cell);
	        this._cells.pushBack(cell);
	        cell.disposed.connect(this._onCellDisposed, this);
	        this.update();
	    };
	    /**
	     * Clear the code cells.
	     */
	    CodeConsole.prototype.clear = function () {
	        // Dispose all the content cells except the first, which is the banner.
	        var cells = this._content.widgets;
	        while (cells.length > 1) {
	            cells.at(1).dispose();
	        }
	    };
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    CodeConsole.prototype.dispose = function () {
	        // Do nothing if already disposed.
	        if (this._foreignHandler === null) {
	            return;
	        }
	        var foreignHandler = this._foreignHandler;
	        var history = this._history;
	        var cells = this._cells;
	        this._foreignHandler = null;
	        this._history = null;
	        this._cells = null;
	        foreignHandler.dispose();
	        history.dispose();
	        cells.clear();
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Execute the current prompt.
	     *
	     * @param force - Whether to force execution without checking code
	     * completeness.
	     *
	     * @param timeout - The length of time, in milliseconds, that the execution
	     * should wait for the API to determine whether code being submitted is
	     * incomplete before attempting submission anyway. The default value is `250`.
	     */
	    CodeConsole.prototype.execute = function (force, timeout) {
	        var _this = this;
	        if (force === void 0) { force = false; }
	        if (timeout === void 0) { timeout = EXECUTION_TIMEOUT; }
	        if (this.session.status === 'dead') {
	            return Promise.resolve(void 0);
	        }
	        var prompt = this.prompt;
	        prompt.trusted = true;
	        if (force) {
	            // Create a new prompt before kernel execution to allow typeahead.
	            this.newPrompt();
	            return this._execute(prompt);
	        }
	        // Check whether we should execute.
	        return this._shouldExecute(timeout).then(function (should) {
	            if (_this.isDisposed) {
	                return;
	            }
	            if (should) {
	                // Create a new prompt before kernel execution to allow typeahead.
	                _this.newPrompt();
	                return _this._execute(prompt);
	            }
	        });
	    };
	    /**
	     * Inject arbitrary code for the console to execute immediately.
	     *
	     * @param code - The code contents of the cell being injected.
	     *
	     * @returns A promise that indicates when the injected cell's execution ends.
	     */
	    CodeConsole.prototype.inject = function (code) {
	        var cell = this._createForeignCell();
	        cell.model.value.text = code;
	        this.addCell(cell);
	        return this._execute(cell);
	    };
	    /**
	     * Insert a line break in the prompt.
	     */
	    CodeConsole.prototype.insertLinebreak = function () {
	        var prompt = this.prompt;
	        var model = prompt.model;
	        var editor = prompt.editor;
	        // Insert the line break at the cursor position, and move cursor forward.
	        var pos = editor.getCursorPosition();
	        var offset = editor.getOffsetAt(pos);
	        var text = model.value.text;
	        model.value.text = text.substr(0, offset) + '\n' + text.substr(offset);
	        pos = editor.getPositionAt(offset + 1);
	        editor.setCursorPosition(pos);
	    };
	    /**
	     * Serialize the output.
	     */
	    CodeConsole.prototype.serialize = function () {
	        var prompt = this.prompt;
	        var layout = this._content.layout;
	        // Serialize content.
	        var output = iteration_1.map(layout.widgets, function (widget) {
	            return widget.model.toJSON();
	        });
	        // Serialize prompt and return.
	        return iteration_1.toArray(output).concat(prompt.model.toJSON());
	    };
	    /**
	     * Handle the DOM events for the widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the notebook panel's node. It should
	     * not be called directly by user code.
	     */
	    CodeConsole.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'keydown':
	                this._evtKeyDown(event);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle `after_attach` messages for the widget.
	     */
	    CodeConsole.prototype.onAfterAttach = function (msg) {
	        var node = this.node;
	        node.addEventListener('keydown', this, true);
	        // Create a prompt if necessary.
	        if (!this.prompt) {
	            this.newPrompt();
	        }
	        else {
	            this.prompt.editor.focus();
	            this.update();
	        }
	    };
	    /**
	     * Handle `before_detach` messages for the widget.
	     */
	    CodeConsole.prototype.onBeforeDetach = function (msg) {
	        var node = this.node;
	        node.removeEventListener('keydown', this, true);
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    CodeConsole.prototype.onActivateRequest = function (msg) {
	        this.prompt.editor.focus();
	        this.update();
	    };
	    /**
	     * Make a new prompt.
	     */
	    CodeConsole.prototype.newPrompt = function () {
	        var prompt = this.prompt;
	        var input = this._input;
	        // Make the last prompt read-only, clear its signals, and move to content.
	        if (prompt) {
	            prompt.readOnly = true;
	            prompt.removeClass(PROMPT_CLASS);
	            signaling_1.clearSignalData(prompt.editor);
	            input.layout.removeWidgetAt(0);
	            this.addCell(prompt);
	        }
	        // Create the new prompt.
	        var factory = this.contentFactory;
	        var options = this._createCodeCellOptions();
	        prompt = factory.createPrompt(options, this);
	        prompt.model.mimeType = this._mimetype;
	        prompt.addClass(PROMPT_CLASS);
	        this._input.addWidget(prompt);
	        // Suppress the default "Enter" key handling.
	        var editor = prompt.editor;
	        editor.addKeydownHandler(this._onEditorKeydown);
	        this._history.editor = editor;
	        if (this.isAttached) {
	            prompt.editor.focus();
	            this.update();
	        }
	        this.promptCreated.emit(prompt);
	    };
	    /**
	     * Handle `update-request` messages.
	     */
	    CodeConsole.prototype.onUpdateRequest = function (msg) {
	        Private.scrollToBottom(this._content.node);
	    };
	    /**
	     * Handle the `'keydown'` event for the widget.
	     */
	    CodeConsole.prototype._evtKeyDown = function (event) {
	        var editor = this.prompt.editor;
	        if (event.keyCode === 13 && !editor.hasFocus()) {
	            editor.focus();
	        }
	    };
	    /**
	     * Initialize the banner and mimetype.
	     */
	    CodeConsole.prototype._initialize = function () {
	        var _this = this;
	        var kernel = this.session.kernel;
	        if (!kernel) {
	            return;
	        }
	        kernel.ready.then(function () {
	            if (_this.isDisposed) {
	                return;
	            }
	            _this._handleInfo(kernel.info);
	        });
	    };
	    /**
	     * Execute the code in the current prompt.
	     */
	    CodeConsole.prototype._execute = function (cell) {
	        var _this = this;
	        this._history.push(cell.model.value.text);
	        cell.model.contentChanged.connect(this.update, this);
	        var onSuccess = function (value) {
	            if (_this.isDisposed) {
	                return;
	            }
	            if (value && value.content.status === 'ok') {
	                var content = value.content;
	                // Use deprecated payloads for backwards compatibility.
	                if (content.payload && content.payload.length) {
	                    var setNextInput = content.payload.filter(function (i) {
	                        return i.source === 'set_next_input';
	                    })[0];
	                    if (setNextInput) {
	                        var text = setNextInput.text;
	                        // Ignore the `replace` value and always set the next cell.
	                        cell.model.value.text = text;
	                    }
	                }
	            }
	            cell.model.contentChanged.disconnect(_this.update, _this);
	            _this.update();
	            _this.executed.emit(new Date());
	        };
	        var onFailure = function () {
	            if (_this.isDisposed) {
	                return;
	            }
	            cell.model.contentChanged.disconnect(_this.update, _this);
	            _this.update();
	        };
	        return cell.execute(this.session.kernel).then(onSuccess, onFailure);
	    };
	    /**
	     * Update the console based on the kernel info.
	     */
	    CodeConsole.prototype._handleInfo = function (info) {
	        var layout = this._content.layout;
	        var banner = layout.widgets.at(0);
	        banner.model.value.text = info.banner;
	        var lang = info.language_info;
	        this._mimetype = this._mimeTypeService.getMimeTypeByLanguage(lang);
	        if (this.prompt) {
	            this.prompt.model.mimeType = this._mimetype;
	        }
	    };
	    /**
	     * Create a new foreign cell.
	     */
	    CodeConsole.prototype._createForeignCell = function () {
	        var factory = this.contentFactory;
	        var options = this._createCodeCellOptions();
	        var cell = factory.createForeignCell(options, this);
	        cell.readOnly = true;
	        cell.model.mimeType = this._mimetype;
	        cell.addClass(FOREIGN_CELL_CLASS);
	        return cell;
	    };
	    /**
	     * Create the options used to initialize a code cell widget.
	     */
	    CodeConsole.prototype._createCodeCellOptions = function () {
	        var factory = this.contentFactory;
	        var contentFactory = factory.codeCellContentFactory;
	        var modelFactory = this.modelFactory;
	        var model = modelFactory.createCodeCell({});
	        var rendermime = this.rendermime;
	        return { model: model, rendermime: rendermime, contentFactory: contentFactory };
	    };
	    /**
	     * Handle cell disposed signals.
	     */
	    CodeConsole.prototype._onCellDisposed = function (sender, args) {
	        if (!this.isDisposed) {
	            this._cells.remove(sender);
	        }
	    };
	    /**
	     * Test whether we should execute the prompt.
	     */
	    CodeConsole.prototype._shouldExecute = function (timeout) {
	        var _this = this;
	        var prompt = this.prompt;
	        var model = prompt.model;
	        var code = model.value.text + '\n';
	        return new Promise(function (resolve, reject) {
	            var timer = setTimeout(function () { resolve(true); }, timeout);
	            _this.session.kernel.requestIsComplete({ code: code }).then(function (isComplete) {
	                clearTimeout(timer);
	                if (_this.isDisposed) {
	                    resolve(false);
	                }
	                if (isComplete.content.status !== 'incomplete') {
	                    resolve(true);
	                    return;
	                }
	                model.value.text = code + isComplete.content.indent;
	                var editor = prompt.editor;
	                var pos = editor.getPositionAt(model.value.text.length);
	                editor.setCursorPosition(pos);
	                resolve(false);
	            }).catch(function () { resolve(true); });
	        });
	    };
	    /**
	     * Handle a keydown event on an editor.
	     */
	    CodeConsole.prototype._onEditorKeydown = function (editor, event) {
	        // Suppress "Enter" events.
	        return event.keyCode === 13;
	    };
	    /**
	     * Handle a change to the kernel.
	     */
	    CodeConsole.prototype._onKernelChanged = function (sender, kernel) {
	        this.clear();
	        this._initialize();
	        this._history.kernel = kernel;
	        this._foreignHandler.kernel = kernel;
	        this.newPrompt();
	    };
	    return CodeConsole;
	}(widget_1.Widget));
	exports.CodeConsole = CodeConsole;
	// Define the signals for the `CodeConsole` class.
	signaling_1.defineSignal(CodeConsole.prototype, 'executed');
	signaling_1.defineSignal(CodeConsole.prototype, 'promptCreated');
	/**
	 * A namespace for CodeConsole statics.
	 */
	var CodeConsole;
	(function (CodeConsole) {
	    /**
	     * Default implementation of `IContentFactory`.
	     */
	    var ContentFactory = (function () {
	        /**
	         * Create a new content factory.
	         */
	        function ContentFactory(options) {
	            var editorFactory = options.editorFactory;
	            var outputAreaContentFactory = (options.outputAreaContentFactory ||
	                outputarea_1.OutputAreaWidget.defaultContentFactory);
	            this.codeCellContentFactory = (options.codeCellContentFactory ||
	                new cells_1.CodeCellWidget.ContentFactory({
	                    editorFactory: editorFactory,
	                    outputAreaContentFactory: outputAreaContentFactory
	                }));
	            this.rawCellContentFactory = (options.rawCellContentFactory ||
	                new cells_1.RawCellWidget.ContentFactory({ editorFactory: editorFactory }));
	        }
	        /**
	         * The history manager for a console widget.
	         */
	        ContentFactory.prototype.createConsoleHistory = function (options) {
	            return new history_1.ConsoleHistory(options);
	        };
	        /**
	         * The foreign handler for a console widget.
	         */
	        ContentFactory.prototype.createForeignHandler = function (options) {
	            return new foreign_1.ForeignHandler(options);
	        };
	        /**
	         * Create a new banner widget.
	         */
	        ContentFactory.prototype.createBanner = function (options, parent) {
	            return new cells_1.RawCellWidget(options);
	        };
	        /**
	         * Create a new prompt widget.
	         */
	        ContentFactory.prototype.createPrompt = function (options, parent) {
	            return new cells_1.CodeCellWidget(options);
	        };
	        /**
	         * Create a new code cell widget for an input from a foreign session.
	         */
	        ContentFactory.prototype.createForeignCell = function (options, parent) {
	            return new cells_1.CodeCellWidget(options);
	        };
	        return ContentFactory;
	    }());
	    CodeConsole.ContentFactory = ContentFactory;
	    /**
	     * The default implementation of an `IModelFactory`.
	     */
	    var ModelFactory = (function () {
	        /**
	         * Create a new cell model factory.
	         */
	        function ModelFactory(options) {
	            this.codeCellContentFactory = (options.codeCellContentFactory ||
	                cells_1.CodeCellModel.defaultContentFactory);
	        }
	        /**
	         * Create a new code cell.
	         *
	         * @param source - The data to use for the original source data.
	         *
	         * @returns A new code cell. If a source cell is provided, the
	         *   new cell will be intialized with the data from the source.
	         *   If the contentFactory is not provided, the instance
	         *   `codeCellContentFactory` will be used.
	         */
	        ModelFactory.prototype.createCodeCell = function (options) {
	            if (!options.contentFactory) {
	                options.contentFactory = this.codeCellContentFactory;
	            }
	            return new cells_1.CodeCellModel(options);
	        };
	        /**
	         * Create a new raw cell.
	         *
	         * @param source - The data to use for the original source data.
	         *
	         * @returns A new raw cell. If a source cell is provided, the
	         *   new cell will be intialized with the data from the source.
	         */
	        ModelFactory.prototype.createRawCell = function (options) {
	            return new cells_1.RawCellModel(options);
	        };
	        return ModelFactory;
	    }());
	    CodeConsole.ModelFactory = ModelFactory;
	    /**
	     * The default `ModelFactory` instance.
	     */
	    CodeConsole.defaultModelFactory = new ModelFactory({});
	})(CodeConsole = exports.CodeConsole || (exports.CodeConsole = {}));
	/**
	 * A namespace for console widget private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Jump to the bottom of a node.
	     *
	     * @param node - The scrollable element.
	     */
	    function scrollToBottom(node) {
	        node.scrollTop = node.scrollHeight - node.clientHeight;
	    }
	    Private.scrollToBottom = scrollToBottom;
	})(Private || (Private = {}));
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/console/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/cells/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/cells/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/cells/model.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/cells/widget.js'));
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/cells/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/cells/model.js **/
jupyter.define('jupyterlab@0.15.1/lib/cells/model.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var json_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/json.js');
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var codeeditor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/index.js');
	var metadata_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/metadata.js');
	var outputarea_1 = __jupyter_require__('jupyterlab@0.15.1/lib/outputarea/index.js');
	/**
	 * An implementation of the cell model.
	 */
	var CellModel = (function (_super) {
	    __extends(CellModel, _super);
	    /**
	     * Construct a cell model from optional cell content.
	     */
	    function CellModel(options) {
	        _super.call(this);
	        this._metadata = Object.create(null);
	        this._cursors = Object.create(null);
	        this.value.changed.connect(this._onValueChanged, this);
	        var cell = options.cell;
	        if (!cell) {
	            return;
	        }
	        if (Array.isArray(cell.source)) {
	            this.value.text = cell.source.join('\n');
	        }
	        else {
	            this.value.text = cell.source;
	        }
	        var metadata = services_1.utils.copy(cell.metadata);
	        if (this.type !== 'raw') {
	            delete metadata['format'];
	        }
	        if (this.type !== 'code') {
	            delete metadata['collapsed'];
	            delete metadata['scrolled'];
	        }
	        this._metadata = metadata;
	    }
	    /**
	     * Dispose of the resources held by the model.
	     */
	    CellModel.prototype.dispose = function () {
	        // Do nothing if already disposed.
	        if (this.isDisposed) {
	            return;
	        }
	        for (var key in this._cursors) {
	            this._cursors[key].dispose();
	        }
	        this._cursors = null;
	        this._metadata = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Serialize the model to JSON.
	     */
	    CellModel.prototype.toJSON = function () {
	        return {
	            cell_type: this.type,
	            source: this.value.text,
	            metadata: services_1.utils.copy(this._metadata)
	        };
	    };
	    /**
	     * Get a metadata cursor for the cell.
	     *
	     * #### Notes
	     * Metadata associated with the nbformat spec are set directly
	     * on the model.  This method is used to interact with a namespaced
	     * set of metadata on the cell.
	     */
	    CellModel.prototype.getMetadata = function (name) {
	        var _this = this;
	        if (this.isDisposed) {
	            return null;
	        }
	        if (name in this._cursors) {
	            return this._cursors[name];
	        }
	        var cursor = new metadata_1.MetadataCursor(name, function () {
	            return _this._metadata[name];
	        }, function (value) {
	            _this.setCursorData(name, value);
	        });
	        this._cursors[name] = cursor;
	        return cursor;
	    };
	    /**
	     * List the metadata namespace keys for the notebook.
	     *
	     * #### Notes
	     * Metadata associated with the nbformat are not included.
	     */
	    CellModel.prototype.listMetadata = function () {
	        return iteration_1.iter(Object.keys(this._metadata));
	    };
	    /**
	     * Set the cursor data for a given field.
	     */
	    CellModel.prototype.setCursorData = function (name, newValue) {
	        var oldValue = this._metadata[name];
	        if (json_1.deepEqual(oldValue, newValue)) {
	            return;
	        }
	        this._metadata[name] = newValue;
	        this.contentChanged.emit(void 0);
	        this.metadataChanged.emit({ name: name, oldValue: oldValue, newValue: newValue });
	    };
	    /**
	     * Handle a change to the observable value.
	     */
	    CellModel.prototype._onValueChanged = function (sender, args) {
	        this.contentChanged.emit(void 0);
	    };
	    return CellModel;
	}(codeeditor_1.CodeEditor.Model));
	exports.CellModel = CellModel;
	// Define the signals for the `CellModel` class.
	signaling_1.defineSignal(CellModel.prototype, 'contentChanged');
	signaling_1.defineSignal(CellModel.prototype, 'metadataChanged');
	signaling_1.defineSignal(CellModel.prototype, 'stateChanged');
	/**
	 * An implementation of a raw cell model.
	 */
	var RawCellModel = (function (_super) {
	    __extends(RawCellModel, _super);
	    function RawCellModel() {
	        _super.apply(this, arguments);
	    }
	    Object.defineProperty(RawCellModel.prototype, "type", {
	        /**
	         * The type of the cell.
	         */
	        get: function () {
	            return 'raw';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return RawCellModel;
	}(CellModel));
	exports.RawCellModel = RawCellModel;
	/**
	 * An implementation of a markdown cell model.
	 */
	var MarkdownCellModel = (function (_super) {
	    __extends(MarkdownCellModel, _super);
	    function MarkdownCellModel() {
	        _super.apply(this, arguments);
	    }
	    Object.defineProperty(MarkdownCellModel.prototype, "type", {
	        /**
	         * The type of the cell.
	         */
	        get: function () {
	            return 'markdown';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return MarkdownCellModel;
	}(CellModel));
	exports.MarkdownCellModel = MarkdownCellModel;
	/**
	 * An implementation of a code cell Model.
	 */
	var CodeCellModel = (function (_super) {
	    __extends(CodeCellModel, _super);
	    /**
	     * Construct a new code cell with optional original cell content.
	     */
	    function CodeCellModel(options) {
	        _super.call(this, options);
	        this._outputs = null;
	        this._executionCount = null;
	        var factory = (options.contentFactory ||
	            CodeCellModel.defaultContentFactory);
	        this._outputs = factory.createOutputArea();
	        var cell = options.cell;
	        if (cell && cell.cell_type === 'code') {
	            this.executionCount = cell.execution_count;
	            for (var _i = 0, _a = cell.outputs; _i < _a.length; _i++) {
	                var output = _a[_i];
	                this._outputs.add(output);
	            }
	        }
	        this._outputs.changed.connect(this._onOutputsChanged, this);
	    }
	    Object.defineProperty(CodeCellModel.prototype, "type", {
	        /**
	         * The type of the cell.
	         */
	        get: function () {
	            return 'code';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeCellModel.prototype, "executionCount", {
	        /**
	         * The execution count of the cell.
	         */
	        get: function () {
	            return this._executionCount || null;
	        },
	        set: function (newValue) {
	            if (newValue === this._executionCount) {
	                return;
	            }
	            var oldValue = this.executionCount;
	            this._executionCount = newValue || null;
	            this.contentChanged.emit(void 0);
	            this.stateChanged.emit({ name: 'executionCount', oldValue: oldValue, newValue: newValue });
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CodeCellModel.prototype, "outputs", {
	        /**
	         * The cell outputs.
	         */
	        get: function () {
	            return this._outputs;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the model.
	     */
	    CodeCellModel.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._outputs.dispose();
	        this._outputs = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Serialize the model to JSON.
	     */
	    CodeCellModel.prototype.toJSON = function () {
	        var cell = _super.prototype.toJSON.call(this);
	        cell.execution_count = this.executionCount || null;
	        var outputs = this.outputs;
	        cell.outputs = [];
	        for (var i = 0; i < outputs.length; i++) {
	            var output = outputs.get(i);
	            if (output.output_type !== 'input_request') {
	                cell.outputs.push(output);
	            }
	        }
	        return cell;
	    };
	    /**
	     * Handle the outputs changing.
	     */
	    CodeCellModel.prototype._onOutputsChanged = function () {
	        this.contentChanged.emit(void 0);
	    };
	    return CodeCellModel;
	}(CellModel));
	exports.CodeCellModel = CodeCellModel;
	/**
	 * The namespace for `CodeCellModel` statics.
	 */
	var CodeCellModel;
	(function (CodeCellModel) {
	    /**
	     * The default implementation of an `IContentFactory`.
	     */
	    var ContentFactory = (function () {
	        function ContentFactory() {
	        }
	        /**
	         * Create an output area.
	         */
	        ContentFactory.prototype.createOutputArea = function () {
	            return new outputarea_1.OutputAreaModel();
	        };
	        return ContentFactory;
	    }());
	    CodeCellModel.ContentFactory = ContentFactory;
	    /**
	     * The shared `ConetntFactory` instance.
	     */
	    CodeCellModel.defaultContentFactory = new ContentFactory();
	})(CodeCellModel = exports.CodeCellModel || (exports.CodeCellModel = {}));
	//# sourceMappingURL=model.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/cells/model.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/metadata.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/metadata.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * An implementation of a metadata cursor.
	 */
	var MetadataCursor = (function () {
	    /**
	     * Construct a new metadata cursor.
	     *
	     * @param name - The metadata namespace key.
	     *
	     * @param read - The read callback.
	     *
	     * @param write - The write callback.
	     */
	    function MetadataCursor(name, read, write) {
	        this._name = '';
	        this._read = null;
	        this._write = null;
	        this._name = name;
	        this._read = read;
	        this._write = write;
	    }
	    Object.defineProperty(MetadataCursor.prototype, "name", {
	        /**
	         * Get the namespace key of the metadata.
	         */
	        get: function () {
	            return this._name;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the cursor.
	     *
	     * #### Notes
	     * This is not meant to be called by user code.
	     */
	    MetadataCursor.prototype.dispose = function () {
	        this._read = null;
	        this._write = null;
	    };
	    /**
	     * Get the value of the namespace data.
	     */
	    MetadataCursor.prototype.getValue = function () {
	        var read = this._read;
	        return read();
	    };
	    /**
	     * Set the value of the namespace data.
	     */
	    MetadataCursor.prototype.setValue = function (value) {
	        var write = this._write;
	        write(value);
	    };
	    return MetadataCursor;
	}());
	exports.MetadataCursor = MetadataCursor;
	//# sourceMappingURL=metadata.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/metadata.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/outputarea/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/outputarea/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/outputarea/model.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/outputarea/widget.js'));
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/outputarea/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/outputarea/model.js **/
jupyter.define('jupyterlab@0.15.1/lib/outputarea/model.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var observablevector_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/observablevector.js');
	/**
	 * An model that maintains a list of output data.
	 */
	var OutputAreaModel = (function () {
	    /**
	     * Construct a new observable outputs instance.
	     */
	    function OutputAreaModel() {
	        this.clearNext = false;
	        this.list = null;
	        this.list = new observablevector_1.ObservableVector();
	        this.list.changed.connect(this._onListChanged, this);
	    }
	    Object.defineProperty(OutputAreaModel.prototype, "length", {
	        /**
	         * Get the length of the items in the model.
	         */
	        get: function () {
	            return this.list ? this.list.length : 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(OutputAreaModel.prototype, "isDisposed", {
	        /**
	         * Test whether the model is disposed.
	         */
	        get: function () {
	            return this.list === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the model.
	     */
	    OutputAreaModel.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        var list = this.list;
	        this.list = null;
	        list.clear();
	        this.disposed.emit(void 0);
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Get an item at the specified index.
	     */
	    OutputAreaModel.prototype.get = function (index) {
	        return this.list.at(index);
	    };
	    /**
	     * Add an output, which may be combined with previous output.
	     *
	     * #### Notes
	     * The output bundle is copied.
	     * Contiguous stream outputs of the same `name` are combined.
	     */
	    OutputAreaModel.prototype.add = function (output) {
	        // If we received a delayed clear message, then clear now.
	        if (this.clearNext) {
	            this.clear();
	            this.clearNext = false;
	        }
	        if (output.output_type === 'input_request') {
	            this.list.pushBack(output);
	        }
	        // Make a copy of the output bundle.
	        var value = JSON.parse(JSON.stringify(output));
	        // Join multiline text outputs.
	        if (value.output_type === 'stream') {
	            if (Array.isArray(value.text)) {
	                value.text = value.text.join('\n');
	            }
	        }
	        // Consolidate outputs if they are stream outputs of the same kind.
	        var index = this.length - 1;
	        var lastOutput = this.get(index);
	        if (value.output_type === 'stream'
	            && lastOutput && lastOutput.output_type === 'stream'
	            && value.name === lastOutput.name) {
	            // In order to get a list change event, we add the previous
	            // text to the current item and replace the previous item.
	            // This also replaces the metadata of the last item.
	            var text = value.text;
	            value.text = lastOutput.text + text;
	            this.list.set(index, value);
	            return index;
	        }
	        else {
	            switch (value.output_type) {
	                case 'stream':
	                case 'execute_result':
	                case 'display_data':
	                case 'error':
	                    return this.list.pushBack(value);
	                default:
	                    break;
	            }
	        }
	        return -1;
	    };
	    /**
	     * Clear all of the output.
	     *
	     * @param wait Delay clearing the output until the next message is added.
	     */
	    OutputAreaModel.prototype.clear = function (wait) {
	        if (wait === void 0) { wait = false; }
	        if (wait) {
	            this.clearNext = true;
	            return;
	        }
	        this.list.clear();
	    };
	    /**
	     * Add a mime type to an output data bundle.
	     *
	     * @param output - The output to augment.
	     *
	     * @param mimetype - The mimetype to add.
	     *
	     * @param value - The value to add.
	     *
	     * #### Notes
	     * The output must be contained in the model, or an error will be thrown.
	     * Only non-existent types can be added.
	     * Types are validated before being added.
	     */
	    OutputAreaModel.prototype.addMimeData = function (output, mimetype, value) {
	        var index = searching_1.indexOf(this.list, output);
	        if (index === -1) {
	            throw new Error("Cannot add data to non-tracked bundle");
	        }
	        if (mimetype in output.data) {
	            console.warn("Cannot add existing key '" + mimetype + "' to bundle");
	            return;
	        }
	        if (services_1.nbformat.validateMimeValue(mimetype, value)) {
	            output.data[mimetype] = value;
	        }
	        else {
	            console.warn("Refusing to add invalid mime value of type " + mimetype + " to output");
	        }
	    };
	    /**
	     * Execute code on a kernel and send outputs to the model.
	     */
	    OutputAreaModel.prototype.execute = function (code, kernel) {
	        var _this = this;
	        // Override the default for `stop_on_error`.
	        var content = {
	            code: code,
	            stop_on_error: true
	        };
	        this.clear();
	        return new Promise(function (resolve, reject) {
	            var future = kernel.requestExecute(content);
	            // Handle published messages.
	            future.onIOPub = function (msg) {
	                var msgType = msg.header.msg_type;
	                switch (msgType) {
	                    case 'execute_result':
	                    case 'display_data':
	                    case 'stream':
	                    case 'error':
	                        var model = msg.content;
	                        model.output_type = msgType;
	                        _this.add(model);
	                        break;
	                    case 'clear_output':
	                        _this.clear(msg.content.wait);
	                        break;
	                    default:
	                        break;
	                }
	            };
	            // Handle the execute reply.
	            future.onReply = function (msg) {
	                resolve(msg);
	                // API responses that contain a pager are special cased and their type
	                // is overriden from 'execute_reply' to 'display_data' in order to
	                // render output.
	                var content = msg.content;
	                var payload = content && content.payload;
	                if (!payload || !payload.length) {
	                    return;
	                }
	                var pages = payload.filter(function (i) { return i.source === 'page'; });
	                if (!pages.length) {
	                    return;
	                }
	                var page = JSON.parse(JSON.stringify(pages[0]));
	                var model = {
	                    output_type: 'display_data',
	                    data: page.data,
	                    metadata: {}
	                };
	                _this.add(model);
	            };
	            // Handle stdin.
	            future.onStdin = function (msg) {
	                if (services_1.KernelMessage.isInputRequestMsg(msg)) {
	                    _this.add({
	                        output_type: 'input_request',
	                        prompt: msg.content.prompt,
	                        password: msg.content.password,
	                        kernel: kernel
	                    });
	                }
	            };
	        });
	    };
	    /**
	     * Handle a change to the list.
	     */
	    OutputAreaModel.prototype._onListChanged = function (sender, args) {
	        this.changed.emit(args);
	    };
	    return OutputAreaModel;
	}());
	exports.OutputAreaModel = OutputAreaModel;
	/**
	 * A namespace for OutputAreaModel statics.
	 */
	var OutputAreaModel;
	(function (OutputAreaModel) {
	    /**
	     * Get the mime bundle for an output.
	     *
	     * @params output - A kernel output message payload.
	     *
	     * @returns - A mime bundle for the payload.
	     */
	    function getBundle(output) {
	        var bundle;
	        switch (output.output_type) {
	            case 'execute_result':
	                bundle = output.data;
	                break;
	            case 'display_data':
	                bundle = output.data;
	                break;
	            case 'stream':
	                var text = output.text;
	                bundle = {
	                    'application/vnd.jupyter.console-text': text
	                };
	                break;
	            case 'error':
	                var out = output;
	                var traceback = out.traceback.join('\n');
	                bundle = {
	                    'application/vnd.jupyter.console-text': traceback ||
	                        out.ename + ": " + out.evalue
	                };
	                break;
	            default:
	                break;
	        }
	        return bundle || {};
	    }
	    OutputAreaModel.getBundle = getBundle;
	    /**
	     * Convert a mime bundle to a mime map.
	     */
	    function convertBundle(bundle) {
	        var map = Object.create(null);
	        for (var mimeType in bundle) {
	            var value = bundle[mimeType];
	            if (Array.isArray(value)) {
	                map[mimeType] = value.join('\n');
	            }
	            else {
	                map[mimeType] = value;
	            }
	        }
	        return map;
	    }
	    OutputAreaModel.convertBundle = convertBundle;
	})(OutputAreaModel = exports.OutputAreaModel || (exports.OutputAreaModel = {}));
	// Define the signals for the `OutputAreaModel` class.
	signaling_1.defineSignal(OutputAreaModel.prototype, 'changed');
	signaling_1.defineSignal(OutputAreaModel.prototype, 'disposed');
	//# sourceMappingURL=model.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/outputarea/model.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/observablevector.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/observablevector.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	/**
	 * A concrete implementation of [[IObservableVector]].
	 */
	var ObservableVector = (function (_super) {
	    __extends(ObservableVector, _super);
	    function ObservableVector() {
	        _super.apply(this, arguments);
	        this._isDisposed = false;
	    }
	    Object.defineProperty(ObservableVector.prototype, "isDisposed", {
	        /**
	         * Test whether the vector has been disposed.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the vector.
	     */
	    ObservableVector.prototype.dispose = function () {
	        if (this._isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        signaling_1.clearSignalData(this);
	        this.clear();
	    };
	    /**
	     * Set the value at the specified index.
	     *
	     * @param index - The positive integer index of interest.
	     *
	     * @param value - The value to set at the specified index.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * No changes.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral or out of range.
	     */
	    ObservableVector.prototype.set = function (index, value) {
	        var oldValues = [this.at(index)];
	        _super.prototype.set.call(this, index, value);
	        this.changed.emit({
	            type: 'set',
	            oldIndex: index,
	            newIndex: index,
	            oldValues: oldValues,
	            newValues: [value]
	        });
	    };
	    /**
	     * Add a value to the back of the vector.
	     *
	     * @param value - The value to add to the back of the vector.
	     *
	     * @returns The new length of the vector.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * No changes.
	     */
	    ObservableVector.prototype.pushBack = function (value) {
	        var num = _super.prototype.pushBack.call(this, value);
	        this.changed.emit({
	            type: 'add',
	            oldIndex: -1,
	            newIndex: this.length - 1,
	            oldValues: [],
	            newValues: [value]
	        });
	        return num;
	    };
	    /**
	     * Remove and return the value at the back of the vector.
	     *
	     * @returns The value at the back of the vector, or `undefined` if
	     *   the vector is empty.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * Iterators pointing at the removed value are invalidated.
	     */
	    ObservableVector.prototype.popBack = function () {
	        var value = _super.prototype.popBack.call(this);
	        this.changed.emit({
	            type: 'remove',
	            oldIndex: this.length,
	            newIndex: -1,
	            oldValues: [value],
	            newValues: []
	        });
	        return value;
	    };
	    /**
	     * Insert a value into the vector at a specific index.
	     *
	     * @param index - The index at which to insert the value.
	     *
	     * @param value - The value to set at the specified index.
	     *
	     * @returns The new length of the vector.
	     *
	     * #### Complexity
	     * Linear.
	     *
	     * #### Iterator Validity
	     * No changes.
	     *
	     * #### Notes
	     * The `index` will be clamped to the bounds of the vector.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral.
	     */
	    ObservableVector.prototype.insert = function (index, value) {
	        var num = _super.prototype.insert.call(this, index, value);
	        this.changed.emit({
	            type: 'add',
	            oldIndex: -1,
	            newIndex: index,
	            oldValues: [],
	            newValues: [value]
	        });
	        return num;
	    };
	    /**
	     * Remove the first occurrence of a value from the vector.
	     *
	     * @param value - The value of interest.
	     *
	     * @returns The index of the removed value, or `-1` if the value
	     *   is not contained in the vector.
	     *
	     * #### Complexity
	     * Linear.
	     *
	     * #### Iterator Validity
	     * Iterators pointing at the removed value and beyond are invalidated.
	     *
	     * #### Notes
	     * Comparison is performed using strict `===` equality.
	     */
	    ObservableVector.prototype.remove = function (value) {
	        var index = searching_1.indexOf(this, value);
	        this.removeAt(index);
	        return index;
	    };
	    /**
	     * Remove and return the value at a specific index.
	     *
	     * @param index - The index of the value of interest.
	     *
	     * @returns The value at the specified index, or `undefined` if the
	     *   index is out of range.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * Iterators pointing at the removed value and beyond are invalidated.
	     *
	     * #### Undefined Behavior
	     * An `index` which is non-integral.
	     */
	    ObservableVector.prototype.removeAt = function (index) {
	        var value = _super.prototype.removeAt.call(this, index);
	        this.changed.emit({
	            type: 'remove',
	            oldIndex: index,
	            newIndex: -1,
	            oldValues: [value],
	            newValues: []
	        });
	        return value;
	    };
	    /**
	     * Remove all values from the vector.
	     *
	     * #### Complexity
	     * Linear.
	     *
	     * #### Iterator Validity
	     * All current iterators are invalidated.
	     */
	    ObservableVector.prototype.clear = function () {
	        var oldValues = iteration_1.toArray(this);
	        _super.prototype.clear.call(this);
	        this.changed.emit({
	            type: 'remove',
	            oldIndex: 0,
	            newIndex: 0,
	            oldValues: oldValues,
	            newValues: []
	        });
	    };
	    /**
	     * Move a value from one index to another.
	     *
	     * @parm fromIndex - The index of the element to move.
	     *
	     * @param toIndex - The index to move the element to.
	     *
	     * #### Complexity
	     * Constant.
	     *
	     * #### Iterator Validity
	     * Iterators pointing at the lesser of the `fromIndex` and the `toIndex`
	     * and beyond are invalidated.
	     *
	     * #### Undefined Behavior
	     * A `fromIndex` or a `toIndex` which is non-integral.
	     */
	    ObservableVector.prototype.move = function (fromIndex, toIndex) {
	        var value = this.at(fromIndex);
	        _super.prototype.removeAt.call(this, fromIndex);
	        if (toIndex < fromIndex) {
	            _super.prototype.insert.call(this, toIndex - 1, value);
	        }
	        else {
	            _super.prototype.insert.call(this, toIndex, value);
	        }
	        var arr = [value];
	        this.changed.emit({
	            type: 'move',
	            oldIndex: fromIndex,
	            newIndex: toIndex,
	            oldValues: arr,
	            newValues: arr
	        });
	    };
	    /**
	     * Push a set of values to the back of the vector.
	     *
	     * @param values - An iterable or array-like set of values to add.
	     *
	     * @returns The new length of the vector.
	     *
	     * #### Complexity
	     * Linear.
	     *
	     * #### Iterator Validity
	     * No changes.
	     */
	    ObservableVector.prototype.pushAll = function (values) {
	        var _this = this;
	        var newIndex = this.length;
	        var newValues = iteration_1.toArray(values);
	        iteration_1.each(newValues, function (value) { _super.prototype.pushBack.call(_this, value); });
	        this.changed.emit({
	            type: 'add',
	            oldIndex: -1,
	            newIndex: newIndex,
	            oldValues: [],
	            newValues: newValues
	        });
	        return this.length;
	    };
	    /**
	     * Insert a set of items into the vector at the specified index.
	     *
	     * @param index - The index at which to insert the values.
	     *
	     * @param values - The values to insert at the specified index.
	     *
	     * @returns The new length of the vector.
	     *
	     * #### Complexity.
	     * Linear.
	     *
	     * #### Iterator Validity
	     * No changes.
	     *
	     * #### Notes
	     * The `index` will be clamped to the bounds of the vector.
	     *
	     * #### Undefined Behavior.
	     * An `index` which is non-integral.
	     */
	    ObservableVector.prototype.insertAll = function (index, values) {
	        var _this = this;
	        var newIndex = index;
	        var newValues = iteration_1.toArray(values);
	        iteration_1.each(newValues, function (value) { _super.prototype.insert.call(_this, index++, value); });
	        this.changed.emit({
	            type: 'add',
	            oldIndex: -1,
	            newIndex: newIndex,
	            oldValues: [],
	            newValues: newValues
	        });
	        return this.length;
	    };
	    /**
	     * Remove a range of items from the vector.
	     *
	     * @param startIndex - The start index of the range to remove (inclusive).
	     *
	     * @param endIndex - The end index of the range to remove (exclusive).
	     *
	     * @returns The new length of the vector.
	     *
	     * #### Complexity
	     * Linear.
	     *
	     * #### Iterator Validity
	     * Iterators pointing to the first removed value and beyond are invalid.
	     *
	     * #### Undefined Behavior
	     * A `startIndex` or `endIndex` which is non-integral.
	     */
	    ObservableVector.prototype.removeRange = function (startIndex, endIndex) {
	        var oldValues = [];
	        for (var i = startIndex; i < endIndex; i++) {
	            oldValues.push(_super.prototype.removeAt.call(this, startIndex));
	        }
	        this.changed.emit({
	            type: 'remove',
	            oldIndex: startIndex,
	            newIndex: -1,
	            oldValues: oldValues,
	            newValues: []
	        });
	        return this.length;
	    };
	    return ObservableVector;
	}(vector_1.Vector));
	exports.ObservableVector = ObservableVector;
	// Define the signals for the `ObservableVector` class.
	signaling_1.defineSignal(ObservableVector.prototype, 'changed');
	//# sourceMappingURL=observablevector.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/observablevector.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/outputarea/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/outputarea/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var mimedata_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/mimedata.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var dragdrop_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/dragdrop.js');
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var model_1 = __jupyter_require__('jupyterlab@0.15.1/lib/outputarea/model.js');
	/**
	 * The threshold in pixels to start a drag event.
	 */
	var DRAG_THRESHOLD = 5;
	/**
	 * The factory MIME type supported by phosphor dock panels.
	 */
	var FACTORY_MIME = 'application/vnd.phosphor.widget-factory';
	/**
	 * The class name added to an output area widget.
	 */
	var OUTPUT_AREA_CLASS = 'jp-OutputArea';
	/**
	 * The class name added to a "mirrored" output area widget created by a drag.
	 */
	var MIRRORED_OUTPUT_AREA_CLASS = 'jp-MirroredOutputArea';
	/**
	 * The class name added to an output widget.
	 */
	var OUTPUT_CLASS = 'jp-Output';
	/**
	 * The class name added to an execute result.
	 */
	var EXECUTE_CLASS = 'jp-Output-executeResult';
	/**
	 * The class name added to display data.
	 */
	var DISPLAY_CLASS = 'jp-Output-displayData';
	/**
	 * The class name added to stdout data.
	 */
	var STDOUT_CLASS = 'jp-Output-stdout';
	/**
	 * The class name added to stderr data.
	 */
	var STDERR_CLASS = 'jp-Output-stderr';
	/**
	 * The class name added to error data.
	 */
	var ERROR_CLASS = 'jp-Output-error';
	/**
	 * The class name added to stdin data.
	 */
	var STDIN_CLASS = 'jp-Output-stdin';
	/**
	 * The class name added to stdin data prompt nodes.
	 */
	var STDIN_PROMPT_CLASS = 'jp-Output-stdinPrompt';
	/**
	 * The class name added to stdin data input nodes.
	 */
	var STDIN_INPUT_CLASS = 'jp-Output-stdinInput';
	/**
	 * The class name added to stdin rendered text nodes.
	 */
	var STDIN_RENDERED_CLASS = 'jp-Output-stdinRendered';
	/**
	 * The class name added to fixed height output areas.
	 */
	var FIXED_HEIGHT_CLASS = 'jp-mod-fixedHeight';
	/**
	 * The class name added to collaped output areas.
	 */
	var COLLAPSED_CLASS = 'jp-mod-collapsed';
	/**
	 * The class name added to output area prompts.
	 */
	var PROMPT_CLASS = 'jp-Output-prompt';
	/**
	 * The class name added to output area results.
	 */
	var RESULT_CLASS = 'jp-Output-result';
	/**
	 * An output area widget.
	 *
	 * #### Notes
	 * The widget model must be set separately and can be changed
	 * at any time.  Consumers of the widget must account for a
	 * `null` model, and may want to listen to the `modelChanged`
	 * signal.
	 */
	var OutputAreaWidget = (function (_super) {
	    __extends(OutputAreaWidget, _super);
	    /**
	     * Construct an output area widget.
	     */
	    function OutputAreaWidget(options) {
	        _super.call(this);
	        this._trusted = false;
	        this._fixedHeight = false;
	        this._collapsed = false;
	        this._minHeightTimeout = null;
	        this._model = null;
	        this._injecting = false;
	        this.addClass(OUTPUT_AREA_CLASS);
	        this.rendermime = options.rendermime;
	        this.contentFactory = (options.contentFactory || OutputAreaWidget.defaultContentFactory);
	        this.layout = new panel_1.PanelLayout();
	    }
	    /**
	     * Create a mirrored output widget.
	     */
	    OutputAreaWidget.prototype.mirror = function () {
	        var rendermime = this.rendermime;
	        var contentFactory = this.contentFactory;
	        var widget = new OutputAreaWidget({ rendermime: rendermime, contentFactory: contentFactory });
	        widget.model = this._model;
	        widget.trusted = this._trusted;
	        widget.title.label = 'Mirrored Output';
	        widget.title.closable = true;
	        widget.addClass(MIRRORED_OUTPUT_AREA_CLASS);
	        return widget;
	    };
	    Object.defineProperty(OutputAreaWidget.prototype, "widgets", {
	        /**
	         * A read-only sequence of the widgets in the output area.
	         */
	        get: function () {
	            return this.layout.widgets;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(OutputAreaWidget.prototype, "model", {
	        /**
	         * The model for the widget.
	         */
	        get: function () {
	            return this._model;
	        },
	        set: function (newValue) {
	            if (!newValue && !this._model || newValue === this._model) {
	                return;
	            }
	            var oldValue = this._model;
	            this._model = newValue;
	            // Trigger private, protected, and public updates.
	            this._onModelChanged(oldValue, newValue);
	            this.onModelChanged(oldValue, newValue);
	            this.modelChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(OutputAreaWidget.prototype, "trusted", {
	        /**
	         * The trusted state of the widget.
	         */
	        get: function () {
	            return this._trusted;
	        },
	        set: function (value) {
	            if (this._trusted === value) {
	                return;
	            }
	            this._trusted = value;
	            // Trigger a update of the child widgets.
	            var layout = this.layout;
	            for (var i = 0; i < layout.widgets.length; i++) {
	                this.updateChild(i);
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(OutputAreaWidget.prototype, "collapsed", {
	        /**
	         * The collapsed state of the widget.
	         */
	        get: function () {
	            return this._collapsed;
	        },
	        set: function (value) {
	            if (this._collapsed === value) {
	                return;
	            }
	            this._collapsed = value;
	            this.update();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(OutputAreaWidget.prototype, "fixedHeight", {
	        /**
	         * The fixed height state of the widget.
	         */
	        get: function () {
	            return this._fixedHeight;
	        },
	        set: function (value) {
	            if (this._fixedHeight === value) {
	                return;
	            }
	            this._fixedHeight = value;
	            this.update();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    OutputAreaWidget.prototype.dispose = function () {
	        this._model = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle `update-request` messages.
	     */
	    OutputAreaWidget.prototype.onUpdateRequest = function (msg) {
	        if (this.collapsed) {
	            this.addClass(COLLAPSED_CLASS);
	        }
	        else {
	            this.removeClass(COLLAPSED_CLASS);
	        }
	        if (this.fixedHeight) {
	            this.addClass(FIXED_HEIGHT_CLASS);
	        }
	        else {
	            this.removeClass(FIXED_HEIGHT_CLASS);
	        }
	    };
	    /**
	     * Add a child to the layout.
	     */
	    OutputAreaWidget.prototype.addChild = function () {
	        var rendermime = this.rendermime;
	        var widget = this.contentFactory.createOutput({ rendermime: rendermime });
	        var layout = this.layout;
	        layout.addWidget(widget);
	        this.updateChild(layout.widgets.length - 1);
	    };
	    /**
	     * Remove a child from the layout.
	     */
	    OutputAreaWidget.prototype.removeChild = function (index) {
	        var layout = this.layout;
	        layout.widgets.at(index).dispose();
	    };
	    /**
	     * Update a child in the layout.
	     */
	    OutputAreaWidget.prototype.updateChild = function (index) {
	        var _this = this;
	        var layout = this.layout;
	        var widget = layout.widgets.at(index);
	        var output = this._model.get(index);
	        var injector;
	        if (output.output_type === 'display_data' ||
	            output.output_type === 'execute_result') {
	            injector = function (mimetype, value) {
	                _this._injecting = true;
	                _this._model.addMimeData(output, mimetype, value);
	                _this._injecting = false;
	            };
	        }
	        var trusted = this._trusted;
	        widget.render({ output: output, trusted: trusted, injector: injector });
	    };
	    /**
	     * Follow changes on the model state.
	     */
	    OutputAreaWidget.prototype.onModelStateChanged = function (sender, args) {
	        var _this = this;
	        switch (args.type) {
	            case 'add':
	                // Children are always added at the end.
	                this.addChild();
	                break;
	            case 'remove':
	                // Only "clear" is supported by the model.
	                // When an output area is cleared and then quickly replaced with new
	                // content (as happens with @interact in widgets, for example), the
	                // quickly changing height can make the page jitter.
	                // We introduce a small delay in the minimum height
	                // to prevent this jitter.
	                var rect = this.node.getBoundingClientRect();
	                this.node.style.minHeight = rect.height + "px";
	                if (this._minHeightTimeout) {
	                    clearTimeout(this._minHeightTimeout);
	                }
	                this._minHeightTimeout = setTimeout(function () {
	                    if (_this.isDisposed) {
	                        return;
	                    }
	                    _this.node.style.minHeight = '';
	                }, 50);
	                iteration_1.each(args.oldValues, function (value) {
	                    _this.removeChild(args.oldIndex);
	                });
	                break;
	            case 'set':
	                if (!this._injecting) {
	                    this.updateChild(args.newIndex);
	                }
	                break;
	            default:
	                break;
	        }
	        this.update();
	    };
	    /**
	     * Handle a new model.
	     *
	     * #### Notes
	     * This method is called after the model change has been handled
	     * internally and before the `modelChanged` signal is emitted.
	     * The default implementation is a no-op.
	     */
	    OutputAreaWidget.prototype.onModelChanged = function (oldValue, newValue) {
	        // no-op
	    };
	    /**
	     * Handle a change to the model.
	     */
	    OutputAreaWidget.prototype._onModelChanged = function (oldValue, newValue) {
	        var layout = this.layout;
	        if (oldValue) {
	            oldValue.changed.disconnect(this.onModelStateChanged, this);
	            oldValue.disposed.disconnect(this._onModelDisposed, this);
	        }
	        var start = newValue ? newValue.length : 0;
	        // Clear unnecessary child widgets.
	        while (layout.widgets.length > start) {
	            this.removeChild(start);
	        }
	        if (!newValue) {
	            return;
	        }
	        newValue.changed.connect(this.onModelStateChanged, this);
	        newValue.disposed.connect(this._onModelDisposed, this);
	        // Reuse existing child widgets.
	        for (var i = 0; i < layout.widgets.length; i++) {
	            this.updateChild(i);
	        }
	        // Add new widgets as necessary.
	        for (var i = layout.widgets.length; i < newValue.length; i++) {
	            this.addChild();
	        }
	    };
	    /**
	     * Handle a model disposal.
	     */
	    OutputAreaWidget.prototype.onModelDisposed = function (oldValue, newValue) {
	        // no-op
	    };
	    OutputAreaWidget.prototype._onModelDisposed = function () {
	        this.modelDisposed.emit(void 0);
	        this.dispose();
	    };
	    return OutputAreaWidget;
	}(widget_1.Widget));
	exports.OutputAreaWidget = OutputAreaWidget;
	/**
	 * A namespace for OutputAreaWidget statics.
	 */
	var OutputAreaWidget;
	(function (OutputAreaWidget) {
	    /**
	     * The default implementation of `IContentFactory`.
	     */
	    var ContentFactory = (function () {
	        function ContentFactory() {
	        }
	        /**
	         * Create an output widget.
	         *
	         *
	         * @returns A new widget for an output.
	         */
	        ContentFactory.prototype.createOutput = function (options) {
	            return new OutputWidget(options);
	        };
	        return ContentFactory;
	    }());
	    OutputAreaWidget.ContentFactory = ContentFactory;
	    /**
	     * The default `ContentFactory` instance.
	     */
	    OutputAreaWidget.defaultContentFactory = new ContentFactory();
	})(OutputAreaWidget = exports.OutputAreaWidget || (exports.OutputAreaWidget = {}));
	/**
	 * The gutter on the left side of the OutputWidget
	 */
	var OutputGutter = (function (_super) {
	    __extends(OutputGutter, _super);
	    function OutputGutter() {
	        _super.apply(this, arguments);
	        this._drag = null;
	        this._dragData = null;
	    }
	    /**
	     * Handle the DOM events for the output gutter widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the panel's DOM node. It should
	     * not be called directly by user code.
	     */
	    OutputGutter.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'mousedown':
	                this._evtMousedown(event);
	                break;
	            case 'mouseup':
	                this._evtMouseup(event);
	                break;
	            case 'mousemove':
	                this._evtMousemove(event);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    OutputGutter.prototype.onAfterAttach = function (msg) {
	        _super.prototype.onAfterAttach.call(this, msg);
	        this.node.addEventListener('mousedown', this);
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    OutputGutter.prototype.onBeforeDetach = function (msg) {
	        _super.prototype.onBeforeDetach.call(this, msg);
	        var node = this.node;
	        node.removeEventListener('mousedown', this);
	    };
	    /**
	     * Handle the `'mousedown'` event for the widget.
	     */
	    OutputGutter.prototype._evtMousedown = function (event) {
	        // Left mouse press for drag start.
	        if (event.button === 0) {
	            this._dragData = { pressX: event.clientX, pressY: event.clientY };
	            document.addEventListener('mouseup', this, true);
	            document.addEventListener('mousemove', this, true);
	        }
	    };
	    /**
	     * Handle the `'mouseup'` event for the widget.
	     */
	    OutputGutter.prototype._evtMouseup = function (event) {
	        if (event.button !== 0 || !this._drag) {
	            document.removeEventListener('mousemove', this, true);
	            document.removeEventListener('mouseup', this, true);
	            return;
	        }
	        event.preventDefault();
	        event.stopPropagation();
	    };
	    /**
	     * Handle the `'mousemove'` event for the widget.
	     */
	    OutputGutter.prototype._evtMousemove = function (event) {
	        event.preventDefault();
	        event.stopPropagation();
	        // Bail if we are the one dragging.
	        if (this._drag) {
	            return;
	        }
	        // Check for a drag initialization.
	        var data = this._dragData;
	        var dx = Math.abs(event.clientX - data.pressX);
	        var dy = Math.abs(event.clientY - data.pressY);
	        if (dx < DRAG_THRESHOLD && dy < DRAG_THRESHOLD) {
	            return;
	        }
	        this._startDrag(event.clientX, event.clientY);
	    };
	    /**
	     * Start a drag event.
	     */
	    OutputGutter.prototype._startDrag = function (clientX, clientY) {
	        var _this = this;
	        // Set up the drag event.
	        this._drag = new dragdrop_1.Drag({
	            mimeData: new mimedata_1.MimeData(),
	            supportedActions: 'copy',
	            proposedAction: 'copy'
	        });
	        this._drag.mimeData.setData(FACTORY_MIME, function () {
	            var outputArea = _this.parent.parent;
	            return outputArea.mirror();
	        });
	        // Remove mousemove and mouseup listeners and start the drag.
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('mouseup', this, true);
	        this._drag.start(clientX, clientY).then(function (action) {
	            _this._drag = null;
	        });
	    };
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    OutputGutter.prototype.dispose = function () {
	        this._dragData = null;
	        this._drag = null;
	        _super.prototype.dispose.call(this);
	    };
	    return OutputGutter;
	}(widget_1.Widget));
	exports.OutputGutter = OutputGutter;
	/**
	 * An output widget.
	 */
	var OutputWidget = (function (_super) {
	    __extends(OutputWidget, _super);
	    /**
	     * Construct a new output widget.
	     */
	    function OutputWidget(options) {
	        _super.call(this);
	        this._rendermime = null;
	        this._placeholder = null;
	        var layout = new panel_1.PanelLayout();
	        this.layout = layout;
	        var prompt = new OutputGutter();
	        this._placeholder = new widget_1.Widget();
	        this.addClass(OUTPUT_CLASS);
	        prompt.addClass(PROMPT_CLASS);
	        this._placeholder.addClass(RESULT_CLASS);
	        layout.addWidget(prompt);
	        layout.addWidget(this._placeholder);
	        this._rendermime = options.rendermime;
	    }
	    Object.defineProperty(OutputWidget.prototype, "prompt", {
	        /**
	         * The prompt widget used by the output widget.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            var layout = this.layout;
	            return layout.widgets.at(0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(OutputWidget.prototype, "output", {
	        /**
	         * The rendered output used by the output widget.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            var layout = this.layout;
	            return layout.widgets.at(1);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    OutputWidget.prototype.dispose = function () {
	        this._rendermime = null;
	        this._placeholder = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Clear the widget contents.
	     */
	    OutputWidget.prototype.clear = function () {
	        this.setOutput(this._placeholder);
	        this.prompt.node.textContent = '';
	    };
	    /**
	     * Render an output.
	     *
	     * @param options - The options used to render the output.
	     */
	    OutputWidget.prototype.render = function (options) {
	        var output = options.output, trusted = options.trusted, injector = options.injector;
	        // Handle an input request.
	        if (output.output_type === 'input_request') {
	            var child_1 = new InputWidget(output);
	            this.setOutput(child_1);
	            return;
	        }
	        // Extract the data from the output and sanitize if necessary.
	        var rendermime = this._rendermime;
	        var bundle = model_1.OutputAreaModel.getBundle(output);
	        var data = model_1.OutputAreaModel.convertBundle(bundle);
	        // Clear the content.
	        this.clear();
	        // Bail if no data to display.
	        if (!data) {
	            console.warn('Did not find renderer for output mimebundle.');
	            return;
	        }
	        // Create the output result area.
	        var child = rendermime.render({ bundle: data, trusted: trusted, injector: injector });
	        if (!child) {
	            return;
	        }
	        this.setOutput(child);
	        // Add classes and output prompt as necessary.
	        switch (output.output_type) {
	            case 'execute_result':
	                child.addClass(EXECUTE_CLASS);
	                var count = output.execution_count;
	                this.prompt.node.textContent = "Out[" + (count === null ? ' ' : count) + "]:";
	                break;
	            case 'display_data':
	                child.addClass(DISPLAY_CLASS);
	                break;
	            case 'stream':
	                if (output.name === 'stdout') {
	                    child.addClass(STDOUT_CLASS);
	                }
	                else {
	                    child.addClass(STDERR_CLASS);
	                }
	                break;
	            case 'error':
	                child.addClass(ERROR_CLASS);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Set the widget output.
	     */
	    OutputWidget.prototype.setOutput = function (value) {
	        var layout = this.layout;
	        var old = this.output;
	        value = value || null;
	        if (old === value) {
	            return;
	        }
	        if (old) {
	            if (old !== this._placeholder) {
	                old.dispose();
	            }
	            else {
	                old.parent = null;
	            }
	        }
	        if (value) {
	            layout.addWidget(value);
	            value.addClass(RESULT_CLASS);
	        }
	        else {
	            layout.addWidget(this._placeholder);
	        }
	    };
	    return OutputWidget;
	}(widget_1.Widget));
	exports.OutputWidget = OutputWidget;
	/**
	 * A widget that handles stdin requests from the kernel.
	 */
	var InputWidget = (function (_super) {
	    __extends(InputWidget, _super);
	    /**
	     * Construct a new input widget.
	     */
	    function InputWidget(request) {
	        _super.call(this, { node: Private.createInputWidgetNode() });
	        this._kernel = null;
	        this._input = null;
	        this.addClass(STDIN_CLASS);
	        var text = this.node.firstChild;
	        text.textContent = request.prompt;
	        this._input = this.node.lastChild;
	        if (request.password) {
	            this._input.type = 'password';
	        }
	        this._kernel = request.kernel;
	    }
	    /**
	     * Handle the DOM events for the widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the dock panel's node. It should
	     * not be called directly by user code.
	     */
	    InputWidget.prototype.handleEvent = function (event) {
	        var input = this._input;
	        if (event.type === 'keydown') {
	            if (event.keyCode === 13) {
	                this._kernel.sendInputReply({
	                    value: input.value
	                });
	                var rendered = document.createElement('span');
	                rendered.className = STDIN_RENDERED_CLASS;
	                if (input.type === 'password') {
	                    rendered.textContent = Array(input.value.length + 1).join('·');
	                }
	                else {
	                    rendered.textContent = input.value;
	                }
	                this.node.replaceChild(rendered, input);
	            }
	            // Suppress keydown events from leaving the input.
	            event.stopPropagation();
	        }
	    };
	    /**
	     * Handle `after-attach` messages sent to the widget.
	     */
	    InputWidget.prototype.onAfterAttach = function (msg) {
	        this._input.addEventListener('keydown', this);
	        this.update();
	    };
	    /**
	     * Handle `update-request` messages sent to the widget.
	     */
	    InputWidget.prototype.onUpdateRequest = function (msg) {
	        this._input.focus();
	    };
	    /**
	     * Handle `before-detach` messages sent to the widget.
	     */
	    InputWidget.prototype.onBeforeDetach = function (msg) {
	        this._input.removeEventListener('keydown', this);
	    };
	    return InputWidget;
	}(widget_1.Widget));
	// Define the signals for the `OutputAreaWidget` class.
	signaling_1.defineSignal(OutputAreaWidget.prototype, 'modelChanged');
	signaling_1.defineSignal(OutputAreaWidget.prototype, 'modelDisposed');
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create the node for an InputWidget.
	     */
	    function createInputWidgetNode() {
	        var node = document.createElement('div');
	        var prompt = document.createElement('span');
	        prompt.className = STDIN_PROMPT_CLASS;
	        var input = document.createElement('input');
	        input.className = STDIN_INPUT_CLASS;
	        node.appendChild(prompt);
	        node.appendChild(input);
	        return node;
	    }
	    Private.createInputWidgetNode = createInputWidgetNode;
	})(Private || (Private = {}));
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/outputarea/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/cells/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/cells/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var codeeditor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/index.js');
	var outputarea_1 = __jupyter_require__('jupyterlab@0.15.1/lib/outputarea/index.js');
	/**
	 * The class name added to cell widgets.
	 */
	var CELL_CLASS = 'jp-Cell';
	/**
	 * The class name added to the prompt area of cell.
	 */
	var PROMPT_CLASS = 'jp-Cell-prompt';
	/**
	 * The class name added to input area widgets.
	 */
	var INPUT_CLASS = 'jp-InputArea';
	/**
	 * The class name added to the editor area of the cell.
	 */
	var EDITOR_CLASS = 'jp-InputArea-editor';
	/**
	 * The class name added to the cell when collapsed.
	 */
	var COLLAPSED_CLASS = 'jp-mod-collapsed';
	/**
	 * The class name added to the cell when readonly.
	 */
	var READONLY_CLASS = 'jp-mod-readOnly';
	/**
	 * The class name added to code cells.
	 */
	var CODE_CELL_CLASS = 'jp-CodeCell';
	/**
	 * The class name added to markdown cells.
	 */
	var MARKDOWN_CELL_CLASS = 'jp-MarkdownCell';
	/**
	 * The class name added to rendered markdown output widgets.
	 */
	var MARKDOWN_OUTPUT_CLASS = 'jp-MarkdownOutput';
	/**
	 * The class name added to raw cells.
	 */
	var RAW_CELL_CLASS = 'jp-RawCell';
	/**
	 * The class name added to cell editor widget nodes.
	 */
	var CELL_EDITOR_CLASS = 'jp-CellEditor';
	/**
	 * The class name added to a rendered input area.
	 */
	var RENDERED_CLASS = 'jp-mod-rendered';
	/**
	 * The text applied to an empty markdown cell.
	 */
	var DEFAULT_MARKDOWN_TEXT = 'Type Markdown and LaTeX: $ α^2 $';
	/**
	 * A base cell widget.
	 */
	var BaseCellWidget = (function (_super) {
	    __extends(BaseCellWidget, _super);
	    /**
	     * Construct a new base cell widget.
	     */
	    function BaseCellWidget(options) {
	        _super.call(this);
	        this._input = null;
	        this._editor = null;
	        this._model = null;
	        this._readOnly = false;
	        this._trustedCursor = null;
	        this._trusted = false;
	        this.addClass(CELL_CLASS);
	        this.layout = new panel_1.PanelLayout();
	        var model = this._model = options.model;
	        var factory = options.contentFactory;
	        var editorOptions = { model: model, factory: factory.editorFactory };
	        var editor = this._editor = factory.createCellEditor(editorOptions);
	        editor.addClass(CELL_EDITOR_CLASS);
	        this._input = factory.createInputArea({ editor: editor });
	        this.layout.addWidget(this._input);
	        // Handle trusted cursor.
	        this._trustedCursor = model.getMetadata('trusted');
	        this._trusted = !!this._trustedCursor.getValue();
	        // Connect signal handlers.
	        model.metadataChanged.connect(this.onMetadataChanged, this);
	        model.stateChanged.connect(this.onModelStateChanged, this);
	    }
	    Object.defineProperty(BaseCellWidget.prototype, "promptNode", {
	        /**
	         * Get the prompt node used by the cell.
	         */
	        get: function () {
	            return this._input.promptNode;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(BaseCellWidget.prototype, "editorWidget", {
	        /**
	         * Get the editor widget used by the cell.
	         */
	        get: function () {
	            return this._editor;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(BaseCellWidget.prototype, "editor", {
	        /**
	         * Get the editor used by the cell.
	         */
	        get: function () {
	            return this._editor.editor;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(BaseCellWidget.prototype, "model", {
	        /**
	         * Get the model used by the cell.
	         */
	        get: function () {
	            return this._model;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(BaseCellWidget.prototype, "readOnly", {
	        /**
	         * The read only state of the cell.
	         */
	        get: function () {
	            return this._readOnly;
	        },
	        set: function (value) {
	            if (value === this._readOnly) {
	                return;
	            }
	            this._readOnly = value;
	            this.update();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(BaseCellWidget.prototype, "trusted", {
	        /**
	         * The trusted state of the cell.
	         */
	        get: function () {
	            return this._trusted;
	        },
	        set: function (value) {
	            if (!this._model) {
	                return;
	            }
	            this._trustedCursor.setValue(value);
	            this._trusted = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Set the prompt for the widget.
	     */
	    BaseCellWidget.prototype.setPrompt = function (value) {
	        this._input.setPrompt(value);
	    };
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    BaseCellWidget.prototype.dispose = function () {
	        // Do nothing if already disposed.
	        if (this.isDisposed) {
	            return;
	        }
	        this._model = null;
	        this._input = null;
	        this._editor = null;
	        this._trustedCursor = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle `after-attach` messages.
	     */
	    BaseCellWidget.prototype.onAfterAttach = function (msg) {
	        this.update();
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    BaseCellWidget.prototype.onActivateRequest = function (msg) {
	        this._editor.editor.focus();
	    };
	    /**
	     * Handle `update-request` messages.
	     */
	    BaseCellWidget.prototype.onUpdateRequest = function (msg) {
	        if (!this._model) {
	            return;
	        }
	        // Handle read only state.
	        this._editor.editor.readOnly = this._readOnly;
	        this.toggleClass(READONLY_CLASS, this._readOnly);
	    };
	    /**
	     * Handle changes in the model.
	     *
	     * #### Notes
	     * Subclasses may reimplement this method as needed.
	     */
	    BaseCellWidget.prototype.onModelStateChanged = function (model, args) {
	        // no-op
	    };
	    /**
	     * Handle changes in the model.
	     */
	    BaseCellWidget.prototype.onMetadataChanged = function (model, args) {
	        switch (args.name) {
	            case 'trusted':
	                this._trusted = !!this._trustedCursor.getValue();
	                this.update();
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Render an input instead of the text editor.
	     */
	    BaseCellWidget.prototype.renderInput = function (widget) {
	        this.addClass(RENDERED_CLASS);
	        this._input.renderInput(widget);
	    };
	    /**
	     * Show the text editor.
	     */
	    BaseCellWidget.prototype.showEditor = function () {
	        this.removeClass(RENDERED_CLASS);
	        this._input.showEditor();
	    };
	    return BaseCellWidget;
	}(widget_1.Widget));
	exports.BaseCellWidget = BaseCellWidget;
	/**
	 * The namespace for the `BaseCellWidget` class statics.
	 */
	var BaseCellWidget;
	(function (BaseCellWidget) {
	    /**
	     * The default implementation of an `IContentFactory`.
	     */
	    var ContentFactory = (function () {
	        /**
	         * Creates a new renderer.
	         */
	        function ContentFactory(options) {
	            this.editorFactory = options.editorFactory;
	        }
	        /**
	         * Create a new cell editor for the widget.
	         */
	        ContentFactory.prototype.createCellEditor = function (options) {
	            return new codeeditor_1.CodeEditorWidget(options);
	        };
	        /**
	         * Create a new input area for the widget.
	         */
	        ContentFactory.prototype.createInputArea = function (options) {
	            return new InputAreaWidget(options);
	        };
	        return ContentFactory;
	    }());
	    BaseCellWidget.ContentFactory = ContentFactory;
	})(BaseCellWidget = exports.BaseCellWidget || (exports.BaseCellWidget = {}));
	/**
	 * A widget for a code cell.
	 */
	var CodeCellWidget = (function (_super) {
	    __extends(CodeCellWidget, _super);
	    /**
	     * Construct a code cell widget.
	     */
	    function CodeCellWidget(options) {
	        _super.call(this, options);
	        this._rendermime = null;
	        this._output = null;
	        this._collapsedCursor = null;
	        this._scrolledCursor = null;
	        this.addClass(CODE_CELL_CLASS);
	        var rendermime = this._rendermime = options.rendermime;
	        var factory = options.contentFactory;
	        this._output = factory.createOutputArea({
	            rendermime: rendermime,
	            contentFactory: factory.outputAreaContentFactory
	        });
	        this.layout.addWidget(this._output);
	        var model = this.model;
	        this._output.model = model.outputs;
	        this._output.trusted = this.trusted;
	        this._collapsedCursor = model.getMetadata('collapsed');
	        this._scrolledCursor = model.getMetadata('scrolled');
	        this.setPrompt("" + (model.executionCount || ''));
	    }
	    /**
	     * Dispose of the resources used by the widget.
	     */
	    CodeCellWidget.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._collapsedCursor = null;
	        this._scrolledCursor = null;
	        this._output = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Execute the cell given a kernel.
	     */
	    CodeCellWidget.prototype.execute = function (kernel) {
	        var _this = this;
	        var model = this.model;
	        var code = model.value.text;
	        if (!code.trim()) {
	            model.executionCount = null;
	            model.outputs.clear();
	            return Promise.resolve(null);
	        }
	        model.executionCount = null;
	        this.setPrompt('*');
	        this.trusted = true;
	        var outputs = model.outputs;
	        return outputs.execute(code, kernel).then(function (reply) {
	            var status = reply.content.status;
	            if (status === 'abort') {
	                model.executionCount = null;
	                _this.setPrompt(' ');
	            }
	            else {
	                model.executionCount = reply.content.execution_count;
	            }
	            return reply;
	        });
	    };
	    /**
	     * Handle `update-request` messages.
	     */
	    CodeCellWidget.prototype.onUpdateRequest = function (msg) {
	        if (this._collapsedCursor) {
	            var value = this._collapsedCursor.getValue();
	            this.toggleClass(COLLAPSED_CLASS, value);
	        }
	        if (this._output) {
	            // TODO: handle scrolled state.
	            this._output.trusted = this.trusted;
	        }
	        _super.prototype.onUpdateRequest.call(this, msg);
	    };
	    /**
	     * Handle changes in the model.
	     */
	    CodeCellWidget.prototype.onModelStateChanged = function (model, args) {
	        switch (args.name) {
	            case 'executionCount':
	                this.setPrompt("" + model.executionCount);
	                break;
	            default:
	                break;
	        }
	        _super.prototype.onModelStateChanged.call(this, model, args);
	    };
	    /**
	     * Handle changes in the metadata.
	     */
	    CodeCellWidget.prototype.onMetadataChanged = function (model, args) {
	        switch (args.name) {
	            case 'collapsed':
	            case 'scrolled':
	                this.update();
	                break;
	            default:
	                break;
	        }
	        _super.prototype.onMetadataChanged.call(this, model, args);
	    };
	    return CodeCellWidget;
	}(BaseCellWidget));
	exports.CodeCellWidget = CodeCellWidget;
	/**
	 * The namespace for the `CodeCellWidget` class statics.
	 */
	var CodeCellWidget;
	(function (CodeCellWidget) {
	    /**
	     * The default implementation of an `IContentFactory`.
	     */
	    var ContentFactory = (function (_super) {
	        __extends(ContentFactory, _super);
	        /**
	         * Construct a new code cell content factory
	         */
	        function ContentFactory(options) {
	            _super.call(this, options);
	            this.outputAreaContentFactory = (options.outputAreaContentFactory ||
	                outputarea_1.OutputAreaWidget.defaultContentFactory);
	        }
	        /**
	         * Create an output area widget.
	         */
	        ContentFactory.prototype.createOutputArea = function (options) {
	            return new outputarea_1.OutputAreaWidget(options);
	        };
	        return ContentFactory;
	    }(BaseCellWidget.ContentFactory));
	    CodeCellWidget.ContentFactory = ContentFactory;
	})(CodeCellWidget = exports.CodeCellWidget || (exports.CodeCellWidget = {}));
	/**
	 * A widget for a Markdown cell.
	 *
	 * #### Notes
	 * Things get complicated if we want the rendered text to update
	 * any time the text changes, the text editor model changes,
	 * or the input area model changes.  We don't support automatically
	 * updating the rendered text in all of these cases.
	 */
	var MarkdownCellWidget = (function (_super) {
	    __extends(MarkdownCellWidget, _super);
	    /**
	     * Construct a Markdown cell widget.
	     */
	    function MarkdownCellWidget(options) {
	        _super.call(this, options);
	        this._rendermime = null;
	        this._output = null;
	        this._rendered = true;
	        this._prevText = '';
	        this._prevTrusted = false;
	        this.addClass(MARKDOWN_CELL_CLASS);
	        // Insist on the Github-flavored markdown mode.
	        this.model.mimeType = 'text/x-ipythongfm';
	        this._rendermime = options.rendermime;
	        this.editor.wordWrap = true;
	    }
	    Object.defineProperty(MarkdownCellWidget.prototype, "rendered", {
	        /**
	         * Whether the cell is rendered.
	         */
	        get: function () {
	            return this._rendered;
	        },
	        set: function (value) {
	            if (value === this._rendered) {
	                return;
	            }
	            this._rendered = value;
	            this._handleRendered();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resource held by the widget.
	     */
	    MarkdownCellWidget.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._output = null;
	        _super.prototype.dispose.call(this);
	    };
	    /*
	     * Handle `update-request` messages.
	     */
	    MarkdownCellWidget.prototype.onUpdateRequest = function (msg) {
	        // Make sure we are properly rendered.
	        this._handleRendered();
	        _super.prototype.onUpdateRequest.call(this, msg);
	    };
	    /**
	     * Handle the rendered state.
	     */
	    MarkdownCellWidget.prototype._handleRendered = function () {
	        if (!this._rendered) {
	            this.showEditor();
	        }
	        else {
	            this._updateOutput();
	            this.renderInput(this._output);
	        }
	    };
	    /**
	     * Update the output.
	     */
	    MarkdownCellWidget.prototype._updateOutput = function () {
	        var model = this.model;
	        var text = model && model.value.text || DEFAULT_MARKDOWN_TEXT;
	        var trusted = this.trusted;
	        // Do not re-render if the text has not changed and the trusted
	        // has not changed.
	        if (text !== this._prevText || trusted !== this._prevTrusted) {
	            var bundle = { 'text/markdown': text };
	            var widget = this._rendermime.render({ bundle: bundle, trusted: trusted });
	            this._output = widget || new widget_1.Widget();
	            this._output.addClass(MARKDOWN_OUTPUT_CLASS);
	        }
	        this._prevText = text;
	        this._prevTrusted = trusted;
	    };
	    return MarkdownCellWidget;
	}(BaseCellWidget));
	exports.MarkdownCellWidget = MarkdownCellWidget;
	/**
	 * A widget for a raw cell.
	 */
	var RawCellWidget = (function (_super) {
	    __extends(RawCellWidget, _super);
	    /**
	     * Construct a raw cell widget.
	     */
	    function RawCellWidget(options) {
	        _super.call(this, options);
	        this.addClass(RAW_CELL_CLASS);
	    }
	    return RawCellWidget;
	}(BaseCellWidget));
	exports.RawCellWidget = RawCellWidget;
	/**
	 * An input area widget, which hosts a prompt and an editor widget.
	 */
	var InputAreaWidget = (function (_super) {
	    __extends(InputAreaWidget, _super);
	    /**
	     * Construct an input area widget.
	     */
	    function InputAreaWidget(options) {
	        _super.call(this);
	        this.addClass(INPUT_CLASS);
	        var editor = this._editor = options.editor;
	        editor.addClass(EDITOR_CLASS);
	        this.layout = new panel_1.PanelLayout();
	        var prompt = this._prompt = new widget_1.Widget();
	        prompt.addClass(PROMPT_CLASS);
	        var layout = this.layout;
	        layout.addWidget(prompt);
	        layout.addWidget(editor);
	    }
	    Object.defineProperty(InputAreaWidget.prototype, "promptNode", {
	        /**
	         * Get the prompt node used by the cell.
	         */
	        get: function () {
	            return this._prompt.node;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Render an input instead of the text editor.
	     */
	    InputAreaWidget.prototype.renderInput = function (widget) {
	        this._editor.hide();
	        var layout = this.layout;
	        if (this._rendered) {
	            layout.removeWidget(this._rendered);
	        }
	        this._rendered = widget;
	        widget.show();
	        layout.addWidget(widget);
	    };
	    /**
	     * Show the text editor.
	     */
	    InputAreaWidget.prototype.showEditor = function () {
	        this._editor.show();
	        var layout = this.layout;
	        if (this._rendered) {
	            layout.removeWidget(this._rendered);
	        }
	    };
	    /**
	     * Set the prompt of the input area.
	     */
	    InputAreaWidget.prototype.setPrompt = function (value) {
	        if (value === 'null') {
	            value = ' ';
	        }
	        var text = "In [" + (value || ' ') + "]:";
	        this._prompt.node.textContent = text;
	    };
	    return InputAreaWidget;
	}(widget_1.Widget));
	exports.InputAreaWidget = InputAreaWidget;
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/cells/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/console/foreign.js **/
jupyter.define('jupyterlab@0.15.1/lib/console/foreign.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * A handler for capturing API messages from other sessions that should be
	 * rendered in a given parent.
	 */
	var ForeignHandler = (function () {
	    /**
	     * Construct a new foreign message handler.
	     */
	    function ForeignHandler(options) {
	        this._cells = new Map();
	        this._enabled = true;
	        this._kernel = null;
	        this._parent = null;
	        this._factory = null;
	        this.kernel = options.kernel;
	        this._factory = options.cellFactory;
	        this._parent = options.parent;
	    }
	    Object.defineProperty(ForeignHandler.prototype, "enabled", {
	        /**
	         * Set whether the handler is able to inject foreign cells into a console.
	         */
	        get: function () {
	            return this._enabled;
	        },
	        set: function (value) {
	            this._enabled = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ForeignHandler.prototype, "kernel", {
	        /**
	         * The kernel used by the foreign handler.
	         */
	        get: function () {
	            return this._kernel;
	        },
	        set: function (value) {
	            if (this._kernel === value) {
	                return;
	            }
	            // Disconnect previously connected kernel.
	            if (this._kernel) {
	                this._cells.clear();
	                this._kernel.iopubMessage.disconnect(this.onIOPubMessage, this);
	            }
	            this._kernel = value;
	            if (this._kernel) {
	                this._kernel.iopubMessage.connect(this.onIOPubMessage, this);
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ForeignHandler.prototype, "parent", {
	        /**
	         * The foreign handler's parent receiver.
	         */
	        get: function () {
	            return this._parent;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ForeignHandler.prototype, "isDisposed", {
	        /**
	         * Test whether the handler is disposed.
	         */
	        get: function () {
	            return this._cells === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose the resources held by the handler.
	     */
	    ForeignHandler.prototype.dispose = function () {
	        if (this._cells === null) {
	            return;
	        }
	        var cells = this._cells;
	        this._cells = null;
	        this._kernel = null;
	        cells.clear();
	    };
	    /**
	     * Handler IOPub messages.
	     *
	     * @returns `true` if the message resulted in a new cell injection or a
	     * previously injected cell being updated and `false` for all other messages.
	     */
	    ForeignHandler.prototype.onIOPubMessage = function (sender, msg) {
	        // Only process messages if foreign cell injection is enabled.
	        if (!this._enabled) {
	            return false;
	        }
	        // Check whether this message came from an external session.
	        var parent = this._parent;
	        var session = msg.parent_header.session;
	        if (session === this._kernel.clientId) {
	            return false;
	        }
	        var msgType = msg.header.msg_type;
	        var parentHeader = msg.parent_header;
	        var parentMsgId = parentHeader.msg_id;
	        var cell;
	        switch (msgType) {
	            case 'execute_input':
	                var inputMsg = msg;
	                cell = this._newCell(parentMsgId);
	                cell.model.executionCount = inputMsg.content.execution_count;
	                cell.model.value.text = inputMsg.content.code;
	                cell.trusted = true;
	                parent.update();
	                return true;
	            case 'execute_result':
	            case 'display_data':
	            case 'stream':
	            case 'error':
	                if (!this._cells.has(parentMsgId)) {
	                    // This is an output from an input that was broadcast before our
	                    // session started listening. We will ignore it.
	                    console.warn('Ignoring output with no associated input cell.');
	                    return false;
	                }
	                var output = msg.content;
	                cell = this._cells.get(parentMsgId);
	                output.output_type = msgType;
	                cell.model.outputs.add(output);
	                parent.update();
	                return true;
	            case 'clear_output':
	                var wait = msg.content.wait;
	                cell = this._cells.get(parentMsgId);
	                cell.model.outputs.clear(wait);
	                return true;
	            default:
	                return false;
	        }
	    };
	    /**
	     * Create a new code cell for an input originated from a foreign session.
	     */
	    ForeignHandler.prototype._newCell = function (parentMsgId) {
	        var cell = this._factory();
	        this._cells.set(parentMsgId, cell);
	        this._parent.addCell(cell);
	        return cell;
	    };
	    return ForeignHandler;
	}());
	exports.ForeignHandler = ForeignHandler;
	//# sourceMappingURL=foreign.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/console/foreign.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/console/history.js **/
jupyter.define('jupyterlab@0.15.1/lib/console/history.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	/**
	 * A console history manager object.
	 */
	var ConsoleHistory = (function () {
	    /**
	     * Construct a new console history object.
	     */
	    function ConsoleHistory(options) {
	        this._cursor = 0;
	        this._hasSession = false;
	        this._history = null;
	        this._kernel = null;
	        this._placeholder = '';
	        this._setByHistory = false;
	        this._editor = null;
	        this._history = new vector_1.Vector();
	        if (options && options.kernel) {
	            this.kernel = options.kernel;
	        }
	    }
	    Object.defineProperty(ConsoleHistory.prototype, "kernel", {
	        /**
	         * The current kernel supplying navigation history.
	         */
	        get: function () {
	            return this._kernel;
	        },
	        set: function (newValue) {
	            var _this = this;
	            if (newValue === this._kernel) {
	                return;
	            }
	            this._kernel = newValue;
	            if (!this._kernel) {
	                this._history = new vector_1.Vector();
	                return;
	            }
	            this._kernel.requestHistory(Private.initialRequest).then(function (v) {
	                _this.onHistory(v);
	            });
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ConsoleHistory.prototype, "editor", {
	        /**
	         * The current editor used by the history manager.
	         */
	        get: function () {
	            return this._editor;
	        },
	        set: function (value) {
	            if (this._editor === value) {
	                return;
	            }
	            var editor = this._editor;
	            if (editor) {
	                editor.edgeRequested.disconnect(this.onEdgeRequest, this);
	                editor.model.value.changed.disconnect(this.onTextChange, this);
	            }
	            editor = this._editor = value;
	            editor.edgeRequested.connect(this.onEdgeRequest, this);
	            editor.model.value.changed.connect(this.onTextChange, this);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ConsoleHistory.prototype, "placeholder", {
	        /**
	         * The placeholder text that a history session began with.
	         */
	        get: function () {
	            return this._placeholder;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ConsoleHistory.prototype, "isDisposed", {
	        /**
	         * Get whether the console history manager is disposed.
	         */
	        get: function () {
	            return this._history === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the console history manager.
	     */
	    ConsoleHistory.prototype.dispose = function () {
	        if (this._history == null) {
	            return;
	        }
	        this._history = null;
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Get the previous item in the console history.
	     *
	     * @param placeholder - The placeholder string that gets temporarily added
	     * to the history only for the duration of one history session. If multiple
	     * placeholders are sent within a session, only the first one is accepted.
	     *
	     * @returns A Promise for console command text or `undefined` if unavailable.
	     */
	    ConsoleHistory.prototype.back = function (placeholder) {
	        if (!this._hasSession) {
	            this._hasSession = true;
	            this._placeholder = placeholder;
	        }
	        var content = this._history.at(--this._cursor);
	        this._cursor = Math.max(0, this._cursor);
	        return Promise.resolve(content);
	    };
	    /**
	     * Get the next item in the console history.
	     *
	     * @param placeholder - The placeholder string that gets temporarily added
	     * to the history only for the duration of one history session. If multiple
	     * placeholders are sent within a session, only the first one is accepted.
	     *
	     * @returns A Promise for console command text or `undefined` if unavailable.
	     */
	    ConsoleHistory.prototype.forward = function (placeholder) {
	        if (!this._hasSession) {
	            this._hasSession = true;
	            this._placeholder = placeholder;
	        }
	        var content = this._history.at(++this._cursor);
	        this._cursor = Math.min(this._history.length, this._cursor);
	        return Promise.resolve(content);
	    };
	    /**
	     * Add a new item to the bottom of history.
	     *
	     * @param item The item being added to the bottom of history.
	     *
	     * #### Notes
	     * If the item being added is undefined or empty, it is ignored. If the item
	     * being added is the same as the last item in history, it is ignored as well
	     * so that the console's history will consist of no contiguous repetitions.
	     */
	    ConsoleHistory.prototype.push = function (item) {
	        if (item && item !== this._history.back) {
	            this._history.pushBack(item);
	        }
	        this.reset();
	    };
	    /**
	     * Reset the history navigation state, i.e., start a new history session.
	     */
	    ConsoleHistory.prototype.reset = function () {
	        this._cursor = this._history.length;
	        this._hasSession = false;
	        this._placeholder = '';
	    };
	    /**
	     * Populate the history collection on history reply from a kernel.
	     *
	     * @param value The kernel message history reply.
	     *
	     * #### Notes
	     * History entries have the shape:
	     * [session: number, line: number, input: string]
	     * Contiguous duplicates are stripped out of the API response.
	     */
	    ConsoleHistory.prototype.onHistory = function (value) {
	        this._history = new vector_1.Vector();
	        var last = '';
	        var current = '';
	        for (var i = 0; i < value.content.history.length; i++) {
	            current = value.content.history[i][2];
	            if (current !== last) {
	                this._history.pushBack(last = current);
	            }
	        }
	        // Reset the history navigation cursor back to the bottom.
	        this._cursor = this._history.length;
	    };
	    /**
	     * Handle a text change signal from the editor.
	     */
	    ConsoleHistory.prototype.onTextChange = function () {
	        if (this._setByHistory) {
	            this._setByHistory = false;
	            return;
	        }
	        this.reset();
	    };
	    /**
	     * Handle an edge requested signal.
	     */
	    ConsoleHistory.prototype.onEdgeRequest = function (editor, location) {
	        var _this = this;
	        var model = this._editor.model;
	        var source = model.value.text;
	        if (location === 'top') {
	            this.back(source).then(function (value) {
	                if (_this.isDisposed || !value) {
	                    return;
	                }
	                if (model.value.text === value) {
	                    return;
	                }
	                _this._setByHistory = true;
	                model.value.text = value;
	                editor.setCursorPosition({ line: 0, column: 0 });
	            });
	        }
	        else {
	            this.forward(source).then(function (value) {
	                if (_this.isDisposed) {
	                    return;
	                }
	                var text = value || _this.placeholder;
	                if (model.value.text === text) {
	                    return;
	                }
	                _this._setByHistory = true;
	                model.value.text = text;
	                editor.setCursorPosition(editor.getPositionAt(text.length));
	            });
	        }
	    };
	    return ConsoleHistory;
	}());
	exports.ConsoleHistory = ConsoleHistory;
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    Private.initialRequest = {
	        output: false,
	        raw: true,
	        hist_access_type: 'tail',
	        n: 500
	    };
	})(Private || (Private = {}));
	//# sourceMappingURL=history.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/console/history.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/console/tracker.js **/
jupyter.define('jupyterlab@0.15.1/lib/console/tracker.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	/* tslint:disable */
	/**
	 * The console tracker token.
	 */
	exports.IConsoleTracker = new token_1.Token('jupyter.services.consoles');
	//# sourceMappingURL=tracker.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/console/tracker.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/csvwidget/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/csvwidget/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var widget_1 = __jupyter_require__('jupyterlab@0.15.1/lib/csvwidget/widget.js');
	/**
	 * The name of the factory that creates CSV widgets.
	 */
	var FACTORY = 'Table';
	/**
	 * The table file handler extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.csv-handler',
	    requires: [docregistry_1.IDocumentRegistry, instancerestorer_1.IInstanceRestorer],
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the table widget extension.
	 */
	function activate(app, registry, restorer) {
	    var factory = new widget_1.CSVWidgetFactory({
	        name: FACTORY,
	        fileExtensions: ['.csv'],
	        defaultFor: ['.csv']
	    });
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: 'csvwidget' });
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: filebrowser_1.CommandIDs.open,
	        args: function (widget) { return ({ path: widget.context.path, factory: FACTORY }); },
	        name: function (widget) { return widget.context.path; }
	    });
	    registry.addWidgetFactory(factory);
	    factory.widgetCreated.connect(function (sender, widget) {
	        // Track the widget.
	        tracker.add(widget);
	        // Notify the instance tracker if restore data needs to update.
	        widget.context.pathChanged.connect(function () { tracker.save(widget); });
	    });
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/csvwidget/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/csvwidget/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/csvwidget/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var table_1 = __jupyter_require__('jupyterlab@0.15.1/lib/csvwidget/table.js');
	var toolbar_1 = __jupyter_require__('jupyterlab@0.15.1/lib/csvwidget/toolbar.js');
	/**
	 * The class name added to a CSV widget.
	 */
	var CSV_CLASS = 'jp-CSVWidget';
	/**
	 * The class name added to a CSV widget warning.
	 */
	var CSV_WARNING_CLASS = 'jp-CSVWidget-warning';
	/**
	 * A widget for CSV tables.
	 */
	var CSVWidget = (function (_super) {
	    __extends(CSVWidget, _super);
	    /**
	     * Construct a new CSV widget.
	     */
	    function CSVWidget(options) {
	        _super.call(this);
	        this._context = null;
	        this._model = null;
	        this._table = null;
	        this._toolbar = null;
	        this._warning = null;
	        var context = this._context = options.context;
	        var layout = this.layout = new panel_1.PanelLayout();
	        this.addClass(CSV_CLASS);
	        this.title.label = context.path.split('/').pop();
	        this._warning = new widget_1.Widget();
	        this._warning.addClass(CSV_WARNING_CLASS);
	        this._model = new table_1.CSVModel({ content: context.model.toString() });
	        this._table = new table_1.CSVTable();
	        this._table.model = this._model;
	        this._model.maxExceeded.connect(this._onMaxExceeded, this);
	        this._toolbar = new toolbar_1.CSVToolbar();
	        this._toolbar.delimiterChanged.connect(this._onDelimiterChanged, this);
	        layout.addWidget(this._toolbar);
	        layout.addWidget(this._table);
	        layout.addWidget(this._warning);
	        context.pathChanged.connect(this._onPathChanged, this);
	        context.model.contentChanged.connect(this._onContentChanged, this);
	    }
	    Object.defineProperty(CSVWidget.prototype, "context", {
	        /**
	         * The CSV widget's context.
	         */
	        get: function () {
	            return this._context;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CSVWidget.prototype, "model", {
	        /**
	         * The CSV data model.
	         */
	        get: function () {
	            return this._model;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the widget.
	     */
	    CSVWidget.prototype.dispose = function () {
	        if (this._model === null) {
	            return;
	        }
	        var model = this._model;
	        var table = this._table;
	        var toolbar = this._toolbar;
	        var warning = this._warning;
	        this._model = null;
	        this._table = null;
	        this._toolbar = null;
	        this._warning = null;
	        model.dispose();
	        table.dispose();
	        toolbar.dispose();
	        warning.dispose();
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    CSVWidget.prototype.onActivateRequest = function (msg) {
	        this.node.tabIndex = -1;
	        this.node.focus();
	    };
	    /**
	     * Handle a max exceeded in a csv widget.
	     */
	    CSVWidget.prototype._onMaxExceeded = function (sender, overflow) {
	        var available = overflow.available, maximum = overflow.maximum;
	        var message = "Table is too long to render,\n      rendering " + maximum + " of " + available + " rows";
	        this._warning.node.textContent = message;
	    };
	    /**
	     * Handle a change in delimiter.
	     */
	    CSVWidget.prototype._onDelimiterChanged = function (sender, delimiter) {
	        this._table.model.delimiter = delimiter;
	    };
	    /**
	     * Handle a change in content.
	     */
	    CSVWidget.prototype._onContentChanged = function () {
	        this._table.model.content = this._context.model.toString();
	    };
	    /**
	     * Handle a change in path.
	     */
	    CSVWidget.prototype._onPathChanged = function () {
	        this.title.label = this._context.path.split('/').pop();
	    };
	    return CSVWidget;
	}(widget_1.Widget));
	exports.CSVWidget = CSVWidget;
	/**
	 * A widget factory for CSV widgets.
	 */
	var CSVWidgetFactory = (function (_super) {
	    __extends(CSVWidgetFactory, _super);
	    function CSVWidgetFactory() {
	        _super.apply(this, arguments);
	    }
	    /**
	     * Create a new widget given a context.
	     */
	    CSVWidgetFactory.prototype.createNewWidget = function (context) {
	        return new CSVWidget({ context: context });
	    };
	    return CSVWidgetFactory;
	}(docregistry_1.ABCWidgetFactory));
	exports.CSVWidgetFactory = CSVWidgetFactory;
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/csvwidget/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/csvwidget/table.js **/
jupyter.define('jupyterlab@0.15.1/lib/csvwidget/table.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var dsv = __jupyter_require__('d3-dsv@^1.0.0/build/d3-dsv.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var vdom_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/vdom.js');
	var vdom_2 = __jupyter_require__('jupyterlab@0.15.1/lib/common/vdom.js');
	var widget_1 = __jupyter_require__('jupyterlab@0.15.1/lib/renderers/widget.js');
	/**
	 * The hard limit on the number of rows to display.
	 */
	exports.DISPLAY_LIMIT = 1000;
	/**
	 * The class name added to a csv table widget.
	 */
	var CSV_TABLE_CLASS = 'jp-CSVTable';
	/**
	 * A CSV table content model.
	 */
	var CSVModel = (function (_super) {
	    __extends(CSVModel, _super);
	    /**
	     * Instantiate a CSV model.
	     */
	    function CSVModel(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this);
	        this._content = options.content || '';
	        this._delimiter = options.delimiter || ',';
	    }
	    Object.defineProperty(CSVModel.prototype, "content", {
	        /**
	         * The raw model content.
	         */
	        get: function () {
	            return this._content;
	        },
	        set: function (content) {
	            if (this._content === content) {
	                return;
	            }
	            this._content = content;
	            this.stateChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(CSVModel.prototype, "delimiter", {
	        /**
	         * The CSV delimiter value.
	         */
	        get: function () {
	            return this._delimiter;
	        },
	        set: function (delimiter) {
	            if (this._delimiter === delimiter) {
	                return;
	            }
	            this._delimiter = delimiter;
	            this.stateChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Parse the content using the model's delimiter.
	     *
	     * #### Notes
	     * This method will always return parsed content that has at most the display
	     * limit worth of rows, currently maxing out at 1000 rows.
	     */
	    CSVModel.prototype.parse = function () {
	        var output = dsv.dsvFormat(this._delimiter).parse(this._content);
	        var available = output.length;
	        var maximum = exports.DISPLAY_LIMIT;
	        if (available > maximum) {
	            // Mutate the array instead of slicing in order to conserve memory.
	            output.splice(maximum);
	            this.maxExceeded.emit({ available: available, maximum: maximum });
	        }
	        return output;
	    };
	    return CSVModel;
	}(vdom_2.VDomModel));
	exports.CSVModel = CSVModel;
	// Define the signals for the `CSVModel` class.
	signaling_1.defineSignal(CSVModel.prototype, 'maxExceeded');
	/**
	 * A CSV table content widget.
	 */
	var CSVTable = (function (_super) {
	    __extends(CSVTable, _super);
	    /**
	     * Instantiate a new CSV table widget.
	     */
	    function CSVTable() {
	        _super.call(this);
	        this.addClass(CSV_TABLE_CLASS);
	        this.addClass(widget_1.HTML_COMMON_CLASS);
	    }
	    /**
	     * Render the content as virtual DOM nodes.
	     */
	    CSVTable.prototype.render = function () {
	        if (!this.model) {
	            return vdom_1.h.table([vdom_1.h.thead(), vdom_1.h.tbody()]);
	        }
	        var rows = this.model.parse();
	        var cols = rows.columns || [];
	        return vdom_1.h.table([
	            vdom_1.h.thead(cols.map(function (col) { return vdom_1.h.th(col); })),
	            vdom_1.h.tbody(rows.map(function (row) { return vdom_1.h.tr(cols.map(function (col) { return vdom_1.h.td(row[col]); })); }))
	        ]);
	    };
	    return CSVTable;
	}(vdom_2.VDomWidget));
	exports.CSVTable = CSVTable;
	//# sourceMappingURL=table.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/csvwidget/table.js **/


/** START DEFINE BLOCK for d3-dsv@1.0.3/build/d3-dsv.js **/
jupyter.define('d3-dsv@1.0.3/build/d3-dsv.js', function (module, exports, __jupyter_require__) {
	// https://d3js.org/d3-dsv/ Version 1.0.3. Copyright 2016 Mike Bostock.
	(function (global, factory) {
	   true ? factory(exports) :
	  typeof define === 'function' && define.amd ? define(['exports'], factory) :
	  (factory((global.d3 = global.d3 || {})));
	}(this, (function (exports) { 'use strict';
	
	function objectConverter(columns) {
	  return new Function("d", "return {" + columns.map(function(name, i) {
	    return JSON.stringify(name) + ": d[" + i + "]";
	  }).join(",") + "}");
	}
	
	function customConverter(columns, f) {
	  var object = objectConverter(columns);
	  return function(row, i) {
	    return f(object(row), i, columns);
	  };
	}
	
	// Compute unique columns in order of discovery.
	function inferColumns(rows) {
	  var columnSet = Object.create(null),
	      columns = [];
	
	  rows.forEach(function(row) {
	    for (var column in row) {
	      if (!(column in columnSet)) {
	        columns.push(columnSet[column] = column);
	      }
	    }
	  });
	
	  return columns;
	}
	
	function dsv(delimiter) {
	  var reFormat = new RegExp("[\"" + delimiter + "\n]"),
	      delimiterCode = delimiter.charCodeAt(0);
	
	  function parse(text, f) {
	    var convert, columns, rows = parseRows(text, function(row, i) {
	      if (convert) return convert(row, i - 1);
	      columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
	    });
	    rows.columns = columns;
	    return rows;
	  }
	
	  function parseRows(text, f) {
	    var EOL = {}, // sentinel value for end-of-line
	        EOF = {}, // sentinel value for end-of-file
	        rows = [], // output rows
	        N = text.length,
	        I = 0, // current character index
	        n = 0, // the current line number
	        t, // the current token
	        eol; // is the current token followed by EOL?
	
	    function token() {
	      if (I >= N) return EOF; // special case: end of file
	      if (eol) return eol = false, EOL; // special case: end of line
	
	      // special case: quotes
	      var j = I, c;
	      if (text.charCodeAt(j) === 34) {
	        var i = j;
	        while (i++ < N) {
	          if (text.charCodeAt(i) === 34) {
	            if (text.charCodeAt(i + 1) !== 34) break;
	            ++i;
	          }
	        }
	        I = i + 2;
	        c = text.charCodeAt(i + 1);
	        if (c === 13) {
	          eol = true;
	          if (text.charCodeAt(i + 2) === 10) ++I;
	        } else if (c === 10) {
	          eol = true;
	        }
	        return text.slice(j + 1, i).replace(/""/g, "\"");
	      }
	
	      // common case: find next delimiter or newline
	      while (I < N) {
	        var k = 1;
	        c = text.charCodeAt(I++);
	        if (c === 10) eol = true; // \n
	        else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
	        else if (c !== delimiterCode) continue;
	        return text.slice(j, I - k);
	      }
	
	      // special case: last token before EOF
	      return text.slice(j);
	    }
	
	    while ((t = token()) !== EOF) {
	      var a = [];
	      while (t !== EOL && t !== EOF) {
	        a.push(t);
	        t = token();
	      }
	      if (f && (a = f(a, n++)) == null) continue;
	      rows.push(a);
	    }
	
	    return rows;
	  }
	
	  function format(rows, columns) {
	    if (columns == null) columns = inferColumns(rows);
	    return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
	      return columns.map(function(column) {
	        return formatValue(row[column]);
	      }).join(delimiter);
	    })).join("\n");
	  }
	
	  function formatRows(rows) {
	    return rows.map(formatRow).join("\n");
	  }
	
	  function formatRow(row) {
	    return row.map(formatValue).join(delimiter);
	  }
	
	  function formatValue(text) {
	    return text == null ? ""
	        : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\""
	        : text;
	  }
	
	  return {
	    parse: parse,
	    parseRows: parseRows,
	    format: format,
	    formatRows: formatRows
	  };
	}
	
	var csv = dsv(",");
	
	var csvParse = csv.parse;
	var csvParseRows = csv.parseRows;
	var csvFormat = csv.format;
	var csvFormatRows = csv.formatRows;
	
	var tsv = dsv("\t");
	
	var tsvParse = tsv.parse;
	var tsvParseRows = tsv.parseRows;
	var tsvFormat = tsv.format;
	var tsvFormatRows = tsv.formatRows;
	
	exports.dsvFormat = dsv;
	exports.csvParse = csvParse;
	exports.csvParseRows = csvParseRows;
	exports.csvFormat = csvFormat;
	exports.csvFormatRows = csvFormatRows;
	exports.tsvParse = tsvParse;
	exports.tsvParseRows = tsvParseRows;
	exports.tsvFormat = tsvFormat;
	exports.tsvFormatRows = tsvFormatRows;
	
	Object.defineProperty(exports, '__esModule', { value: true });
	
	})));
})
/** END DEFINE BLOCK for d3-dsv@1.0.3/build/d3-dsv.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/csvwidget/toolbar.js **/
jupyter.define('jupyterlab@0.15.1/lib/csvwidget/toolbar.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	/**
	 * The supported parsing delimiters.
	 */
	exports.DELIMITERS = [',', ';', '\t'];
	/**
	 * The labels for each delimiter as they appear in the dropdown menu.
	 */
	exports.LABELS = [',', ';', '\\t'];
	/**
	 * The class name added to a csv toolbar widget.
	 */
	var CSV_TOOLBAR_CLASS = 'jp-CSVToolbar';
	/**
	 * The class name added to a csv toolbar's dropdown element.
	 */
	var CSV_TOOLBAR_DROPDOWN_CLASS = 'jp-CSVToolbar-dropdown';
	/**
	 * A widget for CSV widget toolbars.
	 */
	var CSVToolbar = (function (_super) {
	    __extends(CSVToolbar, _super);
	    /**
	     * Construct a new csv table widget.
	     */
	    function CSVToolbar(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this, { node: Private.createNode(options.selected) });
	        this.addClass(CSV_TOOLBAR_CLASS);
	    }
	    Object.defineProperty(CSVToolbar.prototype, "selectNode", {
	        /**
	         * The delimiter dropdown menu.
	         */
	        get: function () {
	            return this.node.getElementsByTagName('select')[0];
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Handle the DOM events for the widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the dock panel's node. It should
	     * not be called directly by user code.
	     */
	    CSVToolbar.prototype.handleEvent = function (event) {
	        switch (event.type) {
	            case 'change':
	                this.delimiterChanged.emit(this.selectNode.value);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle `after-attach` messages for the widget.
	     */
	    CSVToolbar.prototype.onAfterAttach = function (msg) {
	        this.selectNode.addEventListener('change', this);
	    };
	    /**
	     * Handle `before-detach` messages for the widget.
	     */
	    CSVToolbar.prototype.onBeforeDetach = function (msg) {
	        this.selectNode.removeEventListener('change', this);
	    };
	    return CSVToolbar;
	}(widget_1.Widget));
	exports.CSVToolbar = CSVToolbar;
	// Define the signals for the `CSVToolbar` class.
	signaling_1.defineSignal(CSVToolbar.prototype, 'delimiterChanged');
	/**
	 * A namespace for private toolbar methods.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create the node for the delimiter switcher.
	     */
	    function createNode(selected) {
	        var div = document.createElement('div');
	        var label = document.createElement('label');
	        var select = document.createElement('select');
	        select.className = CSV_TOOLBAR_DROPDOWN_CLASS;
	        label.textContent = 'Delimiter: ';
	        iteration_1.each(iteration_1.zip(exports.DELIMITERS, exports.LABELS), function (_a) {
	            var delimiter = _a[0], label = _a[1];
	            var option = document.createElement('option');
	            option.value = delimiter;
	            option.textContent = label;
	            if (delimiter === selected) {
	                option.selected = true;
	            }
	            select.appendChild(option);
	        });
	        label.appendChild(select);
	        div.appendChild(label);
	        return div;
	    }
	    Private.createNode = createNode;
	})(Private || (Private = {}));
	//# sourceMappingURL=toolbar.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/csvwidget/toolbar.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/docmanager/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var index_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docmanager/index.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var services_1 = __jupyter_require__('jupyterlab@0.15.1/lib/services/index.js');
	/**
	 * The default document manager provider.
	 */
	var plugin = {
	    id: 'jupyter.services.document-manager',
	    provides: index_1.IDocumentManager,
	    requires: [services_1.IServiceManager, docregistry_1.IDocumentRegistry],
	    activate: function (app, manager, registry) {
	        var id = 1;
	        var opener = {
	            open: function (widget) {
	                if (!widget.id) {
	                    widget.id = "document-manager-" + ++id;
	                }
	                if (!widget.isAttached) {
	                    app.shell.addToMainArea(widget);
	                }
	                app.shell.activateMain(widget.id);
	            }
	        };
	        return new index_1.DocumentManager({ registry: registry, manager: manager, opener: opener });
	    }
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/docmanager/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/docmanager/manager.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/docmanager/savehandler.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/docmanager/widgetmanager.js'));
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/manager.js **/
jupyter.define('jupyterlab@0.15.1/lib/docmanager/manager.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var properties_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/properties.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var savehandler_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docmanager/savehandler.js');
	var widgetmanager_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docmanager/widgetmanager.js');
	/* tslint:disable */
	/**
	 * The document registry token.
	 */
	exports.IDocumentManager = new token_1.Token('jupyter.services.document-manager');
	/**
	 * The document manager.
	 *
	 * #### Notes
	 * The document manager is used to register model and widget creators,
	 * and the file browser uses the document manager to create widgets. The
	 * document manager maintains a context for each path and model type that is
	 * open, and a list of widgets for each context. The document manager is in
	 * control of the proper closing and disposal of the widgets and contexts.
	 */
	var DocumentManager = (function () {
	    /**
	     * Construct a new document manager.
	     */
	    function DocumentManager(options) {
	        this._serviceManager = null;
	        this._widgetManager = null;
	        this._registry = null;
	        this._contexts = new vector_1.Vector();
	        this._opener = null;
	        this._registry = options.registry;
	        this._serviceManager = options.manager;
	        this._opener = options.opener;
	        this._widgetManager = new widgetmanager_1.DocumentWidgetManager({
	            registry: this._registry
	        });
	    }
	    Object.defineProperty(DocumentManager.prototype, "registry", {
	        /**
	         * Get the registry used by the manager.
	         */
	        get: function () {
	            return this._registry;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DocumentManager.prototype, "services", {
	        /**
	         * Get the service manager used by the manager.
	         */
	        get: function () {
	            return this._serviceManager;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(DocumentManager.prototype, "isDisposed", {
	        /**
	         * Get whether the document manager has been disposed.
	         */
	        get: function () {
	            return this._serviceManager === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the document manager.
	     */
	    DocumentManager.prototype.dispose = function () {
	        if (this._serviceManager === null) {
	            return;
	        }
	        this._serviceManager = null;
	        this._widgetManager = null;
	        signaling_1.clearSignalData(this);
	        iteration_1.each(this._contexts, function (context) {
	            context.dispose();
	        });
	        this._contexts.clear();
	    };
	    /**
	     * Open a file and return the widget used to view it.
	     * Reveals an already existing editor.
	     *
	     * @param path - The file path to open.
	     *
	     * @param widgetName - The name of the widget factory to use. 'default' will use the default widget.
	     *
	     * @param kernel - An optional kernel name/id to override the default.
	     *
	     * @returns The created widget, or `undefined`.
	     *
	     * #### Notes
	     * This function will return `undefined` if a valid widget factory
	     * cannot be found.
	     */
	    DocumentManager.prototype.openOrReveal = function (path, widgetName, kernel) {
	        if (widgetName === void 0) { widgetName = 'default'; }
	        var widget = this.findWidget(path, widgetName);
	        if (!widget) {
	            widget = this.open(path, widgetName, kernel);
	        }
	        else {
	            this._opener.open(widget);
	        }
	        return widget;
	    };
	    /**
	     * Open a file and return the widget used to view it.
	     *
	     * @param path - The file path to open.
	     *
	     * @param widgetName - The name of the widget factory to use. 'default' will use the default widget.
	     *
	     * @param kernel - An optional kernel name/id to override the default.
	     *
	     * @returns The created widget, or `undefined`.
	     *
	     * #### Notes
	     * This function will return `undefined` if a valid widget factory
	     * cannot be found.
	     */
	    DocumentManager.prototype.open = function (path, widgetName, kernel) {
	        if (widgetName === void 0) { widgetName = 'default'; }
	        return this._createOrOpenDocument('open', path, widgetName, kernel);
	    };
	    /**
	     * Create a new file and return the widget used to view it.
	     *
	     * @param path - The file path to create.
	     *
	     * @param widgetName - The name of the widget factory to use. 'default' will use the default widget.
	     *
	     * @param kernel - An optional kernel name/id to override the default.
	     *
	     * @returns The created widget, or `undefined`.
	     *
	     * #### Notes
	     * This function will return `undefined` if a valid widget factory
	     * cannot be found.
	     */
	    DocumentManager.prototype.createNew = function (path, widgetName, kernel) {
	        if (widgetName === void 0) { widgetName = 'default'; }
	        return this._createOrOpenDocument('create', path, widgetName, kernel);
	    };
	    /**
	     * See if a widget already exists for the given path and widget name.
	     *
	     * @param path - The file path to use.
	     *
	     * @param widgetName - The name of the widget factory to use. 'default' will use the default widget.
	     *
	     * @returns The found widget, or `undefined`.
	     *
	     * #### Notes
	     * This can be used to use an existing widget instead of opening
	     * a new widget.
	     */
	    DocumentManager.prototype.findWidget = function (path, widgetName) {
	        if (widgetName === void 0) { widgetName = 'default'; }
	        if (widgetName === 'default') {
	            var extname = docregistry_1.DocumentRegistry.extname(path);
	            var factory = this._registry.defaultWidgetFactory(extname);
	            if (!factory) {
	                return;
	            }
	            widgetName = factory.name;
	        }
	        var context = this._contextForPath(path);
	        if (context) {
	            return this._widgetManager.findWidget(context, widgetName);
	        }
	    };
	    /**
	     * Get the document context for a widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The context associated with the widget, or `undefined`.
	     */
	    DocumentManager.prototype.contextForWidget = function (widget) {
	        return this._widgetManager.contextForWidget(widget);
	    };
	    /**
	     * Clone a widget.
	     *
	     * @param widget - The source widget.
	     *
	     * @returns A new widget or `undefined`.
	     *
	     * #### Notes
	     *  Uses the same widget factory and context as the source, or returns
	     *  `undefined` if the source widget is not managed by this manager.
	     */
	    DocumentManager.prototype.cloneWidget = function (widget) {
	        return this._widgetManager.cloneWidget(widget);
	    };
	    /**
	     * Close the widgets associated with a given path.
	     *
	     * @param path - The target path.
	     */
	    DocumentManager.prototype.closeFile = function (path) {
	        var context = this._contextForPath(path);
	        if (context) {
	            this._widgetManager.closeWidgets(context);
	        }
	    };
	    /**
	     * Close all of the open documents.
	     */
	    DocumentManager.prototype.closeAll = function () {
	        var _this = this;
	        iteration_1.each(iteration_1.toArray(this._contexts), function (context) {
	            _this._widgetManager.closeWidgets(context);
	        });
	    };
	    /**
	     * Find a context for a given path and factory name.
	     */
	    DocumentManager.prototype._findContext = function (path, factoryName) {
	        return searching_1.find(this._contexts, function (context) {
	            return (context.factoryName === factoryName &&
	                context.path === path);
	        });
	    };
	    /**
	     * Get a context for a given path.
	     */
	    DocumentManager.prototype._contextForPath = function (path) {
	        return searching_1.find(this._contexts, function (context) {
	            return context.path === path;
	        });
	    };
	    /**
	     * Create a context from a path and a model factory.
	     */
	    DocumentManager.prototype._createContext = function (path, factory) {
	        var _this = this;
	        var adopter = function (widget) {
	            _this._widgetManager.adoptWidget(context, widget);
	            _this._opener.open(widget);
	        };
	        var context = new docregistry_1.Context({
	            opener: adopter,
	            manager: this._serviceManager,
	            factory: factory,
	            path: path
	        });
	        var handler = new savehandler_1.SaveHandler({
	            context: context,
	            manager: this._serviceManager
	        });
	        Private.saveHandlerProperty.set(context, handler);
	        context.ready.then(function () {
	            handler.start();
	        });
	        context.disposed.connect(this._onContextDisposed, this);
	        this._contexts.pushBack(context);
	        return context;
	    };
	    /**
	     * Handle a context disposal.
	     */
	    DocumentManager.prototype._onContextDisposed = function (context) {
	        this._contexts.remove(context);
	    };
	    /**
	     * Get the model factory for a given widget name.
	     */
	    DocumentManager.prototype._widgetFactoryFor = function (path, widgetName) {
	        var registry = this._registry;
	        if (widgetName === 'default') {
	            var extname = docregistry_1.DocumentRegistry.extname(path);
	            var factory = registry.defaultWidgetFactory(extname);
	            if (!factory) {
	                return;
	            }
	            widgetName = factory.name;
	        }
	        return registry.getWidgetFactory(widgetName);
	    };
	    /**
	     * Creates a new document, or loads one from disk, depending on the `which` argument.
	     * If `which==='create'`, then it creates a new document. If `which==='open'`,
	     * then it loads the document from disk.
	     *
	     * The two cases differ in how the document context is handled, but the creation
	     * of the widget and launching of the kernel are identical.
	     */
	    DocumentManager.prototype._createOrOpenDocument = function (which, path, widgetName, kernel) {
	        if (widgetName === void 0) { widgetName = 'default'; }
	        var widgetFactory = this._widgetFactoryFor(path, widgetName);
	        if (!widgetFactory) {
	            return;
	        }
	        var factory = this._registry.getModelFactory(widgetFactory.modelName);
	        if (!factory) {
	            return;
	        }
	        var context = null;
	        // Handle the load-from-disk case
	        if (which === 'open') {
	            // Use an existing context if available.
	            context = this._findContext(path, factory.name);
	            if (!context) {
	                context = this._createContext(path, factory);
	                // Load the contents from disk.
	                context.revert();
	            }
	        }
	        else if (which === 'create') {
	            context = this._createContext(path, factory);
	            // Immediately save the contents to disk.
	            context.save();
	        }
	        // Maybe launch/connect the kernel for the context.
	        if (kernel && (kernel.id || kernel.name) && widgetFactory.canStartKernel) {
	            // If the kernel is valid and the widgetFactory wants one.
	            context.changeKernel(kernel);
	        }
	        else if (widgetFactory.preferKernel &&
	            !(kernel && !kernel.id && !kernel.name) &&
	            !context.kernel) {
	            // If the kernel is not the `None` kernel and the widgetFactory wants one
	            context.startDefaultKernel();
	        }
	        var widget = this._widgetManager.createWidget(widgetFactory.name, context);
	        this._opener.open(widget);
	        return widget;
	    };
	    return DocumentManager;
	}());
	exports.DocumentManager = DocumentManager;
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * An attached property for a context save handler.
	     */
	    Private.saveHandlerProperty = new properties_1.AttachedProperty({
	        name: 'saveHandler'
	    });
	    ;
	})(Private || (Private = {}));
	//# sourceMappingURL=manager.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/manager.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/savehandler.js **/
jupyter.define('jupyterlab@0.15.1/lib/docmanager/savehandler.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	/**
	 * A class that manages the auto saving of a document.
	 *
	 * #### Notes
	 * Implements https://github.com/ipython/ipython/wiki/IPEP-15:-Autosaving-the-IPython-Notebook.
	 */
	var SaveHandler = (function () {
	    /**
	     * Construct a new save handler.
	     */
	    function SaveHandler(options) {
	        this._autosaveTimer = -1;
	        this._minInterval = -1;
	        this._interval = -1;
	        this._context = null;
	        this._manager = null;
	        this._isActive = false;
	        this._inDialog = false;
	        this._manager = options.manager;
	        this._context = options.context;
	        this._minInterval = options.saveInterval * 1000 || 120000;
	        this._interval = this._minInterval;
	        // Restart the timer when the contents model is updated.
	        this._context.fileChanged.connect(this._setTimer, this);
	        this._context.disposed.connect(this.dispose, this);
	    }
	    Object.defineProperty(SaveHandler.prototype, "saveInterval", {
	        /**
	         * The save interval used by the timer (in seconds).
	         */
	        get: function () {
	            return this._interval / 1000;
	        },
	        set: function (value) {
	            this._minInterval = this._interval = value * 1000;
	            if (this._isActive) {
	                this._setTimer();
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SaveHandler.prototype, "isActive", {
	        /**
	         * Get whether the handler is active.
	         */
	        get: function () {
	            return this._isActive;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(SaveHandler.prototype, "isDisposed", {
	        /**
	         * Get whether the save handler is disposed.
	         */
	        get: function () {
	            return this._context === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the save handler.
	     */
	    SaveHandler.prototype.dispose = function () {
	        if (this._context === null) {
	            return;
	        }
	        this._context = null;
	        clearTimeout(this._autosaveTimer);
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Start the autosaver.
	     */
	    SaveHandler.prototype.start = function () {
	        this._isActive = true;
	        this._setTimer();
	    };
	    /**
	     * Stop the autosaver.
	     */
	    SaveHandler.prototype.stop = function () {
	        this._isActive = false;
	        clearTimeout(this._autosaveTimer);
	    };
	    /**
	     * Set the timer.
	     */
	    SaveHandler.prototype._setTimer = function () {
	        var _this = this;
	        clearTimeout(this._autosaveTimer);
	        if (!this._isActive) {
	            return;
	        }
	        this._autosaveTimer = setTimeout(function () {
	            _this._save();
	        }, this._interval);
	    };
	    /**
	     * Handle an autosave timeout.
	     */
	    SaveHandler.prototype._save = function () {
	        var _this = this;
	        var context = this._context;
	        // Trigger the next update.
	        this._setTimer();
	        if (!context) {
	            return;
	        }
	        // Bail if the model is not dirty or it is read only, or the dialog
	        // is already showing.
	        if (!context.model.dirty || context.model.readOnly || this._inDialog) {
	            return;
	        }
	        // Make sure the file has not changed on disk.
	        var promise = this._manager.contents.get(context.path);
	        promise.then(function (model) {
	            if (!_this.isDisposed && context.contentsModel &&
	                model.last_modified !== context.contentsModel.last_modified) {
	                return _this._timeConflict(model.last_modified);
	            }
	            return _this._finishSave();
	        }, function (err) {
	            return _this._finishSave();
	        }).catch(function (err) {
	            console.error('Error in Auto-Save', err.message);
	        });
	    };
	    /**
	     * Handle a time conflict.
	     */
	    SaveHandler.prototype._timeConflict = function (modified) {
	        var _this = this;
	        var localTime = new Date(this._context.contentsModel.last_modified);
	        var remoteTime = new Date(modified);
	        console.warn(("Last saving peformed " + localTime + " ") +
	            "while the current file seem to have been saved " +
	            ("" + remoteTime));
	        var body = "The file has changed on disk since the last time we " +
	            "opened or saved it. " +
	            "Do you want to overwrite the file on disk with the version " +
	            " open here, or load the version on disk (revert)?";
	        this._inDialog = true;
	        return dialog_1.showDialog({
	            title: 'File Changed', body: body, okText: 'OVERWRITE',
	            buttons: [dialog_1.cancelButton, { text: 'REVERT' }, dialog_1.okButton]
	        }).then(function (result) {
	            if (_this.isDisposed) {
	                return;
	            }
	            _this._inDialog = false;
	            if (result.text === 'OVERWRITE') {
	                return _this._finishSave();
	            }
	            else if (result.text === 'REVERT') {
	                return _this._context.revert();
	            }
	        });
	    };
	    /**
	     * Perform the save, adjusting the save interval as necessary.
	     */
	    SaveHandler.prototype._finishSave = function () {
	        var _this = this;
	        var start = new Date().getTime();
	        return this._context.save().then(function () {
	            if (_this.isDisposed) {
	                return;
	            }
	            var duration = new Date().getTime() - start;
	            // New save interval: higher of 10x save duration or min interval.
	            _this._interval = Math.max(10 * duration, _this._minInterval);
	            // Restart the update to pick up the new interval.
	            _this._setTimer();
	        });
	    };
	    return SaveHandler;
	}());
	exports.SaveHandler = SaveHandler;
	//# sourceMappingURL=savehandler.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/savehandler.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/widgetmanager.js **/
jupyter.define('jupyterlab@0.15.1/lib/docmanager/widgetmanager.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var messaging_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/messaging.js');
	var properties_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/properties.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var dates_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dates.js');
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	/**
	 * The class name added to document widgets.
	 */
	var DOCUMENT_CLASS = 'jp-Document';
	/**
	 * A class that maintains the lifecyle of file-backed widgets.
	 */
	var DocumentWidgetManager = (function () {
	    /**
	     * Construct a new document widget manager.
	     */
	    function DocumentWidgetManager(options) {
	        this._closeGuard = false;
	        this._registry = null;
	        this._registry = options.registry;
	    }
	    Object.defineProperty(DocumentWidgetManager.prototype, "isDisposed", {
	        /**
	         * Test whether the document widget manager is disposed.
	         */
	        get: function () {
	            return this._registry === null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the widget manager.
	     */
	    DocumentWidgetManager.prototype.dispose = function () {
	        if (this._registry == null) {
	            return;
	        }
	        this._registry = null;
	        signaling_1.disconnectReceiver(this);
	    };
	    /**
	     * Create a widget for a document and handle its lifecycle.
	     *
	     * @param name - The name of the widget factory.
	     *
	     * @param context - The document context object.
	     *
	     * @returns A widget created by the factory.
	     *
	     * @throws If the factory is not registered.
	     */
	    DocumentWidgetManager.prototype.createWidget = function (name, context) {
	        var _this = this;
	        var factory = this._registry.getWidgetFactory(name);
	        if (!factory) {
	            throw new Error("Factory is not registered: " + name);
	        }
	        var widget = factory.createNew(context);
	        Private.nameProperty.set(widget, name);
	        // Handle widget extensions.
	        var disposables = new disposable_1.DisposableSet();
	        iteration_1.each(this._registry.widgetExtensions(name), function (extender) {
	            disposables.add(extender.createNew(widget, context));
	        });
	        Private.disposablesProperty.set(widget, disposables);
	        widget.disposed.connect(this._onWidgetDisposed, this);
	        this.adoptWidget(context, widget);
	        context.fileChanged.connect(this._onFileChanged, this);
	        context.ready.then(function () {
	            _this.setCaption(widget);
	        });
	        return widget;
	    };
	    /**
	     * Install the message hook for the widget and add to list
	     * of known widgets.
	     *
	     * @param context - The document context object.
	     *
	     * @param widget - The widget to adopt.
	     */
	    DocumentWidgetManager.prototype.adoptWidget = function (context, widget) {
	        var _this = this;
	        var widgets = Private.widgetsProperty.get(context);
	        widgets.pushBack(widget);
	        messaging_1.installMessageHook(widget, function (handler, msg) {
	            return _this.filterMessage(handler, msg);
	        });
	        widget.addClass(DOCUMENT_CLASS);
	        widget.title.closable = true;
	        widget.disposed.connect(this._widgetDisposed, this);
	        Private.contextProperty.set(widget, context);
	    };
	    /**
	     * See if a widget already exists for the given context and widget name.
	     *
	     * @param context - The document context object.
	     *
	     * @returns The found widget, or `undefined`.
	     *
	     * #### Notes
	     * This can be used to use an existing widget instead of opening
	     * a new widget.
	     */
	    DocumentWidgetManager.prototype.findWidget = function (context, widgetName) {
	        var widgets = Private.widgetsProperty.get(context);
	        return searching_1.find(widgets, function (widget) {
	            var name = Private.nameProperty.get(widget);
	            if (name === widgetName) {
	                return true;
	            }
	        });
	    };
	    /**
	     * Get the document context for a widget.
	     *
	     * @param widget - The widget of interest.
	     *
	     * @returns The context associated with the widget, or `undefined`.
	     */
	    DocumentWidgetManager.prototype.contextForWidget = function (widget) {
	        return Private.contextProperty.get(widget);
	    };
	    /**
	     * Clone a widget.
	     *
	     * @param widget - The source widget.
	     *
	     * @returns A new widget or `undefined`.
	     *
	     * #### Notes
	     *  Uses the same widget factory and context as the source, or returns
	     *  `undefined` if the source widget is not managed by this manager.
	     */
	    DocumentWidgetManager.prototype.cloneWidget = function (widget) {
	        var context = Private.contextProperty.get(widget);
	        if (!context) {
	            return;
	        }
	        var name = Private.nameProperty.get(widget);
	        var newWidget = this.createWidget(name, context);
	        this.adoptWidget(context, newWidget);
	        return widget;
	    };
	    /**
	     * Close the widgets associated with a given context.
	     *
	     * @param context - The document context object.
	     */
	    DocumentWidgetManager.prototype.closeWidgets = function (context) {
	        var widgets = Private.widgetsProperty.get(context);
	        iteration_1.each(widgets, function (widget) {
	            widget.close();
	        });
	    };
	    /**
	     * Filter a message sent to a message handler.
	     *
	     * @param handler - The target handler of the message.
	     *
	     * @param msg - The message dispatched to the handler.
	     *
	     * @returns `false` if the message should be filtered, of `true`
	     *   if the message should be dispatched to the handler as normal.
	     */
	    DocumentWidgetManager.prototype.filterMessage = function (handler, msg) {
	        if (msg.type === 'close-request') {
	            if (this._closeGuard) {
	                return true;
	            }
	            this.onClose(handler);
	            return false;
	        }
	        return true;
	    };
	    /**
	     * Set the caption for widget title.
	     *
	     * @param widget - The target widget.
	     */
	    DocumentWidgetManager.prototype.setCaption = function (widget) {
	        var context = Private.contextProperty.get(widget);
	        var model = context.contentsModel;
	        if (!model) {
	            widget.title.caption = '';
	            return;
	        }
	        context.listCheckpoints().then(function (checkpoints) {
	            if (widget.isDisposed) {
	                return;
	            }
	            var last = checkpoints[checkpoints.length - 1];
	            var checkpoint = last ? dates_1.dateTime(last.last_modified) : 'None';
	            widget.title.caption = (("Name: " + model.name + "\n") +
	                ("Path: " + model.path + "\n") +
	                ("Last Saved: " + dates_1.dateTime(model.last_modified) + "\n") +
	                ("Last Checkpoint: " + checkpoint));
	        });
	    };
	    /**
	     * Handle `'close-request'` messages.
	     *
	     * @param widget - The target widget.
	     *
	     * @returns A promise that resolves with whether the widget was closed.
	     */
	    DocumentWidgetManager.prototype.onClose = function (widget) {
	        var _this = this;
	        // Handle dirty state.
	        return this._maybeClose(widget).then(function (result) {
	            if (widget.isDisposed) {
	                return true;
	            }
	            if (result) {
	                _this._closeGuard = true;
	                widget.close();
	                _this._closeGuard = false;
	                // Dispose of document widgets when they are closed.
	                widget.dispose();
	            }
	            return result;
	        }).catch(function () {
	            widget.dispose();
	        });
	    };
	    /**
	     * Ask the user whether to close an unsaved file.
	     */
	    DocumentWidgetManager.prototype._maybeClose = function (widget) {
	        // Bail if the model is not dirty or other widgets are using the model.
	        var context = Private.contextProperty.get(widget);
	        var widgets = Private.widgetsProperty.get(context);
	        var model = context.model;
	        if (!model.dirty || widgets.length > 1) {
	            return Promise.resolve(true);
	        }
	        var fileName = widget.title.label;
	        return dialog_1.showDialog({
	            title: 'Close without saving?',
	            body: "File \"" + fileName + "\" has unsaved changes, close without saving?",
	            buttons: [dialog_1.cancelButton, dialog_1.warnButton]
	        }).then(function (value) {
	            if (value && value.text === 'OK') {
	                return true;
	            }
	            return false;
	        });
	    };
	    /**
	     * Handle the disposal of a widget.
	     */
	    DocumentWidgetManager.prototype._widgetDisposed = function (widget) {
	        var context = Private.contextProperty.get(widget);
	        var widgets = Private.widgetsProperty.get(context);
	        // Remove the widget.
	        widgets.remove(widget);
	        // Dispose of the context if this is the last widget using it.
	        if (!widgets.length) {
	            context.dispose();
	        }
	    };
	    /**
	     * Handle the disposal of a widget.
	     */
	    DocumentWidgetManager.prototype._onWidgetDisposed = function (widget) {
	        var disposables = Private.disposablesProperty.get(widget);
	        disposables.dispose();
	    };
	    /**
	     * Handle a file changed signal for a context.
	     */
	    DocumentWidgetManager.prototype._onFileChanged = function (context) {
	        var _this = this;
	        var widgets = Private.widgetsProperty.get(context);
	        iteration_1.each(widgets, function (widget) { _this.setCaption(widget); });
	    };
	    return DocumentWidgetManager;
	}());
	exports.DocumentWidgetManager = DocumentWidgetManager;
	/**
	 * A private namespace for DocumentManager data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * A private attached property for a widget context.
	     */
	    Private.contextProperty = new properties_1.AttachedProperty({
	        name: 'context'
	    });
	    /**
	     * A private attached property for a widget factory name.
	     */
	    Private.nameProperty = new properties_1.AttachedProperty({
	        name: 'name'
	    });
	    /**
	     * A private attached property for the widgets associated with a context.
	     */
	    Private.widgetsProperty = new properties_1.AttachedProperty({
	        name: 'widgets',
	        create: function () {
	            return new vector_1.Vector();
	        }
	    });
	    /**
	     * A private attached property for a widget's disposables.
	     */
	    Private.disposablesProperty = new properties_1.AttachedProperty({
	        name: 'disposables'
	    });
	})(Private || (Private = {}));
	//# sourceMappingURL=widgetmanager.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docmanager/widgetmanager.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/docregistry/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var index_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	/**
	 * The default document registry provider.
	 */
	var plugin = {
	    id: 'jupyter.services.document-registry',
	    provides: index_1.IDocumentRegistry,
	    activate: function () {
	        var registry = new index_1.DocumentRegistry();
	        registry.addModelFactory(new index_1.TextModelFactory());
	        registry.addModelFactory(new index_1.Base64ModelFactory());
	        registry.addFileType({
	            name: 'Text',
	            extension: '.txt',
	            contentType: 'file',
	            fileFormat: 'text'
	        });
	        registry.addCreator({ name: 'Text File', fileType: 'Text', });
	        return registry;
	    }
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/docregistry/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/editorwidget/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/editorwidget/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var properties_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/properties.js');
	var codeeditor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/index.js');
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var console_1 = __jupyter_require__('jupyterlab@0.15.1/lib/console/index.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/editorwidget/index.js');
	/**
	 * The class name for all main area portrait tab icons.
	 */
	var PORTRAIT_ICON_CLASS = 'jp-MainAreaPortraitIcon';
	/**
	 * The class name for the text editor icon from the default theme.
	 */
	var EDITOR_ICON_CLASS = 'jp-ImageTextEditor';
	/**
	 * The name of the factory that creates editor widgets.
	 */
	var FACTORY = 'Editor';
	/**
	 * The editor handler extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.services.editor-handler',
	    requires: [docregistry_1.IDocumentRegistry, instancerestorer_1.IInstanceRestorer, codeeditor_1.IEditorServices],
	    provides: _1.IEditorTracker,
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Sets up the editor widget
	 */
	function activate(app, registry, restorer, editorServices) {
	    var factory = new _1.EditorWidgetFactory({
	        editorServices: editorServices,
	        factoryOptions: {
	            name: FACTORY,
	            fileExtensions: ['*'],
	            defaultFor: ['*']
	        }
	    });
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: 'editor' });
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: filebrowser_1.CommandIDs.open,
	        args: function (widget) { return ({ path: widget.context.path, factory: FACTORY }); },
	        name: function (widget) { return widget.context.path; }
	    });
	    factory.widgetCreated.connect(function (sender, widget) {
	        widget.title.icon = PORTRAIT_ICON_CLASS + " " + EDITOR_ICON_CLASS;
	        // Notify the instance tracker if restore data needs to update.
	        widget.context.pathChanged.connect(function () { tracker.save(widget); });
	        tracker.add(widget);
	    });
	    registry.addWidgetFactory(factory);
	    /**
	     * Toggle editor line numbers
	     */
	    function toggleLineNums() {
	        if (tracker.currentWidget) {
	            var editor = tracker.currentWidget.editor;
	            editor.lineNumbers = !editor.lineNumbers;
	        }
	    }
	    /**
	     * Toggle editor line wrap
	     */
	    function toggleLineWrap() {
	        if (tracker.currentWidget) {
	            var editor = tracker.currentWidget.editor;
	            editor.wordWrap = !editor.wordWrap;
	        }
	    }
	    /**
	     * An attached property for the session id associated with an editor widget.
	     */
	    var sessionIdProperty = new properties_1.AttachedProperty({
	        name: 'sessionId'
	    });
	    var commands = app.commands;
	    commands.addCommand(_1.CommandIDs.lineNumbers, {
	        execute: function () { toggleLineNums(); },
	        label: 'Toggle Line Numbers'
	    });
	    commands.addCommand(_1.CommandIDs.lineWrap, {
	        execute: function () { toggleLineWrap(); },
	        label: 'Toggle Line Wrap'
	    });
	    commands.addCommand(_1.CommandIDs.createConsole, {
	        execute: function () {
	            var widget = tracker.currentWidget;
	            if (!widget) {
	                return;
	            }
	            var options = {
	                path: widget.context.path,
	                preferredLanguage: widget.context.model.defaultKernelLanguage
	            };
	            return commands.execute(console_1.CommandIDs.create, options)
	                .then(function (id) { sessionIdProperty.set(widget, id); });
	        },
	        label: 'Create Console for Editor'
	    });
	    commands.addCommand(_1.CommandIDs.runCode, {
	        execute: function () {
	            var widget = tracker.currentWidget;
	            if (!widget) {
	                return;
	            }
	            // Get the session id.
	            var id = sessionIdProperty.get(widget);
	            if (!id) {
	                return;
	            }
	            // Get the selected code from the editor.
	            var editor = widget.editor;
	            var selection = editor.getSelection();
	            var start = editor.getOffsetAt(selection.start);
	            var end = editor.getOffsetAt(selection.end);
	            var code = editor.model.value.text.substring(start, end);
	            return commands.execute(console_1.CommandIDs.inject, { id: id, code: code });
	        },
	        label: 'Run Code'
	    });
	    return tracker;
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/editorwidget/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/faq/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/faq/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var commandlinker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandlinker/index.js');
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/faq/index.js');
	/**
	 * The FAQ page extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.faq',
	    requires: [commandpalette_1.ICommandPalette, commandlinker_1.ICommandLinker, instancerestorer_1.IInstanceRestorer],
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the FAQ plugin.
	 */
	function activate(app, palette, linker, restorer) {
	    var category = 'Help';
	    var command = _1.CommandIDs.open;
	    var model = new _1.FaqModel();
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: 'faq' });
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: command,
	        args: function () { return null; },
	        name: function () { return 'faq'; }
	    });
	    var widget;
	    function newWidget() {
	        var widget = new _1.FaqWidget({ linker: linker });
	        widget.model = model;
	        widget.id = 'faq';
	        widget.title.label = 'FAQ';
	        widget.title.closable = true;
	        tracker.add(widget);
	        return widget;
	    }
	    app.commands.addCommand(command, {
	        label: 'Open FAQ',
	        execute: function () {
	            if (!widget || widget.isDisposed) {
	                widget = newWidget();
	                app.shell.addToMainArea(widget);
	            }
	            app.shell.activateMain(widget.id);
	        }
	    });
	    palette.addItem({ command: command, category: category });
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/faq/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/commandlinker/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/commandlinker/index.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) Jupyter Development Team.
	| Distributed under the terms of the Modified BSD License.
	|----------------------------------------------------------------------------*/
	"use strict";
	var commandlinker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandlinker/commandlinker.js');
	exports.ICommandLinker = commandlinker_1.ICommandLinker;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/commandlinker/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/faq/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/faq/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/faq/widget.js'));
	/**
	 * The command IDs used by the FAQ plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.open = 'faq-jupyterlab:open';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/faq/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/faq/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/faq/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var vdom_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/vdom.js');
	var about_1 = __jupyter_require__('jupyterlab@0.15.1/lib/about/index.js');
	var vdom_2 = __jupyter_require__('jupyterlab@0.15.1/lib/common/vdom.js');
	/**
	 * The class name added to the FAQ plugin.
	 */
	var FAQ_CLASS = 'jp-FAQ';
	/**
	 * The id name added to the header section element.
	 */
	var HEADER_ID = 'faq-header';
	/**
	 * The class name added to the title.
	 */
	var TITLE_CLASS = 'jp-FAQ-title';
	/**
	 * The class name added to h1 elements.
	 */
	var HEADER_CLASS = 'jp-FAQ-h1';
	/**
	 * The class name added to h2 elements.
	 */
	var SUBHEADER_CLASS = 'jp-FAQ-h2';
	/**
	 * The class name added for the question mark icon from default-theme.
	 */
	var QUESTIONMARK_ICON_CLASS = 'jp-QuestionMark';
	/**
	 * The class named added the question mark icon.
	 */
	var QUESTIONMARK_CLASS = 'jp-FAQ-QuestionMark';
	/**
	 * The class name added to faq content.
	 */
	var CONTENT_CLASS = 'jp-FAQ-content';
	/**
	 * The class name added to unordered list elements.
	 */
	var FAQ_LIST_CLASS = 'jp-FAQ-ul';
	/**
	 * The class name added to table of contents elements.
	 */
	var TOC_CLASS = 'jp-FAQ-toc';
	/**
	 * The class name added to questions.
	 */
	var QUESTION_CLASS = 'jp-FAQ-question';
	/**
	 * The class name added to answers.
	 */
	var ANSWER_CLASS = 'jp-FAQ-answer';
	/**
	 * The class name added to anchor elements.
	 */
	var ANCHOR_CLASS = 'jp-FAQ-a';
	/**
	 * Title of the FAQ plugin.
	 */
	var TITLE = 'Frequently Asked Questions';
	/**
	 * Contain subheadings for each section.
	 */
	var SUBHEADINGS = ['THE BASICS', 'FEATURES', 'DEVELOPER'];
	/**
	 * Contain questions for `the basics` section.
	 */
	var BASIC_QUESTIONS = [
	    'What is JupyterLab?',
	    'What is a Jupyter Notebook?',
	    'How stable is JupyterLab?',
	    "I'm confused with the interface. How do I navigate around JupyterLab?"
	];
	/**
	 * Contain questions for the `features` section.
	 */
	var FEATURES_QUESTIONS = [
	    'How do I add more kernels/languages to JupyterLab?',
	    'How can I share my notebooks?'
	];
	/**
	 * Contain questions for the `developer` section.
	 */
	var DEVELOPER_QUESTIONS = [
	    'How do I report a bug?',
	    'I have security concerns about JupyterLab.',
	    'How can I contribute?'
	];
	/**
	 * FaqModel holds data which the FaqWidget will render.
	 */
	var FaqModel = (function (_super) {
	    __extends(FaqModel, _super);
	    function FaqModel() {
	        _super.apply(this, arguments);
	        /**
	         * Title of the FAQ plugin.
	         */
	        this.title = TITLE;
	        /**
	         * Contain subheadings for each section.
	         */
	        this.subheadings = SUBHEADINGS;
	        /**
	         * Contain questions for `the basics` section.
	         */
	        this.basicsQuestions = BASIC_QUESTIONS;
	        /**
	         * Contain questions for the `features` section.
	         */
	        this.featuresQuestions = FEATURES_QUESTIONS;
	        /**
	         * Contain questions for the `developer` section.
	         */
	        this.developerQuestions = DEVELOPER_QUESTIONS;
	    }
	    return FaqModel;
	}(vdom_2.VDomModel));
	exports.FaqModel = FaqModel;
	/**
	 * A virtual-DOM-based widget for the FAQ plugin.
	 */
	var FaqWidget = (function (_super) {
	    __extends(FaqWidget, _super);
	    /**
	     * Construct a new faq widget.
	     */
	    function FaqWidget(options) {
	        _super.call(this);
	        this._linker = options.linker;
	        this.addClass(FAQ_CLASS);
	    }
	    /**
	     * Render the faq plugin to virtual DOM nodes.
	     */
	    FaqWidget.prototype.render = function () {
	        var subheadings = this.model.subheadings;
	        var basicsQuestions = this.model.basicsQuestions;
	        var featuresQuestions = this.model.featuresQuestions;
	        var developerQuestions = this.model.developerQuestions;
	        // Create Frequently Asked Questions Header Section.
	        var faqHeader = vdom_1.h.section({ id: HEADER_ID }, vdom_1.h.span({
	            className: QUESTIONMARK_ICON_CLASS + ' ' + QUESTIONMARK_CLASS
	        }), vdom_1.h.h1({ className: HEADER_CLASS }, vdom_1.h.span({ className: TITLE_CLASS }, this.model.title)));
	        // Create a section element that holds Table of Contents.
	        var questionList = vdom_1.h.section({ className: CONTENT_CLASS }, vdom_1.h.h2({ className: SUBHEADER_CLASS }, subheadings[0]), vdom_1.h.ul({ className: FAQ_LIST_CLASS }, vdom_1.h.li({ className: QUESTION_CLASS + ' ' + TOC_CLASS }, vdom_1.h.a({ href: '#basicsQ1' }, basicsQuestions[0])), vdom_1.h.li({ className: QUESTION_CLASS + ' ' + TOC_CLASS }, vdom_1.h.a({ href: '#basicsQ2' }, basicsQuestions[1])), vdom_1.h.li({ className: QUESTION_CLASS + ' ' + TOC_CLASS }, vdom_1.h.a({ href: '#basicsQ3' }, basicsQuestions[2])), vdom_1.h.li({ className: QUESTION_CLASS + ' ' + TOC_CLASS }, vdom_1.h.a({ href: '#basicsQ4' }, basicsQuestions[3]))), vdom_1.h.h2({ className: SUBHEADER_CLASS }, subheadings[1]), vdom_1.h.ul({ className: FAQ_LIST_CLASS }, vdom_1.h.li({ className: QUESTION_CLASS + ' ' + TOC_CLASS }, vdom_1.h.a({ href: '#featuresQ1' }, featuresQuestions[0])), vdom_1.h.li({ className: QUESTION_CLASS + ' ' + TOC_CLASS }, vdom_1.h.a({ href: '#featuresQ2' }, featuresQuestions[1]))), vdom_1.h.h2({ className: SUBHEADER_CLASS }, subheadings[2]), vdom_1.h.ul({ className: FAQ_LIST_CLASS }, vdom_1.h.li({ className: QUESTION_CLASS + ' ' + TOC_CLASS }, vdom_1.h.a({ href: '#developerQ1' }, developerQuestions[0])), vdom_1.h.li({ className: QUESTION_CLASS + ' ' + TOC_CLASS }, vdom_1.h.a({ href: '#developerQ2' }, developerQuestions[1])), vdom_1.h.li({ className: QUESTION_CLASS + ' ' + TOC_CLASS }, vdom_1.h.a({ href: '#developerQ3' }, developerQuestions[2]))));
	        // Create a section element that all other FAQ Content will go under.
	        var questionAnswerList = vdom_1.h.section({ className: CONTENT_CLASS }, vdom_1.h.h2({ className: SUBHEADER_CLASS }, subheadings[0]), 
	        // Create list of questions/answers under the Basics section.
	        vdom_1.h.ul({ className: FAQ_LIST_CLASS }, vdom_1.h.li({ className: QUESTION_CLASS, id: 'basicsQ1' }, basicsQuestions[0]), vdom_1.h.li({ className: ANSWER_CLASS }, "JupyterLab allows users to arrange multiple Jupyter notebooks,\n          text editors, terminals, output areas, etc. on a single page with\n          multiple panels and tabs into one application. The codebase and UI of\n          JupyterLab is based on a flexible plugin system that makes it easy to\n          extend with new components."), vdom_1.h.li({ className: QUESTION_CLASS, id: 'basicsQ2' }, basicsQuestions[1]), vdom_1.h.li({ className: ANSWER_CLASS }, "Central to the project is the Jupyter Notebook, a web-based\n          platform that allows users to combine live code, equations, narrative\n          text, visualizations, interactive dashboards and other media. Together\n          these building blocks make science and data reproducible across over\n          40 programming languages and combine to form what we call a\n          computational narrative."), vdom_1.h.li({ className: QUESTION_CLASS, id: 'basicsQ3' }, basicsQuestions[2]), vdom_1.h.li({ className: ANSWER_CLASS }, "JupyterLab is currently in an alpha release and not ready for public\n          use as new features and bug fixes are being added very frequently. We\n          strongly recommend to back up your work before using JupyterLab.\n          However, testing, development, and user feedback are greatly\n          appreciated."), vdom_1.h.li({ className: QUESTION_CLASS, id: 'basicsQ4' }, basicsQuestions[3]), vdom_1.h.li({ className: ANSWER_CLASS }, 'Check out the JupyterLab tour ', vdom_1.h.a(this._linker.populateVNodeAttrs({
	            className: ANCHOR_CLASS
	        }, about_1.CommandIDs.open, null), 'here'))), vdom_1.h.h2({ className: SUBHEADER_CLASS }, subheadings[1]), 
	        // Create list of questions/answers under the Features section.
	        vdom_1.h.ul({ className: FAQ_LIST_CLASS }, vdom_1.h.li({
	            className: QUESTION_CLASS,
	            id: 'featuresQ1'
	        }, featuresQuestions[0]), vdom_1.h.li({ className: ANSWER_CLASS }, "To add more languages to the JupyterLab you must install a new\n          kernel. Installing a kernel is usually fairly simple and can be done\n          with a couple terminal commands. However the instructions for\n          installing kernels is different for each language. For further\n          instructions, click", vdom_1.h.a({
	            className: ANCHOR_CLASS,
	            href: 'https://jupyter.readthedocs.io/en/latest/install-kernel.html',
	            target: '_blank'
	        }, 'this'), ' link.'), vdom_1.h.li({
	            className: QUESTION_CLASS,
	            id: 'featuresQ2'
	        }, featuresQuestions[1]), vdom_1.h.li({ className: ANSWER_CLASS }, "You can either publish your notebooks on GitHub or use a free service\n          such as ", vdom_1.h.a({
	            className: ANCHOR_CLASS,
	            href: 'https://nbviewer.jupyter.org/',
	            target: '_blank'
	        }, 'nbviewer.org'), ' to render your notebooks online.')), vdom_1.h.h2({ className: SUBHEADER_CLASS }, subheadings[2]), 
	        // Create list of questions/answers under the Developer section.
	        vdom_1.h.ul({ className: FAQ_LIST_CLASS }, vdom_1.h.li({
	            className: QUESTION_CLASS,
	            id: 'developerQ1'
	        }, developerQuestions[0]), vdom_1.h.li({ className: ANSWER_CLASS }, 'You can open an issue on our ', vdom_1.h.a({
	            className: ANCHOR_CLASS,
	            href: 'https://github.com/jupyterlab/jupyterlab/issues',
	            target: '_blank'
	        }, 'GitHub repository'), '. Please check already opened issues before posting.'), vdom_1.h.li({
	            className: QUESTION_CLASS,
	            id: 'developerQ2'
	        }, developerQuestions[1]), vdom_1.h.li({ className: ANSWER_CLASS }, "If you have any inquiries, concerns, or thought you found a security\n          vulnerability, please write to use at ", vdom_1.h.a({
	            className: ANCHOR_CLASS,
	            href: 'mailto:security@jupyter.org'
	        }, 'security@jupyter.org'), '. We will do our best to repond to you promptly.'), vdom_1.h.li({
	            className: QUESTION_CLASS,
	            id: 'developerQ3'
	        }, developerQuestions[2]), vdom_1.h.li({ className: ANSWER_CLASS }, "There are many ways to contribute to JupyterLab. Whether you are an\n          experienced Python programmer or a newcomer, any interested developers\n          are welcome. You can learn about the JupyterLab codebase by going\n          through our", vdom_1.h.a({
	            className: ANCHOR_CLASS,
	            href: 'https://jupyterlab-tutorial.readthedocs.io/en/latest/index.html',
	            target: '_blank'
	        }, 'tutorial walkthrough'), ' and ', vdom_1.h.a({
	            className: ANCHOR_CLASS,
	            href: 'https://jupyterlab.github.io/jupyterlab/',
	            target: '_blank'
	        }, 'documentation'), '. Also, feel free to ask questions on our ', vdom_1.h.a({
	            className: ANCHOR_CLASS,
	            href: 'https://github.com/jupyterlab/jupyterlab',
	            target: '_blank'
	        }, 'github'), ' or through any of our ', vdom_1.h.a({
	            className: ANCHOR_CLASS,
	            href: 'http://jupyter.org/community.html',
	            target: '_blank'
	        }, 'community resources'), '.')));
	        return [faqHeader, questionList, questionAnswerList];
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    FaqWidget.prototype.onActivateRequest = function (msg) {
	        this.node.tabIndex = -1;
	        this.node.focus();
	    };
	    /**
	     * Handle `'close-request'` messages.
	     */
	    FaqWidget.prototype.onCloseRequest = function (msg) {
	        _super.prototype.onCloseRequest.call(this, msg);
	        this.dispose();
	    };
	    return FaqWidget;
	}(vdom_2.VDomWidget));
	exports.FaqWidget = FaqWidget;
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/faq/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/filebrowser/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var menu_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/menu.js');
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var docmanager_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docmanager/index.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var mainmenu_1 = __jupyter_require__('jupyterlab@0.15.1/lib/mainmenu/index.js');
	var services_1 = __jupyter_require__('jupyterlab@0.15.1/lib/services/index.js');
	var statedb_1 = __jupyter_require__('jupyterlab@0.15.1/lib/statedb/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	/**
	 * The default file browser provider.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.services.file-browser',
	    provides: _1.IPathTracker,
	    requires: [
	        services_1.IServiceManager,
	        docmanager_1.IDocumentManager,
	        docregistry_1.IDocumentRegistry,
	        mainmenu_1.IMainMenu,
	        commandpalette_1.ICommandPalette,
	        instancerestorer_1.IInstanceRestorer,
	        statedb_1.IStateDB
	    ],
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * The filebrowser plugin state namespace.
	 */
	var NAMESPACE = 'filebrowser';
	/**
	 * Activate the file browser.
	 */
	function activate(app, manager, documentManager, registry, mainMenu, palette, restorer, state) {
	    var commands = app.commands, keymap = app.keymap;
	    var fbModel = new _1.FileBrowserModel({ manager: manager });
	    var fbWidget = new _1.FileBrowser({
	        commands: commands, keymap: keymap,
	        manager: documentManager,
	        model: fbModel
	    });
	    // Let the application restorer track the file browser for restoration of
	    // application state (e.g. setting the file browser as the current side bar
	    // widget).
	    restorer.add(fbWidget, NAMESPACE);
	    var category = 'File Operations';
	    var creatorCmds = Object.create(null);
	    var addCreator = function (name) {
	        var disposables = creatorCmds[name] = new disposable_1.DisposableSet();
	        var command = Private.commandForName(name);
	        disposables.add(commands.addCommand(command, {
	            execute: function () { return fbWidget.createFrom(name); },
	            label: "New " + name
	        }));
	        disposables.add(palette.addItem({ command: command, category: category }));
	    };
	    // Restore the state of the file browser on reload.
	    var key = NAMESPACE + ":cwd";
	    var connect = function () {
	        // Save the subsequent state of the file browser in the state database.
	        fbModel.pathChanged.connect(function (sender, args) {
	            state.save(key, { path: args.newValue });
	        });
	    };
	    Promise.all([state.fetch(key), app.started, manager.ready]).then(function (_a) {
	        var cwd = _a[0];
	        if (!cwd) {
	            return;
	        }
	        var path = cwd['path'];
	        return manager.contents.get(path)
	            .then(function () { return fbModel.cd(path); })
	            .catch(function () { return state.remove(key); });
	    }).then(connect)
	        .catch(function () { return state.remove(key).then(connect); });
	    iteration_1.each(registry.creators(), function (creator) { addCreator(creator.name); });
	    // Add a context menu to the dir listing.
	    var node = fbWidget.node.getElementsByClassName('jp-DirListing-content')[0];
	    node.addEventListener('contextmenu', function (event) {
	        event.preventDefault();
	        var path = fbWidget.pathForClick(event) || '';
	        var ext = docregistry_1.DocumentRegistry.extname(path);
	        var factories = registry.preferredWidgetFactories(ext);
	        var widgetNames = iteration_1.toArray(iteration_1.map(factories, function (factory) { return factory.name; }));
	        var prefix = "file-browser-contextmenu-" + ++Private.id;
	        var openWith = null;
	        if (path && widgetNames.length > 1) {
	            var disposables_1 = new disposable_1.DisposableSet();
	            var command = void 0;
	            openWith = new menu_1.Menu({ commands: commands, keymap: keymap });
	            openWith.title.label = 'Open With...';
	            openWith.disposed.connect(function () { disposables_1.dispose(); });
	            var _loop_1 = function(widgetName) {
	                command = prefix + ":" + widgetName;
	                disposables_1.add(commands.addCommand(command, {
	                    execute: function () { return fbWidget.openPath(path, widgetName); },
	                    label: widgetName
	                }));
	                openWith.addItem({ command: command });
	            };
	            for (var _i = 0, widgetNames_1 = widgetNames; _i < widgetNames_1.length; _i++) {
	                var widgetName = widgetNames_1[_i];
	                _loop_1(widgetName);
	            }
	        }
	        var menu = createContextMenu(fbWidget, openWith);
	        menu.open(event.clientX, event.clientY);
	    });
	    addCommands(app, fbWidget, documentManager);
	    [
	        _1.CommandIDs.save,
	        _1.CommandIDs.restoreCheckpoint,
	        _1.CommandIDs.saveAs,
	        _1.CommandIDs.close,
	        _1.CommandIDs.closeAllFiles
	    ].forEach(function (command) { palette.addItem({ command: command, category: category }); });
	    var menu = createMenu(app, Object.keys(creatorCmds));
	    mainMenu.addMenu(menu, { rank: 1 });
	    fbWidget.title.label = 'Files';
	    fbWidget.id = 'file-browser';
	    app.shell.addToLeftArea(fbWidget, { rank: 40 });
	    // If the layout is a fresh session without saved data, open file browser.
	    app.restored.then(function (layout) {
	        if (layout.fresh) {
	            app.commands.execute(_1.CommandIDs.showBrowser, void 0);
	        }
	    });
	    // Handle fileCreator items as they are added.
	    registry.changed.connect(function (sender, args) {
	        if (args.type === 'fileCreator') {
	            menu.dispose();
	            var name_1 = args.name;
	            if (args.change === 'added') {
	                addCreator(name_1);
	            }
	            else {
	                creatorCmds[name_1].dispose();
	                delete creatorCmds[name_1];
	            }
	            menu = createMenu(app, Object.keys(creatorCmds));
	            mainMenu.addMenu(menu, { rank: 1 });
	        }
	    });
	    return fbModel;
	}
	/**
	 * Add the filebrowser commands to the application's command registry.
	 */
	function addCommands(app, fbWidget, docManager) {
	    var commands = app.commands;
	    var isEnabled = function () {
	        var currentWidget = app.shell.currentWidget;
	        return !!(currentWidget && docManager.contextForWidget(currentWidget));
	    };
	    commands.addCommand(_1.CommandIDs.save, {
	        label: 'Save',
	        caption: 'Save and create checkpoint',
	        isEnabled: isEnabled,
	        execute: function () {
	            if (isEnabled()) {
	                var context_1 = docManager.contextForWidget(app.shell.currentWidget);
	                return context_1.save().then(function () { return context_1.createCheckpoint(); });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.restoreCheckpoint, {
	        label: 'Revert to Checkpoint',
	        caption: 'Revert contents to previous checkpoint',
	        isEnabled: isEnabled,
	        execute: function () {
	            if (isEnabled()) {
	                var context_2 = docManager.contextForWidget(app.shell.currentWidget);
	                return context_2.restoreCheckpoint().then(function () { return context_2.revert(); });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.saveAs, {
	        label: 'Save As...',
	        caption: 'Save with new path and create checkpoint',
	        isEnabled: isEnabled,
	        execute: function () {
	            if (isEnabled()) {
	                var context_3 = docManager.contextForWidget(app.shell.currentWidget);
	                return context_3.saveAs().then(function () {
	                    return context_3.createCheckpoint();
	                });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.open, {
	        execute: function (args) {
	            var path = args['path'];
	            var factory = args['factory'] || void 0;
	            return docManager.services.contents.get(path)
	                .then(function () { return fbWidget.openPath(path, factory); });
	        }
	    });
	    commands.addCommand(_1.CommandIDs.close, {
	        label: 'Close',
	        execute: function () {
	            if (app.shell.currentWidget) {
	                app.shell.currentWidget.close();
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.closeAllFiles, {
	        label: 'Close All',
	        execute: function () { app.shell.closeAll(); }
	    });
	    commands.addCommand(_1.CommandIDs.showBrowser, {
	        execute: function () { app.shell.activateLeft(fbWidget.id); }
	    });
	    commands.addCommand(_1.CommandIDs.hideBrowser, {
	        execute: function () {
	            if (!fbWidget.isHidden) {
	                app.shell.collapseLeft();
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.toggleBrowser, {
	        execute: function () {
	            if (fbWidget.isHidden) {
	                return commands.execute(_1.CommandIDs.showBrowser, void 0);
	            }
	            else {
	                return commands.execute(_1.CommandIDs.hideBrowser, void 0);
	            }
	        }
	    });
	}
	/**
	 * Create a top level menu for the file browser.
	 */
	function createMenu(app, creatorCmds) {
	    var commands = app.commands, keymap = app.keymap;
	    var menu = new menu_1.Menu({ commands: commands, keymap: keymap });
	    menu.title.label = 'File';
	    creatorCmds.forEach(function (name) {
	        menu.addItem({ command: Private.commandForName(name) });
	    });
	    [
	        _1.CommandIDs.save,
	        _1.CommandIDs.restoreCheckpoint,
	        _1.CommandIDs.saveAs,
	        _1.CommandIDs.close,
	        _1.CommandIDs.closeAllFiles
	    ].forEach(function (command) { menu.addItem({ command: command }); });
	    return menu;
	}
	/**
	 * Create a context menu for the file browser listing.
	 *
	 * #### Notes
	 * This function generates temporary commands with an incremented name. These
	 * commands are disposed when the menu itself is disposed.
	 */
	function createContextMenu(fbWidget, openWith) {
	    var commands = fbWidget.commands, keymap = fbWidget.keymap;
	    var menu = new menu_1.Menu({ commands: commands, keymap: keymap });
	    var prefix = "file-browser-" + ++Private.id;
	    var disposables = new disposable_1.DisposableSet();
	    var command;
	    // Remove all the commands associated with this menu upon disposal.
	    menu.disposed.connect(function () { disposables.dispose(); });
	    command = prefix + ":open";
	    disposables.add(commands.addCommand(command, {
	        execute: function () { fbWidget.open(); },
	        icon: 'jp-MaterialIcon jp-OpenFolderIcon',
	        label: 'Open',
	        mnemonic: 0
	    }));
	    menu.addItem({ command: command });
	    if (openWith) {
	        menu.addItem({ type: 'submenu', menu: openWith });
	    }
	    command = prefix + ":rename";
	    disposables.add(commands.addCommand(command, {
	        execute: function () { return fbWidget.rename(); },
	        icon: 'jp-MaterialIcon jp-EditIcon',
	        label: 'Rename',
	        mnemonic: 0
	    }));
	    menu.addItem({ command: command });
	    command = prefix + ":delete";
	    disposables.add(commands.addCommand(command, {
	        execute: function () { return fbWidget.delete(); },
	        icon: 'jp-MaterialIcon jp-CloseIcon',
	        label: 'Delete',
	        mnemonic: 0
	    }));
	    menu.addItem({ command: command });
	    command = prefix + ":duplicate";
	    disposables.add(commands.addCommand(command, {
	        execute: function () { return fbWidget.duplicate(); },
	        icon: 'jp-MaterialIcon jp-CopyIcon',
	        label: 'Duplicate'
	    }));
	    menu.addItem({ command: command });
	    command = prefix + ":cut";
	    disposables.add(commands.addCommand(command, {
	        execute: function () { fbWidget.cut(); },
	        icon: 'jp-MaterialIcon jp-CutIcon',
	        label: 'Cut'
	    }));
	    menu.addItem({ command: command });
	    command = prefix + ":copy";
	    disposables.add(commands.addCommand(command, {
	        execute: function () { fbWidget.copy(); },
	        icon: 'jp-MaterialIcon jp-CopyIcon',
	        label: 'Copy',
	        mnemonic: 0
	    }));
	    menu.addItem({ command: command });
	    command = prefix + ":paste";
	    disposables.add(commands.addCommand(command, {
	        execute: function () { return fbWidget.paste(); },
	        icon: 'jp-MaterialIcon jp-PasteIcon',
	        label: 'Paste',
	        mnemonic: 0
	    }));
	    menu.addItem({ command: command });
	    command = prefix + ":download";
	    disposables.add(commands.addCommand(command, {
	        execute: function () { fbWidget.download(); },
	        icon: 'jp-MaterialIcon jp-DownloadIcon',
	        label: 'Download'
	    }));
	    menu.addItem({ command: command });
	    command = prefix + ":shutdown";
	    disposables.add(commands.addCommand(command, {
	        execute: function () { return fbWidget.shutdownKernels(); },
	        icon: 'jp-MaterialIcon jp-StopIcon',
	        label: 'Shutdown Kernel'
	    }));
	    menu.addItem({ command: command });
	    menu.disposed.connect(function () { disposables.dispose(); });
	    return menu;
	}
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * The ID counter prefix for new commands.
	     *
	     * #### Notes
	     * Even though the commands are disposed when the menus are disposed,
	     * in order to guarantee there are no race conditions, each set of commands
	     * is prefixed.
	     */
	    Private.id = 0;
	    /**
	     * Get the command for a name.
	     */
	    function commandForName(name) {
	        name = name.split(' ').join('-').toLocaleLowerCase();
	        return "file-operations:new-" + name;
	    }
	    Private.commandForName = commandForName;
	})(Private || (Private = {}));
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/filebrowser/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/statedb/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/statedb/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/statedb/statedb.js'));
	/**
	 * The command IDs used by the state database plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.clear = 'statedb:clear';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	/* tslint:disable */
	/**
	 * The default state database token.
	 */
	exports.IStateDB = new token_1.Token('jupyter.services.statedb');
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/statedb/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/statedb/statedb.js **/
jupyter.define('jupyterlab@0.15.1/lib/statedb/statedb.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * The default concrete implementation of a state database.
	 */
	var StateDB = (function () {
	    /**
	     * Create a new state database.
	     *
	     * @param options - The instantiation options for a state database.
	     */
	    function StateDB(options) {
	        /**
	         * The maximum allowed length of the data after it has been serialized.
	         */
	        this.maxLength = 2000;
	        this.namespace = options.namespace;
	    }
	    /**
	     * Clear the entire database.
	     */
	    StateDB.prototype.clear = function () {
	        var prefix = this.namespace + ":";
	        var i = window.localStorage.length;
	        while (i) {
	            var key = window.localStorage.key(--i);
	            if (key.indexOf(prefix) === 0) {
	                window.localStorage.removeItem(key);
	            }
	        }
	        return Promise.resolve(void 0);
	    };
	    /**
	     * Retrieve a saved bundle from the database.
	     *
	     * @param id - The identifier used to retrieve a data bundle.
	     *
	     * @returns A promise that bears a data payload if available.
	     *
	     * #### Notes
	     * The `id` values of stored items in the state database are formatted:
	     * `'namespace:identifier'`, which is the same convention that command
	     * identifiers in JupyterLab use as well. While this is not a technical
	     * requirement for `fetch()`, `remove()`, and `save()`, it *is* necessary for
	     * using the `fetchNamespace()` method.
	     *
	     * The promise returned by this method may be rejected if an error occurs in
	     * retrieving the data. Non-existence of an `id` will succeed, however.
	     */
	    StateDB.prototype.fetch = function (id) {
	        var key = this.namespace + ":" + id;
	        try {
	            return Promise.resolve(JSON.parse(window.localStorage.getItem(key)));
	        }
	        catch (error) {
	            return Promise.reject(error);
	        }
	    };
	    /**
	     * Retrieve all the saved bundles for a namespace.
	     *
	     * @param namespace - The namespace to retrieve.
	     *
	     * @returns A promise that bears a collection data payloads for a namespace.
	     *
	     * #### Notes
	     * Namespaces are entirely conventional entities. The `id` values of stored
	     * items in the state database are formatted: `'namespace:identifier'`, which
	     * is the same convention that command identifiers in JupyterLab use as well.
	     *
	     * If there are any errors in retrieving the data, they will be logged to the
	     * console in order to optimistically return any extant data without failing.
	     * This promise will always succeed.
	     */
	    StateDB.prototype.fetchNamespace = function (namespace) {
	        var prefix = this.namespace + ":" + namespace + ":";
	        var regex = new RegExp("^" + this.namespace + ":");
	        var items = [];
	        var i = window.localStorage.length;
	        while (i) {
	            var key = window.localStorage.key(--i);
	            if (key.indexOf(prefix) === 0) {
	                try {
	                    items.push({
	                        id: key.replace(regex, ''),
	                        value: JSON.parse(window.localStorage.getItem(key))
	                    });
	                }
	                catch (error) {
	                    console.warn(error);
	                    window.localStorage.removeItem(key);
	                }
	            }
	        }
	        return Promise.resolve(items);
	    };
	    /**
	     * Remove a value from the database.
	     *
	     * @param id - The identifier for the data being removed.
	     *
	     * @returns A promise that is rejected if remove fails and succeeds otherwise.
	     */
	    StateDB.prototype.remove = function (id) {
	        window.localStorage.removeItem(this.namespace + ":" + id);
	        return Promise.resolve(void 0);
	    };
	    /**
	     * Save a value in the database.
	     *
	     * @param id - The identifier for the data being saved.
	     *
	     * @param value - The data being saved.
	     *
	     * @returns A promise that is rejected if saving fails and succeeds otherwise.
	     *
	     * #### Notes
	     * The `id` values of stored items in the state database are formatted:
	     * `'namespace:identifier'`, which is the same convention that command
	     * identifiers in JupyterLab use as well. While this is not a technical
	     * requirement for `fetch()`, `remove()`, and `save()`, it *is* necessary for
	     * using the `fetchNamespace()` method.
	     */
	    StateDB.prototype.save = function (id, value) {
	        try {
	            var key = this.namespace + ":" + id;
	            var serialized = JSON.stringify(value);
	            var length_1 = serialized.length;
	            var max = this.maxLength;
	            if (length_1 > max) {
	                throw new Error("Data length (" + length_1 + ") exceeds maximum (" + max + ")");
	            }
	            window.localStorage.setItem(key, serialized);
	            return Promise.resolve(void 0);
	        }
	        catch (error) {
	            return Promise.reject(error);
	        }
	    };
	    return StateDB;
	}());
	exports.StateDB = StateDB;
	//# sourceMappingURL=statedb.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/statedb/statedb.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/help/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/help/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var menu_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/menu.js');
	var about_1 = __jupyter_require__('jupyterlab@0.15.1/lib/about/index.js');
	var iframe_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/iframe.js');
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var faq_1 = __jupyter_require__('jupyterlab@0.15.1/lib/faq/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var mainmenu_1 = __jupyter_require__('jupyterlab@0.15.1/lib/mainmenu/index.js');
	var statedb_1 = __jupyter_require__('jupyterlab@0.15.1/lib/statedb/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/help/index.js');
	/**
	 * A flag denoting whether the application is loaded over HTTPS.
	 */
	var LAB_IS_SECURE = window.location.protocol === 'https:';
	/**
	 * The class name added to the help widget.
	 */
	var HELP_CLASS = 'jp-Help';
	/**
	 * A list of help resources.
	 */
	var RESOURCES = [
	    {
	        text: 'Scipy Lecture Notes',
	        url: 'http://www.scipy-lectures.org/'
	    },
	    {
	        text: 'Numpy Reference',
	        url: 'https://docs.scipy.org/doc/numpy/reference/'
	    },
	    {
	        text: 'Scipy Reference',
	        url: 'https://docs.scipy.org/doc/scipy/reference/'
	    },
	    {
	        text: 'Notebook Tutorial',
	        url: 'https://nbviewer.jupyter.org/github/jupyter/notebook/' +
	            'blob/master/docs/source/examples/Notebook/Notebook Basics.ipynb'
	    },
	    {
	        text: 'Python Reference',
	        url: 'https://docs.python.org/3.5/'
	    },
	    {
	        text: 'IPython Reference',
	        url: 'https://ipython.org/documentation.html?v=20160707164940'
	    },
	    {
	        text: 'Matplotlib Reference',
	        url: 'http://matplotlib.org/contents.html?v=20160707164940'
	    },
	    {
	        text: 'SymPy Reference',
	        url: 'http://docs.sympy.org/latest/index.html?v=20160707164940'
	    },
	    {
	        text: 'Pandas Reference',
	        url: 'http://pandas.pydata.org/pandas-docs/stable/?v=20160707164940'
	    },
	    {
	        text: 'Markdown Reference',
	        url: 'https://help.github.com/articles/' +
	            'getting-started-with-writing-and-formatting-on-github/'
	    }
	];
	RESOURCES.sort(function (a, b) {
	    return a.text.localeCompare(b.text);
	});
	/**
	 * The help handler extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.help-handler',
	    requires: [mainmenu_1.IMainMenu, commandpalette_1.ICommandPalette, instancerestorer_1.IInstanceRestorer],
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the help handler extension.
	 *
	 * @param app - The phosphide application object.
	 *
	 * returns A promise that resolves when the extension is activated.
	 */
	function activate(app, mainMenu, palette, restorer) {
	    var iframe = null;
	    var category = 'Help';
	    var namespace = 'help-doc';
	    var command = _1.CommandIDs.open;
	    var menu = createMenu();
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: namespace });
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: command,
	        args: function (widget) { return ({ isHidden: widget.isHidden, url: widget.url }); },
	        name: function (widget) { return namespace; }
	    });
	    /**
	     * Create a new IFrame widget.
	     */
	    function newIFrame(url) {
	        var iframe = new iframe_1.IFrame();
	        iframe.addClass(HELP_CLASS);
	        iframe.title.label = category;
	        iframe.id = "" + namespace;
	        iframe.url = url;
	        return iframe;
	    }
	    /**
	     * Create a menu for the help plugin.
	     */
	    function createMenu() {
	        var commands = app.commands, keymap = app.keymap;
	        var menu = new menu_1.Menu({ commands: commands, keymap: keymap });
	        menu.title.label = category;
	        menu.addItem({ command: about_1.CommandIDs.open });
	        menu.addItem({ command: faq_1.CommandIDs.open });
	        menu.addItem({ command: _1.CommandIDs.launchClassic });
	        menu.addItem({ type: 'separator' });
	        RESOURCES.forEach(function (args) { menu.addItem({ args: args, command: command }); });
	        menu.addItem({ type: 'separator' });
	        menu.addItem({ command: _1.CommandIDs.close });
	        menu.addItem({ command: statedb_1.CommandIDs.clear });
	        return menu;
	    }
	    /**
	     * Show the help widget.
	     */
	    function showHelp() {
	        if (!iframe) {
	            return;
	        }
	        app.shell.activateRight(iframe.id);
	    }
	    /**
	     * Hide the help widget.
	     */
	    function hideHelp() {
	        if (iframe && !iframe.isHidden) {
	            app.shell.collapseRight();
	        }
	    }
	    app.commands.addCommand(command, {
	        label: function (args) { return args['text']; },
	        execute: function (args) {
	            var url = args['url'];
	            var isHidden = args['isHidden'] || false;
	            // If help resource will generate a mixed content error, load externally.
	            if (LAB_IS_SECURE && services_1.utils.urlParse(url).protocol !== 'https:') {
	                window.open(url);
	                return;
	            }
	            if (iframe) {
	                iframe.url = url;
	            }
	            else {
	                iframe = newIFrame(url);
	                tracker.add(iframe);
	            }
	            tracker.save(iframe);
	            if (!iframe.isAttached) {
	                app.shell.addToRightArea(iframe);
	            }
	            if (isHidden) {
	                hideHelp();
	            }
	            else {
	                showHelp();
	            }
	        }
	    });
	    app.commands.addCommand(_1.CommandIDs.close, {
	        label: 'Close Help',
	        execute: function () {
	            if (iframe) {
	                iframe.dispose();
	                iframe = null;
	            }
	        }
	    });
	    app.commands.addCommand(_1.CommandIDs.toggle, {
	        execute: function () {
	            if (!iframe) {
	                return;
	            }
	            if (iframe.isHidden) {
	                showHelp();
	            }
	            else {
	                hideHelp();
	            }
	        }
	    });
	    app.commands.addCommand(_1.CommandIDs.launchClassic, {
	        label: 'Launch Classic Notebook',
	        execute: function () { window.open(services_1.utils.getBaseUrl() + 'tree'); }
	    });
	    app.commands.addCommand(_1.CommandIDs.show, { execute: showHelp });
	    app.commands.addCommand(_1.CommandIDs.hide, { execute: hideHelp });
	    RESOURCES.forEach(function (args) { palette.addItem({ args: args, command: command, category: category }); });
	    palette.addItem({ command: _1.CommandIDs.close, category: category });
	    palette.addItem({ command: statedb_1.CommandIDs.clear, category: category });
	    palette.addItem({ command: _1.CommandIDs.launchClassic, category: category });
	    mainMenu.addMenu(menu, {});
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/help/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/iframe.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/iframe.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	/**
	 * The class name added to an IFrame widget.
	 */
	var IFRAME_CLASS = 'jp-IFrame';
	/**
	 * A phosphor widget which wraps an IFrame.
	 */
	var IFrame = (function (_super) {
	    __extends(IFrame, _super);
	    /**
	     * Create a new IFrame widget.
	     */
	    function IFrame() {
	        _super.call(this, { node: Private.createNode() });
	        this.addClass(IFRAME_CLASS);
	    }
	    Object.defineProperty(IFrame.prototype, "url", {
	        /**
	         * The IFrame's URL.
	         */
	        get: function () {
	            return this.node.querySelector('iframe').getAttribute('src');
	        },
	        set: function (url) {
	            this.node.querySelector('iframe').setAttribute('src', url);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return IFrame;
	}(widget_1.Widget));
	exports.IFrame = IFrame;
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create the main content node of an iframe widget.
	     */
	    function createNode() {
	        var node = document.createElement('div');
	        var iframe = document.createElement('iframe');
	        iframe.style.height = '100%';
	        iframe.style.width = '100%';
	        node.appendChild(iframe);
	        return node;
	    }
	    Private.createNode = createNode;
	})(Private || (Private = {}));
	//# sourceMappingURL=iframe.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/iframe.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/help/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/help/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * The command IDs used by the help plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.open = 'help-jupyterlab:open';
	    CommandIDs.activate = 'help-jupyterlab:activate';
	    CommandIDs.close = 'help-jupyterlab:close';
	    CommandIDs.show = 'help-jupyterlab:show';
	    CommandIDs.hide = 'help-jupyterlab:hide';
	    CommandIDs.toggle = 'help-jupyterlab:toggle';
	    CommandIDs.launchClassic = 'classic-notebook:launchClassic';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/help/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/imagewidget/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/imagewidget/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/imagewidget/index.js');
	/**
	 * The list of file extensions for images.
	 */
	var EXTENSIONS = ['.png', '.gif', '.jpeg', '.jpg', '.svg', '.bmp', '.ico',
	    '.xbm', '.tiff', '.tif'];
	/**
	 * The name of the factory that creates image widgets.
	 */
	var FACTORY = 'Image';
	/**
	 * The image file handler extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.image-handler',
	    requires: [docregistry_1.IDocumentRegistry, commandpalette_1.ICommandPalette, instancerestorer_1.IInstanceRestorer],
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the image widget extension.
	 */
	function activate(app, registry, palette, restorer) {
	    var namespace = 'image-widget';
	    var factory = new _1.ImageWidgetFactory({
	        name: FACTORY,
	        modelName: 'base64',
	        fileExtensions: EXTENSIONS,
	        defaultFor: EXTENSIONS
	    });
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: namespace });
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: filebrowser_1.CommandIDs.open,
	        args: function (widget) { return ({ path: widget.context.path, factory: FACTORY }); },
	        name: function (widget) { return widget.context.path; }
	    });
	    registry.addWidgetFactory(factory);
	    factory.widgetCreated.connect(function (sender, widget) {
	        // Notify the instance tracker if restore data needs to update.
	        widget.context.pathChanged.connect(function () { tracker.save(widget); });
	        tracker.add(widget);
	    });
	    app.commands.addCommand(_1.CommandIDs.zoomIn, {
	        execute: zoomIn,
	        label: 'Zoom In'
	    });
	    app.commands.addCommand(_1.CommandIDs.zoomOut, {
	        execute: zoomOut,
	        label: 'Zoom Out'
	    });
	    app.commands.addCommand(_1.CommandIDs.resetZoom, {
	        execute: resetZoom,
	        label: 'Reset Zoom'
	    });
	    var category = 'Image Widget';
	    [_1.CommandIDs.zoomIn, _1.CommandIDs.zoomOut, _1.CommandIDs.resetZoom]
	        .forEach(function (command) { return palette.addItem({ command: command, category: category }); });
	    function zoomIn() {
	        var widget = tracker.currentWidget;
	        if (!widget) {
	            return;
	        }
	        if (widget.scale > 1) {
	            widget.scale += .5;
	        }
	        else {
	            widget.scale *= 2;
	        }
	    }
	    function zoomOut() {
	        var widget = tracker.currentWidget;
	        if (!widget) {
	            return;
	        }
	        if (widget.scale > 1) {
	            widget.scale -= .5;
	        }
	        else {
	            widget.scale /= 2;
	        }
	    }
	    function resetZoom() {
	        var widget = tracker.currentWidget;
	        if (!widget) {
	            return;
	        }
	        widget.scale = 1;
	    }
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/imagewidget/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/imagewidget/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/imagewidget/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/imagewidget/widget.js'));
	/**
	 * The command IDs used by the image widget plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.zoomIn = 'imagewidget:zoom-in';
	    CommandIDs.zoomOut = 'imagewidget:zoom-out';
	    CommandIDs.resetZoom = 'imagewidget:reset-zoom';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/imagewidget/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/imagewidget/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/imagewidget/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	/**
	 * The class name added to a imagewidget.
	 */
	var IMAGE_CLASS = 'jp-ImageWidget';
	/**
	 * A widget for images.
	 */
	var ImageWidget = (function (_super) {
	    __extends(ImageWidget, _super);
	    /**
	     * Construct a new image widget.
	     */
	    function ImageWidget(context) {
	        var _this = this;
	        _super.call(this, { node: Private.createNode() });
	        this._scale = 1;
	        this._context = context;
	        this.node.tabIndex = -1;
	        this.addClass(IMAGE_CLASS);
	        this._onTitleChanged();
	        context.pathChanged.connect(this._onTitleChanged, this);
	        context.ready.then(function () {
	            _this.update();
	            context.model.contentChanged.connect(_this.update, _this);
	            context.fileChanged.connect(_this.update, _this);
	        });
	    }
	    Object.defineProperty(ImageWidget.prototype, "context", {
	        /**
	         * The image widget's context.
	         */
	        get: function () {
	            return this._context;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ImageWidget.prototype, "scale", {
	        /**
	         * The scale factor for the image.
	         */
	        get: function () {
	            return this._scale;
	        },
	        set: function (value) {
	            if (value === this._scale) {
	                return;
	            }
	            this._scale = value;
	            var scaleNode = this.node.querySelector('div');
	            var transform;
	            transform = "scale(" + value + ")";
	            scaleNode.style.transform = transform;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the widget.
	     */
	    ImageWidget.prototype.dispose = function () {
	        this._context = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle `update-request` messages for the widget.
	     */
	    ImageWidget.prototype.onUpdateRequest = function (msg) {
	        var context = this._context;
	        if (this.isDisposed || !context.isReady) {
	            return;
	        }
	        var cm = context.contentsModel;
	        var content = context.model.toString();
	        var src = "data:" + cm.mimetype + ";" + cm.format + "," + content;
	        this.node.querySelector('img').setAttribute('src', src);
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    ImageWidget.prototype.onActivateRequest = function (msg) {
	        this.node.focus();
	    };
	    /**
	     * Handle a change to the title.
	     */
	    ImageWidget.prototype._onTitleChanged = function () {
	        this.title.label = this._context.path.split('/').pop();
	    };
	    return ImageWidget;
	}(widget_1.Widget));
	exports.ImageWidget = ImageWidget;
	/**
	 * A widget factory for images.
	 */
	var ImageWidgetFactory = (function (_super) {
	    __extends(ImageWidgetFactory, _super);
	    function ImageWidgetFactory() {
	        _super.apply(this, arguments);
	    }
	    /**
	     * Create a new widget given a context.
	     */
	    ImageWidgetFactory.prototype.createNewWidget = function (context) {
	        return new ImageWidget(context);
	    };
	    return ImageWidgetFactory;
	}(docregistry_1.ABCWidgetFactory));
	exports.ImageWidgetFactory = ImageWidgetFactory;
	/**
	 * A namespace for image widget private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create the node for the image widget.
	     */
	    function createNode() {
	        var node = document.createElement('div');
	        var innerNode = document.createElement('div');
	        var image = document.createElement('img');
	        node.appendChild(innerNode);
	        innerNode.appendChild(image);
	        return node;
	    }
	    Private.createNode = createNode;
	})(Private || (Private = {}));
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/imagewidget/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/inspector/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/inspector/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/inspector/index.js');
	/**
	 * A service providing an inspector panel.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.services.inspector',
	    requires: [commandpalette_1.ICommandPalette, instancerestorer_1.IInstanceRestorer],
	    provides: _1.IInspector
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * A class that manages inspector widget instances and offers persistent
	 * `IInspector` instance that other plugins can communicate with.
	 */
	var InspectorManager = (function () {
	    function InspectorManager() {
	        this._inspector = null;
	        this._source = null;
	    }
	    Object.defineProperty(InspectorManager.prototype, "inspector", {
	        /**
	         * The current inspector widget.
	         */
	        get: function () {
	            return this._inspector;
	        },
	        set: function (inspector) {
	            if (this._inspector === inspector) {
	                return;
	            }
	            this._inspector = inspector;
	            // If an inspector was added and it has no source
	            if (inspector && !inspector.source) {
	                inspector.source = this._source;
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(InspectorManager.prototype, "source", {
	        /**
	         * The source of events the inspector panel listens for.
	         */
	        get: function () {
	            return this._source;
	        },
	        set: function (source) {
	            if (this._source !== source) {
	                if (this._source) {
	                    this._source.disposed.disconnect(this._onSourceDisposed, this);
	                }
	                this._source = source;
	                this._source.disposed.connect(this._onSourceDisposed, this);
	            }
	            if (this._inspector && !this._inspector.isDisposed) {
	                this._inspector.source = this._source;
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Handle the source disposed signal.
	     */
	    InspectorManager.prototype._onSourceDisposed = function () {
	        this._source = null;
	    };
	    return InspectorManager;
	}());
	/**
	 * Activate the console extension.
	 */
	function activate(app, palette, restorer) {
	    var category = 'Inspector';
	    var command = _1.CommandIDs.open;
	    var label = 'Open Inspector';
	    var manager = new InspectorManager();
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: 'inspector' });
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: command,
	        args: function () { return null; },
	        name: function () { return 'inspector'; }
	    });
	    function newInspector() {
	        var inspector = new _1.Inspector({ items: Private.defaultInspectorItems });
	        inspector.id = 'jp-inspector';
	        inspector.title.label = 'Inspector';
	        inspector.title.closable = true;
	        inspector.disposed.connect(function () {
	            if (manager.inspector === inspector) {
	                manager.inspector = null;
	            }
	        });
	        tracker.add(inspector);
	        return inspector;
	    }
	    function openInspector() {
	        if (!manager.inspector || manager.inspector.isDisposed) {
	            manager.inspector = newInspector();
	            app.shell.addToMainArea(manager.inspector);
	        }
	        if (manager.inspector.isAttached) {
	            app.shell.activateMain(manager.inspector.id);
	        }
	    }
	    app.commands.addCommand(command, { execute: openInspector, label: label });
	    palette.addItem({ command: command, category: category });
	    return manager;
	}
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * The default set of inspector items added to the inspector panel.
	     */
	    Private.defaultInspectorItems = [
	        {
	            className: 'jp-HintsInspectorItem',
	            name: 'Hints',
	            rank: 20,
	            type: 'hints'
	        }
	    ];
	})(Private || (Private = {}));
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/inspector/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/landing/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/landing/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var services_1 = __jupyter_require__('jupyterlab@0.15.1/lib/services/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/landing/index.js');
	/**
	 * The class name added to the landing plugin.
	 */
	var LANDING_CLASS = 'jp-Landing';
	/**
	 * The landing page extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.landing',
	    requires: [filebrowser_1.IPathTracker, commandpalette_1.ICommandPalette, services_1.IServiceManager, instancerestorer_1.IInstanceRestorer],
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the landing plugin.
	 */
	function activate(app, pathTracker, palette, services, restorer) {
	    var category = 'Help';
	    var command = _1.CommandIDs.open;
	    var model = new _1.LandingModel(services.terminals.isAvailable());
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: 'landing' });
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: command,
	        args: function () { return null; },
	        name: function () { return 'landing'; }
	    });
	    var widget;
	    function newWidget() {
	        var widget = new _1.LandingWidget(app);
	        widget.model = model;
	        widget.id = 'landing-jupyterlab';
	        widget.title.label = 'Landing';
	        widget.title.closable = true;
	        widget.addClass(LANDING_CLASS);
	        tracker.add(widget);
	        return widget;
	    }
	    app.commands.addCommand(command, {
	        label: 'Open Landing',
	        execute: function () {
	            if (!widget || widget.isDisposed) {
	                widget = newWidget();
	                app.shell.addToMainArea(widget);
	            }
	            app.shell.activateMain(widget.id);
	        }
	    });
	    pathTracker.pathChanged.connect(function () {
	        if (pathTracker.path.length) {
	            model.path = 'home > ' + pathTracker.path.replace('/', ' > ');
	        }
	        else {
	            model.path = 'home';
	        }
	    });
	    palette.addItem({ category: category, command: command });
	    // Only create a landing page if there are no other tabs open.
	    app.restored.then(function () {
	        if (app.shell.mainAreaIsEmpty) {
	            app.commands.execute(command, void 0);
	        }
	    });
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/landing/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/landing/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/landing/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/landing/widget.js'));
	/**
	 * The command IDs used by the landing plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.open = 'landing-jupyterlab:open';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/landing/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/landing/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/landing/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var vdom_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/vdom.js');
	var about_1 = __jupyter_require__('jupyterlab@0.15.1/lib/about/index.js');
	var vdom_2 = __jupyter_require__('jupyterlab@0.15.1/lib/common/vdom.js');
	var console_1 = __jupyter_require__('jupyterlab@0.15.1/lib/console/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var terminal_1 = __jupyter_require__('jupyterlab@0.15.1/lib/terminal/index.js');
	/**
	 * The class name added to the landing scroll wrapper.
	 */
	var LANDING_WRAPPER_CLASS = 'jp-Landing-wrapper';
	/**
	 * The class name added to the dialog.
	 */
	var LANDING_DIALOG_CLASS = 'jp-Landing-dialog';
	/**
	 * The class name for the JupyterLab icon from default-theme.
	 */
	var JUPYTERLAB_ICON_CLASS = 'jp-ImageJupyterLab';
	/**
	 * The class name added to specify size of the JupyterLab logo.
	 */
	var LANDING_LOGO_CLASS = 'jp-Landing-logo';
	/**
	 * The class name added to the preview message subtitle.
	 */
	var LANDING_SUBTITLE_CLASS = 'jp-Landing-subtitle';
	/**
	 * The class name added for the tour icon from default-theme.
	 */
	var TOUR_ICON_CLASS = 'jp-Landing-tour';
	/**
	 * The class name added to the header text.
	 */
	var LANDING_HEADER_CLASS = 'jp-Landing-header';
	/**
	 * The class name added to the dialog body.
	 */
	var LANDING_BODY_CLASS = 'jp-Landing-body';
	/**
	 * The class name added to the column of the dialog.
	 */
	var LANDING_COLUMN_CLASS = 'jp-Landing-column';
	/**
	 * The class name added to specify size of activity icons.
	 */
	var LANDING_ICON_CLASS = 'jp-Landing-image';
	/**
	 * The class name added to the image text of an activity.
	 */
	var LANDING_TEXT_CLASS = 'jp-Landing-text';
	/**
	 * The class name added to the current working directory.
	 */
	var LANDING_CWD_CLASS = 'jp-Landing-cwd';
	/**
	 * The class name added to Landing folder node.
	 */
	var FOLDER_CLASS = 'jp-Landing-folder';
	/**
	 * The class name added for the folder icon from default-theme.
	 */
	var FOLDER_ICON_CLASS = 'jp-FolderIcon';
	/**
	 * The class name added to the current working directory path.
	 */
	var LANDING_PATH_CLASS = 'jp-Landing-path';
	/**
	 * The list of preview messages.
	 */
	var previewMessages = [
	    'super alpha preview',
	    'very alpha preview',
	    'extremely alpha preview',
	    'exceedingly alpha preview',
	    'alpha alpha preview'
	];
	/**
	 * LandingModel keeps track of the path to working directory and has text data,
	 * which the LandingWidget will render.
	 */
	var LandingModel = (function (_super) {
	    __extends(LandingModel, _super);
	    /**
	     * Construct a new landing model.
	     */
	    function LandingModel(terminalsAvailable) {
	        if (terminalsAvailable === void 0) { terminalsAvailable = false; }
	        _super.call(this);
	        this.previewMessage = previewMessages[Math.floor(Math.random() * previewMessages.length)];
	        this.headerText = 'Start a new activity';
	        this.activities =
	            [['Notebook', filebrowser_1.CommandIDs.newNotebook],
	                ['Code Console', console_1.CommandIDs.create],
	                ['Text Editor', filebrowser_1.CommandIDs.newTextFile]];
	        if (terminalsAvailable) {
	            this.activities.push(['Terminal', terminal_1.CommandIDs.createNew]);
	        }
	        this._path = 'home';
	    }
	    Object.defineProperty(LandingModel.prototype, "path", {
	        /**
	         * Get the path of the current working directory.
	         */
	        get: function () {
	            return this._path;
	        },
	        /**
	         * Set the path of the current working directory.
	         */
	        set: function (value) {
	            this._path = value;
	            this.stateChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    return LandingModel;
	}(vdom_2.VDomModel));
	exports.LandingModel = LandingModel;
	/**
	 * A virtual-DOM-based widget for the Landing plugin.
	 */
	var LandingWidget = (function (_super) {
	    __extends(LandingWidget, _super);
	    /**
	     * Construct a new landing widget.
	     */
	    function LandingWidget(app) {
	        _super.call(this);
	        this._app = app;
	    }
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    LandingWidget.prototype.onActivateRequest = function (msg) {
	        this.node.tabIndex = -1;
	        this.node.focus();
	    };
	    /**
	     * Handle `'close-request'` messages.
	     */
	    LandingWidget.prototype.onCloseRequest = function (msg) {
	        _super.prototype.onCloseRequest.call(this, msg);
	        this.dispose();
	    };
	    /**
	     * Render the landing plugin to virtual DOM nodes.
	     */
	    LandingWidget.prototype.render = function () {
	        var _this = this;
	        var activitiesList = [];
	        var activites = this.model.activities;
	        var _loop_1 = function(activityName) {
	            var imgName = activityName[0].replace(' ', '');
	            var column = vdom_1.h.div({ className: LANDING_COLUMN_CLASS }, vdom_1.h.span({ className: LANDING_ICON_CLASS + (" jp-Image" + imgName),
	                onclick: function () {
	                    _this._app.commands.execute(activityName[1], void 0);
	                } }), vdom_1.h.span({ className: LANDING_TEXT_CLASS }, activityName[0]));
	            activitiesList.push(column);
	        };
	        for (var _i = 0, activites_1 = activites; _i < activites_1.length; _i++) {
	            var activityName = activites_1[_i];
	            _loop_1(activityName);
	        }
	        var logo = vdom_1.h.span({ className: JUPYTERLAB_ICON_CLASS + ' ' + LANDING_LOGO_CLASS });
	        var subtitle = vdom_1.h.span({ className: LANDING_SUBTITLE_CLASS }, this.model.previewMessage);
	        var tour = vdom_1.h.span({ className: TOUR_ICON_CLASS,
	            onclick: function () {
	                _this._app.commands.execute(about_1.CommandIDs.open, void 0);
	            } });
	        var header = vdom_1.h.span({
	            className: LANDING_HEADER_CLASS
	        }, this.model.headerText);
	        var body = vdom_1.h.div({ className: LANDING_BODY_CLASS }, activitiesList);
	        var dialog = vdom_1.h.div({ className: LANDING_DIALOG_CLASS }, logo, subtitle, tour, header, body, vdom_1.h.div({ className: LANDING_CWD_CLASS }, vdom_1.h.span({ className: FOLDER_ICON_CLASS + ' ' + FOLDER_CLASS }), vdom_1.h.span({ className: LANDING_PATH_CLASS }, this.model.path)));
	        return vdom_1.h.div({ className: LANDING_WRAPPER_CLASS }, dialog);
	    };
	    return LandingWidget;
	}(vdom_2.VDomWidget));
	exports.LandingWidget = LandingWidget;
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/landing/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/terminal/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/terminal/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/terminal/widget.js'));
	/**
	 * The command IDs used by the terminal plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.createNew = 'terminal:create-new';
	    CommandIDs.open = 'terminal:open';
	    CommandIDs.increaseFont = 'terminal:increase-font';
	    CommandIDs.decreaseFont = 'terminal:decrease-font';
	    CommandIDs.toggleTheme = 'terminal:toggle-theme';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/terminal/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/terminal/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/terminal/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var messaging_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/messaging.js');
	var sizing_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/sizing.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var Xterm = __jupyter_require__('xterm@~2.0.1/dist/xterm.js');
	/**
	 * The class name added to a terminal widget.
	 */
	var TERMINAL_CLASS = 'jp-TerminalWidget';
	/**
	 * The class name added to a terminal body.
	 */
	var TERMINAL_BODY_CLASS = 'jp-TerminalWidget-body';
	/**
	 * The number of rows to use in the dummy terminal.
	 */
	var DUMMY_ROWS = 24;
	/**
	 * The number of cols to use in the dummy terminal.
	 */
	var DUMMY_COLS = 80;
	/**
	 * A widget which manages a terminal session.
	 */
	var TerminalWidget = (function (_super) {
	    __extends(TerminalWidget, _super);
	    /**
	     * Construct a new terminal widget.
	     *
	     * @param options - The terminal configuration options.
	     */
	    function TerminalWidget(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this);
	        this._term = null;
	        this._sheet = null;
	        this._dummyTerm = null;
	        this._fontSize = -1;
	        this._needsSnap = true;
	        this._needsResize = true;
	        this._needsStyle = true;
	        this._rowHeight = -1;
	        this._colWidth = -1;
	        this._offsetWidth = -1;
	        this._offsetHeight = -1;
	        this._sessionSize = [1, 1, 1, 1];
	        this._background = '';
	        this._color = '';
	        this._box = null;
	        this._session = null;
	        this.addClass(TERMINAL_CLASS);
	        // Create the xterm, dummy terminal, and private style sheet.
	        this._term = new Xterm(Private.getConfig(options));
	        this._initializeTerm();
	        this._dummyTerm = Private.createDummyTerm();
	        this._sheet = document.createElement('style');
	        this.node.appendChild(this._sheet);
	        // Initialize settings.
	        this._fontSize = options.fontSize || 14;
	        this._background = options.background || 'black';
	        this._color = options.color || 'white';
	        this.id = "jp-TerminalWidget-" + Private.id++;
	        this.title.label = 'Terminal';
	    }
	    Object.defineProperty(TerminalWidget.prototype, "session", {
	        /**
	         * The terminal session associated with the widget.
	         */
	        get: function () {
	            return this._session;
	        },
	        set: function (value) {
	            var _this = this;
	            if (this._session && !this._session.isDisposed) {
	                this._session.messageReceived.disconnect(this._onMessage, this);
	            }
	            this._session = value || null;
	            if (!value) {
	                return;
	            }
	            this._session.ready.then(function () {
	                if (_this.isDisposed) {
	                    return;
	                }
	                _this._session.messageReceived.connect(_this._onMessage, _this);
	                _this.title.label = "Terminal " + _this._session.name;
	                _this._setSessionSize();
	            });
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TerminalWidget.prototype, "fontSize", {
	        /**
	         * Get the font size of the terminal in pixels.
	         */
	        get: function () {
	            return this._fontSize;
	        },
	        /**
	         * Set the font size of the terminal in pixels.
	         */
	        set: function (size) {
	            if (this._fontSize === size) {
	                return;
	            }
	            this._fontSize = size;
	            this._needsSnap = true;
	            this.update();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TerminalWidget.prototype, "background", {
	        /**
	         * Get the background color of the terminal.
	         */
	        get: function () {
	            return this._background;
	        },
	        /**
	         * Set the background color of the terminal.
	         */
	        set: function (value) {
	            if (this._background === value) {
	                return;
	            }
	            this._background = value;
	            this._needsStyle = true;
	            this.update();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TerminalWidget.prototype, "color", {
	        /**
	         * Get the text color of the terminal.
	         */
	        get: function () {
	            return this._color;
	        },
	        /**
	         * Set the text color of the terminal.
	         */
	        set: function (value) {
	            if (this._color === value) {
	                return;
	            }
	            this._color = value;
	            this._needsStyle = true;
	            this.update();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the terminal widget.
	     */
	    TerminalWidget.prototype.dispose = function () {
	        this._session = null;
	        this._sheet = null;
	        this._term = null;
	        this._dummyTerm = null;
	        this._box = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Process a message sent to the widget.
	     *
	     * @param msg - The message sent to the widget.
	     *
	     * #### Notes
	     * Subclasses may reimplement this method as needed.
	     */
	    TerminalWidget.prototype.processMessage = function (msg) {
	        _super.prototype.processMessage.call(this, msg);
	        switch (msg.type) {
	            case 'fit-request':
	                this.onFitRequest(msg);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Set the size of the terminal when attached if dirty.
	     */
	    TerminalWidget.prototype.onAfterAttach = function (msg) {
	        this.update();
	    };
	    /**
	     * Set the size of the terminal when shown if dirty.
	     */
	    TerminalWidget.prototype.onAfterShow = function (msg) {
	        this.update();
	    };
	    /**
	     * Dispose of the terminal when closing.
	     */
	    TerminalWidget.prototype.onCloseRequest = function (msg) {
	        _super.prototype.onCloseRequest.call(this, msg);
	        this.dispose();
	    };
	    /**
	     * On resize, use the computed row and column sizes to resize the terminal.
	     */
	    TerminalWidget.prototype.onResize = function (msg) {
	        this._offsetWidth = msg.width;
	        this._offsetHeight = msg.height;
	        this._needsResize = true;
	        this.update();
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    TerminalWidget.prototype.onUpdateRequest = function (msg) {
	        if (!this.isVisible) {
	            return;
	        }
	        if (this._needsSnap) {
	            this._snapTermSizing();
	        }
	        if (this._needsResize) {
	            this._resizeTerminal();
	        }
	        if (this._needsStyle) {
	            this._setStyle();
	        }
	    };
	    /**
	     * A message handler invoked on an `'fit-request'` message.
	     */
	    TerminalWidget.prototype.onFitRequest = function (msg) {
	        var resize = widget_1.ResizeMessage.UnknownSize;
	        messaging_1.sendMessage(this, resize);
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    TerminalWidget.prototype.onActivateRequest = function (msg) {
	        this._term.focus();
	    };
	    /**
	     * Create the terminal object.
	     */
	    TerminalWidget.prototype._initializeTerm = function () {
	        var _this = this;
	        this._term.open(this.node);
	        this._term.element.classList.add(TERMINAL_BODY_CLASS);
	        this._term.on('data', function (data) {
	            if (_this._session) {
	                _this._session.send({
	                    type: 'stdin',
	                    content: [data]
	                });
	            }
	        });
	        this._term.on('title', function (title) {
	            _this.title.label = title;
	        });
	    };
	    /**
	     * Handle a message from the terminal session.
	     */
	    TerminalWidget.prototype._onMessage = function (sender, msg) {
	        switch (msg.type) {
	            case 'stdout':
	                this._term.write(msg.content[0]);
	                break;
	            case 'disconnect':
	                this._term.write('\r\n\r\n[Finished... Term Session]\r\n');
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Use the dummy terminal to measure the row and column sizes.
	     */
	    TerminalWidget.prototype._snapTermSizing = function () {
	        this._term.element.style.fontSize = this.fontSize + "px";
	        var node = this._dummyTerm;
	        this._term.element.appendChild(node);
	        this._rowHeight = node.offsetHeight / DUMMY_ROWS;
	        this._colWidth = node.offsetWidth / DUMMY_COLS;
	        this._term.element.removeChild(node);
	        this._needsSnap = false;
	        this._needsResize = true;
	    };
	    /**
	     * Resize the terminal based on computed geometry.
	     */
	    TerminalWidget.prototype._resizeTerminal = function () {
	        var offsetWidth = this._offsetWidth;
	        var offsetHeight = this._offsetHeight;
	        if (offsetWidth < 0) {
	            offsetWidth = this.node.offsetWidth;
	        }
	        if (offsetHeight < 0) {
	            offsetHeight = this.node.offsetHeight;
	        }
	        var box = this._box || (this._box = sizing_1.boxSizing(this.node));
	        var height = offsetHeight - box.verticalSum;
	        var width = offsetWidth - box.horizontalSum;
	        var rows = Math.floor(height / this._rowHeight) - 1;
	        var cols = Math.floor(width / this._colWidth) - 1;
	        this._term.resize(cols, rows);
	        this._sessionSize = [rows, cols, height, width];
	        this._setSessionSize();
	        this._needsResize = false;
	    };
	    /**
	     * Send the size to the session.
	     */
	    TerminalWidget.prototype._setSessionSize = function () {
	        if (this._session) {
	            this._session.send({
	                type: 'set_size',
	                content: this._sessionSize
	            });
	        }
	    };
	    /**
	     * Set the stylesheet.
	     */
	    TerminalWidget.prototype._setStyle = function () {
	        // Set the fg and bg colors of the terminal and cursor.
	        this._sheet.innerHTML = ("\n      #" + this.node.id + " {\n        background: " + this._background + ";\n        color: " + this._color + ";\n      }\n      #" + this.node.id + " .xterm-viewport, #" + this.node.id + " .xterm-rows {\n        background-color: " + this._background + ";\n        color: " + this._color + ";\n      }\n      #" + this.node.id + " .terminal.focus .terminal-cursor.blinking {\n          animation: " + this.node.id + "-blink-cursor 1.2s infinite step-end;\n      }\n      @keyframes " + this.node.id + "-blink-cursor {\n          0% {\n              background-color: " + this._color + ";\n              color: " + this._background + ";\n          }\n          50% {\n              background-color: transparent;\n              color: " + this._color + ";\n          }\n      }\n    ");
	        this._needsStyle = false;
	    };
	    return TerminalWidget;
	}(widget_1.Widget));
	exports.TerminalWidget = TerminalWidget;
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Get term.js options from ITerminalOptions.
	     */
	    function getConfig(options) {
	        var config = {};
	        if (options.cursorBlink !== void 0) {
	            config.cursorBlink = options.cursorBlink;
	        }
	        else {
	            config.cursorBlink = true;
	        }
	        return config;
	    }
	    Private.getConfig = getConfig;
	    /**
	     * Create a dummy terminal element used to measure text size.
	     */
	    function createDummyTerm() {
	        var node = document.createElement('div');
	        var rowspan = document.createElement('span');
	        rowspan.innerHTML = Array(DUMMY_ROWS).join('a<br>');
	        var colspan = document.createElement('span');
	        colspan.textContent = Array(DUMMY_COLS + 1).join('a');
	        node.appendChild(rowspan);
	        node.appendChild(colspan);
	        node.style.visibility = 'hidden';
	        node.style.position = 'absolute';
	        node.style.height = 'auto';
	        node.style.width = 'auto';
	        node.style['white-space'] = 'nowrap';
	        return node;
	    }
	    Private.createDummyTerm = createDummyTerm;
	    /**
	     * An incrementing counter for ids.
	     */
	    Private.id = 0;
	})(Private || (Private = {}));
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/terminal/widget.js **/


/** START DEFINE BLOCK for xterm@2.0.1/dist/xterm.js **/
jupyter.define('xterm@2.0.1/dist/xterm.js', function (module, exports, __jupyter_require__) {
	(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Terminal = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	/**
	 * xterm.js: xterm, in the browser
	 * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License)
	 */
	
	/**
	 * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend
	 * events, displaying the in-progress composition to the UI and forwarding the final composition
	 * to the handler.
	 * @param {HTMLTextAreaElement} textarea The textarea that xterm uses for input.
	 * @param {HTMLElement} compositionView The element to display the in-progress composition in.
	 * @param {Terminal} terminal The Terminal to forward the finished composition to.
	 */
	function CompositionHelper(textarea, compositionView, terminal) {
	  this.textarea = textarea;
	  this.compositionView = compositionView;
	  this.terminal = terminal;
	
	  // Whether input composition is currently happening, eg. via a mobile keyboard, speech input
	  // or IME. This variable determines whether the compositionText should be displayed on the UI.
	  this.isComposing = false;
	
	  // The input currently being composed, eg. via a mobile keyboard, speech input or IME.
	  this.compositionText = null;
	
	  // The position within the input textarea's value of the current composition.
	  this.compositionPosition = { start: null, end: null };
	
	  // Whether a composition is in the process of being sent, setting this to false will cancel
	  // any in-progress composition.
	  this.isSendingComposition = false;
	}
	
	/**
	 * Handles the compositionstart event, activating the composition view.
	 */
	CompositionHelper.prototype.compositionstart = function () {
	  this.isComposing = true;
	  this.compositionPosition.start = this.textarea.value.length;
	  this.compositionView.textContent = '';
	  this.compositionView.classList.add('active');
	};
	
	/**
	 * Handles the compositionupdate event, updating the composition view.
	 * @param {CompositionEvent} ev The event.
	 */
	CompositionHelper.prototype.compositionupdate = function (ev) {
	  this.compositionView.textContent = ev.data;
	  this.updateCompositionElements();
	  var self = this;
	  setTimeout(function () {
	    self.compositionPosition.end = self.textarea.value.length;
	  }, 0);
	};
	
	/**
	 * Handles the compositionend event, hiding the composition view and sending the composition to
	 * the handler.
	 */
	CompositionHelper.prototype.compositionend = function () {
	  this.finalizeComposition(true);
	};
	
	/**
	 * Handles the keydown event, routing any necessary events to the CompositionHelper functions.
	 * @return Whether the Terminal should continue processing the keydown event.
	 */
	CompositionHelper.prototype.keydown = function (ev) {
	  if (this.isComposing || this.isSendingComposition) {
	    if (ev.keyCode === 229) {
	      // Continue composing if the keyCode is the "composition character"
	      return false;
	    } else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) {
	      // Continue composing if the keyCode is a modifier key
	      return false;
	    } else {
	      // Finish composition immediately. This is mainly here for the case where enter is
	      // pressed and the handler needs to be triggered before the command is executed.
	      this.finalizeComposition(false);
	    }
	  }
	
	  if (ev.keyCode === 229) {
	    // If the "composition character" is used but gets to this point it means a non-composition
	    // character (eg. numbers and punctuation) was pressed when the IME was active.
	    this.handleAnyTextareaChanges();
	    return false;
	  }
	
	  return true;
	};
	
	/**
	 * Finalizes the composition, resuming regular input actions. This is called when a composition
	 * is ending.
	 * @param {boolean} waitForPropogation Whether to wait for events to propogate before sending
	 *   the input. This should be false if a non-composition keystroke is entered before the
	 *   compositionend event is triggered, such as enter, so that the composition is send before
	 *   the command is executed.
	 */
	CompositionHelper.prototype.finalizeComposition = function (waitForPropogation) {
	  this.compositionView.classList.remove('active');
	  this.isComposing = false;
	  this.clearTextareaPosition();
	
	  if (!waitForPropogation) {
	    // Cancel any delayed composition send requests and send the input immediately.
	    this.isSendingComposition = false;
	    var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end);
	    this.terminal.handler(input);
	  } else {
	    // Make a deep copy of the composition position here as a new compositionstart event may
	    // fire before the setTimeout executes.
	    var currentCompositionPosition = {
	      start: this.compositionPosition.start,
	      end: this.compositionPosition.end
	    };
	
	    // Since composition* events happen before the changes take place in the textarea on most
	    // browsers, use a setTimeout with 0ms time to allow the native compositionend event to
	    // complete. This ensures the correct character is retrieved, this solution was used
	    // because:
	    // - The compositionend event's data property is unreliable, at least on Chromium
	    // - The last compositionupdate event's data property does not always accurately describe
	    //   the character, a counter example being Korean where an ending consonsant can move to
	    //   the following character if the following input is a vowel.
	    var self = this;
	    this.isSendingComposition = true;
	    setTimeout(function () {
	      // Ensure that the input has not already been sent
	      if (self.isSendingComposition) {
	        self.isSendingComposition = false;
	        var input;
	        if (self.isComposing) {
	          // Use the end position to get the string if a new composition has started.
	          input = self.textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end);
	        } else {
	          // Don't use the end position here in order to pick up any characters after the
	          // composition has finished, for example when typing a non-composition character
	          // (eg. 2) after a composition character.
	          input = self.textarea.value.substring(currentCompositionPosition.start);
	        }
	        self.terminal.handler(input);
	      }
	    }, 0);
	  }
	};
	
	/**
	 * Apply any changes made to the textarea after the current event chain is allowed to complete.
	 * This should be called when not currently composing but a keydown event with the "composition
	 * character" (229) is triggered, in order to allow non-composition text to be entered when an
	 * IME is active.
	 */
	CompositionHelper.prototype.handleAnyTextareaChanges = function () {
	  var oldValue = this.textarea.value;
	  var self = this;
	  setTimeout(function () {
	    // Ignore if a composition has started since the timeout
	    if (!self.isComposing) {
	      var newValue = self.textarea.value;
	      var diff = newValue.replace(oldValue, '');
	      if (diff.length > 0) {
	        self.terminal.handler(diff);
	      }
	    }
	  }, 0);
	};
	
	/**
	 * Positions the composition view on top of the cursor and the textarea just below it (so the
	 * IME helper dialog is positioned correctly).
	 */
	CompositionHelper.prototype.updateCompositionElements = function (dontRecurse) {
	  if (!this.isComposing) {
	    return;
	  }
	  var cursor = this.terminal.element.querySelector('.terminal-cursor');
	  if (cursor) {
	    this.compositionView.style.left = cursor.offsetLeft + 'px';
	    this.compositionView.style.top = cursor.offsetTop + 'px';
	    var compositionViewBounds = this.compositionView.getBoundingClientRect();
	    this.textarea.style.left = cursor.offsetLeft + compositionViewBounds.width + 'px';
	    this.textarea.style.top = cursor.offsetTop + cursor.offsetHeight + 'px';
	  }
	  if (!dontRecurse) {
	    setTimeout(this.updateCompositionElements.bind(this, true), 0);
	  }
	};
	
	/**
	 * Clears the textarea's position so that the cursor does not blink on IE.
	 * @private
	 */
	CompositionHelper.prototype.clearTextareaPosition = function () {
	  this.textarea.style.left = '';
	  this.textarea.style.top = '';
	};
	
	exports.CompositionHelper = CompositionHelper;
	
	},{}],2:[function(_dereq_,module,exports){
	"use strict";
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	/**
	 * xterm.js: xterm, in the browser
	 * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License)
	 */
	
	function EventEmitter() {
	  this._events = this._events || {};
	}
	
	EventEmitter.prototype.addListener = function (type, listener) {
	  this._events[type] = this._events[type] || [];
	  this._events[type].push(listener);
	};
	
	EventEmitter.prototype.on = EventEmitter.prototype.addListener;
	
	EventEmitter.prototype.removeListener = function (type, listener) {
	  if (!this._events[type]) return;
	
	  var obj = this._events[type],
	      i = obj.length;
	
	  while (i--) {
	    if (obj[i] === listener || obj[i].listener === listener) {
	      obj.splice(i, 1);
	      return;
	    }
	  }
	};
	
	EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
	
	EventEmitter.prototype.removeAllListeners = function (type) {
	  if (this._events[type]) delete this._events[type];
	};
	
	EventEmitter.prototype.once = function (type, listener) {
	  var self = this;
	  function on() {
	    var args = Array.prototype.slice.call(arguments);
	    this.removeListener(type, on);
	    return listener.apply(this, args);
	  }
	  on.listener = listener;
	  return this.on(type, on);
	};
	
	EventEmitter.prototype.emit = function (type) {
	  if (!this._events[type]) return;
	
	  var args = Array.prototype.slice.call(arguments, 1),
	      obj = this._events[type],
	      l = obj.length,
	      i = 0;
	
	  for (; i < l; i++) {
	    obj[i].apply(this, args);
	  }
	};
	
	EventEmitter.prototype.listeners = function (type) {
	  return this._events[type] = this._events[type] || [];
	};
	
	exports.EventEmitter = EventEmitter;
	
	},{}],3:[function(_dereq_,module,exports){
	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	/**
	 * xterm.js: xterm, in the browser
	 * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License)
	 */
	
	/**
	 * Represents the viewport of a terminal, the visible area within the larger buffer of output.
	 * Logic for the virtual scroll bar is included in this object.
	 * @param {Terminal} terminal The Terminal object.
	 * @param {HTMLElement} viewportElement The DOM element acting as the viewport
	 * @param {HTMLElement} charMeasureElement A DOM element used to measure the character size of
	 *   the terminal.
	 */
	function Viewport(terminal, viewportElement, scrollArea, charMeasureElement) {
	  this.terminal = terminal;
	  this.viewportElement = viewportElement;
	  this.scrollArea = scrollArea;
	  this.charMeasureElement = charMeasureElement;
	  this.currentRowHeight = 0;
	  this.lastRecordedBufferLength = 0;
	  this.lastRecordedViewportHeight = 0;
	
	  this.terminal.on('scroll', this.syncScrollArea.bind(this));
	  this.terminal.on('resize', this.syncScrollArea.bind(this));
	  this.viewportElement.addEventListener('scroll', this.onScroll.bind(this));
	
	  this.syncScrollArea();
	}
	
	/**
	 * Refreshes row height, setting line-height, viewport height and scroll area height if
	 * necessary.
	 * @param {number|undefined} charSize A character size measurement bounding rect object, if it
	 *   doesn't exist it will be created.
	 */
	Viewport.prototype.refresh = function (charSize) {
	  var size = charSize || this.charMeasureElement.getBoundingClientRect();
	  if (size.height > 0) {
	    var rowHeightChanged = size.height !== this.currentRowHeight;
	    if (rowHeightChanged) {
	      this.currentRowHeight = size.height;
	      this.viewportElement.style.lineHeight = size.height + 'px';
	      this.terminal.rowContainer.style.lineHeight = size.height + 'px';
	    }
	    var viewportHeightChanged = this.lastRecordedViewportHeight !== this.terminal.rows;
	    if (rowHeightChanged || viewportHeightChanged) {
	      this.lastRecordedViewportHeight = this.terminal.rows;
	      this.viewportElement.style.height = size.height * this.terminal.rows + 'px';
	    }
	    this.scrollArea.style.height = size.height * this.lastRecordedBufferLength + 'px';
	  }
	};
	
	/**
	 * Updates dimensions and synchronizes the scroll area if necessary.
	 */
	Viewport.prototype.syncScrollArea = function () {
	  if (this.lastRecordedBufferLength !== this.terminal.lines.length) {
	    // If buffer height changed
	    this.lastRecordedBufferLength = this.terminal.lines.length;
	    this.refresh();
	  } else if (this.lastRecordedViewportHeight !== this.terminal.rows) {
	    // If viewport height changed
	    this.refresh();
	  } else {
	    // If size has changed, refresh viewport
	    var size = this.charMeasureElement.getBoundingClientRect();
	    if (size.height !== this.currentRowHeight) {
	      this.refresh(size);
	    }
	  }
	
	  // Sync scrollTop
	  var scrollTop = this.terminal.ydisp * this.currentRowHeight;
	  if (this.viewportElement.scrollTop !== scrollTop) {
	    this.viewportElement.scrollTop = scrollTop;
	  }
	};
	
	/**
	 * Handles scroll events on the viewport, calculating the new viewport and requesting the
	 * terminal to scroll to it.
	 * @param {Event} ev The scroll event.
	 */
	Viewport.prototype.onScroll = function (ev) {
	  var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight);
	  var diff = newRow - this.terminal.ydisp;
	  this.terminal.scrollDisp(diff, true);
	};
	
	/**
	 * Handles mouse wheel events by adjusting the viewport's scrollTop and delegating the actual
	 * scrolling to `onScroll`, this event needs to be attached manually by the consumer of
	 * `Viewport`.
	 * @param {WheelEvent} ev The mouse wheel event.
	 */
	Viewport.prototype.onWheel = function (ev) {
	  if (ev.deltaY === 0) {
	    // Do nothing if it's not a vertical scroll event
	    return;
	  }
	  // Fallback to WheelEvent.DOM_DELTA_PIXEL
	  var multiplier = 1;
	  if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {
	    multiplier = this.currentRowHeight;
	  } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
	    multiplier = this.currentRowHeight * this.terminal.rows;
	  }
	  this.viewportElement.scrollTop += ev.deltaY * multiplier;
	  // Prevent the page from scrolling when the terminal scrolls
	  ev.preventDefault();
	};
	
	exports.Viewport = Viewport;
	
	},{}],4:[function(_dereq_,module,exports){
	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	/**
	 * xterm.js: xterm, in the browser
	 * Copyright (c) 2016, SourceLair Private Company <www.sourcelair.com> (MIT License)
	 */
	
	/**
	 * Clipboard handler module. This module contains methods for handling all
	 * clipboard-related events appropriately in the terminal.
	 * @module xterm/handlers/Clipboard
	 */
	
	/**
	 * Prepares text copied from terminal selection, to be saved in the clipboard by:
	 *   1. stripping all trailing white spaces
	 *   2. converting all non-breaking spaces to regular spaces
	 * @param {string} text The copied text that needs processing for storing in clipboard
	 * @returns {string}
	 */
	function prepareTextForClipboard(text) {
	  var space = String.fromCharCode(32),
	      nonBreakingSpace = String.fromCharCode(160),
	      allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'),
	      processedText = text.split('\n').map(function (line) {
	    // Strip all trailing white spaces and convert all non-breaking spaces
	    // to regular spaces.
	    var processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space);
	
	    return processedLine;
	  }).join('\n');
	
	  return processedText;
	}
	
	/**
	 * Binds copy functionality to the given terminal.
	 * @param {ClipboardEvent} ev The original copy event to be handled
	 */
	function copyHandler(ev) {
	  var copiedText = window.getSelection().toString(),
	      text = prepareTextForClipboard(copiedText);
	
	  ev.clipboardData.setData('text/plain', text);
	  ev.preventDefault(); // Prevent or the original text will be copied.
	}
	
	/**
	 * Redirect the clipboard's data to the terminal's input handler.
	 * @param {ClipboardEvent} ev The original paste event to be handled
	 * @param {Terminal} term The terminal on which to apply the handled paste event
	 */
	function pasteHandler(ev, term) {
	  ev.stopPropagation();
	  if (ev.clipboardData) {
	    var text = ev.clipboardData.getData('text/plain');
	    term.handler(text);
	    term.textarea.value = '';
	    return term.cancel(ev);
	  }
	}
	
	/**
	 * Bind to right-click event and allow right-click copy and paste.
	 *
	 * **Logic**
	 * If text is selected and right-click happens on selected text, then
	 * do nothing to allow seamless copying.
	 * If no text is selected or right-click is outside of the selection
	 * area, then bring the terminal's input below the cursor, in order to
	 * trigger the event on the textarea and allow-right click paste, without
	 * caring about disappearing selection.
	 * @param {ClipboardEvent} ev The original paste event to be handled
	 * @param {Terminal} term The terminal on which to apply the handled paste event
	 */
	function rightClickHandler(ev, term) {
	  var s = document.getSelection(),
	      sText = prepareTextForClipboard(s.toString()),
	      r = s.getRangeAt(0);
	
	  var x = ev.clientX,
	      y = ev.clientY;
	
	  var cr = r.getClientRects(),
	      clickIsOnSelection = false,
	      i,
	      rect;
	
	  for (i = 0; i < cr.length; i++) {
	    rect = cr[i];
	    clickIsOnSelection = x > rect.left && x < rect.right && y > rect.top && y < rect.bottom;
	    // If we clicked on selection and selection is not a single space,
	    // then mark the right click as copy-only. We check for the single
	    // space selection, as this can happen when clicking on an &nbsp;
	    // and there is not much pointing in copying a single space.
	    // Single space is char
	    if (clickIsOnSelection && sText !== ' ') {
	      break;
	    }
	  }
	
	  // Bring textarea at the cursor position
	  if (!clickIsOnSelection) {
	    term.textarea.style.position = 'fixed';
	    term.textarea.style.width = '10px';
	    term.textarea.style.height = '10px';
	    term.textarea.style.left = x + 'px';
	    term.textarea.style.top = y + 'px';
	    term.textarea.style.zIndex = 1000;
	    term.textarea.focus();
	
	    // Reset the terminal textarea's styling
	    setTimeout(function () {
	      term.textarea.style.position = null;
	      term.textarea.style.width = null;
	      term.textarea.style.height = null;
	      term.textarea.style.left = null;
	      term.textarea.style.top = null;
	      term.textarea.style.zIndex = null;
	    }, 1);
	  }
	}
	
	exports.prepareTextForClipboard = prepareTextForClipboard;
	exports.copyHandler = copyHandler;
	exports.pasteHandler = pasteHandler;
	exports.rightClickHandler = rightClickHandler;
	
	},{}],5:[function(_dereq_,module,exports){
	(function (__dirname){
	'use strict';var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};/**
	 * xterm.js: xterm, in the browser
	 * Copyright (c) 2014-2014, SourceLair Private Company <www.sourcelair.com> (MIT License)
	 * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
	 * https://github.com/chjj/term.js
	 *
	 * Permission is hereby granted, free of charge, to any person obtaining a copy
	 * of this software and associated documentation files (the "Software"), to deal
	 * in the Software without restriction, including without limitation the rights
	 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	 * copies of the Software, and to permit persons to whom the Software is
	 * furnished to do so, subject to the following conditions:
	 *
	 * The above copyright notice and this permission notice shall be included in
	 * all copies or substantial portions of the Software.
	 *
	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	 * THE SOFTWARE.
	 *
	 * Originally forked from (with the author's permission):
	 *   Fabrice Bellard's javascript vt100 for jslinux:
	 *   http://bellard.org/jslinux/
	 *   Copyright (c) 2011 Fabrice Bellard
	 *   The original design remains. The terminal itself
	 *   has been extended to include xterm CSI codes, among
	 *   other features.
	 */var _CompositionHelper=_dereq_('./CompositionHelper.js');var _EventEmitter=_dereq_('./EventEmitter.js');var _Viewport=_dereq_('./Viewport.js');var _Clipboard=_dereq_('./handlers/Clipboard.js');/**
	 * Terminal Emulation References:
	 *   http://vt100.net/
	 *   http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt
	 *   http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
	 *   http://invisible-island.net/vttest/
	 *   http://www.inwap.com/pdp10/ansicode.txt
	 *   http://linux.die.net/man/4/console_codes
	 *   http://linux.die.net/man/7/urxvt
	 */// Let it work inside Node.js for automated testing purposes.
	var document=typeof window!='undefined'?window.document:null;/**
	 * States
	 */var normal=0,escaped=1,csi=2,osc=3,charset=4,dcs=5,ignore=6;/**
	 * Terminal
	 *//**
	 * Creates a new `Terminal` object.
	 *
	 * @param {object} options An object containing a set of options, the available options are:
	 *   - cursorBlink (boolean): Whether the terminal cursor blinks
	 *
	 * @public
	 * @class Xterm Xterm
	 * @alias module:xterm/src/xterm
	 */function Terminal(options){var self=this;if(!(this instanceof Terminal)){return new Terminal(arguments[0],arguments[1],arguments[2]);}self.cancel=Terminal.cancel;_EventEmitter.EventEmitter.call(this);if(typeof options==='number'){options={cols:arguments[0],rows:arguments[1],handler:arguments[2]};}options=options||{};Object.keys(Terminal.defaults).forEach(function(key){if(options[key]==null){options[key]=Terminal.options[key];if(Terminal[key]!==Terminal.defaults[key]){options[key]=Terminal[key];}}self[key]=options[key];});if(options.colors.length===8){options.colors=options.colors.concat(Terminal._colors.slice(8));}else if(options.colors.length===16){options.colors=options.colors.concat(Terminal._colors.slice(16));}else if(options.colors.length===10){options.colors=options.colors.slice(0,-2).concat(Terminal._colors.slice(8,-2),options.colors.slice(-2));}else if(options.colors.length===18){options.colors=options.colors.concat(Terminal._colors.slice(16,-2),options.colors.slice(-2));}this.colors=options.colors;this.options=options;// this.context = options.context || window;
	// this.document = options.document || document;
	this.parent=options.body||options.parent||(document?document.getElementsByTagName('body')[0]:null);this.cols=options.cols||options.geometry[0];this.rows=options.rows||options.geometry[1];if(options.handler){this.on('data',options.handler);}/**
	   * The scroll position of the y cursor, ie. ybase + y = the y position within the entire
	   * buffer
	   */this.ybase=0;/**
	   * The scroll position of the viewport
	   */this.ydisp=0;/**
	   * The cursor's x position after ybase
	   */this.x=0;/**
	   * The cursor's y position after ybase
	   */this.y=0;/**
	   * Used to debounce the refresh function
	   */this.isRefreshing=false;/**
	   * Whether there is a full terminal refresh queued
	   */this.cursorState=0;this.cursorHidden=false;this.convertEol;this.state=0;this.queue='';this.scrollTop=0;this.scrollBottom=this.rows-1;this.customKeydownHandler=null;// modes
	this.applicationKeypad=false;this.applicationCursor=false;this.originMode=false;this.insertMode=false;this.wraparoundMode=true;// defaults: xterm - true, vt100 - false
	this.normal=null;// charset
	this.charset=null;this.gcharset=null;this.glevel=0;this.charsets=[null];// mouse properties
	this.decLocator;this.x10Mouse;this.vt200Mouse;this.vt300Mouse;this.normalMouse;this.mouseEvents;this.sendFocus;this.utfMouse;this.sgrMouse;this.urxvtMouse;// misc
	this.element;this.children;this.refreshStart;this.refreshEnd;this.savedX;this.savedY;this.savedCols;// stream
	this.readable=true;this.writable=true;this.defAttr=0<<18|257<<9|256<<0;this.curAttr=this.defAttr;this.params=[];this.currentParam=0;this.prefix='';this.postfix='';// leftover surrogate high from previous write invocation
	this.surrogate_high='';/**
	   * An array of all lines in the entire buffer, including the prompt. The lines are array of
	   * characters which are 2-length arrays where [0] is an attribute and [1] is the character.
	   */this.lines=[];var i=this.rows;while(i--){this.lines.push(this.blankLine());}this.tabs;this.setupStops();}inherits(Terminal,_EventEmitter.EventEmitter);/**
	 * back_color_erase feature for xterm.
	 */Terminal.prototype.eraseAttr=function(){// if (this.is('screen')) return this.defAttr;
	return this.defAttr&~0x1ff|this.curAttr&0x1ff;};/**
	 * Colors
	 */// Colors 0-15
	Terminal.tangoColors=[// dark:
	'#2e3436','#cc0000','#4e9a06','#c4a000','#3465a4','#75507b','#06989a','#d3d7cf',// bright:
	'#555753','#ef2929','#8ae234','#fce94f','#729fcf','#ad7fa8','#34e2e2','#eeeeec'];// Colors 0-15 + 16-255
	// Much thanks to TooTallNate for writing this.
	Terminal.colors=function(){var colors=Terminal.tangoColors.slice(),r=[0x00,0x5f,0x87,0xaf,0xd7,0xff],i;// 16-231
	i=0;for(;i<216;i++){out(r[i/36%6|0],r[i/6%6|0],r[i%6]);}// 232-255 (grey)
	i=0;for(;i<24;i++){r=8+i*10;out(r,r,r);}function out(r,g,b){colors.push('#'+hex(r)+hex(g)+hex(b));}function hex(c){c=c.toString(16);return c.length<2?'0'+c:c;}return colors;}();Terminal._colors=Terminal.colors.slice();Terminal.vcolors=function(){var out=[],colors=Terminal.colors,i=0,color;for(;i<256;i++){color=parseInt(colors[i].substring(1),16);out.push([color>>16&0xff,color>>8&0xff,color&0xff]);}return out;}();/**
	 * Options
	 */Terminal.defaults={colors:Terminal.colors,theme:'default',convertEol:false,termName:'xterm',geometry:[80,24],cursorBlink:false,visualBell:false,popOnBell:false,scrollback:1000,screenKeys:false,debug:false,cancelEvents:false// programFeatures: false,
	// focusKeys: false,
	};Terminal.options={};Terminal.focus=null;each(keys(Terminal.defaults),function(key){Terminal[key]=Terminal.defaults[key];Terminal.options[key]=Terminal.defaults[key];});/**
	 * Focus the terminal. Delegates focus handling to the terminal's DOM element.
	 */Terminal.prototype.focus=function(){return this.textarea.focus();};/**
	 * Retrieves an option's value from the terminal.
	 * @param {string} key The option key.
	 */Terminal.prototype.getOption=function(key,value){if(!(key in Terminal.defaults)){throw new Error('No option with key "'+key+'"');}if(typeof this.options[key]!=='undefined'){return this.options[key];}return this[key];};/**
	 * Sets an option on the terminal.
	 * @param {string} key The option key.
	 * @param {string} value The option value.
	 */Terminal.prototype.setOption=function(key,value){if(!(key in Terminal.defaults)){throw new Error('No option with key "'+key+'"');}this[key]=value;this.options[key]=value;};/**
	 * Binds the desired focus behavior on a given terminal object.
	 *
	 * @static
	 */Terminal.bindFocus=function(term){on(term.textarea,'focus',function(ev){if(term.sendFocus){term.send('\x1b[I');}term.element.classList.add('focus');term.showCursor();Terminal.focus=term;term.emit('focus',{terminal:term});});};/**
	 * Blur the terminal. Delegates blur handling to the terminal's DOM element.
	 */Terminal.prototype.blur=function(){return this.textarea.blur();};/**
	 * Binds the desired blur behavior on a given terminal object.
	 *
	 * @static
	 */Terminal.bindBlur=function(term){on(term.textarea,'blur',function(ev){term.refresh(term.y,term.y);if(term.sendFocus){term.send('\x1b[O');}term.element.classList.remove('focus');Terminal.focus=null;term.emit('blur',{terminal:term});});};/**
	 * Initialize default behavior
	 */Terminal.prototype.initGlobal=function(){var term=this;Terminal.bindKeys(this);Terminal.bindFocus(this);Terminal.bindBlur(this);// Bind clipboard functionality
	on(this.element,'copy',_Clipboard.copyHandler);on(this.textarea,'paste',function(ev){_Clipboard.pasteHandler.call(this,ev,term);});on(this.element,'contextmenu',function(ev){_Clipboard.rightClickHandler.call(this,ev,term);});};/**
	 * Apply key handling to the terminal
	 */Terminal.bindKeys=function(term){on(term.element,'keydown',function(ev){if(document.activeElement!=this){return;}term.keyDown(ev);},true);on(term.element,'keypress',function(ev){if(document.activeElement!=this){return;}term.keyPress(ev);},true);on(term.element,'keyup',term.focus.bind(term));on(term.textarea,'keydown',function(ev){term.keyDown(ev);},true);on(term.textarea,'keypress',function(ev){term.keyPress(ev);// Truncate the textarea's value, since it is not needed
	this.value='';},true);on(term.textarea,'compositionstart',term.compositionHelper.compositionstart.bind(term.compositionHelper));on(term.textarea,'compositionupdate',term.compositionHelper.compositionupdate.bind(term.compositionHelper));on(term.textarea,'compositionend',term.compositionHelper.compositionend.bind(term.compositionHelper));term.on('refresh',term.compositionHelper.updateCompositionElements.bind(term.compositionHelper));};/**
	 * Insert the given row to the terminal or produce a new one
	 * if no row argument is passed. Return the inserted row.
	 * @param {HTMLElement} row (optional) The row to append to the terminal.
	 */Terminal.prototype.insertRow=function(row){if((typeof row==='undefined'?'undefined':_typeof(row))!='object'){row=document.createElement('div');}this.rowContainer.appendChild(row);this.children.push(row);return row;};/**
	 * Opens the terminal within an element.
	 *
	 * @param {HTMLElement} parent The element to create the terminal within.
	 */Terminal.prototype.open=function(parent){var self=this,i=0,div;this.parent=parent||this.parent;if(!this.parent){throw new Error('Terminal requires a parent element.');}// Grab global elements
	this.context=this.parent.ownerDocument.defaultView;this.document=this.parent.ownerDocument;this.body=this.document.getElementsByTagName('body')[0];// Parse User-Agent
	if(this.context.navigator&&this.context.navigator.userAgent){this.isMSIE=!!~this.context.navigator.userAgent.indexOf('MSIE');}// Find the users platform. We use this to interpret the meta key
	// and ISO third level shifts.
	// http://stackoverflow.com/q/19877924/577598
	if(this.context.navigator&&this.context.navigator.platform){this.isMac=contains(this.context.navigator.platform,['Macintosh','MacIntel','MacPPC','Mac68K']);this.isIpad=this.context.navigator.platform==='iPad';this.isIphone=this.context.navigator.platform==='iPhone';this.isMSWindows=contains(this.context.navigator.platform,['Windows','Win16','Win32','WinCE']);}//Create main element container
	this.element=this.document.createElement('div');this.element.classList.add('terminal');this.element.classList.add('xterm');this.element.classList.add('xterm-theme-'+this.theme);this.element.style.height;this.element.setAttribute('tabindex',0);this.viewportElement=document.createElement('div');this.viewportElement.classList.add('xterm-viewport');this.element.appendChild(this.viewportElement);this.viewportScrollArea=document.createElement('div');this.viewportScrollArea.classList.add('xterm-scroll-area');this.viewportElement.appendChild(this.viewportScrollArea);// Create the container that will hold the lines of the terminal and then
	// produce the lines the lines.
	this.rowContainer=document.createElement('div');this.rowContainer.classList.add('xterm-rows');this.element.appendChild(this.rowContainer);this.children=[];// Create the container that will hold helpers like the textarea for
	// capturing DOM Events. Then produce the helpers.
	this.helperContainer=document.createElement('div');this.helperContainer.classList.add('xterm-helpers');// TODO: This should probably be inserted once it's filled to prevent an additional layout
	this.element.appendChild(this.helperContainer);this.textarea=document.createElement('textarea');this.textarea.classList.add('xterm-helper-textarea');this.textarea.setAttribute('autocorrect','off');this.textarea.setAttribute('autocapitalize','off');this.textarea.setAttribute('spellcheck','false');this.textarea.tabIndex=0;this.textarea.addEventListener('focus',function(){self.emit('focus',{terminal:self});});this.textarea.addEventListener('blur',function(){self.emit('blur',{terminal:self});});this.helperContainer.appendChild(this.textarea);this.compositionView=document.createElement('div');this.compositionView.classList.add('composition-view');this.compositionHelper=new _CompositionHelper.CompositionHelper(this.textarea,this.compositionView,this);this.helperContainer.appendChild(this.compositionView);this.charMeasureElement=document.createElement('div');this.charMeasureElement.classList.add('xterm-char-measure-element');this.charMeasureElement.innerHTML='W';this.helperContainer.appendChild(this.charMeasureElement);for(;i<this.rows;i++){this.insertRow();}this.parent.appendChild(this.element);this.viewport=new _Viewport.Viewport(this,this.viewportElement,this.viewportScrollArea,this.charMeasureElement);// Draw the screen.
	this.refresh(0,this.rows-1);// Initialize global actions that
	// need to be taken on the document.
	this.initGlobal();// Ensure there is a Terminal.focus.
	this.focus();on(this.element,'click',function(){var selection=document.getSelection(),collapsed=selection.isCollapsed,isRange=typeof collapsed=='boolean'?!collapsed:selection.type=='Range';if(!isRange){self.focus();}});// Listen for mouse events and translate
	// them into terminal mouse protocols.
	this.bindMouse();// Figure out whether boldness affects
	// the character width of monospace fonts.
	if(Terminal.brokenBold==null){Terminal.brokenBold=isBoldBroken(this.document);}this.emit('open');};/**
	 * Attempts to load an add-on using CommonJS or RequireJS (whichever is available).
	 * @param {string} addon The name of the addon to load
	 * @static
	 */Terminal.loadAddon=function(addon,callback){if((typeof exports==='undefined'?'undefined':_typeof(exports))==='object'&&(typeof module==='undefined'?'undefined':_typeof(module))==='object'){// CommonJS
	return _dereq_(__dirname+'/../addons/'+addon);}else if(typeof define=='function'){// RequireJS
	return _dereq_(['../addons/'+addon+'/'+addon],callback);}else{console.error('Cannot load a module without a CommonJS or RequireJS environment.');return false;}};/**
	 * XTerm mouse events
	 * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
	 * To better understand these
	 * the xterm code is very helpful:
	 * Relevant files:
	 *   button.c, charproc.c, misc.c
	 * Relevant functions in xterm/button.c:
	 *   BtnCode, EmitButtonCode, EditorButton, SendMousePosition
	 */Terminal.prototype.bindMouse=function(){var el=this.element,self=this,pressed=32;// mouseup, mousedown, wheel
	// left click: ^[[M 3<^[[M#3<
	// wheel up: ^[[M`3>
	function sendButton(ev){var button,pos;// get the xterm-style button
	button=getButton(ev);// get mouse coordinates
	pos=getCoords(ev);if(!pos)return;sendEvent(button,pos);switch(ev.overrideType||ev.type){case'mousedown':pressed=button;break;case'mouseup':// keep it at the left
	// button, just in case.
	pressed=32;break;case'wheel':// nothing. don't
	// interfere with
	// `pressed`.
	break;}}// motion example of a left click:
	// ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7<
	function sendMove(ev){var button=pressed,pos;pos=getCoords(ev);if(!pos)return;// buttons marked as motions
	// are incremented by 32
	button+=32;sendEvent(button,pos);}// encode button and
	// position to characters
	function encode(data,ch){if(!self.utfMouse){if(ch===255)return data.push(0);if(ch>127)ch=127;data.push(ch);}else{if(ch===2047)return data.push(0);if(ch<127){data.push(ch);}else{if(ch>2047)ch=2047;data.push(0xC0|ch>>6);data.push(0x80|ch&0x3F);}}}// send a mouse event:
	// regular/utf8: ^[[M Cb Cx Cy
	// urxvt: ^[[ Cb ; Cx ; Cy M
	// sgr: ^[[ Cb ; Cx ; Cy M/m
	// vt300: ^[[ 24(1/3/5)~ [ Cx , Cy ] \r
	// locator: CSI P e ; P b ; P r ; P c ; P p & w
	function sendEvent(button,pos){// self.emit('mouse', {
	//   x: pos.x - 32,
	//   y: pos.x - 32,
	//   button: button
	// });
	if(self.vt300Mouse){// NOTE: Unstable.
	// http://www.vt100.net/docs/vt3xx-gp/chapter15.html
	button&=3;pos.x-=32;pos.y-=32;var data='\x1b[24';if(button===0)data+='1';else if(button===1)data+='3';else if(button===2)data+='5';else if(button===3)return;else data+='0';data+='~['+pos.x+','+pos.y+']\r';self.send(data);return;}if(self.decLocator){// NOTE: Unstable.
	button&=3;pos.x-=32;pos.y-=32;if(button===0)button=2;else if(button===1)button=4;else if(button===2)button=6;else if(button===3)button=3;self.send('\x1b['+button+';'+(button===3?4:0)+';'+pos.y+';'+pos.x+';'+(pos.page||0)+'&w');return;}if(self.urxvtMouse){pos.x-=32;pos.y-=32;pos.x++;pos.y++;self.send('\x1b['+button+';'+pos.x+';'+pos.y+'M');return;}if(self.sgrMouse){pos.x-=32;pos.y-=32;self.send('\x1b[<'+((button&3)===3?button&~3:button)+';'+pos.x+';'+pos.y+((button&3)===3?'m':'M'));return;}var data=[];encode(data,button);encode(data,pos.x);encode(data,pos.y);self.send('\x1b[M'+String.fromCharCode.apply(String,data));}function getButton(ev){var button,shift,meta,ctrl,mod;// two low bits:
	// 0 = left
	// 1 = middle
	// 2 = right
	// 3 = release
	// wheel up/down:
	// 1, and 2 - with 64 added
	switch(ev.overrideType||ev.type){case'mousedown':button=ev.button!=null?+ev.button:ev.which!=null?ev.which-1:null;if(self.isMSIE){button=button===1?0:button===4?1:button;}break;case'mouseup':button=3;break;case'DOMMouseScroll':button=ev.detail<0?64:65;break;case'wheel':button=ev.wheelDeltaY>0?64:65;break;}// next three bits are the modifiers:
	// 4 = shift, 8 = meta, 16 = control
	shift=ev.shiftKey?4:0;meta=ev.metaKey?8:0;ctrl=ev.ctrlKey?16:0;mod=shift|meta|ctrl;// no mods
	if(self.vt200Mouse){// ctrl only
	mod&=ctrl;}else if(!self.normalMouse){mod=0;}// increment to SP
	button=32+(mod<<2)+button;return button;}// mouse coordinates measured in cols/rows
	function getCoords(ev){var x,y,w,h,el;// ignore browsers without pageX for now
	if(ev.pageX==null)return;x=ev.pageX;y=ev.pageY;el=self.element;// should probably check offsetParent
	// but this is more portable
	while(el&&el!==self.document.documentElement){x-=el.offsetLeft;y-=el.offsetTop;el='offsetParent'in el?el.offsetParent:el.parentNode;}// convert to cols/rows
	w=self.element.clientWidth;h=self.element.clientHeight;x=Math.ceil(x/w*self.cols);y=Math.ceil(y/h*self.rows);// be sure to avoid sending
	// bad positions to the program
	if(x<0)x=0;if(x>self.cols)x=self.cols;if(y<0)y=0;if(y>self.rows)y=self.rows;// xterm sends raw bytes and
	// starts at 32 (SP) for each.
	x+=32;y+=32;return{x:x,y:y,type:'wheel'};}on(el,'mousedown',function(ev){if(!self.mouseEvents)return;// send the button
	sendButton(ev);// ensure focus
	self.focus();// fix for odd bug
	//if (self.vt200Mouse && !self.normalMouse) {
	if(self.vt200Mouse){ev.overrideType='mouseup';sendButton(ev);return self.cancel(ev);}// bind events
	if(self.normalMouse)on(self.document,'mousemove',sendMove);// x10 compatibility mode can't send button releases
	if(!self.x10Mouse){on(self.document,'mouseup',function up(ev){sendButton(ev);if(self.normalMouse)off(self.document,'mousemove',sendMove);off(self.document,'mouseup',up);return self.cancel(ev);});}return self.cancel(ev);});//if (self.normalMouse) {
	//  on(self.document, 'mousemove', sendMove);
	//}
	on(el,'wheel',function(ev){if(!self.mouseEvents)return;if(self.x10Mouse||self.vt300Mouse||self.decLocator)return;sendButton(ev);return self.cancel(ev);});// allow wheel scrolling in
	// the shell for example
	on(el,'wheel',function(ev){if(self.mouseEvents)return;self.viewport.onWheel(ev);return self.cancel(ev);});};/**
	 * Destroys the terminal.
	 */Terminal.prototype.destroy=function(){this.readable=false;this.writable=false;this._events={};this.handler=function(){};this.write=function(){};if(this.element.parentNode){this.element.parentNode.removeChild(this.element);}//this.emit('close');
	};/**
	 * Flags used to render terminal text properly
	 */Terminal.flags={BOLD:1,UNDERLINE:2,BLINK:4,INVERSE:8,INVISIBLE:16};/**
	 * Refreshes (re-renders) terminal content within two rows (inclusive)
	 *
	 * Rendering Engine:
	 *
	 * In the screen buffer, each character is stored as a an array with a character
	 * and a 32-bit integer:
	 *   - First value: a utf-16 character.
	 *   - Second value:
	 *   - Next 9 bits: background color (0-511).
	 *   - Next 9 bits: foreground color (0-511).
	 *   - Next 14 bits: a mask for misc. flags:
	 *     - 1=bold
	 *     - 2=underline
	 *     - 4=blink
	 *     - 8=inverse
	 *     - 16=invisible
	 *
	 * @param {number} start The row to start from (between 0 and terminal's height terminal - 1)
	 * @param {number} end The row to end at (between fromRow and terminal's height terminal - 1)
	 * @param {boolean} queue Whether the refresh should ran right now or be queued
	 */Terminal.prototype.refresh=function(start,end,queue){var self=this;// queue defaults to true
	queue=typeof queue=='undefined'?true:queue;/**
	   * The refresh queue allows refresh to execute only approximately 30 times a second. For
	   * commands that pass a significant amount of output to the write function, this prevents the
	   * terminal from maxing out the CPU and making the UI unresponsive. While commands can still
	   * run beyond what they do on the terminal, it is far better with a debounce in place as
	   * every single terminal manipulation does not need to be constructed in the DOM.
	   *
	   * A side-effect of this is that it makes ^C to interrupt a process seem more responsive.
	   */if(queue){// If refresh should be queued, order the refresh and return.
	if(this._refreshIsQueued){// If a refresh has already been queued, just order a full refresh next
	this._fullRefreshNext=true;}else{setTimeout(function(){self.refresh(start,end,false);},34);this._refreshIsQueued=true;}return;}// If refresh should be run right now (not be queued), release the lock
	this._refreshIsQueued=false;// If multiple refreshes were requested, make a full refresh.
	if(this._fullRefreshNext){start=0;end=this.rows-1;this._fullRefreshNext=false;// reset lock
	}var x,y,i,line,out,ch,ch_width,width,data,attr,bg,fg,flags,row,parent,focused=document.activeElement;// If this is a big refresh, remove the terminal rows from the DOM for faster calculations
	if(end-start>=this.rows/2){parent=this.element.parentNode;if(parent){this.element.removeChild(this.rowContainer);}}width=this.cols;y=start;if(end>=this.rows.length){this.log('`end` is too large. Most likely a bad CSR.');end=this.rows.length-1;}for(;y<=end;y++){row=y+this.ydisp;line=this.lines[row];out='';if(this.y===y-(this.ybase-this.ydisp)&&this.cursorState&&!this.cursorHidden){x=this.x;}else{x=-1;}attr=this.defAttr;i=0;for(;i<width;i++){data=line[i][0];ch=line[i][1];ch_width=line[i][2];if(!ch_width)continue;if(i===x)data=-1;if(data!==attr){if(attr!==this.defAttr){out+='</span>';}if(data!==this.defAttr){if(data===-1){out+='<span class="reverse-video terminal-cursor';if(this.cursorBlink){out+=' blinking';}out+='">';}else{var classNames=[];bg=data&0x1ff;fg=data>>9&0x1ff;flags=data>>18;if(flags&Terminal.flags.BOLD){if(!Terminal.brokenBold){classNames.push('xterm-bold');}// See: XTerm*boldColors
	if(fg<8)fg+=8;}if(flags&Terminal.flags.UNDERLINE){classNames.push('xterm-underline');}if(flags&Terminal.flags.BLINK){classNames.push('xterm-blink');}// If inverse flag is on, then swap the foreground and background variables.
	if(flags&Terminal.flags.INVERSE){/* One-line variable swap in JavaScript: http://stackoverflow.com/a/16201730 */bg=[fg,fg=bg][0];// Should inverse just be before the
	// above boldColors effect instead?
	if(flags&1&&fg<8)fg+=8;}if(flags&Terminal.flags.INVISIBLE){classNames.push('xterm-hidden');}/**
	             * Weird situation: Invert flag used black foreground and white background results
	             * in invalid background color, positioned at the 256 index of the 256 terminal
	             * color map. Pin the colors manually in such a case.
	             *
	             * Source: https://github.com/sourcelair/xterm.js/issues/57
	             */if(flags&Terminal.flags.INVERSE){if(bg==257){bg=15;}if(fg==256){fg=0;}}if(bg<256){classNames.push('xterm-bg-color-'+bg);}if(fg<256){classNames.push('xterm-color-'+fg);}out+='<span';if(classNames.length){out+=' class="'+classNames.join(' ')+'"';}out+='>';}}}switch(ch){case'&':out+='&amp;';break;case'<':out+='&lt;';break;case'>':out+='&gt;';break;default:if(ch<=' '){out+='&nbsp;';}else{out+=ch;}break;}attr=data;}if(attr!==this.defAttr){out+='</span>';}this.children[y].innerHTML=out;}if(parent){this.element.appendChild(this.rowContainer);}this.emit('refresh',{element:this.element,start:start,end:end});};/**
	 * Display the cursor element
	 */Terminal.prototype.showCursor=function(){if(!this.cursorState){this.cursorState=1;this.refresh(this.y,this.y);}};/**
	 * Scroll the terminal
	 */Terminal.prototype.scroll=function(){var row;if(++this.ybase===this.scrollback){this.ybase=this.ybase/2|0;this.lines=this.lines.slice(-(this.ybase+this.rows)+1);}this.ydisp=this.ybase;// last line
	row=this.ybase+this.rows-1;// subtract the bottom scroll region
	row-=this.rows-1-this.scrollBottom;if(row===this.lines.length){// potential optimization:
	// pushing is faster than splicing
	// when they amount to the same
	// behavior.
	this.lines.push(this.blankLine());}else{// add our new line
	this.lines.splice(row,0,this.blankLine());}if(this.scrollTop!==0){if(this.ybase!==0){this.ybase--;this.ydisp=this.ybase;}this.lines.splice(this.ybase+this.scrollTop,1);}// this.maxRange();
	this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);this.emit('scroll',this.ydisp);};/**
	 * Scroll the display of the terminal
	 * @param {number} disp The number of lines to scroll down (negatives scroll up).
	 * @param {boolean} suppressScrollEvent Don't emit the scroll event as scrollDisp. This is used
	 * to avoid unwanted events being handled by the veiwport when the event was triggered from the
	 * viewport originally.
	 */Terminal.prototype.scrollDisp=function(disp,suppressScrollEvent){this.ydisp+=disp;if(this.ydisp>this.ybase){this.ydisp=this.ybase;}else if(this.ydisp<0){this.ydisp=0;}if(!suppressScrollEvent){this.emit('scroll',this.ydisp);}this.refresh(0,this.rows-1);};/**
	 * Writes text to the terminal.
	 * @param {string} text The text to write to the terminal.
	 */Terminal.prototype.write=function(data){var l=data.length,i=0,j,cs,ch,code,low,ch_width,row;this.refreshStart=this.y;this.refreshEnd=this.y;if(this.ybase!==this.ydisp){this.ydisp=this.ybase;this.emit('scroll',this.ydisp);this.maxRange();}// apply leftover surrogate high from last write
	if(this.surrogate_high){data=this.surrogate_high+data;this.surrogate_high='';}for(;i<l;i++){ch=data[i];// FIXME: higher chars than 0xa0 are not allowed in escape sequences
	//        --> maybe move to default
	code=data.charCodeAt(i);if(0xD800<=code&&code<=0xDBFF){// we got a surrogate high
	// get surrogate low (next 2 bytes)
	low=data.charCodeAt(i+1);if(isNaN(low)){// end of data stream, save surrogate high
	this.surrogate_high=ch;continue;}code=(code-0xD800)*0x400+(low-0xDC00)+0x10000;ch+=data.charAt(i+1);}// surrogate low - already handled above
	if(0xDC00<=code&&code<=0xDFFF)continue;switch(this.state){case normal:switch(ch){case'\x07':this.bell();break;// '\n', '\v', '\f'
	case'\n':case'\x0b':case'\x0c':if(this.convertEol){this.x=0;}this.y++;if(this.y>this.scrollBottom){this.y--;this.scroll();}break;// '\r'
	case'\r':this.x=0;break;// '\b'
	case'\x08':if(this.x>0){this.x--;}break;// '\t'
	case'\t':this.x=this.nextStop();break;// shift out
	case'\x0e':this.setgLevel(1);break;// shift in
	case'\x0f':this.setgLevel(0);break;// '\e'
	case'\x1b':this.state=escaped;break;default:// ' '
	// calculate print space
	// expensive call, therefore we save width in line buffer
	ch_width=wcwidth(code);if(ch>=' '){if(this.charset&&this.charset[ch]){ch=this.charset[ch];}row=this.y+this.ybase;// insert combining char in last cell
	// FIXME: needs handling after cursor jumps
	if(!ch_width&&this.x){// dont overflow left
	if(this.lines[row][this.x-1]){if(!this.lines[row][this.x-1][2]){// found empty cell after fullwidth, need to go 2 cells back
	if(this.lines[row][this.x-2])this.lines[row][this.x-2][1]+=ch;}else{this.lines[row][this.x-1][1]+=ch;}this.updateRange(this.y);}break;}// goto next line if ch would overflow
	// TODO: needs a global min terminal width of 2
	if(this.x+ch_width-1>=this.cols){// autowrap - DECAWM
	if(this.wraparoundMode){this.x=0;this.y++;if(this.y>this.scrollBottom){this.y--;this.scroll();}}else{this.x=this.cols-1;if(ch_width===2)// FIXME: check for xterm behavior
	continue;}}row=this.y+this.ybase;// insert mode: move characters to right
	if(this.insertMode){// do this twice for a fullwidth char
	for(var moves=0;moves<ch_width;++moves){// remove last cell, if it's width is 0
	// we have to adjust the second last cell as well
	var removed=this.lines[this.y+this.ybase].pop();if(removed[2]===0&&this.lines[row][this.cols-2]&&this.lines[row][this.cols-2][2]===2)this.lines[row][this.cols-2]=[this.curAttr,' ',1];// insert empty cell at cursor
	this.lines[row].splice(this.x,0,[this.curAttr,' ',1]);}}this.lines[row][this.x]=[this.curAttr,ch,ch_width];this.x++;this.updateRange(this.y);// fullwidth char - set next cell width to zero and advance cursor
	if(ch_width===2){this.lines[row][this.x]=[this.curAttr,'',0];this.x++;}}break;}break;case escaped:switch(ch){// ESC [ Control Sequence Introducer ( CSI is 0x9b).
	case'[':this.params=[];this.currentParam=0;this.state=csi;break;// ESC ] Operating System Command ( OSC is 0x9d).
	case']':this.params=[];this.currentParam=0;this.state=osc;break;// ESC P Device Control String ( DCS is 0x90).
	case'P':this.params=[];this.currentParam=0;this.state=dcs;break;// ESC _ Application Program Command ( APC is 0x9f).
	case'_':this.state=ignore;break;// ESC ^ Privacy Message ( PM is 0x9e).
	case'^':this.state=ignore;break;// ESC c Full Reset (RIS).
	case'c':this.reset();break;// ESC E Next Line ( NEL is 0x85).
	// ESC D Index ( IND is 0x84).
	case'E':this.x=0;;case'D':this.index();break;// ESC M Reverse Index ( RI is 0x8d).
	case'M':this.reverseIndex();break;// ESC % Select default/utf-8 character set.
	// @ = default, G = utf-8
	case'%'://this.charset = null;
	this.setgLevel(0);this.setgCharset(0,Terminal.charsets.US);this.state=normal;i++;break;// ESC (,),*,+,-,. Designate G0-G2 Character Set.
	case'(':// <-- this seems to get all the attention
	case')':case'*':case'+':case'-':case'.':switch(ch){case'(':this.gcharset=0;break;case')':this.gcharset=1;break;case'*':this.gcharset=2;break;case'+':this.gcharset=3;break;case'-':this.gcharset=1;break;case'.':this.gcharset=2;break;}this.state=charset;break;// Designate G3 Character Set (VT300).
	// A = ISO Latin-1 Supplemental.
	// Not implemented.
	case'/':this.gcharset=3;this.state=charset;i--;break;// ESC N
	// Single Shift Select of G2 Character Set
	// ( SS2 is 0x8e). This affects next character only.
	case'N':break;// ESC O
	// Single Shift Select of G3 Character Set
	// ( SS3 is 0x8f). This affects next character only.
	case'O':break;// ESC n
	// Invoke the G2 Character Set as GL (LS2).
	case'n':this.setgLevel(2);break;// ESC o
	// Invoke the G3 Character Set as GL (LS3).
	case'o':this.setgLevel(3);break;// ESC |
	// Invoke the G3 Character Set as GR (LS3R).
	case'|':this.setgLevel(3);break;// ESC }
	// Invoke the G2 Character Set as GR (LS2R).
	case'}':this.setgLevel(2);break;// ESC ~
	// Invoke the G1 Character Set as GR (LS1R).
	case'~':this.setgLevel(1);break;// ESC 7 Save Cursor (DECSC).
	case'7':this.saveCursor();this.state=normal;break;// ESC 8 Restore Cursor (DECRC).
	case'8':this.restoreCursor();this.state=normal;break;// ESC # 3 DEC line height/width
	case'#':this.state=normal;i++;break;// ESC H Tab Set (HTS is 0x88).
	case'H':this.tabSet();break;// ESC = Application Keypad (DECKPAM).
	case'=':this.log('Serial port requested application keypad.');this.applicationKeypad=true;this.viewport.syncScrollArea();this.state=normal;break;// ESC > Normal Keypad (DECKPNM).
	case'>':this.log('Switching back to normal keypad.');this.applicationKeypad=false;this.viewport.syncScrollArea();this.state=normal;break;default:this.state=normal;this.error('Unknown ESC control: %s.',ch);break;}break;case charset:switch(ch){case'0':// DEC Special Character and Line Drawing Set.
	cs=Terminal.charsets.SCLD;break;case'A':// UK
	cs=Terminal.charsets.UK;break;case'B':// United States (USASCII).
	cs=Terminal.charsets.US;break;case'4':// Dutch
	cs=Terminal.charsets.Dutch;break;case'C':// Finnish
	case'5':cs=Terminal.charsets.Finnish;break;case'R':// French
	cs=Terminal.charsets.French;break;case'Q':// FrenchCanadian
	cs=Terminal.charsets.FrenchCanadian;break;case'K':// German
	cs=Terminal.charsets.German;break;case'Y':// Italian
	cs=Terminal.charsets.Italian;break;case'E':// NorwegianDanish
	case'6':cs=Terminal.charsets.NorwegianDanish;break;case'Z':// Spanish
	cs=Terminal.charsets.Spanish;break;case'H':// Swedish
	case'7':cs=Terminal.charsets.Swedish;break;case'=':// Swiss
	cs=Terminal.charsets.Swiss;break;case'/':// ISOLatin (actually /A)
	cs=Terminal.charsets.ISOLatin;i++;break;default:// Default
	cs=Terminal.charsets.US;break;}this.setgCharset(this.gcharset,cs);this.gcharset=null;this.state=normal;break;case osc:// OSC Ps ; Pt ST
	// OSC Ps ; Pt BEL
	//   Set Text Parameters.
	if(ch==='\x1b'||ch==='\x07'){if(ch==='\x1b')i++;this.params.push(this.currentParam);switch(this.params[0]){case 0:case 1:case 2:if(this.params[1]){this.title=this.params[1];this.handleTitle(this.title);}break;case 3:// set X property
	break;case 4:case 5:// change dynamic colors
	break;case 10:case 11:case 12:case 13:case 14:case 15:case 16:case 17:case 18:case 19:// change dynamic ui colors
	break;case 46:// change log file
	break;case 50:// dynamic font
	break;case 51:// emacs shell
	break;case 52:// manipulate selection data
	break;case 104:case 105:case 110:case 111:case 112:case 113:case 114:case 115:case 116:case 117:case 118:// reset colors
	break;}this.params=[];this.currentParam=0;this.state=normal;}else{if(!this.params.length){if(ch>='0'&&ch<='9'){this.currentParam=this.currentParam*10+ch.charCodeAt(0)-48;}else if(ch===';'){this.params.push(this.currentParam);this.currentParam='';}}else{this.currentParam+=ch;}}break;case csi:// '?', '>', '!'
	if(ch==='?'||ch==='>'||ch==='!'){this.prefix=ch;break;}// 0 - 9
	if(ch>='0'&&ch<='9'){this.currentParam=this.currentParam*10+ch.charCodeAt(0)-48;break;}// '$', '"', ' ', '\''
	if(ch==='$'||ch==='"'||ch===' '||ch==='\''){this.postfix=ch;break;}this.params.push(this.currentParam);this.currentParam=0;// ';'
	if(ch===';')break;this.state=normal;switch(ch){// CSI Ps A
	// Cursor Up Ps Times (default = 1) (CUU).
	case'A':this.cursorUp(this.params);break;// CSI Ps B
	// Cursor Down Ps Times (default = 1) (CUD).
	case'B':this.cursorDown(this.params);break;// CSI Ps C
	// Cursor Forward Ps Times (default = 1) (CUF).
	case'C':this.cursorForward(this.params);break;// CSI Ps D
	// Cursor Backward Ps Times (default = 1) (CUB).
	case'D':this.cursorBackward(this.params);break;// CSI Ps ; Ps H
	// Cursor Position [row;column] (default = [1,1]) (CUP).
	case'H':this.cursorPos(this.params);break;// CSI Ps J  Erase in Display (ED).
	case'J':this.eraseInDisplay(this.params);break;// CSI Ps K  Erase in Line (EL).
	case'K':this.eraseInLine(this.params);break;// CSI Pm m  Character Attributes (SGR).
	case'm':if(!this.prefix){this.charAttributes(this.params);}break;// CSI Ps n  Device Status Report (DSR).
	case'n':if(!this.prefix){this.deviceStatus(this.params);}break;/**
	             * Additions
	             */// CSI Ps @
	// Insert Ps (Blank) Character(s) (default = 1) (ICH).
	case'@':this.insertChars(this.params);break;// CSI Ps E
	// Cursor Next Line Ps Times (default = 1) (CNL).
	case'E':this.cursorNextLine(this.params);break;// CSI Ps F
	// Cursor Preceding Line Ps Times (default = 1) (CNL).
	case'F':this.cursorPrecedingLine(this.params);break;// CSI Ps G
	// Cursor Character Absolute  [column] (default = [row,1]) (CHA).
	case'G':this.cursorCharAbsolute(this.params);break;// CSI Ps L
	// Insert Ps Line(s) (default = 1) (IL).
	case'L':this.insertLines(this.params);break;// CSI Ps M
	// Delete Ps Line(s) (default = 1) (DL).
	case'M':this.deleteLines(this.params);break;// CSI Ps P
	// Delete Ps Character(s) (default = 1) (DCH).
	case'P':this.deleteChars(this.params);break;// CSI Ps X
	// Erase Ps Character(s) (default = 1) (ECH).
	case'X':this.eraseChars(this.params);break;// CSI Pm `  Character Position Absolute
	//   [column] (default = [row,1]) (HPA).
	case'`':this.charPosAbsolute(this.params);break;// 141 61 a * HPR -
	// Horizontal Position Relative
	case'a':this.HPositionRelative(this.params);break;// CSI P s c
	// Send Device Attributes (Primary DA).
	// CSI > P s c
	// Send Device Attributes (Secondary DA)
	case'c':this.sendDeviceAttributes(this.params);break;// CSI Pm d
	// Line Position Absolute  [row] (default = [1,column]) (VPA).
	case'd':this.linePosAbsolute(this.params);break;// 145 65 e * VPR - Vertical Position Relative
	case'e':this.VPositionRelative(this.params);break;// CSI Ps ; Ps f
	//   Horizontal and Vertical Position [row;column] (default =
	//   [1,1]) (HVP).
	case'f':this.HVPosition(this.params);break;// CSI Pm h  Set Mode (SM).
	// CSI ? Pm h - mouse escape codes, cursor escape codes
	case'h':this.setMode(this.params);break;// CSI Pm l  Reset Mode (RM).
	// CSI ? Pm l
	case'l':this.resetMode(this.params);break;// CSI Ps ; Ps r
	//   Set Scrolling Region [top;bottom] (default = full size of win-
	//   dow) (DECSTBM).
	// CSI ? Pm r
	case'r':this.setScrollRegion(this.params);break;// CSI s
	//   Save cursor (ANSI.SYS).
	case's':this.saveCursor(this.params);break;// CSI u
	//   Restore cursor (ANSI.SYS).
	case'u':this.restoreCursor(this.params);break;/**
	             * Lesser Used
	             */// CSI Ps I
	// Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).
	case'I':this.cursorForwardTab(this.params);break;// CSI Ps S  Scroll up Ps lines (default = 1) (SU).
	case'S':this.scrollUp(this.params);break;// CSI Ps T  Scroll down Ps lines (default = 1) (SD).
	// CSI Ps ; Ps ; Ps ; Ps ; Ps T
	// CSI > Ps; Ps T
	case'T':// if (this.prefix === '>') {
	//   this.resetTitleModes(this.params);
	//   break;
	// }
	// if (this.params.length > 2) {
	//   this.initMouseTracking(this.params);
	//   break;
	// }
	if(this.params.length<2&&!this.prefix){this.scrollDown(this.params);}break;// CSI Ps Z
	// Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).
	case'Z':this.cursorBackwardTab(this.params);break;// CSI Ps b  Repeat the preceding graphic character Ps times (REP).
	case'b':this.repeatPrecedingCharacter(this.params);break;// CSI Ps g  Tab Clear (TBC).
	case'g':this.tabClear(this.params);break;// CSI Pm i  Media Copy (MC).
	// CSI ? Pm i
	// case 'i':
	//   this.mediaCopy(this.params);
	//   break;
	// CSI Pm m  Character Attributes (SGR).
	// CSI > Ps; Ps m
	// case 'm': // duplicate
	//   if (this.prefix === '>') {
	//     this.setResources(this.params);
	//   } else {
	//     this.charAttributes(this.params);
	//   }
	//   break;
	// CSI Ps n  Device Status Report (DSR).
	// CSI > Ps n
	// case 'n': // duplicate
	//   if (this.prefix === '>') {
	//     this.disableModifiers(this.params);
	//   } else {
	//     this.deviceStatus(this.params);
	//   }
	//   break;
	// CSI > Ps p  Set pointer mode.
	// CSI ! p   Soft terminal reset (DECSTR).
	// CSI Ps$ p
	//   Request ANSI mode (DECRQM).
	// CSI ? Ps$ p
	//   Request DEC private mode (DECRQM).
	// CSI Ps ; Ps " p
	case'p':switch(this.prefix){// case '>':
	//   this.setPointerMode(this.params);
	//   break;
	case'!':this.softReset(this.params);break;// case '?':
	//   if (this.postfix === '$') {
	//     this.requestPrivateMode(this.params);
	//   }
	//   break;
	// default:
	//   if (this.postfix === '"') {
	//     this.setConformanceLevel(this.params);
	//   } else if (this.postfix === '$') {
	//     this.requestAnsiMode(this.params);
	//   }
	//   break;
	}break;// CSI Ps q  Load LEDs (DECLL).
	// CSI Ps SP q
	// CSI Ps " q
	// case 'q':
	//   if (this.postfix === ' ') {
	//     this.setCursorStyle(this.params);
	//     break;
	//   }
	//   if (this.postfix === '"') {
	//     this.setCharProtectionAttr(this.params);
	//     break;
	//   }
	//   this.loadLEDs(this.params);
	//   break;
	// CSI Ps ; Ps r
	//   Set Scrolling Region [top;bottom] (default = full size of win-
	//   dow) (DECSTBM).
	// CSI ? Pm r
	// CSI Pt; Pl; Pb; Pr; Ps$ r
	// case 'r': // duplicate
	//   if (this.prefix === '?') {
	//     this.restorePrivateValues(this.params);
	//   } else if (this.postfix === '$') {
	//     this.setAttrInRectangle(this.params);
	//   } else {
	//     this.setScrollRegion(this.params);
	//   }
	//   break;
	// CSI s     Save cursor (ANSI.SYS).
	// CSI ? Pm s
	// case 's': // duplicate
	//   if (this.prefix === '?') {
	//     this.savePrivateValues(this.params);
	//   } else {
	//     this.saveCursor(this.params);
	//   }
	//   break;
	// CSI Ps ; Ps ; Ps t
	// CSI Pt; Pl; Pb; Pr; Ps$ t
	// CSI > Ps; Ps t
	// CSI Ps SP t
	// case 't':
	//   if (this.postfix === '$') {
	//     this.reverseAttrInRectangle(this.params);
	//   } else if (this.postfix === ' ') {
	//     this.setWarningBellVolume(this.params);
	//   } else {
	//     if (this.prefix === '>') {
	//       this.setTitleModeFeature(this.params);
	//     } else {
	//       this.manipulateWindow(this.params);
	//     }
	//   }
	//   break;
	// CSI u     Restore cursor (ANSI.SYS).
	// CSI Ps SP u
	// case 'u': // duplicate
	//   if (this.postfix === ' ') {
	//     this.setMarginBellVolume(this.params);
	//   } else {
	//     this.restoreCursor(this.params);
	//   }
	//   break;
	// CSI Pt; Pl; Pb; Pr; Pp; Pt; Pl; Pp$ v
	// case 'v':
	//   if (this.postfix === '$') {
	//     this.copyRectagle(this.params);
	//   }
	//   break;
	// CSI Pt ; Pl ; Pb ; Pr ' w
	// case 'w':
	//   if (this.postfix === '\'') {
	//     this.enableFilterRectangle(this.params);
	//   }
	//   break;
	// CSI Ps x  Request Terminal Parameters (DECREQTPARM).
	// CSI Ps x  Select Attribute Change Extent (DECSACE).
	// CSI Pc; Pt; Pl; Pb; Pr$ x
	// case 'x':
	//   if (this.postfix === '$') {
	//     this.fillRectangle(this.params);
	//   } else {
	//     this.requestParameters(this.params);
	//     //this.__(this.params);
	//   }
	//   break;
	// CSI Ps ; Pu ' z
	// CSI Pt; Pl; Pb; Pr$ z
	// case 'z':
	//   if (this.postfix === '\'') {
	//     this.enableLocatorReporting(this.params);
	//   } else if (this.postfix === '$') {
	//     this.eraseRectangle(this.params);
	//   }
	//   break;
	// CSI Pm ' {
	// CSI Pt; Pl; Pb; Pr$ {
	// case '{':
	//   if (this.postfix === '\'') {
	//     this.setLocatorEvents(this.params);
	//   } else if (this.postfix === '$') {
	//     this.selectiveEraseRectangle(this.params);
	//   }
	//   break;
	// CSI Ps ' |
	// case '|':
	//   if (this.postfix === '\'') {
	//     this.requestLocatorPosition(this.params);
	//   }
	//   break;
	// CSI P m SP }
	// Insert P s Column(s) (default = 1) (DECIC), VT420 and up.
	// case '}':
	//   if (this.postfix === ' ') {
	//     this.insertColumns(this.params);
	//   }
	//   break;
	// CSI P m SP ~
	// Delete P s Column(s) (default = 1) (DECDC), VT420 and up
	// case '~':
	//   if (this.postfix === ' ') {
	//     this.deleteColumns(this.params);
	//   }
	//   break;
	default:this.error('Unknown CSI code: %s.',ch);break;}this.prefix='';this.postfix='';break;case dcs:if(ch==='\x1b'||ch==='\x07'){if(ch==='\x1b')i++;switch(this.prefix){// User-Defined Keys (DECUDK).
	case'':break;// Request Status String (DECRQSS).
	// test: echo -e '\eP$q"p\e\\'
	case'$q':var pt=this.currentParam,valid=false;switch(pt){// DECSCA
	case'"q':pt='0"q';break;// DECSCL
	case'"p':pt='61"p';break;// DECSTBM
	case'r':pt=''+(this.scrollTop+1)+';'+(this.scrollBottom+1)+'r';break;// SGR
	case'm':pt='0m';break;default:this.error('Unknown DCS Pt: %s.',pt);pt='';break;}this.send('\x1bP'+ +valid+'$r'+pt+'\x1b\\');break;// Set Termcap/Terminfo Data (xterm, experimental).
	case'+p':break;// Request Termcap/Terminfo String (xterm, experimental)
	// Regular xterm does not even respond to this sequence.
	// This can cause a small glitch in vim.
	// test: echo -ne '\eP+q6b64\e\\'
	case'+q':var pt=this.currentParam,valid=false;this.send('\x1bP'+ +valid+'+r'+pt+'\x1b\\');break;default:this.error('Unknown DCS prefix: %s.',this.prefix);break;}this.currentParam=0;this.prefix='';this.state=normal;}else if(!this.currentParam){if(!this.prefix&&ch!=='$'&&ch!=='+'){this.currentParam=ch;}else if(this.prefix.length===2){this.currentParam=ch;}else{this.prefix+=ch;}}else{this.currentParam+=ch;}break;case ignore:// For PM and APC.
	if(ch==='\x1b'||ch==='\x07'){if(ch==='\x1b')i++;this.state=normal;}break;}}this.updateRange(this.y);this.refresh(this.refreshStart,this.refreshEnd);};/**
	 * Writes text to the terminal, followed by a break line character (\n).
	 * @param {string} text The text to write to the terminal.
	 */Terminal.prototype.writeln=function(data){this.write(data+'\r\n');};/**
	 * Attaches a custom keydown handler which is run before keys are processed, giving consumers of
	 * xterm.js ultimate control as to what keys should be processed by the terminal and what keys
	 * should not.
	 * @param {function} customKeydownHandler The custom KeyboardEvent handler to attach. This is a
	 *   function that takes a KeyboardEvent, allowing consumers to stop propogation and/or prevent
	 *   the default action. The function returns whether the event should be processed by xterm.js.
	 */Terminal.prototype.attachCustomKeydownHandler=function(customKeydownHandler){this.customKeydownHandler=customKeydownHandler;};/**
	 * Handle a keydown event
	 * Key Resources:
	 *   - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent
	 * @param {KeyboardEvent} ev The keydown event to be handled.
	 */Terminal.prototype.keyDown=function(ev){if(this.customKeydownHandler&&this.customKeydownHandler(ev)===false){return false;}if(!this.compositionHelper.keydown.bind(this.compositionHelper)(ev)){return false;}var self=this;var result=this.evaluateKeyEscapeSequence(ev);if(result.scrollDisp){this.scrollDisp(result.scrollDisp);return this.cancel(ev,true);}if(isThirdLevelShift(this,ev)){return true;}if(result.cancel){// The event is canceled at the end already, is this necessary?
	this.cancel(ev,true);}if(!result.key){return true;}this.emit('keydown',ev);this.emit('key',result.key,ev);this.showCursor();this.handler(result.key);return this.cancel(ev,true);};/**
	 * Returns an object that determines how a KeyboardEvent should be handled. The key of the
	 * returned value is the new key code to pass to the PTY.
	 *
	 * Reference: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
	 * @param {KeyboardEvent} ev The keyboard event to be translated to key escape sequence.
	 */Terminal.prototype.evaluateKeyEscapeSequence=function(ev){var result={// Whether to cancel event propogation (NOTE: this may not be needed since the event is
	// canceled at the end of keyDown
	cancel:false,// The new key even to emit
	key:undefined,// The number of characters to scroll, if this is defined it will cancel the event
	scrollDisp:undefined};var modifiers=ev.shiftKey<<0|ev.altKey<<1|ev.ctrlKey<<2|ev.metaKey<<3;switch(ev.keyCode){case 8:// backspace
	if(ev.shiftKey){result.key='\x08';// ^H
	break;}result.key='\x7f';// ^?
	break;case 9:// tab
	if(ev.shiftKey){result.key='\x1b[Z';break;}result.key='\t';result.cancel=true;break;case 13:// return/enter
	result.key='\r';result.cancel=true;break;case 27:// escape
	result.key='\x1b';result.cancel=true;break;case 37:// left-arrow
	if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'D';// HACK: Make Alt + left-arrow behave like Ctrl + left-arrow: move one word backwards
	// http://unix.stackexchange.com/a/108106
	if(result.key=='\x1b[1;3D'){result.key='\x1b[1;5D';}}else if(this.applicationCursor){result.key='\x1bOD';}else{result.key='\x1b[D';}break;case 39:// right-arrow
	if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'C';// HACK: Make Alt + right-arrow behave like Ctrl + right-arrow: move one word forward
	// http://unix.stackexchange.com/a/108106
	if(result.key=='\x1b[1;3C'){result.key='\x1b[1;5C';}}else if(this.applicationCursor){result.key='\x1bOC';}else{result.key='\x1b[C';}break;case 38:// up-arrow
	if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'A';// HACK: Make Alt + up-arrow behave like Ctrl + up-arrow
	// http://unix.stackexchange.com/a/108106
	if(result.key=='\x1b[1;3A'){result.key='\x1b[1;5A';}}else if(this.applicationCursor){result.key='\x1bOA';}else{result.key='\x1b[A';}break;case 40:// down-arrow
	if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'B';// HACK: Make Alt + down-arrow behave like Ctrl + down-arrow
	// http://unix.stackexchange.com/a/108106
	if(result.key=='\x1b[1;3B'){result.key='\x1b[1;5B';}}else if(this.applicationCursor){result.key='\x1bOB';}else{result.key='\x1b[B';}break;case 45:// insert
	if(!ev.shiftKey&&!ev.ctrlKey){// <Ctrl> or <Shift> + <Insert> are used to
	// copy-paste on some systems.
	result.key='\x1b[2~';}break;case 46:// delete
	if(modifiers){result.key='\x1b[3;'+(modifiers+1)+'~';}else{result.key='\x1b[3~';}break;case 36:// home
	if(modifiers)result.key='\x1b[1;'+(modifiers+1)+'H';else if(this.applicationCursor)result.key='\x1bOH';else result.key='\x1b[H';break;case 35:// end
	if(modifiers)result.key='\x1b[1;'+(modifiers+1)+'F';else if(this.applicationCursor)result.key='\x1bOF';else result.key='\x1b[F';break;case 33:// page up
	if(ev.shiftKey){result.scrollDisp=-(this.rows-1);}else{result.key='\x1b[5~';}break;case 34:// page down
	if(ev.shiftKey){result.scrollDisp=this.rows-1;}else{result.key='\x1b[6~';}break;case 112:// F1-F12
	if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'P';}else{result.key='\x1bOP';}break;case 113:if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'Q';}else{result.key='\x1bOQ';}break;case 114:if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'R';}else{result.key='\x1bOR';}break;case 115:if(modifiers){result.key='\x1b[1;'+(modifiers+1)+'S';}else{result.key='\x1bOS';}break;case 116:if(modifiers){result.key='\x1b[15;'+(modifiers+1)+'~';}else{result.key='\x1b[15~';}break;case 117:if(modifiers){result.key='\x1b[17;'+(modifiers+1)+'~';}else{result.key='\x1b[17~';}break;case 118:if(modifiers){result.key='\x1b[18;'+(modifiers+1)+'~';}else{result.key='\x1b[18~';}break;case 119:if(modifiers){result.key='\x1b[19;'+(modifiers+1)+'~';}else{result.key='\x1b[19~';}break;case 120:if(modifiers){result.key='\x1b[20;'+(modifiers+1)+'~';}else{result.key='\x1b[20~';}break;case 121:if(modifiers){result.key='\x1b[21;'+(modifiers+1)+'~';}else{result.key='\x1b[21~';}break;case 122:if(modifiers){result.key='\x1b[23;'+(modifiers+1)+'~';}else{result.key='\x1b[23~';}break;case 123:if(modifiers){result.key='\x1b[24;'+(modifiers+1)+'~';}else{result.key='\x1b[24~';}break;default:// a-z and space
	if(ev.ctrlKey&&!ev.shiftKey&&!ev.altKey&&!ev.metaKey){if(ev.keyCode>=65&&ev.keyCode<=90){result.key=String.fromCharCode(ev.keyCode-64);}else if(ev.keyCode===32){// NUL
	result.key=String.fromCharCode(0);}else if(ev.keyCode>=51&&ev.keyCode<=55){// escape, file sep, group sep, record sep, unit sep
	result.key=String.fromCharCode(ev.keyCode-51+27);}else if(ev.keyCode===56){// delete
	result.key=String.fromCharCode(127);}else if(ev.keyCode===219){// ^[ - escape
	result.key=String.fromCharCode(27);}else if(ev.keyCode===221){// ^] - group sep
	result.key=String.fromCharCode(29);}}else if(!this.isMac&&ev.altKey&&!ev.ctrlKey&&!ev.metaKey){// On Mac this is a third level shift. Use <Esc> instead.
	if(ev.keyCode>=65&&ev.keyCode<=90){result.key='\x1b'+String.fromCharCode(ev.keyCode+32);}else if(ev.keyCode===192){result.key='\x1b`';}else if(ev.keyCode>=48&&ev.keyCode<=57){result.key='\x1b'+(ev.keyCode-48);}}break;}return result;};/**
	 * Set the G level of the terminal
	 * @param g
	 */Terminal.prototype.setgLevel=function(g){this.glevel=g;this.charset=this.charsets[g];};/**
	 * Set the charset for the given G level of the terminal
	 * @param g
	 * @param charset
	 */Terminal.prototype.setgCharset=function(g,charset){this.charsets[g]=charset;if(this.glevel===g){this.charset=charset;}};/**
	 * Handle a keypress event.
	 * Key Resources:
	 *   - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent
	 * @param {KeyboardEvent} ev The keypress event to be handled.
	 */Terminal.prototype.keyPress=function(ev){var key;this.cancel(ev);if(ev.charCode){key=ev.charCode;}else if(ev.which==null){key=ev.keyCode;}else if(ev.which!==0&&ev.charCode!==0){key=ev.which;}else{return false;}if(!key||(ev.altKey||ev.ctrlKey||ev.metaKey)&&!isThirdLevelShift(this,ev)){return false;}key=String.fromCharCode(key);this.emit('keypress',key,ev);this.emit('key',key,ev);this.showCursor();this.handler(key);return false;};/**
	 * Send data for handling to the terminal
	 * @param {string} data
	 */Terminal.prototype.send=function(data){var self=this;if(!this.queue){setTimeout(function(){self.handler(self.queue);self.queue='';},1);}this.queue+=data;};/**
	 * Ring the bell.
	 * Note: We could do sweet things with webaudio here
	 */Terminal.prototype.bell=function(){if(!this.visualBell)return;var self=this;this.element.style.borderColor='white';setTimeout(function(){self.element.style.borderColor='';},10);if(this.popOnBell)this.focus();};/**
	 * Log the current state to the console.
	 */Terminal.prototype.log=function(){if(!this.debug)return;if(!this.context.console||!this.context.console.log)return;var args=Array.prototype.slice.call(arguments);this.context.console.log.apply(this.context.console,args);};/**
	 * Log the current state as error to the console.
	 */Terminal.prototype.error=function(){if(!this.debug)return;if(!this.context.console||!this.context.console.error)return;var args=Array.prototype.slice.call(arguments);this.context.console.error.apply(this.context.console,args);};/**
	 * Resizes the terminal.
	 *
	 * @param {number} x The number of columns to resize to.
	 * @param {number} y The number of rows to resize to.
	 */Terminal.prototype.resize=function(x,y){var line,el,i,j,ch,addToY;if(x===this.cols&&y===this.rows){return;}if(x<1)x=1;if(y<1)y=1;// resize cols
	j=this.cols;if(j<x){ch=[this.defAttr,' ',1];// does xterm use the default attr?
	i=this.lines.length;while(i--){while(this.lines[i].length<x){this.lines[i].push(ch);}}}else{// (j > x)
	i=this.lines.length;while(i--){while(this.lines[i].length>x){this.lines[i].pop();}}}this.setupStops(j);this.cols=x;// resize rows
	j=this.rows;addToY=0;if(j<y){el=this.element;while(j++<y){// y is rows, not this.y
	if(this.lines.length<y+this.ybase){if(this.ybase>0&&this.lines.length<=this.ybase+this.y+addToY+1){// There is room above the buffer and there are no empty elements below the line,
	// scroll up
	this.ybase--;addToY++;if(this.ydisp>0){// Viewport is at the top of the buffer, must increase downwards
	this.ydisp--;}}else{// Add a blank line if there is no buffer left at the top to scroll to, or if there
	// are blank lines after the cursor
	this.lines.push(this.blankLine());}}if(this.children.length<y){this.insertRow();}}}else{// (j > y)
	while(j-->y){if(this.lines.length>y+this.ybase){if(this.lines.length>this.ybase+this.y+1){// The line is a blank line below the cursor, remove it
	this.lines.pop();}else{// The line is the cursor, scroll down
	this.ybase++;this.ydisp++;}}if(this.children.length>y){el=this.children.shift();if(!el)continue;el.parentNode.removeChild(el);}}}this.rows=y;// Make sure that the cursor stays on screen
	if(this.y>=y){this.y=y-1;}if(addToY){this.y+=addToY;}if(this.x>=x){this.x=x-1;}this.scrollTop=0;this.scrollBottom=y-1;this.refresh(0,this.rows-1);this.normal=null;this.emit('resize',{terminal:this,cols:x,rows:y});};/**
	 * Updates the range of rows to refresh
	 * @param {number} y The number of rows to refresh next.
	 */Terminal.prototype.updateRange=function(y){if(y<this.refreshStart)this.refreshStart=y;if(y>this.refreshEnd)this.refreshEnd=y;// if (y > this.refreshEnd) {
	//   this.refreshEnd = y;
	//   if (y > this.rows - 1) {
	//     this.refreshEnd = this.rows - 1;
	//   }
	// }
	};/**
	 * Set the range of refreshing to the maximyum value
	 */Terminal.prototype.maxRange=function(){this.refreshStart=0;this.refreshEnd=this.rows-1;};/**
	 * Setup the tab stops.
	 * @param {number} i
	 */Terminal.prototype.setupStops=function(i){if(i!=null){if(!this.tabs[i]){i=this.prevStop(i);}}else{this.tabs={};i=0;}for(;i<this.cols;i+=8){this.tabs[i]=true;}};/**
	 * Move the cursor to the previous tab stop from the given position (default is current).
	 * @param {number} x The position to move the cursor to the previous tab stop.
	 */Terminal.prototype.prevStop=function(x){if(x==null)x=this.x;while(!this.tabs[--x]&&x>0){}return x>=this.cols?this.cols-1:x<0?0:x;};/**
	 * Move the cursor one tab stop forward from the given position (default is current).
	 * @param {number} x The position to move the cursor one tab stop forward.
	 */Terminal.prototype.nextStop=function(x){if(x==null)x=this.x;while(!this.tabs[++x]&&x<this.cols){}return x>=this.cols?this.cols-1:x<0?0:x;};/**
	 * Erase in the identified line everything from "x" to the end of the line (right).
	 * @param {number} x The column from which to start erasing to the end of the line.
	 * @param {number} y The line in which to operate.
	 */Terminal.prototype.eraseRight=function(x,y){var line=this.lines[this.ybase+y],ch=[this.eraseAttr(),' ',1];// xterm
	for(;x<this.cols;x++){line[x]=ch;}this.updateRange(y);};/**
	 * Erase in the identified line everything from "x" to the start of the line (left).
	 * @param {number} x The column from which to start erasing to the start of the line.
	 * @param {number} y The line in which to operate.
	 */Terminal.prototype.eraseLeft=function(x,y){var line=this.lines[this.ybase+y],ch=[this.eraseAttr(),' ',1];// xterm
	x++;while(x--){line[x]=ch;}this.updateRange(y);};/**
	 * Clears the entire buffer, making the prompt line the new first line.
	 */Terminal.prototype.clear=function(){if(this.ybase===0&&this.y===0){// Don't clear if it's already clear
	return;}this.lines=[this.lines[this.ybase+this.y]];this.ydisp=0;this.ybase=0;this.y=0;for(var i=1;i<this.rows;i++){this.lines.push(this.blankLine());}this.refresh(0,this.rows-1);this.emit('scroll',this.ydisp);};/**
	 * Erase all content in the given line
	 * @param {number} y The line to erase all of its contents.
	 */Terminal.prototype.eraseLine=function(y){this.eraseRight(0,y);};/**
	 * Return the data array of a blank line/
	 * @param {number} cur First bunch of data for each "blank" character.
	 */Terminal.prototype.blankLine=function(cur){var attr=cur?this.eraseAttr():this.defAttr;var ch=[attr,' ',1]// width defaults to 1 halfwidth character
	,line=[],i=0;for(;i<this.cols;i++){line[i]=ch;}return line;};/**
	 * If cur return the back color xterm feature attribute. Else return defAttr.
	 * @param {object} cur
	 */Terminal.prototype.ch=function(cur){return cur?[this.eraseAttr(),' ',1]:[this.defAttr,' ',1];};/**
	 * Evaluate if the current erminal is the given argument.
	 * @param {object} term The terminal to evaluate
	 */Terminal.prototype.is=function(term){var name=this.termName;return(name+'').indexOf(term)===0;};/**
	     * Emit the 'data' event and populate the given data.
	     * @param {string} data The data to populate in the event.
	     */Terminal.prototype.handler=function(data){this.emit('data',data);};/**
	 * Emit the 'title' event and populate the given title.
	 * @param {string} title The title to populate in the event.
	 */Terminal.prototype.handleTitle=function(title){this.emit('title',title);};/**
	 * ESC
	 *//**
	 * ESC D Index (IND is 0x84).
	 */Terminal.prototype.index=function(){this.y++;if(this.y>this.scrollBottom){this.y--;this.scroll();}this.state=normal;};/**
	 * ESC M Reverse Index (RI is 0x8d).
	 */Terminal.prototype.reverseIndex=function(){var j;this.y--;if(this.y<this.scrollTop){this.y++;// possibly move the code below to term.reverseScroll();
	// test: echo -ne '\e[1;1H\e[44m\eM\e[0m'
	// blankLine(true) is xterm/linux behavior
	this.lines.splice(this.y+this.ybase,0,this.blankLine(true));j=this.rows-1-this.scrollBottom;this.lines.splice(this.rows-1+this.ybase-j+1,1);// this.maxRange();
	this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);}this.state=normal;};/**
	 * ESC c Full Reset (RIS).
	 */Terminal.prototype.reset=function(){this.options.rows=this.rows;this.options.cols=this.cols;var customKeydownHandler=this.customKeydownHandler;Terminal.call(this,this.options);this.customKeydownHandler=customKeydownHandler;this.refresh(0,this.rows-1);this.viewport.syncScrollArea();};/**
	 * ESC H Tab Set (HTS is 0x88).
	 */Terminal.prototype.tabSet=function(){this.tabs[this.x]=true;this.state=normal;};/**
	 * CSI
	 *//**
	 * CSI Ps A
	 * Cursor Up Ps Times (default = 1) (CUU).
	 */Terminal.prototype.cursorUp=function(params){var param=params[0];if(param<1)param=1;this.y-=param;if(this.y<0)this.y=0;};/**
	 * CSI Ps B
	 * Cursor Down Ps Times (default = 1) (CUD).
	 */Terminal.prototype.cursorDown=function(params){var param=params[0];if(param<1)param=1;this.y+=param;if(this.y>=this.rows){this.y=this.rows-1;}};/**
	 * CSI Ps C
	 * Cursor Forward Ps Times (default = 1) (CUF).
	 */Terminal.prototype.cursorForward=function(params){var param=params[0];if(param<1)param=1;this.x+=param;if(this.x>=this.cols){this.x=this.cols-1;}};/**
	 * CSI Ps D
	 * Cursor Backward Ps Times (default = 1) (CUB).
	 */Terminal.prototype.cursorBackward=function(params){var param=params[0];if(param<1)param=1;this.x-=param;if(this.x<0)this.x=0;};/**
	 * CSI Ps ; Ps H
	 * Cursor Position [row;column] (default = [1,1]) (CUP).
	 */Terminal.prototype.cursorPos=function(params){var row,col;row=params[0]-1;if(params.length>=2){col=params[1]-1;}else{col=0;}if(row<0){row=0;}else if(row>=this.rows){row=this.rows-1;}if(col<0){col=0;}else if(col>=this.cols){col=this.cols-1;}this.x=col;this.y=row;};/**
	 * CSI Ps J  Erase in Display (ED).
	 *     Ps = 0  -> Erase Below (default).
	 *     Ps = 1  -> Erase Above.
	 *     Ps = 2  -> Erase All.
	 *     Ps = 3  -> Erase Saved Lines (xterm).
	 * CSI ? Ps J
	 *   Erase in Display (DECSED).
	 *     Ps = 0  -> Selective Erase Below (default).
	 *     Ps = 1  -> Selective Erase Above.
	 *     Ps = 2  -> Selective Erase All.
	 */Terminal.prototype.eraseInDisplay=function(params){var j;switch(params[0]){case 0:this.eraseRight(this.x,this.y);j=this.y+1;for(;j<this.rows;j++){this.eraseLine(j);}break;case 1:this.eraseLeft(this.x,this.y);j=this.y;while(j--){this.eraseLine(j);}break;case 2:j=this.rows;while(j--){this.eraseLine(j);}break;case 3:;// no saved lines
	break;}};/**
	 * CSI Ps K  Erase in Line (EL).
	 *     Ps = 0  -> Erase to Right (default).
	 *     Ps = 1  -> Erase to Left.
	 *     Ps = 2  -> Erase All.
	 * CSI ? Ps K
	 *   Erase in Line (DECSEL).
	 *     Ps = 0  -> Selective Erase to Right (default).
	 *     Ps = 1  -> Selective Erase to Left.
	 *     Ps = 2  -> Selective Erase All.
	 */Terminal.prototype.eraseInLine=function(params){switch(params[0]){case 0:this.eraseRight(this.x,this.y);break;case 1:this.eraseLeft(this.x,this.y);break;case 2:this.eraseLine(this.y);break;}};/**
	 * CSI Pm m  Character Attributes (SGR).
	 *     Ps = 0  -> Normal (default).
	 *     Ps = 1  -> Bold.
	 *     Ps = 4  -> Underlined.
	 *     Ps = 5  -> Blink (appears as Bold).
	 *     Ps = 7  -> Inverse.
	 *     Ps = 8  -> Invisible, i.e., hidden (VT300).
	 *     Ps = 2 2  -> Normal (neither bold nor faint).
	 *     Ps = 2 4  -> Not underlined.
	 *     Ps = 2 5  -> Steady (not blinking).
	 *     Ps = 2 7  -> Positive (not inverse).
	 *     Ps = 2 8  -> Visible, i.e., not hidden (VT300).
	 *     Ps = 3 0  -> Set foreground color to Black.
	 *     Ps = 3 1  -> Set foreground color to Red.
	 *     Ps = 3 2  -> Set foreground color to Green.
	 *     Ps = 3 3  -> Set foreground color to Yellow.
	 *     Ps = 3 4  -> Set foreground color to Blue.
	 *     Ps = 3 5  -> Set foreground color to Magenta.
	 *     Ps = 3 6  -> Set foreground color to Cyan.
	 *     Ps = 3 7  -> Set foreground color to White.
	 *     Ps = 3 9  -> Set foreground color to default (original).
	 *     Ps = 4 0  -> Set background color to Black.
	 *     Ps = 4 1  -> Set background color to Red.
	 *     Ps = 4 2  -> Set background color to Green.
	 *     Ps = 4 3  -> Set background color to Yellow.
	 *     Ps = 4 4  -> Set background color to Blue.
	 *     Ps = 4 5  -> Set background color to Magenta.
	 *     Ps = 4 6  -> Set background color to Cyan.
	 *     Ps = 4 7  -> Set background color to White.
	 *     Ps = 4 9  -> Set background color to default (original).
	 *
	 *   If 16-color support is compiled, the following apply.  Assume
	 *   that xterm's resources are set so that the ISO color codes are
	 *   the first 8 of a set of 16.  Then the aixterm colors are the
	 *   bright versions of the ISO colors:
	 *     Ps = 9 0  -> Set foreground color to Black.
	 *     Ps = 9 1  -> Set foreground color to Red.
	 *     Ps = 9 2  -> Set foreground color to Green.
	 *     Ps = 9 3  -> Set foreground color to Yellow.
	 *     Ps = 9 4  -> Set foreground color to Blue.
	 *     Ps = 9 5  -> Set foreground color to Magenta.
	 *     Ps = 9 6  -> Set foreground color to Cyan.
	 *     Ps = 9 7  -> Set foreground color to White.
	 *     Ps = 1 0 0  -> Set background color to Black.
	 *     Ps = 1 0 1  -> Set background color to Red.
	 *     Ps = 1 0 2  -> Set background color to Green.
	 *     Ps = 1 0 3  -> Set background color to Yellow.
	 *     Ps = 1 0 4  -> Set background color to Blue.
	 *     Ps = 1 0 5  -> Set background color to Magenta.
	 *     Ps = 1 0 6  -> Set background color to Cyan.
	 *     Ps = 1 0 7  -> Set background color to White.
	 *
	 *   If xterm is compiled with the 16-color support disabled, it
	 *   supports the following, from rxvt:
	 *     Ps = 1 0 0  -> Set foreground and background color to
	 *     default.
	 *
	 *   If 88- or 256-color support is compiled, the following apply.
	 *     Ps = 3 8  ; 5  ; Ps -> Set foreground color to the second
	 *     Ps.
	 *     Ps = 4 8  ; 5  ; Ps -> Set background color to the second
	 *     Ps.
	 */Terminal.prototype.charAttributes=function(params){// Optimize a single SGR0.
	if(params.length===1&&params[0]===0){this.curAttr=this.defAttr;return;}var l=params.length,i=0,flags=this.curAttr>>18,fg=this.curAttr>>9&0x1ff,bg=this.curAttr&0x1ff,p;for(;i<l;i++){p=params[i];if(p>=30&&p<=37){// fg color 8
	fg=p-30;}else if(p>=40&&p<=47){// bg color 8
	bg=p-40;}else if(p>=90&&p<=97){// fg color 16
	p+=8;fg=p-90;}else if(p>=100&&p<=107){// bg color 16
	p+=8;bg=p-100;}else if(p===0){// default
	flags=this.defAttr>>18;fg=this.defAttr>>9&0x1ff;bg=this.defAttr&0x1ff;// flags = 0;
	// fg = 0x1ff;
	// bg = 0x1ff;
	}else if(p===1){// bold text
	flags|=1;}else if(p===4){// underlined text
	flags|=2;}else if(p===5){// blink
	flags|=4;}else if(p===7){// inverse and positive
	// test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m'
	flags|=8;}else if(p===8){// invisible
	flags|=16;}else if(p===22){// not bold
	flags&=~1;}else if(p===24){// not underlined
	flags&=~2;}else if(p===25){// not blink
	flags&=~4;}else if(p===27){// not inverse
	flags&=~8;}else if(p===28){// not invisible
	flags&=~16;}else if(p===39){// reset fg
	fg=this.defAttr>>9&0x1ff;}else if(p===49){// reset bg
	bg=this.defAttr&0x1ff;}else if(p===38){// fg color 256
	if(params[i+1]===2){i+=2;fg=matchColor(params[i]&0xff,params[i+1]&0xff,params[i+2]&0xff);if(fg===-1)fg=0x1ff;i+=2;}else if(params[i+1]===5){i+=2;p=params[i]&0xff;fg=p;}}else if(p===48){// bg color 256
	if(params[i+1]===2){i+=2;bg=matchColor(params[i]&0xff,params[i+1]&0xff,params[i+2]&0xff);if(bg===-1)bg=0x1ff;i+=2;}else if(params[i+1]===5){i+=2;p=params[i]&0xff;bg=p;}}else if(p===100){// reset fg/bg
	fg=this.defAttr>>9&0x1ff;bg=this.defAttr&0x1ff;}else{this.error('Unknown SGR attribute: %d.',p);}}this.curAttr=flags<<18|fg<<9|bg;};/**
	 * CSI Ps n  Device Status Report (DSR).
	 *     Ps = 5  -> Status Report.  Result (``OK'') is
	 *   CSI 0 n
	 *     Ps = 6  -> Report Cursor Position (CPR) [row;column].
	 *   Result is
	 *   CSI r ; c R
	 * CSI ? Ps n
	 *   Device Status Report (DSR, DEC-specific).
	 *     Ps = 6  -> Report Cursor Position (CPR) [row;column] as CSI
	 *     ? r ; c R (assumes page is zero).
	 *     Ps = 1 5  -> Report Printer status as CSI ? 1 0  n  (ready).
	 *     or CSI ? 1 1  n  (not ready).
	 *     Ps = 2 5  -> Report UDK status as CSI ? 2 0  n  (unlocked)
	 *     or CSI ? 2 1  n  (locked).
	 *     Ps = 2 6  -> Report Keyboard status as
	 *   CSI ? 2 7  ;  1  ;  0  ;  0  n  (North American).
	 *   The last two parameters apply to VT400 & up, and denote key-
	 *   board ready and LK01 respectively.
	 *     Ps = 5 3  -> Report Locator status as
	 *   CSI ? 5 3  n  Locator available, if compiled-in, or
	 *   CSI ? 5 0  n  No Locator, if not.
	 */Terminal.prototype.deviceStatus=function(params){if(!this.prefix){switch(params[0]){case 5:// status report
	this.send('\x1b[0n');break;case 6:// cursor position
	this.send('\x1b['+(this.y+1)+';'+(this.x+1)+'R');break;}}else if(this.prefix==='?'){// modern xterm doesnt seem to
	// respond to any of these except ?6, 6, and 5
	switch(params[0]){case 6:// cursor position
	this.send('\x1b[?'+(this.y+1)+';'+(this.x+1)+'R');break;case 15:// no printer
	// this.send('\x1b[?11n');
	break;case 25:// dont support user defined keys
	// this.send('\x1b[?21n');
	break;case 26:// north american keyboard
	// this.send('\x1b[?27;1;0;0n');
	break;case 53:// no dec locator/mouse
	// this.send('\x1b[?50n');
	break;}}};/**
	 * Additions
	 *//**
	 * CSI Ps @
	 * Insert Ps (Blank) Character(s) (default = 1) (ICH).
	 */Terminal.prototype.insertChars=function(params){var param,row,j,ch;param=params[0];if(param<1)param=1;row=this.y+this.ybase;j=this.x;ch=[this.eraseAttr(),' ',1];// xterm
	while(param--&&j<this.cols){this.lines[row].splice(j++,0,ch);this.lines[row].pop();}};/**
	 * CSI Ps E
	 * Cursor Next Line Ps Times (default = 1) (CNL).
	 * same as CSI Ps B ?
	 */Terminal.prototype.cursorNextLine=function(params){var param=params[0];if(param<1)param=1;this.y+=param;if(this.y>=this.rows){this.y=this.rows-1;}this.x=0;};/**
	 * CSI Ps F
	 * Cursor Preceding Line Ps Times (default = 1) (CNL).
	 * reuse CSI Ps A ?
	 */Terminal.prototype.cursorPrecedingLine=function(params){var param=params[0];if(param<1)param=1;this.y-=param;if(this.y<0)this.y=0;this.x=0;};/**
	 * CSI Ps G
	 * Cursor Character Absolute  [column] (default = [row,1]) (CHA).
	 */Terminal.prototype.cursorCharAbsolute=function(params){var param=params[0];if(param<1)param=1;this.x=param-1;};/**
	 * CSI Ps L
	 * Insert Ps Line(s) (default = 1) (IL).
	 */Terminal.prototype.insertLines=function(params){var param,row,j;param=params[0];if(param<1)param=1;row=this.y+this.ybase;j=this.rows-1-this.scrollBottom;j=this.rows-1+this.ybase-j+1;while(param--){// test: echo -e '\e[44m\e[1L\e[0m'
	// blankLine(true) - xterm/linux behavior
	this.lines.splice(row,0,this.blankLine(true));this.lines.splice(j,1);}// this.maxRange();
	this.updateRange(this.y);this.updateRange(this.scrollBottom);};/**
	 * CSI Ps M
	 * Delete Ps Line(s) (default = 1) (DL).
	 */Terminal.prototype.deleteLines=function(params){var param,row,j;param=params[0];if(param<1)param=1;row=this.y+this.ybase;j=this.rows-1-this.scrollBottom;j=this.rows-1+this.ybase-j;while(param--){// test: echo -e '\e[44m\e[1M\e[0m'
	// blankLine(true) - xterm/linux behavior
	this.lines.splice(j+1,0,this.blankLine(true));this.lines.splice(row,1);}// this.maxRange();
	this.updateRange(this.y);this.updateRange(this.scrollBottom);};/**
	 * CSI Ps P
	 * Delete Ps Character(s) (default = 1) (DCH).
	 */Terminal.prototype.deleteChars=function(params){var param,row,ch;param=params[0];if(param<1)param=1;row=this.y+this.ybase;ch=[this.eraseAttr(),' ',1];// xterm
	while(param--){this.lines[row].splice(this.x,1);this.lines[row].push(ch);}};/**
	 * CSI Ps X
	 * Erase Ps Character(s) (default = 1) (ECH).
	 */Terminal.prototype.eraseChars=function(params){var param,row,j,ch;param=params[0];if(param<1)param=1;row=this.y+this.ybase;j=this.x;ch=[this.eraseAttr(),' ',1];// xterm
	while(param--&&j<this.cols){this.lines[row][j++]=ch;}};/**
	 * CSI Pm `  Character Position Absolute
	 *   [column] (default = [row,1]) (HPA).
	 */Terminal.prototype.charPosAbsolute=function(params){var param=params[0];if(param<1)param=1;this.x=param-1;if(this.x>=this.cols){this.x=this.cols-1;}};/**
	 * 141 61 a * HPR -
	 * Horizontal Position Relative
	 * reuse CSI Ps C ?
	 */Terminal.prototype.HPositionRelative=function(params){var param=params[0];if(param<1)param=1;this.x+=param;if(this.x>=this.cols){this.x=this.cols-1;}};/**
	 * CSI Ps c  Send Device Attributes (Primary DA).
	 *     Ps = 0  or omitted -> request attributes from terminal.  The
	 *     response depends on the decTerminalID resource setting.
	 *     -> CSI ? 1 ; 2 c  (``VT100 with Advanced Video Option'')
	 *     -> CSI ? 1 ; 0 c  (``VT101 with No Options'')
	 *     -> CSI ? 6 c  (``VT102'')
	 *     -> CSI ? 6 0 ; 1 ; 2 ; 6 ; 8 ; 9 ; 1 5 ; c  (``VT220'')
	 *   The VT100-style response parameters do not mean anything by
	 *   themselves.  VT220 parameters do, telling the host what fea-
	 *   tures the terminal supports:
	 *     Ps = 1  -> 132-columns.
	 *     Ps = 2  -> Printer.
	 *     Ps = 6  -> Selective erase.
	 *     Ps = 8  -> User-defined keys.
	 *     Ps = 9  -> National replacement character sets.
	 *     Ps = 1 5  -> Technical characters.
	 *     Ps = 2 2  -> ANSI color, e.g., VT525.
	 *     Ps = 2 9  -> ANSI text locator (i.e., DEC Locator mode).
	 * CSI > Ps c
	 *   Send Device Attributes (Secondary DA).
	 *     Ps = 0  or omitted -> request the terminal's identification
	 *     code.  The response depends on the decTerminalID resource set-
	 *     ting.  It should apply only to VT220 and up, but xterm extends
	 *     this to VT100.
	 *     -> CSI  > Pp ; Pv ; Pc c
	 *   where Pp denotes the terminal type
	 *     Pp = 0  -> ``VT100''.
	 *     Pp = 1  -> ``VT220''.
	 *   and Pv is the firmware version (for xterm, this was originally
	 *   the XFree86 patch number, starting with 95).  In a DEC termi-
	 *   nal, Pc indicates the ROM cartridge registration number and is
	 *   always zero.
	 * More information:
	 *   xterm/charproc.c - line 2012, for more information.
	 *   vim responds with ^[[?0c or ^[[?1c after the terminal's response (?)
	 */Terminal.prototype.sendDeviceAttributes=function(params){if(params[0]>0)return;if(!this.prefix){if(this.is('xterm')||this.is('rxvt-unicode')||this.is('screen')){this.send('\x1b[?1;2c');}else if(this.is('linux')){this.send('\x1b[?6c');}}else if(this.prefix==='>'){// xterm and urxvt
	// seem to spit this
	// out around ~370 times (?).
	if(this.is('xterm')){this.send('\x1b[>0;276;0c');}else if(this.is('rxvt-unicode')){this.send('\x1b[>85;95;0c');}else if(this.is('linux')){// not supported by linux console.
	// linux console echoes parameters.
	this.send(params[0]+'c');}else if(this.is('screen')){this.send('\x1b[>83;40003;0c');}}};/**
	 * CSI Pm d
	 * Line Position Absolute  [row] (default = [1,column]) (VPA).
	 */Terminal.prototype.linePosAbsolute=function(params){var param=params[0];if(param<1)param=1;this.y=param-1;if(this.y>=this.rows){this.y=this.rows-1;}};/**
	 * 145 65 e * VPR - Vertical Position Relative
	 * reuse CSI Ps B ?
	 */Terminal.prototype.VPositionRelative=function(params){var param=params[0];if(param<1)param=1;this.y+=param;if(this.y>=this.rows){this.y=this.rows-1;}};/**
	 * CSI Ps ; Ps f
	 *   Horizontal and Vertical Position [row;column] (default =
	 *   [1,1]) (HVP).
	 */Terminal.prototype.HVPosition=function(params){if(params[0]<1)params[0]=1;if(params[1]<1)params[1]=1;this.y=params[0]-1;if(this.y>=this.rows){this.y=this.rows-1;}this.x=params[1]-1;if(this.x>=this.cols){this.x=this.cols-1;}};/**
	 * CSI Pm h  Set Mode (SM).
	 *     Ps = 2  -> Keyboard Action Mode (AM).
	 *     Ps = 4  -> Insert Mode (IRM).
	 *     Ps = 1 2  -> Send/receive (SRM).
	 *     Ps = 2 0  -> Automatic Newline (LNM).
	 * CSI ? Pm h
	 *   DEC Private Mode Set (DECSET).
	 *     Ps = 1  -> Application Cursor Keys (DECCKM).
	 *     Ps = 2  -> Designate USASCII for character sets G0-G3
	 *     (DECANM), and set VT100 mode.
	 *     Ps = 3  -> 132 Column Mode (DECCOLM).
	 *     Ps = 4  -> Smooth (Slow) Scroll (DECSCLM).
	 *     Ps = 5  -> Reverse Video (DECSCNM).
	 *     Ps = 6  -> Origin Mode (DECOM).
	 *     Ps = 7  -> Wraparound Mode (DECAWM).
	 *     Ps = 8  -> Auto-repeat Keys (DECARM).
	 *     Ps = 9  -> Send Mouse X & Y on button press.  See the sec-
	 *     tion Mouse Tracking.
	 *     Ps = 1 0  -> Show toolbar (rxvt).
	 *     Ps = 1 2  -> Start Blinking Cursor (att610).
	 *     Ps = 1 8  -> Print form feed (DECPFF).
	 *     Ps = 1 9  -> Set print extent to full screen (DECPEX).
	 *     Ps = 2 5  -> Show Cursor (DECTCEM).
	 *     Ps = 3 0  -> Show scrollbar (rxvt).
	 *     Ps = 3 5  -> Enable font-shifting functions (rxvt).
	 *     Ps = 3 8  -> Enter Tektronix Mode (DECTEK).
	 *     Ps = 4 0  -> Allow 80 -> 132 Mode.
	 *     Ps = 4 1  -> more(1) fix (see curses resource).
	 *     Ps = 4 2  -> Enable Nation Replacement Character sets (DECN-
	 *     RCM).
	 *     Ps = 4 4  -> Turn On Margin Bell.
	 *     Ps = 4 5  -> Reverse-wraparound Mode.
	 *     Ps = 4 6  -> Start Logging.  This is normally disabled by a
	 *     compile-time option.
	 *     Ps = 4 7  -> Use Alternate Screen Buffer.  (This may be dis-
	 *     abled by the titeInhibit resource).
	 *     Ps = 6 6  -> Application keypad (DECNKM).
	 *     Ps = 6 7  -> Backarrow key sends backspace (DECBKM).
	 *     Ps = 1 0 0 0  -> Send Mouse X & Y on button press and
	 *     release.  See the section Mouse Tracking.
	 *     Ps = 1 0 0 1  -> Use Hilite Mouse Tracking.
	 *     Ps = 1 0 0 2  -> Use Cell Motion Mouse Tracking.
	 *     Ps = 1 0 0 3  -> Use All Motion Mouse Tracking.
	 *     Ps = 1 0 0 4  -> Send FocusIn/FocusOut events.
	 *     Ps = 1 0 0 5  -> Enable Extended Mouse Mode.
	 *     Ps = 1 0 1 0  -> Scroll to bottom on tty output (rxvt).
	 *     Ps = 1 0 1 1  -> Scroll to bottom on key press (rxvt).
	 *     Ps = 1 0 3 4  -> Interpret "meta" key, sets eighth bit.
	 *     (enables the eightBitInput resource).
	 *     Ps = 1 0 3 5  -> Enable special modifiers for Alt and Num-
	 *     Lock keys.  (This enables the numLock resource).
	 *     Ps = 1 0 3 6  -> Send ESC   when Meta modifies a key.  (This
	 *     enables the metaSendsEscape resource).
	 *     Ps = 1 0 3 7  -> Send DEL from the editing-keypad Delete
	 *     key.
	 *     Ps = 1 0 3 9  -> Send ESC  when Alt modifies a key.  (This
	 *     enables the altSendsEscape resource).
	 *     Ps = 1 0 4 0  -> Keep selection even if not highlighted.
	 *     (This enables the keepSelection resource).
	 *     Ps = 1 0 4 1  -> Use the CLIPBOARD selection.  (This enables
	 *     the selectToClipboard resource).
	 *     Ps = 1 0 4 2  -> Enable Urgency window manager hint when
	 *     Control-G is received.  (This enables the bellIsUrgent
	 *     resource).
	 *     Ps = 1 0 4 3  -> Enable raising of the window when Control-G
	 *     is received.  (enables the popOnBell resource).
	 *     Ps = 1 0 4 7  -> Use Alternate Screen Buffer.  (This may be
	 *     disabled by the titeInhibit resource).
	 *     Ps = 1 0 4 8  -> Save cursor as in DECSC.  (This may be dis-
	 *     abled by the titeInhibit resource).
	 *     Ps = 1 0 4 9  -> Save cursor as in DECSC and use Alternate
	 *     Screen Buffer, clearing it first.  (This may be disabled by
	 *     the titeInhibit resource).  This combines the effects of the 1
	 *     0 4 7  and 1 0 4 8  modes.  Use this with terminfo-based
	 *     applications rather than the 4 7  mode.
	 *     Ps = 1 0 5 0  -> Set terminfo/termcap function-key mode.
	 *     Ps = 1 0 5 1  -> Set Sun function-key mode.
	 *     Ps = 1 0 5 2  -> Set HP function-key mode.
	 *     Ps = 1 0 5 3  -> Set SCO function-key mode.
	 *     Ps = 1 0 6 0  -> Set legacy keyboard emulation (X11R6).
	 *     Ps = 1 0 6 1  -> Set VT220 keyboard emulation.
	 *     Ps = 2 0 0 4  -> Set bracketed paste mode.
	 * Modes:
	 *   http: *vt100.net/docs/vt220-rm/chapter4.html
	 */Terminal.prototype.setMode=function(params){if((typeof params==='undefined'?'undefined':_typeof(params))==='object'){var l=params.length,i=0;for(;i<l;i++){this.setMode(params[i]);}return;}if(!this.prefix){switch(params){case 4:this.insertMode=true;break;case 20://this.convertEol = true;
	break;}}else if(this.prefix==='?'){switch(params){case 1:this.applicationCursor=true;break;case 2:this.setgCharset(0,Terminal.charsets.US);this.setgCharset(1,Terminal.charsets.US);this.setgCharset(2,Terminal.charsets.US);this.setgCharset(3,Terminal.charsets.US);// set VT100 mode here
	break;case 3:// 132 col mode
	this.savedCols=this.cols;this.resize(132,this.rows);break;case 6:this.originMode=true;break;case 7:this.wraparoundMode=true;break;case 12:// this.cursorBlink = true;
	break;case 66:this.log('Serial port requested application keypad.');this.applicationKeypad=true;this.viewport.syncScrollArea();break;case 9:// X10 Mouse
	// no release, no motion, no wheel, no modifiers.
	case 1000:// vt200 mouse
	// no motion.
	// no modifiers, except control on the wheel.
	case 1002:// button event mouse
	case 1003:// any event mouse
	// any event - sends motion events,
	// even if there is no button held down.
	this.x10Mouse=params===9;this.vt200Mouse=params===1000;this.normalMouse=params>1000;this.mouseEvents=true;this.element.style.cursor='default';this.log('Binding to mouse events.');break;case 1004:// send focusin/focusout events
	// focusin: ^[[I
	// focusout: ^[[O
	this.sendFocus=true;break;case 1005:// utf8 ext mode mouse
	this.utfMouse=true;// for wide terminals
	// simply encodes large values as utf8 characters
	break;case 1006:// sgr ext mode mouse
	this.sgrMouse=true;// for wide terminals
	// does not add 32 to fields
	// press: ^[[<b;x;yM
	// release: ^[[<b;x;ym
	break;case 1015:// urxvt ext mode mouse
	this.urxvtMouse=true;// for wide terminals
	// numbers for fields
	// press: ^[[b;x;yM
	// motion: ^[[b;x;yT
	break;case 25:// show cursor
	this.cursorHidden=false;break;case 1049:// alt screen buffer cursor
	//this.saveCursor();
	;// FALL-THROUGH
	case 47:// alt screen buffer
	case 1047:// alt screen buffer
	if(!this.normal){var normal={lines:this.lines,ybase:this.ybase,ydisp:this.ydisp,x:this.x,y:this.y,scrollTop:this.scrollTop,scrollBottom:this.scrollBottom,tabs:this.tabs// XXX save charset(s) here?
	// charset: this.charset,
	// glevel: this.glevel,
	// charsets: this.charsets
	};this.reset();this.normal=normal;this.showCursor();}break;}}};/**
	 * CSI Pm l  Reset Mode (RM).
	 *     Ps = 2  -> Keyboard Action Mode (AM).
	 *     Ps = 4  -> Replace Mode (IRM).
	 *     Ps = 1 2  -> Send/receive (SRM).
	 *     Ps = 2 0  -> Normal Linefeed (LNM).
	 * CSI ? Pm l
	 *   DEC Private Mode Reset (DECRST).
	 *     Ps = 1  -> Normal Cursor Keys (DECCKM).
	 *     Ps = 2  -> Designate VT52 mode (DECANM).
	 *     Ps = 3  -> 80 Column Mode (DECCOLM).
	 *     Ps = 4  -> Jump (Fast) Scroll (DECSCLM).
	 *     Ps = 5  -> Normal Video (DECSCNM).
	 *     Ps = 6  -> Normal Cursor Mode (DECOM).
	 *     Ps = 7  -> No Wraparound Mode (DECAWM).
	 *     Ps = 8  -> No Auto-repeat Keys (DECARM).
	 *     Ps = 9  -> Don't send Mouse X & Y on button press.
	 *     Ps = 1 0  -> Hide toolbar (rxvt).
	 *     Ps = 1 2  -> Stop Blinking Cursor (att610).
	 *     Ps = 1 8  -> Don't print form feed (DECPFF).
	 *     Ps = 1 9  -> Limit print to scrolling region (DECPEX).
	 *     Ps = 2 5  -> Hide Cursor (DECTCEM).
	 *     Ps = 3 0  -> Don't show scrollbar (rxvt).
	 *     Ps = 3 5  -> Disable font-shifting functions (rxvt).
	 *     Ps = 4 0  -> Disallow 80 -> 132 Mode.
	 *     Ps = 4 1  -> No more(1) fix (see curses resource).
	 *     Ps = 4 2  -> Disable Nation Replacement Character sets (DEC-
	 *     NRCM).
	 *     Ps = 4 4  -> Turn Off Margin Bell.
	 *     Ps = 4 5  -> No Reverse-wraparound Mode.
	 *     Ps = 4 6  -> Stop Logging.  (This is normally disabled by a
	 *     compile-time option).
	 *     Ps = 4 7  -> Use Normal Screen Buffer.
	 *     Ps = 6 6  -> Numeric keypad (DECNKM).
	 *     Ps = 6 7  -> Backarrow key sends delete (DECBKM).
	 *     Ps = 1 0 0 0  -> Don't send Mouse X & Y on button press and
	 *     release.  See the section Mouse Tracking.
	 *     Ps = 1 0 0 1  -> Don't use Hilite Mouse Tracking.
	 *     Ps = 1 0 0 2  -> Don't use Cell Motion Mouse Tracking.
	 *     Ps = 1 0 0 3  -> Don't use All Motion Mouse Tracking.
	 *     Ps = 1 0 0 4  -> Don't send FocusIn/FocusOut events.
	 *     Ps = 1 0 0 5  -> Disable Extended Mouse Mode.
	 *     Ps = 1 0 1 0  -> Don't scroll to bottom on tty output
	 *     (rxvt).
	 *     Ps = 1 0 1 1  -> Don't scroll to bottom on key press (rxvt).
	 *     Ps = 1 0 3 4  -> Don't interpret "meta" key.  (This disables
	 *     the eightBitInput resource).
	 *     Ps = 1 0 3 5  -> Disable special modifiers for Alt and Num-
	 *     Lock keys.  (This disables the numLock resource).
	 *     Ps = 1 0 3 6  -> Don't send ESC  when Meta modifies a key.
	 *     (This disables the metaSendsEscape resource).
	 *     Ps = 1 0 3 7  -> Send VT220 Remove from the editing-keypad
	 *     Delete key.
	 *     Ps = 1 0 3 9  -> Don't send ESC  when Alt modifies a key.
	 *     (This disables the altSendsEscape resource).
	 *     Ps = 1 0 4 0  -> Do not keep selection when not highlighted.
	 *     (This disables the keepSelection resource).
	 *     Ps = 1 0 4 1  -> Use the PRIMARY selection.  (This disables
	 *     the selectToClipboard resource).
	 *     Ps = 1 0 4 2  -> Disable Urgency window manager hint when
	 *     Control-G is received.  (This disables the bellIsUrgent
	 *     resource).
	 *     Ps = 1 0 4 3  -> Disable raising of the window when Control-
	 *     G is received.  (This disables the popOnBell resource).
	 *     Ps = 1 0 4 7  -> Use Normal Screen Buffer, clearing screen
	 *     first if in the Alternate Screen.  (This may be disabled by
	 *     the titeInhibit resource).
	 *     Ps = 1 0 4 8  -> Restore cursor as in DECRC.  (This may be
	 *     disabled by the titeInhibit resource).
	 *     Ps = 1 0 4 9  -> Use Normal Screen Buffer and restore cursor
	 *     as in DECRC.  (This may be disabled by the titeInhibit
	 *     resource).  This combines the effects of the 1 0 4 7  and 1 0
	 *     4 8  modes.  Use this with terminfo-based applications rather
	 *     than the 4 7  mode.
	 *     Ps = 1 0 5 0  -> Reset terminfo/termcap function-key mode.
	 *     Ps = 1 0 5 1  -> Reset Sun function-key mode.
	 *     Ps = 1 0 5 2  -> Reset HP function-key mode.
	 *     Ps = 1 0 5 3  -> Reset SCO function-key mode.
	 *     Ps = 1 0 6 0  -> Reset legacy keyboard emulation (X11R6).
	 *     Ps = 1 0 6 1  -> Reset keyboard emulation to Sun/PC style.
	 *     Ps = 2 0 0 4  -> Reset bracketed paste mode.
	 */Terminal.prototype.resetMode=function(params){if((typeof params==='undefined'?'undefined':_typeof(params))==='object'){var l=params.length,i=0;for(;i<l;i++){this.resetMode(params[i]);}return;}if(!this.prefix){switch(params){case 4:this.insertMode=false;break;case 20://this.convertEol = false;
	break;}}else if(this.prefix==='?'){switch(params){case 1:this.applicationCursor=false;break;case 3:if(this.cols===132&&this.savedCols){this.resize(this.savedCols,this.rows);}delete this.savedCols;break;case 6:this.originMode=false;break;case 7:this.wraparoundMode=false;break;case 12:// this.cursorBlink = false;
	break;case 66:this.log('Switching back to normal keypad.');this.applicationKeypad=false;this.viewport.syncScrollArea();break;case 9:// X10 Mouse
	case 1000:// vt200 mouse
	case 1002:// button event mouse
	case 1003:// any event mouse
	this.x10Mouse=false;this.vt200Mouse=false;this.normalMouse=false;this.mouseEvents=false;this.element.style.cursor='';break;case 1004:// send focusin/focusout events
	this.sendFocus=false;break;case 1005:// utf8 ext mode mouse
	this.utfMouse=false;break;case 1006:// sgr ext mode mouse
	this.sgrMouse=false;break;case 1015:// urxvt ext mode mouse
	this.urxvtMouse=false;break;case 25:// hide cursor
	this.cursorHidden=true;break;case 1049:// alt screen buffer cursor
	;// FALL-THROUGH
	case 47:// normal screen buffer
	case 1047:// normal screen buffer - clearing it first
	if(this.normal){this.lines=this.normal.lines;this.ybase=this.normal.ybase;this.ydisp=this.normal.ydisp;this.x=this.normal.x;this.y=this.normal.y;this.scrollTop=this.normal.scrollTop;this.scrollBottom=this.normal.scrollBottom;this.tabs=this.normal.tabs;this.normal=null;// if (params === 1049) {
	//   this.x = this.savedX;
	//   this.y = this.savedY;
	// }
	this.refresh(0,this.rows-1);this.showCursor();}break;}}};/**
	 * CSI Ps ; Ps r
	 *   Set Scrolling Region [top;bottom] (default = full size of win-
	 *   dow) (DECSTBM).
	 * CSI ? Pm r
	 */Terminal.prototype.setScrollRegion=function(params){if(this.prefix)return;this.scrollTop=(params[0]||1)-1;this.scrollBottom=(params[1]||this.rows)-1;this.x=0;this.y=0;};/**
	 * CSI s
	 *   Save cursor (ANSI.SYS).
	 */Terminal.prototype.saveCursor=function(params){this.savedX=this.x;this.savedY=this.y;};/**
	 * CSI u
	 *   Restore cursor (ANSI.SYS).
	 */Terminal.prototype.restoreCursor=function(params){this.x=this.savedX||0;this.y=this.savedY||0;};/**
	 * Lesser Used
	 *//**
	 * CSI Ps I
	 *   Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).
	 */Terminal.prototype.cursorForwardTab=function(params){var param=params[0]||1;while(param--){this.x=this.nextStop();}};/**
	 * CSI Ps S  Scroll up Ps lines (default = 1) (SU).
	 */Terminal.prototype.scrollUp=function(params){var param=params[0]||1;while(param--){this.lines.splice(this.ybase+this.scrollTop,1);this.lines.splice(this.ybase+this.scrollBottom,0,this.blankLine());}// this.maxRange();
	this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);};/**
	     * CSI Ps T  Scroll down Ps lines (default = 1) (SD).
	     */Terminal.prototype.scrollDown=function(params){var param=params[0]||1;while(param--){this.lines.splice(this.ybase+this.scrollBottom,1);this.lines.splice(this.ybase+this.scrollTop,0,this.blankLine());}// this.maxRange();
	this.updateRange(this.scrollTop);this.updateRange(this.scrollBottom);};/**
	 * CSI Ps ; Ps ; Ps ; Ps ; Ps T
	 *   Initiate highlight mouse tracking.  Parameters are
	 *   [func;startx;starty;firstrow;lastrow].  See the section Mouse
	 *   Tracking.
	 */Terminal.prototype.initMouseTracking=function(params){// Relevant: DECSET 1001
	};/**
	 * CSI > Ps; Ps T
	 *   Reset one or more features of the title modes to the default
	 *   value.  Normally, "reset" disables the feature.  It is possi-
	 *   ble to disable the ability to reset features by compiling a
	 *   different default for the title modes into xterm.
	 *     Ps = 0  -> Do not set window/icon labels using hexadecimal.
	 *     Ps = 1  -> Do not query window/icon labels using hexadeci-
	 *     mal.
	 *     Ps = 2  -> Do not set window/icon labels using UTF-8.
	 *     Ps = 3  -> Do not query window/icon labels using UTF-8.
	 *   (See discussion of "Title Modes").
	 */Terminal.prototype.resetTitleModes=function(params){;};/**
	 * CSI Ps Z  Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).
	 */Terminal.prototype.cursorBackwardTab=function(params){var param=params[0]||1;while(param--){this.x=this.prevStop();}};/**
	 * CSI Ps b  Repeat the preceding graphic character Ps times (REP).
	 */Terminal.prototype.repeatPrecedingCharacter=function(params){var param=params[0]||1,line=this.lines[this.ybase+this.y],ch=line[this.x-1]||[this.defAttr,' ',1];while(param--){line[this.x++]=ch;}};/**
	 * CSI Ps g  Tab Clear (TBC).
	 *     Ps = 0  -> Clear Current Column (default).
	 *     Ps = 3  -> Clear All.
	 * Potentially:
	 *   Ps = 2  -> Clear Stops on Line.
	 *   http://vt100.net/annarbor/aaa-ug/section6.html
	 */Terminal.prototype.tabClear=function(params){var param=params[0];if(param<=0){delete this.tabs[this.x];}else if(param===3){this.tabs={};}};/**
	 * CSI Pm i  Media Copy (MC).
	 *     Ps = 0  -> Print screen (default).
	 *     Ps = 4  -> Turn off printer controller mode.
	 *     Ps = 5  -> Turn on printer controller mode.
	 * CSI ? Pm i
	 *   Media Copy (MC, DEC-specific).
	 *     Ps = 1  -> Print line containing cursor.
	 *     Ps = 4  -> Turn off autoprint mode.
	 *     Ps = 5  -> Turn on autoprint mode.
	 *     Ps = 1  0  -> Print composed display, ignores DECPEX.
	 *     Ps = 1  1  -> Print all pages.
	 */Terminal.prototype.mediaCopy=function(params){;};/**
	 * CSI > Ps; Ps m
	 *   Set or reset resource-values used by xterm to decide whether
	 *   to construct escape sequences holding information about the
	 *   modifiers pressed with a given key.  The first parameter iden-
	 *   tifies the resource to set/reset.  The second parameter is the
	 *   value to assign to the resource.  If the second parameter is
	 *   omitted, the resource is reset to its initial value.
	 *     Ps = 1  -> modifyCursorKeys.
	 *     Ps = 2  -> modifyFunctionKeys.
	 *     Ps = 4  -> modifyOtherKeys.
	 *   If no parameters are given, all resources are reset to their
	 *   initial values.
	 */Terminal.prototype.setResources=function(params){;};/**
	 * CSI > Ps n
	 *   Disable modifiers which may be enabled via the CSI > Ps; Ps m
	 *   sequence.  This corresponds to a resource value of "-1", which
	 *   cannot be set with the other sequence.  The parameter identi-
	 *   fies the resource to be disabled:
	 *     Ps = 1  -> modifyCursorKeys.
	 *     Ps = 2  -> modifyFunctionKeys.
	 *     Ps = 4  -> modifyOtherKeys.
	 *   If the parameter is omitted, modifyFunctionKeys is disabled.
	 *   When modifyFunctionKeys is disabled, xterm uses the modifier
	 *   keys to make an extended sequence of functions rather than
	 *   adding a parameter to each function key to denote the modi-
	 *   fiers.
	 */Terminal.prototype.disableModifiers=function(params){;};/**
	 * CSI > Ps p
	 *   Set resource value pointerMode.  This is used by xterm to
	 *   decide whether to hide the pointer cursor as the user types.
	 *   Valid values for the parameter:
	 *     Ps = 0  -> never hide the pointer.
	 *     Ps = 1  -> hide if the mouse tracking mode is not enabled.
	 *     Ps = 2  -> always hide the pointer.  If no parameter is
	 *     given, xterm uses the default, which is 1 .
	 */Terminal.prototype.setPointerMode=function(params){;};/**
	 * CSI ! p   Soft terminal reset (DECSTR).
	 * http://vt100.net/docs/vt220-rm/table4-10.html
	 */Terminal.prototype.softReset=function(params){this.cursorHidden=false;this.insertMode=false;this.originMode=false;this.wraparoundMode=false;// autowrap
	this.applicationKeypad=false;// ?
	this.viewport.syncScrollArea();this.applicationCursor=false;this.scrollTop=0;this.scrollBottom=this.rows-1;this.curAttr=this.defAttr;this.x=this.y=0;// ?
	this.charset=null;this.glevel=0;// ??
	this.charsets=[null];// ??
	};/**
	 * CSI Ps$ p
	 *   Request ANSI mode (DECRQM).  For VT300 and up, reply is
	 *     CSI Ps; Pm$ y
	 *   where Ps is the mode number as in RM, and Pm is the mode
	 *   value:
	 *     0 - not recognized
	 *     1 - set
	 *     2 - reset
	 *     3 - permanently set
	 *     4 - permanently reset
	 */Terminal.prototype.requestAnsiMode=function(params){;};/**
	 * CSI ? Ps$ p
	 *   Request DEC private mode (DECRQM).  For VT300 and up, reply is
	 *     CSI ? Ps; Pm$ p
	 *   where Ps is the mode number as in DECSET, Pm is the mode value
	 *   as in the ANSI DECRQM.
	 */Terminal.prototype.requestPrivateMode=function(params){;};/**
	 * CSI Ps ; Ps " p
	 *   Set conformance level (DECSCL).  Valid values for the first
	 *   parameter:
	 *     Ps = 6 1  -> VT100.
	 *     Ps = 6 2  -> VT200.
	 *     Ps = 6 3  -> VT300.
	 *   Valid values for the second parameter:
	 *     Ps = 0  -> 8-bit controls.
	 *     Ps = 1  -> 7-bit controls (always set for VT100).
	 *     Ps = 2  -> 8-bit controls.
	 */Terminal.prototype.setConformanceLevel=function(params){;};/**
	 * CSI Ps q  Load LEDs (DECLL).
	 *     Ps = 0  -> Clear all LEDS (default).
	 *     Ps = 1  -> Light Num Lock.
	 *     Ps = 2  -> Light Caps Lock.
	 *     Ps = 3  -> Light Scroll Lock.
	 *     Ps = 2  1  -> Extinguish Num Lock.
	 *     Ps = 2  2  -> Extinguish Caps Lock.
	 *     Ps = 2  3  -> Extinguish Scroll Lock.
	 */Terminal.prototype.loadLEDs=function(params){;};/**
	 * CSI Ps SP q
	 *   Set cursor style (DECSCUSR, VT520).
	 *     Ps = 0  -> blinking block.
	 *     Ps = 1  -> blinking block (default).
	 *     Ps = 2  -> steady block.
	 *     Ps = 3  -> blinking underline.
	 *     Ps = 4  -> steady underline.
	 */Terminal.prototype.setCursorStyle=function(params){;};/**
	 * CSI Ps " q
	 *   Select character protection attribute (DECSCA).  Valid values
	 *   for the parameter:
	 *     Ps = 0  -> DECSED and DECSEL can erase (default).
	 *     Ps = 1  -> DECSED and DECSEL cannot erase.
	 *     Ps = 2  -> DECSED and DECSEL can erase.
	 */Terminal.prototype.setCharProtectionAttr=function(params){;};/**
	 * CSI ? Pm r
	 *   Restore DEC Private Mode Values.  The value of Ps previously
	 *   saved is restored.  Ps values are the same as for DECSET.
	 */Terminal.prototype.restorePrivateValues=function(params){;};/**
	 * CSI Pt; Pl; Pb; Pr; Ps$ r
	 *   Change Attributes in Rectangular Area (DECCARA), VT400 and up.
	 *     Pt; Pl; Pb; Pr denotes the rectangle.
	 *     Ps denotes the SGR attributes to change: 0, 1, 4, 5, 7.
	 * NOTE: xterm doesn't enable this code by default.
	 */Terminal.prototype.setAttrInRectangle=function(params){var t=params[0],l=params[1],b=params[2],r=params[3],attr=params[4];var line,i;for(;t<b+1;t++){line=this.lines[this.ybase+t];for(i=l;i<r;i++){line[i]=[attr,line[i][1]];}}// this.maxRange();
	this.updateRange(params[0]);this.updateRange(params[2]);};/**
	 * CSI Pc; Pt; Pl; Pb; Pr$ x
	 *   Fill Rectangular Area (DECFRA), VT420 and up.
	 *     Pc is the character to use.
	 *     Pt; Pl; Pb; Pr denotes the rectangle.
	 * NOTE: xterm doesn't enable this code by default.
	 */Terminal.prototype.fillRectangle=function(params){var ch=params[0],t=params[1],l=params[2],b=params[3],r=params[4];var line,i;for(;t<b+1;t++){line=this.lines[this.ybase+t];for(i=l;i<r;i++){line[i]=[line[i][0],String.fromCharCode(ch)];}}// this.maxRange();
	this.updateRange(params[1]);this.updateRange(params[3]);};/**
	 * CSI Ps ; Pu ' z
	 *   Enable Locator Reporting (DECELR).
	 *   Valid values for the first parameter:
	 *     Ps = 0  -> Locator disabled (default).
	 *     Ps = 1  -> Locator enabled.
	 *     Ps = 2  -> Locator enabled for one report, then disabled.
	 *   The second parameter specifies the coordinate unit for locator
	 *   reports.
	 *   Valid values for the second parameter:
	 *     Pu = 0  <- or omitted -> default to character cells.
	 *     Pu = 1  <- device physical pixels.
	 *     Pu = 2  <- character cells.
	 */Terminal.prototype.enableLocatorReporting=function(params){var val=params[0]>0;//this.mouseEvents = val;
	//this.decLocator = val;
	};/**
	 * CSI Pt; Pl; Pb; Pr$ z
	 *   Erase Rectangular Area (DECERA), VT400 and up.
	 *     Pt; Pl; Pb; Pr denotes the rectangle.
	 * NOTE: xterm doesn't enable this code by default.
	 */Terminal.prototype.eraseRectangle=function(params){var t=params[0],l=params[1],b=params[2],r=params[3];var line,i,ch;ch=[this.eraseAttr(),' ',1];// xterm?
	for(;t<b+1;t++){line=this.lines[this.ybase+t];for(i=l;i<r;i++){line[i]=ch;}}// this.maxRange();
	this.updateRange(params[0]);this.updateRange(params[2]);};/**
	 * CSI P m SP }
	 * Insert P s Column(s) (default = 1) (DECIC), VT420 and up.
	 * NOTE: xterm doesn't enable this code by default.
	 */Terminal.prototype.insertColumns=function(){var param=params[0],l=this.ybase+this.rows,ch=[this.eraseAttr(),' ',1]// xterm?
	,i;while(param--){for(i=this.ybase;i<l;i++){this.lines[i].splice(this.x+1,0,ch);this.lines[i].pop();}}this.maxRange();};/**
	 * CSI P m SP ~
	 * Delete P s Column(s) (default = 1) (DECDC), VT420 and up
	 * NOTE: xterm doesn't enable this code by default.
	 */Terminal.prototype.deleteColumns=function(){var param=params[0],l=this.ybase+this.rows,ch=[this.eraseAttr(),' ',1]// xterm?
	,i;while(param--){for(i=this.ybase;i<l;i++){this.lines[i].splice(this.x,1);this.lines[i].push(ch);}}this.maxRange();};/**
	 * Character Sets
	 */Terminal.charsets={};// DEC Special Character and Line Drawing Set.
	// http://vt100.net/docs/vt102-ug/table5-13.html
	// A lot of curses apps use this if they see TERM=xterm.
	// testing: echo -e '\e(0a\e(B'
	// The xterm output sometimes seems to conflict with the
	// reference above. xterm seems in line with the reference
	// when running vttest however.
	// The table below now uses xterm's output from vttest.
	Terminal.charsets.SCLD={// (0
	'`':'\u25C6',// '◆'
	'a':'\u2592',// '▒'
	'b':'\t',// '\t'
	'c':'\f',// '\f'
	'd':'\r',// '\r'
	'e':'\n',// '\n'
	'f':'\xB0',// '°'
	'g':'\xB1',// '±'
	'h':'\u2424',// '\u2424' (NL)
	'i':'\x0B',// '\v'
	'j':'\u2518',// '┘'
	'k':'\u2510',// '┐'
	'l':'\u250C',// '┌'
	'm':'\u2514',// '└'
	'n':'\u253C',// '┼'
	'o':'\u23BA',// '⎺'
	'p':'\u23BB',// '⎻'
	'q':'\u2500',// '─'
	'r':'\u23BC',// '⎼'
	's':'\u23BD',// '⎽'
	't':'\u251C',// '├'
	'u':'\u2524',// '┤'
	'v':'\u2534',// '┴'
	'w':'\u252C',// '┬'
	'x':'\u2502',// '│'
	'y':'\u2264',// '≤'
	'z':'\u2265',// '≥'
	'{':'\u03C0',// 'π'
	'|':'\u2260',// '≠'
	'}':'\xA3',// '£'
	'~':'\xB7'// '·'
	};Terminal.charsets.UK=null;// (A
	Terminal.charsets.US=null;// (B (USASCII)
	Terminal.charsets.Dutch=null;// (4
	Terminal.charsets.Finnish=null;// (C or (5
	Terminal.charsets.French=null;// (R
	Terminal.charsets.FrenchCanadian=null;// (Q
	Terminal.charsets.German=null;// (K
	Terminal.charsets.Italian=null;// (Y
	Terminal.charsets.NorwegianDanish=null;// (E or (6
	Terminal.charsets.Spanish=null;// (Z
	Terminal.charsets.Swedish=null;// (H or (7
	Terminal.charsets.Swiss=null;// (=
	Terminal.charsets.ISOLatin=null;// /A
	/**
	 * Helpers
	 */function contains(el,arr){for(var i=0;i<arr.length;i+=1){if(el===arr[i]){return true;}}return false;}function on(el,type,handler,capture){if(!Array.isArray(el)){el=[el];}el.forEach(function(element){element.addEventListener(type,handler,capture||false);});}function off(el,type,handler,capture){el.removeEventListener(type,handler,capture||false);}function cancel(ev,force){if(!this.cancelEvents&&!force){return;}ev.preventDefault();ev.stopPropagation();return false;}function inherits(child,parent){function f(){this.constructor=child;}f.prototype=parent.prototype;child.prototype=new f();}// if bold is broken, we can't
	// use it in the terminal.
	function isBoldBroken(document){var body=document.getElementsByTagName('body')[0];var el=document.createElement('span');el.innerHTML='hello world';body.appendChild(el);var w1=el.scrollWidth;el.style.fontWeight='bold';var w2=el.scrollWidth;body.removeChild(el);return w1!==w2;}function indexOf(obj,el){var i=obj.length;while(i--){if(obj[i]===el)return i;}return-1;}function isThirdLevelShift(term,ev){var thirdLevelKey=term.isMac&&ev.altKey&&!ev.ctrlKey&&!ev.metaKey||term.isMSWindows&&ev.altKey&&ev.ctrlKey&&!ev.metaKey;if(ev.type=='keypress'){return thirdLevelKey;}// Don't invoke for arrows, pageDown, home, backspace, etc. (on non-keypress events)
	return thirdLevelKey&&(!ev.keyCode||ev.keyCode>47);}function matchColor(r1,g1,b1){var hash=r1<<16|g1<<8|b1;if(matchColor._cache[hash]!=null){return matchColor._cache[hash];}var ldiff=Infinity,li=-1,i=0,c,r2,g2,b2,diff;for(;i<Terminal.vcolors.length;i++){c=Terminal.vcolors[i];r2=c[0];g2=c[1];b2=c[2];diff=matchColor.distance(r1,g1,b1,r2,g2,b2);if(diff===0){li=i;break;}if(diff<ldiff){ldiff=diff;li=i;}}return matchColor._cache[hash]=li;}matchColor._cache={};// http://stackoverflow.com/questions/1633828
	matchColor.distance=function(r1,g1,b1,r2,g2,b2){return Math.pow(30*(r1-r2),2)+Math.pow(59*(g1-g2),2)+Math.pow(11*(b1-b2),2);};function each(obj,iter,con){if(obj.forEach)return obj.forEach(iter,con);for(var i=0;i<obj.length;i++){iter.call(con,obj[i],i,obj);}}function keys(obj){if(Object.keys)return Object.keys(obj);var key,keys=[];for(key in obj){if(Object.prototype.hasOwnProperty.call(obj,key)){keys.push(key);}}return keys;}var wcwidth=function(opts){// extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c
	// combining characters
	var COMBINING=[[0x0300,0x036F],[0x0483,0x0486],[0x0488,0x0489],[0x0591,0x05BD],[0x05BF,0x05BF],[0x05C1,0x05C2],[0x05C4,0x05C5],[0x05C7,0x05C7],[0x0600,0x0603],[0x0610,0x0615],[0x064B,0x065E],[0x0670,0x0670],[0x06D6,0x06E4],[0x06E7,0x06E8],[0x06EA,0x06ED],[0x070F,0x070F],[0x0711,0x0711],[0x0730,0x074A],[0x07A6,0x07B0],[0x07EB,0x07F3],[0x0901,0x0902],[0x093C,0x093C],[0x0941,0x0948],[0x094D,0x094D],[0x0951,0x0954],[0x0962,0x0963],[0x0981,0x0981],[0x09BC,0x09BC],[0x09C1,0x09C4],[0x09CD,0x09CD],[0x09E2,0x09E3],[0x0A01,0x0A02],[0x0A3C,0x0A3C],[0x0A41,0x0A42],[0x0A47,0x0A48],[0x0A4B,0x0A4D],[0x0A70,0x0A71],[0x0A81,0x0A82],[0x0ABC,0x0ABC],[0x0AC1,0x0AC5],[0x0AC7,0x0AC8],[0x0ACD,0x0ACD],[0x0AE2,0x0AE3],[0x0B01,0x0B01],[0x0B3C,0x0B3C],[0x0B3F,0x0B3F],[0x0B41,0x0B43],[0x0B4D,0x0B4D],[0x0B56,0x0B56],[0x0B82,0x0B82],[0x0BC0,0x0BC0],[0x0BCD,0x0BCD],[0x0C3E,0x0C40],[0x0C46,0x0C48],[0x0C4A,0x0C4D],[0x0C55,0x0C56],[0x0CBC,0x0CBC],[0x0CBF,0x0CBF],[0x0CC6,0x0CC6],[0x0CCC,0x0CCD],[0x0CE2,0x0CE3],[0x0D41,0x0D43],[0x0D4D,0x0D4D],[0x0DCA,0x0DCA],[0x0DD2,0x0DD4],[0x0DD6,0x0DD6],[0x0E31,0x0E31],[0x0E34,0x0E3A],[0x0E47,0x0E4E],[0x0EB1,0x0EB1],[0x0EB4,0x0EB9],[0x0EBB,0x0EBC],[0x0EC8,0x0ECD],[0x0F18,0x0F19],[0x0F35,0x0F35],[0x0F37,0x0F37],[0x0F39,0x0F39],[0x0F71,0x0F7E],[0x0F80,0x0F84],[0x0F86,0x0F87],[0x0F90,0x0F97],[0x0F99,0x0FBC],[0x0FC6,0x0FC6],[0x102D,0x1030],[0x1032,0x1032],[0x1036,0x1037],[0x1039,0x1039],[0x1058,0x1059],[0x1160,0x11FF],[0x135F,0x135F],[0x1712,0x1714],[0x1732,0x1734],[0x1752,0x1753],[0x1772,0x1773],[0x17B4,0x17B5],[0x17B7,0x17BD],[0x17C6,0x17C6],[0x17C9,0x17D3],[0x17DD,0x17DD],[0x180B,0x180D],[0x18A9,0x18A9],[0x1920,0x1922],[0x1927,0x1928],[0x1932,0x1932],[0x1939,0x193B],[0x1A17,0x1A18],[0x1B00,0x1B03],[0x1B34,0x1B34],[0x1B36,0x1B3A],[0x1B3C,0x1B3C],[0x1B42,0x1B42],[0x1B6B,0x1B73],[0x1DC0,0x1DCA],[0x1DFE,0x1DFF],[0x200B,0x200F],[0x202A,0x202E],[0x2060,0x2063],[0x206A,0x206F],[0x20D0,0x20EF],[0x302A,0x302F],[0x3099,0x309A],[0xA806,0xA806],[0xA80B,0xA80B],[0xA825,0xA826],[0xFB1E,0xFB1E],[0xFE00,0xFE0F],[0xFE20,0xFE23],[0xFEFF,0xFEFF],[0xFFF9,0xFFFB],[0x10A01,0x10A03],[0x10A05,0x10A06],[0x10A0C,0x10A0F],[0x10A38,0x10A3A],[0x10A3F,0x10A3F],[0x1D167,0x1D169],[0x1D173,0x1D182],[0x1D185,0x1D18B],[0x1D1AA,0x1D1AD],[0x1D242,0x1D244],[0xE0001,0xE0001],[0xE0020,0xE007F],[0xE0100,0xE01EF]];// binary search
	function bisearch(ucs){var min=0;var max=COMBINING.length-1;var mid;if(ucs<COMBINING[0][0]||ucs>COMBINING[max][1])return false;while(max>=min){mid=Math.floor((min+max)/2);if(ucs>COMBINING[mid][1])min=mid+1;else if(ucs<COMBINING[mid][0])max=mid-1;else return true;}return false;}function wcwidth(ucs){// test for 8-bit control characters
	if(ucs===0)return opts.nul;if(ucs<32||ucs>=0x7f&&ucs<0xa0)return opts.control;// binary search in table of non-spacing characters
	if(bisearch(ucs))return 0;// if we arrive here, ucs is not a combining or C0/C1 control character
	return 1+(ucs>=0x1100&&(ucs<=0x115f||// Hangul Jamo init. consonants
	ucs==0x2329||ucs==0x232a||ucs>=0x2e80&&ucs<=0xa4cf&&ucs!=0x303f||// CJK..Yi
	ucs>=0xac00&&ucs<=0xd7a3||// Hangul Syllables
	ucs>=0xf900&&ucs<=0xfaff||// CJK Compat Ideographs
	ucs>=0xfe10&&ucs<=0xfe19||// Vertical forms
	ucs>=0xfe30&&ucs<=0xfe6f||// CJK Compat Forms
	ucs>=0xff00&&ucs<=0xff60||// Fullwidth Forms
	ucs>=0xffe0&&ucs<=0xffe6||ucs>=0x20000&&ucs<=0x2fffd||ucs>=0x30000&&ucs<=0x3fffd));}return wcwidth;}({nul:0,control:0});// configurable options
	/**
	 * Expose
	 */Terminal.EventEmitter=_EventEmitter.EventEmitter;Terminal.CompositionHelper=_CompositionHelper.CompositionHelper;Terminal.Viewport=_Viewport.Viewport;Terminal.inherits=inherits;/**
	 * Adds an event listener to the terminal.
	 *
	 * @param {string} event The name of the event. TODO: Document all event types
	 * @param {function} callback The function to call when the event is triggered.
	 */Terminal.on=on;Terminal.off=off;Terminal.cancel=cancel;module.exports=Terminal;
	
	}).call(this,"/src")
	
	},{"./CompositionHelper.js":1,"./EventEmitter.js":2,"./Viewport.js":3,"./handlers/Clipboard.js":4}]},{},[5])(5)
	});
	//# sourceMappingURL=xterm.js.map
	
})
/** END DEFINE BLOCK for xterm@2.0.1/dist/xterm.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/launcher/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/launcher/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var commandlinker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandlinker/index.js');
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var console_1 = __jupyter_require__('jupyterlab@0.15.1/lib/console/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var filebrowser_2 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var services_1 = __jupyter_require__('jupyterlab@0.15.1/lib/services/index.js');
	var terminal_1 = __jupyter_require__('jupyterlab@0.15.1/lib/terminal/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/launcher/index.js');
	/**
	 * A service providing an interface to the the launcher.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.services.launcher',
	    requires: [
	        services_1.IServiceManager,
	        filebrowser_2.IPathTracker,
	        commandpalette_1.ICommandPalette,
	        commandlinker_1.ICommandLinker,
	        instancerestorer_1.IInstanceRestorer
	    ],
	    provides: _1.ILauncher,
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the launcher.
	 */
	function activate(app, services, pathTracker, palette, linker, restorer) {
	    var model = new _1.LauncherModel();
	    // Set launcher path and track the path as it changes.
	    model.path = pathTracker.path;
	    pathTracker.pathChanged.connect(function () { model.path = pathTracker.path; });
	    var widget = new _1.LauncherWidget({ linker: linker });
	    widget.model = model;
	    widget.id = 'launcher';
	    widget.title.label = 'Launcher';
	    // Let the application restorer track the launcher for restoration of
	    // application state (e.g. setting the launcher as the current side bar
	    // widget).
	    restorer.add(widget, 'launcher');
	    // Hardcoded defaults.
	    var defaults = [
	        {
	            name: 'Notebook',
	            command: filebrowser_1.CommandIDs.newNotebook
	        },
	        {
	            name: 'Code Console',
	            command: console_1.CommandIDs.create
	        },
	        {
	            name: 'Text Editor',
	            command: filebrowser_1.CommandIDs.newTextFile
	        }
	    ];
	    if (services.terminals.isAvailable()) {
	        defaults.push({
	            name: 'Terminal',
	            command: terminal_1.CommandIDs.createNew
	        });
	    }
	    // Note: we do not retain a handle on the items added by default, which
	    // means we have to way of removing them after the fact.
	    defaults.forEach(function (options) { model.add(options); });
	    app.commands.addCommand(_1.CommandIDs.show, {
	        label: 'Show Launcher',
	        execute: function () {
	            if (!widget.isAttached) {
	                app.shell.addToLeftArea(widget);
	            }
	            app.shell.activateLeft(widget.id);
	        }
	    });
	    palette.addItem({ command: _1.CommandIDs.show, category: 'Help' });
	    app.shell.addToLeftArea(widget);
	    return model;
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/launcher/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/launcher/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/launcher/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var vector_1 = __jupyter_require__('phosphor@^0.7.0/lib/collections/vector.js');
	var disposable_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/disposable.js');
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	var vdom_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/vdom.js');
	var vdom_2 = __jupyter_require__('jupyterlab@0.15.1/lib/common/vdom.js');
	/**
	 * The command IDs used by the launcher plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.show = 'launcher-jupyterlab:show';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	/* tslint:disable */
	/**
	 * The launcher token.
	 */
	exports.ILauncher = new token_1.Token('jupyter.services.launcher');
	/* tslint:enable */
	/**
	 * The class name added to LauncherWidget instances.
	 */
	var LAUNCHER_CLASS = 'jp-LauncherWidget';
	/**
	 * The class name added to LauncherWidget image nodes.
	 */
	var IMAGE_CLASS = 'jp-LauncherWidget-image';
	/**
	 * The class name added to LauncherWidget text nodes.
	 */
	var TEXT_CLASS = 'jp-LauncherWidget-text';
	/**
	 * The class name added to LauncherWidget item nodes.
	 */
	var ITEM_CLASS = 'jp-LauncherWidget-item';
	/**
	 * The class name added to LauncherWidget folder node.
	 */
	var FOLDER_CLASS = 'jp-LauncherWidget-folder';
	/**
	 * The class name added for the folder icon from default-theme.
	 */
	var FOLDER_ICON_CLASS = 'jp-FolderIcon';
	/**
	 * The class name added to LauncherWidget path nodes.
	 */
	var PATH_CLASS = 'jp-LauncherWidget-path';
	/**
	 * The class name added to LauncherWidget current working directory node.
	 */
	var CWD_CLASS = 'jp-LauncherWidget-cwd';
	/**
	 * The class name added to LauncherWidget body nodes.
	 */
	var BODY_CLASS = 'jp-LauncherWidget-body';
	/**
	 * The class name added to LauncherWidget dialog node.
	 */
	var DIALOG_CLASS = 'jp-LauncherWidget-dialog';
	/**
	 * LauncherModel keeps track of the path to working directory and has a list of
	 * LauncherItems, which the LauncherWidget will render.
	 */
	var LauncherModel = (function (_super) {
	    __extends(LauncherModel, _super);
	    /**
	     * Create a new launcher model.
	     */
	    function LauncherModel() {
	        _super.call(this);
	        this._items = null;
	        this._path = 'home';
	        this._items = new vector_1.Vector();
	    }
	    Object.defineProperty(LauncherModel.prototype, "path", {
	        /**
	         * The path to the current working directory.
	         */
	        get: function () {
	            return this._path;
	        },
	        set: function (path) {
	            if (path === this._path) {
	                return;
	            }
	            this._path = path;
	            this.stateChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a command item to the launcher, and trigger re-render event for parent
	     * widget.
	     *
	     * @param options - The specification options for a launcher item.
	     *
	     * @returns A disposable that will remove the item from Launcher, and trigger
	     * re-render event for parent widget.
	     *
	     */
	    LauncherModel.prototype.add = function (options) {
	        var _this = this;
	        // Create a copy of the options to circumvent mutations to the original.
	        var item = JSON.parse(JSON.stringify(options));
	        // If image class name is not set, use the default value.
	        item.imgClassName = item.imgClassName ||
	            "jp-Image" + item.name.replace(/\ /g, '');
	        this._items.pushBack(item);
	        this.stateChanged.emit(void 0);
	        return new disposable_1.DisposableDelegate(function () {
	            _this._items.remove(item);
	            _this.stateChanged.emit(void 0);
	        });
	    };
	    /**
	     * Return an iterator of launcher items.
	     */
	    LauncherModel.prototype.items = function () {
	        return this._items.iter();
	    };
	    return LauncherModel;
	}(vdom_2.VDomModel));
	exports.LauncherModel = LauncherModel;
	/**
	 * A virtual-DOM-based widget for the Launcher.
	 */
	var LauncherWidget = (function (_super) {
	    __extends(LauncherWidget, _super);
	    /**
	     * Construct a new launcher widget.
	     */
	    function LauncherWidget(options) {
	        _super.call(this);
	        this._linker = null;
	        this.addClass(LAUNCHER_CLASS);
	        this._linker = options.linker;
	    }
	    /**
	     * Render the launcher to virtual DOM nodes.
	     */
	    LauncherWidget.prototype.render = function () {
	        var _this = this;
	        // Create an iterator that yields rendered item nodes.
	        var children = iteration_1.map(this.model.items(), function (item) {
	            var img = vdom_1.h.span({ className: item.imgClassName + ' ' + IMAGE_CLASS });
	            var text = vdom_1.h.span({ className: TEXT_CLASS }, item.name);
	            var attrs = _this._linker.populateVNodeAttrs({
	                className: ITEM_CLASS
	            }, item.command, item.args);
	            return vdom_1.h.div(attrs, [img, text]);
	        });
	        var folderImage = vdom_1.h.span({
	            className: FOLDER_CLASS + " " + FOLDER_ICON_CLASS
	        });
	        var p = this.model.path;
	        var pathName = p.length ? "home > " + p.replace(/\//g, ' > ') : 'home';
	        var path = vdom_1.h.span({ className: PATH_CLASS }, pathName);
	        var cwd = vdom_1.h.div({ className: CWD_CLASS }, [folderImage, path]);
	        var body = vdom_1.h.div({ className: BODY_CLASS }, iteration_1.toArray(children));
	        return vdom_1.h.div({ className: DIALOG_CLASS }, [cwd, body]);
	    };
	    return LauncherWidget;
	}(vdom_2.VDomWidget));
	exports.LauncherWidget = LauncherWidget;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/launcher/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/instancerestorer/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/instancerestorer/plugin.js', function (module, exports, __jupyter_require__) {
	/*-----------------------------------------------------------------------------
	| Copyright (c) Jupyter Development Team.
	| Distributed under the terms of the Modified BSD License.
	|----------------------------------------------------------------------------*/
	"use strict";
	var statedb_1 = __jupyter_require__('jupyterlab@0.15.1/lib/statedb/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/instancerestorer.js');
	/**
	 * The default instance restorer provider.
	 */
	var plugin = {
	    id: 'jupyter.services.instance-restorer',
	    requires: [statedb_1.IStateDB],
	    activate: function (app, state) {
	        var first = app.started;
	        var registry = app.commands;
	        var shell = app.shell;
	        var restorer = new instancerestorer_1.InstanceRestorer({ first: first, registry: registry, state: state });
	        // Use the restorer as the application shell's layout database.
	        shell.setLayoutDB(restorer);
	        return restorer;
	    },
	    autoStart: true,
	    provides: instancerestorer_1.IInstanceRestorer
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/instancerestorer/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/mainmenu/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/mainmenu/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/mainmenu/index.js');
	/**
	 * The class name for all main area portrait tab icons.
	 */
	var PORTRAIT_ICON_CLASS = 'jp-MainAreaPortraitIcon';
	/**
	 * The class name for the jupyter icon from the default theme.
	 */
	var JUPYTER_ICON_CLASS = 'jp-JupyterIcon';
	/**
	 * A service providing an interface to the main menu.
	 */
	var plugin = {
	    id: 'jupyter.services.main-menu',
	    provides: _1.IMainMenu,
	    activate: function (app) {
	        var menu = new _1.MainMenu({ keymap: app.keymap });
	        menu.id = 'jp-MainMenu';
	        var logo = new widget_1.Widget();
	        logo.node.className = PORTRAIT_ICON_CLASS + " " + JUPYTER_ICON_CLASS;
	        logo.id = 'jp-MainLogo';
	        app.shell.addToTopArea(logo);
	        app.shell.addToTopArea(menu);
	        return menu;
	    }
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/mainmenu/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/markdownwidget/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/markdownwidget/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var rendermime_1 = __jupyter_require__('jupyterlab@0.15.1/lib/rendermime/index.js');
	var widget_1 = __jupyter_require__('jupyterlab@0.15.1/lib/markdownwidget/widget.js');
	/**
	 * The class name for all main area portrait tab icons.
	 */
	var PORTRAIT_ICON_CLASS = 'jp-MainAreaPortraitIcon';
	/**
	 * The class name for the text editor icon from the default theme.
	 */
	var TEXTEDITOR_ICON_CLASS = 'jp-ImageTextEditor';
	/**
	 * The name of the factory that creates markdown widgets.
	 */
	var FACTORY = 'Rendered Markdown';
	/**
	 * The markdown handler extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.rendered-markdown',
	    requires: [docregistry_1.IDocumentRegistry, rendermime_1.IRenderMime, instancerestorer_1.IInstanceRestorer],
	    autoStart: true
	};
	/**
	 * Activate the markdown plugin.
	 */
	function activate(app, registry, rendermime, restorer) {
	    var factory = new widget_1.MarkdownWidgetFactory({
	        name: FACTORY,
	        fileExtensions: ['.md'],
	        rendermime: rendermime
	    });
	    var namespace = 'rendered-markdown';
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: namespace });
	    var icon = PORTRAIT_ICON_CLASS + " " + TEXTEDITOR_ICON_CLASS;
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: filebrowser_1.CommandIDs.open,
	        args: function (widget) { return ({ path: widget.context.path, factory: FACTORY }); },
	        name: function (widget) { return widget.context.path; }
	    });
	    factory.widgetCreated.connect(function (sender, widget) {
	        widget.title.icon = icon;
	        // Notify the instance tracker if restore data needs to update.
	        widget.context.pathChanged.connect(function () { tracker.save(widget); });
	        tracker.add(widget);
	    });
	    registry.addWidgetFactory(factory);
	}
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/markdownwidget/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/markdownwidget/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/markdownwidget/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var activitymonitor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/activitymonitor.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	/**
	 * The class name added to a Jupyter MarkdownWidget
	 */
	var MD_CLASS = 'jp-MarkdownWidget';
	/**
	 * The timeout to wait for change activity to have ceased before rendering.
	 */
	var RENDER_TIMEOUT = 1000;
	/**
	 * A widget for rendered markdown.
	 */
	var MarkdownWidget = (function (_super) {
	    __extends(MarkdownWidget, _super);
	    /**
	     * Construct a new markdown widget.
	     */
	    function MarkdownWidget(context, rendermime) {
	        _super.call(this);
	        this._context = null;
	        this._monitor = null;
	        this._rendermime = null;
	        this.addClass(MD_CLASS);
	        this.layout = new panel_1.PanelLayout();
	        this.title.label = context.path.split('/').pop();
	        this._rendermime = rendermime;
	        rendermime.resolver = context;
	        this._context = context;
	        context.pathChanged.connect(this._onPathChanged, this);
	        // Throttle the rendering rate of the widget.
	        this._monitor = new activitymonitor_1.ActivityMonitor({
	            signal: context.model.contentChanged,
	            timeout: RENDER_TIMEOUT
	        });
	        this._monitor.activityStopped.connect(this.update, this);
	    }
	    Object.defineProperty(MarkdownWidget.prototype, "context", {
	        /**
	         * The markdown widget's context.
	         */
	        get: function () {
	            return this._context;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    MarkdownWidget.prototype.dispose = function () {
	        if (this.isDisposed) {
	            return;
	        }
	        this._monitor.dispose();
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    MarkdownWidget.prototype.onActivateRequest = function (msg) {
	        this.node.tabIndex = -1;
	        this.node.focus();
	    };
	    /**
	     * Handle an `after-attach` message to the widget.
	     */
	    MarkdownWidget.prototype.onAfterAttach = function (msg) {
	        this.update();
	    };
	    /**
	     * Handle an `update-request` message to the widget.
	     */
	    MarkdownWidget.prototype.onUpdateRequest = function (msg) {
	        var context = this._context;
	        var model = context.model;
	        var layout = this.layout;
	        var bundle = { 'text/markdown': model.toString() };
	        var widget = this._rendermime.render({ bundle: bundle });
	        if (layout.widgets.length) {
	            layout.widgets.at(0).dispose();
	        }
	        layout.addWidget(widget);
	    };
	    /**
	     * Handle a path change.
	     */
	    MarkdownWidget.prototype._onPathChanged = function () {
	        this.title.label = this._context.path.split('/').pop();
	    };
	    return MarkdownWidget;
	}(widget_1.Widget));
	exports.MarkdownWidget = MarkdownWidget;
	/**
	 * A widget factory for Markdown.
	 */
	var MarkdownWidgetFactory = (function (_super) {
	    __extends(MarkdownWidgetFactory, _super);
	    /**
	     * Construct a new markdown widget factory.
	     */
	    function MarkdownWidgetFactory(options) {
	        _super.call(this, options);
	        this._rendermime = null;
	        this._rendermime = options.rendermime;
	    }
	    /**
	     * Create a new widget given a context.
	     */
	    MarkdownWidgetFactory.prototype.createNewWidget = function (context) {
	        return new MarkdownWidget(context, this._rendermime.clone());
	    };
	    return MarkdownWidgetFactory;
	}(docregistry_1.ABCWidgetFactory));
	exports.MarkdownWidgetFactory = MarkdownWidgetFactory;
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/markdownwidget/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/activitymonitor.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/activitymonitor.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	/**
	 * A class that monitors activity on a signal.
	 */
	var ActivityMonitor = (function () {
	    /**
	     * Construct a new activity monitor.
	     */
	    function ActivityMonitor(options) {
	        this._timer = -1;
	        this._timeout = -1;
	        this._sender = null;
	        this._args = null;
	        this._isDisposed = false;
	        options.signal.connect(this._onSignalFired, this);
	        this._timeout = options.timeout || 1000;
	    }
	    Object.defineProperty(ActivityMonitor.prototype, "timeout", {
	        /**
	         * The timeout associated with the monitor, in milliseconds.
	         */
	        get: function () {
	            return this._timeout;
	        },
	        set: function (value) {
	            this._timeout = value;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ActivityMonitor.prototype, "isDisposed", {
	        /**
	         * Test whether the monitor has been disposed.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the activity monitor.
	     */
	    ActivityMonitor.prototype.dispose = function () {
	        if (this._isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * A signal handler for the monitored signal.
	     */
	    ActivityMonitor.prototype._onSignalFired = function (sender, args) {
	        var _this = this;
	        clearTimeout(this._timer);
	        this._sender = sender;
	        this._args = args;
	        this._timer = setTimeout(function () {
	            _this.activityStopped.emit({
	                sender: _this._sender,
	                args: _this._args
	            });
	            _this._sender = null;
	            _this._args = null;
	        }, this._timeout);
	    };
	    return ActivityMonitor;
	}());
	exports.ActivityMonitor = ActivityMonitor;
	// Define the signals for the `ActivityMonitor` class.
	signaling_1.defineSignal(ActivityMonitor.prototype, 'activityStopped');
	//# sourceMappingURL=activitymonitor.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/activitymonitor.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var menu_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/menu.js');
	var clipboard_1 = __jupyter_require__('jupyterlab@0.15.1/lib/clipboard/index.js');
	var codeeditor_1 = __jupyter_require__('jupyterlab@0.15.1/lib/codeeditor/index.js');
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var mainmenu_1 = __jupyter_require__('jupyterlab@0.15.1/lib/mainmenu/index.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var inspector_1 = __jupyter_require__('jupyterlab@0.15.1/lib/inspector/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var rendermime_1 = __jupyter_require__('jupyterlab@0.15.1/lib/rendermime/index.js');
	var services_1 = __jupyter_require__('jupyterlab@0.15.1/lib/services/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/notebook/index.js');
	/**
	 * The class name for all main area portrait tab icons.
	 */
	var PORTRAIT_ICON_CLASS = 'jp-MainAreaPortraitIcon';
	/**
	 * The class name for the notebook icon from the default theme.
	 */
	var NOTEBOOK_ICON_CLASS = 'jp-ImageNotebook';
	/**
	 * The name of the factory that creates notebooks.
	 */
	var FACTORY = 'Notebook';
	/**
	 * The notebook widget tracker provider.
	 */
	exports.trackerPlugin = {
	    id: 'jupyter.services.notebook-tracker',
	    provides: _1.INotebookTracker,
	    requires: [
	        docregistry_1.IDocumentRegistry,
	        services_1.IServiceManager,
	        rendermime_1.IRenderMime,
	        clipboard_1.IClipboard,
	        mainmenu_1.IMainMenu,
	        commandpalette_1.ICommandPalette,
	        inspector_1.IInspector,
	        _1.NotebookPanel.IContentFactory,
	        codeeditor_1.IEditorServices,
	        instancerestorer_1.IInstanceRestorer
	    ],
	    activate: activateNotebookHandler,
	    autoStart: true
	};
	/**
	 * The notebook cell factory provider.
	 */
	exports.contentFactoryPlugin = {
	    id: 'jupyter.services.notebook-renderer',
	    provides: _1.NotebookPanel.IContentFactory,
	    requires: [codeeditor_1.IEditorServices],
	    autoStart: true,
	    activate: function (app, editorServices) {
	        var editorFactory = editorServices.factoryService.newInlineEditor;
	        return new _1.NotebookPanel.ContentFactory({ editorFactory: editorFactory });
	    }
	};
	/**
	 * Export the plugins as default.
	 */
	var plugins = [exports.contentFactoryPlugin, exports.trackerPlugin];
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugins;
	/**
	 * Activate the notebook handler extension.
	 */
	function activateNotebookHandler(app, registry, services, rendermime, clipboard, mainMenu, palette, inspector, contentFactory, editorServices, restorer) {
	    var factory = new _1.NotebookWidgetFactory({
	        name: FACTORY,
	        fileExtensions: ['.ipynb'],
	        modelName: 'notebook',
	        defaultFor: ['.ipynb'],
	        preferKernel: true,
	        canStartKernel: true,
	        rendermime: rendermime,
	        clipboard: clipboard,
	        contentFactory: contentFactory,
	        mimeTypeService: editorServices.mimeTypeService
	    });
	    var tracker = new _1.NotebookTracker({ namespace: 'notebook' });
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: filebrowser_1.CommandIDs.open,
	        args: function (panel) { return ({ path: panel.context.path, factory: FACTORY }); },
	        name: function (panel) { return panel.context.path; },
	        when: services.ready
	    });
	    // Set the source of the code inspector.
	    tracker.currentChanged.connect(function (sender, widget) {
	        if (widget) {
	            inspector.source = widget.inspectionHandler;
	        }
	    });
	    registry.addModelFactory(new _1.NotebookModelFactory({}));
	    registry.addWidgetFactory(factory);
	    registry.addFileType({
	        name: 'Notebook',
	        extension: '.ipynb',
	        contentType: 'notebook',
	        fileFormat: 'json'
	    });
	    registry.addCreator({
	        name: 'Notebook',
	        fileType: 'Notebook',
	        widgetName: 'Notebook'
	    });
	    addCommands(app, services, tracker);
	    populatePalette(palette);
	    var id = 0; // The ID counter for notebook panels.
	    factory.widgetCreated.connect(function (sender, widget) {
	        // If the notebook panel does not have an ID, assign it one.
	        widget.id = widget.id || "notebook-" + ++id;
	        widget.title.icon = PORTRAIT_ICON_CLASS + " " + NOTEBOOK_ICON_CLASS;
	        // Immediately set the inspector source to the current notebook.
	        inspector.source = widget.inspectionHandler;
	        // Notify the instance tracker if restore data needs to update.
	        widget.context.pathChanged.connect(function () { tracker.save(widget); });
	        // Add the notebook panel to the tracker.
	        tracker.add(widget);
	    });
	    // Add main menu notebook menu.
	    mainMenu.addMenu(createMenu(app), { rank: 20 });
	    return tracker;
	}
	/**
	 * Add the notebook commands to the application's command registry.
	 */
	function addCommands(app, services, tracker) {
	    var commands = app.commands;
	    commands.addCommand(_1.CommandIDs.runAndAdvance, {
	        label: 'Run Cell(s) and Advance',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                var content = current.notebook;
	                _1.NotebookActions.runAndAdvance(content, current.context.kernel);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.run, {
	        label: 'Run Cell(s)',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.run(current.notebook, current.context.kernel);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.runAndInsert, {
	        label: 'Run Cell(s) and Insert',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.runAndInsert(current.notebook, current.context.kernel);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.runAll, {
	        label: 'Run All Cells',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.runAll(current.notebook, current.context.kernel);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.restart, {
	        label: 'Restart Kernel',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                docregistry_1.restartKernel(current.kernel, current.node).then(function () {
	                    current.activate();
	                });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.closeAndHalt, {
	        label: 'Close and Halt',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                current.context.changeKernel(null).then(function () { current.dispose(); });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.trust, {
	        label: 'Trust Notebook',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                return _1.trustNotebook(current.context.model).then(function () {
	                    return current.context.save();
	                });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.restartClear, {
	        label: 'Restart Kernel & Clear Outputs',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                var promise = docregistry_1.restartKernel(current.kernel, current.node);
	                promise.then(function (result) {
	                    current.activate();
	                    if (result) {
	                        _1.NotebookActions.clearAllOutputs(current.notebook);
	                    }
	                });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.restartRunAll, {
	        label: 'Restart Kernel & Run All',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                var promise = docregistry_1.restartKernel(current.kernel, current.node);
	                promise.then(function (result) {
	                    current.activate();
	                    _1.NotebookActions.runAll(current.notebook, current.context.kernel);
	                });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.clearAllOutputs, {
	        label: 'Clear All Outputs',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.clearAllOutputs(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.clearOutputs, {
	        label: 'Clear Output(s)',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.clearOutputs(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.interrupt, {
	        label: 'Interrupt Kernel',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                var kernel = current.context.kernel;
	                if (kernel) {
	                    kernel.interrupt();
	                }
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.toCode, {
	        label: 'Convert to Code',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.changeCellType(current.notebook, 'code');
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.toMarkdown, {
	        label: 'Convert to Markdown',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.changeCellType(current.notebook, 'markdown');
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.toRaw, {
	        label: 'Convert to Raw',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.changeCellType(current.notebook, 'raw');
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.cut, {
	        label: 'Cut Cell(s)',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.cut(current.notebook, current.clipboard);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.copy, {
	        label: 'Copy Cell(s)',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.copy(current.notebook, current.clipboard);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.paste, {
	        label: 'Paste Cell(s)',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.paste(current.notebook, current.clipboard);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.deleteCell, {
	        label: 'Delete Cell(s)',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.deleteCells(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.split, {
	        label: 'Split Cell',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.splitCell(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.merge, {
	        label: 'Merge Selected Cell(s)',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.mergeCells(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.insertAbove, {
	        label: 'Insert Cell Above',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.insertAbove(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.insertBelow, {
	        label: 'Insert Cell Below',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.insertBelow(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.selectAbove, {
	        label: 'Select Cell Above',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.selectAbove(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.selectBelow, {
	        label: 'Select Cell Below',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.selectBelow(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.extendAbove, {
	        label: 'Extend Selection Above',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.extendSelectionAbove(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.extendBelow, {
	        label: 'Extend Selection Below',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.extendSelectionBelow(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.moveUp, {
	        label: 'Move Cell(s) Up',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.moveUp(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.moveDown, {
	        label: 'Move Cell(s) Down',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.moveDown(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.toggleLines, {
	        label: 'Toggle Line Numbers',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.toggleLineNumbers(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.toggleAllLines, {
	        label: 'Toggle All Line Numbers',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.toggleAllLineNumbers(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.commandMode, {
	        label: 'To Command Mode',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                current.notebook.mode = 'command';
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.editMode, {
	        label: 'To Edit Mode',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                current.notebook.mode = 'edit';
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.undo, {
	        label: 'Undo Cell Operation',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.undo(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.redo, {
	        label: 'Redo Cell Operation',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.redo(current.notebook);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.switchKernel, {
	        label: 'Switch Kernel',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                var context = current.context;
	                var node = current.node;
	                docregistry_1.selectKernelForContext(context, services.sessions, node).then(function () {
	                    current.activate();
	                });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.markdown1, {
	        label: 'Markdown Header 1',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.setMarkdownHeader(current.notebook, 1);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.markdown2, {
	        label: 'Markdown Header 2',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.setMarkdownHeader(current.notebook, 2);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.markdown3, {
	        label: 'Markdown Header 3',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.setMarkdownHeader(current.notebook, 3);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.markdown4, {
	        label: 'Markdown Header 4',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.setMarkdownHeader(current.notebook, 4);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.markdown5, {
	        label: 'Markdown Header 5',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.setMarkdownHeader(current.notebook, 5);
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.markdown6, {
	        label: 'Markdown Header 6',
	        execute: function () {
	            var current = tracker.currentWidget;
	            if (current) {
	                _1.NotebookActions.setMarkdownHeader(current.notebook, 6);
	            }
	        }
	    });
	}
	/**
	 * Populate the application's command palette with notebook commands.
	 */
	function populatePalette(palette) {
	    var category = 'Notebook Operations';
	    [
	        _1.CommandIDs.interrupt,
	        _1.CommandIDs.restart,
	        _1.CommandIDs.restartClear,
	        _1.CommandIDs.restartRunAll,
	        _1.CommandIDs.runAll,
	        _1.CommandIDs.clearAllOutputs,
	        _1.CommandIDs.toggleAllLines,
	        _1.CommandIDs.editMode,
	        _1.CommandIDs.commandMode,
	        _1.CommandIDs.switchKernel,
	        _1.CommandIDs.closeAndHalt,
	        _1.CommandIDs.trust
	    ].forEach(function (command) { palette.addItem({ command: command, category: category }); });
	    category = 'Notebook Cell Operations';
	    [
	        _1.CommandIDs.run,
	        _1.CommandIDs.runAndAdvance,
	        _1.CommandIDs.runAndInsert,
	        _1.CommandIDs.clearOutputs,
	        _1.CommandIDs.toCode,
	        _1.CommandIDs.toMarkdown,
	        _1.CommandIDs.toRaw,
	        _1.CommandIDs.cut,
	        _1.CommandIDs.copy,
	        _1.CommandIDs.paste,
	        _1.CommandIDs.deleteCell,
	        _1.CommandIDs.split,
	        _1.CommandIDs.merge,
	        _1.CommandIDs.insertAbove,
	        _1.CommandIDs.insertBelow,
	        _1.CommandIDs.selectAbove,
	        _1.CommandIDs.selectBelow,
	        _1.CommandIDs.extendAbove,
	        _1.CommandIDs.extendBelow,
	        _1.CommandIDs.moveDown,
	        _1.CommandIDs.moveUp,
	        _1.CommandIDs.toggleLines,
	        _1.CommandIDs.undo,
	        _1.CommandIDs.redo,
	        _1.CommandIDs.markdown1,
	        _1.CommandIDs.markdown2,
	        _1.CommandIDs.markdown3,
	        _1.CommandIDs.markdown4,
	        _1.CommandIDs.markdown5,
	        _1.CommandIDs.markdown6
	    ].forEach(function (command) { palette.addItem({ command: command, category: category }); });
	}
	/**
	 * Creates a menu for the notebook.
	 */
	function createMenu(app) {
	    var commands = app.commands, keymap = app.keymap;
	    var menu = new menu_1.Menu({ commands: commands, keymap: keymap });
	    var settings = new menu_1.Menu({ commands: commands, keymap: keymap });
	    menu.title.label = 'Notebook';
	    settings.title.label = 'Settings';
	    settings.addItem({ command: _1.CommandIDs.toggleAllLines });
	    menu.addItem({ command: _1.CommandIDs.undo });
	    menu.addItem({ command: _1.CommandIDs.redo });
	    menu.addItem({ command: _1.CommandIDs.split });
	    menu.addItem({ command: _1.CommandIDs.deleteCell });
	    menu.addItem({ command: _1.CommandIDs.clearAllOutputs });
	    menu.addItem({ command: _1.CommandIDs.runAll });
	    menu.addItem({ command: _1.CommandIDs.restart });
	    menu.addItem({ command: _1.CommandIDs.switchKernel });
	    menu.addItem({ command: _1.CommandIDs.closeAndHalt });
	    menu.addItem({ command: _1.CommandIDs.trust });
	    menu.addItem({ type: 'separator' });
	    menu.addItem({ type: 'submenu', menu: settings });
	    return menu;
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/notebook/actions.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/notebook/default-toolbar.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/notebook/model.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/notebook/modelfactory.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/notebook/panel.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/notebook/tracker.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/notebook/trust.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/notebook/widget.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/notebook/widgetfactory.js'));
	/**
	 * The command IDs used by the notebook plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.interrupt = 'notebook:interrupt-kernel';
	    CommandIDs.restart = 'notebook:restart-kernel';
	    CommandIDs.restartClear = 'notebook:restart-clear';
	    CommandIDs.restartRunAll = 'notebook:restart-runAll';
	    CommandIDs.switchKernel = 'notebook:switch-kernel';
	    CommandIDs.clearAllOutputs = 'notebook:clear-outputs';
	    CommandIDs.closeAndHalt = 'notebook:close-and-halt';
	    CommandIDs.trust = 'notebook:trust';
	    CommandIDs.run = 'notebook-cells:run';
	    CommandIDs.runAndAdvance = 'notebook-cells:run-and-advance';
	    CommandIDs.runAndInsert = 'notebook-cells:run-and-insert';
	    CommandIDs.runAll = 'notebook:run-all';
	    CommandIDs.toCode = 'notebook-cells:to-code';
	    CommandIDs.toMarkdown = 'notebook-cells:to-markdown';
	    CommandIDs.toRaw = 'notebook-cells:to-raw';
	    CommandIDs.cut = 'notebook-cells:cut';
	    CommandIDs.copy = 'notebook-cells:copy';
	    CommandIDs.paste = 'notebook-cells:paste';
	    CommandIDs.moveUp = 'notebook-cells:move-up';
	    CommandIDs.moveDown = 'notebook-cells:move-down';
	    CommandIDs.clearOutputs = 'notebook-cells:clear-output';
	    CommandIDs.deleteCell = 'notebook-cells:delete';
	    CommandIDs.insertAbove = 'notebook-cells:insert-above';
	    CommandIDs.insertBelow = 'notebook-cells:insert-below';
	    CommandIDs.selectAbove = 'notebook-cells:select-above';
	    CommandIDs.selectBelow = 'notebook-cells:select-below';
	    CommandIDs.extendAbove = 'notebook-cells:extend-above';
	    CommandIDs.extendBelow = 'notebook-cells:extend-below';
	    CommandIDs.editMode = 'notebook:edit-mode';
	    CommandIDs.merge = 'notebook-cells:merge';
	    CommandIDs.split = 'notebook-cells:split';
	    CommandIDs.commandMode = 'notebook:command-mode';
	    CommandIDs.toggleLines = 'notebook-cells:toggle-line-numbers';
	    CommandIDs.toggleAllLines = 'notebook-cells:toggle-all-line-numbers';
	    CommandIDs.undo = 'notebook-cells:undo';
	    CommandIDs.redo = 'notebook-cells:redo';
	    CommandIDs.markdown1 = 'notebook-cells:markdown-header1';
	    CommandIDs.markdown2 = 'notebook-cells:markdown-header2';
	    CommandIDs.markdown3 = 'notebook-cells:markdown-header3';
	    CommandIDs.markdown4 = 'notebook-cells:markdown-header4';
	    CommandIDs.markdown5 = 'notebook-cells:markdown-header5';
	    CommandIDs.markdown6 = 'notebook-cells:markdown-header6';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/actions.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/actions.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var cells_1 = __jupyter_require__('jupyterlab@0.15.1/lib/cells/index.js');
	var widget_1 = __jupyter_require__('jupyterlab@0.15.1/lib/notebook/widget.js');
	/**
	 * A namespace for handling actions on a notebook.
	 *
	 * #### Notes
	 * All of the actions are a no-op if there is no model on the notebook.
	 * The actions set the widget `mode` to `'command'` unless otherwise specified.
	 * The actions will preserve the selection on the notebook widget unless
	 * otherwise specified.
	 */
	var NotebookActions;
	(function (NotebookActions) {
	    /**
	     * Split the active cell into two cells.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * It will preserve the existing mode.
	     * The second cell will be activated.
	     * The existing selection will be cleared.
	     * The leading whitespace in the second cell will be removed.
	     * If there is no content, two empty cells will be created.
	     * Both cells will have the same type as the original cell.
	     * This action can be undone.
	     */
	    function splitCell(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        widget.deselectAll();
	        var nbModel = widget.model;
	        var index = widget.activeCellIndex;
	        var child = widget.widgets.at(index);
	        var editor = child.editor;
	        var position = editor.getCursorPosition();
	        var offset = editor.getOffsetAt(position);
	        var orig = child.model.value.text;
	        // Create new models to preserve history.
	        var clone0 = Private.cloneCell(nbModel, child.model);
	        var clone1 = Private.cloneCell(nbModel, child.model);
	        if (clone0.type === 'code') {
	            clone0.outputs.clear();
	        }
	        clone0.value.text = orig.slice(0, offset);
	        clone1.value.text = orig.slice(offset).replace(/^\s+/g, '');
	        // Make the changes while preserving history.
	        var cells = nbModel.cells;
	        cells.beginCompoundOperation();
	        cells.set(index, clone0);
	        cells.insert(index + 1, clone1);
	        cells.endCompoundOperation();
	        widget.activeCellIndex++;
	        widget.scrollToActiveCell();
	        widget.activate();
	    }
	    NotebookActions.splitCell = splitCell;
	    /**
	     * Merge the selected cells.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The widget mode will be preserved.
	     * If only one cell is selected, the next cell will be selected.
	     * If the active cell is a code cell, its outputs will be cleared.
	     * This action can be undone.
	     * The final cell will have the same type as the active cell.
	     * If the active cell is a markdown cell, it will be unrendered.
	     */
	    function mergeCells(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var toMerge = [];
	        var toDelete = [];
	        var model = widget.model;
	        var cells = model.cells;
	        var primary = widget.activeCell;
	        var index = widget.activeCellIndex;
	        // Get the cells to merge.
	        iteration_1.each(iteration_1.enumerate(widget.widgets), function (_a) {
	            var i = _a[0], child = _a[1];
	            if (widget.isSelected(child)) {
	                toMerge.push(child.model.value.text);
	                if (i !== index) {
	                    toDelete.push(child.model);
	                }
	            }
	        });
	        // Check for only a single cell selected.
	        if (toMerge.length === 1) {
	            // Bail if it is the last cell.
	            if (index === cells.length - 1) {
	                return;
	            }
	            // Otherwise merge with the next cell.
	            var cellModel = cells.at(index + 1);
	            toMerge.push(cellModel.value.text);
	            toDelete.push(cellModel);
	        }
	        widget.deselectAll();
	        // Create a new cell for the source to preserve history.
	        var newModel = Private.cloneCell(model, primary.model);
	        newModel.value.text = toMerge.join('\n\n');
	        if (newModel.type === 'code') {
	            newModel.outputs.clear();
	        }
	        // Make the changes while preserving history.
	        cells.beginCompoundOperation();
	        cells.set(index, newModel);
	        iteration_1.each(toDelete, function (cell) {
	            cells.remove(cell);
	        });
	        cells.endCompoundOperation();
	        // If the original cell is a markdown cell, make sure
	        // the new cell is unrendered.
	        if (primary instanceof cells_1.MarkdownCellWidget) {
	            var cell = widget.activeCell;
	            cell.rendered = false;
	        }
	    }
	    NotebookActions.mergeCells = mergeCells;
	    /**
	     * Delete the selected cells.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The cell after the last selected cell will be activated.
	     * It will add a code cell if all cells are deleted.
	     * This action can be undone.
	     */
	    function deleteCells(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var model = widget.model;
	        var cells = model.cells;
	        var toDelete = [];
	        widget.mode = 'command';
	        // Find the cells to delete.
	        iteration_1.each(iteration_1.enumerate(widget.widgets), function (_a) {
	            var i = _a[0], child = _a[1];
	            var deletable = child.model.getMetadata('deletable').getValue();
	            if (widget.isSelected(child) && deletable !== false) {
	                toDelete.push(i);
	            }
	        });
	        // If cells are not deletable, we may not have anything to delete.
	        if (toDelete.length > 0) {
	            // Delete the cells as one undo event.
	            cells.beginCompoundOperation();
	            iteration_1.each(toDelete.reverse(), function (i) {
	                cells.removeAt(i);
	            });
	            // The model will add a new code cell if there are no
	            // remaining cells.
	            model.cells.endCompoundOperation();
	            // Select the *first* interior cell not deleted or the cell
	            // *after* the last selected cell.
	            // Note: The activeCellIndex is clamped to the available cells,
	            // so if the last cell is deleted the previous cell will be activated.
	            widget.activeCellIndex = toDelete[0];
	        }
	        // Deselect any remaining, undeletable cells. Do this even if we don't
	        // delete anything so that users are aware *something* happened.
	        widget.deselectAll();
	    }
	    NotebookActions.deleteCells = deleteCells;
	    /**
	     * Insert a new code cell above the active cell.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The widget mode will be preserved.
	     * This action can be undone.
	     * The existing selection will be cleared.
	     * The new cell will the active cell.
	     */
	    function insertAbove(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var model = widget.model;
	        var cell = model.contentFactory.createCodeCell({});
	        model.cells.insert(widget.activeCellIndex, cell);
	        widget.deselectAll();
	    }
	    NotebookActions.insertAbove = insertAbove;
	    /**
	     * Insert a new code cell below the active cell.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The widget mode will be preserved.
	     * This action can be undone.
	     * The existing selection will be cleared.
	     * The new cell will be the active cell.
	     */
	    function insertBelow(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var model = widget.model;
	        var cell = model.contentFactory.createCodeCell({});
	        model.cells.insert(widget.activeCellIndex + 1, cell);
	        widget.activeCellIndex++;
	        widget.deselectAll();
	    }
	    NotebookActions.insertBelow = insertBelow;
	    /**
	     * Move the selected cell(s) down.
	     *
	     * @param widget = The target notebook widget.
	     */
	    function moveDown(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var cells = widget.model.cells;
	        var widgets = widget.widgets;
	        cells.beginCompoundOperation();
	        for (var i = cells.length - 2; i > -1; i--) {
	            if (widget.isSelected(widgets.at(i))) {
	                if (!widget.isSelected(widgets.at(i + 1))) {
	                    cells.move(i, i + 1);
	                    if (widget.activeCellIndex === i) {
	                        widget.activeCellIndex++;
	                    }
	                    widget.select(widgets.at(i + 1));
	                    widget.deselect(widgets.at(i));
	                }
	            }
	        }
	        cells.endCompoundOperation();
	    }
	    NotebookActions.moveDown = moveDown;
	    /**
	     * Move the selected cell(s) up.
	     *
	     * @param widget - The target notebook widget.
	     */
	    function moveUp(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var cells = widget.model.cells;
	        var widgets = widget.widgets;
	        cells.beginCompoundOperation();
	        for (var i = 1; i < cells.length; i++) {
	            if (widget.isSelected(widgets.at(i))) {
	                if (!widget.isSelected(widgets.at(i - 1))) {
	                    cells.move(i, i - 1);
	                    if (widget.activeCellIndex === i) {
	                        widget.activeCellIndex--;
	                    }
	                    widget.select(widgets.at(i - 1));
	                    widget.deselect(widgets.at(i));
	                }
	            }
	        }
	        cells.endCompoundOperation();
	    }
	    NotebookActions.moveUp = moveUp;
	    /**
	     * Change the selected cell type(s).
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param value - The target cell type.
	     *
	     * #### Notes
	     * It should preserve the widget mode.
	     * This action can be undone.
	     * The existing selection will be cleared.
	     * Any cells converted to markdown will be unrendered.
	     */
	    function changeCellType(widget, value) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var model = widget.model;
	        var cells = model.cells;
	        cells.beginCompoundOperation();
	        iteration_1.each(iteration_1.enumerate(widget.widgets), function (_a) {
	            var i = _a[0], child = _a[1];
	            if (!widget.isSelected(child)) {
	                return;
	            }
	            if (child.model.type !== value) {
	                var cell = child.model.toJSON();
	                var newCell = void 0;
	                switch (value) {
	                    case 'code':
	                        newCell = model.contentFactory.createCodeCell({ cell: cell });
	                        break;
	                    case 'markdown':
	                        newCell = model.contentFactory.createMarkdownCell({ cell: cell });
	                        break;
	                    default:
	                        newCell = model.contentFactory.createRawCell({ cell: cell });
	                }
	                cells.set(i, newCell);
	            }
	            if (value === 'markdown') {
	                // Fetch the new widget and unrender it.
	                child = widget.widgets.at(i);
	                child.rendered = false;
	            }
	        });
	        cells.endCompoundOperation();
	        widget.deselectAll();
	    }
	    NotebookActions.changeCellType = changeCellType;
	    /**
	     * Run the selected cell(s).
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param kernel - An optional kernel object.
	     *
	     * #### Notes
	     * The last selected cell will be activated.
	     * The existing selection will be cleared.
	     * An execution error will prevent the remaining code cells from executing.
	     * All markdown cells will be rendered.
	     */
	    function run(widget, kernel) {
	        if (!widget.model || !widget.activeCell) {
	            return Promise.resolve(false);
	        }
	        widget.mode = 'command';
	        var selected = [];
	        var lastIndex = widget.activeCellIndex;
	        var i = 0;
	        iteration_1.each(widget.widgets, function (child) {
	            if (widget.isSelected(child)) {
	                selected.push(child);
	                lastIndex = i;
	            }
	            i++;
	        });
	        widget.activeCellIndex = lastIndex;
	        widget.deselectAll();
	        var promises = [];
	        iteration_1.each(selected, function (child) {
	            promises.push(Private.runCell(widget, child, kernel));
	        });
	        return Promise.all(promises).then(function (results) {
	            if (widget.isDisposed) {
	                return false;
	            }
	            // Post an update request.
	            widget.update();
	            for (var _i = 0, results_1 = results; _i < results_1.length; _i++) {
	                var result = results_1[_i];
	                if (!result) {
	                    return false;
	                }
	            }
	            return true;
	        });
	    }
	    NotebookActions.run = run;
	    /**
	     * Run the selected cell(s) and advance to the next cell.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param kernel - An optional kernel object.
	     *
	     * #### Notes
	     * The existing selection will be cleared.
	     * The cell after the last selected cell will be activated.
	     * An execution error will prevent the remaining code cells from executing.
	     * All markdown cells will be rendered.
	     * If the last selected cell is the last cell, a new code cell
	     * will be created in `'edit'` mode.  The new cell creation can be undone.
	     */
	    function runAndAdvance(widget, kernel) {
	        if (!widget.model || !widget.activeCell) {
	            return Promise.resolve(false);
	        }
	        var promise = run(widget, kernel);
	        var model = widget.model;
	        if (widget.activeCellIndex === widget.widgets.length - 1) {
	            var cell = model.contentFactory.createCodeCell({});
	            model.cells.pushBack(cell);
	            widget.activeCellIndex++;
	            widget.mode = 'edit';
	        }
	        else {
	            widget.activeCellIndex++;
	        }
	        widget.scrollToActiveCell();
	        return promise;
	    }
	    NotebookActions.runAndAdvance = runAndAdvance;
	    /**
	     * Run the selected cell(s) and insert a new code cell.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param kernel - An optional kernel object.
	     *
	     * #### Notes
	     * An execution error will prevent the remaining code cells from executing.
	     * All markdown cells will be rendered.
	     * The widget mode will be set to `'edit'` after running.
	     * The existing selection will be cleared.
	     * The cell insert can be undone.
	     */
	    function runAndInsert(widget, kernel) {
	        if (!widget.model || !widget.activeCell) {
	            return Promise.resolve(false);
	        }
	        var promise = run(widget, kernel);
	        var model = widget.model;
	        var cell = model.contentFactory.createCodeCell({});
	        model.cells.insert(widget.activeCellIndex + 1, cell);
	        widget.activeCellIndex++;
	        widget.scrollToActiveCell();
	        widget.mode = 'edit';
	        return promise;
	    }
	    NotebookActions.runAndInsert = runAndInsert;
	    /**
	     * Run all of the cells in the notebook.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param kernel - An optional kernel object.
	     * #### Notes
	     * The existing selection will be cleared.
	     * An execution error will prevent the remaining code cells from executing.
	     * All markdown cells will be rendered.
	     * The last cell in the notebook will be activated.
	     */
	    function runAll(widget, kernel) {
	        if (!widget.model || !widget.activeCell) {
	            return Promise.resolve(false);
	        }
	        iteration_1.each(widget.widgets, function (child) {
	            widget.select(child);
	        });
	        return run(widget, kernel);
	    }
	    NotebookActions.runAll = runAll;
	    /**
	     * Select the above the active cell.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The widget mode will be preserved.
	     * This is a no-op if the first cell is the active cell.
	     * The existing selection will be cleared.
	     */
	    function selectAbove(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        if (widget.activeCellIndex === 0) {
	            return;
	        }
	        widget.activeCellIndex -= 1;
	        widget.scrollToActiveCell();
	        widget.deselectAll();
	    }
	    NotebookActions.selectAbove = selectAbove;
	    /**
	     * Select the cell below the active cell.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The widget mode will be preserved.
	     * This is a no-op if the last cell is the active cell.
	     * The existing selection will be cleared.
	     */
	    function selectBelow(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        if (widget.activeCellIndex === widget.widgets.length - 1) {
	            return;
	        }
	        widget.activeCellIndex += 1;
	        widget.scrollToActiveCell();
	        widget.deselectAll();
	    }
	    NotebookActions.selectBelow = selectBelow;
	    /**
	     * Extend the selection to the cell above.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * This is a no-op if the first cell is the active cell.
	     * The new cell will be activated.
	     */
	    function extendSelectionAbove(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        // Do not wrap around.
	        if (widget.activeCellIndex === 0) {
	            return;
	        }
	        widget.mode = 'command';
	        var current = widget.activeCell;
	        var prev = widget.widgets.at(widget.activeCellIndex - 1);
	        if (widget.isSelected(prev)) {
	            widget.deselect(current);
	            if (widget.activeCellIndex > 1) {
	                var prevPrev = widget.widgets.at(widget.activeCellIndex - 2);
	                if (!widget.isSelected(prevPrev)) {
	                    widget.deselect(prev);
	                }
	            }
	        }
	        else {
	            widget.select(current);
	        }
	        widget.activeCellIndex -= 1;
	        widget.scrollToActiveCell();
	    }
	    NotebookActions.extendSelectionAbove = extendSelectionAbove;
	    /**
	     * Extend the selection to the cell below.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * This is a no-op if the last cell is the active cell.
	     * The new cell will be activated.
	     */
	    function extendSelectionBelow(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        // Do not wrap around.
	        if (widget.activeCellIndex === widget.widgets.length - 1) {
	            return;
	        }
	        widget.mode = 'command';
	        var current = widget.activeCell;
	        var next = widget.widgets.at(widget.activeCellIndex + 1);
	        if (widget.isSelected(next)) {
	            widget.deselect(current);
	            if (widget.activeCellIndex < widget.model.cells.length - 2) {
	                var nextNext = widget.widgets.at(widget.activeCellIndex + 2);
	                if (!widget.isSelected(nextNext)) {
	                    widget.deselect(next);
	                }
	            }
	        }
	        else {
	            widget.select(current);
	        }
	        widget.activeCellIndex += 1;
	        widget.scrollToActiveCell();
	    }
	    NotebookActions.extendSelectionBelow = extendSelectionBelow;
	    /**
	     * Copy or cut the selected cell data to a clipboard.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param clipboard - The clipboard object.
	     *
	     * @param cut - Whether to copy or cut.
	     */
	    function copyOrCut(widget, clipboard, cut) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        widget.mode = 'command';
	        clipboard.clear();
	        var data = [];
	        iteration_1.each(widget.widgets, function (child) {
	            if (widget.isSelected(child)) {
	                data.push(child.model.toJSON());
	            }
	        });
	        clipboard.setData(widget_1.JUPYTER_CELL_MIME, data);
	        if (cut) {
	            deleteCells(widget);
	        }
	        else {
	            widget.deselectAll();
	        }
	    }
	    /**
	     * Copy the selected cell data to a clipboard.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param clipboard - The clipboard object.
	     */
	    function copy(widget, clipboard) {
	        copyOrCut(widget, clipboard, false);
	    }
	    NotebookActions.copy = copy;
	    /**
	     * Cut the selected cell data to a clipboard.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param clipboard - The clipboard object.
	     *
	     * #### Notes
	     * This action can be undone.
	     * A new code cell is added if all cells are cut.
	     */
	    function cut(widget, clipboard) {
	        copyOrCut(widget, clipboard, true);
	    }
	    NotebookActions.cut = cut;
	    /**
	     * Paste cells from a clipboard.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param clipboard - The clipboard object.
	     *
	     * #### Notes
	     * The cells are pasted below the active cell.
	     * The last pasted cell becomes the active cell.
	     * This is a no-op if there is no cell data on the clipboard.
	     * This action can be undone.
	     */
	    function paste(widget, clipboard) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        if (!clipboard.hasData(widget_1.JUPYTER_CELL_MIME)) {
	            return;
	        }
	        var values = clipboard.getData(widget_1.JUPYTER_CELL_MIME);
	        var model = widget.model;
	        var newCells = [];
	        widget.mode = 'command';
	        iteration_1.each(values, function (cell) {
	            switch (cell.cell_type) {
	                case 'code':
	                    newCells.push(model.contentFactory.createCodeCell({ cell: cell }));
	                    break;
	                case 'markdown':
	                    newCells.push(model.contentFactory.createMarkdownCell({ cell: cell }));
	                    break;
	                default:
	                    newCells.push(model.contentFactory.createRawCell({ cell: cell }));
	                    break;
	            }
	        });
	        var index = widget.activeCellIndex;
	        var cells = widget.model.cells;
	        cells.beginCompoundOperation();
	        iteration_1.each(newCells, function (cell) {
	            cells.insert(++index, cell);
	        });
	        cells.endCompoundOperation();
	        widget.activeCellIndex += newCells.length;
	        widget.deselectAll();
	    }
	    NotebookActions.paste = paste;
	    /**
	     * Undo a cell action.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * This is a no-op if if there are no cell actions to undo.
	     */
	    function undo(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        widget.mode = 'command';
	        widget.model.cells.undo();
	        widget.deselectAll();
	    }
	    NotebookActions.undo = undo;
	    /**
	     * Redo a cell action.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * This is a no-op if there are no cell actions to redo.
	     */
	    function redo(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        widget.mode = 'command';
	        widget.model.cells.redo();
	        widget.deselectAll();
	    }
	    NotebookActions.redo = redo;
	    /**
	     * Toggle line numbers on the selected cell(s).
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The original state is based on the state of the active cell.
	     * The `mode` of the widget will be preserved.
	     */
	    function toggleLineNumbers(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var lineNumbers = widget.activeCell.editor.lineNumbers;
	        iteration_1.each(widget.widgets, function (child) {
	            if (widget.isSelected(child)) {
	                child.editor.lineNumbers = !lineNumbers;
	            }
	        });
	    }
	    NotebookActions.toggleLineNumbers = toggleLineNumbers;
	    /**
	     * Toggle the line number of all cells.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The original state is based on the state of the active cell.
	     * The `mode` of the widget will be preserved.
	     */
	    function toggleAllLineNumbers(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var lineNumbers = widget.activeCell.editor.lineNumbers;
	        iteration_1.each(widget.widgets, function (child) {
	            child.editor.lineNumbers = !lineNumbers;
	        });
	    }
	    NotebookActions.toggleAllLineNumbers = toggleAllLineNumbers;
	    /**
	     * Clear the code outputs of the selected cells.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The widget `mode` will be preserved.
	     */
	    function clearOutputs(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        var cells = widget.model.cells;
	        var i = 0;
	        iteration_1.each(cells, function (cell) {
	            var child = widget.widgets.at(i);
	            if (widget.isSelected(child) && cell.type === 'code') {
	                cell.outputs.clear();
	                cell.executionCount = null;
	            }
	            i++;
	        });
	    }
	    NotebookActions.clearOutputs = clearOutputs;
	    /**
	     * Clear all the code outputs on the widget.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * #### Notes
	     * The widget `mode` will be preserved.
	     */
	    function clearAllOutputs(widget) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        iteration_1.each(widget.model.cells, function (cell) {
	            if (cell.type === 'code') {
	                cell.outputs.clear();
	                cell.executionCount = null;
	            }
	        });
	    }
	    NotebookActions.clearAllOutputs = clearAllOutputs;
	    /**
	     * Set the markdown header level.
	     *
	     * @param widget - The target notebook widget.
	     *
	     * @param level - The header level.
	     *
	     * #### Notes
	     * All selected cells will be switched to markdown.
	     * The level will be clamped between 1 and 6.
	     * If there is an existing header, it will be replaced.
	     * There will always be one blank space after the header.
	     * The cells will be unrendered.
	     */
	    function setMarkdownHeader(widget, level) {
	        if (!widget.model || !widget.activeCell) {
	            return;
	        }
	        level = Math.min(Math.max(level, 1), 6);
	        var cells = widget.model.cells;
	        var i = 0;
	        iteration_1.each(widget.widgets, function (child) {
	            if (widget.isSelected(child)) {
	                Private.setMarkdownHeader(cells.at(i), level);
	            }
	            i++;
	        });
	        changeCellType(widget, 'markdown');
	    }
	    NotebookActions.setMarkdownHeader = setMarkdownHeader;
	})(NotebookActions = exports.NotebookActions || (exports.NotebookActions = {}));
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Clone a cell model.
	     */
	    function cloneCell(model, cell) {
	        switch (cell.type) {
	            case 'code':
	                return model.contentFactory.createCodeCell(cell.toJSON());
	            case 'markdown':
	                return model.contentFactory.createMarkdownCell(cell.toJSON());
	            default:
	                return model.contentFactory.createRawCell(cell.toJSON());
	        }
	    }
	    Private.cloneCell = cloneCell;
	    /**
	     * Run a cell.
	     */
	    function runCell(parent, child, kernel) {
	        switch (child.model.type) {
	            case 'markdown':
	                child.rendered = true;
	                break;
	            case 'code':
	                if (kernel) {
	                    return child.execute(kernel).then(function (reply) {
	                        if (child.isDisposed) {
	                            return false;
	                        }
	                        if (reply && reply.content.status === 'ok') {
	                            var content = reply.content;
	                            if (content.payload && content.payload.length) {
	                                handlePayload(content, parent, child);
	                            }
	                        }
	                        return reply ? reply.content.status === 'ok' : true;
	                    });
	                }
	                child.model.executionCount = null;
	                break;
	            default:
	                break;
	        }
	        return Promise.resolve(true);
	    }
	    Private.runCell = runCell;
	    /**
	     * Handle payloads from an execute reply.
	     *
	     * #### Notes
	     * Payloads are deprecated and there are no official interfaces for them in
	     * the kernel type definitions.
	     * See [Payloads (DEPRECATED)](https://jupyter-client.readthedocs.io/en/latest/messaging.html#payloads-deprecated).
	     */
	    function handlePayload(content, parent, child) {
	        var setNextInput = content.payload.filter(function (i) {
	            return i.source === 'set_next_input';
	        })[0];
	        if (!setNextInput) {
	            return;
	        }
	        var text = setNextInput.text;
	        var replace = setNextInput.replace;
	        if (replace) {
	            child.model.value.text = text;
	            return;
	        }
	        // Create a new code cell and add as the next cell.
	        var cell = parent.model.contentFactory.createCodeCell({});
	        cell.value.text = text;
	        var cells = parent.model.cells;
	        var i = searching_1.indexOf(cells, child.model);
	        if (i === -1) {
	            cells.pushBack(cell);
	        }
	        else {
	            cells.insert(i + 1, cell);
	        }
	    }
	    /**
	     * Set the markdown header level of a cell.
	     */
	    function setMarkdownHeader(cell, level) {
	        var source = cell.value.text;
	        var newHeader = Array(level + 1).join('#') + ' ';
	        // Remove existing header or leading white space.
	        var regex = /^(#+\s*)|^(\s*)/;
	        var matches = regex.exec(source);
	        if (matches) {
	            source = source.slice(matches[0].length);
	        }
	        cell.value.text = newHeader + source;
	    }
	    Private.setMarkdownHeader = setMarkdownHeader;
	})(Private || (Private = {}));
	//# sourceMappingURL=actions.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/actions.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var searching_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/searching.js');
	var mimedata_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/mimedata.js');
	var properties_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/properties.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var dragdrop_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/dragdrop.js');
	var query_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/query.js');
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var dragscroll_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dragscroll.js');
	var cells_1 = __jupyter_require__('jupyterlab@0.15.1/lib/cells/index.js');
	var outputarea_1 = __jupyter_require__('jupyterlab@0.15.1/lib/outputarea/index.js');
	/**
	 * The class name added to notebook widgets.
	 */
	var NB_CLASS = 'jp-Notebook';
	/**
	 * The class name added to notebook widget cells.
	 */
	var NB_CELL_CLASS = 'jp-Notebook-cell';
	/**
	 * The class name added to a notebook in edit mode.
	 */
	var EDIT_CLASS = 'jp-mod-editMode';
	/**
	 * The class name added to a notebook in command mode.
	 */
	var COMMAND_CLASS = 'jp-mod-commandMode';
	/**
	 * The class name added to the active cell.
	 */
	var ACTIVE_CLASS = 'jp-mod-active';
	/**
	 * The class name added to selected cells.
	 */
	var SELECTED_CLASS = 'jp-mod-selected';
	/**
	 * The class name added to an active cell when there are other selected cells.
	 */
	var OTHER_SELECTED_CLASS = 'jp-mod-multiSelected';
	/**
	 * The class name added to unconfined images.
	 */
	var UNCONFINED_CLASS = 'jp-mod-unconfined';
	/**
	 * The class name added to a drop target.
	 */
	var DROP_TARGET_CLASS = 'jp-mod-dropTarget';
	/**
	 * The class name added to a drop source.
	 */
	var DROP_SOURCE_CLASS = 'jp-mod-dropSource';
	/**
	 * The class name added to drag images.
	 */
	var DRAG_IMAGE_CLASS = 'jp-dragImage';
	/**
	 * The class name added to a filled circle.
	 */
	var FILLED_CIRCLE_CLASS = 'jp-filledCircle';
	/**
	 * The mimetype used for Jupyter cell data.
	 */
	exports.JUPYTER_CELL_MIME = 'application/vnd.jupyter.cells';
	/**
	 * The threshold in pixels to start a drag event.
	 */
	var DRAG_THRESHOLD = 5;
	/**
	 * A widget which renders static non-interactive notebooks.
	 *
	 * #### Notes
	 * The widget model must be set separately and can be changed
	 * at any time.  Consumers of the widget must account for a
	 * `null` model, and may want to listen to the `modelChanged`
	 * signal.
	 */
	var StaticNotebook = (function (_super) {
	    __extends(StaticNotebook, _super);
	    /**
	     * Construct a notebook widget.
	     */
	    function StaticNotebook(options) {
	        _super.call(this);
	        this._mimetype = 'text/plain';
	        this._model = null;
	        this.addClass(NB_CLASS);
	        this.rendermime = options.rendermime;
	        this.layout = new Private.NotebookPanelLayout();
	        this.contentFactory = options.contentFactory;
	        this._mimetypeService = options.mimeTypeService;
	    }
	    Object.defineProperty(StaticNotebook.prototype, "model", {
	        /**
	         * The model for the widget.
	         */
	        get: function () {
	            return this._model;
	        },
	        set: function (newValue) {
	            newValue = newValue || null;
	            if (this._model === newValue) {
	                return;
	            }
	            var oldValue = this._model;
	            this._model = newValue;
	            // Trigger private, protected, and public changes.
	            this._onModelChanged(oldValue, newValue);
	            this.onModelChanged(oldValue, newValue);
	            this.modelChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(StaticNotebook.prototype, "codeMimetype", {
	        /**
	         * Get the mimetype for code cells.
	         */
	        get: function () {
	            return this._mimetype;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(StaticNotebook.prototype, "widgets", {
	        /**
	         * A read-only sequence of the widgets in the notebook.
	         */
	        get: function () {
	            return this.layout.widgets;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    StaticNotebook.prototype.dispose = function () {
	        // Do nothing if already disposed.
	        if (this.isDisposed) {
	            return;
	        }
	        this._model = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle a new model.
	     *
	     * #### Notes
	     * This method is called after the model change has been handled
	     * internally and before the `modelChanged` signal is emitted.
	     * The default implementation is a no-op.
	     */
	    StaticNotebook.prototype.onModelChanged = function (oldValue, newValue) {
	        // No-op.
	    };
	    /**
	     * Handle changes to the notebook model content.
	     *
	     * #### Notes
	     * The default implementation emits the `modelContentChanged` signal.
	     */
	    StaticNotebook.prototype.onModelContentChanged = function (model, args) {
	        this.modelContentChanged.emit(void 0);
	    };
	    /**
	     * Handle changes to the notebook model metadata.
	     *
	     * #### Notes
	     * The default implementation updates the mimetypes of the code cells
	     * when the `language_info` metadata changes.
	     */
	    StaticNotebook.prototype.onMetadataChanged = function (model, args) {
	        switch (args.name) {
	            case 'language_info':
	                this._updateMimetype();
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle a cell being inserted.
	     *
	     * The default implementation is a no-op
	     */
	    StaticNotebook.prototype.onCellInserted = function (index, cell) {
	        // This is a no-op.
	    };
	    /**
	     * Handle a cell being moved.
	     *
	     * The default implementation is a no-op
	     */
	    StaticNotebook.prototype.onCellMoved = function (fromIndex, toIndex) {
	        // This is a no-op.
	    };
	    /**
	     * Handle a cell being removed.
	     *
	     * The default implementation is a no-op
	     */
	    StaticNotebook.prototype.onCellRemoved = function (cell) {
	        // This is a no-op.
	    };
	    /**
	     * Handle a new model on the widget.
	     */
	    StaticNotebook.prototype._onModelChanged = function (oldValue, newValue) {
	        var _this = this;
	        var layout = this.layout;
	        if (oldValue) {
	            oldValue.cells.changed.disconnect(this._onCellsChanged, this);
	            oldValue.metadataChanged.disconnect(this.onMetadataChanged, this);
	            oldValue.contentChanged.disconnect(this.onModelContentChanged, this);
	            // TODO: reuse existing cell widgets if possible.
	            while (layout.widgets.length) {
	                this._removeCell(0);
	            }
	        }
	        if (!newValue) {
	            this._mimetype = 'text/plain';
	            return;
	        }
	        this._updateMimetype();
	        var cells = newValue.cells;
	        iteration_1.each(iteration_1.enumerate(cells), function (_a) {
	            var i = _a[0], cell = _a[1];
	            _this._insertCell(i, cell);
	        });
	        cells.changed.connect(this._onCellsChanged, this);
	        newValue.contentChanged.connect(this.onModelContentChanged, this);
	        newValue.metadataChanged.connect(this.onMetadataChanged, this);
	    };
	    /**
	     * Handle a change cells event.
	     */
	    StaticNotebook.prototype._onCellsChanged = function (sender, args) {
	        var _this = this;
	        var index = 0;
	        switch (args.type) {
	            case 'add':
	                index = args.newIndex;
	                iteration_1.each(args.newValues, function (value) {
	                    _this._insertCell(index++, value);
	                });
	                break;
	            case 'move':
	                this._moveCell(args.newIndex, args.oldIndex);
	                break;
	            case 'remove':
	                iteration_1.each(args.oldValues, function (value) {
	                    _this._removeCell(args.oldIndex);
	                });
	                break;
	            case 'set':
	                // TODO: reuse existing widgets if possible.
	                index = args.newIndex;
	                iteration_1.each(args.newValues, function (value) {
	                    _this._removeCell(index);
	                    _this._insertCell(index, value);
	                    index++;
	                });
	                break;
	            default:
	                return;
	        }
	    };
	    /**
	     * Create a cell widget and insert into the notebook.
	     */
	    StaticNotebook.prototype._insertCell = function (index, cell) {
	        var widget;
	        switch (cell.type) {
	            case 'code':
	                widget = this._createCodeCell(cell);
	                break;
	            case 'markdown':
	                widget = this._createMarkdownCell(cell);
	                break;
	            default:
	                widget = this._createRawCell(cell);
	        }
	        cell.mimeType = this._mimetype;
	        widget.addClass(NB_CELL_CLASS);
	        var layout = this.layout;
	        layout.insertWidget(index, widget);
	        this.onCellInserted(index, widget);
	    };
	    /**
	     * Create a code cell widget from a code cell model.
	     */
	    StaticNotebook.prototype._createCodeCell = function (model) {
	        var factory = this.contentFactory;
	        var contentFactory = factory.codeCellContentFactory;
	        var rendermime = this.rendermime;
	        var options = { model: model, rendermime: rendermime, contentFactory: contentFactory };
	        return factory.createCodeCell(options, this);
	    };
	    /**
	     * Create a markdown cell widget from a markdown cell model.
	     */
	    StaticNotebook.prototype._createMarkdownCell = function (model) {
	        var factory = this.contentFactory;
	        var contentFactory = factory.markdownCellContentFactory;
	        var rendermime = this.rendermime;
	        var options = { model: model, rendermime: rendermime, contentFactory: contentFactory };
	        return factory.createMarkdownCell(options, this);
	    };
	    /**
	     * Create a raw cell widget from a raw cell model.
	     */
	    StaticNotebook.prototype._createRawCell = function (model) {
	        var factory = this.contentFactory;
	        var contentFactory = factory.rawCellContentFactory;
	        var options = { model: model, contentFactory: contentFactory };
	        return factory.createRawCell(options, this);
	    };
	    /**
	     * Move a cell widget.
	     */
	    StaticNotebook.prototype._moveCell = function (fromIndex, toIndex) {
	        var layout = this.layout;
	        layout.insertWidget(toIndex, layout.widgets.at(fromIndex));
	        this.onCellMoved(fromIndex, toIndex);
	    };
	    /**
	     * Remove a cell widget.
	     */
	    StaticNotebook.prototype._removeCell = function (index) {
	        var layout = this.layout;
	        var widget = layout.widgets.at(index);
	        widget.parent = null;
	        this.onCellRemoved(widget);
	        widget.dispose();
	    };
	    /**
	     * Update the mimetype of the notebook.
	     */
	    StaticNotebook.prototype._updateMimetype = function () {
	        var _this = this;
	        var cursor = this._model.getMetadata('language_info');
	        var info = cursor.getValue();
	        this._mimetype = this._mimetypeService.getMimeTypeByLanguage(info);
	        iteration_1.each(this.widgets, function (widget) {
	            widget.model.mimeType = _this._mimetype;
	        });
	    };
	    return StaticNotebook;
	}(widget_1.Widget));
	exports.StaticNotebook = StaticNotebook;
	// Define the signals for the `StaticNotebook` class.
	signaling_1.defineSignal(StaticNotebook.prototype, 'modelChanged');
	signaling_1.defineSignal(StaticNotebook.prototype, 'modelContentChanged');
	/**
	 * The namespace for the `StaticNotebook` class statics.
	 */
	var StaticNotebook;
	(function (StaticNotebook) {
	    /**
	     * The default implementation of an `IContentFactory`.
	     */
	    var ContentFactory = (function () {
	        /**
	         * Creates a new renderer.
	         */
	        function ContentFactory(options) {
	            var editorFactory = options.editorFactory;
	            var outputAreaContentFactory = (options.outputAreaContentFactory ||
	                outputarea_1.OutputAreaWidget.defaultContentFactory);
	            this.codeCellContentFactory = (options.codeCellContentFactory ||
	                new cells_1.CodeCellWidget.ContentFactory({
	                    editorFactory: editorFactory,
	                    outputAreaContentFactory: outputAreaContentFactory
	                }));
	            this.rawCellContentFactory = (options.rawCellContentFactory ||
	                new cells_1.RawCellWidget.ContentFactory({ editorFactory: editorFactory }));
	            this.markdownCellContentFactory = (options.markdownCellContentFactory ||
	                new cells_1.MarkdownCellWidget.ContentFactory({ editorFactory: editorFactory }));
	        }
	        /**
	         * Create a new code cell widget.
	         */
	        ContentFactory.prototype.createCodeCell = function (options, parent) {
	            return new cells_1.CodeCellWidget(options);
	        };
	        /**
	         * Create a new markdown cell widget.
	         */
	        ContentFactory.prototype.createMarkdownCell = function (options, parent) {
	            return new cells_1.MarkdownCellWidget(options);
	        };
	        /**
	         * Create a new raw cell widget.
	         */
	        ContentFactory.prototype.createRawCell = function (options, parent) {
	            return new cells_1.RawCellWidget(options);
	        };
	        return ContentFactory;
	    }());
	    StaticNotebook.ContentFactory = ContentFactory;
	})(StaticNotebook = exports.StaticNotebook || (exports.StaticNotebook = {}));
	/**
	 * A notebook widget that supports interactivity.
	 */
	var Notebook = (function (_super) {
	    __extends(Notebook, _super);
	    /**
	     * Construct a notebook widget.
	     */
	    function Notebook(options) {
	        _super.call(this, options);
	        this._activeCellIndex = -1;
	        this._activeCell = null;
	        this._mode = 'command';
	        this._drag = null;
	        this._dragData = null;
	        this._scrollHandler = null;
	        this.node.tabIndex = -1; // Allow the widget to take focus.
	        this._scrollHandler = new dragscroll_1.DragScrollHandler({ node: this.node });
	    }
	    Object.defineProperty(Notebook.prototype, "mode", {
	        /**
	         * The interactivity mode of the notebook.
	         */
	        get: function () {
	            return this._mode;
	        },
	        set: function (newValue) {
	            var _this = this;
	            var activeCell = this.activeCell;
	            if (!activeCell) {
	                newValue = 'command';
	            }
	            if (newValue === this._mode) {
	                this._ensureFocus();
	                return;
	            }
	            // Post an update request.
	            this.update();
	            var oldValue = this._mode;
	            this._mode = newValue;
	            if (newValue === 'edit') {
	                // Edit mode deselects all cells.
	                iteration_1.each(this.widgets, function (widget) { _this.deselect(widget); });
	                //  Edit mode unrenders an active markdown widget.
	                if (activeCell instanceof cells_1.MarkdownCellWidget) {
	                    activeCell.rendered = false;
	                }
	            }
	            this.stateChanged.emit({ name: 'mode', oldValue: oldValue, newValue: newValue });
	            this._ensureFocus();
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Notebook.prototype, "activeCellIndex", {
	        /**
	         * The active cell index of the notebook.
	         *
	         * #### Notes
	         * The index will be clamped to the bounds of the notebook cells.
	         */
	        get: function () {
	            if (!this.model) {
	                return -1;
	            }
	            return this.model.cells.length ? this._activeCellIndex : -1;
	        },
	        set: function (newValue) {
	            var oldValue = this._activeCellIndex;
	            if (!this.model || !this.model.cells.length) {
	                newValue = -1;
	            }
	            else {
	                newValue = Math.max(newValue, 0);
	                newValue = Math.min(newValue, this.model.cells.length - 1);
	            }
	            this._activeCellIndex = newValue;
	            var cell = this.widgets.at(newValue);
	            if (cell !== this._activeCell) {
	                // Post an update request.
	                this.update();
	                this._activeCell = cell;
	                this.activeCellChanged.emit(cell);
	            }
	            if (this.mode === 'edit' && cell instanceof cells_1.MarkdownCellWidget) {
	                cell.rendered = false;
	            }
	            this._ensureFocus();
	            if (newValue === oldValue) {
	                return;
	            }
	            this.stateChanged.emit({ name: 'activeCellIndex', oldValue: oldValue, newValue: newValue });
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(Notebook.prototype, "activeCell", {
	        /**
	         * Get the active cell widget.
	         */
	        get: function () {
	            return this._activeCell;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    Notebook.prototype.dispose = function () {
	        if (this._activeCell === null) {
	            return;
	        }
	        this._activeCell = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Select a cell widget.
	     *
	     * #### Notes
	     * It is a no-op if the value does not change.
	     * It will emit the `selectionChanged` signal.
	     */
	    Notebook.prototype.select = function (widget) {
	        if (Private.selectedProperty.get(widget)) {
	            return;
	        }
	        Private.selectedProperty.set(widget, true);
	        this.selectionChanged.emit(void 0);
	        this.update();
	    };
	    /**
	     * Deselect a cell widget.
	     *
	     * #### Notes
	     * It is a no-op if the value does not change.
	     * It will emit the `selectionChanged` signal.
	     */
	    Notebook.prototype.deselect = function (widget) {
	        if (!Private.selectedProperty.get(widget)) {
	            return;
	        }
	        Private.selectedProperty.set(widget, false);
	        this.selectionChanged.emit(void 0);
	        this.update();
	    };
	    /**
	     * Whether a cell is selected or is the active cell.
	     */
	    Notebook.prototype.isSelected = function (widget) {
	        if (widget === this._activeCell) {
	            return true;
	        }
	        return Private.selectedProperty.get(widget);
	    };
	    /**
	     * Deselect all of the cells.
	     */
	    Notebook.prototype.deselectAll = function () {
	        var changed = false;
	        iteration_1.each(this.widgets, function (widget) {
	            if (Private.selectedProperty.get(widget)) {
	                changed = true;
	            }
	            Private.selectedProperty.set(widget, false);
	        });
	        if (changed) {
	            this.selectionChanged.emit(void 0);
	        }
	        // Make sure we have a valid active cell.
	        this.activeCellIndex = this.activeCellIndex;
	    };
	    /**
	     * Scroll so that the active cell is visible.
	     */
	    Notebook.prototype.scrollToActiveCell = function () {
	        if (this.activeCell) {
	            query_1.scrollIntoViewIfNeeded(this.node, this.activeCell.node);
	        }
	    };
	    /**
	     * Handle the DOM events for the widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the notebook panel's node. It should
	     * not be called directly by user code.
	     */
	    Notebook.prototype.handleEvent = function (event) {
	        if (!this.model || this.model.readOnly) {
	            return;
	        }
	        switch (event.type) {
	            case 'mousedown':
	                this._evtMouseDown(event);
	                break;
	            case 'mouseup':
	                this._evtMouseup(event);
	                break;
	            case 'mousemove':
	                this._evtMousemove(event);
	                break;
	            case 'dblclick':
	                this._evtDblClick(event);
	                break;
	            case 'focus':
	                this._evtFocus(event);
	                break;
	            case 'blur':
	                this._evtBlur(event);
	                break;
	            case 'p-dragenter':
	                this._evtDragEnter(event);
	                break;
	            case 'p-dragleave':
	                this._evtDragLeave(event);
	                break;
	            case 'p-dragover':
	                this._evtDragOver(event);
	                break;
	            case 'p-drop':
	                this._evtDrop(event);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle `after-attach` messages for the widget.
	     */
	    Notebook.prototype.onAfterAttach = function (msg) {
	        _super.prototype.onAfterAttach.call(this, msg);
	        var node = this.node;
	        node.addEventListener('mousedown', this);
	        node.addEventListener('dblclick', this);
	        node.addEventListener('focus', this, true);
	        node.addEventListener('blur', this, true);
	        node.addEventListener('p-dragenter', this);
	        node.addEventListener('p-dragleave', this);
	        node.addEventListener('p-dragover', this);
	        node.addEventListener('p-drop', this);
	    };
	    /**
	     * Handle `before_detach` messages for the widget.
	     */
	    Notebook.prototype.onBeforeDetach = function (msg) {
	        var node = this.node;
	        node.removeEventListener('mousedown', this);
	        node.removeEventListener('dblclick', this);
	        node.removeEventListener('focus', this, true);
	        node.removeEventListener('blur', this, true);
	        node.removeEventListener('p-dragenter', this);
	        node.removeEventListener('p-dragleave', this);
	        node.removeEventListener('p-dragover', this);
	        node.removeEventListener('p-drop', this);
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('mouseup', this, true);
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    Notebook.prototype.onActivateRequest = function (msg) {
	        this._ensureFocus(true);
	    };
	    /**
	     * Handle `update-request` messages sent to the widget.
	     */
	    Notebook.prototype.onUpdateRequest = function (msg) {
	        var _this = this;
	        var activeCell = this.activeCell;
	        // Set the appropriate classes on the cells.
	        if (this.mode === 'edit') {
	            this.addClass(EDIT_CLASS);
	            this.removeClass(COMMAND_CLASS);
	        }
	        else {
	            this.addClass(COMMAND_CLASS);
	            this.removeClass(EDIT_CLASS);
	        }
	        if (activeCell) {
	            activeCell.addClass(ACTIVE_CLASS);
	        }
	        var count = 0;
	        iteration_1.each(this.widgets, function (widget) {
	            if (widget !== activeCell) {
	                widget.removeClass(ACTIVE_CLASS);
	            }
	            widget.removeClass(OTHER_SELECTED_CLASS);
	            if (_this.isSelected(widget)) {
	                widget.addClass(SELECTED_CLASS);
	                count++;
	            }
	            else {
	                widget.removeClass(SELECTED_CLASS);
	            }
	        });
	        if (count > 1) {
	            activeCell.addClass(OTHER_SELECTED_CLASS);
	        }
	    };
	    /**
	     * Handle a cell being inserted.
	     */
	    Notebook.prototype.onCellInserted = function (index, cell) {
	        cell.editor.edgeRequested.connect(this._onEdgeRequest, this);
	        // Trigger an update of the active cell.
	        this.activeCellIndex = this.activeCellIndex;
	    };
	    /**
	     * Handle a cell being moved.
	     */
	    Notebook.prototype.onCellMoved = function (fromIndex, toIndex) {
	        if (fromIndex === this.activeCellIndex) {
	            this.activeCellIndex = toIndex;
	        }
	    };
	    /**
	     * Handle a cell being removed.
	     */
	    Notebook.prototype.onCellRemoved = function (cell) {
	        // Trigger an update of the active cell.
	        this.activeCellIndex = this.activeCellIndex;
	        if (this.isSelected(cell)) {
	            this.selectionChanged.emit(void 0);
	        }
	    };
	    /**
	     * Handle a new model.
	     */
	    Notebook.prototype.onModelChanged = function (oldValue, newValue) {
	        // Try to set the active cell index to 0.
	        // It will be set to `-1` if there is no new model or the model is empty.
	        this.activeCellIndex = 0;
	    };
	    /**
	     * Handle edge request signals from cells.
	     */
	    Notebook.prototype._onEdgeRequest = function (editor, location) {
	        var prev = this.activeCellIndex;
	        if (location === 'top') {
	            this.activeCellIndex--;
	            // Move the cursor to the first position on the last line.
	            if (this.activeCellIndex < prev) {
	                var editor_1 = this.activeCell.editor;
	                var lastLine = editor_1.lineCount - 1;
	                editor_1.setCursorPosition({ line: lastLine, column: 0 });
	            }
	        }
	        else {
	            this.activeCellIndex++;
	            // Move the cursor to the first character.
	            if (this.activeCellIndex > prev) {
	                var editor_2 = this.activeCell.editor;
	                editor_2.setCursorPosition({ line: 0, column: 0 });
	            }
	        }
	    };
	    /**
	     * Ensure that the notebook has proper focus.
	     */
	    Notebook.prototype._ensureFocus = function (force) {
	        if (force === void 0) { force = false; }
	        var activeCell = this.activeCell;
	        if (this.mode === 'edit') {
	            activeCell.editor.focus();
	        }
	        else if (this.node.contains(document.activeElement)) {
	            // If an editor currently has focus, focus our node.
	            // Otherwise, another input field has focus and should keep it.
	            var w = searching_1.find(this.layout, function (widget) {
	                return widget.editor.hasFocus();
	            });
	            if (w) {
	                this.node.focus();
	            }
	        }
	        if (force && !this.node.contains(document.activeElement)) {
	            this.node.focus();
	        }
	    };
	    /**
	     * Find the cell index containing the target html element.
	     *
	     * #### Notes
	     * Returns -1 if the cell is not found.
	     */
	    Notebook.prototype._findCell = function (node) {
	        // Trace up the DOM hierarchy to find the root cell node.
	        // Then find the corresponding child and select it.
	        while (node && node !== this.node) {
	            if (node.classList.contains(NB_CELL_CLASS)) {
	                var i = searching_1.findIndex(this.widgets, function (widget) { return widget.node === node; });
	                if (i !== -1) {
	                    return i;
	                }
	                break;
	            }
	            node = node.parentElement;
	        }
	        return -1;
	    };
	    /**
	     * Handle `mousedown` events for the widget.
	     */
	    Notebook.prototype._evtMouseDown = function (event) {
	        var target = event.target;
	        var i = this._findCell(target);
	        var shouldDrag = false;
	        if (i !== -1) {
	            var widget = this.widgets.at(i);
	            // Event is on a cell but not in its editor, switch to command mode.
	            if (!widget.editorWidget.node.contains(target)) {
	                this.mode = 'command';
	                shouldDrag = widget.promptNode.contains(target);
	            }
	            if (event.shiftKey) {
	                shouldDrag = false;
	                this._extendSelectionTo(i);
	                // Prevent text select behavior.
	                event.preventDefault();
	                event.stopPropagation();
	            }
	            else {
	                if (!this.isSelected(widget)) {
	                    this.deselectAll();
	                }
	            }
	            // Set the cell as the active one.
	            // This must be done *after* setting the mode above.
	            this.activeCellIndex = i;
	        }
	        // Left mouse press for drag start.
	        if (event.button === 0 && shouldDrag) {
	            this._dragData = { pressX: event.clientX, pressY: event.clientY, index: i };
	            document.addEventListener('mouseup', this, true);
	            document.addEventListener('mousemove', this, true);
	        }
	    };
	    /**
	     * Handle the `'mouseup'` event for the widget.
	     */
	    Notebook.prototype._evtMouseup = function (event) {
	        if (event.button !== 0 || !this._drag) {
	            document.removeEventListener('mousemove', this, true);
	            document.removeEventListener('mouseup', this, true);
	            return;
	        }
	        event.preventDefault();
	        event.stopPropagation();
	    };
	    /**
	     * Handle the `'mousemove'` event for the widget.
	     */
	    Notebook.prototype._evtMousemove = function (event) {
	        event.preventDefault();
	        event.stopPropagation();
	        // Bail if we are the one dragging.
	        if (this._drag) {
	            return;
	        }
	        // Check for a drag initialization.
	        var data = this._dragData;
	        var dx = Math.abs(event.clientX - data.pressX);
	        var dy = Math.abs(event.clientY - data.pressY);
	        if (dx < DRAG_THRESHOLD && dy < DRAG_THRESHOLD) {
	            return;
	        }
	        this._startDrag(data.index, event.clientX, event.clientY);
	    };
	    /**
	     * Handle the `'p-dragenter'` event for the widget.
	     */
	    Notebook.prototype._evtDragEnter = function (event) {
	        if (!event.mimeData.hasData(exports.JUPYTER_CELL_MIME)) {
	            return;
	        }
	        this._scrollHandler.handleDragEvent(event);
	        event.preventDefault();
	        event.stopPropagation();
	        var target = event.target;
	        var index = this._findCell(target);
	        if (index === -1) {
	            return;
	        }
	        var widget = this.layout.widgets.at(index);
	        widget.node.classList.add(DROP_TARGET_CLASS);
	    };
	    /**
	     * Handle the `'p-dragleave'` event for the widget.
	     */
	    Notebook.prototype._evtDragLeave = function (event) {
	        if (!event.mimeData.hasData(exports.JUPYTER_CELL_MIME)) {
	            return;
	        }
	        this._scrollHandler.handleDragEvent(event);
	        event.preventDefault();
	        event.stopPropagation();
	        var elements = this.node.getElementsByClassName(DROP_TARGET_CLASS);
	        if (elements.length) {
	            elements[0].classList.remove(DROP_TARGET_CLASS);
	        }
	    };
	    /**
	     * Handle the `'p-dragover'` event for the widget.
	     */
	    Notebook.prototype._evtDragOver = function (event) {
	        if (!event.mimeData.hasData(exports.JUPYTER_CELL_MIME)) {
	            return;
	        }
	        event.preventDefault();
	        event.stopPropagation();
	        event.dropAction = event.proposedAction;
	        var elements = this.node.getElementsByClassName(DROP_TARGET_CLASS);
	        if (elements.length) {
	            elements[0].classList.remove(DROP_TARGET_CLASS);
	        }
	        this._scrollHandler.handleDragEvent(event);
	        var target = event.target;
	        var index = this._findCell(target);
	        if (index === -1) {
	            return;
	        }
	        var widget = this.layout.widgets.at(index);
	        widget.node.classList.add(DROP_TARGET_CLASS);
	    };
	    /**
	     * Handle the `'p-drop'` event for the widget.
	     */
	    Notebook.prototype._evtDrop = function (event) {
	        if (!event.mimeData.hasData(exports.JUPYTER_CELL_MIME)) {
	            return;
	        }
	        this._scrollHandler.handleDragEvent(event);
	        event.preventDefault();
	        event.stopPropagation();
	        if (event.proposedAction === 'none') {
	            event.dropAction = 'none';
	            return;
	        }
	        event.dropAction = event.proposedAction;
	        var target = event.target;
	        while (target && target.parentElement) {
	            if (target.classList.contains(DROP_TARGET_CLASS)) {
	                target.classList.remove(DROP_TARGET_CLASS);
	                break;
	            }
	            target = target.parentElement;
	        }
	        // Find the target cell and insert the copied cells.
	        var index = this._findCell(target);
	        if (index === -1) {
	            index = this.widgets.length;
	        }
	        var model = this.model;
	        var values = event.mimeData.getData(exports.JUPYTER_CELL_MIME);
	        var factory = model.contentFactory;
	        // Insert the copies of the original cells.
	        iteration_1.each(values, function (cell) {
	            var value;
	            switch (cell.cell_type) {
	                case 'code':
	                    value = factory.createCodeCell({ cell: cell });
	                    break;
	                case 'markdown':
	                    value = factory.createMarkdownCell({ cell: cell });
	                    break;
	                default:
	                    value = factory.createRawCell({ cell: cell });
	                    break;
	            }
	            model.cells.insert(index, value);
	        });
	        // Activate the last cell.
	        this.activeCellIndex = index + values.length - 1;
	    };
	    /**
	     * Start a drag event.
	     */
	    Notebook.prototype._startDrag = function (index, clientX, clientY) {
	        var _this = this;
	        var cells = this.model.cells;
	        var selected = [];
	        var toremove = [];
	        iteration_1.each(iteration_1.enumerate(this.widgets), function (_a) {
	            var i = _a[0], widget = _a[1];
	            var cell = cells.at(i);
	            if (_this.isSelected(widget)) {
	                widget.addClass(DROP_SOURCE_CLASS);
	                selected.push(cell.toJSON());
	                toremove.push(widget);
	            }
	        });
	        // Create the drag image.
	        var dragImage = Private.createDragImage(selected.length);
	        // Set up the drag event.
	        this._drag = new dragdrop_1.Drag({
	            mimeData: new mimedata_1.MimeData(),
	            dragImage: dragImage,
	            supportedActions: 'move',
	            proposedAction: 'move'
	        });
	        this._drag.mimeData.setData(exports.JUPYTER_CELL_MIME, selected);
	        // Remove mousemove and mouseup listeners and start the drag.
	        document.removeEventListener('mousemove', this, true);
	        document.removeEventListener('mouseup', this, true);
	        this._drag.start(clientX, clientY).then(function (action) {
	            if (_this.isDisposed) {
	                return;
	            }
	            _this._drag = null;
	            iteration_1.each(toremove, function (widget) { widget.removeClass(DROP_SOURCE_CLASS); });
	            if (action === 'none') {
	                return;
	            }
	            var activeCell = cells.at(_this.activeCellIndex);
	            iteration_1.each(toremove, function (widget) {
	                _this.model.cells.remove(widget.model);
	            });
	            _this.activeCellIndex = searching_1.indexOf(cells, activeCell);
	        });
	    };
	    /**
	     * Handle `focus` events for the widget.
	     */
	    Notebook.prototype._evtFocus = function (event) {
	        var target = event.target;
	        var i = this._findCell(target);
	        if (i !== -1) {
	            var widget = this.widgets.at(i);
	            // If the editor itself does not have focus, ensure command mode.
	            if (!widget.editorWidget.node.contains(target)) {
	                this.mode = 'command';
	            }
	            this.activeCellIndex = i;
	            // If the editor has focus, ensure edit mode.
	            if (widget.editorWidget.node.contains(target)) {
	                this.mode = 'edit';
	            }
	        }
	        else {
	            // No cell has focus, ensure command mode.
	            this.mode = 'command';
	        }
	    };
	    /**
	     * Handle `blur` events for the widget.
	     */
	    Notebook.prototype._evtBlur = function (event) {
	        var relatedTarget = event.relatedTarget;
	        if (!this.node.contains(relatedTarget)) {
	            this.mode = 'command';
	        }
	        // If the root node is not blurring and we are in command mode,
	        // focus ourselves.
	        if (this.mode === 'command' && event.target !== this.node) {
	            this.node.focus();
	        }
	    };
	    /**
	     * Handle `dblclick` events for the widget.
	     */
	    Notebook.prototype._evtDblClick = function (event) {
	        var model = this.model;
	        if (!model || model.readOnly) {
	            return;
	        }
	        var target = event.target;
	        var i = this._findCell(target);
	        if (i === -1) {
	            return;
	        }
	        this.activeCellIndex = i;
	        if (model.cells.at(i).type === 'markdown') {
	            this.mode = 'edit';
	        }
	        else if (target.localName === 'img') {
	            target.classList.toggle(UNCONFINED_CLASS);
	        }
	    };
	    /**
	     * Extend the selection to a given index.
	     */
	    Notebook.prototype._extendSelectionTo = function (index) {
	        var activeIndex = this.activeCellIndex;
	        var j = index;
	        // extend the existing selection.
	        if (j > activeIndex) {
	            while (j > activeIndex) {
	                Private.selectedProperty.set(this.widgets.at(j), true);
	                j--;
	            }
	        }
	        else if (j < activeIndex) {
	            while (j < activeIndex) {
	                Private.selectedProperty.set(this.widgets.at(j), true);
	                j++;
	            }
	        }
	        Private.selectedProperty.set(this.widgets.at(activeIndex), true);
	        this.selectionChanged.emit(void 0);
	    };
	    return Notebook;
	}(StaticNotebook));
	exports.Notebook = Notebook;
	// Define the signals for the `Notebook` class.
	signaling_1.defineSignal(Notebook.prototype, 'activeCellChanged');
	signaling_1.defineSignal(Notebook.prototype, 'selectionChanged');
	signaling_1.defineSignal(Notebook.prototype, 'stateChanged');
	/**
	 * The namespace for the `Notebook` class statics.
	 */
	var Notebook;
	(function (Notebook) {
	    /**
	     * The default implementation of an `IFactory`.
	     */
	    var ContentFactory = (function (_super) {
	        __extends(ContentFactory, _super);
	        function ContentFactory() {
	            _super.apply(this, arguments);
	        }
	        return ContentFactory;
	    }(StaticNotebook.ContentFactory));
	    Notebook.ContentFactory = ContentFactory;
	})(Notebook = exports.Notebook || (exports.Notebook = {}));
	/**
	 * A namespace for private data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * An attached property for the selected state of a cell.
	     */
	    Private.selectedProperty = new properties_1.AttachedProperty({
	        name: 'selected',
	        value: false
	    });
	    /**
	     * A custom panel layout for the notebook.
	     */
	    var NotebookPanelLayout = (function (_super) {
	        __extends(NotebookPanelLayout, _super);
	        function NotebookPanelLayout() {
	            _super.apply(this, arguments);
	        }
	        /**
	         * A message handler invoked on an `'update-request'` message.
	         *
	         * #### Notes
	         * This is a reimplementation of the base class method,
	         * and is a no-op.
	         */
	        NotebookPanelLayout.prototype.onUpdateRequest = function (msg) {
	            // This is a no-op.
	        };
	        return NotebookPanelLayout;
	    }(panel_1.PanelLayout));
	    Private.NotebookPanelLayout = NotebookPanelLayout;
	    /**
	     * Create a cell drag image.
	     */
	    function createDragImage(count) {
	        var node = document.createElement('div');
	        var span = document.createElement('span');
	        span.textContent = "" + count;
	        span.className = FILLED_CIRCLE_CLASS;
	        node.appendChild(span);
	        node.className = DRAG_IMAGE_CLASS;
	        return node;
	    }
	    Private.createDragImage = createDragImage;
	})(Private || (Private = {}));
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/dragscroll.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/dragscroll.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	/**
	 * A class that allows scrolling within a drag node.
	 */
	var DragScrollHandler = (function () {
	    /**
	     * Construct a new scroll handler.
	     */
	    function DragScrollHandler(options) {
	        this._scrollInterval = -1;
	        this._isScrolling = false;
	        this._scrollAmount = 0;
	        this._edgeDistance = -1;
	        this._maxSpeed = -1;
	        this._node = options.node;
	        this._edgeDistance = options.edgeDistance || 30;
	        this._maxSpeed = options.maxSpeed || 20;
	    }
	    /**
	     * Handle scrolling for drag events.
	     *
	     * @param event - The drag event.
	     *
	     * #### Notes
	     * This should be called for all handled drag events during a drag operation
	     * on the node.
	     */
	    DragScrollHandler.prototype.handleDragEvent = function (event) {
	        switch (event.type) {
	            case 'p-dragleave':
	                if (!this._node.contains(event.relatedTarget)) {
	                    this._clear();
	                }
	                break;
	            case 'p-dragover':
	                this._handleDragOver(event);
	                break;
	            case 'p-drop':
	                this._clear();
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle a `'p-dragover'` event.
	     */
	    DragScrollHandler.prototype._handleDragOver = function (event) {
	        var _this = this;
	        var yPos = event.clientY;
	        var node = this._node;
	        var rect = node.getBoundingClientRect();
	        var maxSpeed = this._maxSpeed;
	        var edgeDistance = this._edgeDistance;
	        var distanceFromTop = yPos - rect.top;
	        var distanceFromBottom = rect.top + rect.height - yPos;
	        // Step 1: Enable/disable scrolling.
	        if ((distanceFromTop <= edgeDistance ||
	            distanceFromBottom <= edgeDistance) &&
	            !this._isScrolling) {
	            // Activate scrolling.
	            this._isScrolling = true;
	            this._scrollAmount = 0;
	            // Update at 60fps.
	            this._scrollInterval = setInterval(function () {
	                if (_this._scrollAmount === 0) {
	                    return;
	                }
	                var prev = node.scrollTop;
	                node.scrollTop += _this._scrollAmount;
	                if (node.scrollTop === prev) {
	                    _this._clear();
	                }
	            }, 16);
	        }
	        else if (distanceFromTop > edgeDistance &&
	            distanceFromBottom > edgeDistance &&
	            this._isScrolling) {
	            // Deactivate scrolling.
	            this._clear();
	        }
	        // Step 2: Set scrolling speed.
	        if (this._isScrolling) {
	            // Scrolling is happening so compute the scroll speed.
	            var direction = 1; // Default to scroll down.
	            var distance = distanceFromBottom;
	            if (distanceFromTop <= edgeDistance) {
	                direction = -1; // Scroll up.
	                distance = distanceFromTop;
	            }
	            var ratio = distance / edgeDistance;
	            this._scrollAmount = direction * Math.min(1, 1 - ratio) * maxSpeed;
	        }
	    };
	    /**
	     * Clear the scroll state.
	     */
	    DragScrollHandler.prototype._clear = function () {
	        clearInterval(this._scrollInterval);
	        this._isScrolling = false;
	    };
	    return DragScrollHandler;
	}());
	exports.DragScrollHandler = DragScrollHandler;
	//# sourceMappingURL=dragscroll.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/dragscroll.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/default-toolbar.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/default-toolbar.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var actions_1 = __jupyter_require__('jupyterlab@0.15.1/lib/notebook/actions.js');
	var toolbar_1 = __jupyter_require__('jupyterlab@0.15.1/lib/toolbar/index.js');
	var kernel_1 = __jupyter_require__('jupyterlab@0.15.1/lib/toolbar/kernel.js');
	/**
	 * The class name added to toolbar save button.
	 */
	var TOOLBAR_SAVE_CLASS = 'jp-SaveIcon';
	/**
	 * The class name added to toolbar insert button.
	 */
	var TOOLBAR_INSERT_CLASS = 'jp-AddIcon';
	/**
	 * The class name added to toolbar cut button.
	 */
	var TOOLBAR_CUT_CLASS = 'jp-CutIcon';
	/**
	 * The class name added to toolbar copy button.
	 */
	var TOOLBAR_COPY_CLASS = 'jp-CopyIcon';
	/**
	 * The class name added to toolbar paste button.
	 */
	var TOOLBAR_PASTE_CLASS = 'jp-PasteIcon';
	/**
	 * The class name added to toolbar run button.
	 */
	var TOOLBAR_RUN_CLASS = 'jp-RunIcon';
	/**
	 * The class name added to toolbar cell type dropdown wrapper.
	 */
	var TOOLBAR_CELLTYPE_CLASS = 'jp-Notebook-toolbarCellType';
	/**
	 * The class name added to toolbar cell type dropdown.
	 */
	var TOOLBAR_CELLTYPE_DROPDOWN_CLASS = 'jp-Notebook-toolbarCellTypeDropdown';
	/**
	 * A namespace for the default toolbar items.
	 */
	var ToolbarItems;
	(function (ToolbarItems) {
	    /**
	     * Create save button toolbar item.
	     */
	    function createSaveButton(panel) {
	        return new toolbar_1.ToolbarButton({
	            className: TOOLBAR_SAVE_CLASS,
	            onClick: function () {
	                panel.context.save().then(function () {
	                    if (!panel.isDisposed) {
	                        return panel.context.createCheckpoint();
	                    }
	                });
	            },
	            tooltip: 'Save the notebook contents and create checkpoint'
	        });
	    }
	    ToolbarItems.createSaveButton = createSaveButton;
	    /**
	     * Create an insert toolbar item.
	     */
	    function createInsertButton(panel) {
	        return new toolbar_1.ToolbarButton({
	            className: TOOLBAR_INSERT_CLASS,
	            onClick: function () { actions_1.NotebookActions.insertBelow(panel.notebook); },
	            tooltip: 'Insert a cell below'
	        });
	    }
	    ToolbarItems.createInsertButton = createInsertButton;
	    /**
	     * Create a cut toolbar item.
	     */
	    function createCutButton(panel) {
	        return new toolbar_1.ToolbarButton({
	            className: TOOLBAR_CUT_CLASS,
	            onClick: function () {
	                actions_1.NotebookActions.cut(panel.notebook, panel.clipboard);
	            },
	            tooltip: 'Cut the selected cell(s)'
	        });
	    }
	    ToolbarItems.createCutButton = createCutButton;
	    /**
	     * Create a copy toolbar item.
	     */
	    function createCopyButton(panel) {
	        return new toolbar_1.ToolbarButton({
	            className: TOOLBAR_COPY_CLASS,
	            onClick: function () {
	                actions_1.NotebookActions.copy(panel.notebook, panel.clipboard);
	            },
	            tooltip: 'Copy the selected cell(s)'
	        });
	    }
	    ToolbarItems.createCopyButton = createCopyButton;
	    /**
	     * Create a paste toolbar item.
	     */
	    function createPasteButton(panel) {
	        return new toolbar_1.ToolbarButton({
	            className: TOOLBAR_PASTE_CLASS,
	            onClick: function () {
	                actions_1.NotebookActions.paste(panel.notebook, panel.clipboard);
	            },
	            tooltip: 'Paste cell(s) from the clipboard'
	        });
	    }
	    ToolbarItems.createPasteButton = createPasteButton;
	    /**
	     * Create a run toolbar item.
	     */
	    function createRunButton(panel) {
	        return new toolbar_1.ToolbarButton({
	            className: TOOLBAR_RUN_CLASS,
	            onClick: function () {
	                actions_1.NotebookActions.runAndAdvance(panel.notebook, panel.kernel);
	            },
	            tooltip: 'Run the selected cell(s) and advance'
	        });
	    }
	    ToolbarItems.createRunButton = createRunButton;
	    /**
	     * Create a cell type switcher item.
	     *
	     * #### Notes
	     * It will display the type of the current active cell.
	     * If more than one cell is selected but are of different types,
	     * it will display `'-'`.
	     * When the user changes the cell type, it will change the
	     * cell types of the selected cells.
	     * It can handle a change to the context.
	     */
	    function createCellTypeItem(panel) {
	        return new CellTypeSwitcher(panel.notebook);
	    }
	    ToolbarItems.createCellTypeItem = createCellTypeItem;
	    /**
	     * Add the default items to the panel toolbar.
	     */
	    function populateDefaults(panel) {
	        var toolbar = panel.toolbar;
	        toolbar.addItem('save', createSaveButton(panel));
	        toolbar.addItem('insert', createInsertButton(panel));
	        toolbar.addItem('cut', createCutButton(panel));
	        toolbar.addItem('copy', createCopyButton(panel));
	        toolbar.addItem('paste', createPasteButton(panel));
	        toolbar.addItem('run', createRunButton(panel));
	        toolbar.addItem('interrupt', kernel_1.createInterruptButton(panel));
	        toolbar.addItem('restart', kernel_1.createRestartButton(panel, panel.node));
	        toolbar.addItem('cellType', createCellTypeItem(panel));
	        toolbar.addItem('kernelName', kernel_1.createKernelNameItem(panel));
	        toolbar.addItem('kernelStatus', kernel_1.createKernelStatusItem(panel));
	    }
	    ToolbarItems.populateDefaults = populateDefaults;
	})(ToolbarItems = exports.ToolbarItems || (exports.ToolbarItems = {}));
	/**
	 * A toolbar widget that switches cell types.
	 */
	var CellTypeSwitcher = (function (_super) {
	    __extends(CellTypeSwitcher, _super);
	    /**
	     * Construct a new cell type switcher.
	     */
	    function CellTypeSwitcher(widget) {
	        var _this = this;
	        _super.call(this, { node: createCellTypeSwitcherNode() });
	        this._changeGuard = false;
	        this._wildCard = null;
	        this._select = null;
	        this._notebook = null;
	        this.addClass(TOOLBAR_CELLTYPE_CLASS);
	        var select = this._select = this.node.firstChild;
	        this._wildCard = document.createElement('option');
	        this._wildCard.value = '-';
	        this._wildCard.textContent = '-';
	        // Change current cell type on a change in the dropdown.
	        select.addEventListener('change', function (event) {
	            if (select.value === '-') {
	                return;
	            }
	            if (!_this._changeGuard) {
	                var value = select.value;
	                actions_1.NotebookActions.changeCellType(widget, value);
	            }
	        });
	        this._notebook = widget;
	        // Set the initial value.
	        if (widget.model) {
	            this._updateValue();
	        }
	        // Follow the type of the active cell.
	        widget.activeCellChanged.connect(this._updateValue, this);
	        // Follow a change in the selection.
	        widget.selectionChanged.connect(this._updateValue, this);
	    }
	    /**
	     * Update the value of the dropdown from the widget state.
	     */
	    CellTypeSwitcher.prototype._updateValue = function () {
	        var widget = this._notebook;
	        var select = this._select;
	        if (!widget.activeCell) {
	            return;
	        }
	        var mType = widget.activeCell.model.type;
	        for (var i = 0; i < widget.widgets.length; i++) {
	            var child = widget.widgets.at(i);
	            if (widget.isSelected(child)) {
	                if (child.model.type !== mType) {
	                    mType = '-';
	                    select.appendChild(this._wildCard);
	                    break;
	                }
	            }
	        }
	        if (mType !== '-') {
	            select.remove(3);
	        }
	        this._changeGuard = true;
	        select.value = mType;
	        this._changeGuard = false;
	    };
	    return CellTypeSwitcher;
	}(widget_1.Widget));
	/**
	 * Create the node for the cell type switcher.
	 */
	function createCellTypeSwitcherNode() {
	    var div = document.createElement('div');
	    var select = document.createElement('select');
	    for (var _i = 0, _a = ['Code', 'Markdown', 'Raw']; _i < _a.length; _i++) {
	        var t = _a[_i];
	        var option = document.createElement('option');
	        option.value = t.toLowerCase();
	        option.textContent = t;
	        select.appendChild(option);
	    }
	    select.className = TOOLBAR_CELLTYPE_DROPDOWN_CLASS;
	    div.appendChild(select);
	    return div;
	}
	//# sourceMappingURL=default-toolbar.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/default-toolbar.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/toolbar/kernel.js **/
jupyter.define('jupyterlab@0.15.1/lib/toolbar/kernel.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var index_1 = __jupyter_require__('jupyterlab@0.15.1/lib/toolbar/index.js');
	/**
	 * The class name added to toolbar interrupt button.
	 */
	var TOOLBAR_INTERRUPT_CLASS = 'jp-StopIcon';
	/**
	 * The class name added to toolbar restart button.
	 */
	var TOOLBAR_RESTART_CLASS = 'jp-RefreshIcon';
	/**
	 * The class name added to toolbar kernel name text.
	 */
	var TOOLBAR_KERNEL_CLASS = 'jp-Kernel-toolbarKernelName';
	/**
	 * The class name added to toolbar kernel indicator icon.
	 */
	var TOOLBAR_INDICATOR_CLASS = 'jp-Kernel-toolbarKernelIndicator';
	/**
	 * The class name added to a busy kernel indicator.
	 */
	var TOOLBAR_BUSY_CLASS = 'jp-mod-busy';
	/**
	 * Create an interrupt toolbar item.
	 */
	function createInterruptButton(kernelOwner) {
	    return new index_1.ToolbarButton({
	        className: TOOLBAR_INTERRUPT_CLASS,
	        onClick: function () {
	            if (kernelOwner.kernel) {
	                kernelOwner.kernel.interrupt();
	            }
	        },
	        tooltip: 'Interrupt the kernel'
	    });
	}
	exports.createInterruptButton = createInterruptButton;
	/**
	 * Create a restart toolbar item.
	 */
	function createRestartButton(kernelOwner, host) {
	    return new index_1.ToolbarButton({
	        className: TOOLBAR_RESTART_CLASS,
	        onClick: function () {
	            docregistry_1.restartKernel(kernelOwner.kernel, host);
	        },
	        tooltip: 'Restart the kernel'
	    });
	}
	exports.createRestartButton = createRestartButton;
	/**
	 * Create a kernel name indicator item.
	 *
	 * #### Notes
	 * It will display the `'display_name`' of the current kernel,
	 * or `'No Kernel!'` if there is no kernel.
	 * It can handle a change in context or kernel.
	 */
	function createKernelNameItem(kernelOwner) {
	    return new KernelName(kernelOwner);
	}
	exports.createKernelNameItem = createKernelNameItem;
	/**
	 * A kernel name widget.
	 */
	var KernelName = (function (_super) {
	    __extends(KernelName, _super);
	    /**
	     * Construct a new kernel name widget.
	     */
	    function KernelName(kernelOwner) {
	        _super.call(this);
	        this.addClass(TOOLBAR_KERNEL_CLASS);
	        this._onKernelChanged(kernelOwner, kernelOwner.kernel);
	        kernelOwner.kernelChanged.connect(this._onKernelChanged, this);
	    }
	    /**
	     * Update the text of the kernel name item.
	     */
	    KernelName.prototype._onKernelChanged = function (sender, kernel) {
	        var _this = this;
	        this.node.textContent = 'No Kernel!';
	        if (!kernel) {
	            return;
	        }
	        kernel.getSpec().then(function (spec) {
	            if (!_this.isDisposed) {
	                _this.node.textContent = spec.display_name;
	            }
	        });
	    };
	    return KernelName;
	}(widget_1.Widget));
	/**
	 * Create a kernel status indicator item.
	 *
	 * #### Notes
	 * It show display a busy status if the kernel status is
	 * not idle.
	 * It will show the current status in the node title.
	 * It can handle a change to the context or the kernel.
	 */
	function createKernelStatusItem(kernelOwner) {
	    return new KernelIndicator(kernelOwner);
	}
	exports.createKernelStatusItem = createKernelStatusItem;
	/**
	 * A toolbar item that displays kernel status.
	 */
	var KernelIndicator = (function (_super) {
	    __extends(KernelIndicator, _super);
	    /**
	     * Construct a new kernel status widget.
	     */
	    function KernelIndicator(kernelOwner) {
	        _super.call(this);
	        this._kernel = null;
	        this.addClass(TOOLBAR_INDICATOR_CLASS);
	        this._onKernelChanged(kernelOwner, kernelOwner.kernel);
	        kernelOwner.kernelChanged.connect(this._onKernelChanged, this);
	    }
	    /**
	     * Handle a change in kernel.
	     */
	    KernelIndicator.prototype._onKernelChanged = function (sender, kernel) {
	        if (this._kernel) {
	            this._kernel.statusChanged.disconnect(this._handleStatus, this);
	        }
	        this._kernel = kernel;
	        if (kernel) {
	            this._handleStatus(kernel, kernel.status);
	            kernel.statusChanged.connect(this._handleStatus, this);
	        }
	        else {
	            this.node.title = 'No Kernel!';
	            this.addClass(TOOLBAR_BUSY_CLASS);
	        }
	    };
	    /**
	     * Handle a status on a kernel.
	     */
	    KernelIndicator.prototype._handleStatus = function (kernel, status) {
	        if (this.isDisposed) {
	            return;
	        }
	        this.toggleClass(TOOLBAR_BUSY_CLASS, status !== 'idle');
	        var title = 'Kernel ' + status[0].toUpperCase() + status.slice(1);
	        this.node.title = title;
	    };
	    return KernelIndicator;
	}(widget_1.Widget));
	//# sourceMappingURL=kernel.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/toolbar/kernel.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/model.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/model.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var json_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/json.js');
	var iteration_2 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var model_1 = __jupyter_require__('jupyterlab@0.15.1/lib/cells/model.js');
	var metadata_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/metadata.js');
	var undoablevector_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/undoablevector.js');
	/**
	 * An implementation of a notebook Model.
	 */
	var NotebookModel = (function (_super) {
	    __extends(NotebookModel, _super);
	    /**
	     * Construct a new notebook model.
	     */
	    function NotebookModel(options) {
	        if (options === void 0) { options = {}; }
	        _super.call(this, options.languagePreference);
	        this._cells = null;
	        this._metadata = Private.createMetadata();
	        this._cursors = Object.create(null);
	        this._nbformat = services_1.nbformat.MAJOR_VERSION;
	        this._nbformatMinor = services_1.nbformat.MINOR_VERSION;
	        var factory = (options.contentFactory || NotebookModel.defaultContentFactory);
	        this.contentFactory = factory;
	        this._cells = new undoablevector_1.ObservableUndoableVector(function (cell) {
	            switch (cell.cell_type) {
	                case 'code':
	                    return factory.createCodeCell({ cell: cell });
	                case 'markdown':
	                    return factory.createMarkdownCell({ cell: cell });
	                default:
	                    return factory.createRawCell({ cell: cell });
	            }
	        });
	        // Add an initial code cell by default.
	        this._cells.pushBack(factory.createCodeCell({}));
	        this._cells.changed.connect(this._onCellsChanged, this);
	        if (options.languagePreference) {
	            this._metadata['language_info'] = { name: options.languagePreference };
	        }
	    }
	    Object.defineProperty(NotebookModel.prototype, "cells", {
	        /**
	         * Get the observable list of notebook cells.
	         */
	        get: function () {
	            return this._cells;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookModel.prototype, "nbformat", {
	        /**
	         * The major version number of the nbformat.
	         */
	        get: function () {
	            return this._nbformat;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookModel.prototype, "nbformatMinor", {
	        /**
	         * The minor version number of the nbformat.
	         */
	        get: function () {
	            return this._nbformatMinor;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookModel.prototype, "defaultKernelName", {
	        /**
	         * The default kernel name of the document.
	         */
	        get: function () {
	            var spec = this._metadata['kernelspec'];
	            return spec ? spec.name : '';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookModel.prototype, "defaultKernelLanguage", {
	        /**
	         * The default kernel language of the document.
	         */
	        get: function () {
	            var info = this._metadata['language_info'];
	            return info ? info.name : '';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the model.
	     */
	    NotebookModel.prototype.dispose = function () {
	        // Do nothing if already disposed.
	        if (this._cells === null) {
	            return;
	        }
	        var cells = this._cells;
	        var cursors = this._cursors;
	        this._cells = null;
	        this._cursors = null;
	        this._metadata = null;
	        for (var i = 0; i < cells.length; i++) {
	            var cell = cells.at(i);
	            cell.dispose();
	        }
	        cells.dispose();
	        for (var key in cursors) {
	            cursors[key].dispose();
	        }
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Serialize the model to a string.
	     */
	    NotebookModel.prototype.toString = function () {
	        return JSON.stringify(this.toJSON());
	    };
	    /**
	     * Deserialize the model from a string.
	     *
	     * #### Notes
	     * Should emit a [contentChanged] signal.
	     */
	    NotebookModel.prototype.fromString = function (value) {
	        this.fromJSON(JSON.parse(value));
	    };
	    /**
	     * Serialize the model to JSON.
	     */
	    NotebookModel.prototype.toJSON = function () {
	        var cells = [];
	        for (var i = 0; i < this.cells.length; i++) {
	            var cell = this.cells.at(i);
	            cells.push(cell.toJSON());
	        }
	        var metadata = services_1.utils.copy(this._metadata);
	        // orig_nbformat should not be written to file per spec.
	        delete metadata['orig_nbformat'];
	        return {
	            metadata: metadata,
	            nbformat_minor: this._nbformatMinor,
	            nbformat: this._nbformat,
	            cells: cells
	        };
	    };
	    /**
	     * Deserialize the model from JSON.
	     *
	     * #### Notes
	     * Should emit a [contentChanged] signal.
	     */
	    NotebookModel.prototype.fromJSON = function (value) {
	        var cells = [];
	        var factory = this.contentFactory;
	        for (var _i = 0, _a = value.cells; _i < _a.length; _i++) {
	            var cell = _a[_i];
	            switch (cell.cell_type) {
	                case 'code':
	                    cells.push(factory.createCodeCell({ cell: cell }));
	                    break;
	                case 'markdown':
	                    cells.push(factory.createMarkdownCell({ cell: cell }));
	                    break;
	                case 'raw':
	                    cells.push(factory.createRawCell({ cell: cell }));
	                    break;
	                default:
	                    continue;
	            }
	        }
	        this.cells.beginCompoundOperation();
	        this.cells.clear();
	        this.cells.pushAll(cells);
	        this.cells.endCompoundOperation();
	        var oldValue = 0;
	        var newValue = 0;
	        this._nbformatMinor = services_1.nbformat.MINOR_VERSION;
	        this._nbformat = services_1.nbformat.MAJOR_VERSION;
	        if (value.nbformat !== this._nbformat) {
	            oldValue = this._nbformat;
	            this._nbformat = newValue = value.nbformat;
	            this.stateChanged.emit({ name: 'nbformat', oldValue: oldValue, newValue: newValue });
	        }
	        if (value.nbformat_minor > this._nbformatMinor) {
	            oldValue = this._nbformatMinor;
	            this._nbformatMinor = newValue = value.nbformat_minor;
	            this.stateChanged.emit({ name: 'nbformatMinor', oldValue: oldValue, newValue: newValue });
	        }
	        // Update the metadata.
	        var metadata = value.metadata;
	        var builtins = ['kernelspec', 'language_info', 'orig_nbformat'];
	        for (var key in this._metadata) {
	            if (builtins.indexOf(key) !== -1) {
	                continue;
	            }
	            if (!(key in metadata)) {
	                this._setCursorData(key, null);
	                delete this._metadata[key];
	                if (this._cursors[key]) {
	                    this._cursors[key].dispose();
	                    delete this._cursors[key];
	                }
	            }
	        }
	        for (var key in metadata) {
	            this._setCursorData(key, metadata[key]);
	        }
	        this.dirty = true;
	    };
	    /**
	     * Get a metadata cursor for the notebook.
	     *
	     * #### Notes
	     * Metadata associated with the nbformat spec are set directly
	     * on the model.  This method is used to interact with a namespaced
	     * set of metadata on the notebook.
	     */
	    NotebookModel.prototype.getMetadata = function (name) {
	        var _this = this;
	        if (name in this._cursors) {
	            return this._cursors[name];
	        }
	        var cursor = new metadata_1.MetadataCursor(name, function () {
	            return _this._metadata[name];
	        }, function (value) {
	            _this._setCursorData(name, value);
	        });
	        this._cursors[name] = cursor;
	        return cursor;
	    };
	    /**
	     * List the metadata namespace keys for the notebook.
	     */
	    NotebookModel.prototype.listMetadata = function () {
	        return iteration_2.iter(Object.keys(this._metadata));
	    };
	    /**
	     * Set the cursor data for a given field.
	     */
	    NotebookModel.prototype._setCursorData = function (name, newValue) {
	        var oldValue = this._metadata[name];
	        if (json_1.deepEqual(oldValue, newValue)) {
	            return;
	        }
	        this._metadata[name] = newValue;
	        this.dirty = true;
	        this.contentChanged.emit(void 0);
	        this.metadataChanged.emit({ name: name, oldValue: oldValue, newValue: newValue });
	    };
	    /**
	     * Handle a change in the cells list.
	     */
	    NotebookModel.prototype._onCellsChanged = function (list, change) {
	        var _this = this;
	        switch (change.type) {
	            case 'add':
	                iteration_1.each(change.newValues, function (cell) {
	                    cell.contentChanged.connect(_this._onCellChanged, _this);
	                });
	                break;
	            case 'remove':
	                iteration_1.each(change.oldValues, function (cell) {
	                    cell.dispose();
	                });
	                break;
	            case 'set':
	                iteration_1.each(change.newValues, function (cell) {
	                    cell.contentChanged.connect(_this._onCellChanged, _this);
	                });
	                iteration_1.each(change.oldValues, function (cell) {
	                    cell.dispose();
	                });
	                break;
	            default:
	                return;
	        }
	        var factory = this.contentFactory;
	        // Add code cell if there are no cells remaining.
	        if (!this._cells.length) {
	            // Add the cell in a new context to avoid triggering another
	            // cell changed event during the handling of this signal.
	            requestAnimationFrame(function () {
	                if (!_this.isDisposed && !_this._cells.length) {
	                    _this._cells.pushBack(factory.createCodeCell({}));
	                }
	            });
	        }
	        this.contentChanged.emit(void 0);
	        this.dirty = true;
	    };
	    /**
	     * Handle a change to a cell state.
	     */
	    NotebookModel.prototype._onCellChanged = function (cell, change) {
	        this.dirty = true;
	        this.contentChanged.emit(void 0);
	    };
	    return NotebookModel;
	}(docregistry_1.DocumentModel));
	exports.NotebookModel = NotebookModel;
	// Define the signals for the `NotebookModel` class.
	signaling_1.defineSignal(NotebookModel.prototype, 'metadataChanged');
	/**
	 * The namespace for the `NotebookModel` class statics.
	 */
	var NotebookModel;
	(function (NotebookModel) {
	    /**
	     * The default implementation of an `IContentFactory`.
	     */
	    var ContentFactory = (function () {
	        /**
	         * Create a new cell model factory.
	         */
	        function ContentFactory(options) {
	            this.codeCellContentFactory = (options.codeCellContentFactory ||
	                model_1.CodeCellModel.defaultContentFactory);
	        }
	        /**
	         * Create a new code cell.
	         *
	         * @param source - The data to use for the original source data.
	         *
	         * @returns A new code cell. If a source cell is provided, the
	         *   new cell will be intialized with the data from the source.
	         *   If the contentFactory is not provided, the instance
	         *   `codeCellContentFactory` will be used.
	         */
	        ContentFactory.prototype.createCodeCell = function (options) {
	            if (options.contentFactory) {
	                options.contentFactory = this.codeCellContentFactory;
	            }
	            return new model_1.CodeCellModel(options);
	        };
	        /**
	         * Create a new markdown cell.
	         *
	         * @param source - The data to use for the original source data.
	         *
	         * @returns A new markdown cell. If a source cell is provided, the
	         *   new cell will be intialized with the data from the source.
	         */
	        ContentFactory.prototype.createMarkdownCell = function (options) {
	            return new model_1.MarkdownCellModel(options);
	        };
	        /**
	         * Create a new raw cell.
	         *
	         * @param source - The data to use for the original source data.
	         *
	         * @returns A new raw cell. If a source cell is provided, the
	         *   new cell will be intialized with the data from the source.
	         */
	        ContentFactory.prototype.createRawCell = function (options) {
	            return new model_1.RawCellModel(options);
	        };
	        return ContentFactory;
	    }());
	    NotebookModel.ContentFactory = ContentFactory;
	    /**
	     * The default `ContentFactory` instance.
	     */
	    NotebookModel.defaultContentFactory = new ContentFactory({});
	})(NotebookModel = exports.NotebookModel || (exports.NotebookModel = {}));
	/**
	 * A private namespace for notebook model data.
	 */
	var Private;
	(function (Private) {
	    /**
	     * Create the default metadata for the notebook.
	     */
	    function createMetadata() {
	        return {
	            kernelspec: { name: '', display_name: '' },
	            language_info: { name: '' },
	            orig_nbformat: 1
	        };
	    }
	    Private.createMetadata = createMetadata;
	})(Private || (Private = {}));
	//# sourceMappingURL=model.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/model.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/undoablevector.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/undoablevector.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var iteration_1 = __jupyter_require__('phosphor@^0.7.0/lib/algorithm/iteration.js');
	var observablevector_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/observablevector.js');
	/**
	 * A concrete implementation of an observable undoable vector.
	 */
	var ObservableUndoableVector = (function (_super) {
	    __extends(ObservableUndoableVector, _super);
	    /**
	     * Construct a new undoable observable vector.
	     */
	    function ObservableUndoableVector(factory) {
	        _super.call(this);
	        this._inCompound = false;
	        this._isUndoable = true;
	        this._madeCompoundChange = false;
	        this._index = -1;
	        this._stack = [];
	        this._factory = null;
	        this._factory = factory;
	        this.changed.connect(this._onVectorChanged, this);
	    }
	    Object.defineProperty(ObservableUndoableVector.prototype, "canRedo", {
	        /**
	         * Whether the object can redo changes.
	         */
	        get: function () {
	            return this._index < this._stack.length - 1;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(ObservableUndoableVector.prototype, "canUndo", {
	        /**
	         * Whether the object can undo changes.
	         */
	        get: function () {
	            return this._index >= 0;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources held by the model.
	     */
	    ObservableUndoableVector.prototype.dispose = function () {
	        this._factory = null;
	        this._stack = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Begin a compound operation.
	     *
	     * @param isUndoAble - Whether the operation is undoable.
	     *   The default is `true`.
	     */
	    ObservableUndoableVector.prototype.beginCompoundOperation = function (isUndoAble) {
	        this._inCompound = true;
	        this._isUndoable = (isUndoAble !== false);
	        this._madeCompoundChange = false;
	    };
	    /**
	     * End a compound operation.
	     */
	    ObservableUndoableVector.prototype.endCompoundOperation = function () {
	        this._inCompound = false;
	        this._isUndoable = true;
	        if (this._madeCompoundChange) {
	            this._index++;
	        }
	    };
	    /**
	     * Undo an operation.
	     */
	    ObservableUndoableVector.prototype.undo = function () {
	        if (!this.canUndo) {
	            return;
	        }
	        var changes = this._stack[this._index];
	        this._isUndoable = false;
	        for (var _i = 0, _a = changes.reverse(); _i < _a.length; _i++) {
	            var change = _a[_i];
	            this._undoChange(change);
	        }
	        this._isUndoable = true;
	        this._index--;
	    };
	    /**
	     * Redo an operation.
	     */
	    ObservableUndoableVector.prototype.redo = function () {
	        if (!this.canRedo) {
	            return;
	        }
	        this._index++;
	        var changes = this._stack[this._index];
	        this._isUndoable = false;
	        for (var _i = 0, changes_1 = changes; _i < changes_1.length; _i++) {
	            var change = changes_1[_i];
	            this._redoChange(change);
	        }
	        this._isUndoable = true;
	    };
	    /**
	     * Clear the change stack.
	     */
	    ObservableUndoableVector.prototype.clearUndo = function () {
	        this._index = -1;
	        this._stack = [];
	    };
	    /**
	     * Handle a change in the vector.
	     */
	    ObservableUndoableVector.prototype._onVectorChanged = function (list, change) {
	        if (this.isDisposed || !this._isUndoable) {
	            return;
	        }
	        // Clear everything after this position if necessary.
	        if (!this._inCompound || !this._madeCompoundChange) {
	            this._stack = this._stack.slice(0, this._index + 1);
	        }
	        // Copy the change.
	        var evt = this._copyChange(change);
	        // Put the change in the stack.
	        if (this._stack[this._index + 1]) {
	            this._stack[this._index + 1].push(evt);
	        }
	        else {
	            this._stack.push([evt]);
	        }
	        // If not in a compound operation, increase index.
	        if (!this._inCompound) {
	            this._index++;
	        }
	        else {
	            this._madeCompoundChange = true;
	        }
	    };
	    /**
	     * Undo a change event.
	     */
	    ObservableUndoableVector.prototype._undoChange = function (change) {
	        var _this = this;
	        var index = 0;
	        var factory = this._factory;
	        switch (change.type) {
	            case 'add':
	                iteration_1.each(change.newValues, function () {
	                    _this.removeAt(change.newIndex);
	                });
	                break;
	            case 'set':
	                index = change.oldIndex;
	                iteration_1.each(change.oldValues, function (value) {
	                    _this.set(index++, factory(value));
	                });
	                break;
	            case 'remove':
	                index = change.oldIndex;
	                iteration_1.each(change.oldValues, function (value) {
	                    _this.insert(index++, factory(value));
	                });
	                break;
	            case 'move':
	                this.move(change.newIndex, change.oldIndex);
	                break;
	            default:
	                return;
	        }
	    };
	    /**
	     * Redo a change event.
	     */
	    ObservableUndoableVector.prototype._redoChange = function (change) {
	        var _this = this;
	        var index = 0;
	        var factory = this._factory;
	        switch (change.type) {
	            case 'add':
	                index = change.newIndex;
	                iteration_1.each(change.newValues, function (value) {
	                    _this.insert(index++, factory(value));
	                });
	                break;
	            case 'set':
	                index = change.newIndex;
	                iteration_1.each(change.newValues, function (value) {
	                    _this.set(change.newIndex++, factory(value));
	                });
	                break;
	            case 'remove':
	                iteration_1.each(change.oldValues, function () {
	                    _this.removeAt(change.oldIndex);
	                });
	                break;
	            case 'move':
	                this.move(change.oldIndex, change.newIndex);
	                break;
	            default:
	                return;
	        }
	    };
	    /**
	     * Copy a change as JSON.
	     */
	    ObservableUndoableVector.prototype._copyChange = function (change) {
	        var oldValues = [];
	        iteration_1.each(change.oldValues, function (value) {
	            oldValues.push(value.toJSON());
	        });
	        var newValues = [];
	        iteration_1.each(change.newValues, function (value) {
	            newValues.push(value.toJSON());
	        });
	        return {
	            type: change.type,
	            oldIndex: change.oldIndex,
	            newIndex: change.newIndex,
	            oldValues: oldValues,
	            newValues: newValues
	        };
	    };
	    return ObservableUndoableVector;
	}(observablevector_1.ObservableVector));
	exports.ObservableUndoableVector = ObservableUndoableVector;
	//# sourceMappingURL=undoablevector.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/undoablevector.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/modelfactory.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/modelfactory.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var model_1 = __jupyter_require__('jupyterlab@0.15.1/lib/notebook/model.js');
	/**
	 * A model factory for notebooks.
	 */
	var NotebookModelFactory = (function () {
	    /**
	     * Construct a new notebook model factory.
	     */
	    function NotebookModelFactory(options) {
	        this._disposed = false;
	        var codeCellContentFactory = options.codeCellContentFactory;
	        this.contentFactory = (options.contentFactory ||
	            new model_1.NotebookModel.ContentFactory({ codeCellContentFactory: codeCellContentFactory }));
	    }
	    Object.defineProperty(NotebookModelFactory.prototype, "name", {
	        /**
	         * The name of the model.
	         */
	        get: function () {
	            return 'notebook';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookModelFactory.prototype, "contentType", {
	        /**
	         * The content type of the file.
	         */
	        get: function () {
	            return 'notebook';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookModelFactory.prototype, "fileFormat", {
	        /**
	         * The format of the file.
	         */
	        get: function () {
	            return 'json';
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookModelFactory.prototype, "isDisposed", {
	        /**
	         * Get whether the model factory has been disposed.
	         */
	        get: function () {
	            return this._disposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the model factory.
	     */
	    NotebookModelFactory.prototype.dispose = function () {
	        this._disposed = true;
	    };
	    /**
	     * Create a new model for a given path.
	     *
	     * @param languagePreference - An optional kernel language preference.
	     *
	     * @returns A new document model.
	     */
	    NotebookModelFactory.prototype.createNew = function (languagePreference) {
	        var contentFactory = this.contentFactory;
	        return new model_1.NotebookModel({ languagePreference: languagePreference, contentFactory: contentFactory });
	    };
	    /**
	     * Get the preferred kernel language given a path.
	     */
	    NotebookModelFactory.prototype.preferredLanguage = function (path) {
	        return '';
	    };
	    return NotebookModelFactory;
	}());
	exports.NotebookModelFactory = NotebookModelFactory;
	//# sourceMappingURL=modelfactory.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/modelfactory.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/panel.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/panel.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var completer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/completer/index.js');
	var inspector_1 = __jupyter_require__('jupyterlab@0.15.1/lib/inspector/index.js');
	var toolbar_1 = __jupyter_require__('jupyterlab@0.15.1/lib/toolbar/index.js');
	var widget_2 = __jupyter_require__('jupyterlab@0.15.1/lib/notebook/widget.js');
	/**
	 * The class name added to notebook panels.
	 */
	var NB_PANEL = 'jp-Notebook-panel';
	/**
	 * The class name added to a dirty widget.
	 */
	var DIRTY_CLASS = 'jp-mod-dirty';
	/**
	 * A widget that hosts a notebook toolbar and content area.
	 *
	 * #### Notes
	 * The widget keeps the document metadata in sync with the current
	 * kernel on the context.
	 */
	var NotebookPanel = (function (_super) {
	    __extends(NotebookPanel, _super);
	    /**
	     * Construct a new notebook panel.
	     */
	    function NotebookPanel(options) {
	        _super.call(this);
	        this._completer = null;
	        this._completerHandler = null;
	        this._context = null;
	        this.addClass(NB_PANEL);
	        this.rendermime = options.rendermime;
	        this.clipboard = options.clipboard;
	        var factory = this.contentFactory = options.contentFactory;
	        this.layout = new panel_1.PanelLayout();
	        var nbOptions = {
	            rendermime: this.rendermime,
	            languagePreference: options.languagePreference,
	            contentFactory: factory.notebookContentFactory,
	            mimeTypeService: options.mimeTypeService
	        };
	        this.notebook = factory.createNotebook(nbOptions);
	        this.notebook.activeCellChanged.connect(this._onActiveCellChanged, this);
	        var toolbar = factory.createToolbar();
	        var layout = this.layout;
	        layout.addWidget(toolbar);
	        layout.addWidget(this.notebook);
	        // Set up the inspection handler.
	        this.inspectionHandler = factory.createInspectionHandler({
	            rendermime: this.rendermime
	        });
	        // Instantiate the completer.
	        this._completer = factory.createCompleter({ model: new completer_1.CompleterModel() });
	        // Set the completer widget's anchor widget to peg its position.
	        this._completer.anchor = this.notebook;
	        widget_1.Widget.attach(this._completer, document.body);
	        // Instantiate the completer handler.
	        this._completerHandler = factory.createCompleterHandler({
	            completer: this._completer
	        });
	        var activeCell = this.notebook.activeCell;
	        if (activeCell) {
	            this.inspectionHandler.editor = activeCell.editor;
	            this._completerHandler.editor = activeCell.editor;
	        }
	    }
	    Object.defineProperty(NotebookPanel.prototype, "toolbar", {
	        /**
	         * Get the toolbar used by the widget.
	         */
	        get: function () {
	            return this.layout.widgets.at(0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookPanel.prototype, "kernel", {
	        /**
	         * Get the current kernel used by the panel.
	         */
	        get: function () {
	            return this._context ? this._context.kernel : null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookPanel.prototype, "model", {
	        /**
	         * The model for the widget.
	         */
	        get: function () {
	            return this.notebook ? this.notebook.model : null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(NotebookPanel.prototype, "context", {
	        /**
	         * The document context for the widget.
	         *
	         * #### Notes
	         * Changing the context also changes the model on the
	         * `content`.
	         */
	        get: function () {
	            return this._context;
	        },
	        set: function (newValue) {
	            newValue = newValue || null;
	            if (newValue === this._context) {
	                return;
	            }
	            var oldValue = this._context;
	            this._context = newValue;
	            this.rendermime.resolver = newValue;
	            // Trigger private, protected, and public changes.
	            this._onContextChanged(oldValue, newValue);
	            this.onContextChanged(oldValue, newValue);
	            this.contextChanged.emit(void 0);
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the widget.
	     */
	    NotebookPanel.prototype.dispose = function () {
	        if (this._completer === null) {
	            return;
	        }
	        var completer = this._completer;
	        var completerHandler = this._completerHandler;
	        this._completer = null;
	        this._context = null;
	        this._completerHandler = null;
	        this.notebook.dispose();
	        completerHandler.dispose();
	        completer.dispose();
	        this.inspectionHandler.dispose();
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    NotebookPanel.prototype.onActivateRequest = function (msg) {
	        this.notebook.activate();
	        this.activated.emit(void 0);
	    };
	    /**
	     * Handle a change to the document context.
	     *
	     * #### Notes
	     * The default implementation is a no-op.
	     */
	    NotebookPanel.prototype.onContextChanged = function (oldValue, newValue) {
	        // This is a no-op.
	    };
	    /**
	     * Handle a change in the model state.
	     */
	    NotebookPanel.prototype.onModelStateChanged = function (sender, args) {
	        if (args.name === 'dirty') {
	            this._handleDirtyState();
	        }
	    };
	    /**
	     * Handle a change to the document path.
	     */
	    NotebookPanel.prototype.onPathChanged = function (sender, path) {
	        this.title.label = path.split('/').pop();
	    };
	    /**
	     * Handle a change in the context.
	     */
	    NotebookPanel.prototype._onContextChanged = function (oldValue, newValue) {
	        var _this = this;
	        if (oldValue) {
	            oldValue.kernelChanged.disconnect(this._onKernelChanged, this);
	            oldValue.pathChanged.disconnect(this.onPathChanged, this);
	            if (oldValue.model) {
	                oldValue.model.stateChanged.disconnect(this.onModelStateChanged, this);
	            }
	        }
	        if (!newValue) {
	            this._onKernelChanged(null, null);
	            return;
	        }
	        var context = newValue;
	        context.kernelChanged.connect(this._onKernelChanged, this);
	        var oldKernel = oldValue ? oldValue.kernel : null;
	        if (context.kernel !== oldKernel) {
	            this._onKernelChanged(this._context, this._context.kernel);
	        }
	        this.notebook.model = newValue.model;
	        this._handleDirtyState();
	        newValue.model.stateChanged.connect(this.onModelStateChanged, this);
	        // Clear the cells when the context is initially populated.
	        if (!newValue.isReady) {
	            newValue.ready.then(function () {
	                if (_this.isDisposed) {
	                    return;
	                }
	                var model = newValue.model;
	                // Clear the undo state of the cells.
	                if (model) {
	                    model.cells.clearUndo();
	                }
	            });
	        }
	        // Handle the document title.
	        this.onPathChanged(context, context.path);
	        context.pathChanged.connect(this.onPathChanged, this);
	    };
	    /**
	     * Handle a change in the kernel by updating the document metadata.
	     */
	    NotebookPanel.prototype._onKernelChanged = function (context, kernel) {
	        var _this = this;
	        this._completerHandler.kernel = kernel;
	        this.inspectionHandler.kernel = kernel;
	        this.kernelChanged.emit(kernel);
	        if (!this.model || !kernel) {
	            return;
	        }
	        kernel.ready.then(function () {
	            if (_this.model) {
	                _this._updateLanguage(kernel.info.language_info);
	            }
	        });
	        this._updateSpec(kernel);
	    };
	    /**
	     * Update the kernel language.
	     */
	    NotebookPanel.prototype._updateLanguage = function (language) {
	        var infoCursor = this.model.getMetadata('language_info');
	        infoCursor.setValue(language);
	    };
	    /**
	     * Update the kernel spec.
	     */
	    NotebookPanel.prototype._updateSpec = function (kernel) {
	        var _this = this;
	        kernel.getSpec().then(function (spec) {
	            if (_this.isDisposed) {
	                return;
	            }
	            var specCursor = _this.model.getMetadata('kernelspec');
	            specCursor.setValue({
	                name: kernel.name,
	                display_name: spec.display_name,
	                language: spec.language
	            });
	        });
	    };
	    /**
	     * Handle the dirty state of the model.
	     */
	    NotebookPanel.prototype._handleDirtyState = function () {
	        if (!this.model) {
	            return;
	        }
	        if (this.model.dirty) {
	            this.title.className += " " + DIRTY_CLASS;
	        }
	        else {
	            this.title.className = this.title.className.replace(DIRTY_CLASS, '');
	        }
	    };
	    /**
	     * Handle a change to the active cell.
	     */
	    NotebookPanel.prototype._onActiveCellChanged = function (sender, widget) {
	        var editor = widget ? widget.editor : null;
	        this.inspectionHandler.editor = editor;
	        this._completerHandler.editor = editor;
	    };
	    return NotebookPanel;
	}(widget_1.Widget));
	exports.NotebookPanel = NotebookPanel;
	// Define the signals for the `NotebookPanel` class.
	signaling_1.defineSignal(NotebookPanel.prototype, 'activated');
	signaling_1.defineSignal(NotebookPanel.prototype, 'contextChanged');
	signaling_1.defineSignal(NotebookPanel.prototype, 'kernelChanged');
	/**
	 * A namespace for `NotebookPanel` statics.
	 */
	var NotebookPanel;
	(function (NotebookPanel) {
	    /**
	     * The default implementation of an `IContentFactory`.
	     */
	    var ContentFactory = (function () {
	        /**
	         * Creates a new renderer.
	         */
	        function ContentFactory(options) {
	            this.editorFactory = options.editorFactory;
	            this.notebookContentFactory = (options.notebookContentFactory ||
	                new widget_2.Notebook.ContentFactory({
	                    editorFactory: this.editorFactory,
	                    outputAreaContentFactory: options.outputAreaContentFactory,
	                    codeCellContentFactory: options.codeCellContentFactory,
	                    rawCellContentFactory: options.rawCellContentFactory,
	                    markdownCellContentFactory: options.markdownCellContentFactory
	                }));
	        }
	        /**
	         * Create a new content area for the panel.
	         */
	        ContentFactory.prototype.createNotebook = function (options) {
	            return new widget_2.Notebook(options);
	        };
	        /**
	         * Create a new toolbar for the panel.
	         */
	        ContentFactory.prototype.createToolbar = function () {
	            return new toolbar_1.Toolbar();
	        };
	        /**
	         * The inspection handler for a console widget.
	         */
	        ContentFactory.prototype.createInspectionHandler = function (options) {
	            return new inspector_1.InspectionHandler(options);
	        };
	        /**
	         * The completer widget for a console widget.
	         */
	        ContentFactory.prototype.createCompleter = function (options) {
	            return new completer_1.CompleterWidget(options);
	        };
	        /**
	         * The completer handler for a console widget.
	         */
	        ContentFactory.prototype.createCompleterHandler = function (options) {
	            return new completer_1.CompletionHandler(options);
	        };
	        return ContentFactory;
	    }());
	    NotebookPanel.ContentFactory = ContentFactory;
	    /* tslint:disable */
	    /**
	     * The notebook renderer token.
	     */
	    NotebookPanel.IContentFactory = new token_1.Token('jupyter.services.notebook.content-factory');
	})(NotebookPanel = exports.NotebookPanel || (exports.NotebookPanel = {}));
	//# sourceMappingURL=panel.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/panel.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/tracker.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/tracker.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var token_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/token.js');
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	/* tslint:disable */
	/**
	 * The notebook tracker token.
	 */
	exports.INotebookTracker = new token_1.Token('jupyter.services.notebooks');
	/* tslint:enable */
	var NotebookTracker = (function (_super) {
	    __extends(NotebookTracker, _super);
	    function NotebookTracker() {
	        _super.apply(this, arguments);
	        this._activeCell = null;
	    }
	    Object.defineProperty(NotebookTracker.prototype, "activeCell", {
	        /**
	         * The currently focused cell.
	         *
	         * #### Notes
	         * This is a read-only property. If there is no cell with the focus, then this
	         * value is `null`.
	         */
	        get: function () {
	            var widget = this.currentWidget;
	            if (!widget) {
	                return null;
	            }
	            return widget.notebook.activeCell || null;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Add a new notebook panel to the tracker.
	     *
	     * @param panel - The notebook panel being added.
	     */
	    NotebookTracker.prototype.add = function (panel) {
	        var promise = _super.prototype.add.call(this, panel);
	        panel.notebook.activeCellChanged.connect(this._onActiveCellChanged, this);
	        return promise;
	    };
	    /**
	     * Dispose of the resources held by the tracker.
	     */
	    NotebookTracker.prototype.dispose = function () {
	        this._activeCell = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle the current change event.
	     */
	    NotebookTracker.prototype.onCurrentChanged = function () {
	        // Store an internal reference to active cell to prevent false positives.
	        var activeCell = this.activeCell;
	        if (activeCell && activeCell === this._activeCell) {
	            return;
	        }
	        this._activeCell = activeCell;
	        var widget = this.currentWidget;
	        if (!widget) {
	            return;
	        }
	        // Since the notebook has changed, immediately signal an active cell change.
	        this.activeCellChanged.emit(widget.notebook.activeCell || null);
	    };
	    NotebookTracker.prototype._onActiveCellChanged = function (sender, cell) {
	        // Check if the active cell change happened for the current notebook.
	        if (this.currentWidget && this.currentWidget.notebook === sender) {
	            this._activeCell = cell || null;
	            this.activeCellChanged.emit(this._activeCell);
	        }
	    };
	    return NotebookTracker;
	}(instancetracker_1.InstanceTracker));
	exports.NotebookTracker = NotebookTracker;
	// Define the signals for the `NotebookTracker` class.
	signaling_1.defineSignal(NotebookTracker.prototype, 'activeCellChanged');
	//# sourceMappingURL=tracker.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/tracker.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/trust.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/trust.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var dialog_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dialog.js');
	// The message to display to the user when prompting to trust the notebook.
	var TRUST_MESSAGE = '<p>A trusted Jupyter notebook may execute hidden malicious code when you open it.<br>Selecting trust will re-render this notebook in a trusted state.<br>For more information, see the <a href="http://ipython.org/ipython-doc/2/notebook/security.html">Jupyter security documentation</a>.</p>';
	/**
	 * Trust the notebook after prompting the user.
	 *
	 * @param model - The notebook model.
	 *
	 * @param host - The host node for the confirmation dialog (defaults to body).
	 *
	 * @returns a promise that resolves when the transaction is finished.
	 *
	 * #### Notes
	 * No dialog will be presented if the notebook is already trusted.
	 */
	function trustNotebook(model, host) {
	    if (!model) {
	        return Promise.resolve(void 0);
	    }
	    // Do nothing if already trusted.
	    var cells = model.cells;
	    var trusted = true;
	    for (var i = 0; i < cells.length; i++) {
	        var cell = cells.at(i);
	        if (!cell.getMetadata('trusted').getValue()) {
	            trusted = false;
	        }
	    }
	    if (trusted) {
	        return dialog_1.showDialog({
	            body: 'Notebook is already trusted',
	            buttons: [dialog_1.okButton]
	        }).then(function () { return void 0; });
	    }
	    return dialog_1.showDialog({
	        body: TRUST_MESSAGE,
	        title: 'Trust this notebook?',
	        buttons: [dialog_1.cancelButton, dialog_1.warnButton]
	    }).then(function (result) {
	        if (result.text === 'OK') {
	            for (var i = 0; i < cells.length; i++) {
	                var cell = cells.at(i);
	                cell.getMetadata('trusted').setValue(true);
	            }
	        }
	    });
	}
	exports.trustNotebook = trustNotebook;
	//# sourceMappingURL=trust.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/trust.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/widgetfactory.js **/
jupyter.define('jupyterlab@0.15.1/lib/notebook/widgetfactory.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var docregistry_1 = __jupyter_require__('jupyterlab@0.15.1/lib/docregistry/index.js');
	var default_toolbar_1 = __jupyter_require__('jupyterlab@0.15.1/lib/notebook/default-toolbar.js');
	var panel_1 = __jupyter_require__('jupyterlab@0.15.1/lib/notebook/panel.js');
	/**
	 * A widget factory for notebook panels.
	 */
	var NotebookWidgetFactory = (function (_super) {
	    __extends(NotebookWidgetFactory, _super);
	    /**
	     * Construct a new notebook widget factory.
	     *
	     * @param options - The options used to construct the factory.
	     */
	    function NotebookWidgetFactory(options) {
	        _super.call(this, options);
	        this.rendermime = options.rendermime;
	        this.clipboard = options.clipboard;
	        this.contentFactory = options.contentFactory;
	        this.mimeTypeService = options.mimeTypeService;
	    }
	    /**
	     * Create a new widget.
	     *
	     * #### Notes
	     * The factory will start the appropriate kernel and populate
	     * the default toolbar items using `ToolbarItems.populateDefaults`.
	     */
	    NotebookWidgetFactory.prototype.createNewWidget = function (context) {
	        var rendermime = this.rendermime.clone();
	        var panel = new panel_1.NotebookPanel({
	            rendermime: rendermime,
	            clipboard: this.clipboard,
	            contentFactory: this.contentFactory,
	            mimeTypeService: this.mimeTypeService
	        });
	        panel.context = context;
	        default_toolbar_1.ToolbarItems.populateDefaults(panel);
	        return panel;
	    };
	    return NotebookWidgetFactory;
	}(docregistry_1.ABCWidgetFactory));
	exports.NotebookWidgetFactory = NotebookWidgetFactory;
	//# sourceMappingURL=widgetfactory.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/notebook/widgetfactory.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/rendermime/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/rendermime/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var sanitizer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/sanitizer.js');
	var commandlinker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandlinker/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/rendermime/index.js');
	/**
	 * The default rendermime provider.
	 */
	var plugin = {
	    id: 'jupyter.services.rendermime',
	    requires: [commandlinker_1.ICommandLinker],
	    provides: _1.IRenderMime,
	    activate: activate,
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the rendermine plugin.
	 */
	function activate(app, linker) {
	    var sanitizer = sanitizer_1.defaultSanitizer;
	    var transformers = _1.RenderMime.defaultRenderers();
	    var renderers = {};
	    var order = [];
	    for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) {
	        var t = transformers_1[_i];
	        for (var _a = 0, _b = t.mimetypes; _a < _b.length; _a++) {
	            var m = _b[_a];
	            renderers[m] = t;
	            order.push(m);
	        }
	    }
	    var linkHandler = {
	        handleLink: function (node, path) {
	            if (!services_1.utils.urlParse(path).protocol && path.indexOf('//') !== 0) {
	                linker.connectNode(node, filebrowser_1.CommandIDs.open, { path: path });
	            }
	        }
	    };
	    return new _1.RenderMime({
	        renderers: renderers,
	        order: order,
	        sanitizer: sanitizer,
	        linkHandler: linkHandler
	    });
	}
	;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/rendermime/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/common/sanitizer.js **/
jupyter.define('jupyterlab@0.15.1/lib/common/sanitizer.js', function (module, exports, __jupyter_require__) {
	"use strict";
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	var sanitize = __jupyter_require__('sanitize-html@^1.12.0/index.js');
	/**
	 * A class to sanitize HTML strings.
	 */
	var Sanitizer = (function () {
	    function Sanitizer() {
	        this._options = {
	            allowedTags: sanitize.defaults.allowedTags
	                .concat('svg', 'h1', 'h2', 'img', 'span'),
	            allowedAttributes: {
	                // Allow the "rel" attribute for <a> tags.
	                'a': sanitize.defaults.allowedAttributes['a'].concat('rel'),
	                // Allow the "src" attribute for <img> tags.
	                'img': ['src', 'height', 'width', 'alt'],
	                // Allow "class" attribute for <code> tags.
	                'code': ['class'],
	                // Allow "class" attribute for <span> tags.
	                'span': ['class']
	            },
	            transformTags: {
	                // Set the "rel" attribute for <a> tags to "nofollow".
	                'a': sanitize.simpleTransform('a', { 'rel': 'nofollow' })
	            }
	        };
	    }
	    /**
	     * Sanitize an HTML string.
	     */
	    Sanitizer.prototype.sanitize = function (dirty) {
	        return sanitize(dirty, this._options);
	    };
	    return Sanitizer;
	}());
	/**
	 * The default instance of an `ISanitizer` meant for use by user code.
	 */
	exports.defaultSanitizer = new Sanitizer();
	//# sourceMappingURL=sanitizer.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/common/sanitizer.js **/


/** START DEFINE BLOCK for sanitize-html@1.14.1/index.js **/
jupyter.define('sanitize-html@1.14.1/index.js', function (module, exports, __jupyter_require__) {
	var htmlparser = __jupyter_require__('htmlparser2@^3.9.0/lib/index.js');
	var extend = __jupyter_require__('xtend@^4.0.0/immutable.js');
	var quoteRegexp = __jupyter_require__('regexp-quote@0.0.0/regexp-quote.js');
	
	function each(obj, cb) {
	  if (obj) Object.keys(obj).forEach(function (key) {
	    cb(obj[key], key);
	  });
	}
	
	// Avoid false positives with .__proto__, .hasOwnProperty, etc.
	function has(obj, key) {
	  return ({}).hasOwnProperty.call(obj, key);
	}
	
	module.exports = sanitizeHtml;
	
	// Ignore the _recursing flag; it's there for recursive
	// invocation as a guard against this exploit:
	// https://github.com/fb55/htmlparser2/issues/105
	
	function sanitizeHtml(html, options, _recursing) {
	  var result = '';
	
	  function Frame(tag, attribs) {
	    var that = this;
	    this.tag = tag;
	    this.attribs = attribs || {};
	    this.tagPosition = result.length;
	    this.text = ''; // Node inner text
	
	    this.updateParentNodeText = function() {
	      if (stack.length) {
	          var parentFrame = stack[stack.length - 1];
	          parentFrame.text += that.text;
	      }
	    };
	  }
	
	  if (!options) {
	    options = sanitizeHtml.defaults;
	    options.parser = htmlParserDefaults;
	  } else {
	    options = extend(sanitizeHtml.defaults, options);
	    if (options.parser) {
	      options.parser = extend(htmlParserDefaults, options.parser);
	    } else {
	      options.parser = htmlParserDefaults;
	    }
	  }
	
	  // Tags that contain something other than HTML, or where discarding
	  // the text when the tag is disallowed makes sense for other reasons.
	  // If we are not allowing these tags, we should drop their content too.
	  // For other tags you would drop the tag but keep its content.
	  var nonTextTagsArray = options.nonTextTags || [ 'script', 'style', 'textarea' ];
	  var allowedAttributesMap;
	  var allowedAttributesGlobMap;
	  if(options.allowedAttributes) {
	    allowedAttributesMap = {};
	    allowedAttributesGlobMap = {};
	    each(options.allowedAttributes, function(attributes, tag) {
	      allowedAttributesMap[tag] = [];
	      var globRegex = [];
	      attributes.forEach(function(name) {
	        if(name.indexOf('*') >= 0) {
	          globRegex.push(quoteRegexp(name).replace(/\\\*/g, '.*'));
	        } else {
	          allowedAttributesMap[tag].push(name);
	        }
	      });
	      allowedAttributesGlobMap[tag] = new RegExp('^(' + globRegex.join('|') + ')$');
	    });
	  }
	  var allowedClassesMap = {};
	  each(options.allowedClasses, function(classes, tag) {
	    // Implicitly allows the class attribute
	    if(allowedAttributesMap) {
	      if (!has(allowedAttributesMap, tag)) {
	        allowedAttributesMap[tag] = [];
	      }
	      allowedAttributesMap[tag].push('class');
	    }
	
	    allowedClassesMap[tag] = classes;
	  });
	
	  var transformTagsMap = {};
	  var transformTagsAll;
	  each(options.transformTags, function(transform, tag) {
	    var transFun;
	    if (typeof transform === 'function') {
	      transFun = transform;
	    } else if (typeof transform === "string") {
	      transFun = sanitizeHtml.simpleTransform(transform);
	    }
	    if (tag === '*') {
	      transformTagsAll = transFun;
	    } else {
	      transformTagsMap[tag] = transFun;
	    }
	  });
	
	  var depth = 0;
	  var stack = [];
	  var skipMap = {};
	  var transformMap = {};
	  var skipText = false;
	  var skipTextDepth = 0;
	
	  var parser = new htmlparser.Parser({
	    onopentag: function(name, attribs) {
	      if (skipText) {
	        skipTextDepth++;
	        return;
	      }
	      var frame = new Frame(name, attribs);
	      stack.push(frame);
	
	      var skip = false;
	      var hasText = frame.text ? true : false;
	      var transformedTag;
	      if (has(transformTagsMap, name)) {
	        transformedTag = transformTagsMap[name](name, attribs);
	
	        frame.attribs = attribs = transformedTag.attribs;
	
	        if (transformedTag.text !== undefined) {
	          frame.innerText = transformedTag.text;
	        }
	
	        if (name !== transformedTag.tagName) {
	          frame.name = name = transformedTag.tagName;
	          transformMap[depth] = transformedTag.tagName;
	        }
	      }
	      if (transformTagsAll) {
	        transformedTag = transformTagsAll(name, attribs);
	
	        frame.attribs = attribs = transformedTag.attribs;
	        if (name !== transformedTag.tagName) {
	          frame.name = name = transformedTag.tagName;
	          transformMap[depth] = transformedTag.tagName;
	        }
	      }
	
	      if (options.allowedTags && options.allowedTags.indexOf(name) === -1) {
	        skip = true;
	        if (nonTextTagsArray.indexOf(name) !== -1) {
	          skipText = true;
	          skipTextDepth = 1;
	        }
	        skipMap[depth] = true;
	      }
	      depth++;
	      if (skip) {
	        // We want the contents but not this tag
	        return;
	      }
	      result += '<' + name;
	      if (!allowedAttributesMap || has(allowedAttributesMap, name) || allowedAttributesMap['*']) {
	        each(attribs, function(value, a) {
	          if (!allowedAttributesMap ||
	              (has(allowedAttributesMap, name) && allowedAttributesMap[name].indexOf(a) !== -1 ) ||
	              (allowedAttributesMap['*'] && allowedAttributesMap['*'].indexOf(a) !== -1 ) ||
	              (has(allowedAttributesGlobMap, name) && allowedAttributesGlobMap[name].test(a)) ||
	              (allowedAttributesGlobMap['*'] && allowedAttributesGlobMap['*'].test(a))) {
	            if ((a === 'href') || (a === 'src')) {
	              if (naughtyHref(name, value)) {
	                delete frame.attribs[a];
	                return;
	              }
	            }
	            if (a === 'class') {
	              value = filterClasses(value, allowedClassesMap[name]);
	              if (!value.length) {
	                delete frame.attribs[a];
	                return;
	              }
	            }
	            result += ' ' + a;
	            if (value.length) {
	              result += '="' + escapeHtml(value) + '"';
	            }
	          } else {
	            delete frame.attribs[a];
	          }
	        });
	      }
	      if (options.selfClosing.indexOf(name) !== -1) {
	        result += " />";
	      } else {
	        result += ">";
	        if (frame.innerText && !hasText && !options.textFilter) {
	          result += frame.innerText;
	        }
	      }
	    },
	    ontext: function(text) {
	      if (skipText) {
	        return;
	      }
	      var lastFrame = stack[stack.length-1];
	      var tag;
	
	      if (lastFrame) {
	        tag = lastFrame.tag;
	        // If inner text was set by transform function then let's use it
	        text = lastFrame.innerText !== undefined ? lastFrame.innerText : text;
	      }
	
	      if ((tag === 'script') || (tag === 'style')) {
	        // htmlparser2 gives us these as-is. Escaping them ruins the content. Allowing
	        // script tags is, by definition, game over for XSS protection, so if that's
	        // your concern, don't allow them. The same is essentially true for style tags
	        // which have their own collection of XSS vectors.
	        result += text;
	      } else {
	        var escaped = escapeHtml(text);
	        if (options.textFilter) {
	          result += options.textFilter(escaped);
	        } else {
	          result += escaped;
	        }
	      }
	      if (stack.length) {
	           var frame = stack[stack.length - 1];
	           frame.text += text;
	      }
	    },
	    onclosetag: function(name) {
	
	      if (skipText) {
	        skipTextDepth--;
	        if (!skipTextDepth) {
	          skipText = false;
	        } else {
	          return;
	        }
	      }
	
	      var frame = stack.pop();
	      if (!frame) {
	        // Do not crash on bad markup
	        return;
	      }
	      skipText = false;
	      depth--;
	      if (skipMap[depth]) {
	        delete skipMap[depth];
	        frame.updateParentNodeText();
	        return;
	      }
	
	      if (transformMap[depth]) {
	        name = transformMap[depth];
	        delete transformMap[depth];
	      }
	
	      if (options.exclusiveFilter && options.exclusiveFilter(frame)) {
	         result = result.substr(0, frame.tagPosition);
	         return;
	      }
	
	      frame.updateParentNodeText();
	
	      if (options.selfClosing.indexOf(name) !== -1) {
	         // Already output />
	         return;
	      }
	
	      result += "</" + name + ">";
	    }
	  }, options.parser);
	  parser.write(html);
	  parser.end();
	
	  return result;
	
	  function escapeHtml(s) {
	    if (typeof(s) !== 'string') {
	      s = s + '';
	    }
	    return s.replace(/\&/g, '&amp;').replace(/</g, '&lt;').replace(/\>/g, '&gt;').replace(/\"/g, '&quot;');
	  }
	
	  function naughtyHref(name, href) {
	    // Browsers ignore character codes of 32 (space) and below in a surprising
	    // number of situations. Start reading here:
	    // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Embedded_tab
	    href = href.replace(/[\x00-\x20]+/g, '');
	    // Clobber any comments in URLs, which the browser might
	    // interpret inside an XML data island, allowing
	    // a javascript: URL to be snuck through
	    href = href.replace(/<\!\-\-.*?\-\-\>/g, '');
	    // Case insensitive so we don't get faked out by JAVASCRIPT #1
	    var matches = href.match(/^([a-zA-Z]+)\:/);
	    if (!matches) {
	      // Protocol-relative URL: "//some.evil.com/nasty"
	      if (href.match(/^\/\//)) {
	        return !options.allowProtocolRelative;
	      }
	
	      // No scheme
	      return false;
	    }
	    var scheme = matches[1].toLowerCase();
	
	    if (has(options.allowedSchemesByTag, name)) {
	      return options.allowedSchemesByTag[name].indexOf(scheme) === -1;
	    }
	
	    return !options.allowedSchemes || options.allowedSchemes.indexOf(scheme) === -1;
	  }
	
	  function filterClasses(classes, allowed) {
	    if (!allowed) {
	      // The class attribute is allowed without filtering on this tag
	      return classes;
	    }
	    classes = classes.split(/\s+/);
	    return classes.filter(function(clss) {
	      return allowed.indexOf(clss) !== -1;
	    }).join(' ');
	  }
	}
	
	// Defaults are accessible to you so that you can use them as a starting point
	// programmatically if you wish
	
	var htmlParserDefaults = {
	  decodeEntities: true
	};
	sanitizeHtml.defaults = {
	  allowedTags: [ 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
	    'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div',
	    'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre' ],
	  allowedAttributes: {
	    a: [ 'href', 'name', 'target' ],
	    // We don't currently allow img itself by default, but this
	    // would make sense if we did
	    img: [ 'src' ]
	  },
	  // Lots of these won't come up by default because we don't allow them
	  selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ],
	  // URL schemes we permit
	  allowedSchemes: [ 'http', 'https', 'ftp', 'mailto' ],
	  allowedSchemesByTag: {},
	  allowProtocolRelative: true
	};
	
	sanitizeHtml.simpleTransform = function(newTagName, newAttribs, merge) {
	  merge = (merge === undefined) ? true : merge;
	  newAttribs = newAttribs || {};
	
	  return function(tagName, attribs) {
	    var attrib;
	    if (merge) {
	      for (attrib in newAttribs) {
	        attribs[attrib] = newAttribs[attrib];
	      }
	    } else {
	      attribs = newAttribs;
	    }
	
	    return {
	      tagName: newTagName,
	      attribs: attribs
	    };
	  };
	};
	
})
/** END DEFINE BLOCK for sanitize-html@1.14.1/index.js **/


/** START DEFINE BLOCK for htmlparser2@3.9.2/lib/index.js **/
jupyter.define('htmlparser2@3.9.2/lib/index.js', function (module, exports, __jupyter_require__) {
	var Parser = __jupyter_require__('htmlparser2@3.9.2/lib/Parser.js'),
	    DomHandler = __jupyter_require__('domhandler@^2.3.0/index.js');
	
	function defineProp(name, value){
		delete module.exports[name];
		module.exports[name] = value;
		return value;
	}
	
	module.exports = {
		Parser: Parser,
		Tokenizer: __jupyter_require__('htmlparser2@3.9.2/lib/Tokenizer.js'),
		ElementType: __jupyter_require__('domelementtype@^1.3.0/index.js'),
		DomHandler: DomHandler,
		get FeedHandler(){
			return defineProp("FeedHandler", __jupyter_require__('htmlparser2@3.9.2/lib/FeedHandler.js'));
		},
		get Stream(){
			return defineProp("Stream", __jupyter_require__('htmlparser2@3.9.2/lib/Stream.js'));
		},
		get WritableStream(){
			return defineProp("WritableStream", __jupyter_require__('htmlparser2@3.9.2/lib/WritableStream.js'));
		},
		get ProxyHandler(){
			return defineProp("ProxyHandler", __jupyter_require__('htmlparser2@3.9.2/lib/ProxyHandler.js'));
		},
		get DomUtils(){
			return defineProp("DomUtils", __jupyter_require__('domutils@^1.5.1/index.js'));
		},
		get CollectingHandler(){
			return defineProp("CollectingHandler", __jupyter_require__('htmlparser2@3.9.2/lib/CollectingHandler.js'));
		},
		// For legacy support
		DefaultHandler: DomHandler,
		get RssHandler(){
			return defineProp("RssHandler", this.FeedHandler);
		},
		//helper methods
		parseDOM: function(data, options){
			var handler = new DomHandler(options);
			new Parser(handler, options).end(data);
			return handler.dom;
		},
		parseFeed: function(feed, options){
			var handler = new module.exports.FeedHandler(options);
			new Parser(handler, options).end(feed);
			return handler.dom;
		},
		createDomStream: function(cb, options, elementCb){
			var handler = new DomHandler(cb, options, elementCb);
			return new Parser(handler, options);
		},
		// List of all events that the parser emits
		EVENTS: { /* Format: eventname: number of arguments */
			attribute: 2,
			cdatastart: 0,
			cdataend: 0,
			text: 1,
			processinginstruction: 2,
			comment: 1,
			commentend: 0,
			closetag: 1,
			opentag: 2,
			opentagname: 1,
			error: 1,
			end: 0
		}
	};
	
})
/** END DEFINE BLOCK for htmlparser2@3.9.2/lib/index.js **/


/** START DEFINE BLOCK for htmlparser2@3.9.2/lib/Parser.js **/
jupyter.define('htmlparser2@3.9.2/lib/Parser.js', function (module, exports, __jupyter_require__) {
	var Tokenizer = __jupyter_require__('htmlparser2@3.9.2/lib/Tokenizer.js');
	
	/*
		Options:
	
		xmlMode: Disables the special behavior for script/style tags (false by default)
		lowerCaseAttributeNames: call .toLowerCase for each attribute name (true if xmlMode is `false`)
		lowerCaseTags: call .toLowerCase for each tag name (true if xmlMode is `false`)
	*/
	
	/*
		Callbacks:
	
		oncdataend,
		oncdatastart,
		onclosetag,
		oncomment,
		oncommentend,
		onerror,
		onopentag,
		onprocessinginstruction,
		onreset,
		ontext
	*/
	
	var formTags = {
		input: true,
		option: true,
		optgroup: true,
		select: true,
		button: true,
		datalist: true,
		textarea: true
	};
	
	var openImpliesClose = {
		tr      : { tr:true, th:true, td:true },
		th      : { th:true },
		td      : { thead:true, th:true, td:true },
		body    : { head:true, link:true, script:true },
		li      : { li:true },
		p       : { p:true },
		h1      : { p:true },
		h2      : { p:true },
		h3      : { p:true },
		h4      : { p:true },
		h5      : { p:true },
		h6      : { p:true },
		select  : formTags,
		input   : formTags,
		output  : formTags,
		button  : formTags,
		datalist: formTags,
		textarea: formTags,
		option  : { option:true },
		optgroup: { optgroup:true }
	};
	
	var voidElements = {
		__proto__: null,
		area: true,
		base: true,
		basefont: true,
		br: true,
		col: true,
		command: true,
		embed: true,
		frame: true,
		hr: true,
		img: true,
		input: true,
		isindex: true,
		keygen: true,
		link: true,
		meta: true,
		param: true,
		source: true,
		track: true,
		wbr: true,
	
		//common self closing svg elements
		path: true,
		circle: true,
		ellipse: true,
		line: true,
		rect: true,
		use: true,
		stop: true,
		polyline: true,
		polygon: true
	};
	
	var re_nameEnd = /\s|\//;
	
	function Parser(cbs, options){
		this._options = options || {};
		this._cbs = cbs || {};
	
		this._tagname = "";
		this._attribname = "";
		this._attribvalue = "";
		this._attribs = null;
		this._stack = [];
	
		this.startIndex = 0;
		this.endIndex = null;
	
		this._lowerCaseTagNames = "lowerCaseTags" in this._options ?
										!!this._options.lowerCaseTags :
										!this._options.xmlMode;
		this._lowerCaseAttributeNames = "lowerCaseAttributeNames" in this._options ?
										!!this._options.lowerCaseAttributeNames :
										!this._options.xmlMode;
	
		if(this._options.Tokenizer) {
			Tokenizer = this._options.Tokenizer;
		}
		this._tokenizer = new Tokenizer(this._options, this);
	
		if(this._cbs.onparserinit) this._cbs.onparserinit(this);
	}
	
	__jupyter_require__('inherits@^2.0.1/inherits_browser.js')(Parser, __jupyter_require__('events@1.1.1/events.js').EventEmitter);
	
	Parser.prototype._updatePosition = function(initialOffset){
		if(this.endIndex === null){
			if(this._tokenizer._sectionStart <= initialOffset){
				this.startIndex = 0;
			} else {
				this.startIndex = this._tokenizer._sectionStart - initialOffset;
			}
		}
		else this.startIndex = this.endIndex + 1;
		this.endIndex = this._tokenizer.getAbsoluteIndex();
	};
	
	//Tokenizer event handlers
	Parser.prototype.ontext = function(data){
		this._updatePosition(1);
		this.endIndex--;
	
		if(this._cbs.ontext) this._cbs.ontext(data);
	};
	
	Parser.prototype.onopentagname = function(name){
		if(this._lowerCaseTagNames){
			name = name.toLowerCase();
		}
	
		this._tagname = name;
	
		if(!this._options.xmlMode && name in openImpliesClose) {
			for(
				var el;
				(el = this._stack[this._stack.length - 1]) in openImpliesClose[name];
				this.onclosetag(el)
			);
		}
	
		if(this._options.xmlMode || !(name in voidElements)){
			this._stack.push(name);
		}
	
		if(this._cbs.onopentagname) this._cbs.onopentagname(name);
		if(this._cbs.onopentag) this._attribs = {};
	};
	
	Parser.prototype.onopentagend = function(){
		this._updatePosition(1);
	
		if(this._attribs){
			if(this._cbs.onopentag) this._cbs.onopentag(this._tagname, this._attribs);
			this._attribs = null;
		}
	
		if(!this._options.xmlMode && this._cbs.onclosetag && this._tagname in voidElements){
			this._cbs.onclosetag(this._tagname);
		}
	
		this._tagname = "";
	};
	
	Parser.prototype.onclosetag = function(name){
		this._updatePosition(1);
	
		if(this._lowerCaseTagNames){
			name = name.toLowerCase();
		}
	
		if(this._stack.length && (!(name in voidElements) || this._options.xmlMode)){
			var pos = this._stack.lastIndexOf(name);
			if(pos !== -1){
				if(this._cbs.onclosetag){
					pos = this._stack.length - pos;
					while(pos--) this._cbs.onclosetag(this._stack.pop());
				}
				else this._stack.length = pos;
			} else if(name === "p" && !this._options.xmlMode){
				this.onopentagname(name);
				this._closeCurrentTag();
			}
		} else if(!this._options.xmlMode && (name === "br" || name === "p")){
			this.onopentagname(name);
			this._closeCurrentTag();
		}
	};
	
	Parser.prototype.onselfclosingtag = function(){
		if(this._options.xmlMode || this._options.recognizeSelfClosing){
			this._closeCurrentTag();
		} else {
			this.onopentagend();
		}
	};
	
	Parser.prototype._closeCurrentTag = function(){
		var name = this._tagname;
	
		this.onopentagend();
	
		//self-closing tags will be on the top of the stack
		//(cheaper check than in onclosetag)
		if(this._stack[this._stack.length - 1] === name){
			if(this._cbs.onclosetag){
				this._cbs.onclosetag(name);
			}
			this._stack.pop();
		}
	};
	
	Parser.prototype.onattribname = function(name){
		if(this._lowerCaseAttributeNames){
			name = name.toLowerCase();
		}
		this._attribname = name;
	};
	
	Parser.prototype.onattribdata = function(value){
		this._attribvalue += value;
	};
	
	Parser.prototype.onattribend = function(){
		if(this._cbs.onattribute) this._cbs.onattribute(this._attribname, this._attribvalue);
		if(
			this._attribs &&
			!Object.prototype.hasOwnProperty.call(this._attribs, this._attribname)
		){
			this._attribs[this._attribname] = this._attribvalue;
		}
		this._attribname = "";
		this._attribvalue = "";
	};
	
	Parser.prototype._getInstructionName = function(value){
		var idx = value.search(re_nameEnd),
		    name = idx < 0 ? value : value.substr(0, idx);
	
		if(this._lowerCaseTagNames){
			name = name.toLowerCase();
		}
	
		return name;
	};
	
	Parser.prototype.ondeclaration = function(value){
		if(this._cbs.onprocessinginstruction){
			var name = this._getInstructionName(value);
			this._cbs.onprocessinginstruction("!" + name, "!" + value);
		}
	};
	
	Parser.prototype.onprocessinginstruction = function(value){
		if(this._cbs.onprocessinginstruction){
			var name = this._getInstructionName(value);
			this._cbs.onprocessinginstruction("?" + name, "?" + value);
		}
	};
	
	Parser.prototype.oncomment = function(value){
		this._updatePosition(4);
	
		if(this._cbs.oncomment) this._cbs.oncomment(value);
		if(this._cbs.oncommentend) this._cbs.oncommentend();
	};
	
	Parser.prototype.oncdata = function(value){
		this._updatePosition(1);
	
		if(this._options.xmlMode || this._options.recognizeCDATA){
			if(this._cbs.oncdatastart) this._cbs.oncdatastart();
			if(this._cbs.ontext) this._cbs.ontext(value);
			if(this._cbs.oncdataend) this._cbs.oncdataend();
		} else {
			this.oncomment("[CDATA[" + value + "]]");
		}
	};
	
	Parser.prototype.onerror = function(err){
		if(this._cbs.onerror) this._cbs.onerror(err);
	};
	
	Parser.prototype.onend = function(){
		if(this._cbs.onclosetag){
			for(
				var i = this._stack.length;
				i > 0;
				this._cbs.onclosetag(this._stack[--i])
			);
		}
		if(this._cbs.onend) this._cbs.onend();
	};
	
	
	//Resets the parser to a blank state, ready to parse a new HTML document
	Parser.prototype.reset = function(){
		if(this._cbs.onreset) this._cbs.onreset();
		this._tokenizer.reset();
	
		this._tagname = "";
		this._attribname = "";
		this._attribs = null;
		this._stack = [];
	
		if(this._cbs.onparserinit) this._cbs.onparserinit(this);
	};
	
	//Parses a complete HTML document and pushes it to the handler
	Parser.prototype.parseComplete = function(data){
		this.reset();
		this.end(data);
	};
	
	Parser.prototype.write = function(chunk){
		this._tokenizer.write(chunk);
	};
	
	Parser.prototype.end = function(chunk){
		this._tokenizer.end(chunk);
	};
	
	Parser.prototype.pause = function(){
		this._tokenizer.pause();
	};
	
	Parser.prototype.resume = function(){
		this._tokenizer.resume();
	};
	
	//alias for backwards compat
	Parser.prototype.parseChunk = Parser.prototype.write;
	Parser.prototype.done = Parser.prototype.end;
	
	module.exports = Parser;
	
})
/** END DEFINE BLOCK for htmlparser2@3.9.2/lib/Parser.js **/


/** START DEFINE BLOCK for htmlparser2@3.9.2/lib/Tokenizer.js **/
jupyter.define('htmlparser2@3.9.2/lib/Tokenizer.js', function (module, exports, __jupyter_require__) {
	module.exports = Tokenizer;
	
	var decodeCodePoint = __jupyter_require__('entities@^1.1.1/lib/decode_codepoint.js'),
	    entityMap = __jupyter_require__('entities@^1.1.1/maps/entities.json'),
	    legacyMap = __jupyter_require__('entities@^1.1.1/maps/legacy.json'),
	    xmlMap    = __jupyter_require__('entities@^1.1.1/maps/xml.json'),
	
	    i = 0,
	
	    TEXT                      = i++,
	    BEFORE_TAG_NAME           = i++, //after <
	    IN_TAG_NAME               = i++,
	    IN_SELF_CLOSING_TAG       = i++,
	    BEFORE_CLOSING_TAG_NAME   = i++,
	    IN_CLOSING_TAG_NAME       = i++,
	    AFTER_CLOSING_TAG_NAME    = i++,
	
	    //attributes
	    BEFORE_ATTRIBUTE_NAME     = i++,
	    IN_ATTRIBUTE_NAME         = i++,
	    AFTER_ATTRIBUTE_NAME      = i++,
	    BEFORE_ATTRIBUTE_VALUE    = i++,
	    IN_ATTRIBUTE_VALUE_DQ     = i++, // "
	    IN_ATTRIBUTE_VALUE_SQ     = i++, // '
	    IN_ATTRIBUTE_VALUE_NQ     = i++,
	
	    //declarations
	    BEFORE_DECLARATION        = i++, // !
	    IN_DECLARATION            = i++,
	
	    //processing instructions
	    IN_PROCESSING_INSTRUCTION = i++, // ?
	
	    //comments
	    BEFORE_COMMENT            = i++,
	    IN_COMMENT                = i++,
	    AFTER_COMMENT_1           = i++,
	    AFTER_COMMENT_2           = i++,
	
	    //cdata
	    BEFORE_CDATA_1            = i++, // [
	    BEFORE_CDATA_2            = i++, // C
	    BEFORE_CDATA_3            = i++, // D
	    BEFORE_CDATA_4            = i++, // A
	    BEFORE_CDATA_5            = i++, // T
	    BEFORE_CDATA_6            = i++, // A
	    IN_CDATA                  = i++, // [
	    AFTER_CDATA_1             = i++, // ]
	    AFTER_CDATA_2             = i++, // ]
	
	    //special tags
	    BEFORE_SPECIAL            = i++, //S
	    BEFORE_SPECIAL_END        = i++,   //S
	
	    BEFORE_SCRIPT_1           = i++, //C
	    BEFORE_SCRIPT_2           = i++, //R
	    BEFORE_SCRIPT_3           = i++, //I
	    BEFORE_SCRIPT_4           = i++, //P
	    BEFORE_SCRIPT_5           = i++, //T
	    AFTER_SCRIPT_1            = i++, //C
	    AFTER_SCRIPT_2            = i++, //R
	    AFTER_SCRIPT_3            = i++, //I
	    AFTER_SCRIPT_4            = i++, //P
	    AFTER_SCRIPT_5            = i++, //T
	
	    BEFORE_STYLE_1            = i++, //T
	    BEFORE_STYLE_2            = i++, //Y
	    BEFORE_STYLE_3            = i++, //L
	    BEFORE_STYLE_4            = i++, //E
	    AFTER_STYLE_1             = i++, //T
	    AFTER_STYLE_2             = i++, //Y
	    AFTER_STYLE_3             = i++, //L
	    AFTER_STYLE_4             = i++, //E
	
	    BEFORE_ENTITY             = i++, //&
	    BEFORE_NUMERIC_ENTITY     = i++, //#
	    IN_NAMED_ENTITY           = i++,
	    IN_NUMERIC_ENTITY         = i++,
	    IN_HEX_ENTITY             = i++, //X
	
	    j = 0,
	
	    SPECIAL_NONE              = j++,
	    SPECIAL_SCRIPT            = j++,
	    SPECIAL_STYLE             = j++;
	
	function whitespace(c){
		return c === " " || c === "\n" || c === "\t" || c === "\f" || c === "\r";
	}
	
	function characterState(char, SUCCESS){
		return function(c){
			if(c === char) this._state = SUCCESS;
		};
	}
	
	function ifElseState(upper, SUCCESS, FAILURE){
		var lower = upper.toLowerCase();
	
		if(upper === lower){
			return function(c){
				if(c === lower){
					this._state = SUCCESS;
				} else {
					this._state = FAILURE;
					this._index--;
				}
			};
		} else {
			return function(c){
				if(c === lower || c === upper){
					this._state = SUCCESS;
				} else {
					this._state = FAILURE;
					this._index--;
				}
			};
		}
	}
	
	function consumeSpecialNameChar(upper, NEXT_STATE){
		var lower = upper.toLowerCase();
	
		return function(c){
			if(c === lower || c === upper){
				this._state = NEXT_STATE;
			} else {
				this._state = IN_TAG_NAME;
				this._index--; //consume the token again
			}
		};
	}
	
	function Tokenizer(options, cbs){
		this._state = TEXT;
		this._buffer = "";
		this._sectionStart = 0;
		this._index = 0;
		this._bufferOffset = 0; //chars removed from _buffer
		this._baseState = TEXT;
		this._special = SPECIAL_NONE;
		this._cbs = cbs;
		this._running = true;
		this._ended = false;
		this._xmlMode = !!(options && options.xmlMode);
		this._decodeEntities = !!(options && options.decodeEntities);
	}
	
	Tokenizer.prototype._stateText = function(c){
		if(c === "<"){
			if(this._index > this._sectionStart){
				this._cbs.ontext(this._getSection());
			}
			this._state = BEFORE_TAG_NAME;
			this._sectionStart = this._index;
		} else if(this._decodeEntities && this._special === SPECIAL_NONE && c === "&"){
			if(this._index > this._sectionStart){
				this._cbs.ontext(this._getSection());
			}
			this._baseState = TEXT;
			this._state = BEFORE_ENTITY;
			this._sectionStart = this._index;
		}
	};
	
	Tokenizer.prototype._stateBeforeTagName = function(c){
		if(c === "/"){
			this._state = BEFORE_CLOSING_TAG_NAME;
		} else if(c === "<"){
			this._cbs.ontext(this._getSection());
			this._sectionStart = this._index;
		} else if(c === ">" || this._special !== SPECIAL_NONE || whitespace(c)) {
			this._state = TEXT;
		} else if(c === "!"){
			this._state = BEFORE_DECLARATION;
			this._sectionStart = this._index + 1;
		} else if(c === "?"){
			this._state = IN_PROCESSING_INSTRUCTION;
			this._sectionStart = this._index + 1;
		} else {
			this._state = (!this._xmlMode && (c === "s" || c === "S")) ?
							BEFORE_SPECIAL : IN_TAG_NAME;
			this._sectionStart = this._index;
		}
	};
	
	Tokenizer.prototype._stateInTagName = function(c){
		if(c === "/" || c === ">" || whitespace(c)){
			this._emitToken("onopentagname");
			this._state = BEFORE_ATTRIBUTE_NAME;
			this._index--;
		}
	};
	
	Tokenizer.prototype._stateBeforeCloseingTagName = function(c){
		if(whitespace(c));
		else if(c === ">"){
			this._state = TEXT;
		} else if(this._special !== SPECIAL_NONE){
			if(c === "s" || c === "S"){
				this._state = BEFORE_SPECIAL_END;
			} else {
				this._state = TEXT;
				this._index--;
			}
		} else {
			this._state = IN_CLOSING_TAG_NAME;
			this._sectionStart = this._index;
		}
	};
	
	Tokenizer.prototype._stateInCloseingTagName = function(c){
		if(c === ">" || whitespace(c)){
			this._emitToken("onclosetag");
			this._state = AFTER_CLOSING_TAG_NAME;
			this._index--;
		}
	};
	
	Tokenizer.prototype._stateAfterCloseingTagName = function(c){
		//skip everything until ">"
		if(c === ">"){
			this._state = TEXT;
			this._sectionStart = this._index + 1;
		}
	};
	
	Tokenizer.prototype._stateBeforeAttributeName = function(c){
		if(c === ">"){
			this._cbs.onopentagend();
			this._state = TEXT;
			this._sectionStart = this._index + 1;
		} else if(c === "/"){
			this._state = IN_SELF_CLOSING_TAG;
		} else if(!whitespace(c)){
			this._state = IN_ATTRIBUTE_NAME;
			this._sectionStart = this._index;
		}
	};
	
	Tokenizer.prototype._stateInSelfClosingTag = function(c){
		if(c === ">"){
			this._cbs.onselfclosingtag();
			this._state = TEXT;
			this._sectionStart = this._index + 1;
		} else if(!whitespace(c)){
			this._state = BEFORE_ATTRIBUTE_NAME;
			this._index--;
		}
	};
	
	Tokenizer.prototype._stateInAttributeName = function(c){
		if(c === "=" || c === "/" || c === ">" || whitespace(c)){
			this._cbs.onattribname(this._getSection());
			this._sectionStart = -1;
			this._state = AFTER_ATTRIBUTE_NAME;
			this._index--;
		}
	};
	
	Tokenizer.prototype._stateAfterAttributeName = function(c){
		if(c === "="){
			this._state = BEFORE_ATTRIBUTE_VALUE;
		} else if(c === "/" || c === ">"){
			this._cbs.onattribend();
			this._state = BEFORE_ATTRIBUTE_NAME;
			this._index--;
		} else if(!whitespace(c)){
			this._cbs.onattribend();
			this._state = IN_ATTRIBUTE_NAME;
			this._sectionStart = this._index;
		}
	};
	
	Tokenizer.prototype._stateBeforeAttributeValue = function(c){
		if(c === "\""){
			this._state = IN_ATTRIBUTE_VALUE_DQ;
			this._sectionStart = this._index + 1;
		} else if(c === "'"){
			this._state = IN_ATTRIBUTE_VALUE_SQ;
			this._sectionStart = this._index + 1;
		} else if(!whitespace(c)){
			this._state = IN_ATTRIBUTE_VALUE_NQ;
			this._sectionStart = this._index;
			this._index--; //reconsume token
		}
	};
	
	Tokenizer.prototype._stateInAttributeValueDoubleQuotes = function(c){
		if(c === "\""){
			this._emitToken("onattribdata");
			this._cbs.onattribend();
			this._state = BEFORE_ATTRIBUTE_NAME;
		} else if(this._decodeEntities && c === "&"){
			this._emitToken("onattribdata");
			this._baseState = this._state;
			this._state = BEFORE_ENTITY;
			this._sectionStart = this._index;
		}
	};
	
	Tokenizer.prototype._stateInAttributeValueSingleQuotes = function(c){
		if(c === "'"){
			this._emitToken("onattribdata");
			this._cbs.onattribend();
			this._state = BEFORE_ATTRIBUTE_NAME;
		} else if(this._decodeEntities && c === "&"){
			this._emitToken("onattribdata");
			this._baseState = this._state;
			this._state = BEFORE_ENTITY;
			this._sectionStart = this._index;
		}
	};
	
	Tokenizer.prototype._stateInAttributeValueNoQuotes = function(c){
		if(whitespace(c) || c === ">"){
			this._emitToken("onattribdata");
			this._cbs.onattribend();
			this._state = BEFORE_ATTRIBUTE_NAME;
			this._index--;
		} else if(this._decodeEntities && c === "&"){
			this._emitToken("onattribdata");
			this._baseState = this._state;
			this._state = BEFORE_ENTITY;
			this._sectionStart = this._index;
		}
	};
	
	Tokenizer.prototype._stateBeforeDeclaration = function(c){
		this._state = c === "[" ? BEFORE_CDATA_1 :
						c === "-" ? BEFORE_COMMENT :
							IN_DECLARATION;
	};
	
	Tokenizer.prototype._stateInDeclaration = function(c){
		if(c === ">"){
			this._cbs.ondeclaration(this._getSection());
			this._state = TEXT;
			this._sectionStart = this._index + 1;
		}
	};
	
	Tokenizer.prototype._stateInProcessingInstruction = function(c){
		if(c === ">"){
			this._cbs.onprocessinginstruction(this._getSection());
			this._state = TEXT;
			this._sectionStart = this._index + 1;
		}
	};
	
	Tokenizer.prototype._stateBeforeComment = function(c){
		if(c === "-"){
			this._state = IN_COMMENT;
			this._sectionStart = this._index + 1;
		} else {
			this._state = IN_DECLARATION;
		}
	};
	
	Tokenizer.prototype._stateInComment = function(c){
		if(c === "-") this._state = AFTER_COMMENT_1;
	};
	
	Tokenizer.prototype._stateAfterComment1 = function(c){
		if(c === "-"){
			this._state = AFTER_COMMENT_2;
		} else {
			this._state = IN_COMMENT;
		}
	};
	
	Tokenizer.prototype._stateAfterComment2 = function(c){
		if(c === ">"){
			//remove 2 trailing chars
			this._cbs.oncomment(this._buffer.substring(this._sectionStart, this._index - 2));
			this._state = TEXT;
			this._sectionStart = this._index + 1;
		} else if(c !== "-"){
			this._state = IN_COMMENT;
		}
		// else: stay in AFTER_COMMENT_2 (`--->`)
	};
	
	Tokenizer.prototype._stateBeforeCdata1 = ifElseState("C", BEFORE_CDATA_2, IN_DECLARATION);
	Tokenizer.prototype._stateBeforeCdata2 = ifElseState("D", BEFORE_CDATA_3, IN_DECLARATION);
	Tokenizer.prototype._stateBeforeCdata3 = ifElseState("A", BEFORE_CDATA_4, IN_DECLARATION);
	Tokenizer.prototype._stateBeforeCdata4 = ifElseState("T", BEFORE_CDATA_5, IN_DECLARATION);
	Tokenizer.prototype._stateBeforeCdata5 = ifElseState("A", BEFORE_CDATA_6, IN_DECLARATION);
	
	Tokenizer.prototype._stateBeforeCdata6 = function(c){
		if(c === "["){
			this._state = IN_CDATA;
			this._sectionStart = this._index + 1;
		} else {
			this._state = IN_DECLARATION;
			this._index--;
		}
	};
	
	Tokenizer.prototype._stateInCdata = function(c){
		if(c === "]") this._state = AFTER_CDATA_1;
	};
	
	Tokenizer.prototype._stateAfterCdata1 = characterState("]", AFTER_CDATA_2);
	
	Tokenizer.prototype._stateAfterCdata2 = function(c){
		if(c === ">"){
			//remove 2 trailing chars
			this._cbs.oncdata(this._buffer.substring(this._sectionStart, this._index - 2));
			this._state = TEXT;
			this._sectionStart = this._index + 1;
		} else if(c !== "]") {
			this._state = IN_CDATA;
		}
		//else: stay in AFTER_CDATA_2 (`]]]>`)
	};
	
	Tokenizer.prototype._stateBeforeSpecial = function(c){
		if(c === "c" || c === "C"){
			this._state = BEFORE_SCRIPT_1;
		} else if(c === "t" || c === "T"){
			this._state = BEFORE_STYLE_1;
		} else {
			this._state = IN_TAG_NAME;
			this._index--; //consume the token again
		}
	};
	
	Tokenizer.prototype._stateBeforeSpecialEnd = function(c){
		if(this._special === SPECIAL_SCRIPT && (c === "c" || c === "C")){
			this._state = AFTER_SCRIPT_1;
		} else if(this._special === SPECIAL_STYLE && (c === "t" || c === "T")){
			this._state = AFTER_STYLE_1;
		}
		else this._state = TEXT;
	};
	
	Tokenizer.prototype._stateBeforeScript1 = consumeSpecialNameChar("R", BEFORE_SCRIPT_2);
	Tokenizer.prototype._stateBeforeScript2 = consumeSpecialNameChar("I", BEFORE_SCRIPT_3);
	Tokenizer.prototype._stateBeforeScript3 = consumeSpecialNameChar("P", BEFORE_SCRIPT_4);
	Tokenizer.prototype._stateBeforeScript4 = consumeSpecialNameChar("T", BEFORE_SCRIPT_5);
	
	Tokenizer.prototype._stateBeforeScript5 = function(c){
		if(c === "/" || c === ">" || whitespace(c)){
			this._special = SPECIAL_SCRIPT;
		}
		this._state = IN_TAG_NAME;
		this._index--; //consume the token again
	};
	
	Tokenizer.prototype._stateAfterScript1 = ifElseState("R", AFTER_SCRIPT_2, TEXT);
	Tokenizer.prototype._stateAfterScript2 = ifElseState("I", AFTER_SCRIPT_3, TEXT);
	Tokenizer.prototype._stateAfterScript3 = ifElseState("P", AFTER_SCRIPT_4, TEXT);
	Tokenizer.prototype._stateAfterScript4 = ifElseState("T", AFTER_SCRIPT_5, TEXT);
	
	Tokenizer.prototype._stateAfterScript5 = function(c){
		if(c === ">" || whitespace(c)){
			this._special = SPECIAL_NONE;
			this._state = IN_CLOSING_TAG_NAME;
			this._sectionStart = this._index - 6;
			this._index--; //reconsume the token
		}
		else this._state = TEXT;
	};
	
	Tokenizer.prototype._stateBeforeStyle1 = consumeSpecialNameChar("Y", BEFORE_STYLE_2);
	Tokenizer.prototype._stateBeforeStyle2 = consumeSpecialNameChar("L", BEFORE_STYLE_3);
	Tokenizer.prototype._stateBeforeStyle3 = consumeSpecialNameChar("E", BEFORE_STYLE_4);
	
	Tokenizer.prototype._stateBeforeStyle4 = function(c){
		if(c === "/" || c === ">" || whitespace(c)){
			this._special = SPECIAL_STYLE;
		}
		this._state = IN_TAG_NAME;
		this._index--; //consume the token again
	};
	
	Tokenizer.prototype._stateAfterStyle1 = ifElseState("Y", AFTER_STYLE_2, TEXT);
	Tokenizer.prototype._stateAfterStyle2 = ifElseState("L", AFTER_STYLE_3, TEXT);
	Tokenizer.prototype._stateAfterStyle3 = ifElseState("E", AFTER_STYLE_4, TEXT);
	
	Tokenizer.prototype._stateAfterStyle4 = function(c){
		if(c === ">" || whitespace(c)){
			this._special = SPECIAL_NONE;
			this._state = IN_CLOSING_TAG_NAME;
			this._sectionStart = this._index - 5;
			this._index--; //reconsume the token
		}
		else this._state = TEXT;
	};
	
	Tokenizer.prototype._stateBeforeEntity = ifElseState("#", BEFORE_NUMERIC_ENTITY, IN_NAMED_ENTITY);
	Tokenizer.prototype._stateBeforeNumericEntity = ifElseState("X", IN_HEX_ENTITY, IN_NUMERIC_ENTITY);
	
	//for entities terminated with a semicolon
	Tokenizer.prototype._parseNamedEntityStrict = function(){
		//offset = 1
		if(this._sectionStart + 1 < this._index){
			var entity = this._buffer.substring(this._sectionStart + 1, this._index),
			    map = this._xmlMode ? xmlMap : entityMap;
	
			if(map.hasOwnProperty(entity)){
				this._emitPartial(map[entity]);
				this._sectionStart = this._index + 1;
			}
		}
	};
	
	
	//parses legacy entities (without trailing semicolon)
	Tokenizer.prototype._parseLegacyEntity = function(){
		var start = this._sectionStart + 1,
		    limit = this._index - start;
	
		if(limit > 6) limit = 6; //the max length of legacy entities is 6
	
		while(limit >= 2){ //the min length of legacy entities is 2
			var entity = this._buffer.substr(start, limit);
	
			if(legacyMap.hasOwnProperty(entity)){
				this._emitPartial(legacyMap[entity]);
				this._sectionStart += limit + 1;
				return;
			} else {
				limit--;
			}
		}
	};
	
	Tokenizer.prototype._stateInNamedEntity = function(c){
		if(c === ";"){
			this._parseNamedEntityStrict();
			if(this._sectionStart + 1 < this._index && !this._xmlMode){
				this._parseLegacyEntity();
			}
			this._state = this._baseState;
		} else if((c < "a" || c > "z") && (c < "A" || c > "Z") && (c < "0" || c > "9")){
			if(this._xmlMode);
			else if(this._sectionStart + 1 === this._index);
			else if(this._baseState !== TEXT){
				if(c !== "="){
					this._parseNamedEntityStrict();
				}
			} else {
				this._parseLegacyEntity();
			}
	
			this._state = this._baseState;
			this._index--;
		}
	};
	
	Tokenizer.prototype._decodeNumericEntity = function(offset, base){
		var sectionStart = this._sectionStart + offset;
	
		if(sectionStart !== this._index){
			//parse entity
			var entity = this._buffer.substring(sectionStart, this._index);
			var parsed = parseInt(entity, base);
	
			this._emitPartial(decodeCodePoint(parsed));
			this._sectionStart = this._index;
		} else {
			this._sectionStart--;
		}
	
		this._state = this._baseState;
	};
	
	Tokenizer.prototype._stateInNumericEntity = function(c){
		if(c === ";"){
			this._decodeNumericEntity(2, 10);
			this._sectionStart++;
		} else if(c < "0" || c > "9"){
			if(!this._xmlMode){
				this._decodeNumericEntity(2, 10);
			} else {
				this._state = this._baseState;
			}
			this._index--;
		}
	};
	
	Tokenizer.prototype._stateInHexEntity = function(c){
		if(c === ";"){
			this._decodeNumericEntity(3, 16);
			this._sectionStart++;
		} else if((c < "a" || c > "f") && (c < "A" || c > "F") && (c < "0" || c > "9")){
			if(!this._xmlMode){
				this._decodeNumericEntity(3, 16);
			} else {
				this._state = this._baseState;
			}
			this._index--;
		}
	};
	
	Tokenizer.prototype._cleanup = function (){
		if(this._sectionStart < 0){
			this._buffer = "";
			this._bufferOffset += this._index;
			this._index = 0;
		} else if(this._running){
			if(this._state === TEXT){
				if(this._sectionStart !== this._index){
					this._cbs.ontext(this._buffer.substr(this._sectionStart));
				}
				this._buffer = "";
				this._bufferOffset += this._index;
				this._index = 0;
			} else if(this._sectionStart === this._index){
				//the section just started
				this._buffer = "";
				this._bufferOffset += this._index;
				this._index = 0;
			} else {
				//remove everything unnecessary
				this._buffer = this._buffer.substr(this._sectionStart);
				this._index -= this._sectionStart;
				this._bufferOffset += this._sectionStart;
			}
	
			this._sectionStart = 0;
		}
	};
	
	//TODO make events conditional
	Tokenizer.prototype.write = function(chunk){
		if(this._ended) this._cbs.onerror(Error(".write() after done!"));
	
		this._buffer += chunk;
		this._parse();
	};
	
	Tokenizer.prototype._parse = function(){
		while(this._index < this._buffer.length && this._running){
			var c = this._buffer.charAt(this._index);
			if(this._state === TEXT) {
				this._stateText(c);
			} else if(this._state === BEFORE_TAG_NAME){
				this._stateBeforeTagName(c);
			} else if(this._state === IN_TAG_NAME) {
				this._stateInTagName(c);
			} else if(this._state === BEFORE_CLOSING_TAG_NAME){
				this._stateBeforeCloseingTagName(c);
			} else if(this._state === IN_CLOSING_TAG_NAME){
				this._stateInCloseingTagName(c);
			} else if(this._state === AFTER_CLOSING_TAG_NAME){
				this._stateAfterCloseingTagName(c);
			} else if(this._state === IN_SELF_CLOSING_TAG){
				this._stateInSelfClosingTag(c);
			}
	
			/*
			*	attributes
			*/
			else if(this._state === BEFORE_ATTRIBUTE_NAME){
				this._stateBeforeAttributeName(c);
			} else if(this._state === IN_ATTRIBUTE_NAME){
				this._stateInAttributeName(c);
			} else if(this._state === AFTER_ATTRIBUTE_NAME){
				this._stateAfterAttributeName(c);
			} else if(this._state === BEFORE_ATTRIBUTE_VALUE){
				this._stateBeforeAttributeValue(c);
			} else if(this._state === IN_ATTRIBUTE_VALUE_DQ){
				this._stateInAttributeValueDoubleQuotes(c);
			} else if(this._state === IN_ATTRIBUTE_VALUE_SQ){
				this._stateInAttributeValueSingleQuotes(c);
			} else if(this._state === IN_ATTRIBUTE_VALUE_NQ){
				this._stateInAttributeValueNoQuotes(c);
			}
	
			/*
			*	declarations
			*/
			else if(this._state === BEFORE_DECLARATION){
				this._stateBeforeDeclaration(c);
			} else if(this._state === IN_DECLARATION){
				this._stateInDeclaration(c);
			}
	
			/*
			*	processing instructions
			*/
			else if(this._state === IN_PROCESSING_INSTRUCTION){
				this._stateInProcessingInstruction(c);
			}
	
			/*
			*	comments
			*/
			else if(this._state === BEFORE_COMMENT){
				this._stateBeforeComment(c);
			} else if(this._state === IN_COMMENT){
				this._stateInComment(c);
			} else if(this._state === AFTER_COMMENT_1){
				this._stateAfterComment1(c);
			} else if(this._state === AFTER_COMMENT_2){
				this._stateAfterComment2(c);
			}
	
			/*
			*	cdata
			*/
			else if(this._state === BEFORE_CDATA_1){
				this._stateBeforeCdata1(c);
			} else if(this._state === BEFORE_CDATA_2){
				this._stateBeforeCdata2(c);
			} else if(this._state === BEFORE_CDATA_3){
				this._stateBeforeCdata3(c);
			} else if(this._state === BEFORE_CDATA_4){
				this._stateBeforeCdata4(c);
			} else if(this._state === BEFORE_CDATA_5){
				this._stateBeforeCdata5(c);
			} else if(this._state === BEFORE_CDATA_6){
				this._stateBeforeCdata6(c);
			} else if(this._state === IN_CDATA){
				this._stateInCdata(c);
			} else if(this._state === AFTER_CDATA_1){
				this._stateAfterCdata1(c);
			} else if(this._state === AFTER_CDATA_2){
				this._stateAfterCdata2(c);
			}
	
			/*
			* special tags
			*/
			else if(this._state === BEFORE_SPECIAL){
				this._stateBeforeSpecial(c);
			} else if(this._state === BEFORE_SPECIAL_END){
				this._stateBeforeSpecialEnd(c);
			}
	
			/*
			* script
			*/
			else if(this._state === BEFORE_SCRIPT_1){
				this._stateBeforeScript1(c);
			} else if(this._state === BEFORE_SCRIPT_2){
				this._stateBeforeScript2(c);
			} else if(this._state === BEFORE_SCRIPT_3){
				this._stateBeforeScript3(c);
			} else if(this._state === BEFORE_SCRIPT_4){
				this._stateBeforeScript4(c);
			} else if(this._state === BEFORE_SCRIPT_5){
				this._stateBeforeScript5(c);
			}
	
			else if(this._state === AFTER_SCRIPT_1){
				this._stateAfterScript1(c);
			} else if(this._state === AFTER_SCRIPT_2){
				this._stateAfterScript2(c);
			} else if(this._state === AFTER_SCRIPT_3){
				this._stateAfterScript3(c);
			} else if(this._state === AFTER_SCRIPT_4){
				this._stateAfterScript4(c);
			} else if(this._state === AFTER_SCRIPT_5){
				this._stateAfterScript5(c);
			}
	
			/*
			* style
			*/
			else if(this._state === BEFORE_STYLE_1){
				this._stateBeforeStyle1(c);
			} else if(this._state === BEFORE_STYLE_2){
				this._stateBeforeStyle2(c);
			} else if(this._state === BEFORE_STYLE_3){
				this._stateBeforeStyle3(c);
			} else if(this._state === BEFORE_STYLE_4){
				this._stateBeforeStyle4(c);
			}
	
			else if(this._state === AFTER_STYLE_1){
				this._stateAfterStyle1(c);
			} else if(this._state === AFTER_STYLE_2){
				this._stateAfterStyle2(c);
			} else if(this._state === AFTER_STYLE_3){
				this._stateAfterStyle3(c);
			} else if(this._state === AFTER_STYLE_4){
				this._stateAfterStyle4(c);
			}
	
			/*
			* entities
			*/
			else if(this._state === BEFORE_ENTITY){
				this._stateBeforeEntity(c);
			} else if(this._state === BEFORE_NUMERIC_ENTITY){
				this._stateBeforeNumericEntity(c);
			} else if(this._state === IN_NAMED_ENTITY){
				this._stateInNamedEntity(c);
			} else if(this._state === IN_NUMERIC_ENTITY){
				this._stateInNumericEntity(c);
			} else if(this._state === IN_HEX_ENTITY){
				this._stateInHexEntity(c);
			}
	
			else {
				this._cbs.onerror(Error("unknown _state"), this._state);
			}
	
			this._index++;
		}
	
		this._cleanup();
	};
	
	Tokenizer.prototype.pause = function(){
		this._running = false;
	};
	Tokenizer.prototype.resume = function(){
		this._running = true;
	
		if(this._index < this._buffer.length){
			this._parse();
		}
		if(this._ended){
			this._finish();
		}
	};
	
	Tokenizer.prototype.end = function(chunk){
		if(this._ended) this._cbs.onerror(Error(".end() after done!"));
		if(chunk) this.write(chunk);
	
		this._ended = true;
	
		if(this._running) this._finish();
	};
	
	Tokenizer.prototype._finish = function(){
		//if there is remaining data, emit it in a reasonable way
		if(this._sectionStart < this._index){
			this._handleTrailingData();
		}
	
		this._cbs.onend();
	};
	
	Tokenizer.prototype._handleTrailingData = function(){
		var data = this._buffer.substr(this._sectionStart);
	
		if(this._state === IN_CDATA || this._state === AFTER_CDATA_1 || this._state === AFTER_CDATA_2){
			this._cbs.oncdata(data);
		} else if(this._state === IN_COMMENT || this._state === AFTER_COMMENT_1 || this._state === AFTER_COMMENT_2){
			this._cbs.oncomment(data);
		} else if(this._state === IN_NAMED_ENTITY && !this._xmlMode){
			this._parseLegacyEntity();
			if(this._sectionStart < this._index){
				this._state = this._baseState;
				this._handleTrailingData();
			}
		} else if(this._state === IN_NUMERIC_ENTITY && !this._xmlMode){
			this._decodeNumericEntity(2, 10);
			if(this._sectionStart < this._index){
				this._state = this._baseState;
				this._handleTrailingData();
			}
		} else if(this._state === IN_HEX_ENTITY && !this._xmlMode){
			this._decodeNumericEntity(3, 16);
			if(this._sectionStart < this._index){
				this._state = this._baseState;
				this._handleTrailingData();
			}
		} else if(
			this._state !== IN_TAG_NAME &&
			this._state !== BEFORE_ATTRIBUTE_NAME &&
			this._state !== BEFORE_ATTRIBUTE_VALUE &&
			this._state !== AFTER_ATTRIBUTE_NAME &&
			this._state !== IN_ATTRIBUTE_NAME &&
			this._state !== IN_ATTRIBUTE_VALUE_SQ &&
			this._state !== IN_ATTRIBUTE_VALUE_DQ &&
			this._state !== IN_ATTRIBUTE_VALUE_NQ &&
			this._state !== IN_CLOSING_TAG_NAME
		){
			this._cbs.ontext(data);
		}
		//else, ignore remaining data
		//TODO add a way to remove current tag
	};
	
	Tokenizer.prototype.reset = function(){
		Tokenizer.call(this, {xmlMode: this._xmlMode, decodeEntities: this._decodeEntities}, this._cbs);
	};
	
	Tokenizer.prototype.getAbsoluteIndex = function(){
		return this._bufferOffset + this._index;
	};
	
	Tokenizer.prototype._getSection = function(){
		return this._buffer.substring(this._sectionStart, this._index);
	};
	
	Tokenizer.prototype._emitToken = function(name){
		this._cbs[name](this._getSection());
		this._sectionStart = -1;
	};
	
	Tokenizer.prototype._emitPartial = function(value){
		if(this._baseState !== TEXT){
			this._cbs.onattribdata(value); //TODO implement the new event
		} else {
			this._cbs.ontext(value);
		}
	};
	
})
/** END DEFINE BLOCK for htmlparser2@3.9.2/lib/Tokenizer.js **/


/** START DEFINE BLOCK for entities@1.1.1/lib/decode_codepoint.js **/
jupyter.define('entities@1.1.1/lib/decode_codepoint.js', function (module, exports, __jupyter_require__) {
	var decodeMap = __jupyter_require__('entities@1.1.1/maps/decode.json');
	
	module.exports = decodeCodePoint;
	
	// modified version of https://github.com/mathiasbynens/he/blob/master/src/he.js#L94-L119
	function decodeCodePoint(codePoint){
	
		if((codePoint >= 0xD800 && codePoint <= 0xDFFF) || codePoint > 0x10FFFF){
			return "\uFFFD";
		}
	
		if(codePoint in decodeMap){
			codePoint = decodeMap[codePoint];
		}
	
		var output = "";
	
		if(codePoint > 0xFFFF){
			codePoint -= 0x10000;
			output += String.fromCharCode(codePoint >>> 10 & 0x3FF | 0xD800);
			codePoint = 0xDC00 | codePoint & 0x3FF;
		}
	
		output += String.fromCharCode(codePoint);
		return output;
	}
	
})
/** END DEFINE BLOCK for entities@1.1.1/lib/decode_codepoint.js **/


/** START DEFINE BLOCK for entities@1.1.1/maps/decode.json **/
jupyter.define('entities@1.1.1/maps/decode.json', function (module, exports, __jupyter_require__) {
	module.exports = {
		"0": 65533,
		"128": 8364,
		"130": 8218,
		"131": 402,
		"132": 8222,
		"133": 8230,
		"134": 8224,
		"135": 8225,
		"136": 710,
		"137": 8240,
		"138": 352,
		"139": 8249,
		"140": 338,
		"142": 381,
		"145": 8216,
		"146": 8217,
		"147": 8220,
		"148": 8221,
		"149": 8226,
		"150": 8211,
		"151": 8212,
		"152": 732,
		"153": 8482,
		"154": 353,
		"155": 8250,
		"156": 339,
		"158": 382,
		"159": 376
	};
})
/** END DEFINE BLOCK for entities@1.1.1/maps/decode.json **/


/** START DEFINE BLOCK for entities@1.1.1/maps/entities.json **/
jupyter.define('entities@1.1.1/maps/entities.json', function (module, exports, __jupyter_require__) {
	module.exports = {
		"Aacute": "Á",
		"aacute": "á",
		"Abreve": "Ă",
		"abreve": "ă",
		"ac": "∾",
		"acd": "∿",
		"acE": "∾̳",
		"Acirc": "Â",
		"acirc": "â",
		"acute": "´",
		"Acy": "А",
		"acy": "а",
		"AElig": "Æ",
		"aelig": "æ",
		"af": "⁡",
		"Afr": "𝔄",
		"afr": "𝔞",
		"Agrave": "À",
		"agrave": "à",
		"alefsym": "ℵ",
		"aleph": "ℵ",
		"Alpha": "Α",
		"alpha": "α",
		"Amacr": "Ā",
		"amacr": "ā",
		"amalg": "⨿",
		"amp": "&",
		"AMP": "&",
		"andand": "⩕",
		"And": "⩓",
		"and": "∧",
		"andd": "⩜",
		"andslope": "⩘",
		"andv": "⩚",
		"ang": "∠",
		"ange": "⦤",
		"angle": "∠",
		"angmsdaa": "⦨",
		"angmsdab": "⦩",
		"angmsdac": "⦪",
		"angmsdad": "⦫",
		"angmsdae": "⦬",
		"angmsdaf": "⦭",
		"angmsdag": "⦮",
		"angmsdah": "⦯",
		"angmsd": "∡",
		"angrt": "∟",
		"angrtvb": "⊾",
		"angrtvbd": "⦝",
		"angsph": "∢",
		"angst": "Å",
		"angzarr": "⍼",
		"Aogon": "Ą",
		"aogon": "ą",
		"Aopf": "𝔸",
		"aopf": "𝕒",
		"apacir": "⩯",
		"ap": "≈",
		"apE": "⩰",
		"ape": "≊",
		"apid": "≋",
		"apos": "'",
		"ApplyFunction": "⁡",
		"approx": "≈",
		"approxeq": "≊",
		"Aring": "Å",
		"aring": "å",
		"Ascr": "𝒜",
		"ascr": "𝒶",
		"Assign": "≔",
		"ast": "*",
		"asymp": "≈",
		"asympeq": "≍",
		"Atilde": "Ã",
		"atilde": "ã",
		"Auml": "Ä",
		"auml": "ä",
		"awconint": "∳",
		"awint": "⨑",
		"backcong": "≌",
		"backepsilon": "϶",
		"backprime": "‵",
		"backsim": "∽",
		"backsimeq": "⋍",
		"Backslash": "∖",
		"Barv": "⫧",
		"barvee": "⊽",
		"barwed": "⌅",
		"Barwed": "⌆",
		"barwedge": "⌅",
		"bbrk": "⎵",
		"bbrktbrk": "⎶",
		"bcong": "≌",
		"Bcy": "Б",
		"bcy": "б",
		"bdquo": "„",
		"becaus": "∵",
		"because": "∵",
		"Because": "∵",
		"bemptyv": "⦰",
		"bepsi": "϶",
		"bernou": "ℬ",
		"Bernoullis": "ℬ",
		"Beta": "Β",
		"beta": "β",
		"beth": "ℶ",
		"between": "≬",
		"Bfr": "𝔅",
		"bfr": "𝔟",
		"bigcap": "⋂",
		"bigcirc": "◯",
		"bigcup": "⋃",
		"bigodot": "⨀",
		"bigoplus": "⨁",
		"bigotimes": "⨂",
		"bigsqcup": "⨆",
		"bigstar": "★",
		"bigtriangledown": "▽",
		"bigtriangleup": "△",
		"biguplus": "⨄",
		"bigvee": "⋁",
		"bigwedge": "⋀",
		"bkarow": "⤍",
		"blacklozenge": "⧫",
		"blacksquare": "▪",
		"blacktriangle": "▴",
		"blacktriangledown": "▾",
		"blacktriangleleft": "◂",
		"blacktriangleright": "▸",
		"blank": "␣",
		"blk12": "▒",
		"blk14": "░",
		"blk34": "▓",
		"block": "█",
		"bne": "=⃥",
		"bnequiv": "≡⃥",
		"bNot": "⫭",
		"bnot": "⌐",
		"Bopf": "𝔹",
		"bopf": "𝕓",
		"bot": "⊥",
		"bottom": "⊥",
		"bowtie": "⋈",
		"boxbox": "⧉",
		"boxdl": "┐",
		"boxdL": "╕",
		"boxDl": "╖",
		"boxDL": "╗",
		"boxdr": "┌",
		"boxdR": "╒",
		"boxDr": "╓",
		"boxDR": "╔",
		"boxh": "─",
		"boxH": "═",
		"boxhd": "┬",
		"boxHd": "╤",
		"boxhD": "╥",
		"boxHD": "╦",
		"boxhu": "┴",
		"boxHu": "╧",
		"boxhU": "╨",
		"boxHU": "╩",
		"boxminus": "⊟",
		"boxplus": "⊞",
		"boxtimes": "⊠",
		"boxul": "┘",
		"boxuL": "╛",
		"boxUl": "╜",
		"boxUL": "╝",
		"boxur": "└",
		"boxuR": "╘",
		"boxUr": "╙",
		"boxUR": "╚",
		"boxv": "│",
		"boxV": "║",
		"boxvh": "┼",
		"boxvH": "╪",
		"boxVh": "╫",
		"boxVH": "╬",
		"boxvl": "┤",
		"boxvL": "╡",
		"boxVl": "╢",
		"boxVL": "╣",
		"boxvr": "├",
		"boxvR": "╞",
		"boxVr": "╟",
		"boxVR": "╠",
		"bprime": "‵",
		"breve": "˘",
		"Breve": "˘",
		"brvbar": "¦",
		"bscr": "𝒷",
		"Bscr": "ℬ",
		"bsemi": "⁏",
		"bsim": "∽",
		"bsime": "⋍",
		"bsolb": "⧅",
		"bsol": "\\",
		"bsolhsub": "⟈",
		"bull": "•",
		"bullet": "•",
		"bump": "≎",
		"bumpE": "⪮",
		"bumpe": "≏",
		"Bumpeq": "≎",
		"bumpeq": "≏",
		"Cacute": "Ć",
		"cacute": "ć",
		"capand": "⩄",
		"capbrcup": "⩉",
		"capcap": "⩋",
		"cap": "∩",
		"Cap": "⋒",
		"capcup": "⩇",
		"capdot": "⩀",
		"CapitalDifferentialD": "ⅅ",
		"caps": "∩︀",
		"caret": "⁁",
		"caron": "ˇ",
		"Cayleys": "ℭ",
		"ccaps": "⩍",
		"Ccaron": "Č",
		"ccaron": "č",
		"Ccedil": "Ç",
		"ccedil": "ç",
		"Ccirc": "Ĉ",
		"ccirc": "ĉ",
		"Cconint": "∰",
		"ccups": "⩌",
		"ccupssm": "⩐",
		"Cdot": "Ċ",
		"cdot": "ċ",
		"cedil": "¸",
		"Cedilla": "¸",
		"cemptyv": "⦲",
		"cent": "¢",
		"centerdot": "·",
		"CenterDot": "·",
		"cfr": "𝔠",
		"Cfr": "ℭ",
		"CHcy": "Ч",
		"chcy": "ч",
		"check": "✓",
		"checkmark": "✓",
		"Chi": "Χ",
		"chi": "χ",
		"circ": "ˆ",
		"circeq": "≗",
		"circlearrowleft": "↺",
		"circlearrowright": "↻",
		"circledast": "⊛",
		"circledcirc": "⊚",
		"circleddash": "⊝",
		"CircleDot": "⊙",
		"circledR": "®",
		"circledS": "Ⓢ",
		"CircleMinus": "⊖",
		"CirclePlus": "⊕",
		"CircleTimes": "⊗",
		"cir": "○",
		"cirE": "⧃",
		"cire": "≗",
		"cirfnint": "⨐",
		"cirmid": "⫯",
		"cirscir": "⧂",
		"ClockwiseContourIntegral": "∲",
		"CloseCurlyDoubleQuote": "”",
		"CloseCurlyQuote": "’",
		"clubs": "♣",
		"clubsuit": "♣",
		"colon": ":",
		"Colon": "∷",
		"Colone": "⩴",
		"colone": "≔",
		"coloneq": "≔",
		"comma": ",",
		"commat": "@",
		"comp": "∁",
		"compfn": "∘",
		"complement": "∁",
		"complexes": "ℂ",
		"cong": "≅",
		"congdot": "⩭",
		"Congruent": "≡",
		"conint": "∮",
		"Conint": "∯",
		"ContourIntegral": "∮",
		"copf": "𝕔",
		"Copf": "ℂ",
		"coprod": "∐",
		"Coproduct": "∐",
		"copy": "©",
		"COPY": "©",
		"copysr": "℗",
		"CounterClockwiseContourIntegral": "∳",
		"crarr": "↵",
		"cross": "✗",
		"Cross": "⨯",
		"Cscr": "𝒞",
		"cscr": "𝒸",
		"csub": "⫏",
		"csube": "⫑",
		"csup": "⫐",
		"csupe": "⫒",
		"ctdot": "⋯",
		"cudarrl": "⤸",
		"cudarrr": "⤵",
		"cuepr": "⋞",
		"cuesc": "⋟",
		"cularr": "↶",
		"cularrp": "⤽",
		"cupbrcap": "⩈",
		"cupcap": "⩆",
		"CupCap": "≍",
		"cup": "∪",
		"Cup": "⋓",
		"cupcup": "⩊",
		"cupdot": "⊍",
		"cupor": "⩅",
		"cups": "∪︀",
		"curarr": "↷",
		"curarrm": "⤼",
		"curlyeqprec": "⋞",
		"curlyeqsucc": "⋟",
		"curlyvee": "⋎",
		"curlywedge": "⋏",
		"curren": "¤",
		"curvearrowleft": "↶",
		"curvearrowright": "↷",
		"cuvee": "⋎",
		"cuwed": "⋏",
		"cwconint": "∲",
		"cwint": "∱",
		"cylcty": "⌭",
		"dagger": "†",
		"Dagger": "‡",
		"daleth": "ℸ",
		"darr": "↓",
		"Darr": "↡",
		"dArr": "⇓",
		"dash": "‐",
		"Dashv": "⫤",
		"dashv": "⊣",
		"dbkarow": "⤏",
		"dblac": "˝",
		"Dcaron": "Ď",
		"dcaron": "ď",
		"Dcy": "Д",
		"dcy": "д",
		"ddagger": "‡",
		"ddarr": "⇊",
		"DD": "ⅅ",
		"dd": "ⅆ",
		"DDotrahd": "⤑",
		"ddotseq": "⩷",
		"deg": "°",
		"Del": "∇",
		"Delta": "Δ",
		"delta": "δ",
		"demptyv": "⦱",
		"dfisht": "⥿",
		"Dfr": "𝔇",
		"dfr": "𝔡",
		"dHar": "⥥",
		"dharl": "⇃",
		"dharr": "⇂",
		"DiacriticalAcute": "´",
		"DiacriticalDot": "˙",
		"DiacriticalDoubleAcute": "˝",
		"DiacriticalGrave": "`",
		"DiacriticalTilde": "˜",
		"diam": "⋄",
		"diamond": "⋄",
		"Diamond": "⋄",
		"diamondsuit": "♦",
		"diams": "♦",
		"die": "¨",
		"DifferentialD": "ⅆ",
		"digamma": "ϝ",
		"disin": "⋲",
		"div": "÷",
		"divide": "÷",
		"divideontimes": "⋇",
		"divonx": "⋇",
		"DJcy": "Ђ",
		"djcy": "ђ",
		"dlcorn": "⌞",
		"dlcrop": "⌍",
		"dollar": "$",
		"Dopf": "𝔻",
		"dopf": "𝕕",
		"Dot": "¨",
		"dot": "˙",
		"DotDot": "⃜",
		"doteq": "≐",
		"doteqdot": "≑",
		"DotEqual": "≐",
		"dotminus": "∸",
		"dotplus": "∔",
		"dotsquare": "⊡",
		"doublebarwedge": "⌆",
		"DoubleContourIntegral": "∯",
		"DoubleDot": "¨",
		"DoubleDownArrow": "⇓",
		"DoubleLeftArrow": "⇐",
		"DoubleLeftRightArrow": "⇔",
		"DoubleLeftTee": "⫤",
		"DoubleLongLeftArrow": "⟸",
		"DoubleLongLeftRightArrow": "⟺",
		"DoubleLongRightArrow": "⟹",
		"DoubleRightArrow": "⇒",
		"DoubleRightTee": "⊨",
		"DoubleUpArrow": "⇑",
		"DoubleUpDownArrow": "⇕",
		"DoubleVerticalBar": "∥",
		"DownArrowBar": "⤓",
		"downarrow": "↓",
		"DownArrow": "↓",
		"Downarrow": "⇓",
		"DownArrowUpArrow": "⇵",
		"DownBreve": "̑",
		"downdownarrows": "⇊",
		"downharpoonleft": "⇃",
		"downharpoonright": "⇂",
		"DownLeftRightVector": "⥐",
		"DownLeftTeeVector": "⥞",
		"DownLeftVectorBar": "⥖",
		"DownLeftVector": "↽",
		"DownRightTeeVector": "⥟",
		"DownRightVectorBar": "⥗",
		"DownRightVector": "⇁",
		"DownTeeArrow": "↧",
		"DownTee": "⊤",
		"drbkarow": "⤐",
		"drcorn": "⌟",
		"drcrop": "⌌",
		"Dscr": "𝒟",
		"dscr": "𝒹",
		"DScy": "Ѕ",
		"dscy": "ѕ",
		"dsol": "⧶",
		"Dstrok": "Đ",
		"dstrok": "đ",
		"dtdot": "⋱",
		"dtri": "▿",
		"dtrif": "▾",
		"duarr": "⇵",
		"duhar": "⥯",
		"dwangle": "⦦",
		"DZcy": "Џ",
		"dzcy": "џ",
		"dzigrarr": "⟿",
		"Eacute": "É",
		"eacute": "é",
		"easter": "⩮",
		"Ecaron": "Ě",
		"ecaron": "ě",
		"Ecirc": "Ê",
		"ecirc": "ê",
		"ecir": "≖",
		"ecolon": "≕",
		"Ecy": "Э",
		"ecy": "э",
		"eDDot": "⩷",
		"Edot": "Ė",
		"edot": "ė",
		"eDot": "≑",
		"ee": "ⅇ",
		"efDot": "≒",
		"Efr": "𝔈",
		"efr": "𝔢",
		"eg": "⪚",
		"Egrave": "È",
		"egrave": "è",
		"egs": "⪖",
		"egsdot": "⪘",
		"el": "⪙",
		"Element": "∈",
		"elinters": "⏧",
		"ell": "ℓ",
		"els": "⪕",
		"elsdot": "⪗",
		"Emacr": "Ē",
		"emacr": "ē",
		"empty": "∅",
		"emptyset": "∅",
		"EmptySmallSquare": "◻",
		"emptyv": "∅",
		"EmptyVerySmallSquare": "▫",
		"emsp13": " ",
		"emsp14": " ",
		"emsp": " ",
		"ENG": "Ŋ",
		"eng": "ŋ",
		"ensp": " ",
		"Eogon": "Ę",
		"eogon": "ę",
		"Eopf": "𝔼",
		"eopf": "𝕖",
		"epar": "⋕",
		"eparsl": "⧣",
		"eplus": "⩱",
		"epsi": "ε",
		"Epsilon": "Ε",
		"epsilon": "ε",
		"epsiv": "ϵ",
		"eqcirc": "≖",
		"eqcolon": "≕",
		"eqsim": "≂",
		"eqslantgtr": "⪖",
		"eqslantless": "⪕",
		"Equal": "⩵",
		"equals": "=",
		"EqualTilde": "≂",
		"equest": "≟",
		"Equilibrium": "⇌",
		"equiv": "≡",
		"equivDD": "⩸",
		"eqvparsl": "⧥",
		"erarr": "⥱",
		"erDot": "≓",
		"escr": "ℯ",
		"Escr": "ℰ",
		"esdot": "≐",
		"Esim": "⩳",
		"esim": "≂",
		"Eta": "Η",
		"eta": "η",
		"ETH": "Ð",
		"eth": "ð",
		"Euml": "Ë",
		"euml": "ë",
		"euro": "€",
		"excl": "!",
		"exist": "∃",
		"Exists": "∃",
		"expectation": "ℰ",
		"exponentiale": "ⅇ",
		"ExponentialE": "ⅇ",
		"fallingdotseq": "≒",
		"Fcy": "Ф",
		"fcy": "ф",
		"female": "♀",
		"ffilig": "ﬃ",
		"fflig": "ﬀ",
		"ffllig": "ﬄ",
		"Ffr": "𝔉",
		"ffr": "𝔣",
		"filig": "ﬁ",
		"FilledSmallSquare": "◼",
		"FilledVerySmallSquare": "▪",
		"fjlig": "fj",
		"flat": "♭",
		"fllig": "ﬂ",
		"fltns": "▱",
		"fnof": "ƒ",
		"Fopf": "𝔽",
		"fopf": "𝕗",
		"forall": "∀",
		"ForAll": "∀",
		"fork": "⋔",
		"forkv": "⫙",
		"Fouriertrf": "ℱ",
		"fpartint": "⨍",
		"frac12": "½",
		"frac13": "⅓",
		"frac14": "¼",
		"frac15": "⅕",
		"frac16": "⅙",
		"frac18": "⅛",
		"frac23": "⅔",
		"frac25": "⅖",
		"frac34": "¾",
		"frac35": "⅗",
		"frac38": "⅜",
		"frac45": "⅘",
		"frac56": "⅚",
		"frac58": "⅝",
		"frac78": "⅞",
		"frasl": "⁄",
		"frown": "⌢",
		"fscr": "𝒻",
		"Fscr": "ℱ",
		"gacute": "ǵ",
		"Gamma": "Γ",
		"gamma": "γ",
		"Gammad": "Ϝ",
		"gammad": "ϝ",
		"gap": "⪆",
		"Gbreve": "Ğ",
		"gbreve": "ğ",
		"Gcedil": "Ģ",
		"Gcirc": "Ĝ",
		"gcirc": "ĝ",
		"Gcy": "Г",
		"gcy": "г",
		"Gdot": "Ġ",
		"gdot": "ġ",
		"ge": "≥",
		"gE": "≧",
		"gEl": "⪌",
		"gel": "⋛",
		"geq": "≥",
		"geqq": "≧",
		"geqslant": "⩾",
		"gescc": "⪩",
		"ges": "⩾",
		"gesdot": "⪀",
		"gesdoto": "⪂",
		"gesdotol": "⪄",
		"gesl": "⋛︀",
		"gesles": "⪔",
		"Gfr": "𝔊",
		"gfr": "𝔤",
		"gg": "≫",
		"Gg": "⋙",
		"ggg": "⋙",
		"gimel": "ℷ",
		"GJcy": "Ѓ",
		"gjcy": "ѓ",
		"gla": "⪥",
		"gl": "≷",
		"glE": "⪒",
		"glj": "⪤",
		"gnap": "⪊",
		"gnapprox": "⪊",
		"gne": "⪈",
		"gnE": "≩",
		"gneq": "⪈",
		"gneqq": "≩",
		"gnsim": "⋧",
		"Gopf": "𝔾",
		"gopf": "𝕘",
		"grave": "`",
		"GreaterEqual": "≥",
		"GreaterEqualLess": "⋛",
		"GreaterFullEqual": "≧",
		"GreaterGreater": "⪢",
		"GreaterLess": "≷",
		"GreaterSlantEqual": "⩾",
		"GreaterTilde": "≳",
		"Gscr": "𝒢",
		"gscr": "ℊ",
		"gsim": "≳",
		"gsime": "⪎",
		"gsiml": "⪐",
		"gtcc": "⪧",
		"gtcir": "⩺",
		"gt": ">",
		"GT": ">",
		"Gt": "≫",
		"gtdot": "⋗",
		"gtlPar": "⦕",
		"gtquest": "⩼",
		"gtrapprox": "⪆",
		"gtrarr": "⥸",
		"gtrdot": "⋗",
		"gtreqless": "⋛",
		"gtreqqless": "⪌",
		"gtrless": "≷",
		"gtrsim": "≳",
		"gvertneqq": "≩︀",
		"gvnE": "≩︀",
		"Hacek": "ˇ",
		"hairsp": " ",
		"half": "½",
		"hamilt": "ℋ",
		"HARDcy": "Ъ",
		"hardcy": "ъ",
		"harrcir": "⥈",
		"harr": "↔",
		"hArr": "⇔",
		"harrw": "↭",
		"Hat": "^",
		"hbar": "ℏ",
		"Hcirc": "Ĥ",
		"hcirc": "ĥ",
		"hearts": "♥",
		"heartsuit": "♥",
		"hellip": "…",
		"hercon": "⊹",
		"hfr": "𝔥",
		"Hfr": "ℌ",
		"HilbertSpace": "ℋ",
		"hksearow": "⤥",
		"hkswarow": "⤦",
		"hoarr": "⇿",
		"homtht": "∻",
		"hookleftarrow": "↩",
		"hookrightarrow": "↪",
		"hopf": "𝕙",
		"Hopf": "ℍ",
		"horbar": "―",
		"HorizontalLine": "─",
		"hscr": "𝒽",
		"Hscr": "ℋ",
		"hslash": "ℏ",
		"Hstrok": "Ħ",
		"hstrok": "ħ",
		"HumpDownHump": "≎",
		"HumpEqual": "≏",
		"hybull": "⁃",
		"hyphen": "‐",
		"Iacute": "Í",
		"iacute": "í",
		"ic": "⁣",
		"Icirc": "Î",
		"icirc": "î",
		"Icy": "И",
		"icy": "и",
		"Idot": "İ",
		"IEcy": "Е",
		"iecy": "е",
		"iexcl": "¡",
		"iff": "⇔",
		"ifr": "𝔦",
		"Ifr": "ℑ",
		"Igrave": "Ì",
		"igrave": "ì",
		"ii": "ⅈ",
		"iiiint": "⨌",
		"iiint": "∭",
		"iinfin": "⧜",
		"iiota": "℩",
		"IJlig": "Ĳ",
		"ijlig": "ĳ",
		"Imacr": "Ī",
		"imacr": "ī",
		"image": "ℑ",
		"ImaginaryI": "ⅈ",
		"imagline": "ℐ",
		"imagpart": "ℑ",
		"imath": "ı",
		"Im": "ℑ",
		"imof": "⊷",
		"imped": "Ƶ",
		"Implies": "⇒",
		"incare": "℅",
		"in": "∈",
		"infin": "∞",
		"infintie": "⧝",
		"inodot": "ı",
		"intcal": "⊺",
		"int": "∫",
		"Int": "∬",
		"integers": "ℤ",
		"Integral": "∫",
		"intercal": "⊺",
		"Intersection": "⋂",
		"intlarhk": "⨗",
		"intprod": "⨼",
		"InvisibleComma": "⁣",
		"InvisibleTimes": "⁢",
		"IOcy": "Ё",
		"iocy": "ё",
		"Iogon": "Į",
		"iogon": "į",
		"Iopf": "𝕀",
		"iopf": "𝕚",
		"Iota": "Ι",
		"iota": "ι",
		"iprod": "⨼",
		"iquest": "¿",
		"iscr": "𝒾",
		"Iscr": "ℐ",
		"isin": "∈",
		"isindot": "⋵",
		"isinE": "⋹",
		"isins": "⋴",
		"isinsv": "⋳",
		"isinv": "∈",
		"it": "⁢",
		"Itilde": "Ĩ",
		"itilde": "ĩ",
		"Iukcy": "І",
		"iukcy": "і",
		"Iuml": "Ï",
		"iuml": "ï",
		"Jcirc": "Ĵ",
		"jcirc": "ĵ",
		"Jcy": "Й",
		"jcy": "й",
		"Jfr": "𝔍",
		"jfr": "𝔧",
		"jmath": "ȷ",
		"Jopf": "𝕁",
		"jopf": "𝕛",
		"Jscr": "𝒥",
		"jscr": "𝒿",
		"Jsercy": "Ј",
		"jsercy": "ј",
		"Jukcy": "Є",
		"jukcy": "є",
		"Kappa": "Κ",
		"kappa": "κ",
		"kappav": "ϰ",
		"Kcedil": "Ķ",
		"kcedil": "ķ",
		"Kcy": "К",
		"kcy": "к",
		"Kfr": "𝔎",
		"kfr": "𝔨",
		"kgreen": "ĸ",
		"KHcy": "Х",
		"khcy": "х",
		"KJcy": "Ќ",
		"kjcy": "ќ",
		"Kopf": "𝕂",
		"kopf": "𝕜",
		"Kscr": "𝒦",
		"kscr": "𝓀",
		"lAarr": "⇚",
		"Lacute": "Ĺ",
		"lacute": "ĺ",
		"laemptyv": "⦴",
		"lagran": "ℒ",
		"Lambda": "Λ",
		"lambda": "λ",
		"lang": "⟨",
		"Lang": "⟪",
		"langd": "⦑",
		"langle": "⟨",
		"lap": "⪅",
		"Laplacetrf": "ℒ",
		"laquo": "«",
		"larrb": "⇤",
		"larrbfs": "⤟",
		"larr": "←",
		"Larr": "↞",
		"lArr": "⇐",
		"larrfs": "⤝",
		"larrhk": "↩",
		"larrlp": "↫",
		"larrpl": "⤹",
		"larrsim": "⥳",
		"larrtl": "↢",
		"latail": "⤙",
		"lAtail": "⤛",
		"lat": "⪫",
		"late": "⪭",
		"lates": "⪭︀",
		"lbarr": "⤌",
		"lBarr": "⤎",
		"lbbrk": "❲",
		"lbrace": "{",
		"lbrack": "[",
		"lbrke": "⦋",
		"lbrksld": "⦏",
		"lbrkslu": "⦍",
		"Lcaron": "Ľ",
		"lcaron": "ľ",
		"Lcedil": "Ļ",
		"lcedil": "ļ",
		"lceil": "⌈",
		"lcub": "{",
		"Lcy": "Л",
		"lcy": "л",
		"ldca": "⤶",
		"ldquo": "“",
		"ldquor": "„",
		"ldrdhar": "⥧",
		"ldrushar": "⥋",
		"ldsh": "↲",
		"le": "≤",
		"lE": "≦",
		"LeftAngleBracket": "⟨",
		"LeftArrowBar": "⇤",
		"leftarrow": "←",
		"LeftArrow": "←",
		"Leftarrow": "⇐",
		"LeftArrowRightArrow": "⇆",
		"leftarrowtail": "↢",
		"LeftCeiling": "⌈",
		"LeftDoubleBracket": "⟦",
		"LeftDownTeeVector": "⥡",
		"LeftDownVectorBar": "⥙",
		"LeftDownVector": "⇃",
		"LeftFloor": "⌊",
		"leftharpoondown": "↽",
		"leftharpoonup": "↼",
		"leftleftarrows": "⇇",
		"leftrightarrow": "↔",
		"LeftRightArrow": "↔",
		"Leftrightarrow": "⇔",
		"leftrightarrows": "⇆",
		"leftrightharpoons": "⇋",
		"leftrightsquigarrow": "↭",
		"LeftRightVector": "⥎",
		"LeftTeeArrow": "↤",
		"LeftTee": "⊣",
		"LeftTeeVector": "⥚",
		"leftthreetimes": "⋋",
		"LeftTriangleBar": "⧏",
		"LeftTriangle": "⊲",
		"LeftTriangleEqual": "⊴",
		"LeftUpDownVector": "⥑",
		"LeftUpTeeVector": "⥠",
		"LeftUpVectorBar": "⥘",
		"LeftUpVector": "↿",
		"LeftVectorBar": "⥒",
		"LeftVector": "↼",
		"lEg": "⪋",
		"leg": "⋚",
		"leq": "≤",
		"leqq": "≦",
		"leqslant": "⩽",
		"lescc": "⪨",
		"les": "⩽",
		"lesdot": "⩿",
		"lesdoto": "⪁",
		"lesdotor": "⪃",
		"lesg": "⋚︀",
		"lesges": "⪓",
		"lessapprox": "⪅",
		"lessdot": "⋖",
		"lesseqgtr": "⋚",
		"lesseqqgtr": "⪋",
		"LessEqualGreater": "⋚",
		"LessFullEqual": "≦",
		"LessGreater": "≶",
		"lessgtr": "≶",
		"LessLess": "⪡",
		"lesssim": "≲",
		"LessSlantEqual": "⩽",
		"LessTilde": "≲",
		"lfisht": "⥼",
		"lfloor": "⌊",
		"Lfr": "𝔏",
		"lfr": "𝔩",
		"lg": "≶",
		"lgE": "⪑",
		"lHar": "⥢",
		"lhard": "↽",
		"lharu": "↼",
		"lharul": "⥪",
		"lhblk": "▄",
		"LJcy": "Љ",
		"ljcy": "љ",
		"llarr": "⇇",
		"ll": "≪",
		"Ll": "⋘",
		"llcorner": "⌞",
		"Lleftarrow": "⇚",
		"llhard": "⥫",
		"lltri": "◺",
		"Lmidot": "Ŀ",
		"lmidot": "ŀ",
		"lmoustache": "⎰",
		"lmoust": "⎰",
		"lnap": "⪉",
		"lnapprox": "⪉",
		"lne": "⪇",
		"lnE": "≨",
		"lneq": "⪇",
		"lneqq": "≨",
		"lnsim": "⋦",
		"loang": "⟬",
		"loarr": "⇽",
		"lobrk": "⟦",
		"longleftarrow": "⟵",
		"LongLeftArrow": "⟵",
		"Longleftarrow": "⟸",
		"longleftrightarrow": "⟷",
		"LongLeftRightArrow": "⟷",
		"Longleftrightarrow": "⟺",
		"longmapsto": "⟼",
		"longrightarrow": "⟶",
		"LongRightArrow": "⟶",
		"Longrightarrow": "⟹",
		"looparrowleft": "↫",
		"looparrowright": "↬",
		"lopar": "⦅",
		"Lopf": "𝕃",
		"lopf": "𝕝",
		"loplus": "⨭",
		"lotimes": "⨴",
		"lowast": "∗",
		"lowbar": "_",
		"LowerLeftArrow": "↙",
		"LowerRightArrow": "↘",
		"loz": "◊",
		"lozenge": "◊",
		"lozf": "⧫",
		"lpar": "(",
		"lparlt": "⦓",
		"lrarr": "⇆",
		"lrcorner": "⌟",
		"lrhar": "⇋",
		"lrhard": "⥭",
		"lrm": "‎",
		"lrtri": "⊿",
		"lsaquo": "‹",
		"lscr": "𝓁",
		"Lscr": "ℒ",
		"lsh": "↰",
		"Lsh": "↰",
		"lsim": "≲",
		"lsime": "⪍",
		"lsimg": "⪏",
		"lsqb": "[",
		"lsquo": "‘",
		"lsquor": "‚",
		"Lstrok": "Ł",
		"lstrok": "ł",
		"ltcc": "⪦",
		"ltcir": "⩹",
		"lt": "<",
		"LT": "<",
		"Lt": "≪",
		"ltdot": "⋖",
		"lthree": "⋋",
		"ltimes": "⋉",
		"ltlarr": "⥶",
		"ltquest": "⩻",
		"ltri": "◃",
		"ltrie": "⊴",
		"ltrif": "◂",
		"ltrPar": "⦖",
		"lurdshar": "⥊",
		"luruhar": "⥦",
		"lvertneqq": "≨︀",
		"lvnE": "≨︀",
		"macr": "¯",
		"male": "♂",
		"malt": "✠",
		"maltese": "✠",
		"Map": "⤅",
		"map": "↦",
		"mapsto": "↦",
		"mapstodown": "↧",
		"mapstoleft": "↤",
		"mapstoup": "↥",
		"marker": "▮",
		"mcomma": "⨩",
		"Mcy": "М",
		"mcy": "м",
		"mdash": "—",
		"mDDot": "∺",
		"measuredangle": "∡",
		"MediumSpace": " ",
		"Mellintrf": "ℳ",
		"Mfr": "𝔐",
		"mfr": "𝔪",
		"mho": "℧",
		"micro": "µ",
		"midast": "*",
		"midcir": "⫰",
		"mid": "∣",
		"middot": "·",
		"minusb": "⊟",
		"minus": "−",
		"minusd": "∸",
		"minusdu": "⨪",
		"MinusPlus": "∓",
		"mlcp": "⫛",
		"mldr": "…",
		"mnplus": "∓",
		"models": "⊧",
		"Mopf": "𝕄",
		"mopf": "𝕞",
		"mp": "∓",
		"mscr": "𝓂",
		"Mscr": "ℳ",
		"mstpos": "∾",
		"Mu": "Μ",
		"mu": "μ",
		"multimap": "⊸",
		"mumap": "⊸",
		"nabla": "∇",
		"Nacute": "Ń",
		"nacute": "ń",
		"nang": "∠⃒",
		"nap": "≉",
		"napE": "⩰̸",
		"napid": "≋̸",
		"napos": "ŉ",
		"napprox": "≉",
		"natural": "♮",
		"naturals": "ℕ",
		"natur": "♮",
		"nbsp": " ",
		"nbump": "≎̸",
		"nbumpe": "≏̸",
		"ncap": "⩃",
		"Ncaron": "Ň",
		"ncaron": "ň",
		"Ncedil": "Ņ",
		"ncedil": "ņ",
		"ncong": "≇",
		"ncongdot": "⩭̸",
		"ncup": "⩂",
		"Ncy": "Н",
		"ncy": "н",
		"ndash": "–",
		"nearhk": "⤤",
		"nearr": "↗",
		"neArr": "⇗",
		"nearrow": "↗",
		"ne": "≠",
		"nedot": "≐̸",
		"NegativeMediumSpace": "​",
		"NegativeThickSpace": "​",
		"NegativeThinSpace": "​",
		"NegativeVeryThinSpace": "​",
		"nequiv": "≢",
		"nesear": "⤨",
		"nesim": "≂̸",
		"NestedGreaterGreater": "≫",
		"NestedLessLess": "≪",
		"NewLine": "\n",
		"nexist": "∄",
		"nexists": "∄",
		"Nfr": "𝔑",
		"nfr": "𝔫",
		"ngE": "≧̸",
		"nge": "≱",
		"ngeq": "≱",
		"ngeqq": "≧̸",
		"ngeqslant": "⩾̸",
		"nges": "⩾̸",
		"nGg": "⋙̸",
		"ngsim": "≵",
		"nGt": "≫⃒",
		"ngt": "≯",
		"ngtr": "≯",
		"nGtv": "≫̸",
		"nharr": "↮",
		"nhArr": "⇎",
		"nhpar": "⫲",
		"ni": "∋",
		"nis": "⋼",
		"nisd": "⋺",
		"niv": "∋",
		"NJcy": "Њ",
		"njcy": "њ",
		"nlarr": "↚",
		"nlArr": "⇍",
		"nldr": "‥",
		"nlE": "≦̸",
		"nle": "≰",
		"nleftarrow": "↚",
		"nLeftarrow": "⇍",
		"nleftrightarrow": "↮",
		"nLeftrightarrow": "⇎",
		"nleq": "≰",
		"nleqq": "≦̸",
		"nleqslant": "⩽̸",
		"nles": "⩽̸",
		"nless": "≮",
		"nLl": "⋘̸",
		"nlsim": "≴",
		"nLt": "≪⃒",
		"nlt": "≮",
		"nltri": "⋪",
		"nltrie": "⋬",
		"nLtv": "≪̸",
		"nmid": "∤",
		"NoBreak": "⁠",
		"NonBreakingSpace": " ",
		"nopf": "𝕟",
		"Nopf": "ℕ",
		"Not": "⫬",
		"not": "¬",
		"NotCongruent": "≢",
		"NotCupCap": "≭",
		"NotDoubleVerticalBar": "∦",
		"NotElement": "∉",
		"NotEqual": "≠",
		"NotEqualTilde": "≂̸",
		"NotExists": "∄",
		"NotGreater": "≯",
		"NotGreaterEqual": "≱",
		"NotGreaterFullEqual": "≧̸",
		"NotGreaterGreater": "≫̸",
		"NotGreaterLess": "≹",
		"NotGreaterSlantEqual": "⩾̸",
		"NotGreaterTilde": "≵",
		"NotHumpDownHump": "≎̸",
		"NotHumpEqual": "≏̸",
		"notin": "∉",
		"notindot": "⋵̸",
		"notinE": "⋹̸",
		"notinva": "∉",
		"notinvb": "⋷",
		"notinvc": "⋶",
		"NotLeftTriangleBar": "⧏̸",
		"NotLeftTriangle": "⋪",
		"NotLeftTriangleEqual": "⋬",
		"NotLess": "≮",
		"NotLessEqual": "≰",
		"NotLessGreater": "≸",
		"NotLessLess": "≪̸",
		"NotLessSlantEqual": "⩽̸",
		"NotLessTilde": "≴",
		"NotNestedGreaterGreater": "⪢̸",
		"NotNestedLessLess": "⪡̸",
		"notni": "∌",
		"notniva": "∌",
		"notnivb": "⋾",
		"notnivc": "⋽",
		"NotPrecedes": "⊀",
		"NotPrecedesEqual": "⪯̸",
		"NotPrecedesSlantEqual": "⋠",
		"NotReverseElement": "∌",
		"NotRightTriangleBar": "⧐̸",
		"NotRightTriangle": "⋫",
		"NotRightTriangleEqual": "⋭",
		"NotSquareSubset": "⊏̸",
		"NotSquareSubsetEqual": "⋢",
		"NotSquareSuperset": "⊐̸",
		"NotSquareSupersetEqual": "⋣",
		"NotSubset": "⊂⃒",
		"NotSubsetEqual": "⊈",
		"NotSucceeds": "⊁",
		"NotSucceedsEqual": "⪰̸",
		"NotSucceedsSlantEqual": "⋡",
		"NotSucceedsTilde": "≿̸",
		"NotSuperset": "⊃⃒",
		"NotSupersetEqual": "⊉",
		"NotTilde": "≁",
		"NotTildeEqual": "≄",
		"NotTildeFullEqual": "≇",
		"NotTildeTilde": "≉",
		"NotVerticalBar": "∤",
		"nparallel": "∦",
		"npar": "∦",
		"nparsl": "⫽⃥",
		"npart": "∂̸",
		"npolint": "⨔",
		"npr": "⊀",
		"nprcue": "⋠",
		"nprec": "⊀",
		"npreceq": "⪯̸",
		"npre": "⪯̸",
		"nrarrc": "⤳̸",
		"nrarr": "↛",
		"nrArr": "⇏",
		"nrarrw": "↝̸",
		"nrightarrow": "↛",
		"nRightarrow": "⇏",
		"nrtri": "⋫",
		"nrtrie": "⋭",
		"nsc": "⊁",
		"nsccue": "⋡",
		"nsce": "⪰̸",
		"Nscr": "𝒩",
		"nscr": "𝓃",
		"nshortmid": "∤",
		"nshortparallel": "∦",
		"nsim": "≁",
		"nsime": "≄",
		"nsimeq": "≄",
		"nsmid": "∤",
		"nspar": "∦",
		"nsqsube": "⋢",
		"nsqsupe": "⋣",
		"nsub": "⊄",
		"nsubE": "⫅̸",
		"nsube": "⊈",
		"nsubset": "⊂⃒",
		"nsubseteq": "⊈",
		"nsubseteqq": "⫅̸",
		"nsucc": "⊁",
		"nsucceq": "⪰̸",
		"nsup": "⊅",
		"nsupE": "⫆̸",
		"nsupe": "⊉",
		"nsupset": "⊃⃒",
		"nsupseteq": "⊉",
		"nsupseteqq": "⫆̸",
		"ntgl": "≹",
		"Ntilde": "Ñ",
		"ntilde": "ñ",
		"ntlg": "≸",
		"ntriangleleft": "⋪",
		"ntrianglelefteq": "⋬",
		"ntriangleright": "⋫",
		"ntrianglerighteq": "⋭",
		"Nu": "Ν",
		"nu": "ν",
		"num": "#",
		"numero": "№",
		"numsp": " ",
		"nvap": "≍⃒",
		"nvdash": "⊬",
		"nvDash": "⊭",
		"nVdash": "⊮",
		"nVDash": "⊯",
		"nvge": "≥⃒",
		"nvgt": ">⃒",
		"nvHarr": "⤄",
		"nvinfin": "⧞",
		"nvlArr": "⤂",
		"nvle": "≤⃒",
		"nvlt": "<⃒",
		"nvltrie": "⊴⃒",
		"nvrArr": "⤃",
		"nvrtrie": "⊵⃒",
		"nvsim": "∼⃒",
		"nwarhk": "⤣",
		"nwarr": "↖",
		"nwArr": "⇖",
		"nwarrow": "↖",
		"nwnear": "⤧",
		"Oacute": "Ó",
		"oacute": "ó",
		"oast": "⊛",
		"Ocirc": "Ô",
		"ocirc": "ô",
		"ocir": "⊚",
		"Ocy": "О",
		"ocy": "о",
		"odash": "⊝",
		"Odblac": "Ő",
		"odblac": "ő",
		"odiv": "⨸",
		"odot": "⊙",
		"odsold": "⦼",
		"OElig": "Œ",
		"oelig": "œ",
		"ofcir": "⦿",
		"Ofr": "𝔒",
		"ofr": "𝔬",
		"ogon": "˛",
		"Ograve": "Ò",
		"ograve": "ò",
		"ogt": "⧁",
		"ohbar": "⦵",
		"ohm": "Ω",
		"oint": "∮",
		"olarr": "↺",
		"olcir": "⦾",
		"olcross": "⦻",
		"oline": "‾",
		"olt": "⧀",
		"Omacr": "Ō",
		"omacr": "ō",
		"Omega": "Ω",
		"omega": "ω",
		"Omicron": "Ο",
		"omicron": "ο",
		"omid": "⦶",
		"ominus": "⊖",
		"Oopf": "𝕆",
		"oopf": "𝕠",
		"opar": "⦷",
		"OpenCurlyDoubleQuote": "“",
		"OpenCurlyQuote": "‘",
		"operp": "⦹",
		"oplus": "⊕",
		"orarr": "↻",
		"Or": "⩔",
		"or": "∨",
		"ord": "⩝",
		"order": "ℴ",
		"orderof": "ℴ",
		"ordf": "ª",
		"ordm": "º",
		"origof": "⊶",
		"oror": "⩖",
		"orslope": "⩗",
		"orv": "⩛",
		"oS": "Ⓢ",
		"Oscr": "𝒪",
		"oscr": "ℴ",
		"Oslash": "Ø",
		"oslash": "ø",
		"osol": "⊘",
		"Otilde": "Õ",
		"otilde": "õ",
		"otimesas": "⨶",
		"Otimes": "⨷",
		"otimes": "⊗",
		"Ouml": "Ö",
		"ouml": "ö",
		"ovbar": "⌽",
		"OverBar": "‾",
		"OverBrace": "⏞",
		"OverBracket": "⎴",
		"OverParenthesis": "⏜",
		"para": "¶",
		"parallel": "∥",
		"par": "∥",
		"parsim": "⫳",
		"parsl": "⫽",
		"part": "∂",
		"PartialD": "∂",
		"Pcy": "П",
		"pcy": "п",
		"percnt": "%",
		"period": ".",
		"permil": "‰",
		"perp": "⊥",
		"pertenk": "‱",
		"Pfr": "𝔓",
		"pfr": "𝔭",
		"Phi": "Φ",
		"phi": "φ",
		"phiv": "ϕ",
		"phmmat": "ℳ",
		"phone": "☎",
		"Pi": "Π",
		"pi": "π",
		"pitchfork": "⋔",
		"piv": "ϖ",
		"planck": "ℏ",
		"planckh": "ℎ",
		"plankv": "ℏ",
		"plusacir": "⨣",
		"plusb": "⊞",
		"pluscir": "⨢",
		"plus": "+",
		"plusdo": "∔",
		"plusdu": "⨥",
		"pluse": "⩲",
		"PlusMinus": "±",
		"plusmn": "±",
		"plussim": "⨦",
		"plustwo": "⨧",
		"pm": "±",
		"Poincareplane": "ℌ",
		"pointint": "⨕",
		"popf": "𝕡",
		"Popf": "ℙ",
		"pound": "£",
		"prap": "⪷",
		"Pr": "⪻",
		"pr": "≺",
		"prcue": "≼",
		"precapprox": "⪷",
		"prec": "≺",
		"preccurlyeq": "≼",
		"Precedes": "≺",
		"PrecedesEqual": "⪯",
		"PrecedesSlantEqual": "≼",
		"PrecedesTilde": "≾",
		"preceq": "⪯",
		"precnapprox": "⪹",
		"precneqq": "⪵",
		"precnsim": "⋨",
		"pre": "⪯",
		"prE": "⪳",
		"precsim": "≾",
		"prime": "′",
		"Prime": "″",
		"primes": "ℙ",
		"prnap": "⪹",
		"prnE": "⪵",
		"prnsim": "⋨",
		"prod": "∏",
		"Product": "∏",
		"profalar": "⌮",
		"profline": "⌒",
		"profsurf": "⌓",
		"prop": "∝",
		"Proportional": "∝",
		"Proportion": "∷",
		"propto": "∝",
		"prsim": "≾",
		"prurel": "⊰",
		"Pscr": "𝒫",
		"pscr": "𝓅",
		"Psi": "Ψ",
		"psi": "ψ",
		"puncsp": " ",
		"Qfr": "𝔔",
		"qfr": "𝔮",
		"qint": "⨌",
		"qopf": "𝕢",
		"Qopf": "ℚ",
		"qprime": "⁗",
		"Qscr": "𝒬",
		"qscr": "𝓆",
		"quaternions": "ℍ",
		"quatint": "⨖",
		"quest": "?",
		"questeq": "≟",
		"quot": "\"",
		"QUOT": "\"",
		"rAarr": "⇛",
		"race": "∽̱",
		"Racute": "Ŕ",
		"racute": "ŕ",
		"radic": "√",
		"raemptyv": "⦳",
		"rang": "⟩",
		"Rang": "⟫",
		"rangd": "⦒",
		"range": "⦥",
		"rangle": "⟩",
		"raquo": "»",
		"rarrap": "⥵",
		"rarrb": "⇥",
		"rarrbfs": "⤠",
		"rarrc": "⤳",
		"rarr": "→",
		"Rarr": "↠",
		"rArr": "⇒",
		"rarrfs": "⤞",
		"rarrhk": "↪",
		"rarrlp": "↬",
		"rarrpl": "⥅",
		"rarrsim": "⥴",
		"Rarrtl": "⤖",
		"rarrtl": "↣",
		"rarrw": "↝",
		"ratail": "⤚",
		"rAtail": "⤜",
		"ratio": "∶",
		"rationals": "ℚ",
		"rbarr": "⤍",
		"rBarr": "⤏",
		"RBarr": "⤐",
		"rbbrk": "❳",
		"rbrace": "}",
		"rbrack": "]",
		"rbrke": "⦌",
		"rbrksld": "⦎",
		"rbrkslu": "⦐",
		"Rcaron": "Ř",
		"rcaron": "ř",
		"Rcedil": "Ŗ",
		"rcedil": "ŗ",
		"rceil": "⌉",
		"rcub": "}",
		"Rcy": "Р",
		"rcy": "р",
		"rdca": "⤷",
		"rdldhar": "⥩",
		"rdquo": "”",
		"rdquor": "”",
		"rdsh": "↳",
		"real": "ℜ",
		"realine": "ℛ",
		"realpart": "ℜ",
		"reals": "ℝ",
		"Re": "ℜ",
		"rect": "▭",
		"reg": "®",
		"REG": "®",
		"ReverseElement": "∋",
		"ReverseEquilibrium": "⇋",
		"ReverseUpEquilibrium": "⥯",
		"rfisht": "⥽",
		"rfloor": "⌋",
		"rfr": "𝔯",
		"Rfr": "ℜ",
		"rHar": "⥤",
		"rhard": "⇁",
		"rharu": "⇀",
		"rharul": "⥬",
		"Rho": "Ρ",
		"rho": "ρ",
		"rhov": "ϱ",
		"RightAngleBracket": "⟩",
		"RightArrowBar": "⇥",
		"rightarrow": "→",
		"RightArrow": "→",
		"Rightarrow": "⇒",
		"RightArrowLeftArrow": "⇄",
		"rightarrowtail": "↣",
		"RightCeiling": "⌉",
		"RightDoubleBracket": "⟧",
		"RightDownTeeVector": "⥝",
		"RightDownVectorBar": "⥕",
		"RightDownVector": "⇂",
		"RightFloor": "⌋",
		"rightharpoondown": "⇁",
		"rightharpoonup": "⇀",
		"rightleftarrows": "⇄",
		"rightleftharpoons": "⇌",
		"rightrightarrows": "⇉",
		"rightsquigarrow": "↝",
		"RightTeeArrow": "↦",
		"RightTee": "⊢",
		"RightTeeVector": "⥛",
		"rightthreetimes": "⋌",
		"RightTriangleBar": "⧐",
		"RightTriangle": "⊳",
		"RightTriangleEqual": "⊵",
		"RightUpDownVector": "⥏",
		"RightUpTeeVector": "⥜",
		"RightUpVectorBar": "⥔",
		"RightUpVector": "↾",
		"RightVectorBar": "⥓",
		"RightVector": "⇀",
		"ring": "˚",
		"risingdotseq": "≓",
		"rlarr": "⇄",
		"rlhar": "⇌",
		"rlm": "‏",
		"rmoustache": "⎱",
		"rmoust": "⎱",
		"rnmid": "⫮",
		"roang": "⟭",
		"roarr": "⇾",
		"robrk": "⟧",
		"ropar": "⦆",
		"ropf": "𝕣",
		"Ropf": "ℝ",
		"roplus": "⨮",
		"rotimes": "⨵",
		"RoundImplies": "⥰",
		"rpar": ")",
		"rpargt": "⦔",
		"rppolint": "⨒",
		"rrarr": "⇉",
		"Rrightarrow": "⇛",
		"rsaquo": "›",
		"rscr": "𝓇",
		"Rscr": "ℛ",
		"rsh": "↱",
		"Rsh": "↱",
		"rsqb": "]",
		"rsquo": "’",
		"rsquor": "’",
		"rthree": "⋌",
		"rtimes": "⋊",
		"rtri": "▹",
		"rtrie": "⊵",
		"rtrif": "▸",
		"rtriltri": "⧎",
		"RuleDelayed": "⧴",
		"ruluhar": "⥨",
		"rx": "℞",
		"Sacute": "Ś",
		"sacute": "ś",
		"sbquo": "‚",
		"scap": "⪸",
		"Scaron": "Š",
		"scaron": "š",
		"Sc": "⪼",
		"sc": "≻",
		"sccue": "≽",
		"sce": "⪰",
		"scE": "⪴",
		"Scedil": "Ş",
		"scedil": "ş",
		"Scirc": "Ŝ",
		"scirc": "ŝ",
		"scnap": "⪺",
		"scnE": "⪶",
		"scnsim": "⋩",
		"scpolint": "⨓",
		"scsim": "≿",
		"Scy": "С",
		"scy": "с",
		"sdotb": "⊡",
		"sdot": "⋅",
		"sdote": "⩦",
		"searhk": "⤥",
		"searr": "↘",
		"seArr": "⇘",
		"searrow": "↘",
		"sect": "§",
		"semi": ";",
		"seswar": "⤩",
		"setminus": "∖",
		"setmn": "∖",
		"sext": "✶",
		"Sfr": "𝔖",
		"sfr": "𝔰",
		"sfrown": "⌢",
		"sharp": "♯",
		"SHCHcy": "Щ",
		"shchcy": "щ",
		"SHcy": "Ш",
		"shcy": "ш",
		"ShortDownArrow": "↓",
		"ShortLeftArrow": "←",
		"shortmid": "∣",
		"shortparallel": "∥",
		"ShortRightArrow": "→",
		"ShortUpArrow": "↑",
		"shy": "­",
		"Sigma": "Σ",
		"sigma": "σ",
		"sigmaf": "ς",
		"sigmav": "ς",
		"sim": "∼",
		"simdot": "⩪",
		"sime": "≃",
		"simeq": "≃",
		"simg": "⪞",
		"simgE": "⪠",
		"siml": "⪝",
		"simlE": "⪟",
		"simne": "≆",
		"simplus": "⨤",
		"simrarr": "⥲",
		"slarr": "←",
		"SmallCircle": "∘",
		"smallsetminus": "∖",
		"smashp": "⨳",
		"smeparsl": "⧤",
		"smid": "∣",
		"smile": "⌣",
		"smt": "⪪",
		"smte": "⪬",
		"smtes": "⪬︀",
		"SOFTcy": "Ь",
		"softcy": "ь",
		"solbar": "⌿",
		"solb": "⧄",
		"sol": "/",
		"Sopf": "𝕊",
		"sopf": "𝕤",
		"spades": "♠",
		"spadesuit": "♠",
		"spar": "∥",
		"sqcap": "⊓",
		"sqcaps": "⊓︀",
		"sqcup": "⊔",
		"sqcups": "⊔︀",
		"Sqrt": "√",
		"sqsub": "⊏",
		"sqsube": "⊑",
		"sqsubset": "⊏",
		"sqsubseteq": "⊑",
		"sqsup": "⊐",
		"sqsupe": "⊒",
		"sqsupset": "⊐",
		"sqsupseteq": "⊒",
		"square": "□",
		"Square": "□",
		"SquareIntersection": "⊓",
		"SquareSubset": "⊏",
		"SquareSubsetEqual": "⊑",
		"SquareSuperset": "⊐",
		"SquareSupersetEqual": "⊒",
		"SquareUnion": "⊔",
		"squarf": "▪",
		"squ": "□",
		"squf": "▪",
		"srarr": "→",
		"Sscr": "𝒮",
		"sscr": "𝓈",
		"ssetmn": "∖",
		"ssmile": "⌣",
		"sstarf": "⋆",
		"Star": "⋆",
		"star": "☆",
		"starf": "★",
		"straightepsilon": "ϵ",
		"straightphi": "ϕ",
		"strns": "¯",
		"sub": "⊂",
		"Sub": "⋐",
		"subdot": "⪽",
		"subE": "⫅",
		"sube": "⊆",
		"subedot": "⫃",
		"submult": "⫁",
		"subnE": "⫋",
		"subne": "⊊",
		"subplus": "⪿",
		"subrarr": "⥹",
		"subset": "⊂",
		"Subset": "⋐",
		"subseteq": "⊆",
		"subseteqq": "⫅",
		"SubsetEqual": "⊆",
		"subsetneq": "⊊",
		"subsetneqq": "⫋",
		"subsim": "⫇",
		"subsub": "⫕",
		"subsup": "⫓",
		"succapprox": "⪸",
		"succ": "≻",
		"succcurlyeq": "≽",
		"Succeeds": "≻",
		"SucceedsEqual": "⪰",
		"SucceedsSlantEqual": "≽",
		"SucceedsTilde": "≿",
		"succeq": "⪰",
		"succnapprox": "⪺",
		"succneqq": "⪶",
		"succnsim": "⋩",
		"succsim": "≿",
		"SuchThat": "∋",
		"sum": "∑",
		"Sum": "∑",
		"sung": "♪",
		"sup1": "¹",
		"sup2": "²",
		"sup3": "³",
		"sup": "⊃",
		"Sup": "⋑",
		"supdot": "⪾",
		"supdsub": "⫘",
		"supE": "⫆",
		"supe": "⊇",
		"supedot": "⫄",
		"Superset": "⊃",
		"SupersetEqual": "⊇",
		"suphsol": "⟉",
		"suphsub": "⫗",
		"suplarr": "⥻",
		"supmult": "⫂",
		"supnE": "⫌",
		"supne": "⊋",
		"supplus": "⫀",
		"supset": "⊃",
		"Supset": "⋑",
		"supseteq": "⊇",
		"supseteqq": "⫆",
		"supsetneq": "⊋",
		"supsetneqq": "⫌",
		"supsim": "⫈",
		"supsub": "⫔",
		"supsup": "⫖",
		"swarhk": "⤦",
		"swarr": "↙",
		"swArr": "⇙",
		"swarrow": "↙",
		"swnwar": "⤪",
		"szlig": "ß",
		"Tab": "\t",
		"target": "⌖",
		"Tau": "Τ",
		"tau": "τ",
		"tbrk": "⎴",
		"Tcaron": "Ť",
		"tcaron": "ť",
		"Tcedil": "Ţ",
		"tcedil": "ţ",
		"Tcy": "Т",
		"tcy": "т",
		"tdot": "⃛",
		"telrec": "⌕",
		"Tfr": "𝔗",
		"tfr": "𝔱",
		"there4": "∴",
		"therefore": "∴",
		"Therefore": "∴",
		"Theta": "Θ",
		"theta": "θ",
		"thetasym": "ϑ",
		"thetav": "ϑ",
		"thickapprox": "≈",
		"thicksim": "∼",
		"ThickSpace": "  ",
		"ThinSpace": " ",
		"thinsp": " ",
		"thkap": "≈",
		"thksim": "∼",
		"THORN": "Þ",
		"thorn": "þ",
		"tilde": "˜",
		"Tilde": "∼",
		"TildeEqual": "≃",
		"TildeFullEqual": "≅",
		"TildeTilde": "≈",
		"timesbar": "⨱",
		"timesb": "⊠",
		"times": "×",
		"timesd": "⨰",
		"tint": "∭",
		"toea": "⤨",
		"topbot": "⌶",
		"topcir": "⫱",
		"top": "⊤",
		"Topf": "𝕋",
		"topf": "𝕥",
		"topfork": "⫚",
		"tosa": "⤩",
		"tprime": "‴",
		"trade": "™",
		"TRADE": "™",
		"triangle": "▵",
		"triangledown": "▿",
		"triangleleft": "◃",
		"trianglelefteq": "⊴",
		"triangleq": "≜",
		"triangleright": "▹",
		"trianglerighteq": "⊵",
		"tridot": "◬",
		"trie": "≜",
		"triminus": "⨺",
		"TripleDot": "⃛",
		"triplus": "⨹",
		"trisb": "⧍",
		"tritime": "⨻",
		"trpezium": "⏢",
		"Tscr": "𝒯",
		"tscr": "𝓉",
		"TScy": "Ц",
		"tscy": "ц",
		"TSHcy": "Ћ",
		"tshcy": "ћ",
		"Tstrok": "Ŧ",
		"tstrok": "ŧ",
		"twixt": "≬",
		"twoheadleftarrow": "↞",
		"twoheadrightarrow": "↠",
		"Uacute": "Ú",
		"uacute": "ú",
		"uarr": "↑",
		"Uarr": "↟",
		"uArr": "⇑",
		"Uarrocir": "⥉",
		"Ubrcy": "Ў",
		"ubrcy": "ў",
		"Ubreve": "Ŭ",
		"ubreve": "ŭ",
		"Ucirc": "Û",
		"ucirc": "û",
		"Ucy": "У",
		"ucy": "у",
		"udarr": "⇅",
		"Udblac": "Ű",
		"udblac": "ű",
		"udhar": "⥮",
		"ufisht": "⥾",
		"Ufr": "𝔘",
		"ufr": "𝔲",
		"Ugrave": "Ù",
		"ugrave": "ù",
		"uHar": "⥣",
		"uharl": "↿",
		"uharr": "↾",
		"uhblk": "▀",
		"ulcorn": "⌜",
		"ulcorner": "⌜",
		"ulcrop": "⌏",
		"ultri": "◸",
		"Umacr": "Ū",
		"umacr": "ū",
		"uml": "¨",
		"UnderBar": "_",
		"UnderBrace": "⏟",
		"UnderBracket": "⎵",
		"UnderParenthesis": "⏝",
		"Union": "⋃",
		"UnionPlus": "⊎",
		"Uogon": "Ų",
		"uogon": "ų",
		"Uopf": "𝕌",
		"uopf": "𝕦",
		"UpArrowBar": "⤒",
		"uparrow": "↑",
		"UpArrow": "↑",
		"Uparrow": "⇑",
		"UpArrowDownArrow": "⇅",
		"updownarrow": "↕",
		"UpDownArrow": "↕",
		"Updownarrow": "⇕",
		"UpEquilibrium": "⥮",
		"upharpoonleft": "↿",
		"upharpoonright": "↾",
		"uplus": "⊎",
		"UpperLeftArrow": "↖",
		"UpperRightArrow": "↗",
		"upsi": "υ",
		"Upsi": "ϒ",
		"upsih": "ϒ",
		"Upsilon": "Υ",
		"upsilon": "υ",
		"UpTeeArrow": "↥",
		"UpTee": "⊥",
		"upuparrows": "⇈",
		"urcorn": "⌝",
		"urcorner": "⌝",
		"urcrop": "⌎",
		"Uring": "Ů",
		"uring": "ů",
		"urtri": "◹",
		"Uscr": "𝒰",
		"uscr": "𝓊",
		"utdot": "⋰",
		"Utilde": "Ũ",
		"utilde": "ũ",
		"utri": "▵",
		"utrif": "▴",
		"uuarr": "⇈",
		"Uuml": "Ü",
		"uuml": "ü",
		"uwangle": "⦧",
		"vangrt": "⦜",
		"varepsilon": "ϵ",
		"varkappa": "ϰ",
		"varnothing": "∅",
		"varphi": "ϕ",
		"varpi": "ϖ",
		"varpropto": "∝",
		"varr": "↕",
		"vArr": "⇕",
		"varrho": "ϱ",
		"varsigma": "ς",
		"varsubsetneq": "⊊︀",
		"varsubsetneqq": "⫋︀",
		"varsupsetneq": "⊋︀",
		"varsupsetneqq": "⫌︀",
		"vartheta": "ϑ",
		"vartriangleleft": "⊲",
		"vartriangleright": "⊳",
		"vBar": "⫨",
		"Vbar": "⫫",
		"vBarv": "⫩",
		"Vcy": "В",
		"vcy": "в",
		"vdash": "⊢",
		"vDash": "⊨",
		"Vdash": "⊩",
		"VDash": "⊫",
		"Vdashl": "⫦",
		"veebar": "⊻",
		"vee": "∨",
		"Vee": "⋁",
		"veeeq": "≚",
		"vellip": "⋮",
		"verbar": "|",
		"Verbar": "‖",
		"vert": "|",
		"Vert": "‖",
		"VerticalBar": "∣",
		"VerticalLine": "|",
		"VerticalSeparator": "❘",
		"VerticalTilde": "≀",
		"VeryThinSpace": " ",
		"Vfr": "𝔙",
		"vfr": "𝔳",
		"vltri": "⊲",
		"vnsub": "⊂⃒",
		"vnsup": "⊃⃒",
		"Vopf": "𝕍",
		"vopf": "𝕧",
		"vprop": "∝",
		"vrtri": "⊳",
		"Vscr": "𝒱",
		"vscr": "𝓋",
		"vsubnE": "⫋︀",
		"vsubne": "⊊︀",
		"vsupnE": "⫌︀",
		"vsupne": "⊋︀",
		"Vvdash": "⊪",
		"vzigzag": "⦚",
		"Wcirc": "Ŵ",
		"wcirc": "ŵ",
		"wedbar": "⩟",
		"wedge": "∧",
		"Wedge": "⋀",
		"wedgeq": "≙",
		"weierp": "℘",
		"Wfr": "𝔚",
		"wfr": "𝔴",
		"Wopf": "𝕎",
		"wopf": "𝕨",
		"wp": "℘",
		"wr": "≀",
		"wreath": "≀",
		"Wscr": "𝒲",
		"wscr": "𝓌",
		"xcap": "⋂",
		"xcirc": "◯",
		"xcup": "⋃",
		"xdtri": "▽",
		"Xfr": "𝔛",
		"xfr": "𝔵",
		"xharr": "⟷",
		"xhArr": "⟺",
		"Xi": "Ξ",
		"xi": "ξ",
		"xlarr": "⟵",
		"xlArr": "⟸",
		"xmap": "⟼",
		"xnis": "⋻",
		"xodot": "⨀",
		"Xopf": "𝕏",
		"xopf": "𝕩",
		"xoplus": "⨁",
		"xotime": "⨂",
		"xrarr": "⟶",
		"xrArr": "⟹",
		"Xscr": "𝒳",
		"xscr": "𝓍",
		"xsqcup": "⨆",
		"xuplus": "⨄",
		"xutri": "△",
		"xvee": "⋁",
		"xwedge": "⋀",
		"Yacute": "Ý",
		"yacute": "ý",
		"YAcy": "Я",
		"yacy": "я",
		"Ycirc": "Ŷ",
		"ycirc": "ŷ",
		"Ycy": "Ы",
		"ycy": "ы",
		"yen": "¥",
		"Yfr": "𝔜",
		"yfr": "𝔶",
		"YIcy": "Ї",
		"yicy": "ї",
		"Yopf": "𝕐",
		"yopf": "𝕪",
		"Yscr": "𝒴",
		"yscr": "𝓎",
		"YUcy": "Ю",
		"yucy": "ю",
		"yuml": "ÿ",
		"Yuml": "Ÿ",
		"Zacute": "Ź",
		"zacute": "ź",
		"Zcaron": "Ž",
		"zcaron": "ž",
		"Zcy": "З",
		"zcy": "з",
		"Zdot": "Ż",
		"zdot": "ż",
		"zeetrf": "ℨ",
		"ZeroWidthSpace": "​",
		"Zeta": "Ζ",
		"zeta": "ζ",
		"zfr": "𝔷",
		"Zfr": "ℨ",
		"ZHcy": "Ж",
		"zhcy": "ж",
		"zigrarr": "⇝",
		"zopf": "𝕫",
		"Zopf": "ℤ",
		"Zscr": "𝒵",
		"zscr": "𝓏",
		"zwj": "‍",
		"zwnj": "‌"
	};
})
/** END DEFINE BLOCK for entities@1.1.1/maps/entities.json **/


/** START DEFINE BLOCK for entities@1.1.1/maps/legacy.json **/
jupyter.define('entities@1.1.1/maps/legacy.json', function (module, exports, __jupyter_require__) {
	module.exports = {
		"Aacute": "Á",
		"aacute": "á",
		"Acirc": "Â",
		"acirc": "â",
		"acute": "´",
		"AElig": "Æ",
		"aelig": "æ",
		"Agrave": "À",
		"agrave": "à",
		"amp": "&",
		"AMP": "&",
		"Aring": "Å",
		"aring": "å",
		"Atilde": "Ã",
		"atilde": "ã",
		"Auml": "Ä",
		"auml": "ä",
		"brvbar": "¦",
		"Ccedil": "Ç",
		"ccedil": "ç",
		"cedil": "¸",
		"cent": "¢",
		"copy": "©",
		"COPY": "©",
		"curren": "¤",
		"deg": "°",
		"divide": "÷",
		"Eacute": "É",
		"eacute": "é",
		"Ecirc": "Ê",
		"ecirc": "ê",
		"Egrave": "È",
		"egrave": "è",
		"ETH": "Ð",
		"eth": "ð",
		"Euml": "Ë",
		"euml": "ë",
		"frac12": "½",
		"frac14": "¼",
		"frac34": "¾",
		"gt": ">",
		"GT": ">",
		"Iacute": "Í",
		"iacute": "í",
		"Icirc": "Î",
		"icirc": "î",
		"iexcl": "¡",
		"Igrave": "Ì",
		"igrave": "ì",
		"iquest": "¿",
		"Iuml": "Ï",
		"iuml": "ï",
		"laquo": "«",
		"lt": "<",
		"LT": "<",
		"macr": "¯",
		"micro": "µ",
		"middot": "·",
		"nbsp": " ",
		"not": "¬",
		"Ntilde": "Ñ",
		"ntilde": "ñ",
		"Oacute": "Ó",
		"oacute": "ó",
		"Ocirc": "Ô",
		"ocirc": "ô",
		"Ograve": "Ò",
		"ograve": "ò",
		"ordf": "ª",
		"ordm": "º",
		"Oslash": "Ø",
		"oslash": "ø",
		"Otilde": "Õ",
		"otilde": "õ",
		"Ouml": "Ö",
		"ouml": "ö",
		"para": "¶",
		"plusmn": "±",
		"pound": "£",
		"quot": "\"",
		"QUOT": "\"",
		"raquo": "»",
		"reg": "®",
		"REG": "®",
		"sect": "§",
		"shy": "­",
		"sup1": "¹",
		"sup2": "²",
		"sup3": "³",
		"szlig": "ß",
		"THORN": "Þ",
		"thorn": "þ",
		"times": "×",
		"Uacute": "Ú",
		"uacute": "ú",
		"Ucirc": "Û",
		"ucirc": "û",
		"Ugrave": "Ù",
		"ugrave": "ù",
		"uml": "¨",
		"Uuml": "Ü",
		"uuml": "ü",
		"Yacute": "Ý",
		"yacute": "ý",
		"yen": "¥",
		"yuml": "ÿ"
	};
})
/** END DEFINE BLOCK for entities@1.1.1/maps/legacy.json **/


/** START DEFINE BLOCK for entities@1.1.1/maps/xml.json **/
jupyter.define('entities@1.1.1/maps/xml.json', function (module, exports, __jupyter_require__) {
	module.exports = {
		"amp": "&",
		"apos": "'",
		"gt": ">",
		"lt": "<",
		"quot": "\""
	};
})
/** END DEFINE BLOCK for entities@1.1.1/maps/xml.json **/


/** START DEFINE BLOCK for inherits@2.0.3/inherits_browser.js **/
jupyter.define('inherits@2.0.3/inherits_browser.js', function (module, exports, __jupyter_require__) {
	if (typeof Object.create === 'function') {
	  // implementation from standard node.js 'util' module
	  module.exports = function inherits(ctor, superCtor) {
	    ctor.super_ = superCtor
	    ctor.prototype = Object.create(superCtor.prototype, {
	      constructor: {
	        value: ctor,
	        enumerable: false,
	        writable: true,
	        configurable: true
	      }
	    });
	  };
	} else {
	  // old school shim for old browsers
	  module.exports = function inherits(ctor, superCtor) {
	    ctor.super_ = superCtor
	    var TempCtor = function () {}
	    TempCtor.prototype = superCtor.prototype
	    ctor.prototype = new TempCtor()
	    ctor.prototype.constructor = ctor
	  }
	}
	
})
/** END DEFINE BLOCK for inherits@2.0.3/inherits_browser.js **/


/** START DEFINE BLOCK for events@1.1.1/events.js **/
jupyter.define('events@1.1.1/events.js', function (module, exports, __jupyter_require__) {
	// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.
	
	function EventEmitter() {
	  this._events = this._events || {};
	  this._maxListeners = this._maxListeners || undefined;
	}
	module.exports = EventEmitter;
	
	// Backwards-compat with node 0.10.x
	EventEmitter.EventEmitter = EventEmitter;
	
	EventEmitter.prototype._events = undefined;
	EventEmitter.prototype._maxListeners = undefined;
	
	// By default EventEmitters will print a warning if more than 10 listeners are
	// added to it. This is a useful default which helps finding memory leaks.
	EventEmitter.defaultMaxListeners = 10;
	
	// Obviously not all Emitters should be limited to 10. This function allows
	// that to be increased. Set to zero for unlimited.
	EventEmitter.prototype.setMaxListeners = function(n) {
	  if (!isNumber(n) || n < 0 || isNaN(n))
	    throw TypeError('n must be a positive number');
	  this._maxListeners = n;
	  return this;
	};
	
	EventEmitter.prototype.emit = function(type) {
	  var er, handler, len, args, i, listeners;
	
	  if (!this._events)
	    this._events = {};
	
	  // If there is no 'error' event listener then throw.
	  if (type === 'error') {
	    if (!this._events.error ||
	        (isObject(this._events.error) && !this._events.error.length)) {
	      er = arguments[1];
	      if (er instanceof Error) {
	        throw er; // Unhandled 'error' event
	      } else {
	        // At least give some kind of context to the user
	        var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
	        err.context = er;
	        throw err;
	      }
	    }
	  }
	
	  handler = this._events[type];
	
	  if (isUndefined(handler))
	    return false;
	
	  if (isFunction(handler)) {
	    switch (arguments.length) {
	      // fast cases
	      case 1:
	        handler.call(this);
	        break;
	      case 2:
	        handler.call(this, arguments[1]);
	        break;
	      case 3:
	        handler.call(this, arguments[1], arguments[2]);
	        break;
	      // slower
	      default:
	        args = Array.prototype.slice.call(arguments, 1);
	        handler.apply(this, args);
	    }
	  } else if (isObject(handler)) {
	    args = Array.prototype.slice.call(arguments, 1);
	    listeners = handler.slice();
	    len = listeners.length;
	    for (i = 0; i < len; i++)
	      listeners[i].apply(this, args);
	  }
	
	  return true;
	};
	
	EventEmitter.prototype.addListener = function(type, listener) {
	  var m;
	
	  if (!isFunction(listener))
	    throw TypeError('listener must be a function');
	
	  if (!this._events)
	    this._events = {};
	
	  // To avoid recursion in the case that type === "newListener"! Before
	  // adding it to the listeners, first emit "newListener".
	  if (this._events.newListener)
	    this.emit('newListener', type,
	              isFunction(listener.listener) ?
	              listener.listener : listener);
	
	  if (!this._events[type])
	    // Optimize the case of one listener. Don't need the extra array object.
	    this._events[type] = listener;
	  else if (isObject(this._events[type]))
	    // If we've already got an array, just append.
	    this._events[type].push(listener);
	  else
	    // Adding the second element, need to change to array.
	    this._events[type] = [this._events[type], listener];
	
	  // Check for listener leak
	  if (isObject(this._events[type]) && !this._events[type].warned) {
	    if (!isUndefined(this._maxListeners)) {
	      m = this._maxListeners;
	    } else {
	      m = EventEmitter.defaultMaxListeners;
	    }
	
	    if (m && m > 0 && this._events[type].length > m) {
	      this._events[type].warned = true;
	      console.error('(node) warning: possible EventEmitter memory ' +
	                    'leak detected. %d listeners added. ' +
	                    'Use emitter.setMaxListeners() to increase limit.',
	                    this._events[type].length);
	      if (typeof console.trace === 'function') {
	        // not supported in IE 10
	        console.trace();
	      }
	    }
	  }
	
	  return this;
	};
	
	EventEmitter.prototype.on = EventEmitter.prototype.addListener;
	
	EventEmitter.prototype.once = function(type, listener) {
	  if (!isFunction(listener))
	    throw TypeError('listener must be a function');
	
	  var fired = false;
	
	  function g() {
	    this.removeListener(type, g);
	
	    if (!fired) {
	      fired = true;
	      listener.apply(this, arguments);
	    }
	  }
	
	  g.listener = listener;
	  this.on(type, g);
	
	  return this;
	};
	
	// emits a 'removeListener' event iff the listener was removed
	EventEmitter.prototype.removeListener = function(type, listener) {
	  var list, position, length, i;
	
	  if (!isFunction(listener))
	    throw TypeError('listener must be a function');
	
	  if (!this._events || !this._events[type])
	    return this;
	
	  list = this._events[type];
	  length = list.length;
	  position = -1;
	
	  if (list === listener ||
	      (isFunction(list.listener) && list.listener === listener)) {
	    delete this._events[type];
	    if (this._events.removeListener)
	      this.emit('removeListener', type, listener);
	
	  } else if (isObject(list)) {
	    for (i = length; i-- > 0;) {
	      if (list[i] === listener ||
	          (list[i].listener && list[i].listener === listener)) {
	        position = i;
	        break;
	      }
	    }
	
	    if (position < 0)
	      return this;
	
	    if (list.length === 1) {
	      list.length = 0;
	      delete this._events[type];
	    } else {
	      list.splice(position, 1);
	    }
	
	    if (this._events.removeListener)
	      this.emit('removeListener', type, listener);
	  }
	
	  return this;
	};
	
	EventEmitter.prototype.removeAllListeners = function(type) {
	  var key, listeners;
	
	  if (!this._events)
	    return this;
	
	  // not listening for removeListener, no need to emit
	  if (!this._events.removeListener) {
	    if (arguments.length === 0)
	      this._events = {};
	    else if (this._events[type])
	      delete this._events[type];
	    return this;
	  }
	
	  // emit removeListener for all listeners on all events
	  if (arguments.length === 0) {
	    for (key in this._events) {
	      if (key === 'removeListener') continue;
	      this.removeAllListeners(key);
	    }
	    this.removeAllListeners('removeListener');
	    this._events = {};
	    return this;
	  }
	
	  listeners = this._events[type];
	
	  if (isFunction(listeners)) {
	    this.removeListener(type, listeners);
	  } else if (listeners) {
	    // LIFO order
	    while (listeners.length)
	      this.removeListener(type, listeners[listeners.length - 1]);
	  }
	  delete this._events[type];
	
	  return this;
	};
	
	EventEmitter.prototype.listeners = function(type) {
	  var ret;
	  if (!this._events || !this._events[type])
	    ret = [];
	  else if (isFunction(this._events[type]))
	    ret = [this._events[type]];
	  else
	    ret = this._events[type].slice();
	  return ret;
	};
	
	EventEmitter.prototype.listenerCount = function(type) {
	  if (this._events) {
	    var evlistener = this._events[type];
	
	    if (isFunction(evlistener))
	      return 1;
	    else if (evlistener)
	      return evlistener.length;
	  }
	  return 0;
	};
	
	EventEmitter.listenerCount = function(emitter, type) {
	  return emitter.listenerCount(type);
	};
	
	function isFunction(arg) {
	  return typeof arg === 'function';
	}
	
	function isNumber(arg) {
	  return typeof arg === 'number';
	}
	
	function isObject(arg) {
	  return typeof arg === 'object' && arg !== null;
	}
	
	function isUndefined(arg) {
	  return arg === void 0;
	}
	
})
/** END DEFINE BLOCK for events@1.1.1/events.js **/


/** START DEFINE BLOCK for domhandler@2.3.0/index.js **/
jupyter.define('domhandler@2.3.0/index.js', function (module, exports, __jupyter_require__) {
	var ElementType = __jupyter_require__('domelementtype@1/index.js');
	
	var re_whitespace = /\s+/g;
	var NodePrototype = __jupyter_require__('domhandler@2.3.0/lib/node.js');
	var ElementPrototype = __jupyter_require__('domhandler@2.3.0/lib/element.js');
	
	function DomHandler(callback, options, elementCB){
		if(typeof callback === "object"){
			elementCB = options;
			options = callback;
			callback = null;
		} else if(typeof options === "function"){
			elementCB = options;
			options = defaultOpts;
		}
		this._callback = callback;
		this._options = options || defaultOpts;
		this._elementCB = elementCB;
		this.dom = [];
		this._done = false;
		this._tagStack = [];
		this._parser = this._parser || null;
	}
	
	//default options
	var defaultOpts = {
		normalizeWhitespace: false, //Replace all whitespace with single spaces
		withStartIndices: false, //Add startIndex properties to nodes
	};
	
	DomHandler.prototype.onparserinit = function(parser){
		this._parser = parser;
	};
	
	//Resets the handler back to starting state
	DomHandler.prototype.onreset = function(){
		DomHandler.call(this, this._callback, this._options, this._elementCB);
	};
	
	//Signals the handler that parsing is done
	DomHandler.prototype.onend = function(){
		if(this._done) return;
		this._done = true;
		this._parser = null;
		this._handleCallback(null);
	};
	
	DomHandler.prototype._handleCallback =
	DomHandler.prototype.onerror = function(error){
		if(typeof this._callback === "function"){
			this._callback(error, this.dom);
		} else {
			if(error) throw error;
		}
	};
	
	DomHandler.prototype.onclosetag = function(){
		//if(this._tagStack.pop().name !== name) this._handleCallback(Error("Tagname didn't match!"));
		var elem = this._tagStack.pop();
		if(this._elementCB) this._elementCB(elem);
	};
	
	DomHandler.prototype._addDomElement = function(element){
		var parent = this._tagStack[this._tagStack.length - 1];
		var siblings = parent ? parent.children : this.dom;
		var previousSibling = siblings[siblings.length - 1];
	
		element.next = null;
	
		if(this._options.withStartIndices){
			element.startIndex = this._parser.startIndex;
		}
	
		if (this._options.withDomLvl1) {
			element.__proto__ = element.type === "tag" ? ElementPrototype : NodePrototype;
		}
	
		if(previousSibling){
			element.prev = previousSibling;
			previousSibling.next = element;
		} else {
			element.prev = null;
		}
	
		siblings.push(element);
		element.parent = parent || null;
	};
	
	DomHandler.prototype.onopentag = function(name, attribs){
		var element = {
			type: name === "script" ? ElementType.Script : name === "style" ? ElementType.Style : ElementType.Tag,
			name: name,
			attribs: attribs,
			children: []
		};
	
		this._addDomElement(element);
	
		this._tagStack.push(element);
	};
	
	DomHandler.prototype.ontext = function(data){
		//the ignoreWhitespace is officially dropped, but for now,
		//it's an alias for normalizeWhitespace
		var normalize = this._options.normalizeWhitespace || this._options.ignoreWhitespace;
	
		var lastTag;
	
		if(!this._tagStack.length && this.dom.length && (lastTag = this.dom[this.dom.length-1]).type === ElementType.Text){
			if(normalize){
				lastTag.data = (lastTag.data + data).replace(re_whitespace, " ");
			} else {
				lastTag.data += data;
			}
		} else {
			if(
				this._tagStack.length &&
				(lastTag = this._tagStack[this._tagStack.length - 1]) &&
				(lastTag = lastTag.children[lastTag.children.length - 1]) &&
				lastTag.type === ElementType.Text
			){
				if(normalize){
					lastTag.data = (lastTag.data + data).replace(re_whitespace, " ");
				} else {
					lastTag.data += data;
				}
			} else {
				if(normalize){
					data = data.replace(re_whitespace, " ");
				}
	
				this._addDomElement({
					data: data,
					type: ElementType.Text
				});
			}
		}
	};
	
	DomHandler.prototype.oncomment = function(data){
		var lastTag = this._tagStack[this._tagStack.length - 1];
	
		if(lastTag && lastTag.type === ElementType.Comment){
			lastTag.data += data;
			return;
		}
	
		var element = {
			data: data,
			type: ElementType.Comment
		};
	
		this._addDomElement(element);
		this._tagStack.push(element);
	};
	
	DomHandler.prototype.oncdatastart = function(){
		var element = {
			children: [{
				data: "",
				type: ElementType.Text
			}],
			type: ElementType.CDATA
		};
	
		this._addDomElement(element);
		this._tagStack.push(element);
	};
	
	DomHandler.prototype.oncommentend = DomHandler.prototype.oncdataend = function(){
		this._tagStack.pop();
	};
	
	DomHandler.prototype.onprocessinginstruction = function(name, data){
		this._addDomElement({
			name: name,
			data: data,
			type: ElementType.Directive
		});
	};
	
	module.exports = DomHandler;
	
})
/** END DEFINE BLOCK for domhandler@2.3.0/index.js **/


/** START DEFINE BLOCK for domelementtype@1.3.0/index.js **/
jupyter.define('domelementtype@1.3.0/index.js', function (module, exports, __jupyter_require__) {
	//Types of elements found in the DOM
	module.exports = {
		Text: "text", //Text
		Directive: "directive", //<? ... ?>
		Comment: "comment", //<!-- ... -->
		Script: "script", //<script> tags
		Style: "style", //<style> tags
		Tag: "tag", //Any tag
		CDATA: "cdata", //<![CDATA[ ... ]]>
		Doctype: "doctype",
	
		isTag: function(elem){
			return elem.type === "tag" || elem.type === "script" || elem.type === "style";
		}
	};
	
})
/** END DEFINE BLOCK for domelementtype@1.3.0/index.js **/


/** START DEFINE BLOCK for domhandler@2.3.0/lib/node.js **/
jupyter.define('domhandler@2.3.0/lib/node.js', function (module, exports, __jupyter_require__) {
	// This object will be used as the prototype for Nodes when creating a
	// DOM-Level-1-compliant structure.
	var NodePrototype = module.exports = {
		get firstChild() {
			var children = this.children;
			return children && children[0] || null;
		},
		get lastChild() {
			var children = this.children;
			return children && children[children.length - 1] || null;
		},
		get nodeType() {
			return nodeTypes[this.type] || nodeTypes.element;
		}
	};
	
	var domLvl1 = {
		tagName: "name",
		childNodes: "children",
		parentNode: "parent",
		previousSibling: "prev",
		nextSibling: "next",
		nodeValue: "data"
	};
	
	var nodeTypes = {
		element: 1,
		text: 3,
		cdata: 4,
		comment: 8
	};
	
	Object.keys(domLvl1).forEach(function(key) {
		var shorthand = domLvl1[key];
		Object.defineProperty(NodePrototype, key, {
			get: function() {
				return this[shorthand] || null;
			},
			set: function(val) {
				this[shorthand] = val;
				return val;
			}
		});
	});
	
})
/** END DEFINE BLOCK for domhandler@2.3.0/lib/node.js **/


/** START DEFINE BLOCK for domhandler@2.3.0/lib/element.js **/
jupyter.define('domhandler@2.3.0/lib/element.js', function (module, exports, __jupyter_require__) {
	// DOM-Level-1-compliant structure
	var NodePrototype = __jupyter_require__('domhandler@2.3.0/lib/node.js');
	var ElementPrototype = module.exports = Object.create(NodePrototype);
	
	var domLvl1 = {
		tagName: "name"
	};
	
	Object.keys(domLvl1).forEach(function(key) {
		var shorthand = domLvl1[key];
		Object.defineProperty(ElementPrototype, key, {
			get: function() {
				return this[shorthand] || null;
			},
			set: function(val) {
				this[shorthand] = val;
				return val;
			}
		});
	});
	
})
/** END DEFINE BLOCK for domhandler@2.3.0/lib/element.js **/


/** START DEFINE BLOCK for htmlparser2@3.9.2/lib/FeedHandler.js **/
jupyter.define('htmlparser2@3.9.2/lib/FeedHandler.js', function (module, exports, __jupyter_require__) {
	var index = __jupyter_require__('htmlparser2@3.9.2/lib/index.js'),
	    DomHandler = index.DomHandler,
	    DomUtils = index.DomUtils;
	
	//TODO: make this a streamable handler
	function FeedHandler(callback, options){
		this.init(callback, options);
	}
	
	__jupyter_require__('inherits@^2.0.1/inherits_browser.js')(FeedHandler, DomHandler);
	
	FeedHandler.prototype.init = DomHandler;
	
	function getElements(what, where){
		return DomUtils.getElementsByTagName(what, where, true);
	}
	function getOneElement(what, where){
		return DomUtils.getElementsByTagName(what, where, true, 1)[0];
	}
	function fetch(what, where, recurse){
		return DomUtils.getText(
			DomUtils.getElementsByTagName(what, where, recurse, 1)
		).trim();
	}
	
	function addConditionally(obj, prop, what, where, recurse){
		var tmp = fetch(what, where, recurse);
		if(tmp) obj[prop] = tmp;
	}
	
	var isValidFeed = function(value){
		return value === "rss" || value === "feed" || value === "rdf:RDF";
	};
	
	FeedHandler.prototype.onend = function(){
		var feed = {},
		    feedRoot = getOneElement(isValidFeed, this.dom),
		    tmp, childs;
	
		if(feedRoot){
			if(feedRoot.name === "feed"){
				childs = feedRoot.children;
	
				feed.type = "atom";
				addConditionally(feed, "id", "id", childs);
				addConditionally(feed, "title", "title", childs);
				if((tmp = getOneElement("link", childs)) && (tmp = tmp.attribs) && (tmp = tmp.href)) feed.link = tmp;
				addConditionally(feed, "description", "subtitle", childs);
				if((tmp = fetch("updated", childs))) feed.updated = new Date(tmp);
				addConditionally(feed, "author", "email", childs, true);
	
				feed.items = getElements("entry", childs).map(function(item){
					var entry = {}, tmp;
	
					item = item.children;
	
					addConditionally(entry, "id", "id", item);
					addConditionally(entry, "title", "title", item);
					if((tmp = getOneElement("link", item)) && (tmp = tmp.attribs) && (tmp = tmp.href)) entry.link = tmp;
					if((tmp = fetch("summary", item) || fetch("content", item))) entry.description = tmp;
					if((tmp = fetch("updated", item))) entry.pubDate = new Date(tmp);
					return entry;
				});
			} else {
				childs = getOneElement("channel", feedRoot.children).children;
	
				feed.type = feedRoot.name.substr(0, 3);
				feed.id = "";
				addConditionally(feed, "title", "title", childs);
				addConditionally(feed, "link", "link", childs);
				addConditionally(feed, "description", "description", childs);
				if((tmp = fetch("lastBuildDate", childs))) feed.updated = new Date(tmp);
				addConditionally(feed, "author", "managingEditor", childs, true);
	
				feed.items = getElements("item", feedRoot.children).map(function(item){
					var entry = {}, tmp;
	
					item = item.children;
	
					addConditionally(entry, "id", "guid", item);
					addConditionally(entry, "title", "title", item);
					addConditionally(entry, "link", "link", item);
					addConditionally(entry, "description", "description", item);
					if((tmp = fetch("pubDate", item))) entry.pubDate = new Date(tmp);
					return entry;
				});
			}
		}
		this.dom = feed;
		DomHandler.prototype._handleCallback.call(
			this, feedRoot ? null : Error("couldn't find root of feed")
		);
	};
	
	module.exports = FeedHandler;
	
})
/** END DEFINE BLOCK for htmlparser2@3.9.2/lib/FeedHandler.js **/


/** START DEFINE BLOCK for htmlparser2@3.9.2/lib/Stream.js **/
jupyter.define('htmlparser2@3.9.2/lib/Stream.js', function (module, exports, __jupyter_require__) {
	module.exports = Stream;
	
	var Parser = __jupyter_require__('htmlparser2@3.9.2/lib/WritableStream.js');
	
	function Stream(options){
		Parser.call(this, new Cbs(this), options);
	}
	
	__jupyter_require__('inherits@^2.0.1/inherits_browser.js')(Stream, Parser);
	
	Stream.prototype.readable = true;
	
	function Cbs(scope){
		this.scope = scope;
	}
	
	var EVENTS = __jupyter_require__('htmlparser2@3.9.2/lib/index.js').EVENTS;
	
	Object.keys(EVENTS).forEach(function(name){
		if(EVENTS[name] === 0){
			Cbs.prototype["on" + name] = function(){
				this.scope.emit(name);
			};
		} else if(EVENTS[name] === 1){
			Cbs.prototype["on" + name] = function(a){
				this.scope.emit(name, a);
			};
		} else if(EVENTS[name] === 2){
			Cbs.prototype["on" + name] = function(a, b){
				this.scope.emit(name, a, b);
			};
		} else {
			throw Error("wrong number of arguments!");
		}
	});
})
/** END DEFINE BLOCK for htmlparser2@3.9.2/lib/Stream.js **/


/** START DEFINE BLOCK for htmlparser2@3.9.2/lib/WritableStream.js **/
jupyter.define('htmlparser2@3.9.2/lib/WritableStream.js', function (module, exports, __jupyter_require__) {
	module.exports = Stream;
	
	var Parser = __jupyter_require__('htmlparser2@3.9.2/lib/Parser.js'),
	    WritableStream = __jupyter_require__('stream-browserify@2.0.1/index.js').Writable || __jupyter_require__('__ignored__').Writable,
	    StringDecoder = __jupyter_require__('string_decoder@0.10.31/index.js').StringDecoder,
	    Buffer = __jupyter_require__('buffer@4.9.1/index.js').Buffer;
	
	function Stream(cbs, options){
		var parser = this._parser = new Parser(cbs, options);
		var decoder = this._decoder = new StringDecoder();
	
		WritableStream.call(this, {decodeStrings: false});
	
		this.once("finish", function(){
			parser.end(decoder.end());
		});
	}
	
	__jupyter_require__('inherits@^2.0.1/inherits_browser.js')(Stream, WritableStream);
	
	WritableStream.prototype._write = function(chunk, encoding, cb){
		if(chunk instanceof Buffer) chunk = this._decoder.write(chunk);
		this._parser.write(chunk);
		cb();
	};
})
/** END DEFINE BLOCK for htmlparser2@3.9.2/lib/WritableStream.js **/


/** START DEFINE BLOCK for stream-browserify@2.0.1/index.js **/
jupyter.define('stream-browserify@2.0.1/index.js', function (module, exports, __jupyter_require__) {
	// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.
	
	module.exports = Stream;
	
	var EE = __jupyter_require__('events@1.1.1/events.js').EventEmitter;
	var inherits = __jupyter_require__('inherits@~2.0.1/inherits_browser.js');
	
	inherits(Stream, EE);
	Stream.Readable = __jupyter_require__('readable-stream@^2.0.2/readable.js');
	Stream.Writable = __jupyter_require__('readable-stream@^2.0.2/writable.js');
	Stream.Duplex = __jupyter_require__('readable-stream@^2.0.2/duplex.js');
	Stream.Transform = __jupyter_require__('readable-stream@^2.0.2/transform.js');
	Stream.PassThrough = __jupyter_require__('readable-stream@^2.0.2/passthrough.js');
	
	// Backwards-compat with node 0.4.x
	Stream.Stream = Stream;
	
	
	
	// old-style streams.  Note that the pipe method (the only relevant
	// part of this class) is overridden in the Readable class.
	
	function Stream() {
	  EE.call(this);
	}
	
	Stream.prototype.pipe = function(dest, options) {
	  var source = this;
	
	  function ondata(chunk) {
	    if (dest.writable) {
	      if (false === dest.write(chunk) && source.pause) {
	        source.pause();
	      }
	    }
	  }
	
	  source.on('data', ondata);
	
	  function ondrain() {
	    if (source.readable && source.resume) {
	      source.resume();
	    }
	  }
	
	  dest.on('drain', ondrain);
	
	  // If the 'end' option is not supplied, dest.end() will be called when
	  // source gets the 'end' or 'close' events.  Only dest.end() once.
	  if (!dest._isStdio && (!options || options.end !== false)) {
	    source.on('end', onend);
	    source.on('close', onclose);
	  }
	
	  var didOnEnd = false;
	  function onend() {
	    if (didOnEnd) return;
	    didOnEnd = true;
	
	    dest.end();
	  }
	
	
	  function onclose() {
	    if (didOnEnd) return;
	    didOnEnd = true;
	
	    if (typeof dest.destroy === 'function') dest.destroy();
	  }
	
	  // don't leave dangling pipes when there are errors.
	  function onerror(er) {
	    cleanup();
	    if (EE.listenerCount(this, 'error') === 0) {
	      throw er; // Unhandled stream error in pipe.
	    }
	  }
	
	  source.on('error', onerror);
	  dest.on('error', onerror);
	
	  // remove all the event listeners that were added.
	  function cleanup() {
	    source.removeListener('data', ondata);
	    dest.removeListener('drain', ondrain);
	
	    source.removeListener('end', onend);
	    source.removeListener('close', onclose);
	
	    source.removeListener('error', onerror);
	    dest.removeListener('error', onerror);
	
	    source.removeListener('end', cleanup);
	    source.removeListener('close', cleanup);
	
	    dest.removeListener('close', cleanup);
	  }
	
	  source.on('end', cleanup);
	  source.on('close', cleanup);
	
	  dest.on('close', cleanup);
	
	  dest.emit('pipe', source);
	
	  // Allow for unix-like usage: A.pipe(B).pipe(C)
	  return dest;
	};
	
})
/** END DEFINE BLOCK for stream-browserify@2.0.1/index.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/readable.js **/
jupyter.define('readable-stream@2.2.2/readable.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(process) {var Stream = (function (){
	  try {
	    return __jupyter_require__('stream-browserify@2.0.1/index.js'); // hack to fix a circular dependency issue when used with browserify
	  } catch(_){}
	}());
	exports = module.exports = __jupyter_require__('readable-stream@2.2.2/lib/_stream_readable.js');
	exports.Stream = Stream || exports;
	exports.Readable = exports;
	exports.Writable = __jupyter_require__('readable-stream@2.2.2/lib/_stream_writable.js');
	exports.Duplex = __jupyter_require__('readable-stream@2.2.2/lib/_stream_duplex.js');
	exports.Transform = __jupyter_require__('readable-stream@2.2.2/lib/_stream_transform.js');
	exports.PassThrough = __jupyter_require__('readable-stream@2.2.2/lib/_stream_passthrough.js');
	
	if (!process.browser && ({"GIT_DESCRIPTION":"v0.15.1"}).READABLE_STREAM === 'disable' && Stream) {
	  module.exports = Stream;
	}
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('process@0.11.9/browser.js')))
})
/** END DEFINE BLOCK for readable-stream@2.2.2/readable.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_readable.js **/
jupyter.define('readable-stream@2.2.2/lib/_stream_readable.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(process) {'use strict';
	
	module.exports = Readable;
	
	/*<replacement>*/
	var processNextTick = __jupyter_require__('process-nextick-args@~1.0.6/index.js');
	/*</replacement>*/
	
	/*<replacement>*/
	var isArray = __jupyter_require__('isarray@~1.0.0/index.js');
	/*</replacement>*/
	
	/*<replacement>*/
	var Duplex;
	/*</replacement>*/
	
	Readable.ReadableState = ReadableState;
	
	/*<replacement>*/
	var EE = __jupyter_require__('events@1.1.1/events.js').EventEmitter;
	
	var EElistenerCount = function (emitter, type) {
	  return emitter.listeners(type).length;
	};
	/*</replacement>*/
	
	/*<replacement>*/
	var Stream;
	(function () {
	  try {
	    Stream = __jupyter_require__('stream-browserify@2.0.1/index.js');
	  } catch (_) {} finally {
	    if (!Stream) Stream = __jupyter_require__('events@1.1.1/events.js').EventEmitter;
	  }
	})();
	/*</replacement>*/
	
	var Buffer = __jupyter_require__('buffer@4.9.1/index.js').Buffer;
	/*<replacement>*/
	var bufferShim = __jupyter_require__('buffer-shims@^1.0.0/index.js');
	/*</replacement>*/
	
	/*<replacement>*/
	var util = __jupyter_require__('core-util-is@~1.0.0/lib/util.js');
	util.inherits = __jupyter_require__('inherits@~2.0.1/inherits_browser.js');
	/*</replacement>*/
	
	/*<replacement>*/
	var debugUtil = __jupyter_require__('__ignored__');
	var debug = void 0;
	if (debugUtil && debugUtil.debuglog) {
	  debug = debugUtil.debuglog('stream');
	} else {
	  debug = function () {};
	}
	/*</replacement>*/
	
	var BufferList = __jupyter_require__('readable-stream@2.2.2/lib/internal/streams/BufferList.js');
	var StringDecoder;
	
	util.inherits(Readable, Stream);
	
	function prependListener(emitter, event, fn) {
	  // Sadly this is not cacheable as some libraries bundle their own
	  // event emitter implementation with them.
	  if (typeof emitter.prependListener === 'function') {
	    return emitter.prependListener(event, fn);
	  } else {
	    // This is a hack to make sure that our error handler is attached before any
	    // userland ones.  NEVER DO THIS. This is here only because this code needs
	    // to continue to work with older versions of Node.js that do not include
	    // the prependListener() method. The goal is to eventually remove this hack.
	    if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]];
	  }
	}
	
	function ReadableState(options, stream) {
	  Duplex = Duplex || __jupyter_require__('readable-stream@2.2.2/lib/_stream_duplex.js');
	
	  options = options || {};
	
	  // object stream flag. Used to make read(n) ignore n and to
	  // make all the buffer merging and length checks go away
	  this.objectMode = !!options.objectMode;
	
	  if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode;
	
	  // the point at which it stops calling _read() to fill the buffer
	  // Note: 0 is a valid value, means "don't call _read preemptively ever"
	  var hwm = options.highWaterMark;
	  var defaultHwm = this.objectMode ? 16 : 16 * 1024;
	  this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
	
	  // cast to ints.
	  this.highWaterMark = ~ ~this.highWaterMark;
	
	  // A linked list is used to store data chunks instead of an array because the
	  // linked list can remove elements from the beginning faster than
	  // array.shift()
	  this.buffer = new BufferList();
	  this.length = 0;
	  this.pipes = null;
	  this.pipesCount = 0;
	  this.flowing = null;
	  this.ended = false;
	  this.endEmitted = false;
	  this.reading = false;
	
	  // a flag to be able to tell if the onwrite cb is called immediately,
	  // or on a later tick.  We set this to true at first, because any
	  // actions that shouldn't happen until "later" should generally also
	  // not happen before the first write call.
	  this.sync = true;
	
	  // whenever we return null, then we set a flag to say
	  // that we're awaiting a 'readable' event emission.
	  this.needReadable = false;
	  this.emittedReadable = false;
	  this.readableListening = false;
	  this.resumeScheduled = false;
	
	  // Crypto is kind of old and crusty.  Historically, its default string
	  // encoding is 'binary' so we have to make this configurable.
	  // Everything else in the universe uses 'utf8', though.
	  this.defaultEncoding = options.defaultEncoding || 'utf8';
	
	  // when piping, we only care about 'readable' events that happen
	  // after read()ing all the bytes and not getting any pushback.
	  this.ranOut = false;
	
	  // the number of writers that are awaiting a drain event in .pipe()s
	  this.awaitDrain = 0;
	
	  // if true, a maybeReadMore has been scheduled
	  this.readingMore = false;
	
	  this.decoder = null;
	  this.encoding = null;
	  if (options.encoding) {
	    if (!StringDecoder) StringDecoder = __jupyter_require__('string_decoder@~0.10.x/index.js').StringDecoder;
	    this.decoder = new StringDecoder(options.encoding);
	    this.encoding = options.encoding;
	  }
	}
	
	function Readable(options) {
	  Duplex = Duplex || __jupyter_require__('readable-stream@2.2.2/lib/_stream_duplex.js');
	
	  if (!(this instanceof Readable)) return new Readable(options);
	
	  this._readableState = new ReadableState(options, this);
	
	  // legacy
	  this.readable = true;
	
	  if (options && typeof options.read === 'function') this._read = options.read;
	
	  Stream.call(this);
	}
	
	// Manually shove something into the read() buffer.
	// This returns true if the highWaterMark has not been hit yet,
	// similar to how Writable.write() returns true if you should
	// write() some more.
	Readable.prototype.push = function (chunk, encoding) {
	  var state = this._readableState;
	
	  if (!state.objectMode && typeof chunk === 'string') {
	    encoding = encoding || state.defaultEncoding;
	    if (encoding !== state.encoding) {
	      chunk = bufferShim.from(chunk, encoding);
	      encoding = '';
	    }
	  }
	
	  return readableAddChunk(this, state, chunk, encoding, false);
	};
	
	// Unshift should *always* be something directly out of read()
	Readable.prototype.unshift = function (chunk) {
	  var state = this._readableState;
	  return readableAddChunk(this, state, chunk, '', true);
	};
	
	Readable.prototype.isPaused = function () {
	  return this._readableState.flowing === false;
	};
	
	function readableAddChunk(stream, state, chunk, encoding, addToFront) {
	  var er = chunkInvalid(state, chunk);
	  if (er) {
	    stream.emit('error', er);
	  } else if (chunk === null) {
	    state.reading = false;
	    onEofChunk(stream, state);
	  } else if (state.objectMode || chunk && chunk.length > 0) {
	    if (state.ended && !addToFront) {
	      var e = new Error('stream.push() after EOF');
	      stream.emit('error', e);
	    } else if (state.endEmitted && addToFront) {
	      var _e = new Error('stream.unshift() after end event');
	      stream.emit('error', _e);
	    } else {
	      var skipAdd;
	      if (state.decoder && !addToFront && !encoding) {
	        chunk = state.decoder.write(chunk);
	        skipAdd = !state.objectMode && chunk.length === 0;
	      }
	
	      if (!addToFront) state.reading = false;
	
	      // Don't add to the buffer if we've decoded to an empty string chunk and
	      // we're not in object mode
	      if (!skipAdd) {
	        // if we want the data now, just emit it.
	        if (state.flowing && state.length === 0 && !state.sync) {
	          stream.emit('data', chunk);
	          stream.read(0);
	        } else {
	          // update the buffer info.
	          state.length += state.objectMode ? 1 : chunk.length;
	          if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);
	
	          if (state.needReadable) emitReadable(stream);
	        }
	      }
	
	      maybeReadMore(stream, state);
	    }
	  } else if (!addToFront) {
	    state.reading = false;
	  }
	
	  return needMoreData(state);
	}
	
	// if it's past the high water mark, we can push in some more.
	// Also, if we have no data yet, we can stand some
	// more bytes.  This is to work around cases where hwm=0,
	// such as the repl.  Also, if the push() triggered a
	// readable event, and the user called read(largeNumber) such that
	// needReadable was set, then we ought to push more, so that another
	// 'readable' event will be triggered.
	function needMoreData(state) {
	  return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
	}
	
	// backwards compatibility.
	Readable.prototype.setEncoding = function (enc) {
	  if (!StringDecoder) StringDecoder = __jupyter_require__('string_decoder@~0.10.x/index.js').StringDecoder;
	  this._readableState.decoder = new StringDecoder(enc);
	  this._readableState.encoding = enc;
	  return this;
	};
	
	// Don't raise the hwm > 8MB
	var MAX_HWM = 0x800000;
	function computeNewHighWaterMark(n) {
	  if (n >= MAX_HWM) {
	    n = MAX_HWM;
	  } else {
	    // Get the next highest power of 2 to prevent increasing hwm excessively in
	    // tiny amounts
	    n--;
	    n |= n >>> 1;
	    n |= n >>> 2;
	    n |= n >>> 4;
	    n |= n >>> 8;
	    n |= n >>> 16;
	    n++;
	  }
	  return n;
	}
	
	// This function is designed to be inlinable, so please take care when making
	// changes to the function body.
	function howMuchToRead(n, state) {
	  if (n <= 0 || state.length === 0 && state.ended) return 0;
	  if (state.objectMode) return 1;
	  if (n !== n) {
	    // Only flow one buffer at a time
	    if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length;
	  }
	  // If we're asking for more than the current hwm, then raise the hwm.
	  if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
	  if (n <= state.length) return n;
	  // Don't have enough
	  if (!state.ended) {
	    state.needReadable = true;
	    return 0;
	  }
	  return state.length;
	}
	
	// you can override either this method, or the async _read(n) below.
	Readable.prototype.read = function (n) {
	  debug('read', n);
	  n = parseInt(n, 10);
	  var state = this._readableState;
	  var nOrig = n;
	
	  if (n !== 0) state.emittedReadable = false;
	
	  // if we're doing read(0) to trigger a readable event, but we
	  // already have a bunch of data in the buffer, then just trigger
	  // the 'readable' event and move on.
	  if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) {
	    debug('read: emitReadable', state.length, state.ended);
	    if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this);
	    return null;
	  }
	
	  n = howMuchToRead(n, state);
	
	  // if we've ended, and we're now clear, then finish it up.
	  if (n === 0 && state.ended) {
	    if (state.length === 0) endReadable(this);
	    return null;
	  }
	
	  // All the actual chunk generation logic needs to be
	  // *below* the call to _read.  The reason is that in certain
	  // synthetic stream cases, such as passthrough streams, _read
	  // may be a completely synchronous operation which may change
	  // the state of the read buffer, providing enough data when
	  // before there was *not* enough.
	  //
	  // So, the steps are:
	  // 1. Figure out what the state of things will be after we do
	  // a read from the buffer.
	  //
	  // 2. If that resulting state will trigger a _read, then call _read.
	  // Note that this may be asynchronous, or synchronous.  Yes, it is
	  // deeply ugly to write APIs this way, but that still doesn't mean
	  // that the Readable class should behave improperly, as streams are
	  // designed to be sync/async agnostic.
	  // Take note if the _read call is sync or async (ie, if the read call
	  // has returned yet), so that we know whether or not it's safe to emit
	  // 'readable' etc.
	  //
	  // 3. Actually pull the requested chunks out of the buffer and return.
	
	  // if we need a readable event, then we need to do some reading.
	  var doRead = state.needReadable;
	  debug('need readable', doRead);
	
	  // if we currently have less than the highWaterMark, then also read some
	  if (state.length === 0 || state.length - n < state.highWaterMark) {
	    doRead = true;
	    debug('length less than watermark', doRead);
	  }
	
	  // however, if we've ended, then there's no point, and if we're already
	  // reading, then it's unnecessary.
	  if (state.ended || state.reading) {
	    doRead = false;
	    debug('reading or ended', doRead);
	  } else if (doRead) {
	    debug('do read');
	    state.reading = true;
	    state.sync = true;
	    // if the length is currently zero, then we *need* a readable event.
	    if (state.length === 0) state.needReadable = true;
	    // call internal read method
	    this._read(state.highWaterMark);
	    state.sync = false;
	    // If _read pushed data synchronously, then `reading` will be false,
	    // and we need to re-evaluate how much data we can return to the user.
	    if (!state.reading) n = howMuchToRead(nOrig, state);
	  }
	
	  var ret;
	  if (n > 0) ret = fromList(n, state);else ret = null;
	
	  if (ret === null) {
	    state.needReadable = true;
	    n = 0;
	  } else {
	    state.length -= n;
	  }
	
	  if (state.length === 0) {
	    // If we have nothing in the buffer, then we want to know
	    // as soon as we *do* get something into the buffer.
	    if (!state.ended) state.needReadable = true;
	
	    // If we tried to read() past the EOF, then emit end on the next tick.
	    if (nOrig !== n && state.ended) endReadable(this);
	  }
	
	  if (ret !== null) this.emit('data', ret);
	
	  return ret;
	};
	
	function chunkInvalid(state, chunk) {
	  var er = null;
	  if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) {
	    er = new TypeError('Invalid non-string/buffer chunk');
	  }
	  return er;
	}
	
	function onEofChunk(stream, state) {
	  if (state.ended) return;
	  if (state.decoder) {
	    var chunk = state.decoder.end();
	    if (chunk && chunk.length) {
	      state.buffer.push(chunk);
	      state.length += state.objectMode ? 1 : chunk.length;
	    }
	  }
	  state.ended = true;
	
	  // emit 'readable' now to make sure it gets picked up.
	  emitReadable(stream);
	}
	
	// Don't emit readable right away in sync mode, because this can trigger
	// another read() call => stack overflow.  This way, it might trigger
	// a nextTick recursion warning, but that's not so bad.
	function emitReadable(stream) {
	  var state = stream._readableState;
	  state.needReadable = false;
	  if (!state.emittedReadable) {
	    debug('emitReadable', state.flowing);
	    state.emittedReadable = true;
	    if (state.sync) processNextTick(emitReadable_, stream);else emitReadable_(stream);
	  }
	}
	
	function emitReadable_(stream) {
	  debug('emit readable');
	  stream.emit('readable');
	  flow(stream);
	}
	
	// at this point, the user has presumably seen the 'readable' event,
	// and called read() to consume some data.  that may have triggered
	// in turn another _read(n) call, in which case reading = true if
	// it's in progress.
	// However, if we're not ended, or reading, and the length < hwm,
	// then go ahead and try to read some more preemptively.
	function maybeReadMore(stream, state) {
	  if (!state.readingMore) {
	    state.readingMore = true;
	    processNextTick(maybeReadMore_, stream, state);
	  }
	}
	
	function maybeReadMore_(stream, state) {
	  var len = state.length;
	  while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) {
	    debug('maybeReadMore read 0');
	    stream.read(0);
	    if (len === state.length)
	      // didn't get any data, stop spinning.
	      break;else len = state.length;
	  }
	  state.readingMore = false;
	}
	
	// abstract method.  to be overridden in specific implementation classes.
	// call cb(er, data) where data is <= n in length.
	// for virtual (non-string, non-buffer) streams, "length" is somewhat
	// arbitrary, and perhaps not very meaningful.
	Readable.prototype._read = function (n) {
	  this.emit('error', new Error('_read() is not implemented'));
	};
	
	Readable.prototype.pipe = function (dest, pipeOpts) {
	  var src = this;
	  var state = this._readableState;
	
	  switch (state.pipesCount) {
	    case 0:
	      state.pipes = dest;
	      break;
	    case 1:
	      state.pipes = [state.pipes, dest];
	      break;
	    default:
	      state.pipes.push(dest);
	      break;
	  }
	  state.pipesCount += 1;
	  debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
	
	  var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
	
	  var endFn = doEnd ? onend : cleanup;
	  if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn);
	
	  dest.on('unpipe', onunpipe);
	  function onunpipe(readable) {
	    debug('onunpipe');
	    if (readable === src) {
	      cleanup();
	    }
	  }
	
	  function onend() {
	    debug('onend');
	    dest.end();
	  }
	
	  // when the dest drains, it reduces the awaitDrain counter
	  // on the source.  This would be more elegant with a .once()
	  // handler in flow(), but adding and removing repeatedly is
	  // too slow.
	  var ondrain = pipeOnDrain(src);
	  dest.on('drain', ondrain);
	
	  var cleanedUp = false;
	  function cleanup() {
	    debug('cleanup');
	    // cleanup event handlers once the pipe is broken
	    dest.removeListener('close', onclose);
	    dest.removeListener('finish', onfinish);
	    dest.removeListener('drain', ondrain);
	    dest.removeListener('error', onerror);
	    dest.removeListener('unpipe', onunpipe);
	    src.removeListener('end', onend);
	    src.removeListener('end', cleanup);
	    src.removeListener('data', ondata);
	
	    cleanedUp = true;
	
	    // if the reader is waiting for a drain event from this
	    // specific writer, then it would cause it to never start
	    // flowing again.
	    // So, if this is awaiting a drain, then we just call it now.
	    // If we don't know, then assume that we are waiting for one.
	    if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
	  }
	
	  // If the user pushes more data while we're writing to dest then we'll end up
	  // in ondata again. However, we only want to increase awaitDrain once because
	  // dest will only emit one 'drain' event for the multiple writes.
	  // => Introduce a guard on increasing awaitDrain.
	  var increasedAwaitDrain = false;
	  src.on('data', ondata);
	  function ondata(chunk) {
	    debug('ondata');
	    increasedAwaitDrain = false;
	    var ret = dest.write(chunk);
	    if (false === ret && !increasedAwaitDrain) {
	      // If the user unpiped during `dest.write()`, it is possible
	      // to get stuck in a permanently paused state if that write
	      // also returned false.
	      // => Check whether `dest` is still a piping destination.
	      if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
	        debug('false write response, pause', src._readableState.awaitDrain);
	        src._readableState.awaitDrain++;
	        increasedAwaitDrain = true;
	      }
	      src.pause();
	    }
	  }
	
	  // if the dest has an error, then stop piping into it.
	  // however, don't suppress the throwing behavior for this.
	  function onerror(er) {
	    debug('onerror', er);
	    unpipe();
	    dest.removeListener('error', onerror);
	    if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er);
	  }
	
	  // Make sure our error handler is attached before userland ones.
	  prependListener(dest, 'error', onerror);
	
	  // Both close and finish should trigger unpipe, but only once.
	  function onclose() {
	    dest.removeListener('finish', onfinish);
	    unpipe();
	  }
	  dest.once('close', onclose);
	  function onfinish() {
	    debug('onfinish');
	    dest.removeListener('close', onclose);
	    unpipe();
	  }
	  dest.once('finish', onfinish);
	
	  function unpipe() {
	    debug('unpipe');
	    src.unpipe(dest);
	  }
	
	  // tell the dest that it's being piped to
	  dest.emit('pipe', src);
	
	  // start the flow if it hasn't been started already.
	  if (!state.flowing) {
	    debug('pipe resume');
	    src.resume();
	  }
	
	  return dest;
	};
	
	function pipeOnDrain(src) {
	  return function () {
	    var state = src._readableState;
	    debug('pipeOnDrain', state.awaitDrain);
	    if (state.awaitDrain) state.awaitDrain--;
	    if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
	      state.flowing = true;
	      flow(src);
	    }
	  };
	}
	
	Readable.prototype.unpipe = function (dest) {
	  var state = this._readableState;
	
	  // if we're not piping anywhere, then do nothing.
	  if (state.pipesCount === 0) return this;
	
	  // just one destination.  most common case.
	  if (state.pipesCount === 1) {
	    // passed in one, but it's not the right one.
	    if (dest && dest !== state.pipes) return this;
	
	    if (!dest) dest = state.pipes;
	
	    // got a match.
	    state.pipes = null;
	    state.pipesCount = 0;
	    state.flowing = false;
	    if (dest) dest.emit('unpipe', this);
	    return this;
	  }
	
	  // slow case. multiple pipe destinations.
	
	  if (!dest) {
	    // remove all.
	    var dests = state.pipes;
	    var len = state.pipesCount;
	    state.pipes = null;
	    state.pipesCount = 0;
	    state.flowing = false;
	
	    for (var i = 0; i < len; i++) {
	      dests[i].emit('unpipe', this);
	    }return this;
	  }
	
	  // try to find the right one.
	  var index = indexOf(state.pipes, dest);
	  if (index === -1) return this;
	
	  state.pipes.splice(index, 1);
	  state.pipesCount -= 1;
	  if (state.pipesCount === 1) state.pipes = state.pipes[0];
	
	  dest.emit('unpipe', this);
	
	  return this;
	};
	
	// set up data events if they are asked for
	// Ensure readable listeners eventually get something
	Readable.prototype.on = function (ev, fn) {
	  var res = Stream.prototype.on.call(this, ev, fn);
	
	  if (ev === 'data') {
	    // Start flowing on next tick if stream isn't explicitly paused
	    if (this._readableState.flowing !== false) this.resume();
	  } else if (ev === 'readable') {
	    var state = this._readableState;
	    if (!state.endEmitted && !state.readableListening) {
	      state.readableListening = state.needReadable = true;
	      state.emittedReadable = false;
	      if (!state.reading) {
	        processNextTick(nReadingNextTick, this);
	      } else if (state.length) {
	        emitReadable(this, state);
	      }
	    }
	  }
	
	  return res;
	};
	Readable.prototype.addListener = Readable.prototype.on;
	
	function nReadingNextTick(self) {
	  debug('readable nexttick read 0');
	  self.read(0);
	}
	
	// pause() and resume() are remnants of the legacy readable stream API
	// If the user uses them, then switch into old mode.
	Readable.prototype.resume = function () {
	  var state = this._readableState;
	  if (!state.flowing) {
	    debug('resume');
	    state.flowing = true;
	    resume(this, state);
	  }
	  return this;
	};
	
	function resume(stream, state) {
	  if (!state.resumeScheduled) {
	    state.resumeScheduled = true;
	    processNextTick(resume_, stream, state);
	  }
	}
	
	function resume_(stream, state) {
	  if (!state.reading) {
	    debug('resume read 0');
	    stream.read(0);
	  }
	
	  state.resumeScheduled = false;
	  state.awaitDrain = 0;
	  stream.emit('resume');
	  flow(stream);
	  if (state.flowing && !state.reading) stream.read(0);
	}
	
	Readable.prototype.pause = function () {
	  debug('call pause flowing=%j', this._readableState.flowing);
	  if (false !== this._readableState.flowing) {
	    debug('pause');
	    this._readableState.flowing = false;
	    this.emit('pause');
	  }
	  return this;
	};
	
	function flow(stream) {
	  var state = stream._readableState;
	  debug('flow', state.flowing);
	  while (state.flowing && stream.read() !== null) {}
	}
	
	// wrap an old-style stream as the async data source.
	// This is *not* part of the readable stream interface.
	// It is an ugly unfortunate mess of history.
	Readable.prototype.wrap = function (stream) {
	  var state = this._readableState;
	  var paused = false;
	
	  var self = this;
	  stream.on('end', function () {
	    debug('wrapped end');
	    if (state.decoder && !state.ended) {
	      var chunk = state.decoder.end();
	      if (chunk && chunk.length) self.push(chunk);
	    }
	
	    self.push(null);
	  });
	
	  stream.on('data', function (chunk) {
	    debug('wrapped data');
	    if (state.decoder) chunk = state.decoder.write(chunk);
	
	    // don't skip over falsy values in objectMode
	    if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return;
	
	    var ret = self.push(chunk);
	    if (!ret) {
	      paused = true;
	      stream.pause();
	    }
	  });
	
	  // proxy all the other methods.
	  // important when wrapping filters and duplexes.
	  for (var i in stream) {
	    if (this[i] === undefined && typeof stream[i] === 'function') {
	      this[i] = function (method) {
	        return function () {
	          return stream[method].apply(stream, arguments);
	        };
	      }(i);
	    }
	  }
	
	  // proxy certain important events.
	  var events = ['error', 'close', 'destroy', 'pause', 'resume'];
	  forEach(events, function (ev) {
	    stream.on(ev, self.emit.bind(self, ev));
	  });
	
	  // when we try to consume some more bytes, simply unpause the
	  // underlying stream.
	  self._read = function (n) {
	    debug('wrapped _read', n);
	    if (paused) {
	      paused = false;
	      stream.resume();
	    }
	  };
	
	  return self;
	};
	
	// exposed for testing purposes only.
	Readable._fromList = fromList;
	
	// Pluck off n bytes from an array of buffers.
	// Length is the combined lengths of all the buffers in the list.
	// This function is designed to be inlinable, so please take care when making
	// changes to the function body.
	function fromList(n, state) {
	  // nothing buffered
	  if (state.length === 0) return null;
	
	  var ret;
	  if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) {
	    // read it all, truncate the list
	    if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length);
	    state.buffer.clear();
	  } else {
	    // read part of list
	    ret = fromListPartial(n, state.buffer, state.decoder);
	  }
	
	  return ret;
	}
	
	// Extracts only enough buffered data to satisfy the amount requested.
	// This function is designed to be inlinable, so please take care when making
	// changes to the function body.
	function fromListPartial(n, list, hasStrings) {
	  var ret;
	  if (n < list.head.data.length) {
	    // slice is the same for buffers and strings
	    ret = list.head.data.slice(0, n);
	    list.head.data = list.head.data.slice(n);
	  } else if (n === list.head.data.length) {
	    // first chunk is a perfect match
	    ret = list.shift();
	  } else {
	    // result spans more than one buffer
	    ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
	  }
	  return ret;
	}
	
	// Copies a specified amount of characters from the list of buffered data
	// chunks.
	// This function is designed to be inlinable, so please take care when making
	// changes to the function body.
	function copyFromBufferString(n, list) {
	  var p = list.head;
	  var c = 1;
	  var ret = p.data;
	  n -= ret.length;
	  while (p = p.next) {
	    var str = p.data;
	    var nb = n > str.length ? str.length : n;
	    if (nb === str.length) ret += str;else ret += str.slice(0, n);
	    n -= nb;
	    if (n === 0) {
	      if (nb === str.length) {
	        ++c;
	        if (p.next) list.head = p.next;else list.head = list.tail = null;
	      } else {
	        list.head = p;
	        p.data = str.slice(nb);
	      }
	      break;
	    }
	    ++c;
	  }
	  list.length -= c;
	  return ret;
	}
	
	// Copies a specified amount of bytes from the list of buffered data chunks.
	// This function is designed to be inlinable, so please take care when making
	// changes to the function body.
	function copyFromBuffer(n, list) {
	  var ret = bufferShim.allocUnsafe(n);
	  var p = list.head;
	  var c = 1;
	  p.data.copy(ret);
	  n -= p.data.length;
	  while (p = p.next) {
	    var buf = p.data;
	    var nb = n > buf.length ? buf.length : n;
	    buf.copy(ret, ret.length - n, 0, nb);
	    n -= nb;
	    if (n === 0) {
	      if (nb === buf.length) {
	        ++c;
	        if (p.next) list.head = p.next;else list.head = list.tail = null;
	      } else {
	        list.head = p;
	        p.data = buf.slice(nb);
	      }
	      break;
	    }
	    ++c;
	  }
	  list.length -= c;
	  return ret;
	}
	
	function endReadable(stream) {
	  var state = stream._readableState;
	
	  // If we get here before consuming all the bytes, then that is a
	  // bug in node.  Should never happen.
	  if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream');
	
	  if (!state.endEmitted) {
	    state.ended = true;
	    processNextTick(endReadableNT, state, stream);
	  }
	}
	
	function endReadableNT(state, stream) {
	  // Check that we didn't get one last unshift.
	  if (!state.endEmitted && state.length === 0) {
	    state.endEmitted = true;
	    stream.readable = false;
	    stream.emit('end');
	  }
	}
	
	function forEach(xs, f) {
	  for (var i = 0, l = xs.length; i < l; i++) {
	    f(xs[i], i);
	  }
	}
	
	function indexOf(xs, x) {
	  for (var i = 0, l = xs.length; i < l; i++) {
	    if (xs[i] === x) return i;
	  }
	  return -1;
	}
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('process@0.11.9/browser.js')))
})
/** END DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_readable.js **/


/** START DEFINE BLOCK for process-nextick-args@1.0.7/index.js **/
jupyter.define('process-nextick-args@1.0.7/index.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(process) {'use strict';
	
	if (!process.version ||
	    process.version.indexOf('v0.') === 0 ||
	    process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) {
	  module.exports = nextTick;
	} else {
	  module.exports = process.nextTick;
	}
	
	function nextTick(fn, arg1, arg2, arg3) {
	  if (typeof fn !== 'function') {
	    throw new TypeError('"callback" argument must be a function');
	  }
	  var len = arguments.length;
	  var args, i;
	  switch (len) {
	  case 0:
	  case 1:
	    return process.nextTick(fn);
	  case 2:
	    return process.nextTick(function afterTickOne() {
	      fn.call(null, arg1);
	    });
	  case 3:
	    return process.nextTick(function afterTickTwo() {
	      fn.call(null, arg1, arg2);
	    });
	  case 4:
	    return process.nextTick(function afterTickThree() {
	      fn.call(null, arg1, arg2, arg3);
	    });
	  default:
	    args = new Array(len - 1);
	    i = 0;
	    while (i < args.length) {
	      args[i++] = arguments[i];
	    }
	    return process.nextTick(function afterTick() {
	      fn.apply(null, args);
	    });
	  }
	}
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('process@0.11.9/browser.js')))
})
/** END DEFINE BLOCK for process-nextick-args@1.0.7/index.js **/


/** START DEFINE BLOCK for isarray@1.0.0/index.js **/
jupyter.define('isarray@1.0.0/index.js', function (module, exports, __jupyter_require__) {
	var toString = {}.toString;
	
	module.exports = Array.isArray || function (arr) {
	  return toString.call(arr) == '[object Array]';
	};
	
})
/** END DEFINE BLOCK for isarray@1.0.0/index.js **/


/** START DEFINE BLOCK for buffer@4.9.1/index.js **/
jupyter.define('buffer@4.9.1/index.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(global) {/*!
	 * The buffer module from node.js, for the browser.
	 *
	 * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
	 * @license  MIT
	 */
	/* eslint-disable no-proto */
	
	'use strict'
	
	var base64 = __jupyter_require__('base64-js@^1.0.2/index.js')
	var ieee754 = __jupyter_require__('ieee754@^1.1.4/index.js')
	var isArray = __jupyter_require__('isarray@^1.0.0/index.js')
	
	exports.Buffer = Buffer
	exports.SlowBuffer = SlowBuffer
	exports.INSPECT_MAX_BYTES = 50
	
	/**
	 * If `Buffer.TYPED_ARRAY_SUPPORT`:
	 *   === true    Use Uint8Array implementation (fastest)
	 *   === false   Use Object implementation (most compatible, even IE6)
	 *
	 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
	 * Opera 11.6+, iOS 4.2+.
	 *
	 * Due to various browser bugs, sometimes the Object implementation will be used even
	 * when the browser supports typed arrays.
	 *
	 * Note:
	 *
	 *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
	 *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
	 *
	 *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
	 *
	 *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
	 *     incorrect length in some situations.
	
	 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
	 * get the Object implementation, which is slower but behaves correctly.
	 */
	Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
	  ? global.TYPED_ARRAY_SUPPORT
	  : typedArraySupport()
	
	/*
	 * Export kMaxLength after typed array support is determined.
	 */
	exports.kMaxLength = kMaxLength()
	
	function typedArraySupport () {
	  try {
	    var arr = new Uint8Array(1)
	    arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
	    return arr.foo() === 42 && // typed array instances can be augmented
	        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
	        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
	  } catch (e) {
	    return false
	  }
	}
	
	function kMaxLength () {
	  return Buffer.TYPED_ARRAY_SUPPORT
	    ? 0x7fffffff
	    : 0x3fffffff
	}
	
	function createBuffer (that, length) {
	  if (kMaxLength() < length) {
	    throw new RangeError('Invalid typed array length')
	  }
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    // Return an augmented `Uint8Array` instance, for best performance
	    that = new Uint8Array(length)
	    that.__proto__ = Buffer.prototype
	  } else {
	    // Fallback: Return an object instance of the Buffer class
	    if (that === null) {
	      that = new Buffer(length)
	    }
	    that.length = length
	  }
	
	  return that
	}
	
	/**
	 * The Buffer constructor returns instances of `Uint8Array` that have their
	 * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
	 * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
	 * and the `Uint8Array` methods. Square bracket notation works as expected -- it
	 * returns a single octet.
	 *
	 * The `Uint8Array` prototype remains unmodified.
	 */
	
	function Buffer (arg, encodingOrOffset, length) {
	  if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
	    return new Buffer(arg, encodingOrOffset, length)
	  }
	
	  // Common case.
	  if (typeof arg === 'number') {
	    if (typeof encodingOrOffset === 'string') {
	      throw new Error(
	        'If encoding is specified then the first argument must be a string'
	      )
	    }
	    return allocUnsafe(this, arg)
	  }
	  return from(this, arg, encodingOrOffset, length)
	}
	
	Buffer.poolSize = 8192 // not used by this implementation
	
	// TODO: Legacy, not needed anymore. Remove in next major version.
	Buffer._augment = function (arr) {
	  arr.__proto__ = Buffer.prototype
	  return arr
	}
	
	function from (that, value, encodingOrOffset, length) {
	  if (typeof value === 'number') {
	    throw new TypeError('"value" argument must not be a number')
	  }
	
	  if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
	    return fromArrayBuffer(that, value, encodingOrOffset, length)
	  }
	
	  if (typeof value === 'string') {
	    return fromString(that, value, encodingOrOffset)
	  }
	
	  return fromObject(that, value)
	}
	
	/**
	 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
	 * if value is a number.
	 * Buffer.from(str[, encoding])
	 * Buffer.from(array)
	 * Buffer.from(buffer)
	 * Buffer.from(arrayBuffer[, byteOffset[, length]])
	 **/
	Buffer.from = function (value, encodingOrOffset, length) {
	  return from(null, value, encodingOrOffset, length)
	}
	
	if (Buffer.TYPED_ARRAY_SUPPORT) {
	  Buffer.prototype.__proto__ = Uint8Array.prototype
	  Buffer.__proto__ = Uint8Array
	  if (typeof Symbol !== 'undefined' && Symbol.species &&
	      Buffer[Symbol.species] === Buffer) {
	    // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
	    Object.defineProperty(Buffer, Symbol.species, {
	      value: null,
	      configurable: true
	    })
	  }
	}
	
	function assertSize (size) {
	  if (typeof size !== 'number') {
	    throw new TypeError('"size" argument must be a number')
	  } else if (size < 0) {
	    throw new RangeError('"size" argument must not be negative')
	  }
	}
	
	function alloc (that, size, fill, encoding) {
	  assertSize(size)
	  if (size <= 0) {
	    return createBuffer(that, size)
	  }
	  if (fill !== undefined) {
	    // Only pay attention to encoding if it's a string. This
	    // prevents accidentally sending in a number that would
	    // be interpretted as a start offset.
	    return typeof encoding === 'string'
	      ? createBuffer(that, size).fill(fill, encoding)
	      : createBuffer(that, size).fill(fill)
	  }
	  return createBuffer(that, size)
	}
	
	/**
	 * Creates a new filled Buffer instance.
	 * alloc(size[, fill[, encoding]])
	 **/
	Buffer.alloc = function (size, fill, encoding) {
	  return alloc(null, size, fill, encoding)
	}
	
	function allocUnsafe (that, size) {
	  assertSize(size)
	  that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
	  if (!Buffer.TYPED_ARRAY_SUPPORT) {
	    for (var i = 0; i < size; ++i) {
	      that[i] = 0
	    }
	  }
	  return that
	}
	
	/**
	 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
	 * */
	Buffer.allocUnsafe = function (size) {
	  return allocUnsafe(null, size)
	}
	/**
	 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
	 */
	Buffer.allocUnsafeSlow = function (size) {
	  return allocUnsafe(null, size)
	}
	
	function fromString (that, string, encoding) {
	  if (typeof encoding !== 'string' || encoding === '') {
	    encoding = 'utf8'
	  }
	
	  if (!Buffer.isEncoding(encoding)) {
	    throw new TypeError('"encoding" must be a valid string encoding')
	  }
	
	  var length = byteLength(string, encoding) | 0
	  that = createBuffer(that, length)
	
	  var actual = that.write(string, encoding)
	
	  if (actual !== length) {
	    // Writing a hex string, for example, that contains invalid characters will
	    // cause everything after the first invalid character to be ignored. (e.g.
	    // 'abxxcd' will be treated as 'ab')
	    that = that.slice(0, actual)
	  }
	
	  return that
	}
	
	function fromArrayLike (that, array) {
	  var length = array.length < 0 ? 0 : checked(array.length) | 0
	  that = createBuffer(that, length)
	  for (var i = 0; i < length; i += 1) {
	    that[i] = array[i] & 255
	  }
	  return that
	}
	
	function fromArrayBuffer (that, array, byteOffset, length) {
	  array.byteLength // this throws if `array` is not a valid ArrayBuffer
	
	  if (byteOffset < 0 || array.byteLength < byteOffset) {
	    throw new RangeError('\'offset\' is out of bounds')
	  }
	
	  if (array.byteLength < byteOffset + (length || 0)) {
	    throw new RangeError('\'length\' is out of bounds')
	  }
	
	  if (byteOffset === undefined && length === undefined) {
	    array = new Uint8Array(array)
	  } else if (length === undefined) {
	    array = new Uint8Array(array, byteOffset)
	  } else {
	    array = new Uint8Array(array, byteOffset, length)
	  }
	
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    // Return an augmented `Uint8Array` instance, for best performance
	    that = array
	    that.__proto__ = Buffer.prototype
	  } else {
	    // Fallback: Return an object instance of the Buffer class
	    that = fromArrayLike(that, array)
	  }
	  return that
	}
	
	function fromObject (that, obj) {
	  if (Buffer.isBuffer(obj)) {
	    var len = checked(obj.length) | 0
	    that = createBuffer(that, len)
	
	    if (that.length === 0) {
	      return that
	    }
	
	    obj.copy(that, 0, 0, len)
	    return that
	  }
	
	  if (obj) {
	    if ((typeof ArrayBuffer !== 'undefined' &&
	        obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
	      if (typeof obj.length !== 'number' || isnan(obj.length)) {
	        return createBuffer(that, 0)
	      }
	      return fromArrayLike(that, obj)
	    }
	
	    if (obj.type === 'Buffer' && isArray(obj.data)) {
	      return fromArrayLike(that, obj.data)
	    }
	  }
	
	  throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
	}
	
	function checked (length) {
	  // Note: cannot use `length < kMaxLength()` here because that fails when
	  // length is NaN (which is otherwise coerced to zero.)
	  if (length >= kMaxLength()) {
	    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
	                         'size: 0x' + kMaxLength().toString(16) + ' bytes')
	  }
	  return length | 0
	}
	
	function SlowBuffer (length) {
	  if (+length != length) { // eslint-disable-line eqeqeq
	    length = 0
	  }
	  return Buffer.alloc(+length)
	}
	
	Buffer.isBuffer = function isBuffer (b) {
	  return !!(b != null && b._isBuffer)
	}
	
	Buffer.compare = function compare (a, b) {
	  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
	    throw new TypeError('Arguments must be Buffers')
	  }
	
	  if (a === b) return 0
	
	  var x = a.length
	  var y = b.length
	
	  for (var i = 0, len = Math.min(x, y); i < len; ++i) {
	    if (a[i] !== b[i]) {
	      x = a[i]
	      y = b[i]
	      break
	    }
	  }
	
	  if (x < y) return -1
	  if (y < x) return 1
	  return 0
	}
	
	Buffer.isEncoding = function isEncoding (encoding) {
	  switch (String(encoding).toLowerCase()) {
	    case 'hex':
	    case 'utf8':
	    case 'utf-8':
	    case 'ascii':
	    case 'latin1':
	    case 'binary':
	    case 'base64':
	    case 'ucs2':
	    case 'ucs-2':
	    case 'utf16le':
	    case 'utf-16le':
	      return true
	    default:
	      return false
	  }
	}
	
	Buffer.concat = function concat (list, length) {
	  if (!isArray(list)) {
	    throw new TypeError('"list" argument must be an Array of Buffers')
	  }
	
	  if (list.length === 0) {
	    return Buffer.alloc(0)
	  }
	
	  var i
	  if (length === undefined) {
	    length = 0
	    for (i = 0; i < list.length; ++i) {
	      length += list[i].length
	    }
	  }
	
	  var buffer = Buffer.allocUnsafe(length)
	  var pos = 0
	  for (i = 0; i < list.length; ++i) {
	    var buf = list[i]
	    if (!Buffer.isBuffer(buf)) {
	      throw new TypeError('"list" argument must be an Array of Buffers')
	    }
	    buf.copy(buffer, pos)
	    pos += buf.length
	  }
	  return buffer
	}
	
	function byteLength (string, encoding) {
	  if (Buffer.isBuffer(string)) {
	    return string.length
	  }
	  if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
	      (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
	    return string.byteLength
	  }
	  if (typeof string !== 'string') {
	    string = '' + string
	  }
	
	  var len = string.length
	  if (len === 0) return 0
	
	  // Use a for loop to avoid recursion
	  var loweredCase = false
	  for (;;) {
	    switch (encoding) {
	      case 'ascii':
	      case 'latin1':
	      case 'binary':
	        return len
	      case 'utf8':
	      case 'utf-8':
	      case undefined:
	        return utf8ToBytes(string).length
	      case 'ucs2':
	      case 'ucs-2':
	      case 'utf16le':
	      case 'utf-16le':
	        return len * 2
	      case 'hex':
	        return len >>> 1
	      case 'base64':
	        return base64ToBytes(string).length
	      default:
	        if (loweredCase) return utf8ToBytes(string).length // assume utf8
	        encoding = ('' + encoding).toLowerCase()
	        loweredCase = true
	    }
	  }
	}
	Buffer.byteLength = byteLength
	
	function slowToString (encoding, start, end) {
	  var loweredCase = false
	
	  // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
	  // property of a typed array.
	
	  // This behaves neither like String nor Uint8Array in that we set start/end
	  // to their upper/lower bounds if the value passed is out of range.
	  // undefined is handled specially as per ECMA-262 6th Edition,
	  // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
	  if (start === undefined || start < 0) {
	    start = 0
	  }
	  // Return early if start > this.length. Done here to prevent potential uint32
	  // coercion fail below.
	  if (start > this.length) {
	    return ''
	  }
	
	  if (end === undefined || end > this.length) {
	    end = this.length
	  }
	
	  if (end <= 0) {
	    return ''
	  }
	
	  // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
	  end >>>= 0
	  start >>>= 0
	
	  if (end <= start) {
	    return ''
	  }
	
	  if (!encoding) encoding = 'utf8'
	
	  while (true) {
	    switch (encoding) {
	      case 'hex':
	        return hexSlice(this, start, end)
	
	      case 'utf8':
	      case 'utf-8':
	        return utf8Slice(this, start, end)
	
	      case 'ascii':
	        return asciiSlice(this, start, end)
	
	      case 'latin1':
	      case 'binary':
	        return latin1Slice(this, start, end)
	
	      case 'base64':
	        return base64Slice(this, start, end)
	
	      case 'ucs2':
	      case 'ucs-2':
	      case 'utf16le':
	      case 'utf-16le':
	        return utf16leSlice(this, start, end)
	
	      default:
	        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
	        encoding = (encoding + '').toLowerCase()
	        loweredCase = true
	    }
	  }
	}
	
	// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
	// Buffer instances.
	Buffer.prototype._isBuffer = true
	
	function swap (b, n, m) {
	  var i = b[n]
	  b[n] = b[m]
	  b[m] = i
	}
	
	Buffer.prototype.swap16 = function swap16 () {
	  var len = this.length
	  if (len % 2 !== 0) {
	    throw new RangeError('Buffer size must be a multiple of 16-bits')
	  }
	  for (var i = 0; i < len; i += 2) {
	    swap(this, i, i + 1)
	  }
	  return this
	}
	
	Buffer.prototype.swap32 = function swap32 () {
	  var len = this.length
	  if (len % 4 !== 0) {
	    throw new RangeError('Buffer size must be a multiple of 32-bits')
	  }
	  for (var i = 0; i < len; i += 4) {
	    swap(this, i, i + 3)
	    swap(this, i + 1, i + 2)
	  }
	  return this
	}
	
	Buffer.prototype.swap64 = function swap64 () {
	  var len = this.length
	  if (len % 8 !== 0) {
	    throw new RangeError('Buffer size must be a multiple of 64-bits')
	  }
	  for (var i = 0; i < len; i += 8) {
	    swap(this, i, i + 7)
	    swap(this, i + 1, i + 6)
	    swap(this, i + 2, i + 5)
	    swap(this, i + 3, i + 4)
	  }
	  return this
	}
	
	Buffer.prototype.toString = function toString () {
	  var length = this.length | 0
	  if (length === 0) return ''
	  if (arguments.length === 0) return utf8Slice(this, 0, length)
	  return slowToString.apply(this, arguments)
	}
	
	Buffer.prototype.equals = function equals (b) {
	  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
	  if (this === b) return true
	  return Buffer.compare(this, b) === 0
	}
	
	Buffer.prototype.inspect = function inspect () {
	  var str = ''
	  var max = exports.INSPECT_MAX_BYTES
	  if (this.length > 0) {
	    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
	    if (this.length > max) str += ' ... '
	  }
	  return '<Buffer ' + str + '>'
	}
	
	Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
	  if (!Buffer.isBuffer(target)) {
	    throw new TypeError('Argument must be a Buffer')
	  }
	
	  if (start === undefined) {
	    start = 0
	  }
	  if (end === undefined) {
	    end = target ? target.length : 0
	  }
	  if (thisStart === undefined) {
	    thisStart = 0
	  }
	  if (thisEnd === undefined) {
	    thisEnd = this.length
	  }
	
	  if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
	    throw new RangeError('out of range index')
	  }
	
	  if (thisStart >= thisEnd && start >= end) {
	    return 0
	  }
	  if (thisStart >= thisEnd) {
	    return -1
	  }
	  if (start >= end) {
	    return 1
	  }
	
	  start >>>= 0
	  end >>>= 0
	  thisStart >>>= 0
	  thisEnd >>>= 0
	
	  if (this === target) return 0
	
	  var x = thisEnd - thisStart
	  var y = end - start
	  var len = Math.min(x, y)
	
	  var thisCopy = this.slice(thisStart, thisEnd)
	  var targetCopy = target.slice(start, end)
	
	  for (var i = 0; i < len; ++i) {
	    if (thisCopy[i] !== targetCopy[i]) {
	      x = thisCopy[i]
	      y = targetCopy[i]
	      break
	    }
	  }
	
	  if (x < y) return -1
	  if (y < x) return 1
	  return 0
	}
	
	// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
	// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
	//
	// Arguments:
	// - buffer - a Buffer to search
	// - val - a string, Buffer, or number
	// - byteOffset - an index into `buffer`; will be clamped to an int32
	// - encoding - an optional encoding, relevant is val is a string
	// - dir - true for indexOf, false for lastIndexOf
	function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
	  // Empty buffer means no match
	  if (buffer.length === 0) return -1
	
	  // Normalize byteOffset
	  if (typeof byteOffset === 'string') {
	    encoding = byteOffset
	    byteOffset = 0
	  } else if (byteOffset > 0x7fffffff) {
	    byteOffset = 0x7fffffff
	  } else if (byteOffset < -0x80000000) {
	    byteOffset = -0x80000000
	  }
	  byteOffset = +byteOffset  // Coerce to Number.
	  if (isNaN(byteOffset)) {
	    // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
	    byteOffset = dir ? 0 : (buffer.length - 1)
	  }
	
	  // Normalize byteOffset: negative offsets start from the end of the buffer
	  if (byteOffset < 0) byteOffset = buffer.length + byteOffset
	  if (byteOffset >= buffer.length) {
	    if (dir) return -1
	    else byteOffset = buffer.length - 1
	  } else if (byteOffset < 0) {
	    if (dir) byteOffset = 0
	    else return -1
	  }
	
	  // Normalize val
	  if (typeof val === 'string') {
	    val = Buffer.from(val, encoding)
	  }
	
	  // Finally, search either indexOf (if dir is true) or lastIndexOf
	  if (Buffer.isBuffer(val)) {
	    // Special case: looking for empty string/buffer always fails
	    if (val.length === 0) {
	      return -1
	    }
	    return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
	  } else if (typeof val === 'number') {
	    val = val & 0xFF // Search for a byte value [0-255]
	    if (Buffer.TYPED_ARRAY_SUPPORT &&
	        typeof Uint8Array.prototype.indexOf === 'function') {
	      if (dir) {
	        return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
	      } else {
	        return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
	      }
	    }
	    return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
	  }
	
	  throw new TypeError('val must be string, number or Buffer')
	}
	
	function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
	  var indexSize = 1
	  var arrLength = arr.length
	  var valLength = val.length
	
	  if (encoding !== undefined) {
	    encoding = String(encoding).toLowerCase()
	    if (encoding === 'ucs2' || encoding === 'ucs-2' ||
	        encoding === 'utf16le' || encoding === 'utf-16le') {
	      if (arr.length < 2 || val.length < 2) {
	        return -1
	      }
	      indexSize = 2
	      arrLength /= 2
	      valLength /= 2
	      byteOffset /= 2
	    }
	  }
	
	  function read (buf, i) {
	    if (indexSize === 1) {
	      return buf[i]
	    } else {
	      return buf.readUInt16BE(i * indexSize)
	    }
	  }
	
	  var i
	  if (dir) {
	    var foundIndex = -1
	    for (i = byteOffset; i < arrLength; i++) {
	      if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
	        if (foundIndex === -1) foundIndex = i
	        if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
	      } else {
	        if (foundIndex !== -1) i -= i - foundIndex
	        foundIndex = -1
	      }
	    }
	  } else {
	    if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
	    for (i = byteOffset; i >= 0; i--) {
	      var found = true
	      for (var j = 0; j < valLength; j++) {
	        if (read(arr, i + j) !== read(val, j)) {
	          found = false
	          break
	        }
	      }
	      if (found) return i
	    }
	  }
	
	  return -1
	}
	
	Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
	  return this.indexOf(val, byteOffset, encoding) !== -1
	}
	
	Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
	  return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
	}
	
	Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
	  return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
	}
	
	function hexWrite (buf, string, offset, length) {
	  offset = Number(offset) || 0
	  var remaining = buf.length - offset
	  if (!length) {
	    length = remaining
	  } else {
	    length = Number(length)
	    if (length > remaining) {
	      length = remaining
	    }
	  }
	
	  // must be an even number of digits
	  var strLen = string.length
	  if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')
	
	  if (length > strLen / 2) {
	    length = strLen / 2
	  }
	  for (var i = 0; i < length; ++i) {
	    var parsed = parseInt(string.substr(i * 2, 2), 16)
	    if (isNaN(parsed)) return i
	    buf[offset + i] = parsed
	  }
	  return i
	}
	
	function utf8Write (buf, string, offset, length) {
	  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
	}
	
	function asciiWrite (buf, string, offset, length) {
	  return blitBuffer(asciiToBytes(string), buf, offset, length)
	}
	
	function latin1Write (buf, string, offset, length) {
	  return asciiWrite(buf, string, offset, length)
	}
	
	function base64Write (buf, string, offset, length) {
	  return blitBuffer(base64ToBytes(string), buf, offset, length)
	}
	
	function ucs2Write (buf, string, offset, length) {
	  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
	}
	
	Buffer.prototype.write = function write (string, offset, length, encoding) {
	  // Buffer#write(string)
	  if (offset === undefined) {
	    encoding = 'utf8'
	    length = this.length
	    offset = 0
	  // Buffer#write(string, encoding)
	  } else if (length === undefined && typeof offset === 'string') {
	    encoding = offset
	    length = this.length
	    offset = 0
	  // Buffer#write(string, offset[, length][, encoding])
	  } else if (isFinite(offset)) {
	    offset = offset | 0
	    if (isFinite(length)) {
	      length = length | 0
	      if (encoding === undefined) encoding = 'utf8'
	    } else {
	      encoding = length
	      length = undefined
	    }
	  // legacy write(string, encoding, offset, length) - remove in v0.13
	  } else {
	    throw new Error(
	      'Buffer.write(string, encoding, offset[, length]) is no longer supported'
	    )
	  }
	
	  var remaining = this.length - offset
	  if (length === undefined || length > remaining) length = remaining
	
	  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
	    throw new RangeError('Attempt to write outside buffer bounds')
	  }
	
	  if (!encoding) encoding = 'utf8'
	
	  var loweredCase = false
	  for (;;) {
	    switch (encoding) {
	      case 'hex':
	        return hexWrite(this, string, offset, length)
	
	      case 'utf8':
	      case 'utf-8':
	        return utf8Write(this, string, offset, length)
	
	      case 'ascii':
	        return asciiWrite(this, string, offset, length)
	
	      case 'latin1':
	      case 'binary':
	        return latin1Write(this, string, offset, length)
	
	      case 'base64':
	        // Warning: maxLength not taken into account in base64Write
	        return base64Write(this, string, offset, length)
	
	      case 'ucs2':
	      case 'ucs-2':
	      case 'utf16le':
	      case 'utf-16le':
	        return ucs2Write(this, string, offset, length)
	
	      default:
	        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
	        encoding = ('' + encoding).toLowerCase()
	        loweredCase = true
	    }
	  }
	}
	
	Buffer.prototype.toJSON = function toJSON () {
	  return {
	    type: 'Buffer',
	    data: Array.prototype.slice.call(this._arr || this, 0)
	  }
	}
	
	function base64Slice (buf, start, end) {
	  if (start === 0 && end === buf.length) {
	    return base64.fromByteArray(buf)
	  } else {
	    return base64.fromByteArray(buf.slice(start, end))
	  }
	}
	
	function utf8Slice (buf, start, end) {
	  end = Math.min(buf.length, end)
	  var res = []
	
	  var i = start
	  while (i < end) {
	    var firstByte = buf[i]
	    var codePoint = null
	    var bytesPerSequence = (firstByte > 0xEF) ? 4
	      : (firstByte > 0xDF) ? 3
	      : (firstByte > 0xBF) ? 2
	      : 1
	
	    if (i + bytesPerSequence <= end) {
	      var secondByte, thirdByte, fourthByte, tempCodePoint
	
	      switch (bytesPerSequence) {
	        case 1:
	          if (firstByte < 0x80) {
	            codePoint = firstByte
	          }
	          break
	        case 2:
	          secondByte = buf[i + 1]
	          if ((secondByte & 0xC0) === 0x80) {
	            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
	            if (tempCodePoint > 0x7F) {
	              codePoint = tempCodePoint
	            }
	          }
	          break
	        case 3:
	          secondByte = buf[i + 1]
	          thirdByte = buf[i + 2]
	          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
	            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
	            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
	              codePoint = tempCodePoint
	            }
	          }
	          break
	        case 4:
	          secondByte = buf[i + 1]
	          thirdByte = buf[i + 2]
	          fourthByte = buf[i + 3]
	          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
	            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
	            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
	              codePoint = tempCodePoint
	            }
	          }
	      }
	    }
	
	    if (codePoint === null) {
	      // we did not generate a valid codePoint so insert a
	      // replacement char (U+FFFD) and advance only 1 byte
	      codePoint = 0xFFFD
	      bytesPerSequence = 1
	    } else if (codePoint > 0xFFFF) {
	      // encode to utf16 (surrogate pair dance)
	      codePoint -= 0x10000
	      res.push(codePoint >>> 10 & 0x3FF | 0xD800)
	      codePoint = 0xDC00 | codePoint & 0x3FF
	    }
	
	    res.push(codePoint)
	    i += bytesPerSequence
	  }
	
	  return decodeCodePointsArray(res)
	}
	
	// Based on http://stackoverflow.com/a/22747272/680742, the browser with
	// the lowest limit is Chrome, with 0x10000 args.
	// We go 1 magnitude less, for safety
	var MAX_ARGUMENTS_LENGTH = 0x1000
	
	function decodeCodePointsArray (codePoints) {
	  var len = codePoints.length
	  if (len <= MAX_ARGUMENTS_LENGTH) {
	    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
	  }
	
	  // Decode in chunks to avoid "call stack size exceeded".
	  var res = ''
	  var i = 0
	  while (i < len) {
	    res += String.fromCharCode.apply(
	      String,
	      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
	    )
	  }
	  return res
	}
	
	function asciiSlice (buf, start, end) {
	  var ret = ''
	  end = Math.min(buf.length, end)
	
	  for (var i = start; i < end; ++i) {
	    ret += String.fromCharCode(buf[i] & 0x7F)
	  }
	  return ret
	}
	
	function latin1Slice (buf, start, end) {
	  var ret = ''
	  end = Math.min(buf.length, end)
	
	  for (var i = start; i < end; ++i) {
	    ret += String.fromCharCode(buf[i])
	  }
	  return ret
	}
	
	function hexSlice (buf, start, end) {
	  var len = buf.length
	
	  if (!start || start < 0) start = 0
	  if (!end || end < 0 || end > len) end = len
	
	  var out = ''
	  for (var i = start; i < end; ++i) {
	    out += toHex(buf[i])
	  }
	  return out
	}
	
	function utf16leSlice (buf, start, end) {
	  var bytes = buf.slice(start, end)
	  var res = ''
	  for (var i = 0; i < bytes.length; i += 2) {
	    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
	  }
	  return res
	}
	
	Buffer.prototype.slice = function slice (start, end) {
	  var len = this.length
	  start = ~~start
	  end = end === undefined ? len : ~~end
	
	  if (start < 0) {
	    start += len
	    if (start < 0) start = 0
	  } else if (start > len) {
	    start = len
	  }
	
	  if (end < 0) {
	    end += len
	    if (end < 0) end = 0
	  } else if (end > len) {
	    end = len
	  }
	
	  if (end < start) end = start
	
	  var newBuf
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    newBuf = this.subarray(start, end)
	    newBuf.__proto__ = Buffer.prototype
	  } else {
	    var sliceLen = end - start
	    newBuf = new Buffer(sliceLen, undefined)
	    for (var i = 0; i < sliceLen; ++i) {
	      newBuf[i] = this[i + start]
	    }
	  }
	
	  return newBuf
	}
	
	/*
	 * Need to make sure that buffer isn't trying to write out of bounds.
	 */
	function checkOffset (offset, ext, length) {
	  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
	  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
	}
	
	Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
	  offset = offset | 0
	  byteLength = byteLength | 0
	  if (!noAssert) checkOffset(offset, byteLength, this.length)
	
	  var val = this[offset]
	  var mul = 1
	  var i = 0
	  while (++i < byteLength && (mul *= 0x100)) {
	    val += this[offset + i] * mul
	  }
	
	  return val
	}
	
	Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
	  offset = offset | 0
	  byteLength = byteLength | 0
	  if (!noAssert) {
	    checkOffset(offset, byteLength, this.length)
	  }
	
	  var val = this[offset + --byteLength]
	  var mul = 1
	  while (byteLength > 0 && (mul *= 0x100)) {
	    val += this[offset + --byteLength] * mul
	  }
	
	  return val
	}
	
	Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 1, this.length)
	  return this[offset]
	}
	
	Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 2, this.length)
	  return this[offset] | (this[offset + 1] << 8)
	}
	
	Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 2, this.length)
	  return (this[offset] << 8) | this[offset + 1]
	}
	
	Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 4, this.length)
	
	  return ((this[offset]) |
	      (this[offset + 1] << 8) |
	      (this[offset + 2] << 16)) +
	      (this[offset + 3] * 0x1000000)
	}
	
	Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 4, this.length)
	
	  return (this[offset] * 0x1000000) +
	    ((this[offset + 1] << 16) |
	    (this[offset + 2] << 8) |
	    this[offset + 3])
	}
	
	Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
	  offset = offset | 0
	  byteLength = byteLength | 0
	  if (!noAssert) checkOffset(offset, byteLength, this.length)
	
	  var val = this[offset]
	  var mul = 1
	  var i = 0
	  while (++i < byteLength && (mul *= 0x100)) {
	    val += this[offset + i] * mul
	  }
	  mul *= 0x80
	
	  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
	
	  return val
	}
	
	Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
	  offset = offset | 0
	  byteLength = byteLength | 0
	  if (!noAssert) checkOffset(offset, byteLength, this.length)
	
	  var i = byteLength
	  var mul = 1
	  var val = this[offset + --i]
	  while (i > 0 && (mul *= 0x100)) {
	    val += this[offset + --i] * mul
	  }
	  mul *= 0x80
	
	  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
	
	  return val
	}
	
	Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 1, this.length)
	  if (!(this[offset] & 0x80)) return (this[offset])
	  return ((0xff - this[offset] + 1) * -1)
	}
	
	Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 2, this.length)
	  var val = this[offset] | (this[offset + 1] << 8)
	  return (val & 0x8000) ? val | 0xFFFF0000 : val
	}
	
	Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 2, this.length)
	  var val = this[offset + 1] | (this[offset] << 8)
	  return (val & 0x8000) ? val | 0xFFFF0000 : val
	}
	
	Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 4, this.length)
	
	  return (this[offset]) |
	    (this[offset + 1] << 8) |
	    (this[offset + 2] << 16) |
	    (this[offset + 3] << 24)
	}
	
	Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 4, this.length)
	
	  return (this[offset] << 24) |
	    (this[offset + 1] << 16) |
	    (this[offset + 2] << 8) |
	    (this[offset + 3])
	}
	
	Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 4, this.length)
	  return ieee754.read(this, offset, true, 23, 4)
	}
	
	Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 4, this.length)
	  return ieee754.read(this, offset, false, 23, 4)
	}
	
	Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 8, this.length)
	  return ieee754.read(this, offset, true, 52, 8)
	}
	
	Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
	  if (!noAssert) checkOffset(offset, 8, this.length)
	  return ieee754.read(this, offset, false, 52, 8)
	}
	
	function checkInt (buf, value, offset, ext, max, min) {
	  if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
	  if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
	  if (offset + ext > buf.length) throw new RangeError('Index out of range')
	}
	
	Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
	  value = +value
	  offset = offset | 0
	  byteLength = byteLength | 0
	  if (!noAssert) {
	    var maxBytes = Math.pow(2, 8 * byteLength) - 1
	    checkInt(this, value, offset, byteLength, maxBytes, 0)
	  }
	
	  var mul = 1
	  var i = 0
	  this[offset] = value & 0xFF
	  while (++i < byteLength && (mul *= 0x100)) {
	    this[offset + i] = (value / mul) & 0xFF
	  }
	
	  return offset + byteLength
	}
	
	Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
	  value = +value
	  offset = offset | 0
	  byteLength = byteLength | 0
	  if (!noAssert) {
	    var maxBytes = Math.pow(2, 8 * byteLength) - 1
	    checkInt(this, value, offset, byteLength, maxBytes, 0)
	  }
	
	  var i = byteLength - 1
	  var mul = 1
	  this[offset + i] = value & 0xFF
	  while (--i >= 0 && (mul *= 0x100)) {
	    this[offset + i] = (value / mul) & 0xFF
	  }
	
	  return offset + byteLength
	}
	
	Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
	  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
	  this[offset] = (value & 0xff)
	  return offset + 1
	}
	
	function objectWriteUInt16 (buf, value, offset, littleEndian) {
	  if (value < 0) value = 0xffff + value + 1
	  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {
	    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
	      (littleEndian ? i : 1 - i) * 8
	  }
	}
	
	Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    this[offset] = (value & 0xff)
	    this[offset + 1] = (value >>> 8)
	  } else {
	    objectWriteUInt16(this, value, offset, true)
	  }
	  return offset + 2
	}
	
	Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    this[offset] = (value >>> 8)
	    this[offset + 1] = (value & 0xff)
	  } else {
	    objectWriteUInt16(this, value, offset, false)
	  }
	  return offset + 2
	}
	
	function objectWriteUInt32 (buf, value, offset, littleEndian) {
	  if (value < 0) value = 0xffffffff + value + 1
	  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {
	    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
	  }
	}
	
	Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    this[offset + 3] = (value >>> 24)
	    this[offset + 2] = (value >>> 16)
	    this[offset + 1] = (value >>> 8)
	    this[offset] = (value & 0xff)
	  } else {
	    objectWriteUInt32(this, value, offset, true)
	  }
	  return offset + 4
	}
	
	Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    this[offset] = (value >>> 24)
	    this[offset + 1] = (value >>> 16)
	    this[offset + 2] = (value >>> 8)
	    this[offset + 3] = (value & 0xff)
	  } else {
	    objectWriteUInt32(this, value, offset, false)
	  }
	  return offset + 4
	}
	
	Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) {
	    var limit = Math.pow(2, 8 * byteLength - 1)
	
	    checkInt(this, value, offset, byteLength, limit - 1, -limit)
	  }
	
	  var i = 0
	  var mul = 1
	  var sub = 0
	  this[offset] = value & 0xFF
	  while (++i < byteLength && (mul *= 0x100)) {
	    if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
	      sub = 1
	    }
	    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
	  }
	
	  return offset + byteLength
	}
	
	Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) {
	    var limit = Math.pow(2, 8 * byteLength - 1)
	
	    checkInt(this, value, offset, byteLength, limit - 1, -limit)
	  }
	
	  var i = byteLength - 1
	  var mul = 1
	  var sub = 0
	  this[offset + i] = value & 0xFF
	  while (--i >= 0 && (mul *= 0x100)) {
	    if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
	      sub = 1
	    }
	    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
	  }
	
	  return offset + byteLength
	}
	
	Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
	  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
	  if (value < 0) value = 0xff + value + 1
	  this[offset] = (value & 0xff)
	  return offset + 1
	}
	
	Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    this[offset] = (value & 0xff)
	    this[offset + 1] = (value >>> 8)
	  } else {
	    objectWriteUInt16(this, value, offset, true)
	  }
	  return offset + 2
	}
	
	Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    this[offset] = (value >>> 8)
	    this[offset + 1] = (value & 0xff)
	  } else {
	    objectWriteUInt16(this, value, offset, false)
	  }
	  return offset + 2
	}
	
	Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    this[offset] = (value & 0xff)
	    this[offset + 1] = (value >>> 8)
	    this[offset + 2] = (value >>> 16)
	    this[offset + 3] = (value >>> 24)
	  } else {
	    objectWriteUInt32(this, value, offset, true)
	  }
	  return offset + 4
	}
	
	Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
	  value = +value
	  offset = offset | 0
	  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
	  if (value < 0) value = 0xffffffff + value + 1
	  if (Buffer.TYPED_ARRAY_SUPPORT) {
	    this[offset] = (value >>> 24)
	    this[offset + 1] = (value >>> 16)
	    this[offset + 2] = (value >>> 8)
	    this[offset + 3] = (value & 0xff)
	  } else {
	    objectWriteUInt32(this, value, offset, false)
	  }
	  return offset + 4
	}
	
	function checkIEEE754 (buf, value, offset, ext, max, min) {
	  if (offset + ext > buf.length) throw new RangeError('Index out of range')
	  if (offset < 0) throw new RangeError('Index out of range')
	}
	
	function writeFloat (buf, value, offset, littleEndian, noAssert) {
	  if (!noAssert) {
	    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
	  }
	  ieee754.write(buf, value, offset, littleEndian, 23, 4)
	  return offset + 4
	}
	
	Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
	  return writeFloat(this, value, offset, true, noAssert)
	}
	
	Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
	  return writeFloat(this, value, offset, false, noAssert)
	}
	
	function writeDouble (buf, value, offset, littleEndian, noAssert) {
	  if (!noAssert) {
	    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
	  }
	  ieee754.write(buf, value, offset, littleEndian, 52, 8)
	  return offset + 8
	}
	
	Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
	  return writeDouble(this, value, offset, true, noAssert)
	}
	
	Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
	  return writeDouble(this, value, offset, false, noAssert)
	}
	
	// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
	Buffer.prototype.copy = function copy (target, targetStart, start, end) {
	  if (!start) start = 0
	  if (!end && end !== 0) end = this.length
	  if (targetStart >= target.length) targetStart = target.length
	  if (!targetStart) targetStart = 0
	  if (end > 0 && end < start) end = start
	
	  // Copy 0 bytes; we're done
	  if (end === start) return 0
	  if (target.length === 0 || this.length === 0) return 0
	
	  // Fatal error conditions
	  if (targetStart < 0) {
	    throw new RangeError('targetStart out of bounds')
	  }
	  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
	  if (end < 0) throw new RangeError('sourceEnd out of bounds')
	
	  // Are we oob?
	  if (end > this.length) end = this.length
	  if (target.length - targetStart < end - start) {
	    end = target.length - targetStart + start
	  }
	
	  var len = end - start
	  var i
	
	  if (this === target && start < targetStart && targetStart < end) {
	    // descending copy from end
	    for (i = len - 1; i >= 0; --i) {
	      target[i + targetStart] = this[i + start]
	    }
	  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
	    // ascending copy from start
	    for (i = 0; i < len; ++i) {
	      target[i + targetStart] = this[i + start]
	    }
	  } else {
	    Uint8Array.prototype.set.call(
	      target,
	      this.subarray(start, start + len),
	      targetStart
	    )
	  }
	
	  return len
	}
	
	// Usage:
	//    buffer.fill(number[, offset[, end]])
	//    buffer.fill(buffer[, offset[, end]])
	//    buffer.fill(string[, offset[, end]][, encoding])
	Buffer.prototype.fill = function fill (val, start, end, encoding) {
	  // Handle string cases:
	  if (typeof val === 'string') {
	    if (typeof start === 'string') {
	      encoding = start
	      start = 0
	      end = this.length
	    } else if (typeof end === 'string') {
	      encoding = end
	      end = this.length
	    }
	    if (val.length === 1) {
	      var code = val.charCodeAt(0)
	      if (code < 256) {
	        val = code
	      }
	    }
	    if (encoding !== undefined && typeof encoding !== 'string') {
	      throw new TypeError('encoding must be a string')
	    }
	    if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
	      throw new TypeError('Unknown encoding: ' + encoding)
	    }
	  } else if (typeof val === 'number') {
	    val = val & 255
	  }
	
	  // Invalid ranges are not set to a default, so can range check early.
	  if (start < 0 || this.length < start || this.length < end) {
	    throw new RangeError('Out of range index')
	  }
	
	  if (end <= start) {
	    return this
	  }
	
	  start = start >>> 0
	  end = end === undefined ? this.length : end >>> 0
	
	  if (!val) val = 0
	
	  var i
	  if (typeof val === 'number') {
	    for (i = start; i < end; ++i) {
	      this[i] = val
	    }
	  } else {
	    var bytes = Buffer.isBuffer(val)
	      ? val
	      : utf8ToBytes(new Buffer(val, encoding).toString())
	    var len = bytes.length
	    for (i = 0; i < end - start; ++i) {
	      this[i + start] = bytes[i % len]
	    }
	  }
	
	  return this
	}
	
	// HELPER FUNCTIONS
	// ================
	
	var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
	
	function base64clean (str) {
	  // Node strips out invalid characters like \n and \t from the string, base64-js does not
	  str = stringtrim(str).replace(INVALID_BASE64_RE, '')
	  // Node converts strings with length < 2 to ''
	  if (str.length < 2) return ''
	  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
	  while (str.length % 4 !== 0) {
	    str = str + '='
	  }
	  return str
	}
	
	function stringtrim (str) {
	  if (str.trim) return str.trim()
	  return str.replace(/^\s+|\s+$/g, '')
	}
	
	function toHex (n) {
	  if (n < 16) return '0' + n.toString(16)
	  return n.toString(16)
	}
	
	function utf8ToBytes (string, units) {
	  units = units || Infinity
	  var codePoint
	  var length = string.length
	  var leadSurrogate = null
	  var bytes = []
	
	  for (var i = 0; i < length; ++i) {
	    codePoint = string.charCodeAt(i)
	
	    // is surrogate component
	    if (codePoint > 0xD7FF && codePoint < 0xE000) {
	      // last char was a lead
	      if (!leadSurrogate) {
	        // no lead yet
	        if (codePoint > 0xDBFF) {
	          // unexpected trail
	          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
	          continue
	        } else if (i + 1 === length) {
	          // unpaired lead
	          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
	          continue
	        }
	
	        // valid lead
	        leadSurrogate = codePoint
	
	        continue
	      }
	
	      // 2 leads in a row
	      if (codePoint < 0xDC00) {
	        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
	        leadSurrogate = codePoint
	        continue
	      }
	
	      // valid surrogate pair
	      codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
	    } else if (leadSurrogate) {
	      // valid bmp char, but last char was a lead
	      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
	    }
	
	    leadSurrogate = null
	
	    // encode utf8
	    if (codePoint < 0x80) {
	      if ((units -= 1) < 0) break
	      bytes.push(codePoint)
	    } else if (codePoint < 0x800) {
	      if ((units -= 2) < 0) break
	      bytes.push(
	        codePoint >> 0x6 | 0xC0,
	        codePoint & 0x3F | 0x80
	      )
	    } else if (codePoint < 0x10000) {
	      if ((units -= 3) < 0) break
	      bytes.push(
	        codePoint >> 0xC | 0xE0,
	        codePoint >> 0x6 & 0x3F | 0x80,
	        codePoint & 0x3F | 0x80
	      )
	    } else if (codePoint < 0x110000) {
	      if ((units -= 4) < 0) break
	      bytes.push(
	        codePoint >> 0x12 | 0xF0,
	        codePoint >> 0xC & 0x3F | 0x80,
	        codePoint >> 0x6 & 0x3F | 0x80,
	        codePoint & 0x3F | 0x80
	      )
	    } else {
	      throw new Error('Invalid code point')
	    }
	  }
	
	  return bytes
	}
	
	function asciiToBytes (str) {
	  var byteArray = []
	  for (var i = 0; i < str.length; ++i) {
	    // Node's code seems to be doing this and not & 0x7F..
	    byteArray.push(str.charCodeAt(i) & 0xFF)
	  }
	  return byteArray
	}
	
	function utf16leToBytes (str, units) {
	  var c, hi, lo
	  var byteArray = []
	  for (var i = 0; i < str.length; ++i) {
	    if ((units -= 2) < 0) break
	
	    c = str.charCodeAt(i)
	    hi = c >> 8
	    lo = c % 256
	    byteArray.push(lo)
	    byteArray.push(hi)
	  }
	
	  return byteArray
	}
	
	function base64ToBytes (str) {
	  return base64.toByteArray(base64clean(str))
	}
	
	function blitBuffer (src, dst, offset, length) {
	  for (var i = 0; i < length; ++i) {
	    if ((i + offset >= dst.length) || (i >= src.length)) break
	    dst[i + offset] = src[i]
	  }
	  return i
	}
	
	function isnan (val) {
	  return val !== val // eslint-disable-line no-self-compare
	}
	
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
})
/** END DEFINE BLOCK for buffer@4.9.1/index.js **/


/** START DEFINE BLOCK for base64-js@1.2.0/index.js **/
jupyter.define('base64-js@1.2.0/index.js', function (module, exports, __jupyter_require__) {
	'use strict'
	
	exports.byteLength = byteLength
	exports.toByteArray = toByteArray
	exports.fromByteArray = fromByteArray
	
	var lookup = []
	var revLookup = []
	var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
	
	var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
	for (var i = 0, len = code.length; i < len; ++i) {
	  lookup[i] = code[i]
	  revLookup[code.charCodeAt(i)] = i
	}
	
	revLookup['-'.charCodeAt(0)] = 62
	revLookup['_'.charCodeAt(0)] = 63
	
	function placeHoldersCount (b64) {
	  var len = b64.length
	  if (len % 4 > 0) {
	    throw new Error('Invalid string. Length must be a multiple of 4')
	  }
	
	  // the number of equal signs (place holders)
	  // if there are two placeholders, than the two characters before it
	  // represent one byte
	  // if there is only one, then the three characters before it represent 2 bytes
	  // this is just a cheap hack to not do indexOf twice
	  return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
	}
	
	function byteLength (b64) {
	  // base64 is 4/3 + up to two characters of the original data
	  return b64.length * 3 / 4 - placeHoldersCount(b64)
	}
	
	function toByteArray (b64) {
	  var i, j, l, tmp, placeHolders, arr
	  var len = b64.length
	  placeHolders = placeHoldersCount(b64)
	
	  arr = new Arr(len * 3 / 4 - placeHolders)
	
	  // if there are placeholders, only get up to the last complete 4 chars
	  l = placeHolders > 0 ? len - 4 : len
	
	  var L = 0
	
	  for (i = 0, j = 0; i < l; i += 4, j += 3) {
	    tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
	    arr[L++] = (tmp >> 16) & 0xFF
	    arr[L++] = (tmp >> 8) & 0xFF
	    arr[L++] = tmp & 0xFF
	  }
	
	  if (placeHolders === 2) {
	    tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
	    arr[L++] = tmp & 0xFF
	  } else if (placeHolders === 1) {
	    tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
	    arr[L++] = (tmp >> 8) & 0xFF
	    arr[L++] = tmp & 0xFF
	  }
	
	  return arr
	}
	
	function tripletToBase64 (num) {
	  return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
	}
	
	function encodeChunk (uint8, start, end) {
	  var tmp
	  var output = []
	  for (var i = start; i < end; i += 3) {
	    tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
	    output.push(tripletToBase64(tmp))
	  }
	  return output.join('')
	}
	
	function fromByteArray (uint8) {
	  var tmp
	  var len = uint8.length
	  var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
	  var output = ''
	  var parts = []
	  var maxChunkLength = 16383 // must be multiple of 3
	
	  // go through the array every three bytes, we'll deal with trailing stuff later
	  for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
	    parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
	  }
	
	  // pad the end with zeros, but make sure to not forget the extra bytes
	  if (extraBytes === 1) {
	    tmp = uint8[len - 1]
	    output += lookup[tmp >> 2]
	    output += lookup[(tmp << 4) & 0x3F]
	    output += '=='
	  } else if (extraBytes === 2) {
	    tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
	    output += lookup[tmp >> 10]
	    output += lookup[(tmp >> 4) & 0x3F]
	    output += lookup[(tmp << 2) & 0x3F]
	    output += '='
	  }
	
	  parts.push(output)
	
	  return parts.join('')
	}
	
})
/** END DEFINE BLOCK for base64-js@1.2.0/index.js **/


/** START DEFINE BLOCK for ieee754@1.1.8/index.js **/
jupyter.define('ieee754@1.1.8/index.js', function (module, exports, __jupyter_require__) {
	exports.read = function (buffer, offset, isLE, mLen, nBytes) {
	  var e, m
	  var eLen = nBytes * 8 - mLen - 1
	  var eMax = (1 << eLen) - 1
	  var eBias = eMax >> 1
	  var nBits = -7
	  var i = isLE ? (nBytes - 1) : 0
	  var d = isLE ? -1 : 1
	  var s = buffer[offset + i]
	
	  i += d
	
	  e = s & ((1 << (-nBits)) - 1)
	  s >>= (-nBits)
	  nBits += eLen
	  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
	
	  m = e & ((1 << (-nBits)) - 1)
	  e >>= (-nBits)
	  nBits += mLen
	  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
	
	  if (e === 0) {
	    e = 1 - eBias
	  } else if (e === eMax) {
	    return m ? NaN : ((s ? -1 : 1) * Infinity)
	  } else {
	    m = m + Math.pow(2, mLen)
	    e = e - eBias
	  }
	  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
	}
	
	exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
	  var e, m, c
	  var eLen = nBytes * 8 - mLen - 1
	  var eMax = (1 << eLen) - 1
	  var eBias = eMax >> 1
	  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
	  var i = isLE ? 0 : (nBytes - 1)
	  var d = isLE ? 1 : -1
	  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
	
	  value = Math.abs(value)
	
	  if (isNaN(value) || value === Infinity) {
	    m = isNaN(value) ? 1 : 0
	    e = eMax
	  } else {
	    e = Math.floor(Math.log(value) / Math.LN2)
	    if (value * (c = Math.pow(2, -e)) < 1) {
	      e--
	      c *= 2
	    }
	    if (e + eBias >= 1) {
	      value += rt / c
	    } else {
	      value += rt * Math.pow(2, 1 - eBias)
	    }
	    if (value * c >= 2) {
	      e++
	      c /= 2
	    }
	
	    if (e + eBias >= eMax) {
	      m = 0
	      e = eMax
	    } else if (e + eBias >= 1) {
	      m = (value * c - 1) * Math.pow(2, mLen)
	      e = e + eBias
	    } else {
	      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
	      e = 0
	    }
	  }
	
	  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
	
	  e = (e << mLen) | m
	  eLen += mLen
	  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
	
	  buffer[offset + i - d] |= s * 128
	}
	
})
/** END DEFINE BLOCK for ieee754@1.1.8/index.js **/


/** START DEFINE BLOCK for isarray@1.0.0/index.js **/
jupyter.define('isarray@1.0.0/index.js', function (module, exports, __jupyter_require__) {
	var toString = {}.toString;
	
	module.exports = Array.isArray || function (arr) {
	  return toString.call(arr) == '[object Array]';
	};
	
})
/** END DEFINE BLOCK for isarray@1.0.0/index.js **/


/** START DEFINE BLOCK for buffer-shims@1.0.0/index.js **/
jupyter.define('buffer-shims@1.0.0/index.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(global) {'use strict';
	
	var buffer = __jupyter_require__('buffer@4.9.1/index.js');
	var Buffer = buffer.Buffer;
	var SlowBuffer = buffer.SlowBuffer;
	var MAX_LEN = buffer.kMaxLength || 2147483647;
	exports.alloc = function alloc(size, fill, encoding) {
	  if (typeof Buffer.alloc === 'function') {
	    return Buffer.alloc(size, fill, encoding);
	  }
	  if (typeof encoding === 'number') {
	    throw new TypeError('encoding must not be number');
	  }
	  if (typeof size !== 'number') {
	    throw new TypeError('size must be a number');
	  }
	  if (size > MAX_LEN) {
	    throw new RangeError('size is too large');
	  }
	  var enc = encoding;
	  var _fill = fill;
	  if (_fill === undefined) {
	    enc = undefined;
	    _fill = 0;
	  }
	  var buf = new Buffer(size);
	  if (typeof _fill === 'string') {
	    var fillBuf = new Buffer(_fill, enc);
	    var flen = fillBuf.length;
	    var i = -1;
	    while (++i < size) {
	      buf[i] = fillBuf[i % flen];
	    }
	  } else {
	    buf.fill(_fill);
	  }
	  return buf;
	}
	exports.allocUnsafe = function allocUnsafe(size) {
	  if (typeof Buffer.allocUnsafe === 'function') {
	    return Buffer.allocUnsafe(size);
	  }
	  if (typeof size !== 'number') {
	    throw new TypeError('size must be a number');
	  }
	  if (size > MAX_LEN) {
	    throw new RangeError('size is too large');
	  }
	  return new Buffer(size);
	}
	exports.from = function from(value, encodingOrOffset, length) {
	  if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) {
	    return Buffer.from(value, encodingOrOffset, length);
	  }
	  if (typeof value === 'number') {
	    throw new TypeError('"value" argument must not be a number');
	  }
	  if (typeof value === 'string') {
	    return new Buffer(value, encodingOrOffset);
	  }
	  if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
	    var offset = encodingOrOffset;
	    if (arguments.length === 1) {
	      return new Buffer(value);
	    }
	    if (typeof offset === 'undefined') {
	      offset = 0;
	    }
	    var len = length;
	    if (typeof len === 'undefined') {
	      len = value.byteLength - offset;
	    }
	    if (offset >= value.byteLength) {
	      throw new RangeError('\'offset\' is out of bounds');
	    }
	    if (len > value.byteLength - offset) {
	      throw new RangeError('\'length\' is out of bounds');
	    }
	    return new Buffer(value.slice(offset, offset + len));
	  }
	  if (Buffer.isBuffer(value)) {
	    var out = new Buffer(value.length);
	    value.copy(out, 0, 0, value.length);
	    return out;
	  }
	  if (value) {
	    if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) {
	      return new Buffer(value);
	    }
	    if (value.type === 'Buffer' && Array.isArray(value.data)) {
	      return new Buffer(value.data);
	    }
	  }
	
	  throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.');
	}
	exports.allocUnsafeSlow = function allocUnsafeSlow(size) {
	  if (typeof Buffer.allocUnsafeSlow === 'function') {
	    return Buffer.allocUnsafeSlow(size);
	  }
	  if (typeof size !== 'number') {
	    throw new TypeError('size must be a number');
	  }
	  if (size >= MAX_LEN) {
	    throw new RangeError('size is too large');
	  }
	  return new SlowBuffer(size);
	}
	
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
})
/** END DEFINE BLOCK for buffer-shims@1.0.0/index.js **/


/** START DEFINE BLOCK for core-util-is@1.0.2/lib/util.js **/
jupyter.define('core-util-is@1.0.2/lib/util.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(Buffer) {// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.
	
	// NOTE: These type checking functions intentionally don't use `instanceof`
	// because it is fragile and can be easily faked with `Object.create()`.
	
	function isArray(arg) {
	  if (Array.isArray) {
	    return Array.isArray(arg);
	  }
	  return objectToString(arg) === '[object Array]';
	}
	exports.isArray = isArray;
	
	function isBoolean(arg) {
	  return typeof arg === 'boolean';
	}
	exports.isBoolean = isBoolean;
	
	function isNull(arg) {
	  return arg === null;
	}
	exports.isNull = isNull;
	
	function isNullOrUndefined(arg) {
	  return arg == null;
	}
	exports.isNullOrUndefined = isNullOrUndefined;
	
	function isNumber(arg) {
	  return typeof arg === 'number';
	}
	exports.isNumber = isNumber;
	
	function isString(arg) {
	  return typeof arg === 'string';
	}
	exports.isString = isString;
	
	function isSymbol(arg) {
	  return typeof arg === 'symbol';
	}
	exports.isSymbol = isSymbol;
	
	function isUndefined(arg) {
	  return arg === void 0;
	}
	exports.isUndefined = isUndefined;
	
	function isRegExp(re) {
	  return objectToString(re) === '[object RegExp]';
	}
	exports.isRegExp = isRegExp;
	
	function isObject(arg) {
	  return typeof arg === 'object' && arg !== null;
	}
	exports.isObject = isObject;
	
	function isDate(d) {
	  return objectToString(d) === '[object Date]';
	}
	exports.isDate = isDate;
	
	function isError(e) {
	  return (objectToString(e) === '[object Error]' || e instanceof Error);
	}
	exports.isError = isError;
	
	function isFunction(arg) {
	  return typeof arg === 'function';
	}
	exports.isFunction = isFunction;
	
	function isPrimitive(arg) {
	  return arg === null ||
	         typeof arg === 'boolean' ||
	         typeof arg === 'number' ||
	         typeof arg === 'string' ||
	         typeof arg === 'symbol' ||  // ES6 symbol
	         typeof arg === 'undefined';
	}
	exports.isPrimitive = isPrimitive;
	
	exports.isBuffer = Buffer.isBuffer;
	
	function objectToString(o) {
	  return Object.prototype.toString.call(o);
	}
	
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('buffer@4.9.1/index.js').Buffer))
})
/** END DEFINE BLOCK for core-util-is@1.0.2/lib/util.js **/


/** START DEFINE BLOCK for __ignored__ **/
jupyter.define('__ignored__', function (module, exports, __jupyter_require__) {
	/* (ignored) */
})
/** END DEFINE BLOCK for __ignored__ **/


/** START DEFINE BLOCK for readable-stream@2.2.2/lib/internal/streams/BufferList.js **/
jupyter.define('readable-stream@2.2.2/lib/internal/streams/BufferList.js', function (module, exports, __jupyter_require__) {
	'use strict';
	
	var Buffer = __jupyter_require__('buffer@4.9.1/index.js').Buffer;
	/*<replacement>*/
	var bufferShim = __jupyter_require__('buffer-shims@^1.0.0/index.js');
	/*</replacement>*/
	
	module.exports = BufferList;
	
	function BufferList() {
	  this.head = null;
	  this.tail = null;
	  this.length = 0;
	}
	
	BufferList.prototype.push = function (v) {
	  var entry = { data: v, next: null };
	  if (this.length > 0) this.tail.next = entry;else this.head = entry;
	  this.tail = entry;
	  ++this.length;
	};
	
	BufferList.prototype.unshift = function (v) {
	  var entry = { data: v, next: this.head };
	  if (this.length === 0) this.tail = entry;
	  this.head = entry;
	  ++this.length;
	};
	
	BufferList.prototype.shift = function () {
	  if (this.length === 0) return;
	  var ret = this.head.data;
	  if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
	  --this.length;
	  return ret;
	};
	
	BufferList.prototype.clear = function () {
	  this.head = this.tail = null;
	  this.length = 0;
	};
	
	BufferList.prototype.join = function (s) {
	  if (this.length === 0) return '';
	  var p = this.head;
	  var ret = '' + p.data;
	  while (p = p.next) {
	    ret += s + p.data;
	  }return ret;
	};
	
	BufferList.prototype.concat = function (n) {
	  if (this.length === 0) return bufferShim.alloc(0);
	  if (this.length === 1) return this.head.data;
	  var ret = bufferShim.allocUnsafe(n >>> 0);
	  var p = this.head;
	  var i = 0;
	  while (p) {
	    p.data.copy(ret, i);
	    i += p.data.length;
	    p = p.next;
	  }
	  return ret;
	};
})
/** END DEFINE BLOCK for readable-stream@2.2.2/lib/internal/streams/BufferList.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_duplex.js **/
jupyter.define('readable-stream@2.2.2/lib/_stream_duplex.js', function (module, exports, __jupyter_require__) {
	// a duplex stream is just a stream that is both readable and writable.
	// Since JS doesn't have multiple prototypal inheritance, this class
	// prototypally inherits from Readable, and then parasitically from
	// Writable.
	
	'use strict';
	
	/*<replacement>*/
	
	var objectKeys = Object.keys || function (obj) {
	  var keys = [];
	  for (var key in obj) {
	    keys.push(key);
	  }return keys;
	};
	/*</replacement>*/
	
	module.exports = Duplex;
	
	/*<replacement>*/
	var processNextTick = __jupyter_require__('process-nextick-args@~1.0.6/index.js');
	/*</replacement>*/
	
	/*<replacement>*/
	var util = __jupyter_require__('core-util-is@~1.0.0/lib/util.js');
	util.inherits = __jupyter_require__('inherits@~2.0.1/inherits_browser.js');
	/*</replacement>*/
	
	var Readable = __jupyter_require__('readable-stream@2.2.2/lib/_stream_readable.js');
	var Writable = __jupyter_require__('readable-stream@2.2.2/lib/_stream_writable.js');
	
	util.inherits(Duplex, Readable);
	
	var keys = objectKeys(Writable.prototype);
	for (var v = 0; v < keys.length; v++) {
	  var method = keys[v];
	  if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
	}
	
	function Duplex(options) {
	  if (!(this instanceof Duplex)) return new Duplex(options);
	
	  Readable.call(this, options);
	  Writable.call(this, options);
	
	  if (options && options.readable === false) this.readable = false;
	
	  if (options && options.writable === false) this.writable = false;
	
	  this.allowHalfOpen = true;
	  if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
	
	  this.once('end', onend);
	}
	
	// the no-half-open enforcer
	function onend() {
	  // if we allow half-open state, or if the writable side ended,
	  // then we're ok.
	  if (this.allowHalfOpen || this._writableState.ended) return;
	
	  // no more data can be written.
	  // But allow more writes to happen in this tick.
	  processNextTick(onEndNT, this);
	}
	
	function onEndNT(self) {
	  self.end();
	}
	
	function forEach(xs, f) {
	  for (var i = 0, l = xs.length; i < l; i++) {
	    f(xs[i], i);
	  }
	}
})
/** END DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_duplex.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_writable.js **/
jupyter.define('readable-stream@2.2.2/lib/_stream_writable.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(process, setImmediate) {// A bit simpler than readable streams.
	// Implement an async ._write(chunk, encoding, cb), and it'll handle all
	// the drain event emission and buffering.
	
	'use strict';
	
	module.exports = Writable;
	
	/*<replacement>*/
	var processNextTick = __jupyter_require__('process-nextick-args@~1.0.6/index.js');
	/*</replacement>*/
	
	/*<replacement>*/
	var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick;
	/*</replacement>*/
	
	/*<replacement>*/
	var Duplex;
	/*</replacement>*/
	
	Writable.WritableState = WritableState;
	
	/*<replacement>*/
	var util = __jupyter_require__('core-util-is@~1.0.0/lib/util.js');
	util.inherits = __jupyter_require__('inherits@~2.0.1/inherits_browser.js');
	/*</replacement>*/
	
	/*<replacement>*/
	var internalUtil = {
	  deprecate: __jupyter_require__('util-deprecate@~1.0.1/browser.js')
	};
	/*</replacement>*/
	
	/*<replacement>*/
	var Stream;
	(function () {
	  try {
	    Stream = __jupyter_require__('stream-browserify@2.0.1/index.js');
	  } catch (_) {} finally {
	    if (!Stream) Stream = __jupyter_require__('events@1.1.1/events.js').EventEmitter;
	  }
	})();
	/*</replacement>*/
	
	var Buffer = __jupyter_require__('buffer@4.9.1/index.js').Buffer;
	/*<replacement>*/
	var bufferShim = __jupyter_require__('buffer-shims@^1.0.0/index.js');
	/*</replacement>*/
	
	util.inherits(Writable, Stream);
	
	function nop() {}
	
	function WriteReq(chunk, encoding, cb) {
	  this.chunk = chunk;
	  this.encoding = encoding;
	  this.callback = cb;
	  this.next = null;
	}
	
	function WritableState(options, stream) {
	  Duplex = Duplex || __jupyter_require__('readable-stream@2.2.2/lib/_stream_duplex.js');
	
	  options = options || {};
	
	  // object stream flag to indicate whether or not this stream
	  // contains buffers or objects.
	  this.objectMode = !!options.objectMode;
	
	  if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
	
	  // the point at which write() starts returning false
	  // Note: 0 is a valid value, means that we always return false if
	  // the entire buffer is not flushed immediately on write()
	  var hwm = options.highWaterMark;
	  var defaultHwm = this.objectMode ? 16 : 16 * 1024;
	  this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
	
	  // cast to ints.
	  this.highWaterMark = ~ ~this.highWaterMark;
	
	  // drain event flag.
	  this.needDrain = false;
	  // at the start of calling end()
	  this.ending = false;
	  // when end() has been called, and returned
	  this.ended = false;
	  // when 'finish' is emitted
	  this.finished = false;
	
	  // should we decode strings into buffers before passing to _write?
	  // this is here so that some node-core streams can optimize string
	  // handling at a lower level.
	  var noDecode = options.decodeStrings === false;
	  this.decodeStrings = !noDecode;
	
	  // Crypto is kind of old and crusty.  Historically, its default string
	  // encoding is 'binary' so we have to make this configurable.
	  // Everything else in the universe uses 'utf8', though.
	  this.defaultEncoding = options.defaultEncoding || 'utf8';
	
	  // not an actual buffer we keep track of, but a measurement
	  // of how much we're waiting to get pushed to some underlying
	  // socket or file.
	  this.length = 0;
	
	  // a flag to see when we're in the middle of a write.
	  this.writing = false;
	
	  // when true all writes will be buffered until .uncork() call
	  this.corked = 0;
	
	  // a flag to be able to tell if the onwrite cb is called immediately,
	  // or on a later tick.  We set this to true at first, because any
	  // actions that shouldn't happen until "later" should generally also
	  // not happen before the first write call.
	  this.sync = true;
	
	  // a flag to know if we're processing previously buffered items, which
	  // may call the _write() callback in the same tick, so that we don't
	  // end up in an overlapped onwrite situation.
	  this.bufferProcessing = false;
	
	  // the callback that's passed to _write(chunk,cb)
	  this.onwrite = function (er) {
	    onwrite(stream, er);
	  };
	
	  // the callback that the user supplies to write(chunk,encoding,cb)
	  this.writecb = null;
	
	  // the amount that is being written when _write is called.
	  this.writelen = 0;
	
	  this.bufferedRequest = null;
	  this.lastBufferedRequest = null;
	
	  // number of pending user-supplied write callbacks
	  // this must be 0 before 'finish' can be emitted
	  this.pendingcb = 0;
	
	  // emit prefinish if the only thing we're waiting for is _write cbs
	  // This is relevant for synchronous Transform streams
	  this.prefinished = false;
	
	  // True if the error was already emitted and should not be thrown again
	  this.errorEmitted = false;
	
	  // count buffered requests
	  this.bufferedRequestCount = 0;
	
	  // allocate the first CorkedRequest, there is always
	  // one allocated and free to use, and we maintain at most two
	  this.corkedRequestsFree = new CorkedRequest(this);
	}
	
	WritableState.prototype.getBuffer = function getBuffer() {
	  var current = this.bufferedRequest;
	  var out = [];
	  while (current) {
	    out.push(current);
	    current = current.next;
	  }
	  return out;
	};
	
	(function () {
	  try {
	    Object.defineProperty(WritableState.prototype, 'buffer', {
	      get: internalUtil.deprecate(function () {
	        return this.getBuffer();
	      }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.')
	    });
	  } catch (_) {}
	})();
	
	// Test _writableState for inheritance to account for Duplex streams,
	// whose prototype chain only points to Readable.
	var realHasInstance;
	if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
	  realHasInstance = Function.prototype[Symbol.hasInstance];
	  Object.defineProperty(Writable, Symbol.hasInstance, {
	    value: function (object) {
	      if (realHasInstance.call(this, object)) return true;
	
	      return object && object._writableState instanceof WritableState;
	    }
	  });
	} else {
	  realHasInstance = function (object) {
	    return object instanceof this;
	  };
	}
	
	function Writable(options) {
	  Duplex = Duplex || __jupyter_require__('readable-stream@2.2.2/lib/_stream_duplex.js');
	
	  // Writable ctor is applied to Duplexes, too.
	  // `realHasInstance` is necessary because using plain `instanceof`
	  // would return false, as no `_writableState` property is attached.
	
	  // Trying to use the custom `instanceof` for Writable here will also break the
	  // Node.js LazyTransform implementation, which has a non-trivial getter for
	  // `_writableState` that would lead to infinite recursion.
	  if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
	    return new Writable(options);
	  }
	
	  this._writableState = new WritableState(options, this);
	
	  // legacy.
	  this.writable = true;
	
	  if (options) {
	    if (typeof options.write === 'function') this._write = options.write;
	
	    if (typeof options.writev === 'function') this._writev = options.writev;
	  }
	
	  Stream.call(this);
	}
	
	// Otherwise people can pipe Writable streams, which is just wrong.
	Writable.prototype.pipe = function () {
	  this.emit('error', new Error('Cannot pipe, not readable'));
	};
	
	function writeAfterEnd(stream, cb) {
	  var er = new Error('write after end');
	  // TODO: defer error events consistently everywhere, not just the cb
	  stream.emit('error', er);
	  processNextTick(cb, er);
	}
	
	// If we get something that is not a buffer, string, null, or undefined,
	// and we're not in objectMode, then that's an error.
	// Otherwise stream chunks are all considered to be of length=1, and the
	// watermarks determine how many objects to keep in the buffer, rather than
	// how many bytes or characters.
	function validChunk(stream, state, chunk, cb) {
	  var valid = true;
	  var er = false;
	  // Always throw error if a null is written
	  // if we are not in object mode then throw
	  // if it is not a buffer, string, or undefined.
	  if (chunk === null) {
	    er = new TypeError('May not write null values to stream');
	  } else if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
	    er = new TypeError('Invalid non-string/buffer chunk');
	  }
	  if (er) {
	    stream.emit('error', er);
	    processNextTick(cb, er);
	    valid = false;
	  }
	  return valid;
	}
	
	Writable.prototype.write = function (chunk, encoding, cb) {
	  var state = this._writableState;
	  var ret = false;
	
	  if (typeof encoding === 'function') {
	    cb = encoding;
	    encoding = null;
	  }
	
	  if (Buffer.isBuffer(chunk)) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
	
	  if (typeof cb !== 'function') cb = nop;
	
	  if (state.ended) writeAfterEnd(this, cb);else if (validChunk(this, state, chunk, cb)) {
	    state.pendingcb++;
	    ret = writeOrBuffer(this, state, chunk, encoding, cb);
	  }
	
	  return ret;
	};
	
	Writable.prototype.cork = function () {
	  var state = this._writableState;
	
	  state.corked++;
	};
	
	Writable.prototype.uncork = function () {
	  var state = this._writableState;
	
	  if (state.corked) {
	    state.corked--;
	
	    if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
	  }
	};
	
	Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
	  // node::ParseEncoding() requires lower case.
	  if (typeof encoding === 'string') encoding = encoding.toLowerCase();
	  if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding);
	  this._writableState.defaultEncoding = encoding;
	  return this;
	};
	
	function decodeChunk(state, chunk, encoding) {
	  if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
	    chunk = bufferShim.from(chunk, encoding);
	  }
	  return chunk;
	}
	
	// if we're already writing something, then just put this
	// in the queue, and wait our turn.  Otherwise, call _write
	// If we return false, then we need a drain event, so set that flag.
	function writeOrBuffer(stream, state, chunk, encoding, cb) {
	  chunk = decodeChunk(state, chunk, encoding);
	
	  if (Buffer.isBuffer(chunk)) encoding = 'buffer';
	  var len = state.objectMode ? 1 : chunk.length;
	
	  state.length += len;
	
	  var ret = state.length < state.highWaterMark;
	  // we must ensure that previous needDrain will not be reset to false.
	  if (!ret) state.needDrain = true;
	
	  if (state.writing || state.corked) {
	    var last = state.lastBufferedRequest;
	    state.lastBufferedRequest = new WriteReq(chunk, encoding, cb);
	    if (last) {
	      last.next = state.lastBufferedRequest;
	    } else {
	      state.bufferedRequest = state.lastBufferedRequest;
	    }
	    state.bufferedRequestCount += 1;
	  } else {
	    doWrite(stream, state, false, len, chunk, encoding, cb);
	  }
	
	  return ret;
	}
	
	function doWrite(stream, state, writev, len, chunk, encoding, cb) {
	  state.writelen = len;
	  state.writecb = cb;
	  state.writing = true;
	  state.sync = true;
	  if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
	  state.sync = false;
	}
	
	function onwriteError(stream, state, sync, er, cb) {
	  --state.pendingcb;
	  if (sync) processNextTick(cb, er);else cb(er);
	
	  stream._writableState.errorEmitted = true;
	  stream.emit('error', er);
	}
	
	function onwriteStateUpdate(state) {
	  state.writing = false;
	  state.writecb = null;
	  state.length -= state.writelen;
	  state.writelen = 0;
	}
	
	function onwrite(stream, er) {
	  var state = stream._writableState;
	  var sync = state.sync;
	  var cb = state.writecb;
	
	  onwriteStateUpdate(state);
	
	  if (er) onwriteError(stream, state, sync, er, cb);else {
	    // Check if we're actually ready to finish, but don't emit yet
	    var finished = needFinish(state);
	
	    if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
	      clearBuffer(stream, state);
	    }
	
	    if (sync) {
	      /*<replacement>*/
	      asyncWrite(afterWrite, stream, state, finished, cb);
	      /*</replacement>*/
	    } else {
	        afterWrite(stream, state, finished, cb);
	      }
	  }
	}
	
	function afterWrite(stream, state, finished, cb) {
	  if (!finished) onwriteDrain(stream, state);
	  state.pendingcb--;
	  cb();
	  finishMaybe(stream, state);
	}
	
	// Must force callback to be called on nextTick, so that we don't
	// emit 'drain' before the write() consumer gets the 'false' return
	// value, and has a chance to attach a 'drain' listener.
	function onwriteDrain(stream, state) {
	  if (state.length === 0 && state.needDrain) {
	    state.needDrain = false;
	    stream.emit('drain');
	  }
	}
	
	// if there's something in the buffer waiting, then process it
	function clearBuffer(stream, state) {
	  state.bufferProcessing = true;
	  var entry = state.bufferedRequest;
	
	  if (stream._writev && entry && entry.next) {
	    // Fast case, write everything using _writev()
	    var l = state.bufferedRequestCount;
	    var buffer = new Array(l);
	    var holder = state.corkedRequestsFree;
	    holder.entry = entry;
	
	    var count = 0;
	    while (entry) {
	      buffer[count] = entry;
	      entry = entry.next;
	      count += 1;
	    }
	
	    doWrite(stream, state, true, state.length, buffer, '', holder.finish);
	
	    // doWrite is almost always async, defer these to save a bit of time
	    // as the hot path ends with doWrite
	    state.pendingcb++;
	    state.lastBufferedRequest = null;
	    if (holder.next) {
	      state.corkedRequestsFree = holder.next;
	      holder.next = null;
	    } else {
	      state.corkedRequestsFree = new CorkedRequest(state);
	    }
	  } else {
	    // Slow case, write chunks one-by-one
	    while (entry) {
	      var chunk = entry.chunk;
	      var encoding = entry.encoding;
	      var cb = entry.callback;
	      var len = state.objectMode ? 1 : chunk.length;
	
	      doWrite(stream, state, false, len, chunk, encoding, cb);
	      entry = entry.next;
	      // if we didn't call the onwrite immediately, then
	      // it means that we need to wait until it does.
	      // also, that means that the chunk and cb are currently
	      // being processed, so move the buffer counter past them.
	      if (state.writing) {
	        break;
	      }
	    }
	
	    if (entry === null) state.lastBufferedRequest = null;
	  }
	
	  state.bufferedRequestCount = 0;
	  state.bufferedRequest = entry;
	  state.bufferProcessing = false;
	}
	
	Writable.prototype._write = function (chunk, encoding, cb) {
	  cb(new Error('_write() is not implemented'));
	};
	
	Writable.prototype._writev = null;
	
	Writable.prototype.end = function (chunk, encoding, cb) {
	  var state = this._writableState;
	
	  if (typeof chunk === 'function') {
	    cb = chunk;
	    chunk = null;
	    encoding = null;
	  } else if (typeof encoding === 'function') {
	    cb = encoding;
	    encoding = null;
	  }
	
	  if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);
	
	  // .end() fully uncorks
	  if (state.corked) {
	    state.corked = 1;
	    this.uncork();
	  }
	
	  // ignore unnecessary end() calls.
	  if (!state.ending && !state.finished) endWritable(this, state, cb);
	};
	
	function needFinish(state) {
	  return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
	}
	
	function prefinish(stream, state) {
	  if (!state.prefinished) {
	    state.prefinished = true;
	    stream.emit('prefinish');
	  }
	}
	
	function finishMaybe(stream, state) {
	  var need = needFinish(state);
	  if (need) {
	    if (state.pendingcb === 0) {
	      prefinish(stream, state);
	      state.finished = true;
	      stream.emit('finish');
	    } else {
	      prefinish(stream, state);
	    }
	  }
	  return need;
	}
	
	function endWritable(stream, state, cb) {
	  state.ending = true;
	  finishMaybe(stream, state);
	  if (cb) {
	    if (state.finished) processNextTick(cb);else stream.once('finish', cb);
	  }
	  state.ended = true;
	  stream.writable = false;
	}
	
	// It seems a linked list but it is not
	// there will be only 2 of these for each stream
	function CorkedRequest(state) {
	  var _this = this;
	
	  this.next = null;
	  this.entry = null;
	
	  this.finish = function (err) {
	    var entry = _this.entry;
	    _this.entry = null;
	    while (entry) {
	      var cb = entry.callback;
	      state.pendingcb--;
	      cb(err);
	      entry = entry.next;
	    }
	    if (state.corkedRequestsFree) {
	      state.corkedRequestsFree.next = _this;
	    } else {
	      state.corkedRequestsFree = _this;
	    }
	  };
	}
	/* WEBPACK VAR INJECTION */}.call(exports, __jupyter_require__('process@0.11.9/browser.js'), __jupyter_require__('timers-browserify@2.0.2/main.js').setImmediate))
})
/** END DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_writable.js **/


/** START DEFINE BLOCK for util-deprecate@1.0.2/browser.js **/
jupyter.define('util-deprecate@1.0.2/browser.js', function (module, exports, __jupyter_require__) {
	/* WEBPACK VAR INJECTION */(function(global) {
	/**
	 * Module exports.
	 */
	
	module.exports = deprecate;
	
	/**
	 * Mark that a method should not be used.
	 * Returns a modified function which warns once by default.
	 *
	 * If `localStorage.noDeprecation = true` is set, then it is a no-op.
	 *
	 * If `localStorage.throwDeprecation = true` is set, then deprecated functions
	 * will throw an Error when invoked.
	 *
	 * If `localStorage.traceDeprecation = true` is set, then deprecated functions
	 * will invoke `console.trace()` instead of `console.error()`.
	 *
	 * @param {Function} fn - the function to deprecate
	 * @param {String} msg - the string to print to the console when `fn` is invoked
	 * @returns {Function} a new "deprecated" version of `fn`
	 * @api public
	 */
	
	function deprecate (fn, msg) {
	  if (config('noDeprecation')) {
	    return fn;
	  }
	
	  var warned = false;
	  function deprecated() {
	    if (!warned) {
	      if (config('throwDeprecation')) {
	        throw new Error(msg);
	      } else if (config('traceDeprecation')) {
	        console.trace(msg);
	      } else {
	        console.warn(msg);
	      }
	      warned = true;
	    }
	    return fn.apply(this, arguments);
	  }
	
	  return deprecated;
	}
	
	/**
	 * Checks `localStorage` for boolean values for the given `name`.
	 *
	 * @param {String} name
	 * @returns {Boolean}
	 * @api private
	 */
	
	function config (name) {
	  // accessing global.localStorage can trigger a DOMException in sandboxed iframes
	  try {
	    if (!global.localStorage) return false;
	  } catch (_) {
	    return false;
	  }
	  var val = global.localStorage[name];
	  if (null == val) return false;
	  return String(val).toLowerCase() === 'true';
	}
	
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
})
/** END DEFINE BLOCK for util-deprecate@1.0.2/browser.js **/


/** START DEFINE BLOCK for string_decoder@0.10.31/index.js **/
jupyter.define('string_decoder@0.10.31/index.js', function (module, exports, __jupyter_require__) {
	// Copyright Joyent, Inc. and other Node contributors.
	//
	// Permission is hereby granted, free of charge, to any person obtaining a
	// copy of this software and associated documentation files (the
	// "Software"), to deal in the Software without restriction, including
	// without limitation the rights to use, copy, modify, merge, publish,
	// distribute, sublicense, and/or sell copies of the Software, and to permit
	// persons to whom the Software is furnished to do so, subject to the
	// following conditions:
	//
	// The above copyright notice and this permission notice shall be included
	// in all copies or substantial portions of the Software.
	//
	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
	// USE OR OTHER DEALINGS IN THE SOFTWARE.
	
	var Buffer = __jupyter_require__('buffer@4.9.1/index.js').Buffer;
	
	var isBufferEncoding = Buffer.isEncoding
	  || function(encoding) {
	       switch (encoding && encoding.toLowerCase()) {
	         case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
	         default: return false;
	       }
	     }
	
	
	function assertEncoding(encoding) {
	  if (encoding && !isBufferEncoding(encoding)) {
	    throw new Error('Unknown encoding: ' + encoding);
	  }
	}
	
	// StringDecoder provides an interface for efficiently splitting a series of
	// buffers into a series of JS strings without breaking apart multi-byte
	// characters. CESU-8 is handled as part of the UTF-8 encoding.
	//
	// @TODO Handling all encodings inside a single object makes it very difficult
	// to reason about this code, so it should be split up in the future.
	// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
	// points as used by CESU-8.
	var StringDecoder = exports.StringDecoder = function(encoding) {
	  this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
	  assertEncoding(encoding);
	  switch (this.encoding) {
	    case 'utf8':
	      // CESU-8 represents each of Surrogate Pair by 3-bytes
	      this.surrogateSize = 3;
	      break;
	    case 'ucs2':
	    case 'utf16le':
	      // UTF-16 represents each of Surrogate Pair by 2-bytes
	      this.surrogateSize = 2;
	      this.detectIncompleteChar = utf16DetectIncompleteChar;
	      break;
	    case 'base64':
	      // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
	      this.surrogateSize = 3;
	      this.detectIncompleteChar = base64DetectIncompleteChar;
	      break;
	    default:
	      this.write = passThroughWrite;
	      return;
	  }
	
	  // Enough space to store all bytes of a single character. UTF-8 needs 4
	  // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
	  this.charBuffer = new Buffer(6);
	  // Number of bytes received for the current incomplete multi-byte character.
	  this.charReceived = 0;
	  // Number of bytes expected for the current incomplete multi-byte character.
	  this.charLength = 0;
	};
	
	
	// write decodes the given buffer and returns it as JS string that is
	// guaranteed to not contain any partial multi-byte characters. Any partial
	// character found at the end of the buffer is buffered up, and will be
	// returned when calling write again with the remaining bytes.
	//
	// Note: Converting a Buffer containing an orphan surrogate to a String
	// currently works, but converting a String to a Buffer (via `new Buffer`, or
	// Buffer#write) will replace incomplete surrogates with the unicode
	// replacement character. See https://codereview.chromium.org/121173009/ .
	StringDecoder.prototype.write = function(buffer) {
	  var charStr = '';
	  // if our last write ended with an incomplete multibyte character
	  while (this.charLength) {
	    // determine how many remaining bytes this buffer has to offer for this char
	    var available = (buffer.length >= this.charLength - this.charReceived) ?
	        this.charLength - this.charReceived :
	        buffer.length;
	
	    // add the new bytes to the char buffer
	    buffer.copy(this.charBuffer, this.charReceived, 0, available);
	    this.charReceived += available;
	
	    if (this.charReceived < this.charLength) {
	      // still not enough chars in this buffer? wait for more ...
	      return '';
	    }
	
	    // remove bytes belonging to the current character from the buffer
	    buffer = buffer.slice(available, buffer.length);
	
	    // get the character that was split
	    charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
	
	    // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
	    var charCode = charStr.charCodeAt(charStr.length - 1);
	    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
	      this.charLength += this.surrogateSize;
	      charStr = '';
	      continue;
	    }
	    this.charReceived = this.charLength = 0;
	
	    // if there are no more bytes in this buffer, just emit our char
	    if (buffer.length === 0) {
	      return charStr;
	    }
	    break;
	  }
	
	  // determine and set charLength / charReceived
	  this.detectIncompleteChar(buffer);
	
	  var end = buffer.length;
	  if (this.charLength) {
	    // buffer the incomplete character bytes we got
	    buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
	    end -= this.charReceived;
	  }
	
	  charStr += buffer.toString(this.encoding, 0, end);
	
	  var end = charStr.length - 1;
	  var charCode = charStr.charCodeAt(end);
	  // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
	  if (charCode >= 0xD800 && charCode <= 0xDBFF) {
	    var size = this.surrogateSize;
	    this.charLength += size;
	    this.charReceived += size;
	    this.charBuffer.copy(this.charBuffer, size, 0, size);
	    buffer.copy(this.charBuffer, 0, 0, size);
	    return charStr.substring(0, end);
	  }
	
	  // or just emit the charStr
	  return charStr;
	};
	
	// detectIncompleteChar determines if there is an incomplete UTF-8 character at
	// the end of the given buffer. If so, it sets this.charLength to the byte
	// length that character, and sets this.charReceived to the number of bytes
	// that are available for this character.
	StringDecoder.prototype.detectIncompleteChar = function(buffer) {
	  // determine how many bytes we have to check at the end of this buffer
	  var i = (buffer.length >= 3) ? 3 : buffer.length;
	
	  // Figure out if one of the last i bytes of our buffer announces an
	  // incomplete char.
	  for (; i > 0; i--) {
	    var c = buffer[buffer.length - i];
	
	    // See http://en.wikipedia.org/wiki/UTF-8#Description
	
	    // 110XXXXX
	    if (i == 1 && c >> 5 == 0x06) {
	      this.charLength = 2;
	      break;
	    }
	
	    // 1110XXXX
	    if (i <= 2 && c >> 4 == 0x0E) {
	      this.charLength = 3;
	      break;
	    }
	
	    // 11110XXX
	    if (i <= 3 && c >> 3 == 0x1E) {
	      this.charLength = 4;
	      break;
	    }
	  }
	  this.charReceived = i;
	};
	
	StringDecoder.prototype.end = function(buffer) {
	  var res = '';
	  if (buffer && buffer.length)
	    res = this.write(buffer);
	
	  if (this.charReceived) {
	    var cr = this.charReceived;
	    var buf = this.charBuffer;
	    var enc = this.encoding;
	    res += buf.slice(0, cr).toString(enc);
	  }
	
	  return res;
	};
	
	function passThroughWrite(buffer) {
	  return buffer.toString(this.encoding);
	}
	
	function utf16DetectIncompleteChar(buffer) {
	  this.charReceived = buffer.length % 2;
	  this.charLength = this.charReceived ? 2 : 0;
	}
	
	function base64DetectIncompleteChar(buffer) {
	  this.charReceived = buffer.length % 3;
	  this.charLength = this.charReceived ? 3 : 0;
	}
	
})
/** END DEFINE BLOCK for string_decoder@0.10.31/index.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_transform.js **/
jupyter.define('readable-stream@2.2.2/lib/_stream_transform.js', function (module, exports, __jupyter_require__) {
	// a transform stream is a readable/writable stream where you do
	// something with the data.  Sometimes it's called a "filter",
	// but that's not a great name for it, since that implies a thing where
	// some bits pass through, and others are simply ignored.  (That would
	// be a valid example of a transform, of course.)
	//
	// While the output is causally related to the input, it's not a
	// necessarily symmetric or synchronous transformation.  For example,
	// a zlib stream might take multiple plain-text writes(), and then
	// emit a single compressed chunk some time in the future.
	//
	// Here's how this works:
	//
	// The Transform stream has all the aspects of the readable and writable
	// stream classes.  When you write(chunk), that calls _write(chunk,cb)
	// internally, and returns false if there's a lot of pending writes
	// buffered up.  When you call read(), that calls _read(n) until
	// there's enough pending readable data buffered up.
	//
	// In a transform stream, the written data is placed in a buffer.  When
	// _read(n) is called, it transforms the queued up data, calling the
	// buffered _write cb's as it consumes chunks.  If consuming a single
	// written chunk would result in multiple output chunks, then the first
	// outputted bit calls the readcb, and subsequent chunks just go into
	// the read buffer, and will cause it to emit 'readable' if necessary.
	//
	// This way, back-pressure is actually determined by the reading side,
	// since _read has to be called to start processing a new chunk.  However,
	// a pathological inflate type of transform can cause excessive buffering
	// here.  For example, imagine a stream where every byte of input is
	// interpreted as an integer from 0-255, and then results in that many
	// bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
	// 1kb of data being output.  In this case, you could write a very small
	// amount of input, and end up with a very large amount of output.  In
	// such a pathological inflating mechanism, there'd be no way to tell
	// the system to stop doing the transform.  A single 4MB write could
	// cause the system to run out of memory.
	//
	// However, even in such a pathological case, only a single written chunk
	// would be consumed, and then the rest would wait (un-transformed) until
	// the results of the previous transformed chunk were consumed.
	
	'use strict';
	
	module.exports = Transform;
	
	var Duplex = __jupyter_require__('readable-stream@2.2.2/lib/_stream_duplex.js');
	
	/*<replacement>*/
	var util = __jupyter_require__('core-util-is@~1.0.0/lib/util.js');
	util.inherits = __jupyter_require__('inherits@~2.0.1/inherits_browser.js');
	/*</replacement>*/
	
	util.inherits(Transform, Duplex);
	
	function TransformState(stream) {
	  this.afterTransform = function (er, data) {
	    return afterTransform(stream, er, data);
	  };
	
	  this.needTransform = false;
	  this.transforming = false;
	  this.writecb = null;
	  this.writechunk = null;
	  this.writeencoding = null;
	}
	
	function afterTransform(stream, er, data) {
	  var ts = stream._transformState;
	  ts.transforming = false;
	
	  var cb = ts.writecb;
	
	  if (!cb) return stream.emit('error', new Error('no writecb in Transform class'));
	
	  ts.writechunk = null;
	  ts.writecb = null;
	
	  if (data !== null && data !== undefined) stream.push(data);
	
	  cb(er);
	
	  var rs = stream._readableState;
	  rs.reading = false;
	  if (rs.needReadable || rs.length < rs.highWaterMark) {
	    stream._read(rs.highWaterMark);
	  }
	}
	
	function Transform(options) {
	  if (!(this instanceof Transform)) return new Transform(options);
	
	  Duplex.call(this, options);
	
	  this._transformState = new TransformState(this);
	
	  var stream = this;
	
	  // start out asking for a readable event once data is transformed.
	  this._readableState.needReadable = true;
	
	  // we have implemented the _read method, and done the other things
	  // that Readable wants before the first _read call, so unset the
	  // sync guard flag.
	  this._readableState.sync = false;
	
	  if (options) {
	    if (typeof options.transform === 'function') this._transform = options.transform;
	
	    if (typeof options.flush === 'function') this._flush = options.flush;
	  }
	
	  // When the writable side finishes, then flush out anything remaining.
	  this.once('prefinish', function () {
	    if (typeof this._flush === 'function') this._flush(function (er, data) {
	      done(stream, er, data);
	    });else done(stream);
	  });
	}
	
	Transform.prototype.push = function (chunk, encoding) {
	  this._transformState.needTransform = false;
	  return Duplex.prototype.push.call(this, chunk, encoding);
	};
	
	// This is the part where you do stuff!
	// override this function in implementation classes.
	// 'chunk' is an input chunk.
	//
	// Call `push(newChunk)` to pass along transformed output
	// to the readable side.  You may call 'push' zero or more times.
	//
	// Call `cb(err)` when you are done with this chunk.  If you pass
	// an error, then that'll put the hurt on the whole operation.  If you
	// never call cb(), then you'll never get another chunk.
	Transform.prototype._transform = function (chunk, encoding, cb) {
	  throw new Error('_transform() is not implemented');
	};
	
	Transform.prototype._write = function (chunk, encoding, cb) {
	  var ts = this._transformState;
	  ts.writecb = cb;
	  ts.writechunk = chunk;
	  ts.writeencoding = encoding;
	  if (!ts.transforming) {
	    var rs = this._readableState;
	    if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
	  }
	};
	
	// Doesn't matter what the args are here.
	// _transform does all the work.
	// That we got here means that the readable side wants more data.
	Transform.prototype._read = function (n) {
	  var ts = this._transformState;
	
	  if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
	    ts.transforming = true;
	    this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
	  } else {
	    // mark that we need a transform, so that any data that comes in
	    // will get processed, now that we've asked for it.
	    ts.needTransform = true;
	  }
	};
	
	function done(stream, er, data) {
	  if (er) return stream.emit('error', er);
	
	  if (data !== null && data !== undefined) stream.push(data);
	
	  // if there's nothing in the write buffer, then that means
	  // that nothing more will ever be provided
	  var ws = stream._writableState;
	  var ts = stream._transformState;
	
	  if (ws.length) throw new Error('Calling transform done when ws.length != 0');
	
	  if (ts.transforming) throw new Error('Calling transform done when still transforming');
	
	  return stream.push(null);
	}
})
/** END DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_transform.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_passthrough.js **/
jupyter.define('readable-stream@2.2.2/lib/_stream_passthrough.js', function (module, exports, __jupyter_require__) {
	// a passthrough stream.
	// basically just the most minimal sort of Transform stream.
	// Every written chunk gets output as-is.
	
	'use strict';
	
	module.exports = PassThrough;
	
	var Transform = __jupyter_require__('readable-stream@2.2.2/lib/_stream_transform.js');
	
	/*<replacement>*/
	var util = __jupyter_require__('core-util-is@~1.0.0/lib/util.js');
	util.inherits = __jupyter_require__('inherits@~2.0.1/inherits_browser.js');
	/*</replacement>*/
	
	util.inherits(PassThrough, Transform);
	
	function PassThrough(options) {
	  if (!(this instanceof PassThrough)) return new PassThrough(options);
	
	  Transform.call(this, options);
	}
	
	PassThrough.prototype._transform = function (chunk, encoding, cb) {
	  cb(null, chunk);
	};
})
/** END DEFINE BLOCK for readable-stream@2.2.2/lib/_stream_passthrough.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/writable.js **/
jupyter.define('readable-stream@2.2.2/writable.js', function (module, exports, __jupyter_require__) {
	module.exports = __jupyter_require__('readable-stream@2.2.2/lib/_stream_writable.js')
	
})
/** END DEFINE BLOCK for readable-stream@2.2.2/writable.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/duplex.js **/
jupyter.define('readable-stream@2.2.2/duplex.js', function (module, exports, __jupyter_require__) {
	module.exports = __jupyter_require__('readable-stream@2.2.2/lib/_stream_duplex.js')
	
})
/** END DEFINE BLOCK for readable-stream@2.2.2/duplex.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/transform.js **/
jupyter.define('readable-stream@2.2.2/transform.js', function (module, exports, __jupyter_require__) {
	module.exports = __jupyter_require__('readable-stream@2.2.2/lib/_stream_transform.js')
	
})
/** END DEFINE BLOCK for readable-stream@2.2.2/transform.js **/


/** START DEFINE BLOCK for readable-stream@2.2.2/passthrough.js **/
jupyter.define('readable-stream@2.2.2/passthrough.js', function (module, exports, __jupyter_require__) {
	module.exports = __jupyter_require__('readable-stream@2.2.2/lib/_stream_passthrough.js')
	
})
/** END DEFINE BLOCK for readable-stream@2.2.2/passthrough.js **/


/** START DEFINE BLOCK for __ignored__ **/
jupyter.define('__ignored__', function (module, exports, __jupyter_require__) {
	/* (ignored) */
})
/** END DEFINE BLOCK for __ignored__ **/


/** START DEFINE BLOCK for htmlparser2@3.9.2/lib/ProxyHandler.js **/
jupyter.define('htmlparser2@3.9.2/lib/ProxyHandler.js', function (module, exports, __jupyter_require__) {
	module.exports = ProxyHandler;
	
	function ProxyHandler(cbs){
		this._cbs = cbs || {};
	}
	
	var EVENTS = __jupyter_require__('htmlparser2@3.9.2/lib/index.js').EVENTS;
	Object.keys(EVENTS).forEach(function(name){
		if(EVENTS[name] === 0){
			name = "on" + name;
			ProxyHandler.prototype[name] = function(){
				if(this._cbs[name]) this._cbs[name]();
			};
		} else if(EVENTS[name] === 1){
			name = "on" + name;
			ProxyHandler.prototype[name] = function(a){
				if(this._cbs[name]) this._cbs[name](a);
			};
		} else if(EVENTS[name] === 2){
			name = "on" + name;
			ProxyHandler.prototype[name] = function(a, b){
				if(this._cbs[name]) this._cbs[name](a, b);
			};
		} else {
			throw Error("wrong number of arguments");
		}
	});
})
/** END DEFINE BLOCK for htmlparser2@3.9.2/lib/ProxyHandler.js **/


/** START DEFINE BLOCK for domutils@1.5.1/index.js **/
jupyter.define('domutils@1.5.1/index.js', function (module, exports, __jupyter_require__) {
	var DomUtils = module.exports;
	
	[
		__jupyter_require__('domutils@1.5.1/lib/stringify.js'),
		__jupyter_require__('domutils@1.5.1/lib/traversal.js'),
		__jupyter_require__('domutils@1.5.1/lib/manipulation.js'),
		__jupyter_require__('domutils@1.5.1/lib/querying.js'),
		__jupyter_require__('domutils@1.5.1/lib/legacy.js'),
		__jupyter_require__('domutils@1.5.1/lib/helpers.js')
	].forEach(function(ext){
		Object.keys(ext).forEach(function(key){
			DomUtils[key] = ext[key].bind(DomUtils);
		});
	});
	
})
/** END DEFINE BLOCK for domutils@1.5.1/index.js **/


/** START DEFINE BLOCK for domutils@1.5.1/lib/stringify.js **/
jupyter.define('domutils@1.5.1/lib/stringify.js', function (module, exports, __jupyter_require__) {
	var ElementType = __jupyter_require__('domelementtype@1/index.js'),
	    getOuterHTML = __jupyter_require__('dom-serializer@0/index.js'),
	    isTag = ElementType.isTag;
	
	module.exports = {
		getInnerHTML: getInnerHTML,
		getOuterHTML: getOuterHTML,
		getText: getText
	};
	
	function getInnerHTML(elem, opts){
		return elem.children ? elem.children.map(function(elem){
			return getOuterHTML(elem, opts);
		}).join("") : "";
	}
	
	function getText(elem){
		if(Array.isArray(elem)) return elem.map(getText).join("");
		if(isTag(elem) || elem.type === ElementType.CDATA) return getText(elem.children);
		if(elem.type === ElementType.Text) return elem.data;
		return "";
	}
	
})
/** END DEFINE BLOCK for domutils@1.5.1/lib/stringify.js **/


/** START DEFINE BLOCK for dom-serializer@0.1.0/index.js **/
jupyter.define('dom-serializer@0.1.0/index.js', function (module, exports, __jupyter_require__) {
	/*
	  Module dependencies
	*/
	var ElementType = __jupyter_require__('domelementtype@~1.1.1/index.js');
	var entities = __jupyter_require__('entities@~1.1.1/index.js');
	
	/*
	  Boolean Attributes
	*/
	var booleanAttributes = {
	  __proto__: null,
	  allowfullscreen: true,
	  async: true,
	  autofocus: true,
	  autoplay: true,
	  checked: true,
	  controls: true,
	  default: true,
	  defer: true,
	  disabled: true,
	  hidden: true,
	  ismap: true,
	  loop: true,
	  multiple: true,
	  muted: true,
	  open: true,
	  readonly: true,
	  required: true,
	  reversed: true,
	  scoped: true,
	  seamless: true,
	  selected: true,
	  typemustmatch: true
	};
	
	var unencodedElements = {
	  __proto__: null,
	  style: true,
	  script: true,
	  xmp: true,
	  iframe: true,
	  noembed: true,
	  noframes: true,
	  plaintext: true,
	  noscript: true
	};
	
	/*
	  Format attributes
	*/
	function formatAttrs(attributes, opts) {
	  if (!attributes) return;
	
	  var output = '',
	      value;
	
	  // Loop through the attributes
	  for (var key in attributes) {
	    value = attributes[key];
	    if (output) {
	      output += ' ';
	    }
	
	    if (!value && booleanAttributes[key]) {
	      output += key;
	    } else {
	      output += key + '="' + (opts.decodeEntities ? entities.encodeXML(value) : value) + '"';
	    }
	  }
	
	  return output;
	}
	
	/*
	  Self-enclosing tags (stolen from node-htmlparser)
	*/
	var singleTag = {
	  __proto__: null,
	  area: true,
	  base: true,
	  basefont: true,
	  br: true,
	  col: true,
	  command: true,
	  embed: true,
	  frame: true,
	  hr: true,
	  img: true,
	  input: true,
	  isindex: true,
	  keygen: true,
	  link: true,
	  meta: true,
	  param: true,
	  source: true,
	  track: true,
	  wbr: true,
	};
	
	
	var render = module.exports = function(dom, opts) {
	  if (!Array.isArray(dom) && !dom.cheerio) dom = [dom];
	  opts = opts || {};
	
	  var output = '';
	
	  for(var i = 0; i < dom.length; i++){
	    var elem = dom[i];
	
	    if (elem.type === 'root')
	      output += render(elem.children, opts);
	    else if (ElementType.isTag(elem))
	      output += renderTag(elem, opts);
	    else if (elem.type === ElementType.Directive)
	      output += renderDirective(elem);
	    else if (elem.type === ElementType.Comment)
	      output += renderComment(elem);
	    else if (elem.type === ElementType.CDATA)
	      output += renderCdata(elem);
	    else
	      output += renderText(elem, opts);
	  }
	
	  return output;
	};
	
	function renderTag(elem, opts) {
	  // Handle SVG
	  if (elem.name === "svg") opts = {decodeEntities: opts.decodeEntities, xmlMode: true};
	
	  var tag = '<' + elem.name,
	      attribs = formatAttrs(elem.attribs, opts);
	
	  if (attribs) {
	    tag += ' ' + attribs;
	  }
	
	  if (
	    opts.xmlMode
	    && (!elem.children || elem.children.length === 0)
	  ) {
	    tag += '/>';
	  } else {
	    tag += '>';
	    if (elem.children) {
	      tag += render(elem.children, opts);
	    }
	
	    if (!singleTag[elem.name] || opts.xmlMode) {
	      tag += '</' + elem.name + '>';
	    }
	  }
	
	  return tag;
	}
	
	function renderDirective(elem) {
	  return '<' + elem.data + '>';
	}
	
	function renderText(elem, opts) {
	  var data = elem.data || '';
	
	  // if entities weren't decoded, no need to encode them back
	  if (opts.decodeEntities && !(elem.parent && elem.parent.name in unencodedElements)) {
	    data = entities.encodeXML(data);
	  }
	
	  return data;
	}
	
	function renderCdata(elem) {
	  return '<![CDATA[' + elem.children[0].data + ']]>';
	}
	
	function renderComment(elem) {
	  return '<!--' + elem.data + '-->';
	}
	
})
/** END DEFINE BLOCK for dom-serializer@0.1.0/index.js **/


/** START DEFINE BLOCK for domelementtype@1.1.3/index.js **/
jupyter.define('domelementtype@1.1.3/index.js', function (module, exports, __jupyter_require__) {
	//Types of elements found in the DOM
	module.exports = {
		Text: "text", //Text
		Directive: "directive", //<? ... ?>
		Comment: "comment", //<!-- ... -->
		Script: "script", //<script> tags
		Style: "style", //<style> tags
		Tag: "tag", //Any tag
		CDATA: "cdata", //<![CDATA[ ... ]]>
	
		isTag: function(elem){
			return elem.type === "tag" || elem.type === "script" || elem.type === "style";
		}
	};
})
/** END DEFINE BLOCK for domelementtype@1.1.3/index.js **/


/** START DEFINE BLOCK for entities@1.1.1/index.js **/
jupyter.define('entities@1.1.1/index.js', function (module, exports, __jupyter_require__) {
	var encode = __jupyter_require__('entities@1.1.1/lib/encode.js'),
	    decode = __jupyter_require__('entities@1.1.1/lib/decode.js');
	
	exports.decode = function(data, level){
		return (!level || level <= 0 ? decode.XML : decode.HTML)(data);
	};
	
	exports.decodeStrict = function(data, level){
		return (!level || level <= 0 ? decode.XML : decode.HTMLStrict)(data);
	};
	
	exports.encode = function(data, level){
		return (!level || level <= 0 ? encode.XML : encode.HTML)(data);
	};
	
	exports.encodeXML = encode.XML;
	
	exports.encodeHTML4 =
	exports.encodeHTML5 =
	exports.encodeHTML  = encode.HTML;
	
	exports.decodeXML =
	exports.decodeXMLStrict = decode.XML;
	
	exports.decodeHTML4 =
	exports.decodeHTML5 =
	exports.decodeHTML = decode.HTML;
	
	exports.decodeHTML4Strict =
	exports.decodeHTML5Strict =
	exports.decodeHTMLStrict = decode.HTMLStrict;
	
	exports.escape = encode.escape;
	
})
/** END DEFINE BLOCK for entities@1.1.1/index.js **/


/** START DEFINE BLOCK for entities@1.1.1/lib/encode.js **/
jupyter.define('entities@1.1.1/lib/encode.js', function (module, exports, __jupyter_require__) {
	var inverseXML = getInverseObj(__jupyter_require__('entities@1.1.1/maps/xml.json')),
	    xmlReplacer = getInverseReplacer(inverseXML);
	
	exports.XML = getInverse(inverseXML, xmlReplacer);
	
	var inverseHTML = getInverseObj(__jupyter_require__('entities@1.1.1/maps/entities.json')),
	    htmlReplacer = getInverseReplacer(inverseHTML);
	
	exports.HTML = getInverse(inverseHTML, htmlReplacer);
	
	function getInverseObj(obj){
		return Object.keys(obj).sort().reduce(function(inverse, name){
			inverse[obj[name]] = "&" + name + ";";
			return inverse;
		}, {});
	}
	
	function getInverseReplacer(inverse){
		var single = [],
		    multiple = [];
	
		Object.keys(inverse).forEach(function(k){
			if(k.length === 1){
				single.push("\\" + k);
			} else {
				multiple.push(k);
			}
		});
	
		//TODO add ranges
		multiple.unshift("[" + single.join("") + "]");
	
		return new RegExp(multiple.join("|"), "g");
	}
	
	var re_nonASCII = /[^\0-\x7F]/g,
	    re_astralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
	
	function singleCharReplacer(c){
		return "&#x" + c.charCodeAt(0).toString(16).toUpperCase() + ";";
	}
	
	function astralReplacer(c){
		// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
		var high = c.charCodeAt(0);
		var low  = c.charCodeAt(1);
		var codePoint = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000;
		return "&#x" + codePoint.toString(16).toUpperCase() + ";";
	}
	
	function getInverse(inverse, re){
		function func(name){
			return inverse[name];
		}
	
		return function(data){
			return data
					.replace(re, func)
					.replace(re_astralSymbols, astralReplacer)
					.replace(re_nonASCII, singleCharReplacer);
		};
	}
	
	var re_xmlChars = getInverseReplacer(inverseXML);
	
	function escapeXML(data){
		return data
				.replace(re_xmlChars, singleCharReplacer)
				.replace(re_astralSymbols, astralReplacer)
				.replace(re_nonASCII, singleCharReplacer);
	}
	
	exports.escape = escapeXML;
	
})
/** END DEFINE BLOCK for entities@1.1.1/lib/encode.js **/


/** START DEFINE BLOCK for entities@1.1.1/lib/decode.js **/
jupyter.define('entities@1.1.1/lib/decode.js', function (module, exports, __jupyter_require__) {
	var entityMap = __jupyter_require__('entities@1.1.1/maps/entities.json'),
	    legacyMap = __jupyter_require__('entities@1.1.1/maps/legacy.json'),
	    xmlMap    = __jupyter_require__('entities@1.1.1/maps/xml.json'),
	    decodeCodePoint = __jupyter_require__('entities@1.1.1/lib/decode_codepoint.js');
	
	var decodeXMLStrict  = getStrictDecoder(xmlMap),
	    decodeHTMLStrict = getStrictDecoder(entityMap);
	
	function getStrictDecoder(map){
		var keys = Object.keys(map).join("|"),
		    replace = getReplacer(map);
	
		keys += "|#[xX][\\da-fA-F]+|#\\d+";
	
		var re = new RegExp("&(?:" + keys + ");", "g");
	
		return function(str){
			return String(str).replace(re, replace);
		};
	}
	
	var decodeHTML = (function(){
		var legacy = Object.keys(legacyMap)
			.sort(sorter);
	
		var keys = Object.keys(entityMap)
			.sort(sorter);
	
		for(var i = 0, j = 0; i < keys.length; i++){
			if(legacy[j] === keys[i]){
				keys[i] += ";?";
				j++;
			} else {
				keys[i] += ";";
			}
		}
	
		var re = new RegExp("&(?:" + keys.join("|") + "|#[xX][\\da-fA-F]+;?|#\\d+;?)", "g"),
		    replace = getReplacer(entityMap);
	
		function replacer(str){
			if(str.substr(-1) !== ";") str += ";";
			return replace(str);
		}
	
		//TODO consider creating a merged map
		return function(str){
			return String(str).replace(re, replacer);
		};
	}());
	
	function sorter(a, b){
		return a < b ? 1 : -1;
	}
	
	function getReplacer(map){
		return function replace(str){
			if(str.charAt(1) === "#"){
				if(str.charAt(2) === "X" || str.charAt(2) === "x"){
					return decodeCodePoint(parseInt(str.substr(3), 16));
				}
				return decodeCodePoint(parseInt(str.substr(2), 10));
			}
			return map[str.slice(1, -1)];
		};
	}
	
	module.exports = {
		XML: decodeXMLStrict,
		HTML: decodeHTML,
		HTMLStrict: decodeHTMLStrict
	};
})
/** END DEFINE BLOCK for entities@1.1.1/lib/decode.js **/


/** START DEFINE BLOCK for domutils@1.5.1/lib/traversal.js **/
jupyter.define('domutils@1.5.1/lib/traversal.js', function (module, exports, __jupyter_require__) {
	var getChildren = exports.getChildren = function(elem){
		return elem.children;
	};
	
	var getParent = exports.getParent = function(elem){
		return elem.parent;
	};
	
	exports.getSiblings = function(elem){
		var parent = getParent(elem);
		return parent ? getChildren(parent) : [elem];
	};
	
	exports.getAttributeValue = function(elem, name){
		return elem.attribs && elem.attribs[name];
	};
	
	exports.hasAttrib = function(elem, name){
		return !!elem.attribs && hasOwnProperty.call(elem.attribs, name);
	};
	
	exports.getName = function(elem){
		return elem.name;
	};
	
})
/** END DEFINE BLOCK for domutils@1.5.1/lib/traversal.js **/


/** START DEFINE BLOCK for domutils@1.5.1/lib/manipulation.js **/
jupyter.define('domutils@1.5.1/lib/manipulation.js', function (module, exports, __jupyter_require__) {
	exports.removeElement = function(elem){
		if(elem.prev) elem.prev.next = elem.next;
		if(elem.next) elem.next.prev = elem.prev;
	
		if(elem.parent){
			var childs = elem.parent.children;
			childs.splice(childs.lastIndexOf(elem), 1);
		}
	};
	
	exports.replaceElement = function(elem, replacement){
		var prev = replacement.prev = elem.prev;
		if(prev){
			prev.next = replacement;
		}
	
		var next = replacement.next = elem.next;
		if(next){
			next.prev = replacement;
		}
	
		var parent = replacement.parent = elem.parent;
		if(parent){
			var childs = parent.children;
			childs[childs.lastIndexOf(elem)] = replacement;
		}
	};
	
	exports.appendChild = function(elem, child){
		child.parent = elem;
	
		if(elem.children.push(child) !== 1){
			var sibling = elem.children[elem.children.length - 2];
			sibling.next = child;
			child.prev = sibling;
			child.next = null;
		}
	};
	
	exports.append = function(elem, next){
		var parent = elem.parent,
			currNext = elem.next;
	
		next.next = currNext;
		next.prev = elem;
		elem.next = next;
		next.parent = parent;
	
		if(currNext){
			currNext.prev = next;
			if(parent){
				var childs = parent.children;
				childs.splice(childs.lastIndexOf(currNext), 0, next);
			}
		} else if(parent){
			parent.children.push(next);
		}
	};
	
	exports.prepend = function(elem, prev){
		var parent = elem.parent;
		if(parent){
			var childs = parent.children;
			childs.splice(childs.lastIndexOf(elem), 0, prev);
		}
	
		if(elem.prev){
			elem.prev.next = prev;
		}
		
		prev.parent = parent;
		prev.prev = elem.prev;
		prev.next = elem;
		elem.prev = prev;
	};
	
	
	
})
/** END DEFINE BLOCK for domutils@1.5.1/lib/manipulation.js **/


/** START DEFINE BLOCK for domutils@1.5.1/lib/querying.js **/
jupyter.define('domutils@1.5.1/lib/querying.js', function (module, exports, __jupyter_require__) {
	var isTag = __jupyter_require__('domelementtype@1/index.js').isTag;
	
	module.exports = {
		filter: filter,
		find: find,
		findOneChild: findOneChild,
		findOne: findOne,
		existsOne: existsOne,
		findAll: findAll
	};
	
	function filter(test, element, recurse, limit){
		if(!Array.isArray(element)) element = [element];
	
		if(typeof limit !== "number" || !isFinite(limit)){
			limit = Infinity;
		}
		return find(test, element, recurse !== false, limit);
	}
	
	function find(test, elems, recurse, limit){
		var result = [], childs;
	
		for(var i = 0, j = elems.length; i < j; i++){
			if(test(elems[i])){
				result.push(elems[i]);
				if(--limit <= 0) break;
			}
	
			childs = elems[i].children;
			if(recurse && childs && childs.length > 0){
				childs = find(test, childs, recurse, limit);
				result = result.concat(childs);
				limit -= childs.length;
				if(limit <= 0) break;
			}
		}
	
		return result;
	}
	
	function findOneChild(test, elems){
		for(var i = 0, l = elems.length; i < l; i++){
			if(test(elems[i])) return elems[i];
		}
	
		return null;
	}
	
	function findOne(test, elems){
		var elem = null;
	
		for(var i = 0, l = elems.length; i < l && !elem; i++){
			if(!isTag(elems[i])){
				continue;
			} else if(test(elems[i])){
				elem = elems[i];
			} else if(elems[i].children.length > 0){
				elem = findOne(test, elems[i].children);
			}
		}
	
		return elem;
	}
	
	function existsOne(test, elems){
		for(var i = 0, l = elems.length; i < l; i++){
			if(
				isTag(elems[i]) && (
					test(elems[i]) || (
						elems[i].children.length > 0 &&
						existsOne(test, elems[i].children)
					)
				)
			){
				return true;
			}
		}
	
		return false;
	}
	
	function findAll(test, elems){
		var result = [];
		for(var i = 0, j = elems.length; i < j; i++){
			if(!isTag(elems[i])) continue;
			if(test(elems[i])) result.push(elems[i]);
	
			if(elems[i].children.length > 0){
				result = result.concat(findAll(test, elems[i].children));
			}
		}
		return result;
	}
	
})
/** END DEFINE BLOCK for domutils@1.5.1/lib/querying.js **/


/** START DEFINE BLOCK for domutils@1.5.1/lib/legacy.js **/
jupyter.define('domutils@1.5.1/lib/legacy.js', function (module, exports, __jupyter_require__) {
	var ElementType = __jupyter_require__('domelementtype@1/index.js');
	var isTag = exports.isTag = ElementType.isTag;
	
	exports.testElement = function(options, element){
		for(var key in options){
			if(!options.hasOwnProperty(key));
			else if(key === "tag_name"){
				if(!isTag(element) || !options.tag_name(element.name)){
					return false;
				}
			} else if(key === "tag_type"){
				if(!options.tag_type(element.type)) return false;
			} else if(key === "tag_contains"){
				if(isTag(element) || !options.tag_contains(element.data)){
					return false;
				}
			} else if(!element.attribs || !options[key](element.attribs[key])){
				return false;
			}
		}
		return true;
	};
	
	var Checks = {
		tag_name: function(name){
			if(typeof name === "function"){
				return function(elem){ return isTag(elem) && name(elem.name); };
			} else if(name === "*"){
				return isTag;
			} else {
				return function(elem){ return isTag(elem) && elem.name === name; };
			}
		},
		tag_type: function(type){
			if(typeof type === "function"){
				return function(elem){ return type(elem.type); };
			} else {
				return function(elem){ return elem.type === type; };
			}
		},
		tag_contains: function(data){
			if(typeof data === "function"){
				return function(elem){ return !isTag(elem) && data(elem.data); };
			} else {
				return function(elem){ return !isTag(elem) && elem.data === data; };
			}
		}
	};
	
	function getAttribCheck(attrib, value){
		if(typeof value === "function"){
			return function(elem){ return elem.attribs && value(elem.attribs[attrib]); };
		} else {
			return function(elem){ return elem.attribs && elem.attribs[attrib] === value; };
		}
	}
	
	function combineFuncs(a, b){
		return function(elem){
			return a(elem) || b(elem);
		};
	}
	
	exports.getElements = function(options, element, recurse, limit){
		var funcs = Object.keys(options).map(function(key){
			var value = options[key];
			return key in Checks ? Checks[key](value) : getAttribCheck(key, value);
		});
	
		return funcs.length === 0 ? [] : this.filter(
			funcs.reduce(combineFuncs),
			element, recurse, limit
		);
	};
	
	exports.getElementById = function(id, element, recurse){
		if(!Array.isArray(element)) element = [element];
		return this.findOne(getAttribCheck("id", id), element, recurse !== false);
	};
	
	exports.getElementsByTagName = function(name, element, recurse, limit){
		return this.filter(Checks.tag_name(name), element, recurse, limit);
	};
	
	exports.getElementsByTagType = function(type, element, recurse, limit){
		return this.filter(Checks.tag_type(type), element, recurse, limit);
	};
	
})
/** END DEFINE BLOCK for domutils@1.5.1/lib/legacy.js **/


/** START DEFINE BLOCK for domutils@1.5.1/lib/helpers.js **/
jupyter.define('domutils@1.5.1/lib/helpers.js', function (module, exports, __jupyter_require__) {
	// removeSubsets
	// Given an array of nodes, remove any member that is contained by another.
	exports.removeSubsets = function(nodes) {
		var idx = nodes.length, node, ancestor, replace;
	
		// Check if each node (or one of its ancestors) is already contained in the
		// array.
		while (--idx > -1) {
			node = ancestor = nodes[idx];
	
			// Temporarily remove the node under consideration
			nodes[idx] = null;
			replace = true;
	
			while (ancestor) {
				if (nodes.indexOf(ancestor) > -1) {
					replace = false;
					nodes.splice(idx, 1);
					break;
				}
				ancestor = ancestor.parent;
			}
	
			// If the node has been found to be unique, re-insert it.
			if (replace) {
				nodes[idx] = node;
			}
		}
	
		return nodes;
	};
	
	// Source: http://dom.spec.whatwg.org/#dom-node-comparedocumentposition
	var POSITION = {
		DISCONNECTED: 1,
		PRECEDING: 2,
		FOLLOWING: 4,
		CONTAINS: 8,
		CONTAINED_BY: 16
	};
	
	// Compare the position of one node against another node in any other document.
	// The return value is a bitmask with the following values:
	//
	// document order:
	// > There is an ordering, document order, defined on all the nodes in the
	// > document corresponding to the order in which the first character of the
	// > XML representation of each node occurs in the XML representation of the
	// > document after expansion of general entities. Thus, the document element
	// > node will be the first node. Element nodes occur before their children.
	// > Thus, document order orders element nodes in order of the occurrence of
	// > their start-tag in the XML (after expansion of entities). The attribute
	// > nodes of an element occur after the element and before its children. The
	// > relative order of attribute nodes is implementation-dependent./
	// Source:
	// http://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-document-order
	//
	// @argument {Node} nodaA The first node to use in the comparison
	// @argument {Node} nodeB The second node to use in the comparison
	//
	// @return {Number} A bitmask describing the input nodes' relative position.
	//         See http://dom.spec.whatwg.org/#dom-node-comparedocumentposition for
	//         a description of these values.
	var comparePos = exports.compareDocumentPosition = function(nodeA, nodeB) {
		var aParents = [];
		var bParents = [];
		var current, sharedParent, siblings, aSibling, bSibling, idx;
	
		if (nodeA === nodeB) {
			return 0;
		}
	
		current = nodeA;
		while (current) {
			aParents.unshift(current);
			current = current.parent;
		}
		current = nodeB;
		while (current) {
			bParents.unshift(current);
			current = current.parent;
		}
	
		idx = 0;
		while (aParents[idx] === bParents[idx]) {
			idx++;
		}
	
		if (idx === 0) {
			return POSITION.DISCONNECTED;
		}
	
		sharedParent = aParents[idx - 1];
		siblings = sharedParent.children;
		aSibling = aParents[idx];
		bSibling = bParents[idx];
	
		if (siblings.indexOf(aSibling) > siblings.indexOf(bSibling)) {
			if (sharedParent === nodeB) {
				return POSITION.FOLLOWING | POSITION.CONTAINED_BY;
			}
			return POSITION.FOLLOWING;
		} else {
			if (sharedParent === nodeA) {
				return POSITION.PRECEDING | POSITION.CONTAINS;
			}
			return POSITION.PRECEDING;
		}
	};
	
	// Sort an array of nodes based on their relative position in the document and
	// remove any duplicate nodes. If the array contains nodes that do not belong
	// to the same document, sort order is unspecified.
	//
	// @argument {Array} nodes Array of DOM nodes
	//
	// @returns {Array} collection of unique nodes, sorted in document order
	exports.uniqueSort = function(nodes) {
		var idx = nodes.length, node, position;
	
		nodes = nodes.slice();
	
		while (--idx > -1) {
			node = nodes[idx];
			position = nodes.indexOf(node);
			if (position > -1 && position < idx) {
				nodes.splice(idx, 1);
			}
		}
		nodes.sort(function(a, b) {
			var relative = comparePos(a, b);
			if (relative & POSITION.PRECEDING) {
				return -1;
			} else if (relative & POSITION.FOLLOWING) {
				return 1;
			}
			return 0;
		});
	
		return nodes;
	};
	
})
/** END DEFINE BLOCK for domutils@1.5.1/lib/helpers.js **/


/** START DEFINE BLOCK for htmlparser2@3.9.2/lib/CollectingHandler.js **/
jupyter.define('htmlparser2@3.9.2/lib/CollectingHandler.js', function (module, exports, __jupyter_require__) {
	module.exports = CollectingHandler;
	
	function CollectingHandler(cbs){
		this._cbs = cbs || {};
		this.events = [];
	}
	
	var EVENTS = __jupyter_require__('htmlparser2@3.9.2/lib/index.js').EVENTS;
	Object.keys(EVENTS).forEach(function(name){
		if(EVENTS[name] === 0){
			name = "on" + name;
			CollectingHandler.prototype[name] = function(){
				this.events.push([name]);
				if(this._cbs[name]) this._cbs[name]();
			};
		} else if(EVENTS[name] === 1){
			name = "on" + name;
			CollectingHandler.prototype[name] = function(a){
				this.events.push([name, a]);
				if(this._cbs[name]) this._cbs[name](a);
			};
		} else if(EVENTS[name] === 2){
			name = "on" + name;
			CollectingHandler.prototype[name] = function(a, b){
				this.events.push([name, a, b]);
				if(this._cbs[name]) this._cbs[name](a, b);
			};
		} else {
			throw Error("wrong number of arguments");
		}
	});
	
	CollectingHandler.prototype.onreset = function(){
		this.events = [];
		if(this._cbs.onreset) this._cbs.onreset();
	};
	
	CollectingHandler.prototype.restart = function(){
		if(this._cbs.onreset) this._cbs.onreset();
	
		for(var i = 0, len = this.events.length; i < len; i++){
			if(this._cbs[this.events[i][0]]){
	
				var num = this.events[i].length;
	
				if(num === 1){
					this._cbs[this.events[i][0]]();
				} else if(num === 2){
					this._cbs[this.events[i][0]](this.events[i][1]);
				} else {
					this._cbs[this.events[i][0]](this.events[i][1], this.events[i][2]);
				}
			}
		}
	};
	
})
/** END DEFINE BLOCK for htmlparser2@3.9.2/lib/CollectingHandler.js **/


/** START DEFINE BLOCK for xtend@4.0.1/immutable.js **/
jupyter.define('xtend@4.0.1/immutable.js', function (module, exports, __jupyter_require__) {
	module.exports = extend
	
	var hasOwnProperty = Object.prototype.hasOwnProperty;
	
	function extend() {
	    var target = {}
	
	    for (var i = 0; i < arguments.length; i++) {
	        var source = arguments[i]
	
	        for (var key in source) {
	            if (hasOwnProperty.call(source, key)) {
	                target[key] = source[key]
	            }
	        }
	    }
	
	    return target
	}
	
})
/** END DEFINE BLOCK for xtend@4.0.1/immutable.js **/


/** START DEFINE BLOCK for regexp-quote@0.0.0/regexp-quote.js **/
jupyter.define('regexp-quote@0.0.0/regexp-quote.js', function (module, exports, __jupyter_require__) {
	module.exports = function (string) {
	  return string.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&")
	}
	
})
/** END DEFINE BLOCK for regexp-quote@0.0.0/regexp-quote.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/running/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/running/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var console_1 = __jupyter_require__('jupyterlab@0.15.1/lib/console/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var services_1 = __jupyter_require__('jupyterlab@0.15.1/lib/services/index.js');
	var terminal_1 = __jupyter_require__('jupyterlab@0.15.1/lib/terminal/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/running/index.js');
	/**
	 * The default running sessions extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.running-sessions',
	    requires: [services_1.IServiceManager, instancerestorer_1.IInstanceRestorer],
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the running plugin.
	 */
	function activate(app, services, restorer) {
	    var running = new _1.RunningSessions({ manager: services });
	    running.id = 'jp-running-sessions';
	    running.title.label = 'Running';
	    // Let the application restorer track the running panel for restoration of
	    // application state (e.g. setting the running panel as the current side bar
	    // widget).
	    restorer.add(running, 'running-sessions');
	    running.sessionOpenRequested.connect(function (sender, model) {
	        var path = model.notebook.path;
	        var name = path.split('/').pop();
	        if (_1.CONSOLE_REGEX.test(name)) {
	            app.commands.execute(console_1.CommandIDs.open, { id: model.id });
	        }
	        else {
	            app.commands.execute(filebrowser_1.CommandIDs.open, { path: path });
	        }
	    });
	    running.terminalOpenRequested.connect(function (sender, model) {
	        app.commands.execute(terminal_1.CommandIDs.open, { name: model.name });
	    });
	    // Rank has been chosen somewhat arbitrarily to give priority to the running
	    // sessions widget in the sidebar.
	    app.shell.addToLeftArea(running, { rank: 50 });
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/running/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/running/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/running/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	var query_1 = __jupyter_require__('phosphor@^0.7.0/lib/dom/query.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var dom_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/dom.js');
	/**
	 * The class name added to a running widget.
	 */
	var RUNNING_CLASS = 'jp-RunningSessions';
	/**
	 * The class name added to a running widget header.
	 */
	var HEADER_CLASS = 'jp-RunningSessions-header';
	/**
	 * The class name added to a running widget header refresh button.
	 */
	var REFRESH_CLASS = 'jp-RunningSessions-headerRefresh';
	var MATERIAL_CLASS = 'jp-MaterialIcon';
	/**
	 * The class name added to the running terminal sessions section.
	 */
	var SECTION_CLASS = 'jp-RunningSessions-section';
	/**
	 * The class name added to the running terminal sessions section.
	 */
	var TERMINALS_CLASS = 'jp-RunningSessions-terminalSection';
	/**
	 * The class name added to the running kernel sessions section.
	 */
	var SESSIONS_CLASS = 'jp-RunningSessions-sessionsSection';
	/**
	 * The class name added to the running sessions section header.
	 */
	var SECTION_HEADER_CLASS = 'jp-RunningSessions-sectionHeader';
	/**
	 * The class name added to a section container.
	 */
	var CONTAINER_CLASS = 'jp-RunningSessions-sectionContainer';
	/**
	 * The class name added to the running kernel sessions section list.
	 */
	var LIST_CLASS = 'jp-RunningSessions-sectionList';
	/**
	 * The class name added to the running sessions items.
	 */
	var ITEM_CLASS = 'jp-RunningSessions-item';
	/**
	 * The class name added to a running session item icon.
	 */
	var ITEM_ICON_CLASS = 'jp-RunningSessions-itemIcon';
	/**
	 * The class name added to a running session item label.
	 */
	var ITEM_LABEL_CLASS = 'jp-RunningSessions-itemLabel';
	/**
	 * The class name added to a running session item shutdown button.
	 */
	var SHUTDOWN_BUTTON_CLASS = 'jp-RunningSessions-itemShutdown';
	/**
	 * The class name added to a notebook icon.
	 */
	var NOTEBOOK_ICON_CLASS = 'jp-mod-notebook';
	/**
	 * The class name added to a console icon.
	 */
	var CONSOLE_ICON_CLASS = 'jp-mod-console';
	/**
	 * The class name added to a file icon.
	 */
	var FILE_ICON_CLASS = 'jp-mod-file';
	/**
	 * The class name added to a terminal icon.
	 */
	var TERMINAL_ICON_CLASS = 'jp-mod-terminal';
	/**
	 * A regex for console names.
	 */
	exports.CONSOLE_REGEX = /^console-(\d)+-[0-9a-f]+$/;
	/**
	 * A class that exposes the running terminal and kernel sessions.
	 */
	var RunningSessions = (function (_super) {
	    __extends(RunningSessions, _super);
	    /**
	     * Construct a new running widget.
	     */
	    function RunningSessions(options) {
	        _super.call(this, {
	            node: (options.renderer || RunningSessions.defaultRenderer).createNode()
	        });
	        this._manager = null;
	        this._renderer = null;
	        this._runningSessions = [];
	        this._runningTerminals = [];
	        this._refreshId = -1;
	        var manager = this._manager = options.manager;
	        this._renderer = options.renderer || RunningSessions.defaultRenderer;
	        this.addClass(RUNNING_CLASS);
	        // Populate the terminals section.
	        if (manager.terminals.isAvailable()) {
	            var termNode = dom_1.findElement(this.node, TERMINALS_CLASS);
	            var termHeader = this._renderer.createTerminalHeaderNode();
	            termHeader.className = SECTION_HEADER_CLASS;
	            termNode.appendChild(termHeader);
	            var termContainer = document.createElement('div');
	            termContainer.className = CONTAINER_CLASS;
	            var termList = document.createElement('ul');
	            termList.className = LIST_CLASS;
	            termContainer.appendChild(termList);
	            termNode.appendChild(termContainer);
	            manager.terminals.runningChanged.connect(this._onTerminalsChanged, this);
	        }
	        // Populate the sessions section.
	        var sessionNode = dom_1.findElement(this.node, SESSIONS_CLASS);
	        var sessionHeader = this._renderer.createSessionHeaderNode();
	        sessionHeader.className = SECTION_HEADER_CLASS;
	        sessionNode.appendChild(sessionHeader);
	        var sessionContainer = document.createElement('div');
	        sessionContainer.className = CONTAINER_CLASS;
	        var sessionList = document.createElement('ul');
	        sessionList.className = LIST_CLASS;
	        sessionContainer.appendChild(sessionList);
	        sessionNode.appendChild(sessionContainer);
	        manager.sessions.runningChanged.connect(this._onSessionsChanged, this);
	    }
	    Object.defineProperty(RunningSessions.prototype, "renderer", {
	        /**
	         * The renderer used by the running sessions widget.
	         */
	        get: function () {
	            return this._renderer;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the widget.
	     */
	    RunningSessions.prototype.dispose = function () {
	        this._manager = null;
	        this._runningSessions = null;
	        this._runningTerminals = null;
	        this._renderer = null;
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Refresh the widget.
	     */
	    RunningSessions.prototype.refresh = function () {
	        var terminals = this._manager.terminals;
	        var sessions = this._manager.sessions;
	        clearTimeout(this._refreshId);
	        var promises = [];
	        if (terminals.isAvailable()) {
	            promises.push(terminals.refreshRunning());
	        }
	        promises.push(sessions.refreshRunning());
	        return Promise.all(promises).then(function () { return void 0; });
	    };
	    /**
	     * Handle the DOM events for the widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the widget's DOM nodes. It should
	     * not be called directly by user code.
	     */
	    RunningSessions.prototype.handleEvent = function (event) {
	        if (event.type === 'click') {
	            this._evtClick(event);
	        }
	    };
	    /**
	     * A message handler invoked on an `'after-attach'` message.
	     */
	    RunningSessions.prototype.onAfterAttach = function (msg) {
	        this.node.addEventListener('click', this);
	    };
	    /**
	     * A message handler invoked on a `'before-detach'` message.
	     */
	    RunningSessions.prototype.onBeforeDetach = function (msg) {
	        this.node.removeEventListener('click', this);
	    };
	    /**
	     * A message handler invoked on an `'update-request'` message.
	     */
	    RunningSessions.prototype.onUpdateRequest = function (msg) {
	        // Fetch common variables.
	        var termSection = dom_1.findElement(this.node, TERMINALS_CLASS);
	        var termList = dom_1.findElement(termSection, LIST_CLASS);
	        var sessionSection = dom_1.findElement(this.node, SESSIONS_CLASS);
	        var sessionList = dom_1.findElement(sessionSection, LIST_CLASS);
	        var renderer = this._renderer;
	        var specs = this._manager.specs;
	        // Create a dummy div if terminals are not available.
	        termList = termList || document.createElement('div');
	        // Remove any excess item nodes.
	        while (termList.children.length > this._runningTerminals.length) {
	            termList.removeChild(termList.firstChild);
	        }
	        while (sessionList.children.length > this._runningSessions.length) {
	            sessionList.removeChild(sessionList.firstChild);
	        }
	        // Add any missing item nodes.
	        while (termList.children.length < this._runningTerminals.length) {
	            var node = renderer.createTerminalNode();
	            node.classList.add(ITEM_CLASS);
	            termList.appendChild(node);
	        }
	        while (sessionList.children.length < this._runningSessions.length) {
	            var node = renderer.createSessionNode();
	            node.classList.add(ITEM_CLASS);
	            sessionList.appendChild(node);
	        }
	        // Populate the nodes.
	        for (var i = 0; i < this._runningTerminals.length; i++) {
	            var node = termList.children[i];
	            renderer.updateTerminalNode(node, this._runningTerminals[i]);
	        }
	        for (var i = 0; i < this._runningSessions.length; i++) {
	            var node = sessionList.children[i];
	            var model = this._runningSessions[i];
	            var kernelName = model.kernel.name;
	            if (specs) {
	                kernelName = specs.kernelspecs[kernelName].display_name;
	            }
	            renderer.updateSessionNode(node, model, kernelName);
	        }
	    };
	    /**
	     * Handle the `'click'` event for the widget.
	     *
	     * #### Notes
	     * This listener is attached to the document node.
	     */
	    RunningSessions.prototype._evtClick = function (event) {
	        // Fetch common variables.
	        var termSection = dom_1.findElement(this.node, TERMINALS_CLASS);
	        var termList = dom_1.findElement(termSection, LIST_CLASS);
	        var sessionSection = dom_1.findElement(this.node, SESSIONS_CLASS);
	        var sessionList = dom_1.findElement(sessionSection, LIST_CLASS);
	        var refresh = dom_1.findElement(this.node, REFRESH_CLASS);
	        var renderer = this._renderer;
	        var clientX = event.clientX;
	        var clientY = event.clientY;
	        // Check for a refresh.
	        if (query_1.hitTest(refresh, clientX, clientY)) {
	            return;
	        }
	        // Check for a terminal item click.
	        var index = dom_1.hitTestNodes(termList.children, clientX, clientY);
	        if (index !== -1) {
	            var node = termList.children[index];
	            var shutdown = renderer.getTerminalShutdown(node);
	            var model = this._runningTerminals[index];
	            if (query_1.hitTest(shutdown, clientX, clientY)) {
	                this._manager.terminals.shutdown(model.name);
	                return;
	            }
	            this.terminalOpenRequested.emit(model);
	        }
	        // Check for a session item click.
	        index = dom_1.hitTestNodes(sessionList.children, clientX, clientY);
	        if (index !== -1) {
	            var node = sessionList.children[index];
	            var shutdown = renderer.getSessionShutdown(node);
	            var model = this._runningSessions[index];
	            if (query_1.hitTest(shutdown, clientX, clientY)) {
	                this._manager.sessions.shutdown(model.id);
	                return;
	            }
	            this.sessionOpenRequested.emit(model);
	        }
	    };
	    /**
	     * Handle a change to the running sessions.
	     */
	    RunningSessions.prototype._onSessionsChanged = function (sender, models) {
	        // Strip out non-file backed sessions.
	        this._runningSessions = [];
	        for (var _i = 0, models_1 = models; _i < models_1.length; _i++) {
	            var session = models_1[_i];
	            var name_1 = session.notebook.path.split('/').pop();
	            if (name_1.indexOf('.') !== -1 || exports.CONSOLE_REGEX.test(name_1)) {
	                this._runningSessions.push(session);
	            }
	        }
	        this.update();
	    };
	    /**
	     * Handle a change to the running terminals.
	     */
	    RunningSessions.prototype._onTerminalsChanged = function (sender, models) {
	        this._runningTerminals = models;
	        this.update();
	    };
	    return RunningSessions;
	}(widget_1.Widget));
	exports.RunningSessions = RunningSessions;
	// Define the signals for the `RunningSessions` class.
	signaling_1.defineSignal(RunningSessions.prototype, 'sessionOpenRequested');
	signaling_1.defineSignal(RunningSessions.prototype, 'terminalOpenRequested');
	/**
	 * The namespace for the `RunningSessions` class statics.
	 */
	var RunningSessions;
	(function (RunningSessions) {
	    /**
	     * The default implementation of `IRenderer`.
	     */
	    var Renderer = (function () {
	        function Renderer() {
	        }
	        /**
	         * Create the root node for the running sessions widget.
	         */
	        Renderer.prototype.createNode = function () {
	            var node = document.createElement('div');
	            var header = document.createElement('div');
	            header.className = HEADER_CLASS;
	            var terminals = document.createElement('div');
	            terminals.className = SECTION_CLASS + " " + TERMINALS_CLASS;
	            var sessions = document.createElement('div');
	            sessions.className = SECTION_CLASS + " " + SESSIONS_CLASS;
	            var refresh = document.createElement('button');
	            refresh.className = REFRESH_CLASS;
	            header.appendChild(refresh);
	            node.appendChild(header);
	            node.appendChild(terminals);
	            node.appendChild(sessions);
	            return node;
	        };
	        /**
	         * Create a fully populated header node for the terminals section.
	         *
	         * @returns A new node for a running terminal session header.
	         */
	        Renderer.prototype.createTerminalHeaderNode = function () {
	            var node = document.createElement('div');
	            node.textContent = 'Terminal Sessions';
	            return node;
	        };
	        /**
	         * Create a fully populated header node for the sessions section.
	         *
	         * @returns A new node for a running kernel session header.
	         */
	        Renderer.prototype.createSessionHeaderNode = function () {
	            var node = document.createElement('div');
	            node.textContent = 'Kernel Sessions';
	            return node;
	        };
	        /**
	         * Create a node for a running terminal session item.
	         *
	         * @returns A new node for a running terminal session item.
	         *
	         * #### Notes
	         * The data in the node should be uninitialized.
	         *
	         * The `updateTerminalNode` method will be called for initialization.
	         */
	        Renderer.prototype.createTerminalNode = function () {
	            var node = document.createElement('li');
	            var icon = document.createElement('span');
	            icon.className = ITEM_ICON_CLASS + " " + TERMINAL_ICON_CLASS;
	            var label = document.createElement('span');
	            label.className = ITEM_LABEL_CLASS;
	            var shutdown = document.createElement('span');
	            shutdown.className = SHUTDOWN_BUTTON_CLASS;
	            shutdown.textContent = 'SHUTDOWN';
	            node.appendChild(icon);
	            node.appendChild(label);
	            node.appendChild(shutdown);
	            return node;
	        };
	        /**
	         * Create a node for a running kernel session item.
	         *
	         * @returns A new node for a running kernel session item.
	         *
	         * #### Notes
	         * The data in the node should be uninitialized.
	         *
	         * The `updateSessionNode` method will be called for initialization.
	         */
	        Renderer.prototype.createSessionNode = function () {
	            var node = document.createElement('li');
	            var icon = document.createElement('span');
	            icon.className = ITEM_ICON_CLASS;
	            var label = document.createElement('span');
	            label.className = ITEM_LABEL_CLASS;
	            var shutdown = document.createElement('span');
	            shutdown.className = SHUTDOWN_BUTTON_CLASS;
	            shutdown.textContent = 'SHUTDOWN';
	            node.appendChild(icon);
	            node.appendChild(label);
	            node.appendChild(shutdown);
	            return node;
	        };
	        /**
	         * Get the shutdown node for a terminal node.
	         *
	         * @param node - A node created by a call to `createTerminalNode`.
	         *
	         * @returns The node representing the shutdown option.
	         *
	         * #### Notes
	         * A click on this node is considered a shutdown request.
	         * A click anywhere else on the node is considered an open request.
	         */
	        Renderer.prototype.getTerminalShutdown = function (node) {
	            return dom_1.findElement(node, SHUTDOWN_BUTTON_CLASS);
	        };
	        /**
	         * Get the shutdown node for a session node.
	         *
	         * @param node - A node created by a call to `createSessionNode`.
	         *
	         * @returns The node representing the shutdown option.
	         *
	         * #### Notes
	         * A click on this node is considered a shutdown request.
	         * A click anywhere else on the node is considered an open request.
	         */
	        Renderer.prototype.getSessionShutdown = function (node) {
	            return dom_1.findElement(node, SHUTDOWN_BUTTON_CLASS);
	        };
	        /**
	         * Populate a node with running terminal session data.
	         *
	         * @param node - A node created by a call to `createTerminalNode`.
	         *
	         * @param models - The list of terminal session models.
	         *
	         * #### Notes
	         * This method should completely reset the state of the node to
	         * reflect the data for the session models.
	         */
	        Renderer.prototype.updateTerminalNode = function (node, model) {
	            var label = dom_1.findElement(node, ITEM_LABEL_CLASS);
	            label.textContent = "terminals/" + model.name;
	        };
	        /**
	         * Populate a node with running kernel session data.
	         *
	         * @param node - A node created by a call to `createSessionNode`.
	         *
	         * @param models - The list of kernel session models.
	         *
	         * @param kernelName - The kernel display name.
	         *
	         * #### Notes
	         * This method should completely reset the state of the node to
	         * reflect the data for the session models.
	         */
	        Renderer.prototype.updateSessionNode = function (node, model, kernelName) {
	            var icon = dom_1.findElement(node, ITEM_ICON_CLASS);
	            var path = model.notebook.path;
	            var name = path.split('/').pop();
	            if (name.indexOf('.ipynb') !== -1) {
	                icon.className = ITEM_ICON_CLASS + " " + NOTEBOOK_ICON_CLASS;
	            }
	            else if (exports.CONSOLE_REGEX.test(name)) {
	                icon.className = ITEM_ICON_CLASS + " " + CONSOLE_ICON_CLASS;
	                path = "Console " + name.match(exports.CONSOLE_REGEX)[1];
	            }
	            else {
	                icon.className = ITEM_ICON_CLASS + " " + FILE_ICON_CLASS;
	            }
	            var label = dom_1.findElement(node, ITEM_LABEL_CLASS);
	            label.textContent = path;
	            var title = (("Path: " + model.notebook.path + "\n") +
	                ("Kernel: " + kernelName));
	            label.title = title;
	        };
	        return Renderer;
	    }());
	    RunningSessions.Renderer = Renderer;
	    /**
	     * The default `Renderer` instance.
	     */
	    RunningSessions.defaultRenderer = new Renderer();
	})(RunningSessions = exports.RunningSessions || (exports.RunningSessions = {}));
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/running/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/services/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/services/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var services_1 = __jupyter_require__('@jupyterlab/services@^0.36.1/lib/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/services/index.js');
	/**
	 * The default services provider.
	 */
	var plugin = {
	    id: 'jupyter.services.services',
	    provides: _1.IServiceManager,
	    activate: function () { return new services_1.ServiceManager(); }
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/services/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/shortcuts/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/shortcuts/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var console_1 = __jupyter_require__('jupyterlab@0.15.1/lib/console/index.js');
	var editorwidget_1 = __jupyter_require__('jupyterlab@0.15.1/lib/editorwidget/index.js');
	var filebrowser_1 = __jupyter_require__('jupyterlab@0.15.1/lib/filebrowser/index.js');
	var help_1 = __jupyter_require__('jupyterlab@0.15.1/lib/help/index.js');
	var imagewidget_1 = __jupyter_require__('jupyterlab@0.15.1/lib/imagewidget/index.js');
	var inspector_1 = __jupyter_require__('jupyterlab@0.15.1/lib/inspector/index.js');
	var notebook_1 = __jupyter_require__('jupyterlab@0.15.1/lib/notebook/index.js');
	var tooltip_1 = __jupyter_require__('jupyterlab@0.15.1/lib/tooltip/index.js');
	/**
	 * The list of default application shortcuts.
	 *
	 * #### Notes
	 * When setting shortcut selectors, there are two concepts to consider:
	 * specificity and matchability. These two interact in sometimes
	 * counterintuitive ways. Keyboard events are triggered from an element and
	 * they propagate up the DOM until they reach the `documentElement` (`<body>`).
	 *
	 * When a registered shortcut sequence is fired, the shortcut manager checks
	 * the node that fired the event and each of its ancestors until a node matches
	 * one or more registered selectors. The *first* matching selector in the
	 * chain of ancestors will invoke the shortcut handler and the traversal will
	 * end at that point. If a node matches more than one selector, the handler for
	 * whichever selector is more *specific* fires.
	 * @see https://www.w3.org/TR/css3-selectors/#specificity
	 *
	 * The practical consequence of this is that a very broadly matching selector,
	 * e.g. `'*'` or `'div'` may match and therefore invoke a handler *before* a
	 * more specific selector. The most common pitfall is to use the universal
	 * (`'*'`) selector. For almost any use case where a global keyboard shortcut is
	 * required, using the `'body'` selector is more appropriate.
	 */
	var SHORTCUTS = [
	    {
	        command: commandpalette_1.CommandIDs.activate,
	        selector: 'body',
	        keys: ['Accel Shift P']
	    },
	    {
	        command: console_1.CommandIDs.run,
	        selector: '.jp-CodeConsole-prompt',
	        keys: ['Enter']
	    },
	    {
	        command: console_1.CommandIDs.runForced,
	        selector: '.jp-CodeConsole-prompt',
	        keys: ['Shift Enter']
	    },
	    {
	        command: console_1.CommandIDs.linebreak,
	        selector: '.jp-CodeConsole-prompt',
	        keys: ['Ctrl Enter']
	    },
	    {
	        command: editorwidget_1.CommandIDs.runCode,
	        selector: '.jp-EditorWidget',
	        keys: ['Shift Enter']
	    },
	    {
	        command: filebrowser_1.CommandIDs.toggleBrowser,
	        selector: 'body',
	        keys: ['Accel Shift F']
	    },
	    {
	        command: filebrowser_1.CommandIDs.newTextFile,
	        selector: 'body',
	        keys: ['Ctrl O']
	    },
	    {
	        command: filebrowser_1.CommandIDs.newNotebook,
	        selector: 'body',
	        keys: ['Ctrl Shift N']
	    },
	    {
	        command: filebrowser_1.CommandIDs.save,
	        selector: '.jp-Document',
	        keys: ['Accel S']
	    },
	    {
	        command: filebrowser_1.CommandIDs.close,
	        selector: '.jp-Document',
	        keys: ['Ctrl Q']
	    },
	    {
	        command: filebrowser_1.CommandIDs.closeAllFiles,
	        selector: '.jp-Document',
	        keys: ['Ctrl Shift Q']
	    },
	    {
	        command: help_1.CommandIDs.toggle,
	        selector: 'body',
	        keys: ['Accel Shift H']
	    },
	    {
	        command: imagewidget_1.CommandIDs.zoomIn,
	        selector: '.jp-ImageWidget',
	        keys: ['=']
	    },
	    {
	        command: imagewidget_1.CommandIDs.zoomOut,
	        selector: '.jp-ImageWidget',
	        keys: ['-']
	    },
	    {
	        command: imagewidget_1.CommandIDs.resetZoom,
	        selector: '.jp-ImageWidget',
	        keys: ['0']
	    },
	    {
	        command: inspector_1.CommandIDs.open,
	        selector: '.jp-CodeConsole-prompt',
	        keys: ['Accel I']
	    },
	    {
	        command: notebook_1.CommandIDs.runAndAdvance,
	        selector: '.jp-Notebook',
	        keys: ['Shift Enter']
	    },
	    {
	        command: notebook_1.CommandIDs.runAndInsert,
	        selector: '.jp-Notebook',
	        keys: ['Alt Enter']
	    },
	    {
	        command: notebook_1.CommandIDs.run,
	        selector: '.jp-Notebook',
	        keys: ['Ctrl Enter']
	    },
	    {
	        command: notebook_1.CommandIDs.interrupt,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['I', 'I']
	    },
	    {
	        command: notebook_1.CommandIDs.restart,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['0', '0']
	    },
	    {
	        command: notebook_1.CommandIDs.toCode,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['Y']
	    },
	    {
	        command: notebook_1.CommandIDs.toMarkdown,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['M']
	    },
	    {
	        command: notebook_1.CommandIDs.toRaw,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['R']
	    },
	    {
	        command: notebook_1.CommandIDs.deleteCell,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['D', 'D'],
	    },
	    {
	        command: notebook_1.CommandIDs.split,
	        selector: '.jp-Notebook.jp-mod-editMode',
	        keys: ['Ctrl Shift -'],
	    },
	    {
	        command: notebook_1.CommandIDs.merge,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['Shift M'],
	    },
	    {
	        command: notebook_1.CommandIDs.selectAbove,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['ArrowUp'],
	    },
	    {
	        command: notebook_1.CommandIDs.selectAbove,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['K'],
	    },
	    {
	        command: notebook_1.CommandIDs.selectBelow,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['ArrowDown'],
	    },
	    {
	        command: notebook_1.CommandIDs.selectBelow,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['J'],
	    },
	    {
	        command: notebook_1.CommandIDs.extendAbove,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['Shift ArrowUp'],
	    },
	    {
	        command: notebook_1.CommandIDs.extendAbove,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['Shift K'],
	    },
	    {
	        command: notebook_1.CommandIDs.extendBelow,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['Shift ArrowDown'],
	    },
	    {
	        command: notebook_1.CommandIDs.extendBelow,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['Shift J'],
	    },
	    {
	        command: notebook_1.CommandIDs.undo,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['Z'],
	    },
	    {
	        command: notebook_1.CommandIDs.redo,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['Shift Z'],
	    },
	    {
	        command: notebook_1.CommandIDs.cut,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['X']
	    },
	    {
	        command: notebook_1.CommandIDs.copy,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['C']
	    },
	    {
	        command: notebook_1.CommandIDs.paste,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['V']
	    },
	    {
	        command: notebook_1.CommandIDs.insertAbove,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['A']
	    },
	    {
	        command: notebook_1.CommandIDs.insertBelow,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['B']
	    },
	    {
	        command: notebook_1.CommandIDs.toggleLines,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['L']
	    },
	    {
	        command: notebook_1.CommandIDs.markdown1,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['1']
	    },
	    {
	        command: notebook_1.CommandIDs.markdown2,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['2']
	    },
	    {
	        command: notebook_1.CommandIDs.markdown3,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['3']
	    },
	    {
	        command: notebook_1.CommandIDs.markdown4,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['4']
	    },
	    {
	        command: notebook_1.CommandIDs.markdown5,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['5']
	    },
	    {
	        command: notebook_1.CommandIDs.markdown6,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['6']
	    },
	    {
	        command: notebook_1.CommandIDs.editMode,
	        selector: '.jp-Notebook.jp-mod-commandMode',
	        keys: ['Enter']
	    },
	    {
	        command: notebook_1.CommandIDs.commandMode,
	        selector: '.jp-Notebook.jp-mod-editMode',
	        keys: ['Escape']
	    },
	    {
	        command: notebook_1.CommandIDs.commandMode,
	        selector: '.jp-Notebook.jp-mod-editMode',
	        keys: ['Ctrl M']
	    },
	    {
	        command: tooltip_1.CommandIDs.launch,
	        selector: '.jp-Notebook',
	        keys: ['Shift Tab'],
	        args: { notebook: true }
	    },
	    {
	        command: tooltip_1.CommandIDs.launch,
	        selector: '.jp-ConsolePanel',
	        keys: ['Shift Tab'],
	        args: { notebook: false }
	    }
	];
	/**
	 * The default shortcuts extension.
	 */
	var plugin = {
	    id: 'jupyter.extensions.shortcuts',
	    activate: function (app) {
	        SHORTCUTS.forEach(function (shortcut) { app.keymap.addBinding(shortcut); });
	    },
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/shortcuts/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/tooltip/index.js **/
jupyter.define('jupyterlab@0.15.1/lib/tooltip/index.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	function __export(m) {
	    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
	}
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/tooltip/model.js'));
	__export(__jupyter_require__('jupyterlab@0.15.1/lib/tooltip/widget.js'));
	/**
	 * The command IDs used by the tooltip plugin.
	 */
	var CommandIDs;
	(function (CommandIDs) {
	    CommandIDs.launch = 'tooltip:launch';
	})(CommandIDs = exports.CommandIDs || (exports.CommandIDs = {}));
	;
	//# sourceMappingURL=index.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/tooltip/index.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/tooltip/model.js **/
jupyter.define('jupyterlab@0.15.1/lib/tooltip/model.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var signaling_1 = __jupyter_require__('phosphor@^0.7.0/lib/core/signaling.js');
	/**
	 * The data model for a tooltip widget.
	 */
	var TooltipModel = (function () {
	    /**
	     * Construct a new tooltip model.
	     */
	    function TooltipModel(options) {
	        this._content = null;
	        this._detailLevel = 0;
	        this._isDisposed = false;
	        this._pending = 0;
	        this.editor = options.editor;
	        this.kernel = options.kernel;
	        this.rendermime = options.rendermime;
	    }
	    Object.defineProperty(TooltipModel.prototype, "content", {
	        /**
	         * The tooltip model's content.
	         */
	        get: function () {
	            return this._content;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TooltipModel.prototype, "detailLevel", {
	        /**
	         * The detail level of API requests.
	         *
	         * #### Notes
	         * The only acceptable values are 0 and 1.
	         * @see http://jupyter-client.readthedocs.io/en/latest/messaging.html#introspection
	         */
	        get: function () {
	            return this._detailLevel;
	        },
	        set: function (level) {
	            if (this._detailLevel !== level) {
	                this._detailLevel = level;
	                this.fetch();
	            }
	        },
	        enumerable: true,
	        configurable: true
	    });
	    Object.defineProperty(TooltipModel.prototype, "isDisposed", {
	        /**
	         * Get whether the tooltip model is disposed.
	         *
	         * #### Notes
	         * This is a read-only property.
	         */
	        get: function () {
	            return this._isDisposed;
	        },
	        enumerable: true,
	        configurable: true
	    });
	    /**
	     * Dispose of the resources used by the model.
	     */
	    TooltipModel.prototype.dispose = function () {
	        if (this._isDisposed) {
	            return;
	        }
	        this._isDisposed = true;
	        this.disposed.emit(void 0);
	        signaling_1.clearSignalData(this);
	    };
	    /**
	     * Fetch a tooltip's content from the API server.
	     */
	    TooltipModel.prototype.fetch = function () {
	        var _this = this;
	        var editor = this.editor;
	        var kernel = this.kernel;
	        var code = editor.model.value.text;
	        var position = editor.getCursorPosition();
	        var offset = editor.getOffsetAt(position);
	        // Clear hints if the new text value is empty or kernel is unavailable.
	        if (!code || !this.kernel) {
	            return;
	        }
	        var contents = {
	            code: code,
	            cursor_pos: offset,
	            detail_level: this._detailLevel
	        };
	        var pending = ++this._pending;
	        kernel.requestInspect(contents).then(function (msg) {
	            var value = msg.content;
	            // If model has been disposed, bail.
	            if (_this._isDisposed) {
	                return;
	            }
	            // If a newer text change has created a pending request, bail.
	            if (pending !== _this._pending) {
	                return;
	            }
	            // Hint request failures or negative results fail silently.
	            if (value.status !== 'ok' || !value.found) {
	                return;
	            }
	            // Set the content to a rendered widget.
	            _this._content = _this.rendermime.render({
	                bundle: value.data,
	                trusted: true
	            });
	            // Notify listeners of content change.
	            _this.contentChanged.emit(void 0);
	        });
	    };
	    return TooltipModel;
	}());
	exports.TooltipModel = TooltipModel;
	// Define the signals for the `TooltipModel` class.
	signaling_1.defineSignal(TooltipModel.prototype, 'contentChanged');
	signaling_1.defineSignal(TooltipModel.prototype, 'disposed');
	//# sourceMappingURL=model.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/tooltip/model.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/tooltip/widget.js **/
jupyter.define('jupyterlab@0.15.1/lib/tooltip/widget.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var __extends = (this && this.__extends) || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
	var panel_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/panel.js');
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var hoverbox_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/hoverbox.js');
	/**
	 * The class name added to each tooltip.
	 */
	var TOOLTIP_CLASS = 'jp-Tooltip';
	/**
	 * The class added to widgets that have spawned a tooltip and anchor it.
	 */
	var ANCHOR_CLASS = 'jp-Tooltip-anchor';
	/**
	 * The minimum height of a tooltip widget.
	 */
	var MIN_HEIGHT = 20;
	/**
	 * The maximum height of a tooltip widget.
	 */
	var MAX_HEIGHT = 250;
	/**
	 * A flag to indicate that event handlers are caught in the capture phase.
	 */
	var USE_CAPTURE = true;
	/**
	 * A tooltip widget.
	 */
	var TooltipWidget = (function (_super) {
	    __extends(TooltipWidget, _super);
	    /**
	     * Instantiate a tooltip.
	     */
	    function TooltipWidget(options) {
	        _super.call(this);
	        this._content = null;
	        this.layout = new panel_1.PanelLayout();
	        this.anchor = options.anchor;
	        this.model = options.model;
	        this.model.contentChanged.connect(this._onContentChanged, this);
	        this.addClass(TOOLTIP_CLASS);
	        this.anchor.addClass(ANCHOR_CLASS);
	    }
	    /**
	     * Dispose of the resources held by the widget.
	     */
	    TooltipWidget.prototype.dispose = function () {
	        this.anchor.removeClass(ANCHOR_CLASS);
	        if (this._content) {
	            this._content.dispose();
	            this._content = null;
	        }
	        _super.prototype.dispose.call(this);
	    };
	    /**
	     * Handle the DOM events for the widget.
	     *
	     * @param event - The DOM event sent to the widget.
	     *
	     * #### Notes
	     * This method implements the DOM `EventListener` interface and is
	     * called in response to events on the dock panel's node. It should
	     * not be called directly by user code.
	     */
	    TooltipWidget.prototype.handleEvent = function (event) {
	        if (this.isHidden || this.isDisposed) {
	            return;
	        }
	        switch (event.type) {
	            case 'keydown':
	            case 'mousedown':
	                this._dismiss(event);
	                break;
	            case 'scroll':
	                this._evtScroll(event);
	                break;
	            default:
	                break;
	        }
	    };
	    /**
	     * Handle `'activate-request'` messages.
	     */
	    TooltipWidget.prototype.onActivateRequest = function (msg) {
	        this.node.tabIndex = -1;
	        this.node.focus();
	    };
	    /**
	     * Handle `'after-attach'` messages.
	     */
	    TooltipWidget.prototype.onAfterAttach = function (msg) {
	        document.addEventListener('keydown', this, USE_CAPTURE);
	        document.addEventListener('mousedown', this, USE_CAPTURE);
	        this.anchor.node.addEventListener('scroll', this, USE_CAPTURE);
	        this.model.fetch();
	    };
	    /**
	     * Handle `before_detach` messages for the widget.
	     */
	    TooltipWidget.prototype.onBeforeDetach = function (msg) {
	        document.removeEventListener('keydown', this, USE_CAPTURE);
	        document.removeEventListener('mousedown', this, USE_CAPTURE);
	        this.anchor.node.removeEventListener('scroll', this, USE_CAPTURE);
	    };
	    /**
	     * Handle `'update-request'` messages.
	     */
	    TooltipWidget.prototype.onUpdateRequest = function (msg) {
	        this._setGeometry();
	        _super.prototype.onUpdateRequest.call(this, msg);
	    };
	    /**
	     * Dismiss the tooltip if necessary.
	     */
	    TooltipWidget.prototype._dismiss = function (event) {
	        if (this.node.contains(event.target)) {
	            return;
	        }
	        this.dispose();
	    };
	    /**
	     * Handle scroll events for the widget
	     */
	    TooltipWidget.prototype._evtScroll = function (event) {
	        this.update();
	    };
	    /**
	     * Handle model content changes.
	     */
	    TooltipWidget.prototype._onContentChanged = function () {
	        if (this._content) {
	            this._content.dispose();
	        }
	        this._content = this.model.content;
	        if (this._content) {
	            this.layout.addWidget(this._content);
	        }
	        this.update();
	    };
	    /**
	     * Set the geometry of the tooltip widget.
	     */
	    TooltipWidget.prototype._setGeometry = function () {
	        var node = this.node;
	        var editor = this.model.editor;
	        var charWidth = editor.charWidth, lineHeight = editor.lineHeight;
	        var coords = editor.getCoordinate(editor.getCursorPosition());
	        // Calculate the geometry of the completer.
	        hoverbox_1.HoverBox.setGeometry({
	            charWidth: charWidth, coords: coords, lineHeight: lineHeight, node: node,
	            anchor: this.anchor.node,
	            anchorPoint: this.anchor.node.scrollTop,
	            cursor: { start: 0, end: 0 },
	            maxHeight: MAX_HEIGHT,
	            minHeight: MIN_HEIGHT
	        });
	    };
	    return TooltipWidget;
	}(widget_1.Widget));
	exports.TooltipWidget = TooltipWidget;
	//# sourceMappingURL=widget.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/tooltip/widget.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/statedb/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/statedb/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var index_1 = __jupyter_require__('jupyterlab@0.15.1/lib/statedb/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/statedb/index.js');
	/**
	 * The default state database for storing application state.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.services.statedb',
	    autoStart: true,
	    provides: index_1.IStateDB
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the state database.
	 */
	function activate(app) {
	    var state = new _1.StateDB({ namespace: app.info.namespace });
	    var version = app.info.version;
	    var command = _1.CommandIDs.clear;
	    var key = 'statedb:version';
	    var fetch = state.fetch(key);
	    var save = function () { return state.save(key, { version: version }); };
	    var reset = function () { return state.clear().then(save); };
	    var check = function (value) {
	        var old = value && value['version'];
	        if (!old || old !== version) {
	            console.log("Upgraded: " + (old || 'unknown') + " to " + version + "; Resetting DB.");
	            return reset();
	        }
	    };
	    app.commands.addCommand(command, {
	        label: 'Clear Application Restore State',
	        execute: function () { return state.clear(); }
	    });
	    return fetch.then(check, reset).then(function () { return state; });
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/statedb/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/terminal/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/terminal/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var instancetracker_1 = __jupyter_require__('jupyterlab@0.15.1/lib/common/instancetracker.js');
	var menu_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/menu.js');
	var commandpalette_1 = __jupyter_require__('jupyterlab@0.15.1/lib/commandpalette/index.js');
	var instancerestorer_1 = __jupyter_require__('jupyterlab@0.15.1/lib/instancerestorer/index.js');
	var mainmenu_1 = __jupyter_require__('jupyterlab@0.15.1/lib/mainmenu/index.js');
	var services_1 = __jupyter_require__('jupyterlab@0.15.1/lib/services/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/terminal/index.js');
	/**
	 * The class name for all main area landscape tab icons.
	 */
	var LANDSCAPE_ICON_CLASS = 'jp-MainAreaLandscapeIcon';
	/**
	 * The class name for the terminal icon in the default theme.
	 */
	var TERMINAL_ICON_CLASS = 'jp-ImageTerminal';
	/**
	 * The default terminal extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.terminal',
	    requires: [
	        services_1.IServiceManager, mainmenu_1.IMainMenu, commandpalette_1.ICommandPalette, instancerestorer_1.IInstanceRestorer
	    ],
	    autoStart: true
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the terminal plugin.
	 */
	function activate(app, services, mainMenu, palette, restorer) {
	    // Bail if there are no terminals available.
	    if (!services.terminals.isAvailable()) {
	        console.log('Disabling terminals plugin because they are not available on the server');
	        return;
	    }
	    var category = 'Terminal';
	    var namespace = 'terminal';
	    var tracker = new instancetracker_1.InstanceTracker({ namespace: namespace });
	    var commands = app.commands, keymap = app.keymap;
	    var options = {
	        background: 'black',
	        color: 'white',
	        fontSize: 13
	    };
	    // Handle state restoration.
	    restorer.restore(tracker, {
	        command: _1.CommandIDs.createNew,
	        args: function (widget) { return ({ name: widget.session.name }); },
	        name: function (widget) { return widget.session && widget.session.name; }
	    });
	    // Add terminal commands.
	    commands.addCommand(_1.CommandIDs.createNew, {
	        label: 'New Terminal',
	        caption: 'Start a new terminal session',
	        execute: function (args) {
	            var name = args ? args['name'] : '';
	            var promise;
	            if (name) {
	                promise = services.terminals.connectTo(name);
	            }
	            else {
	                promise = services.terminals.startNew();
	            }
	            return promise.then(function (session) {
	                return session.ready.then(function () {
	                    var term = new _1.TerminalWidget(options);
	                    term.session = session;
	                    term.title.closable = true;
	                    term.title.icon = LANDSCAPE_ICON_CLASS + " " + TERMINAL_ICON_CLASS;
	                    tracker.add(term);
	                    app.shell.addToMainArea(term);
	                    app.shell.activateMain(term.id);
	                });
	            });
	        }
	    });
	    commands.addCommand(_1.CommandIDs.increaseFont, {
	        label: 'Increase Terminal Font Size',
	        execute: function () {
	            if (options.fontSize < 72) {
	                options.fontSize++;
	                tracker.forEach(function (widget) { widget.fontSize = options.fontSize; });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.decreaseFont, {
	        label: 'Decrease Terminal Font Size',
	        execute: function () {
	            if (options.fontSize > 9) {
	                options.fontSize--;
	                tracker.forEach(function (widget) { widget.fontSize = options.fontSize; });
	            }
	        }
	    });
	    commands.addCommand(_1.CommandIDs.toggleTheme, {
	        label: 'Toggle Terminal Theme',
	        caption: 'Switch Terminal Background and Font Colors',
	        execute: function () {
	            if (options.background === 'black') {
	                options.background = 'white';
	                options.color = 'black';
	            }
	            else {
	                options.background = 'black';
	                options.color = 'white';
	            }
	            tracker.forEach(function (widget) {
	                widget.background = options.background;
	                widget.color = options.color;
	            });
	        }
	    });
	    commands.addCommand(_1.CommandIDs.open, {
	        execute: function (args) {
	            var name = args['name'];
	            // Check for a running terminal with the given name.
	            var widget = tracker.find(function (value) { return value.session.name === name; });
	            if (widget) {
	                app.shell.activateMain(widget.id);
	            }
	            else {
	                // Otherwise, create a new terminal with a given name.
	                return commands.execute(_1.CommandIDs.createNew, { name: name });
	            }
	        }
	    });
	    // Add command palette and menu items.
	    var menu = new menu_1.Menu({ commands: commands, keymap: keymap });
	    menu.title.label = category;
	    [
	        _1.CommandIDs.createNew,
	        _1.CommandIDs.increaseFont,
	        _1.CommandIDs.decreaseFont,
	        _1.CommandIDs.toggleTheme
	    ].forEach(function (command) {
	        palette.addItem({ command: command, category: category });
	        menu.addItem({ command: command });
	    });
	    mainMenu.addMenu(menu, { rank: 40 });
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/terminal/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/lib/tooltip/plugin.js **/
jupyter.define('jupyterlab@0.15.1/lib/tooltip/plugin.js', function (module, exports, __jupyter_require__) {
	// Copyright (c) Jupyter Development Team.
	// Distributed under the terms of the Modified BSD License.
	"use strict";
	var widget_1 = __jupyter_require__('phosphor@^0.7.0/lib/ui/widget.js');
	var console_1 = __jupyter_require__('jupyterlab@0.15.1/lib/console/index.js');
	var notebook_1 = __jupyter_require__('jupyterlab@0.15.1/lib/notebook/index.js');
	var _1 = __jupyter_require__('jupyterlab@0.15.1/lib/tooltip/index.js');
	/**
	 * The tooltip extension.
	 */
	var plugin = {
	    activate: activate,
	    id: 'jupyter.extensions.tooltip',
	    autoStart: true,
	    requires: [console_1.IConsoleTracker, notebook_1.INotebookTracker]
	};
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = plugin;
	/**
	 * Activate the tooltip.
	 */
	function activate(app, consoles, notebooks) {
	    var registry = app.commands;
	    var tooltip = null;
	    // Add tooltip launch command.
	    registry.addCommand(_1.CommandIDs.launch, {
	        execute: function (args) {
	            var notebook = args['notebook'];
	            var anchor = null;
	            var editor = null;
	            var kernel = null;
	            var rendermime = null;
	            var parent = null;
	            // If a tooltip is open, remove it.
	            if (tooltip) {
	                tooltip.model.dispose();
	                tooltip.dispose();
	                tooltip = null;
	            }
	            if (notebook) {
	                parent = notebooks.currentWidget;
	                if (parent) {
	                    anchor = parent.notebook;
	                    editor = parent.notebook.activeCell.editor;
	                    kernel = parent.kernel;
	                    rendermime = parent.rendermime;
	                }
	            }
	            else {
	                parent = consoles.currentWidget;
	                if (parent) {
	                    anchor = parent.console;
	                    editor = parent.console.prompt.editor;
	                    kernel = parent.console.session.kernel;
	                    rendermime = parent.console.rendermime;
	                }
	            }
	            // If all components necessary for rendering exist, create a tooltip.
	            var ready = !!editor && !!kernel && !!rendermime;
	            if (!ready) {
	                return;
	            }
	            var model = new _1.TooltipModel({ editor: editor, kernel: kernel, rendermime: rendermime });
	            tooltip = new _1.TooltipWidget({ anchor: anchor, model: model });
	            widget_1.Widget.attach(tooltip, document.body);
	            // Make sure the parent notebook/console still has the focus.
	            parent.activate();
	        }
	    });
	}
	//# sourceMappingURL=plugin.js.map
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/lib/tooltip/plugin.js **/


/** START DEFINE BLOCK for jupyterlab@0.15.1/package.json **/
jupyter.define('jupyterlab@0.15.1/package.json', function (module, exports, __jupyter_require__) {
	module.exports = {
		"name": "jupyterlab",
		"version": "0.15.1",
		"description": "A computational environment for Jupyter.",
		"directories": {
			"lib": "lib/"
		},
		"typings": "lib/index.d.ts",
		"dependencies": {
			"@jupyterlab/services": "^0.36.1",
			"ansi_up": "^1.3.0",
			"backbone": "^1.2.0",
			"codemirror": "^5.20.2",
			"d3-dsv": "^1.0.0",
			"diff-match-patch": "^1.0.0",
			"es6-promise": "^3.2.1",
			"less": "^2.7.1",
			"marked": "^0.3.5",
			"moment": "^2.11.2",
			"phosphor": "^0.7.0",
			"sanitize-html": "^1.12.0",
			"semver": "^5.3.0",
			"simulate-event": "^1.2.0",
			"xterm": "~2.0.1"
		},
		"devDependencies": {
			"@jupyterlab/extension-builder": "^0.9.0",
			"@types/d3-dsv": "^1.0.29",
			"@types/expect.js": "^0.3.29",
			"@types/marked": "0.0.28",
			"@types/mathjax": "0.0.31",
			"@types/mocha": "^2.2.32",
			"@types/node": "0.0.1",
			"@types/sanitize-html": "^1.13.31",
			"@types/semver": "^5.3.30",
			"concurrently": "^2.0.0",
			"css-loader": "^0.23.1",
			"expect.js": "^0.3.1",
			"file-loader": "^0.8.5",
			"font-awesome": "^4.6.3",
			"fs-extra": "^0.26.4",
			"istanbul-instrumenter-loader": "^0.1.3",
			"json-loader": "^0.5.4",
			"json-to-html": "^0.1.2",
			"karma": "^0.13.19",
			"karma-chrome-launcher": "^0.2.2",
			"karma-coverage": "^0.5.3",
			"karma-firefox-launcher": "^0.1.7",
			"karma-ie-launcher": "^0.2.0",
			"karma-mocha": "^0.2.1",
			"karma-mocha-reporter": "^1.1.5",
			"karma-remap-coverage": "^0.1.1",
			"karma-sourcemap-loader": "^0.3.7",
			"mocha": "^2.3.4",
			"raw-loader": "^0.5.1",
			"rimraf": "^2.5.0",
			"style-loader": "^0.13.0",
			"typedoc": "^0.5.0",
			"typescript": "~2.0.3",
			"url-loader": "^0.5.7",
			"watch": "^0.17.1",
			"webpack": "^1.12.11"
		},
		"scripts": {
			"build": "npm run build:src",
			"build:all": "npm run build:src && npm run build:serverextension",
			"build:examples": "node scripts/buildexamples.js",
			"build:src": "rimraf build && tsc --project src && node scripts/copyfiles.js",
			"build:test": "rimraf test/build && tsc --project test/src && webpack --config test/webpack.conf.js",
			"build:serverextension": "cd jupyterlab && rimraf build && tsc --project src && webpack",
			"clean": "rimraf docs && rimraf lib && rimraf test/build && rimraf test/coverage && rimraf jupyterlab/build",
			"clean:examples": "node scripts/cleanexamples.js",
			"clean:slate": "npm run clean && npm run clean:examples && rimraf jupyterlab/node_modules && rimraf node_modules && npm install",
			"docs": "typedoc --mode modules --module commonjs --excludeNotExported --target es5 --moduleResolution node --out docs/ src",
			"postinstall": "node scripts/dedupe.js",
			"preversion": "npm update && npm run postinstall && npm run clean && npm run build:all",
			"test": "npm run test:firefox",
			"test:chrome": "npm run build:test && cd test && python run-test.py --browsers=Chrome karma.conf.js",
			"test:coverage": "tsc --project test/src && webpack --config test/webpack-cov.conf.js && cd test && python run-test.py karma-cov.conf.js",
			"test:debug": "npm run build:test && cd test && python run-test.py  --browsers=Chrome --singleRun=false --debug=true karma.conf.js",
			"test:firefox": "npm run build:test && cd test && python run-test.py --browsers=Firefox karma.conf.js",
			"test:ie": "npm run build:test && cd test && python run-test.py  --browsers=IE karma.conf.js",
			"watch": "watch \"npm run build:all\" src --wait 10 --ignoreDotFiles",
			"watch:src": "watch \"npm run build\" src --wait 10 --ignoreDotFiles",
			"watch:test": "watch \"npm run build && npm test\" src test/src --wait 10 --ignoreDotFiles"
		},
		"repository": {
			"type": "git",
			"url": "https://github.com/jupyterlab/jupyterlab"
		},
		"keywords": [
			"jupyter",
			"jupyterlab"
		],
		"files": [
			"lib/*.css",
			"lib/*.d.ts",
			"lib/*.js",
			"lib/*.js.map",
			"lib/**/*.css",
			"lib/**/*.d.ts",
			"lib/**/*.js",
			"lib/**/*.js.map",
			"lib/**/*.svg",
			"lib/**/*.gif",
			"scripts/dedupe.js"
		],
		"author": "Project Jupyter",
		"license": "BSD-3-Clause",
		"bugs": {
			"url": "https://github.com/jupyterlab/jupyterlab/issues"
		},
		"homepage": "https://github.com/jupyterlab/jupyterlab"
	};
})
/** END DEFINE BLOCK for jupyterlab@0.15.1/package.json **/
