/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ 		}
/******/ 	};
/******/
/******/ 	// define __esModule on exports
/******/ 	__webpack_require__.r = function(exports) {
/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 		}
/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
/******/ 	};
/******/
/******/ 	// create a fake namespace object
/******/ 	// mode & 1: value is a module id, require it
/******/ 	// mode & 2: merge all properties of value into the ns
/******/ 	// mode & 4: return value when already ns object
/******/ 	// mode & 8|1: behave like require
/******/ 	__webpack_require__.t = function(value, mode) {
/******/ 		if(mode & 1) value = __webpack_require__(value);
/******/ 		if(mode & 8) return value;
/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ 		var ns = Object.create(null);
/******/ 		__webpack_require__.r(ns);
/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ 		return ns;
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 557);
/******/ })
/************************************************************************/
/******/ ({

/***/ 10:
/***/ (function(module, exports, __webpack_require__) {

try {
  var util = __webpack_require__(7);
  if (typeof util.inherits !== 'function') throw '';
  module.exports = util.inherits;
} catch (e) {
  module.exports = __webpack_require__(11);
}


/***/ }),

/***/ 108:
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global) {var scope = (typeof global !== "undefined" && global) ||
            (typeof self !== "undefined" && self) ||
            window;
var apply = Function.prototype.apply;

// DOM APIs, for completeness

exports.setTimeout = function() {
  return new Timeout(apply.call(setTimeout, scope, arguments), clearTimeout);
};
exports.setInterval = function() {
  return new Timeout(apply.call(setInterval, scope, 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(scope, 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
__webpack_require__(109);
// On some exotic environments, it's not clear which object `setimmediate` was
// able to install onto.  Search each possibility in the same order as the
// `setimmediate` library.
exports.setImmediate = (typeof self !== "undefined" && self.setImmediate) ||
                       (typeof global !== "undefined" && global.setImmediate) ||
                       (this && this.setImmediate);
exports.clearImmediate = (typeof self !== "undefined" && self.clearImmediate) ||
                         (typeof global !== "undefined" && global.clearImmediate) ||
                         (this && this.clearImmediate);

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(6)))

/***/ }),

/***/ 109:
/***/ (function(module, exports, __webpack_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(this, __webpack_require__(6), __webpack_require__(8)))

/***/ }),

/***/ 11:
/***/ (function(module, exports) {

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
  }
}


/***/ }),

/***/ 12:
/***/ (function(module, exports, __webpack_require__) {

"use strict";
/* WEBPACK VAR INJECTION */(function(global) {

var objectAssign = __webpack_require__(13);

// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js
// original notice:

/*!
 * The buffer module from node.js, for the browser.
 *
 * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
 * @license  MIT
 */
function compare(a, b) {
  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;
}
function isBuffer(b) {
  if (global.Buffer && typeof global.Buffer.isBuffer === 'function') {
    return global.Buffer.isBuffer(b);
  }
  return !!(b != null && b._isBuffer);
}

// based on node assert, original notice:
// NB: The URL to the CommonJS spec is kept just for tradition.
//     node-assert has evolved a lot since then, both in API and behavior.

// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// 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 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 util = __webpack_require__(7);
var hasOwn = Object.prototype.hasOwnProperty;
var pSlice = Array.prototype.slice;
var functionsHaveNames = (function () {
  return function foo() {}.name === 'foo';
}());
function pToString (obj) {
  return Object.prototype.toString.call(obj);
}
function isView(arrbuf) {
  if (isBuffer(arrbuf)) {
    return false;
  }
  if (typeof global.ArrayBuffer !== 'function') {
    return false;
  }
  if (typeof ArrayBuffer.isView === 'function') {
    return ArrayBuffer.isView(arrbuf);
  }
  if (!arrbuf) {
    return false;
  }
  if (arrbuf instanceof DataView) {
    return true;
  }
  if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) {
    return true;
  }
  return false;
}
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.

var assert = module.exports = ok;

// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
//                             actual: actual,
//                             expected: expected })

var regex = /\s*function\s+([^\(\s]*)\s*/;
// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js
function getName(func) {
  if (!util.isFunction(func)) {
    return;
  }
  if (functionsHaveNames) {
    return func.name;
  }
  var str = func.toString();
  var match = str.match(regex);
  return match && match[1];
}
assert.AssertionError = function AssertionError(options) {
  this.name = 'AssertionError';
  this.actual = options.actual;
  this.expected = options.expected;
  this.operator = options.operator;
  if (options.message) {
    this.message = options.message;
    this.generatedMessage = false;
  } else {
    this.message = getMessage(this);
    this.generatedMessage = true;
  }
  var stackStartFunction = options.stackStartFunction || fail;
  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, stackStartFunction);
  } else {
    // non v8 browsers so we can have a stacktrace
    var err = new Error();
    if (err.stack) {
      var out = err.stack;

      // try to strip useless frames
      var fn_name = getName(stackStartFunction);
      var idx = out.indexOf('\n' + fn_name);
      if (idx >= 0) {
        // once we have located the function frame
        // we need to strip out everything before it (and its line)
        var next_line = out.indexOf('\n', idx + 1);
        out = out.substring(next_line + 1);
      }

      this.stack = out;
    }
  }
};

// assert.AssertionError instanceof Error
util.inherits(assert.AssertionError, Error);

function truncate(s, n) {
  if (typeof s === 'string') {
    return s.length < n ? s : s.slice(0, n);
  } else {
    return s;
  }
}
function inspect(something) {
  if (functionsHaveNames || !util.isFunction(something)) {
    return util.inspect(something);
  }
  var rawname = getName(something);
  var name = rawname ? ': ' + rawname : '';
  return '[Function' +  name + ']';
}
function getMessage(self) {
  return truncate(inspect(self.actual), 128) + ' ' +
         self.operator + ' ' +
         truncate(inspect(self.expected), 128);
}

// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.

// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided.  All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.

function fail(actual, expected, message, operator, stackStartFunction) {
  throw new assert.AssertionError({
    message: message,
    actual: actual,
    expected: expected,
    operator: operator,
    stackStartFunction: stackStartFunction
  });
}

// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;

// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.

function ok(value, message) {
  if (!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;

// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);

assert.equal = function equal(actual, expected, message) {
  if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};

// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);

assert.notEqual = function notEqual(actual, expected, message) {
  if (actual == expected) {
    fail(actual, expected, message, '!=', assert.notEqual);
  }
};

// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);

assert.deepEqual = function deepEqual(actual, expected, message) {
  if (!_deepEqual(actual, expected, false)) {
    fail(actual, expected, message, 'deepEqual', assert.deepEqual);
  }
};

assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
  if (!_deepEqual(actual, expected, true)) {
    fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual);
  }
};

function _deepEqual(actual, expected, strict, memos) {
  // 7.1. All identical values are equivalent, as determined by ===.
  if (actual === expected) {
    return true;
  } else if (isBuffer(actual) && isBuffer(expected)) {
    return compare(actual, expected) === 0;

  // 7.2. If the expected value is a Date object, the actual value is
  // equivalent if it is also a Date object that refers to the same time.
  } else if (util.isDate(actual) && util.isDate(expected)) {
    return actual.getTime() === expected.getTime();

  // 7.3 If the expected value is a RegExp object, the actual value is
  // equivalent if it is also a RegExp object with the same source and
  // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
  } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
    return actual.source === expected.source &&
           actual.global === expected.global &&
           actual.multiline === expected.multiline &&
           actual.lastIndex === expected.lastIndex &&
           actual.ignoreCase === expected.ignoreCase;

  // 7.4. Other pairs that do not both pass typeof value == 'object',
  // equivalence is determined by ==.
  } else if ((actual === null || typeof actual !== 'object') &&
             (expected === null || typeof expected !== 'object')) {
    return strict ? actual === expected : actual == expected;

  // If both values are instances of typed arrays, wrap their underlying
  // ArrayBuffers in a Buffer each to increase performance
  // This optimization requires the arrays to have the same type as checked by
  // Object.prototype.toString (aka pToString). Never perform binary
  // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their
  // bit patterns are not identical.
  } else if (isView(actual) && isView(expected) &&
             pToString(actual) === pToString(expected) &&
             !(actual instanceof Float32Array ||
               actual instanceof Float64Array)) {
    return compare(new Uint8Array(actual.buffer),
                   new Uint8Array(expected.buffer)) === 0;

  // 7.5 For all other Object pairs, including Array objects, equivalence is
  // determined by having the same number of owned properties (as verified
  // with Object.prototype.hasOwnProperty.call), the same set of keys
  // (although not necessarily the same order), equivalent values for every
  // corresponding key, and an identical 'prototype' property. Note: this
  // accounts for both named and indexed properties on Arrays.
  } else if (isBuffer(actual) !== isBuffer(expected)) {
    return false;
  } else {
    memos = memos || {actual: [], expected: []};

    var actualIndex = memos.actual.indexOf(actual);
    if (actualIndex !== -1) {
      if (actualIndex === memos.expected.indexOf(expected)) {
        return true;
      }
    }

    memos.actual.push(actual);
    memos.expected.push(expected);

    return objEquiv(actual, expected, strict, memos);
  }
}

function isArguments(object) {
  return Object.prototype.toString.call(object) == '[object Arguments]';
}

function objEquiv(a, b, strict, actualVisitedObjects) {
  if (a === null || a === undefined || b === null || b === undefined)
    return false;
  // if one is a primitive, the other must be same
  if (util.isPrimitive(a) || util.isPrimitive(b))
    return a === b;
  if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))
    return false;
  var aIsArgs = isArguments(a);
  var bIsArgs = isArguments(b);
  if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
    return false;
  if (aIsArgs) {
    a = pSlice.call(a);
    b = pSlice.call(b);
    return _deepEqual(a, b, strict);
  }
  var ka = objectKeys(a);
  var kb = objectKeys(b);
  var key, i;
  // having the same number of owned properties (keys incorporates
  // hasOwnProperty)
  if (ka.length !== kb.length)
    return false;
  //the same set of keys (although not necessarily the same order),
  ka.sort();
  kb.sort();
  //~~~cheap key test
  for (i = ka.length - 1; i >= 0; i--) {
    if (ka[i] !== kb[i])
      return false;
  }
  //equivalent values for every corresponding key, and
  //~~~possibly expensive deep test
  for (i = ka.length - 1; i >= 0; i--) {
    key = ka[i];
    if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects))
      return false;
  }
  return true;
}

// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);

assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
  if (_deepEqual(actual, expected, false)) {
    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
  }
};

assert.notDeepStrictEqual = notDeepStrictEqual;
function notDeepStrictEqual(actual, expected, message) {
  if (_deepEqual(actual, expected, true)) {
    fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual);
  }
}


// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);

assert.strictEqual = function strictEqual(actual, expected, message) {
  if (actual !== expected) {
    fail(actual, expected, message, '===', assert.strictEqual);
  }
};

// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);

assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
  if (actual === expected) {
    fail(actual, expected, message, '!==', assert.notStrictEqual);
  }
};

function expectedException(actual, expected) {
  if (!actual || !expected) {
    return false;
  }

  if (Object.prototype.toString.call(expected) == '[object RegExp]') {
    return expected.test(actual);
  }

  try {
    if (actual instanceof expected) {
      return true;
    }
  } catch (e) {
    // Ignore.  The instanceof check doesn't work for arrow functions.
  }

  if (Error.isPrototypeOf(expected)) {
    return false;
  }

  return expected.call({}, actual) === true;
}

function _tryBlock(block) {
  var error;
  try {
    block();
  } catch (e) {
    error = e;
  }
  return error;
}

function _throws(shouldThrow, block, expected, message) {
  var actual;

  if (typeof block !== 'function') {
    throw new TypeError('"block" argument must be a function');
  }

  if (typeof expected === 'string') {
    message = expected;
    expected = null;
  }

  actual = _tryBlock(block);

  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
            (message ? ' ' + message : '.');

  if (shouldThrow && !actual) {
    fail(actual, expected, 'Missing expected exception' + message);
  }

  var userProvidedMessage = typeof message === 'string';
  var isUnwantedException = !shouldThrow && util.isError(actual);
  var isUnexpectedException = !shouldThrow && actual && !expected;

  if ((isUnwantedException &&
      userProvidedMessage &&
      expectedException(actual, expected)) ||
      isUnexpectedException) {
    fail(actual, expected, 'Got unwanted exception' + message);
  }

  if ((shouldThrow && actual && expected &&
      !expectedException(actual, expected)) || (!shouldThrow && actual)) {
    throw actual;
  }
}

// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);

assert.throws = function(block, /*optional*/error, /*optional*/message) {
  _throws(true, block, error, message);
};

// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
  _throws(false, block, error, message);
};

assert.ifError = function(err) { if (err) throw err; };

// Expose a strict only variant of assert
function strict(value, message) {
  if (!value) fail(value, true, message, '==', strict);
}
assert.strict = objectAssign(strict, assert, {
  equal: assert.strictEqual,
  deepEqual: assert.deepStrictEqual,
  notEqual: assert.notStrictEqual,
  notDeepEqual: assert.notDeepStrictEqual
});
assert.strict.strict = assert.strict;

var objectKeys = Object.keys || function (obj) {
  var keys = [];
  for (var key in obj) {
    if (hasOwn.call(obj, key)) keys.push(key);
  }
  return keys;
};

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(6)))

/***/ }),

/***/ 13:
/***/ (function(module, exports, __webpack_require__) {

"use strict";
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/


/* eslint-disable no-unused-vars */
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;

function toObject(val) {
	if (val === null || val === undefined) {
		throw new TypeError('Object.assign cannot be called with null or undefined');
	}

	return Object(val);
}

function shouldUseNative() {
	try {
		if (!Object.assign) {
			return false;
		}

		// Detect buggy property enumeration order in older V8 versions.

		// https://bugs.chromium.org/p/v8/issues/detail?id=4118
		var test1 = new String('abc');  // eslint-disable-line no-new-wrappers
		test1[5] = 'de';
		if (Object.getOwnPropertyNames(test1)[0] === '5') {
			return false;
		}

		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
		var test2 = {};
		for (var i = 0; i < 10; i++) {
			test2['_' + String.fromCharCode(i)] = i;
		}
		var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
			return test2[n];
		});
		if (order2.join('') !== '0123456789') {
			return false;
		}

		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
		var test3 = {};
		'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
			test3[letter] = letter;
		});
		if (Object.keys(Object.assign({}, test3)).join('') !==
				'abcdefghijklmnopqrst') {
			return false;
		}

		return true;
	} catch (err) {
		// We don't expect any of the above to throw, but better to be safe.
		return false;
	}
}

module.exports = shouldUseNative() ? Object.assign : function (target, source) {
	var from;
	var to = toObject(target);
	var symbols;

	for (var s = 1; s < arguments.length; s++) {
		from = Object(arguments[s]);

		for (var key in from) {
			if (hasOwnProperty.call(from, key)) {
				to[key] = from[key];
			}
		}

		if (getOwnPropertySymbols) {
			symbols = getOwnPropertySymbols(from);
			for (var i = 0; i < symbols.length; i++) {
				if (propIsEnumerable.call(from, symbols[i])) {
					to[symbols[i]] = from[symbols[i]];
				}
			}
		}
	}

	return to;
};


/***/ }),

/***/ 5:
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global) {/*global window, global*/
var util = __webpack_require__(7)
var assert = __webpack_require__(12)
function now() { return new Date().getTime() }

var slice = Array.prototype.slice
var console
var times = {}

if (typeof global !== "undefined" && global.console) {
    console = global.console
} else if (typeof window !== "undefined" && window.console) {
    console = window.console
} else {
    console = {}
}

var functions = [
    [log, "log"],
    [info, "info"],
    [warn, "warn"],
    [error, "error"],
    [time, "time"],
    [timeEnd, "timeEnd"],
    [trace, "trace"],
    [dir, "dir"],
    [consoleAssert, "assert"]
]

for (var i = 0; i < functions.length; i++) {
    var tuple = functions[i]
    var f = tuple[0]
    var name = tuple[1]

    if (!console[name]) {
        console[name] = f
    }
}

module.exports = console

function log() {}

function info() {
    console.log.apply(console, arguments)
}

function warn() {
    console.log.apply(console, arguments)
}

function error() {
    console.warn.apply(console, arguments)
}

function time(label) {
    times[label] = now()
}

function timeEnd(label) {
    var time = times[label]
    if (!time) {
        throw new Error("No such label: " + label)
    }

    delete times[label]
    var duration = now() - time
    console.log(label + ": " + duration + "ms")
}

function trace() {
    var err = new Error()
    err.name = "Trace"
    err.message = util.format.apply(null, arguments)
    console.error(err.stack)
}

function dir(object) {
    console.log(util.inspect(object) + "\n")
}

function consoleAssert(expression) {
    if (!expression) {
        var arr = slice.call(arguments, 1)
        assert.ok(false, util.format.apply(null, arr))
    }
}

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(6)))

/***/ }),

/***/ 557:
/***/ (function(module, exports, __webpack_require__) {

/**
 * ---------------------------------------------------------------------
 * GLPI - Gestionnaire Libre de Parc Informatique
 * Copyright (C) 2015-2022 Teclib' and contributors.
 *
 * http://glpi-project.org
 *
 * based on GLPI - Gestionnaire Libre de Parc Informatique
 * Copyright (C) 2003-2014 by the INDEPNET Development Team.
 *
 * ---------------------------------------------------------------------
 *
 * LICENSE
 *
 * This file is part of GLPI.
 *
 * GLPI is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * GLPI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GLPI. If not, see <http://www.gnu.org/licenses/>.
 * ---------------------------------------------------------------------
 */

// 'tinymce' and 'tinyMCE' objects have to be declared in global scope
window.tinymce = window.tinyMCE = __webpack_require__(558);

// Base theme
__webpack_require__(559);

// Used plugins
__webpack_require__(560);
__webpack_require__(562);
__webpack_require__(564);
__webpack_require__(566);
__webpack_require__(568);
__webpack_require__(570);
__webpack_require__(572);
__webpack_require__(574);
__webpack_require__(576);
__webpack_require__(578);
__webpack_require__(580);
__webpack_require__(582);
__webpack_require__(584);

// Custom plugins
__webpack_require__(586)


/***/ }),

/***/ 558:
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(setImmediate, console, global) {// 4.9.11 (2020-07-13)
(function () {
(function (domGlobals) {
    'use strict';

    var noop = function () {
    };
    var compose = function (fa, fb) {
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        return fa(fb.apply(null, args));
      };
    };
    var constant = function (value) {
      return function () {
        return value;
      };
    };
    var identity = function (x) {
      return x;
    };
    function curry(fn) {
      var initialArgs = [];
      for (var _i = 1; _i < arguments.length; _i++) {
        initialArgs[_i - 1] = arguments[_i];
      }
      return function () {
        var restArgs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          restArgs[_i] = arguments[_i];
        }
        var all = initialArgs.concat(restArgs);
        return fn.apply(null, all);
      };
    }
    var not = function (f) {
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        return !f.apply(null, args);
      };
    };
    var die = function (msg) {
      return function () {
        throw new Error(msg);
      };
    };
    var never = constant(false);
    var always = constant(true);

    var none = function () {
      return NONE;
    };
    var NONE = function () {
      var eq = function (o) {
        return o.isNone();
      };
      var call = function (thunk) {
        return thunk();
      };
      var id = function (n) {
        return n;
      };
      var me = {
        fold: function (n, s) {
          return n();
        },
        is: never,
        isSome: never,
        isNone: always,
        getOr: id,
        getOrThunk: call,
        getOrDie: function (msg) {
          throw new Error(msg || 'error: getOrDie called on none.');
        },
        getOrNull: constant(null),
        getOrUndefined: constant(undefined),
        or: id,
        orThunk: call,
        map: none,
        each: noop,
        bind: none,
        exists: never,
        forall: always,
        filter: none,
        equals: eq,
        equals_: eq,
        toArray: function () {
          return [];
        },
        toString: constant('none()')
      };
      if (Object.freeze) {
        Object.freeze(me);
      }
      return me;
    }();
    var some = function (a) {
      var constant_a = constant(a);
      var self = function () {
        return me;
      };
      var bind = function (f) {
        return f(a);
      };
      var me = {
        fold: function (n, s) {
          return s(a);
        },
        is: function (v) {
          return a === v;
        },
        isSome: always,
        isNone: never,
        getOr: constant_a,
        getOrThunk: constant_a,
        getOrDie: constant_a,
        getOrNull: constant_a,
        getOrUndefined: constant_a,
        or: self,
        orThunk: self,
        map: function (f) {
          return some(f(a));
        },
        each: function (f) {
          f(a);
        },
        bind: bind,
        exists: bind,
        forall: bind,
        filter: function (f) {
          return f(a) ? me : NONE;
        },
        toArray: function () {
          return [a];
        },
        toString: function () {
          return 'some(' + a + ')';
        },
        equals: function (o) {
          return o.is(a);
        },
        equals_: function (o, elementEq) {
          return o.fold(never, function (b) {
            return elementEq(a, b);
          });
        }
      };
      return me;
    };
    var from = function (value) {
      return value === null || value === undefined ? NONE : some(value);
    };
    var Option = {
      some: some,
      none: none,
      from: from
    };

    var typeOf = function (x) {
      if (x === null) {
        return 'null';
      }
      var t = typeof x;
      if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
        return 'array';
      }
      if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
        return 'string';
      }
      return t;
    };
    var isType = function (type) {
      return function (value) {
        return typeOf(value) === type;
      };
    };
    var isString = isType('string');
    var isObject = isType('object');
    var isArray = isType('array');
    var isNull = isType('null');
    var isBoolean = isType('boolean');
    var isFunction = isType('function');
    var isNumber = isType('number');

    var nativeSlice = Array.prototype.slice;
    var nativeIndexOf = Array.prototype.indexOf;
    var nativePush = Array.prototype.push;
    var rawIndexOf = function (ts, t) {
      return nativeIndexOf.call(ts, t);
    };
    var indexOf = function (xs, x) {
      var r = rawIndexOf(xs, x);
      return r === -1 ? Option.none() : Option.some(r);
    };
    var contains = function (xs, x) {
      return rawIndexOf(xs, x) > -1;
    };
    var exists = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return true;
        }
      }
      return false;
    };
    var map = function (xs, f) {
      var len = xs.length;
      var r = new Array(len);
      for (var i = 0; i < len; i++) {
        var x = xs[i];
        r[i] = f(x, i);
      }
      return r;
    };
    var each = function (xs, f) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        f(x, i);
      }
    };
    var eachr = function (xs, f) {
      for (var i = xs.length - 1; i >= 0; i--) {
        var x = xs[i];
        f(x, i);
      }
    };
    var partition = function (xs, pred) {
      var pass = [];
      var fail = [];
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        var arr = pred(x, i) ? pass : fail;
        arr.push(x);
      }
      return {
        pass: pass,
        fail: fail
      };
    };
    var filter = function (xs, pred) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          r.push(x);
        }
      }
      return r;
    };
    var foldr = function (xs, f, acc) {
      eachr(xs, function (x) {
        acc = f(acc, x);
      });
      return acc;
    };
    var foldl = function (xs, f, acc) {
      each(xs, function (x) {
        acc = f(acc, x);
      });
      return acc;
    };
    var find = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return Option.some(x);
        }
      }
      return Option.none();
    };
    var findIndex = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return Option.some(i);
        }
      }
      return Option.none();
    };
    var flatten = function (xs) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; ++i) {
        if (!isArray(xs[i])) {
          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
        }
        nativePush.apply(r, xs[i]);
      }
      return r;
    };
    var bind = function (xs, f) {
      var output = map(xs, f);
      return flatten(output);
    };
    var forall = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; ++i) {
        var x = xs[i];
        if (pred(x, i) !== true) {
          return false;
        }
      }
      return true;
    };
    var reverse = function (xs) {
      var r = nativeSlice.call(xs, 0);
      r.reverse();
      return r;
    };
    var difference = function (a1, a2) {
      return filter(a1, function (x) {
        return !contains(a2, x);
      });
    };
    var mapToObject = function (xs, f) {
      var r = {};
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        r[String(x)] = f(x, i);
      }
      return r;
    };
    var sort = function (xs, comparator) {
      var copy = nativeSlice.call(xs, 0);
      copy.sort(comparator);
      return copy;
    };
    var head = function (xs) {
      return xs.length === 0 ? Option.none() : Option.some(xs[0]);
    };
    var last = function (xs) {
      return xs.length === 0 ? Option.none() : Option.some(xs[xs.length - 1]);
    };
    var from$1 = isFunction(Array.from) ? Array.from : function (x) {
      return nativeSlice.call(x);
    };

    var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();

    var path = function (parts, scope) {
      var o = scope !== undefined && scope !== null ? scope : Global;
      for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
        o = o[parts[i]];
      }
      return o;
    };
    var resolve = function (p, scope) {
      var parts = p.split('.');
      return path(parts, scope);
    };

    var unsafe = function (name, scope) {
      return resolve(name, scope);
    };
    var getOrDie = function (name, scope) {
      var actual = unsafe(name, scope);
      if (actual === undefined || actual === null) {
        throw new Error(name + ' not available on this browser');
      }
      return actual;
    };
    var Global$1 = { getOrDie: getOrDie };

    var url = function () {
      return Global$1.getOrDie('URL');
    };
    var createObjectURL = function (blob) {
      return url().createObjectURL(blob);
    };
    var revokeObjectURL = function (u) {
      url().revokeObjectURL(u);
    };
    var URL = {
      createObjectURL: createObjectURL,
      revokeObjectURL: revokeObjectURL
    };

    var nav = domGlobals.navigator, userAgent = nav.userAgent;
    var opera, webkit, ie, ie11, ie12, gecko, mac, iDevice, android, fileApi, phone, tablet, windowsPhone;
    var matchMediaQuery = function (query) {
      return 'matchMedia' in domGlobals.window ? domGlobals.matchMedia(query).matches : false;
    };
    opera = false;
    android = /Android/.test(userAgent);
    webkit = /WebKit/.test(userAgent);
    ie = !webkit && !opera && /MSIE/gi.test(userAgent) && /Explorer/gi.test(nav.appName);
    ie = ie && /MSIE (\w+)\./.exec(userAgent)[1];
    ie11 = userAgent.indexOf('Trident/') !== -1 && (userAgent.indexOf('rv:') !== -1 || nav.appName.indexOf('Netscape') !== -1) ? 11 : false;
    ie12 = userAgent.indexOf('Edge/') !== -1 && !ie && !ie11 ? 12 : false;
    ie = ie || ie11 || ie12;
    gecko = !webkit && !ie11 && /Gecko/.test(userAgent);
    mac = userAgent.indexOf('Mac') !== -1;
    iDevice = /(iPad|iPhone)/.test(userAgent);
    fileApi = 'FormData' in domGlobals.window && 'FileReader' in domGlobals.window && 'URL' in domGlobals.window && !!URL.createObjectURL;
    phone = matchMediaQuery('only screen and (max-device-width: 480px)') && (android || iDevice);
    tablet = matchMediaQuery('only screen and (min-width: 800px)') && (android || iDevice);
    windowsPhone = userAgent.indexOf('Windows Phone') !== -1;
    if (ie12) {
      webkit = false;
    }
    var contentEditable = !iDevice || fileApi || parseInt(userAgent.match(/AppleWebKit\/(\d*)/)[1], 10) >= 534;
    var Env = {
      opera: opera,
      webkit: webkit,
      ie: ie,
      gecko: gecko,
      mac: mac,
      iOS: iDevice,
      android: android,
      contentEditable: contentEditable,
      transparentSrc: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
      caretAfter: ie !== 8,
      range: domGlobals.window.getSelection && 'Range' in domGlobals.window,
      documentMode: ie && !ie12 ? domGlobals.document.documentMode || 7 : 10,
      fileApi: fileApi,
      ceFalse: ie === false || ie > 8,
      cacheSuffix: null,
      container: null,
      overrideViewPort: null,
      experimentalShadowDom: false,
      canHaveCSP: ie === false || ie > 11,
      desktop: !phone && !tablet,
      windowsPhone: windowsPhone
    };

    var promise = function () {
      function bind(fn, thisArg) {
        return function () {
          fn.apply(thisArg, arguments);
        };
      }
      var isArray = Array.isArray || function (value) {
        return Object.prototype.toString.call(value) === '[object Array]';
      };
      var Promise = function (fn) {
        if (typeof this !== 'object') {
          throw new TypeError('Promises must be constructed via new');
        }
        if (typeof fn !== 'function') {
          throw new TypeError('not a function');
        }
        this._state = null;
        this._value = null;
        this._deferreds = [];
        doResolve(fn, bind(resolve, this), bind(reject, this));
      };
      var asap = Promise.immediateFn || typeof setImmediate === 'function' && setImmediate || function (fn) {
        setTimeout(fn, 1);
      };
      function handle(deferred) {
        var me = this;
        if (this._state === null) {
          this._deferreds.push(deferred);
          return;
        }
        asap(function () {
          var cb = me._state ? deferred.onFulfilled : deferred.onRejected;
          if (cb === null) {
            (me._state ? deferred.resolve : deferred.reject)(me._value);
            return;
          }
          var ret;
          try {
            ret = cb(me._value);
          } catch (e) {
            deferred.reject(e);
            return;
          }
          deferred.resolve(ret);
        });
      }
      function resolve(newValue) {
        try {
          if (newValue === this) {
            throw new TypeError('A promise cannot be resolved with itself.');
          }
          if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
            var then = newValue.then;
            if (typeof then === 'function') {
              doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this));
              return;
            }
          }
          this._state = true;
          this._value = newValue;
          finale.call(this);
        } catch (e) {
          reject.call(this, e);
        }
      }
      function reject(newValue) {
        this._state = false;
        this._value = newValue;
        finale.call(this);
      }
      function finale() {
        for (var i = 0, len = this._deferreds.length; i < len; i++) {
          handle.call(this, this._deferreds[i]);
        }
        this._deferreds = null;
      }
      function Handler(onFulfilled, onRejected, resolve, reject) {
        this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
        this.onRejected = typeof onRejected === 'function' ? onRejected : null;
        this.resolve = resolve;
        this.reject = reject;
      }
      function doResolve(fn, onFulfilled, onRejected) {
        var done = false;
        try {
          fn(function (value) {
            if (done) {
              return;
            }
            done = true;
            onFulfilled(value);
          }, function (reason) {
            if (done) {
              return;
            }
            done = true;
            onRejected(reason);
          });
        } catch (ex) {
          if (done) {
            return;
          }
          done = true;
          onRejected(ex);
        }
      }
      Promise.prototype.catch = function (onRejected) {
        return this.then(null, onRejected);
      };
      Promise.prototype.then = function (onFulfilled, onRejected) {
        var me = this;
        return new Promise(function (resolve, reject) {
          handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject));
        });
      };
      Promise.all = function () {
        var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments);
        return new Promise(function (resolve, reject) {
          if (args.length === 0) {
            return resolve([]);
          }
          var remaining = args.length;
          function res(i, val) {
            try {
              if (val && (typeof val === 'object' || typeof val === 'function')) {
                var then = val.then;
                if (typeof then === 'function') {
                  then.call(val, function (val) {
                    res(i, val);
                  }, reject);
                  return;
                }
              }
              args[i] = val;
              if (--remaining === 0) {
                resolve(args);
              }
            } catch (ex) {
              reject(ex);
            }
          }
          for (var i = 0; i < args.length; i++) {
            res(i, args[i]);
          }
        });
      };
      Promise.resolve = function (value) {
        if (value && typeof value === 'object' && value.constructor === Promise) {
          return value;
        }
        return new Promise(function (resolve) {
          resolve(value);
        });
      };
      Promise.reject = function (value) {
        return new Promise(function (resolve, reject) {
          reject(value);
        });
      };
      Promise.race = function (values) {
        return new Promise(function (resolve, reject) {
          for (var i = 0, len = values.length; i < len; i++) {
            values[i].then(resolve, reject);
          }
        });
      };
      return Promise;
    };
    var promiseObj = window.Promise ? window.Promise : promise();

    var requestAnimationFramePromise;
    var requestAnimationFrame = function (callback, element) {
      var i, requestAnimationFrameFunc = domGlobals.window.requestAnimationFrame;
      var vendors = [
        'ms',
        'moz',
        'webkit'
      ];
      var featurefill = function (callback) {
        domGlobals.window.setTimeout(callback, 0);
      };
      for (i = 0; i < vendors.length && !requestAnimationFrameFunc; i++) {
        requestAnimationFrameFunc = domGlobals.window[vendors[i] + 'RequestAnimationFrame'];
      }
      if (!requestAnimationFrameFunc) {
        requestAnimationFrameFunc = featurefill;
      }
      requestAnimationFrameFunc(callback, element);
    };
    var wrappedSetTimeout = function (callback, time) {
      if (typeof time !== 'number') {
        time = 0;
      }
      return setTimeout(callback, time);
    };
    var wrappedSetInterval = function (callback, time) {
      if (typeof time !== 'number') {
        time = 1;
      }
      return setInterval(callback, time);
    };
    var wrappedClearTimeout = function (id) {
      return clearTimeout(id);
    };
    var wrappedClearInterval = function (id) {
      return clearInterval(id);
    };
    var debounce = function (callback, time) {
      var timer, func;
      func = function () {
        var args = arguments;
        clearTimeout(timer);
        timer = wrappedSetTimeout(function () {
          callback.apply(this, args);
        }, time);
      };
      func.stop = function () {
        clearTimeout(timer);
      };
      return func;
    };
    var Delay = {
      requestAnimationFrame: function (callback, element) {
        if (requestAnimationFramePromise) {
          requestAnimationFramePromise.then(callback);
          return;
        }
        requestAnimationFramePromise = new promiseObj(function (resolve) {
          if (!element) {
            element = domGlobals.document.body;
          }
          requestAnimationFrame(resolve, element);
        }).then(callback);
      },
      setTimeout: wrappedSetTimeout,
      setInterval: wrappedSetInterval,
      setEditorTimeout: function (editor, callback, time) {
        return wrappedSetTimeout(function () {
          if (!editor.removed) {
            callback();
          }
        }, time);
      },
      setEditorInterval: function (editor, callback, time) {
        var timer;
        timer = wrappedSetInterval(function () {
          if (!editor.removed) {
            callback();
          } else {
            clearInterval(timer);
          }
        }, time);
        return timer;
      },
      debounce: debounce,
      throttle: debounce,
      clearInterval: wrappedClearInterval,
      clearTimeout: wrappedClearTimeout
    };

    var eventExpandoPrefix = 'mce-data-';
    var mouseEventRe = /^(?:mouse|contextmenu)|click/;
    var deprecated = {
      keyLocation: 1,
      layerX: 1,
      layerY: 1,
      returnValue: 1,
      webkitMovementX: 1,
      webkitMovementY: 1,
      keyIdentifier: 1
    };
    var hasIsDefaultPrevented = function (event) {
      return event.isDefaultPrevented === returnTrue || event.isDefaultPrevented === returnFalse;
    };
    var returnFalse = function () {
      return false;
    };
    var returnTrue = function () {
      return true;
    };
    var addEvent = function (target, name, callback, capture) {
      if (target.addEventListener) {
        target.addEventListener(name, callback, capture || false);
      } else if (target.attachEvent) {
        target.attachEvent('on' + name, callback);
      }
    };
    var removeEvent = function (target, name, callback, capture) {
      if (target.removeEventListener) {
        target.removeEventListener(name, callback, capture || false);
      } else if (target.detachEvent) {
        target.detachEvent('on' + name, callback);
      }
    };
    var getTargetFromShadowDom = function (event, defaultTarget) {
      if (event.composedPath) {
        var composedPath = event.composedPath();
        if (composedPath && composedPath.length > 0) {
          return composedPath[0];
        }
      }
      return defaultTarget;
    };
    var fix = function (originalEvent, data) {
      var name;
      var event = data || {};
      for (name in originalEvent) {
        if (!deprecated[name]) {
          event[name] = originalEvent[name];
        }
      }
      if (!event.target) {
        event.target = event.srcElement || domGlobals.document;
      }
      if (Env.experimentalShadowDom) {
        event.target = getTargetFromShadowDom(originalEvent, event.target);
      }
      if (originalEvent && mouseEventRe.test(originalEvent.type) && originalEvent.pageX === undefined && originalEvent.clientX !== undefined) {
        var eventDoc = event.target.ownerDocument || domGlobals.document;
        var doc = eventDoc.documentElement;
        var body = eventDoc.body;
        event.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
        event.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
      }
      event.preventDefault = function () {
        event.isDefaultPrevented = returnTrue;
        if (originalEvent) {
          if (originalEvent.preventDefault) {
            originalEvent.preventDefault();
          } else {
            originalEvent.returnValue = false;
          }
        }
      };
      event.stopPropagation = function () {
        event.isPropagationStopped = returnTrue;
        if (originalEvent) {
          if (originalEvent.stopPropagation) {
            originalEvent.stopPropagation();
          } else {
            originalEvent.cancelBubble = true;
          }
        }
      };
      event.stopImmediatePropagation = function () {
        event.isImmediatePropagationStopped = returnTrue;
        event.stopPropagation();
      };
      if (hasIsDefaultPrevented(event) === false) {
        event.isDefaultPrevented = returnFalse;
        event.isPropagationStopped = returnFalse;
        event.isImmediatePropagationStopped = returnFalse;
      }
      if (typeof event.metaKey === 'undefined') {
        event.metaKey = false;
      }
      return event;
    };
    var bindOnReady = function (win, callback, eventUtils) {
      var doc = win.document, event = { type: 'ready' };
      if (eventUtils.domLoaded) {
        callback(event);
        return;
      }
      var isDocReady = function () {
        return doc.readyState === 'complete' || doc.readyState === 'interactive' && doc.body;
      };
      var readyHandler = function () {
        if (!eventUtils.domLoaded) {
          eventUtils.domLoaded = true;
          callback(event);
        }
      };
      var waitForDomLoaded = function () {
        if (isDocReady()) {
          removeEvent(doc, 'readystatechange', waitForDomLoaded);
          readyHandler();
        }
      };
      var tryScroll = function () {
        try {
          doc.documentElement.doScroll('left');
        } catch (ex) {
          Delay.setTimeout(tryScroll);
          return;
        }
        readyHandler();
      };
      if (doc.addEventListener && !(Env.ie && Env.ie < 11)) {
        if (isDocReady()) {
          readyHandler();
        } else {
          addEvent(win, 'DOMContentLoaded', readyHandler);
        }
      } else {
        addEvent(doc, 'readystatechange', waitForDomLoaded);
        if (doc.documentElement.doScroll && win.self === win.top) {
          tryScroll();
        }
      }
      addEvent(win, 'load', readyHandler);
    };
    var EventUtils = function () {
      var self = this;
      var events = {}, count, expando, hasFocusIn, hasMouseEnterLeave, mouseEnterLeave;
      expando = eventExpandoPrefix + (+new Date()).toString(32);
      hasMouseEnterLeave = 'onmouseenter' in domGlobals.document.documentElement;
      hasFocusIn = 'onfocusin' in domGlobals.document.documentElement;
      mouseEnterLeave = {
        mouseenter: 'mouseover',
        mouseleave: 'mouseout'
      };
      count = 1;
      self.domLoaded = false;
      self.events = events;
      var executeHandlers = function (evt, id) {
        var callbackList, i, l, callback;
        var container = events[id];
        callbackList = container && container[evt.type];
        if (callbackList) {
          for (i = 0, l = callbackList.length; i < l; i++) {
            callback = callbackList[i];
            if (callback && callback.func.call(callback.scope, evt) === false) {
              evt.preventDefault();
            }
            if (evt.isImmediatePropagationStopped()) {
              return;
            }
          }
        }
      };
      self.bind = function (target, names, callback, scope) {
        var id, callbackList, i, name, fakeName, nativeHandler, capture;
        var win = domGlobals.window;
        var defaultNativeHandler = function (evt) {
          executeHandlers(fix(evt || win.event), id);
        };
        if (!target || target.nodeType === 3 || target.nodeType === 8) {
          return;
        }
        if (!target[expando]) {
          id = count++;
          target[expando] = id;
          events[id] = {};
        } else {
          id = target[expando];
        }
        scope = scope || target;
        names = names.split(' ');
        i = names.length;
        while (i--) {
          name = names[i];
          nativeHandler = defaultNativeHandler;
          fakeName = capture = false;
          if (name === 'DOMContentLoaded') {
            name = 'ready';
          }
          if (self.domLoaded && name === 'ready' && target.readyState === 'complete') {
            callback.call(scope, fix({ type: name }));
            continue;
          }
          if (!hasMouseEnterLeave) {
            fakeName = mouseEnterLeave[name];
            if (fakeName) {
              nativeHandler = function (evt) {
                var current, related;
                current = evt.currentTarget;
                related = evt.relatedTarget;
                if (related && current.contains) {
                  related = current.contains(related);
                } else {
                  while (related && related !== current) {
                    related = related.parentNode;
                  }
                }
                if (!related) {
                  evt = fix(evt || win.event);
                  evt.type = evt.type === 'mouseout' ? 'mouseleave' : 'mouseenter';
                  evt.target = current;
                  executeHandlers(evt, id);
                }
              };
            }
          }
          if (!hasFocusIn && (name === 'focusin' || name === 'focusout')) {
            capture = true;
            fakeName = name === 'focusin' ? 'focus' : 'blur';
            nativeHandler = function (evt) {
              evt = fix(evt || win.event);
              evt.type = evt.type === 'focus' ? 'focusin' : 'focusout';
              executeHandlers(evt, id);
            };
          }
          callbackList = events[id][name];
          if (!callbackList) {
            events[id][name] = callbackList = [{
                func: callback,
                scope: scope
              }];
            callbackList.fakeName = fakeName;
            callbackList.capture = capture;
            callbackList.nativeHandler = nativeHandler;
            if (name === 'ready') {
              bindOnReady(target, nativeHandler, self);
            } else {
              addEvent(target, fakeName || name, nativeHandler, capture);
            }
          } else {
            if (name === 'ready' && self.domLoaded) {
              callback({ type: name });
            } else {
              callbackList.push({
                func: callback,
                scope: scope
              });
            }
          }
        }
        target = callbackList = 0;
        return callback;
      };
      self.unbind = function (target, names, callback) {
        var id, callbackList, i, ci, name, eventMap;
        if (!target || target.nodeType === 3 || target.nodeType === 8) {
          return self;
        }
        id = target[expando];
        if (id) {
          eventMap = events[id];
          if (names) {
            names = names.split(' ');
            i = names.length;
            while (i--) {
              name = names[i];
              callbackList = eventMap[name];
              if (callbackList) {
                if (callback) {
                  ci = callbackList.length;
                  while (ci--) {
                    if (callbackList[ci].func === callback) {
                      var nativeHandler = callbackList.nativeHandler;
                      var fakeName = callbackList.fakeName, capture = callbackList.capture;
                      callbackList = callbackList.slice(0, ci).concat(callbackList.slice(ci + 1));
                      callbackList.nativeHandler = nativeHandler;
                      callbackList.fakeName = fakeName;
                      callbackList.capture = capture;
                      eventMap[name] = callbackList;
                    }
                  }
                }
                if (!callback || callbackList.length === 0) {
                  delete eventMap[name];
                  removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
                }
              }
            }
          } else {
            for (name in eventMap) {
              callbackList = eventMap[name];
              removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
            }
            eventMap = {};
          }
          for (name in eventMap) {
            return self;
          }
          delete events[id];
          try {
            delete target[expando];
          } catch (ex) {
            target[expando] = null;
          }
        }
        return self;
      };
      self.fire = function (target, name, args) {
        var id;
        if (!target || target.nodeType === 3 || target.nodeType === 8) {
          return self;
        }
        args = fix(null, args);
        args.type = name;
        args.target = target;
        do {
          id = target[expando];
          if (id) {
            executeHandlers(args, id);
          }
          target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow;
        } while (target && !args.isPropagationStopped());
        return self;
      };
      self.clean = function (target) {
        var i, children;
        var unbind = self.unbind;
        if (!target || target.nodeType === 3 || target.nodeType === 8) {
          return self;
        }
        if (target[expando]) {
          unbind(target);
        }
        if (!target.getElementsByTagName) {
          target = target.document;
        }
        if (target && target.getElementsByTagName) {
          unbind(target);
          children = target.getElementsByTagName('*');
          i = children.length;
          while (i--) {
            target = children[i];
            if (target[expando]) {
              unbind(target);
            }
          }
        }
        return self;
      };
      self.destroy = function () {
        events = {};
      };
      self.cancel = function (e) {
        if (e) {
          e.preventDefault();
          e.stopImmediatePropagation();
        }
        return false;
      };
    };
    EventUtils.Event = new EventUtils();
    EventUtils.Event.bind(domGlobals.window, 'ready', function () {
    });

    var i, support, Expr, getText, isXML, tokenize, compile, select, outermostContext, sortInput, hasDuplicate, setDocument, document, docElem, documentIsHTML, rbuggyQSA, rbuggyMatches, matches, contains$1, expando = 'sizzle' + -new Date(), preferredDoc = domGlobals.window.document, dirruns = 0, done = 0, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), sortOrder = function (a, b) {
        if (a === b) {
          hasDuplicate = true;
        }
        return 0;
      }, strundefined = typeof undefined, MAX_NEGATIVE = 1 << 31, hasOwn = {}.hasOwnProperty, arr = [], pop = arr.pop, push_native = arr.push, push = arr.push, slice = arr.slice, indexOf$1 = arr.indexOf || function (elem) {
        var i = 0, len = this.length;
        for (; i < len; i++) {
          if (this[i] === elem) {
            return i;
          }
        }
        return -1;
      }, booleans = 'checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped', whitespace = '[\\x20\\t\\r\\n\\f]', identifier = '(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+', attributes = '\\[' + whitespace + '*(' + identifier + ')(?:' + whitespace + '*([*^$|!~]?=)' + whitespace + '*(?:\'((?:\\\\.|[^\\\\\'])*)\'|"((?:\\\\.|[^\\\\"])*)"|(' + identifier + '))|)' + whitespace + '*\\]', pseudos = ':(' + identifier + ')(?:\\((' + '(\'((?:\\\\.|[^\\\\\'])*)\'|"((?:\\\\.|[^\\\\"])*)")|' + '((?:\\\\.|[^\\\\()[\\]]|' + attributes + ')*)|' + '.*' + ')\\)|)', rtrim = new RegExp('^' + whitespace + '+|((?:^|[^\\\\])(?:\\\\.)*)' + whitespace + '+$', 'g'), rcomma = new RegExp('^' + whitespace + '*,' + whitespace + '*'), rcombinators = new RegExp('^' + whitespace + '*([>+~]|' + whitespace + ')' + whitespace + '*'), rattributeQuotes = new RegExp('=' + whitespace + '*([^\\]\'"]*?)' + whitespace + '*\\]', 'g'), rpseudo = new RegExp(pseudos), ridentifier = new RegExp('^' + identifier + '$'), matchExpr = {
        ID: new RegExp('^#(' + identifier + ')'),
        CLASS: new RegExp('^\\.(' + identifier + ')'),
        TAG: new RegExp('^(' + identifier + '|[*])'),
        ATTR: new RegExp('^' + attributes),
        PSEUDO: new RegExp('^' + pseudos),
        CHILD: new RegExp('^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(' + whitespace + '*(even|odd|(([+-]|)(\\d*)n|)' + whitespace + '*(?:([+-]|)' + whitespace + '*(\\d+)|))' + whitespace + '*\\)|)', 'i'),
        bool: new RegExp('^(?:' + booleans + ')$', 'i'),
        needsContext: new RegExp('^' + whitespace + '*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(' + whitespace + '*((?:-\\d)?\\d*)' + whitespace + '*\\)|)(?=[^-]|$)', 'i')
      }, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, rnative = /^[^{]+\{\s*\[native \w/, rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rsibling = /[+~]/, rescape = /'|\\/g, runescape = new RegExp('\\\\([\\da-f]{1,6}' + whitespace + '?|(' + whitespace + ')|.)', 'ig'), funescape = function (_, escaped, escapedWhitespace) {
        var high = '0x' + escaped - 65536;
        return high !== high || escapedWhitespace ? escaped : high < 0 ? String.fromCharCode(high + 65536) : String.fromCharCode(high >> 10 | 55296, high & 1023 | 56320);
      };
    try {
      push.apply(arr = slice.call(preferredDoc.childNodes), preferredDoc.childNodes);
      arr[preferredDoc.childNodes.length].nodeType;
    } catch (e) {
      push = {
        apply: arr.length ? function (target, els) {
          push_native.apply(target, slice.call(els));
        } : function (target, els) {
          var j = target.length, i = 0;
          while (target[j++] = els[i++]) {
          }
          target.length = j - 1;
        }
      };
    }
    var Sizzle = function (selector, context, results, seed) {
      var match, elem, m, nodeType, i, groups, old, nid, newContext, newSelector;
      if ((context ? context.ownerDocument || context : preferredDoc) !== document) {
        setDocument(context);
      }
      context = context || document;
      results = results || [];
      if (!selector || typeof selector !== 'string') {
        return results;
      }
      if ((nodeType = context.nodeType) !== 1 && nodeType !== 9) {
        return [];
      }
      if (documentIsHTML && !seed) {
        if (match = rquickExpr.exec(selector)) {
          if (m = match[1]) {
            if (nodeType === 9) {
              elem = context.getElementById(m);
              if (elem && elem.parentNode) {
                if (elem.id === m) {
                  results.push(elem);
                  return results;
                }
              } else {
                return results;
              }
            } else {
              if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) && contains$1(context, elem) && elem.id === m) {
                results.push(elem);
                return results;
              }
            }
          } else if (match[2]) {
            push.apply(results, context.getElementsByTagName(selector));
            return results;
          } else if ((m = match[3]) && support.getElementsByClassName) {
            push.apply(results, context.getElementsByClassName(m));
            return results;
          }
        }
        if (support.qsa && (!rbuggyQSA || !rbuggyQSA.test(selector))) {
          nid = old = expando;
          newContext = context;
          newSelector = nodeType === 9 && selector;
          if (nodeType === 1 && context.nodeName.toLowerCase() !== 'object') {
            groups = tokenize(selector);
            if (old = context.getAttribute('id')) {
              nid = old.replace(rescape, '\\$&');
            } else {
              context.setAttribute('id', nid);
            }
            nid = '[id=\'' + nid + '\'] ';
            i = groups.length;
            while (i--) {
              groups[i] = nid + toSelector(groups[i]);
            }
            newContext = rsibling.test(selector) && testContext(context.parentNode) || context;
            newSelector = groups.join(',');
          }
          if (newSelector) {
            try {
              push.apply(results, newContext.querySelectorAll(newSelector));
              return results;
            } catch (qsaError) {
            } finally {
              if (!old) {
                context.removeAttribute('id');
              }
            }
          }
        }
      }
      return select(selector.replace(rtrim, '$1'), context, results, seed);
    };
    function createCache() {
      var keys = [];
      function cache(key, value) {
        if (keys.push(key + ' ') > Expr.cacheLength) {
          delete cache[keys.shift()];
        }
        return cache[key + ' '] = value;
      }
      return cache;
    }
    function markFunction(fn) {
      fn[expando] = true;
      return fn;
    }
    function siblingCheck(a, b) {
      var cur = b && a, diff = cur && a.nodeType === 1 && b.nodeType === 1 && (~b.sourceIndex || MAX_NEGATIVE) - (~a.sourceIndex || MAX_NEGATIVE);
      if (diff) {
        return diff;
      }
      if (cur) {
        while (cur = cur.nextSibling) {
          if (cur === b) {
            return -1;
          }
        }
      }
      return a ? 1 : -1;
    }
    function createInputPseudo(type) {
      return function (elem) {
        var name = elem.nodeName.toLowerCase();
        return name === 'input' && elem.type === type;
      };
    }
    function createButtonPseudo(type) {
      return function (elem) {
        var name = elem.nodeName.toLowerCase();
        return (name === 'input' || name === 'button') && elem.type === type;
      };
    }
    function createPositionalPseudo(fn) {
      return markFunction(function (argument) {
        argument = +argument;
        return markFunction(function (seed, matches) {
          var j, matchIndexes = fn([], seed.length, argument), i = matchIndexes.length;
          while (i--) {
            if (seed[j = matchIndexes[i]]) {
              seed[j] = !(matches[j] = seed[j]);
            }
          }
        });
      });
    }
    function testContext(context) {
      return context && typeof context.getElementsByTagName !== strundefined && context;
    }
    support = Sizzle.support = {};
    isXML = Sizzle.isXML = function (elem) {
      var documentElement = elem && (elem.ownerDocument || elem).documentElement;
      return documentElement ? documentElement.nodeName !== 'HTML' : false;
    };
    setDocument = Sizzle.setDocument = function (node) {
      var hasCompare, doc = node ? node.ownerDocument || node : preferredDoc, parent = doc.defaultView;
      function getTop(win) {
        try {
          return win.top;
        } catch (ex) {
        }
        return null;
      }
      if (doc === document || doc.nodeType !== 9 || !doc.documentElement) {
        return document;
      }
      document = doc;
      docElem = doc.documentElement;
      documentIsHTML = !isXML(doc);
      if (parent && parent !== getTop(parent)) {
        if (parent.addEventListener) {
          parent.addEventListener('unload', function () {
            setDocument();
          }, false);
        } else if (parent.attachEvent) {
          parent.attachEvent('onunload', function () {
            setDocument();
          });
        }
      }
      support.attributes = true;
      support.getElementsByTagName = true;
      support.getElementsByClassName = rnative.test(doc.getElementsByClassName);
      support.getById = true;
      Expr.find.ID = function (id, context) {
        if (typeof context.getElementById !== strundefined && documentIsHTML) {
          var m = context.getElementById(id);
          return m && m.parentNode ? [m] : [];
        }
      };
      Expr.filter.ID = function (id) {
        var attrId = id.replace(runescape, funescape);
        return function (elem) {
          return elem.getAttribute('id') === attrId;
        };
      };
      Expr.find.TAG = support.getElementsByTagName ? function (tag, context) {
        if (typeof context.getElementsByTagName !== strundefined) {
          return context.getElementsByTagName(tag);
        }
      } : function (tag, context) {
        var elem, tmp = [], i = 0, results = context.getElementsByTagName(tag);
        if (tag === '*') {
          while (elem = results[i++]) {
            if (elem.nodeType === 1) {
              tmp.push(elem);
            }
          }
          return tmp;
        }
        return results;
      };
      Expr.find.CLASS = support.getElementsByClassName && function (className, context) {
        if (documentIsHTML) {
          return context.getElementsByClassName(className);
        }
      };
      rbuggyMatches = [];
      rbuggyQSA = [];
      support.disconnectedMatch = true;
      rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join('|'));
      rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join('|'));
      hasCompare = rnative.test(docElem.compareDocumentPosition);
      contains$1 = hasCompare || rnative.test(docElem.contains) ? function (a, b) {
        var adown = a.nodeType === 9 ? a.documentElement : a, bup = b && b.parentNode;
        return a === bup || !!(bup && bup.nodeType === 1 && (adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16));
      } : function (a, b) {
        if (b) {
          while (b = b.parentNode) {
            if (b === a) {
              return true;
            }
          }
        }
        return false;
      };
      sortOrder = hasCompare ? function (a, b) {
        if (a === b) {
          hasDuplicate = true;
          return 0;
        }
        var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
        if (compare) {
          return compare;
        }
        compare = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : 1;
        if (compare & 1 || !support.sortDetached && b.compareDocumentPosition(a) === compare) {
          if (a === doc || a.ownerDocument === preferredDoc && contains$1(preferredDoc, a)) {
            return -1;
          }
          if (b === doc || b.ownerDocument === preferredDoc && contains$1(preferredDoc, b)) {
            return 1;
          }
          return sortInput ? indexOf$1.call(sortInput, a) - indexOf$1.call(sortInput, b) : 0;
        }
        return compare & 4 ? -1 : 1;
      } : function (a, b) {
        if (a === b) {
          hasDuplicate = true;
          return 0;
        }
        var cur, i = 0, aup = a.parentNode, bup = b.parentNode, ap = [a], bp = [b];
        if (!aup || !bup) {
          return a === doc ? -1 : b === doc ? 1 : aup ? -1 : bup ? 1 : sortInput ? indexOf$1.call(sortInput, a) - indexOf$1.call(sortInput, b) : 0;
        } else if (aup === bup) {
          return siblingCheck(a, b);
        }
        cur = a;
        while (cur = cur.parentNode) {
          ap.unshift(cur);
        }
        cur = b;
        while (cur = cur.parentNode) {
          bp.unshift(cur);
        }
        while (ap[i] === bp[i]) {
          i++;
        }
        return i ? siblingCheck(ap[i], bp[i]) : ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0;
      };
      return doc;
    };
    Sizzle.matches = function (expr, elements) {
      return Sizzle(expr, null, null, elements);
    };
    Sizzle.matchesSelector = function (elem, expr) {
      if ((elem.ownerDocument || elem) !== document) {
        setDocument(elem);
      }
      expr = expr.replace(rattributeQuotes, '=\'$1\']');
      if (support.matchesSelector && documentIsHTML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr))) {
        try {
          var ret = matches.call(elem, expr);
          if (ret || support.disconnectedMatch || elem.document && elem.document.nodeType !== 11) {
            return ret;
          }
        } catch (e) {
        }
      }
      return Sizzle(expr, document, null, [elem]).length > 0;
    };
    Sizzle.contains = function (context, elem) {
      if ((context.ownerDocument || context) !== document) {
        setDocument(context);
      }
      return contains$1(context, elem);
    };
    Sizzle.attr = function (elem, name) {
      if ((elem.ownerDocument || elem) !== document) {
        setDocument(elem);
      }
      var fn = Expr.attrHandle[name.toLowerCase()], val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined;
      return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;
    };
    Sizzle.error = function (msg) {
      throw new Error('Syntax error, unrecognized expression: ' + msg);
    };
    Sizzle.uniqueSort = function (results) {
      var elem, duplicates = [], j = 0, i = 0;
      hasDuplicate = !support.detectDuplicates;
      sortInput = !support.sortStable && results.slice(0);
      results.sort(sortOrder);
      if (hasDuplicate) {
        while (elem = results[i++]) {
          if (elem === results[i]) {
            j = duplicates.push(i);
          }
        }
        while (j--) {
          results.splice(duplicates[j], 1);
        }
      }
      sortInput = null;
      return results;
    };
    getText = Sizzle.getText = function (elem) {
      var node, ret = '', i = 0, nodeType = elem.nodeType;
      if (!nodeType) {
        while (node = elem[i++]) {
          ret += getText(node);
        }
      } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
        if (typeof elem.textContent === 'string') {
          return elem.textContent;
        } else {
          for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
            ret += getText(elem);
          }
        }
      } else if (nodeType === 3 || nodeType === 4) {
        return elem.nodeValue;
      }
      return ret;
    };
    Expr = Sizzle.selectors = {
      cacheLength: 50,
      createPseudo: markFunction,
      match: matchExpr,
      attrHandle: {},
      find: {},
      relative: {
        '>': {
          dir: 'parentNode',
          first: true
        },
        ' ': { dir: 'parentNode' },
        '+': {
          dir: 'previousSibling',
          first: true
        },
        '~': { dir: 'previousSibling' }
      },
      preFilter: {
        ATTR: function (match) {
          match[1] = match[1].replace(runescape, funescape);
          match[3] = (match[3] || match[4] || match[5] || '').replace(runescape, funescape);
          if (match[2] === '~=') {
            match[3] = ' ' + match[3] + ' ';
          }
          return match.slice(0, 4);
        },
        CHILD: function (match) {
          match[1] = match[1].toLowerCase();
          if (match[1].slice(0, 3) === 'nth') {
            if (!match[3]) {
              Sizzle.error(match[0]);
            }
            match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === 'even' || match[3] === 'odd'));
            match[5] = +(match[7] + match[8] || match[3] === 'odd');
          } else if (match[3]) {
            Sizzle.error(match[0]);
          }
          return match;
        },
        PSEUDO: function (match) {
          var excess, unquoted = !match[6] && match[2];
          if (matchExpr.CHILD.test(match[0])) {
            return null;
          }
          if (match[3]) {
            match[2] = match[4] || match[5] || '';
          } else if (unquoted && rpseudo.test(unquoted) && (excess = tokenize(unquoted, true)) && (excess = unquoted.indexOf(')', unquoted.length - excess) - unquoted.length)) {
            match[0] = match[0].slice(0, excess);
            match[2] = unquoted.slice(0, excess);
          }
          return match.slice(0, 3);
        }
      },
      filter: {
        TAG: function (nodeNameSelector) {
          var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();
          return nodeNameSelector === '*' ? function () {
            return true;
          } : function (elem) {
            return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
          };
        },
        CLASS: function (className) {
          var pattern = classCache[className + ' '];
          return pattern || (pattern = new RegExp('(^|' + whitespace + ')' + className + '(' + whitespace + '|$)')) && classCache(className, function (elem) {
            return pattern.test(typeof elem.className === 'string' && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute('class') || '');
          });
        },
        ATTR: function (name, operator, check) {
          return function (elem) {
            var result = Sizzle.attr(elem, name);
            if (result == null) {
              return operator === '!=';
            }
            if (!operator) {
              return true;
            }
            result += '';
            return operator === '=' ? result === check : operator === '!=' ? result !== check : operator === '^=' ? check && result.indexOf(check) === 0 : operator === '*=' ? check && result.indexOf(check) > -1 : operator === '$=' ? check && result.slice(-check.length) === check : operator === '~=' ? (' ' + result + ' ').indexOf(check) > -1 : operator === '|=' ? result === check || result.slice(0, check.length + 1) === check + '-' : false;
          };
        },
        CHILD: function (type, what, argument, first, last) {
          var simple = type.slice(0, 3) !== 'nth', forward = type.slice(-4) !== 'last', ofType = what === 'of-type';
          return first === 1 && last === 0 ? function (elem) {
            return !!elem.parentNode;
          } : function (elem, context, xml) {
            var cache, outerCache, node, diff, nodeIndex, start, dir = simple !== forward ? 'nextSibling' : 'previousSibling', parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), useCache = !xml && !ofType;
            if (parent) {
              if (simple) {
                while (dir) {
                  node = elem;
                  while (node = node[dir]) {
                    if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) {
                      return false;
                    }
                  }
                  start = dir = type === 'only' && !start && 'nextSibling';
                }
                return true;
              }
              start = [forward ? parent.firstChild : parent.lastChild];
              if (forward && useCache) {
                outerCache = parent[expando] || (parent[expando] = {});
                cache = outerCache[type] || [];
                nodeIndex = cache[0] === dirruns && cache[1];
                diff = cache[0] === dirruns && cache[2];
                node = nodeIndex && parent.childNodes[nodeIndex];
                while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) {
                  if (node.nodeType === 1 && ++diff && node === elem) {
                    outerCache[type] = [
                      dirruns,
                      nodeIndex,
                      diff
                    ];
                    break;
                  }
                }
              } else if (useCache && (cache = (elem[expando] || (elem[expando] = {}))[type]) && cache[0] === dirruns) {
                diff = cache[1];
              } else {
                while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) {
                  if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) {
                    if (useCache) {
                      (node[expando] || (node[expando] = {}))[type] = [
                        dirruns,
                        diff
                      ];
                    }
                    if (node === elem) {
                      break;
                    }
                  }
                }
              }
              diff -= last;
              return diff === first || diff % first === 0 && diff / first >= 0;
            }
          };
        },
        PSEUDO: function (pseudo, argument) {
          var args, fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error('unsupported pseudo: ' + pseudo);
          if (fn[expando]) {
            return fn(argument);
          }
          if (fn.length > 1) {
            args = [
              pseudo,
              pseudo,
              '',
              argument
            ];
            return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function (seed, matches) {
              var idx, matched = fn(seed, argument), i = matched.length;
              while (i--) {
                idx = indexOf$1.call(seed, matched[i]);
                seed[idx] = !(matches[idx] = matched[i]);
              }
            }) : function (elem) {
              return fn(elem, 0, args);
            };
          }
          return fn;
        }
      },
      pseudos: {
        not: markFunction(function (selector) {
          var input = [], results = [], matcher = compile(selector.replace(rtrim, '$1'));
          return matcher[expando] ? markFunction(function (seed, matches, context, xml) {
            var elem, unmatched = matcher(seed, null, xml, []), i = seed.length;
            while (i--) {
              if (elem = unmatched[i]) {
                seed[i] = !(matches[i] = elem);
              }
            }
          }) : function (elem, context, xml) {
            input[0] = elem;
            matcher(input, null, xml, results);
            return !results.pop();
          };
        }),
        has: markFunction(function (selector) {
          return function (elem) {
            return Sizzle(selector, elem).length > 0;
          };
        }),
        contains: markFunction(function (text) {
          text = text.replace(runescape, funescape);
          return function (elem) {
            return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1;
          };
        }),
        lang: markFunction(function (lang) {
          if (!ridentifier.test(lang || '')) {
            Sizzle.error('unsupported lang: ' + lang);
          }
          lang = lang.replace(runescape, funescape).toLowerCase();
          return function (elem) {
            var elemLang;
            do {
              if (elemLang = documentIsHTML ? elem.lang : elem.getAttribute('xml:lang') || elem.getAttribute('lang')) {
                elemLang = elemLang.toLowerCase();
                return elemLang === lang || elemLang.indexOf(lang + '-') === 0;
              }
            } while ((elem = elem.parentNode) && elem.nodeType === 1);
            return false;
          };
        }),
        target: function (elem) {
          var hash = domGlobals.window.location && domGlobals.window.location.hash;
          return hash && hash.slice(1) === elem.id;
        },
        root: function (elem) {
          return elem === docElem;
        },
        focus: function (elem) {
          return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
        },
        enabled: function (elem) {
          return elem.disabled === false;
        },
        disabled: function (elem) {
          return elem.disabled === true;
        },
        checked: function (elem) {
          var nodeName = elem.nodeName.toLowerCase();
          return nodeName === 'input' && !!elem.checked || nodeName === 'option' && !!elem.selected;
        },
        selected: function (elem) {
          if (elem.parentNode) {
            elem.parentNode.selectedIndex;
          }
          return elem.selected === true;
        },
        empty: function (elem) {
          for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
            if (elem.nodeType < 6) {
              return false;
            }
          }
          return true;
        },
        parent: function (elem) {
          return !Expr.pseudos.empty(elem);
        },
        header: function (elem) {
          return rheader.test(elem.nodeName);
        },
        input: function (elem) {
          return rinputs.test(elem.nodeName);
        },
        button: function (elem) {
          var name = elem.nodeName.toLowerCase();
          return name === 'input' && elem.type === 'button' || name === 'button';
        },
        text: function (elem) {
          var attr;
          return elem.nodeName.toLowerCase() === 'input' && elem.type === 'text' && ((attr = elem.getAttribute('type')) == null || attr.toLowerCase() === 'text');
        },
        first: createPositionalPseudo(function () {
          return [0];
        }),
        last: createPositionalPseudo(function (matchIndexes, length) {
          return [length - 1];
        }),
        eq: createPositionalPseudo(function (matchIndexes, length, argument) {
          return [argument < 0 ? argument + length : argument];
        }),
        even: createPositionalPseudo(function (matchIndexes, length) {
          var i = 0;
          for (; i < length; i += 2) {
            matchIndexes.push(i);
          }
          return matchIndexes;
        }),
        odd: createPositionalPseudo(function (matchIndexes, length) {
          var i = 1;
          for (; i < length; i += 2) {
            matchIndexes.push(i);
          }
          return matchIndexes;
        }),
        lt: createPositionalPseudo(function (matchIndexes, length, argument) {
          var i = argument < 0 ? argument + length : argument;
          for (; --i >= 0;) {
            matchIndexes.push(i);
          }
          return matchIndexes;
        }),
        gt: createPositionalPseudo(function (matchIndexes, length, argument) {
          var i = argument < 0 ? argument + length : argument;
          for (; ++i < length;) {
            matchIndexes.push(i);
          }
          return matchIndexes;
        })
      }
    };
    Expr.pseudos.nth = Expr.pseudos.eq;
    for (i in {
        radio: true,
        checkbox: true,
        file: true,
        password: true,
        image: true
      }) {
      Expr.pseudos[i] = createInputPseudo(i);
    }
    for (i in {
        submit: true,
        reset: true
      }) {
      Expr.pseudos[i] = createButtonPseudo(i);
    }
    function setFilters() {
    }
    setFilters.prototype = Expr.filters = Expr.pseudos;
    Expr.setFilters = new setFilters();
    tokenize = Sizzle.tokenize = function (selector, parseOnly) {
      var matched, match, tokens, type, soFar, groups, preFilters, cached = tokenCache[selector + ' '];
      if (cached) {
        return parseOnly ? 0 : cached.slice(0);
      }
      soFar = selector;
      groups = [];
      preFilters = Expr.preFilter;
      while (soFar) {
        if (!matched || (match = rcomma.exec(soFar))) {
          if (match) {
            soFar = soFar.slice(match[0].length) || soFar;
          }
          groups.push(tokens = []);
        }
        matched = false;
        if (match = rcombinators.exec(soFar)) {
          matched = match.shift();
          tokens.push({
            value: matched,
            type: match[0].replace(rtrim, ' ')
          });
          soFar = soFar.slice(matched.length);
        }
        for (type in Expr.filter) {
          if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || (match = preFilters[type](match)))) {
            matched = match.shift();
            tokens.push({
              value: matched,
              type: type,
              matches: match
            });
            soFar = soFar.slice(matched.length);
          }
        }
        if (!matched) {
          break;
        }
      }
      return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : tokenCache(selector, groups).slice(0);
    };
    function toSelector(tokens) {
      var i = 0, len = tokens.length, selector = '';
      for (; i < len; i++) {
        selector += tokens[i].value;
      }
      return selector;
    }
    function addCombinator(matcher, combinator, base) {
      var dir = combinator.dir, checkNonElements = base && dir === 'parentNode', doneName = done++;
      return combinator.first ? function (elem, context, xml) {
        while (elem = elem[dir]) {
          if (elem.nodeType === 1 || checkNonElements) {
            return matcher(elem, context, xml);
          }
        }
      } : function (elem, context, xml) {
        var oldCache, outerCache, newCache = [
            dirruns,
            doneName
          ];
        if (xml) {
          while (elem = elem[dir]) {
            if (elem.nodeType === 1 || checkNonElements) {
              if (matcher(elem, context, xml)) {
                return true;
              }
            }
          }
        } else {
          while (elem = elem[dir]) {
            if (elem.nodeType === 1 || checkNonElements) {
              outerCache = elem[expando] || (elem[expando] = {});
              if ((oldCache = outerCache[dir]) && oldCache[0] === dirruns && oldCache[1] === doneName) {
                return newCache[2] = oldCache[2];
              } else {
                outerCache[dir] = newCache;
                if (newCache[2] = matcher(elem, context, xml)) {
                  return true;
                }
              }
            }
          }
        }
      };
    }
    function elementMatcher(matchers) {
      return matchers.length > 1 ? function (elem, context, xml) {
        var i = matchers.length;
        while (i--) {
          if (!matchers[i](elem, context, xml)) {
            return false;
          }
        }
        return true;
      } : matchers[0];
    }
    function multipleContexts(selector, contexts, results) {
      var i = 0, len = contexts.length;
      for (; i < len; i++) {
        Sizzle(selector, contexts[i], results);
      }
      return results;
    }
    function condense(unmatched, map, filter, context, xml) {
      var elem, newUnmatched = [], i = 0, len = unmatched.length, mapped = map != null;
      for (; i < len; i++) {
        if (elem = unmatched[i]) {
          if (!filter || filter(elem, context, xml)) {
            newUnmatched.push(elem);
            if (mapped) {
              map.push(i);
            }
          }
        }
      }
      return newUnmatched;
    }
    function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) {
      if (postFilter && !postFilter[expando]) {
        postFilter = setMatcher(postFilter);
      }
      if (postFinder && !postFinder[expando]) {
        postFinder = setMatcher(postFinder, postSelector);
      }
      return markFunction(function (seed, results, context, xml) {
        var temp, i, elem, preMap = [], postMap = [], preexisting = results.length, elems = seed || multipleContexts(selector || '*', context.nodeType ? [context] : context, []), matcherIn = preFilter && (seed || !selector) ? condense(elems, preMap, preFilter, context, xml) : elems, matcherOut = matcher ? postFinder || (seed ? preFilter : preexisting || postFilter) ? [] : results : matcherIn;
        if (matcher) {
          matcher(matcherIn, matcherOut, context, xml);
        }
        if (postFilter) {
          temp = condense(matcherOut, postMap);
          postFilter(temp, [], context, xml);
          i = temp.length;
          while (i--) {
            if (elem = temp[i]) {
              matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);
            }
          }
        }
        if (seed) {
          if (postFinder || preFilter) {
            if (postFinder) {
              temp = [];
              i = matcherOut.length;
              while (i--) {
                if (elem = matcherOut[i]) {
                  temp.push(matcherIn[i] = elem);
                }
              }
              postFinder(null, matcherOut = [], temp, xml);
            }
            i = matcherOut.length;
            while (i--) {
              if ((elem = matcherOut[i]) && (temp = postFinder ? indexOf$1.call(seed, elem) : preMap[i]) > -1) {
                seed[temp] = !(results[temp] = elem);
              }
            }
          }
        } else {
          matcherOut = condense(matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut);
          if (postFinder) {
            postFinder(null, results, matcherOut, xml);
          } else {
            push.apply(results, matcherOut);
          }
        }
      });
    }
    function matcherFromTokens(tokens) {
      var checkContext, matcher, j, len = tokens.length, leadingRelative = Expr.relative[tokens[0].type], implicitRelative = leadingRelative || Expr.relative[' '], i = leadingRelative ? 1 : 0, matchContext = addCombinator(function (elem) {
          return elem === checkContext;
        }, implicitRelative, true), matchAnyContext = addCombinator(function (elem) {
          return indexOf$1.call(checkContext, elem) > -1;
        }, implicitRelative, true), matchers = [function (elem, context, xml) {
            return !leadingRelative && (xml || context !== outermostContext) || ((checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml));
          }];
      for (; i < len; i++) {
        if (matcher = Expr.relative[tokens[i].type]) {
          matchers = [addCombinator(elementMatcher(matchers), matcher)];
        } else {
          matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches);
          if (matcher[expando]) {
            j = ++i;
            for (; j < len; j++) {
              if (Expr.relative[tokens[j].type]) {
                break;
              }
            }
            return setMatcher(i > 1 && elementMatcher(matchers), i > 1 && toSelector(tokens.slice(0, i - 1).concat({ value: tokens[i - 2].type === ' ' ? '*' : '' })).replace(rtrim, '$1'), matcher, i < j && matcherFromTokens(tokens.slice(i, j)), j < len && matcherFromTokens(tokens = tokens.slice(j)), j < len && toSelector(tokens));
          }
          matchers.push(matcher);
        }
      }
      return elementMatcher(matchers);
    }
    function matcherFromGroupMatchers(elementMatchers, setMatchers) {
      var bySet = setMatchers.length > 0, byElement = elementMatchers.length > 0, superMatcher = function (seed, context, xml, results, outermost) {
          var elem, j, matcher, matchedCount = 0, i = '0', unmatched = seed && [], setMatched = [], contextBackup = outermostContext, elems = seed || byElement && Expr.find.TAG('*', outermost), dirrunsUnique = dirruns += contextBackup == null ? 1 : Math.random() || 0.1, len = elems.length;
          if (outermost) {
            outermostContext = context !== document && context;
          }
          for (; i !== len && (elem = elems[i]) != null; i++) {
            if (byElement && elem) {
              j = 0;
              while (matcher = elementMatchers[j++]) {
                if (matcher(elem, context, xml)) {
                  results.push(elem);
                  break;
                }
              }
              if (outermost) {
                dirruns = dirrunsUnique;
              }
            }
            if (bySet) {
              if (elem = !matcher && elem) {
                matchedCount--;
              }
              if (seed) {
                unmatched.push(elem);
              }
            }
          }
          matchedCount += i;
          if (bySet && i !== matchedCount) {
            j = 0;
            while (matcher = setMatchers[j++]) {
              matcher(unmatched, setMatched, context, xml);
            }
            if (seed) {
              if (matchedCount > 0) {
                while (i--) {
                  if (!(unmatched[i] || setMatched[i])) {
                    setMatched[i] = pop.call(results);
                  }
                }
              }
              setMatched = condense(setMatched);
            }
            push.apply(results, setMatched);
            if (outermost && !seed && setMatched.length > 0 && matchedCount + setMatchers.length > 1) {
              Sizzle.uniqueSort(results);
            }
          }
          if (outermost) {
            dirruns = dirrunsUnique;
            outermostContext = contextBackup;
          }
          return unmatched;
        };
      return bySet ? markFunction(superMatcher) : superMatcher;
    }
    compile = Sizzle.compile = function (selector, match) {
      var i, setMatchers = [], elementMatchers = [], cached = compilerCache[selector + ' '];
      if (!cached) {
        if (!match) {
          match = tokenize(selector);
        }
        i = match.length;
        while (i--) {
          cached = matcherFromTokens(match[i]);
          if (cached[expando]) {
            setMatchers.push(cached);
          } else {
            elementMatchers.push(cached);
          }
        }
        cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers));
        cached.selector = selector;
      }
      return cached;
    };
    select = Sizzle.select = function (selector, context, results, seed) {
      var i, tokens, token, type, find, compiled = typeof selector === 'function' && selector, match = !seed && tokenize(selector = compiled.selector || selector);
      results = results || [];
      if (match.length === 1) {
        tokens = match[0] = match[0].slice(0);
        if (tokens.length > 2 && (token = tokens[0]).type === 'ID' && support.getById && context.nodeType === 9 && documentIsHTML && Expr.relative[tokens[1].type]) {
          context = (Expr.find.ID(token.matches[0].replace(runescape, funescape), context) || [])[0];
          if (!context) {
            return results;
          } else if (compiled) {
            context = context.parentNode;
          }
          selector = selector.slice(tokens.shift().value.length);
        }
        i = matchExpr.needsContext.test(selector) ? 0 : tokens.length;
        while (i--) {
          token = tokens[i];
          if (Expr.relative[type = token.type]) {
            break;
          }
          if (find = Expr.find[type]) {
            if (seed = find(token.matches[0].replace(runescape, funescape), rsibling.test(tokens[0].type) && testContext(context.parentNode) || context)) {
              tokens.splice(i, 1);
              selector = seed.length && toSelector(tokens);
              if (!selector) {
                push.apply(results, seed);
                return results;
              }
              break;
            }
          }
        }
      }
      (compiled || compile(selector, match))(seed, context, !documentIsHTML, results, rsibling.test(selector) && testContext(context.parentNode) || context);
      return results;
    };
    support.sortStable = expando.split('').sort(sortOrder).join('') === expando;
    support.detectDuplicates = !!hasDuplicate;
    setDocument();
    support.sortDetached = true;

    var isArray$1 = Array.isArray;
    var toArray = function (obj) {
      var array = obj, i, l;
      if (!isArray$1(obj)) {
        array = [];
        for (i = 0, l = obj.length; i < l; i++) {
          array[i] = obj[i];
        }
      }
      return array;
    };
    var each$1 = function (o, cb, s) {
      var n, l;
      if (!o) {
        return 0;
      }
      s = s || o;
      if (o.length !== undefined) {
        for (n = 0, l = o.length; n < l; n++) {
          if (cb.call(s, o[n], n, o) === false) {
            return 0;
          }
        }
      } else {
        for (n in o) {
          if (o.hasOwnProperty(n)) {
            if (cb.call(s, o[n], n, o) === false) {
              return 0;
            }
          }
        }
      }
      return 1;
    };
    var map$1 = function (array, callback) {
      var out = [];
      each$1(array, function (item, index) {
        out.push(callback(item, index, array));
      });
      return out;
    };
    var filter$1 = function (a, f) {
      var o = [];
      each$1(a, function (v, index) {
        if (!f || f(v, index, a)) {
          o.push(v);
        }
      });
      return o;
    };
    var indexOf$2 = function (a, v) {
      var i, l;
      if (a) {
        for (i = 0, l = a.length; i < l; i++) {
          if (a[i] === v) {
            return i;
          }
        }
      }
      return -1;
    };
    var reduce = function (collection, iteratee, accumulator, thisArg) {
      var i = 0;
      if (arguments.length < 3) {
        accumulator = collection[0];
      }
      for (; i < collection.length; i++) {
        accumulator = iteratee.call(thisArg, accumulator, collection[i], i);
      }
      return accumulator;
    };
    var findIndex$1 = function (array, predicate, thisArg) {
      var i, l;
      for (i = 0, l = array.length; i < l; i++) {
        if (predicate.call(thisArg, array[i], i, array)) {
          return i;
        }
      }
      return -1;
    };
    var find$1 = function (array, predicate, thisArg) {
      var idx = findIndex$1(array, predicate, thisArg);
      if (idx !== -1) {
        return array[idx];
      }
      return undefined;
    };
    var last$1 = function (collection) {
      return collection[collection.length - 1];
    };
    var ArrUtils = {
      isArray: isArray$1,
      toArray: toArray,
      each: each$1,
      map: map$1,
      filter: filter$1,
      indexOf: indexOf$2,
      reduce: reduce,
      findIndex: findIndex$1,
      find: find$1,
      last: last$1
    };

    var whiteSpaceRegExp = /^\s*|\s*$/g;
    var trim = function (str) {
      return str === null || str === undefined ? '' : ('' + str).replace(whiteSpaceRegExp, '');
    };
    var is = function (obj, type) {
      if (!type) {
        return obj !== undefined;
      }
      if (type === 'array' && ArrUtils.isArray(obj)) {
        return true;
      }
      return typeof obj === type;
    };
    var makeMap = function (items, delim, map) {
      var i;
      items = items || [];
      delim = delim || ',';
      if (typeof items === 'string') {
        items = items.split(delim);
      }
      map = map || {};
      i = items.length;
      while (i--) {
        map[items[i]] = {};
      }
      return map;
    };
    var hasOwnProperty = function (obj, prop) {
      return Object.prototype.hasOwnProperty.call(obj, prop);
    };
    var create = function (s, p, root) {
      var self = this;
      var sp, ns, cn, scn, c, de = 0;
      s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
      cn = s[3].match(/(^|\.)(\w+)$/i)[2];
      ns = self.createNS(s[3].replace(/\.\w+$/, ''), root);
      if (ns[cn]) {
        return;
      }
      if (s[2] === 'static') {
        ns[cn] = p;
        if (this.onCreate) {
          this.onCreate(s[2], s[3], ns[cn]);
        }
        return;
      }
      if (!p[cn]) {
        p[cn] = function () {
        };
        de = 1;
      }
      ns[cn] = p[cn];
      self.extend(ns[cn].prototype, p);
      if (s[5]) {
        sp = self.resolve(s[5]).prototype;
        scn = s[5].match(/\.(\w+)$/i)[1];
        c = ns[cn];
        if (de) {
          ns[cn] = function () {
            return sp[scn].apply(this, arguments);
          };
        } else {
          ns[cn] = function () {
            this.parent = sp[scn];
            return c.apply(this, arguments);
          };
        }
        ns[cn].prototype[cn] = ns[cn];
        self.each(sp, function (f, n) {
          ns[cn].prototype[n] = sp[n];
        });
        self.each(p, function (f, n) {
          if (sp[n]) {
            ns[cn].prototype[n] = function () {
              this.parent = sp[n];
              return f.apply(this, arguments);
            };
          } else {
            if (n !== cn) {
              ns[cn].prototype[n] = f;
            }
          }
        });
      }
      self.each(p.static, function (f, n) {
        ns[cn][n] = f;
      });
    };
    var extend = function (obj, ext) {
      var x = [];
      for (var _i = 2; _i < arguments.length; _i++) {
        x[_i - 2] = arguments[_i];
      }
      var i, l, name;
      var args = arguments;
      var value;
      for (i = 1, l = args.length; i < l; i++) {
        ext = args[i];
        for (name in ext) {
          if (ext.hasOwnProperty(name)) {
            value = ext[name];
            if (value !== undefined) {
              obj[name] = value;
            }
          }
        }
      }
      return obj;
    };
    var walk = function (o, f, n, s) {
      s = s || this;
      if (o) {
        if (n) {
          o = o[n];
        }
        ArrUtils.each(o, function (o, i) {
          if (f.call(s, o, i, n) === false) {
            return false;
          }
          walk(o, f, n, s);
        });
      }
    };
    var createNS = function (n, o) {
      var i, v;
      o = o || domGlobals.window;
      n = n.split('.');
      for (i = 0; i < n.length; i++) {
        v = n[i];
        if (!o[v]) {
          o[v] = {};
        }
        o = o[v];
      }
      return o;
    };
    var resolve$1 = function (n, o) {
      var i, l;
      o = o || domGlobals.window;
      n = n.split('.');
      for (i = 0, l = n.length; i < l; i++) {
        o = o[n[i]];
        if (!o) {
          break;
        }
      }
      return o;
    };
    var explode = function (s, d) {
      if (!s || is(s, 'array')) {
        return s;
      }
      return ArrUtils.map(s.split(d || ','), trim);
    };
    var _addCacheSuffix = function (url) {
      var cacheSuffix = Env.cacheSuffix;
      if (cacheSuffix) {
        url += (url.indexOf('?') === -1 ? '?' : '&') + cacheSuffix;
      }
      return url;
    };
    var Tools = {
      trim: trim,
      isArray: ArrUtils.isArray,
      is: is,
      toArray: ArrUtils.toArray,
      makeMap: makeMap,
      each: ArrUtils.each,
      map: ArrUtils.map,
      grep: ArrUtils.filter,
      inArray: ArrUtils.indexOf,
      hasOwn: hasOwnProperty,
      extend: extend,
      create: create,
      walk: walk,
      createNS: createNS,
      resolve: resolve$1,
      explode: explode,
      _addCacheSuffix: _addCacheSuffix
    };

    var doc = domGlobals.document, push$1 = Array.prototype.push, slice$1 = Array.prototype.slice;
    var rquickExpr$1 = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;
    var Event = EventUtils.Event;
    var skipUniques = Tools.makeMap('children,contents,next,prev');
    var isDefined = function (obj) {
      return typeof obj !== 'undefined';
    };
    var isString$1 = function (obj) {
      return typeof obj === 'string';
    };
    var isWindow = function (obj) {
      return obj && obj === obj.window;
    };
    var createFragment = function (html, fragDoc) {
      var frag, node, container;
      fragDoc = fragDoc || doc;
      container = fragDoc.createElement('div');
      frag = fragDoc.createDocumentFragment();
      container.innerHTML = html;
      while (node = container.firstChild) {
        frag.appendChild(node);
      }
      return frag;
    };
    var domManipulate = function (targetNodes, sourceItem, callback, reverse) {
      var i;
      if (isString$1(sourceItem)) {
        sourceItem = createFragment(sourceItem, getElementDocument(targetNodes[0]));
      } else if (sourceItem.length && !sourceItem.nodeType) {
        sourceItem = DomQuery.makeArray(sourceItem);
        if (reverse) {
          for (i = sourceItem.length - 1; i >= 0; i--) {
            domManipulate(targetNodes, sourceItem[i], callback, reverse);
          }
        } else {
          for (i = 0; i < sourceItem.length; i++) {
            domManipulate(targetNodes, sourceItem[i], callback, reverse);
          }
        }
        return targetNodes;
      }
      if (sourceItem.nodeType) {
        i = targetNodes.length;
        while (i--) {
          callback.call(targetNodes[i], sourceItem);
        }
      }
      return targetNodes;
    };
    var hasClass = function (node, className) {
      return node && className && (' ' + node.className + ' ').indexOf(' ' + className + ' ') !== -1;
    };
    var wrap = function (elements, wrapper, all) {
      var lastParent, newWrapper;
      wrapper = DomQuery(wrapper)[0];
      elements.each(function () {
        var self = this;
        if (!all || lastParent !== self.parentNode) {
          lastParent = self.parentNode;
          newWrapper = wrapper.cloneNode(false);
          self.parentNode.insertBefore(newWrapper, self);
          newWrapper.appendChild(self);
        } else {
          newWrapper.appendChild(self);
        }
      });
      return elements;
    };
    var numericCssMap = Tools.makeMap('fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom', ' ');
    var booleanMap = Tools.makeMap('checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected', ' ');
    var propFix = {
      for: 'htmlFor',
      class: 'className',
      readonly: 'readOnly'
    };
    var cssFix = { float: 'cssFloat' };
    var attrHooks = {}, cssHooks = {};
    var DomQuery = function (selector, context) {
      return new DomQuery.fn.init(selector, context);
    };
    var inArray = function (item, array) {
      var i;
      if (array.indexOf) {
        return array.indexOf(item);
      }
      i = array.length;
      while (i--) {
        if (array[i] === item) {
          return i;
        }
      }
      return -1;
    };
    var whiteSpaceRegExp$1 = /^\s*|\s*$/g;
    var trim$1 = function (str) {
      return str === null || str === undefined ? '' : ('' + str).replace(whiteSpaceRegExp$1, '');
    };
    var each$2 = function (obj, callback) {
      var length, key, i, value;
      if (obj) {
        length = obj.length;
        if (length === undefined) {
          for (key in obj) {
            if (obj.hasOwnProperty(key)) {
              value = obj[key];
              if (callback.call(value, key, value) === false) {
                break;
              }
            }
          }
        } else {
          for (i = 0; i < length; i++) {
            value = obj[i];
            if (callback.call(value, i, value) === false) {
              break;
            }
          }
        }
      }
      return obj;
    };
    var grep = function (array, callback) {
      var out = [];
      each$2(array, function (i, item) {
        if (callback(item, i)) {
          out.push(item);
        }
      });
      return out;
    };
    var getElementDocument = function (element) {
      if (!element) {
        return doc;
      }
      if (element.nodeType === 9) {
        return element;
      }
      return element.ownerDocument;
    };
    DomQuery.fn = DomQuery.prototype = {
      constructor: DomQuery,
      selector: '',
      context: null,
      length: 0,
      init: function (selector, context) {
        var self = this;
        var match, node;
        if (!selector) {
          return self;
        }
        if (selector.nodeType) {
          self.context = self[0] = selector;
          self.length = 1;
          return self;
        }
        if (context && context.nodeType) {
          self.context = context;
        } else {
          if (context) {
            return DomQuery(selector).attr(context);
          }
          self.context = context = domGlobals.document;
        }
        if (isString$1(selector)) {
          self.selector = selector;
          if (selector.charAt(0) === '<' && selector.charAt(selector.length - 1) === '>' && selector.length >= 3) {
            match = [
              null,
              selector,
              null
            ];
          } else {
            match = rquickExpr$1.exec(selector);
          }
          if (match) {
            if (match[1]) {
              node = createFragment(selector, getElementDocument(context)).firstChild;
              while (node) {
                push$1.call(self, node);
                node = node.nextSibling;
              }
            } else {
              node = getElementDocument(context).getElementById(match[2]);
              if (!node) {
                return self;
              }
              if (node.id !== match[2]) {
                return self.find(selector);
              }
              self.length = 1;
              self[0] = node;
            }
          } else {
            return DomQuery(context).find(selector);
          }
        } else {
          this.add(selector, false);
        }
        return self;
      },
      toArray: function () {
        return Tools.toArray(this);
      },
      add: function (items, sort) {
        var self = this;
        var nodes, i;
        if (isString$1(items)) {
          return self.add(DomQuery(items));
        }
        if (sort !== false) {
          nodes = DomQuery.unique(self.toArray().concat(DomQuery.makeArray(items)));
          self.length = nodes.length;
          for (i = 0; i < nodes.length; i++) {
            self[i] = nodes[i];
          }
        } else {
          push$1.apply(self, DomQuery.makeArray(items));
        }
        return self;
      },
      attr: function (name, value) {
        var self = this;
        var hook;
        if (typeof name === 'object') {
          each$2(name, function (name, value) {
            self.attr(name, value);
          });
        } else if (isDefined(value)) {
          this.each(function () {
            var hook;
            if (this.nodeType === 1) {
              hook = attrHooks[name];
              if (hook && hook.set) {
                hook.set(this, value);
                return;
              }
              if (value === null) {
                this.removeAttribute(name, 2);
              } else {
                this.setAttribute(name, value, 2);
              }
            }
          });
        } else {
          if (self[0] && self[0].nodeType === 1) {
            hook = attrHooks[name];
            if (hook && hook.get) {
              return hook.get(self[0], name);
            }
            if (booleanMap[name]) {
              return self.prop(name) ? name : undefined;
            }
            value = self[0].getAttribute(name, 2);
            if (value === null) {
              value = undefined;
            }
          }
          return value;
        }
        return self;
      },
      removeAttr: function (name) {
        return this.attr(name, null);
      },
      prop: function (name, value) {
        var self = this;
        name = propFix[name] || name;
        if (typeof name === 'object') {
          each$2(name, function (name, value) {
            self.prop(name, value);
          });
        } else if (isDefined(value)) {
          this.each(function () {
            if (this.nodeType === 1) {
              this[name] = value;
            }
          });
        } else {
          if (self[0] && self[0].nodeType && name in self[0]) {
            return self[0][name];
          }
          return value;
        }
        return self;
      },
      css: function (name, value) {
        var self = this;
        var elm, hook;
        var camel = function (name) {
          return name.replace(/-(\D)/g, function (a, b) {
            return b.toUpperCase();
          });
        };
        var dashed = function (name) {
          return name.replace(/[A-Z]/g, function (a) {
            return '-' + a;
          });
        };
        if (typeof name === 'object') {
          each$2(name, function (name, value) {
            self.css(name, value);
          });
        } else {
          if (isDefined(value)) {
            name = camel(name);
            if (typeof value === 'number' && !numericCssMap[name]) {
              value = value.toString() + 'px';
            }
            self.each(function () {
              var style = this.style;
              hook = cssHooks[name];
              if (hook && hook.set) {
                hook.set(this, value);
                return;
              }
              try {
                this.style[cssFix[name] || name] = value;
              } catch (ex) {
              }
              if (value === null || value === '') {
                if (style.removeProperty) {
                  style.removeProperty(dashed(name));
                } else {
                  style.removeAttribute(name);
                }
              }
            });
          } else {
            elm = self[0];
            hook = cssHooks[name];
            if (hook && hook.get) {
              return hook.get(elm);
            }
            if (elm.ownerDocument.defaultView) {
              try {
                return elm.ownerDocument.defaultView.getComputedStyle(elm, null).getPropertyValue(dashed(name));
              } catch (ex) {
                return undefined;
              }
            } else if (elm.currentStyle) {
              return elm.currentStyle[camel(name)];
            } else {
              return '';
            }
          }
        }
        return self;
      },
      remove: function () {
        var self = this;
        var node, i = this.length;
        while (i--) {
          node = self[i];
          Event.clean(node);
          if (node.parentNode) {
            node.parentNode.removeChild(node);
          }
        }
        return this;
      },
      empty: function () {
        var self = this;
        var node, i = this.length;
        while (i--) {
          node = self[i];
          while (node.firstChild) {
            node.removeChild(node.firstChild);
          }
        }
        return this;
      },
      html: function (value) {
        var self = this;
        var i;
        if (isDefined(value)) {
          i = self.length;
          try {
            while (i--) {
              self[i].innerHTML = value;
            }
          } catch (ex) {
            DomQuery(self[i]).empty().append(value);
          }
          return self;
        }
        return self[0] ? self[0].innerHTML : '';
      },
      text: function (value) {
        var self = this;
        var i;
        if (isDefined(value)) {
          i = self.length;
          while (i--) {
            if ('innerText' in self[i]) {
              self[i].innerText = value;
            } else {
              self[0].textContent = value;
            }
          }
          return self;
        }
        return self[0] ? self[0].innerText || self[0].textContent : '';
      },
      append: function () {
        return domManipulate(this, arguments, function (node) {
          if (this.nodeType === 1 || this.host && this.host.nodeType === 1) {
            this.appendChild(node);
          }
        });
      },
      prepend: function () {
        return domManipulate(this, arguments, function (node) {
          if (this.nodeType === 1 || this.host && this.host.nodeType === 1) {
            this.insertBefore(node, this.firstChild);
          }
        }, true);
      },
      before: function () {
        var self = this;
        if (self[0] && self[0].parentNode) {
          return domManipulate(self, arguments, function (node) {
            this.parentNode.insertBefore(node, this);
          });
        }
        return self;
      },
      after: function () {
        var self = this;
        if (self[0] && self[0].parentNode) {
          return domManipulate(self, arguments, function (node) {
            this.parentNode.insertBefore(node, this.nextSibling);
          }, true);
        }
        return self;
      },
      appendTo: function (val) {
        DomQuery(val).append(this);
        return this;
      },
      prependTo: function (val) {
        DomQuery(val).prepend(this);
        return this;
      },
      replaceWith: function (content) {
        return this.before(content).remove();
      },
      wrap: function (content) {
        return wrap(this, content);
      },
      wrapAll: function (content) {
        return wrap(this, content, true);
      },
      wrapInner: function (content) {
        this.each(function () {
          DomQuery(this).contents().wrapAll(content);
        });
        return this;
      },
      unwrap: function () {
        return this.parent().each(function () {
          DomQuery(this).replaceWith(this.childNodes);
        });
      },
      clone: function () {
        var result = [];
        this.each(function () {
          result.push(this.cloneNode(true));
        });
        return DomQuery(result);
      },
      addClass: function (className) {
        return this.toggleClass(className, true);
      },
      removeClass: function (className) {
        return this.toggleClass(className, false);
      },
      toggleClass: function (className, state) {
        var self = this;
        if (typeof className !== 'string') {
          return self;
        }
        if (className.indexOf(' ') !== -1) {
          each$2(className.split(' '), function () {
            self.toggleClass(this, state);
          });
        } else {
          self.each(function (index, node) {
            var existingClassName, classState;
            classState = hasClass(node, className);
            if (classState !== state) {
              existingClassName = node.className;
              if (classState) {
                node.className = trim$1((' ' + existingClassName + ' ').replace(' ' + className + ' ', ' '));
              } else {
                node.className += existingClassName ? ' ' + className : className;
              }
            }
          });
        }
        return self;
      },
      hasClass: function (className) {
        return hasClass(this[0], className);
      },
      each: function (callback) {
        return each$2(this, callback);
      },
      on: function (name, callback) {
        return this.each(function () {
          Event.bind(this, name, callback);
        });
      },
      off: function (name, callback) {
        return this.each(function () {
          Event.unbind(this, name, callback);
        });
      },
      trigger: function (name) {
        return this.each(function () {
          if (typeof name === 'object') {
            Event.fire(this, name.type, name);
          } else {
            Event.fire(this, name);
          }
        });
      },
      show: function () {
        return this.css('display', '');
      },
      hide: function () {
        return this.css('display', 'none');
      },
      slice: function () {
        return new DomQuery(slice$1.apply(this, arguments));
      },
      eq: function (index) {
        return index === -1 ? this.slice(index) : this.slice(index, +index + 1);
      },
      first: function () {
        return this.eq(0);
      },
      last: function () {
        return this.eq(-1);
      },
      find: function (selector) {
        var i, l;
        var ret = [];
        for (i = 0, l = this.length; i < l; i++) {
          DomQuery.find(selector, this[i], ret);
        }
        return DomQuery(ret);
      },
      filter: function (selector) {
        if (typeof selector === 'function') {
          return DomQuery(grep(this.toArray(), function (item, i) {
            return selector(i, item);
          }));
        }
        return DomQuery(DomQuery.filter(selector, this.toArray()));
      },
      closest: function (selector) {
        var result = [];
        if (selector instanceof DomQuery) {
          selector = selector[0];
        }
        this.each(function (i, node) {
          while (node) {
            if (typeof selector === 'string' && DomQuery(node).is(selector)) {
              result.push(node);
              break;
            } else if (node === selector) {
              result.push(node);
              break;
            }
            node = node.parentNode;
          }
        });
        return DomQuery(result);
      },
      offset: function (offset) {
        var elm, doc, docElm;
        var x = 0, y = 0, pos;
        if (!offset) {
          elm = this[0];
          if (elm) {
            doc = elm.ownerDocument;
            docElm = doc.documentElement;
            if (elm.getBoundingClientRect) {
              pos = elm.getBoundingClientRect();
              x = pos.left + (docElm.scrollLeft || doc.body.scrollLeft) - docElm.clientLeft;
              y = pos.top + (docElm.scrollTop || doc.body.scrollTop) - docElm.clientTop;
            }
          }
          return {
            left: x,
            top: y
          };
        }
        return this.css(offset);
      },
      push: push$1,
      sort: [].sort,
      splice: [].splice
    };
    Tools.extend(DomQuery, {
      extend: Tools.extend,
      makeArray: function (object) {
        if (isWindow(object) || object.nodeType) {
          return [object];
        }
        return Tools.toArray(object);
      },
      inArray: inArray,
      isArray: Tools.isArray,
      each: each$2,
      trim: trim$1,
      grep: grep,
      find: Sizzle,
      expr: Sizzle.selectors,
      unique: Sizzle.uniqueSort,
      text: Sizzle.getText,
      contains: Sizzle.contains,
      filter: function (expr, elems, not) {
        var i = elems.length;
        if (not) {
          expr = ':not(' + expr + ')';
        }
        while (i--) {
          if (elems[i].nodeType !== 1) {
            elems.splice(i, 1);
          }
        }
        if (elems.length === 1) {
          elems = DomQuery.find.matchesSelector(elems[0], expr) ? [elems[0]] : [];
        } else {
          elems = DomQuery.find.matches(expr, elems);
        }
        return elems;
      }
    });
    var dir = function (el, prop, until) {
      var matched = [];
      var cur = el[prop];
      if (typeof until !== 'string' && until instanceof DomQuery) {
        until = until[0];
      }
      while (cur && cur.nodeType !== 9) {
        if (until !== undefined) {
          if (cur === until) {
            break;
          }
          if (typeof until === 'string' && DomQuery(cur).is(until)) {
            break;
          }
        }
        if (cur.nodeType === 1) {
          matched.push(cur);
        }
        cur = cur[prop];
      }
      return matched;
    };
    var sibling = function (node, siblingName, nodeType, until) {
      var result = [];
      if (until instanceof DomQuery) {
        until = until[0];
      }
      for (; node; node = node[siblingName]) {
        if (nodeType && node.nodeType !== nodeType) {
          continue;
        }
        if (until !== undefined) {
          if (node === until) {
            break;
          }
          if (typeof until === 'string' && DomQuery(node).is(until)) {
            break;
          }
        }
        result.push(node);
      }
      return result;
    };
    var firstSibling = function (node, siblingName, nodeType) {
      for (node = node[siblingName]; node; node = node[siblingName]) {
        if (node.nodeType === nodeType) {
          return node;
        }
      }
      return null;
    };
    each$2({
      parent: function (node) {
        var parent = node.parentNode;
        return parent && parent.nodeType !== 11 ? parent : null;
      },
      parents: function (node) {
        return dir(node, 'parentNode');
      },
      next: function (node) {
        return firstSibling(node, 'nextSibling', 1);
      },
      prev: function (node) {
        return firstSibling(node, 'previousSibling', 1);
      },
      children: function (node) {
        return sibling(node.firstChild, 'nextSibling', 1);
      },
      contents: function (node) {
        return Tools.toArray((node.nodeName === 'iframe' ? node.contentDocument || node.contentWindow.document : node).childNodes);
      }
    }, function (name, fn) {
      DomQuery.fn[name] = function (selector) {
        var self = this;
        var result = [];
        self.each(function () {
          var nodes = fn.call(result, this, selector, result);
          if (nodes) {
            if (DomQuery.isArray(nodes)) {
              result.push.apply(result, nodes);
            } else {
              result.push(nodes);
            }
          }
        });
        if (this.length > 1) {
          if (!skipUniques[name]) {
            result = DomQuery.unique(result);
          }
          if (name.indexOf('parents') === 0) {
            result = result.reverse();
          }
        }
        result = DomQuery(result);
        if (selector) {
          return result.filter(selector);
        }
        return result;
      };
    });
    each$2({
      parentsUntil: function (node, until) {
        return dir(node, 'parentNode', until);
      },
      nextUntil: function (node, until) {
        return sibling(node, 'nextSibling', 1, until).slice(1);
      },
      prevUntil: function (node, until) {
        return sibling(node, 'previousSibling', 1, until).slice(1);
      }
    }, function (name, fn) {
      DomQuery.fn[name] = function (selector, filter) {
        var self = this;
        var result = [];
        self.each(function () {
          var nodes = fn.call(result, this, selector, result);
          if (nodes) {
            if (DomQuery.isArray(nodes)) {
              result.push.apply(result, nodes);
            } else {
              result.push(nodes);
            }
          }
        });
        if (this.length > 1) {
          result = DomQuery.unique(result);
          if (name.indexOf('parents') === 0 || name === 'prevUntil') {
            result = result.reverse();
          }
        }
        result = DomQuery(result);
        if (filter) {
          return result.filter(filter);
        }
        return result;
      };
    });
    DomQuery.fn.is = function (selector) {
      return !!selector && this.filter(selector).length > 0;
    };
    DomQuery.fn.init.prototype = DomQuery.fn;
    DomQuery.overrideDefaults = function (callback) {
      var defaults;
      var sub = function (selector, context) {
        defaults = defaults || callback();
        if (arguments.length === 0) {
          selector = defaults.element;
        }
        if (!context) {
          context = defaults.context;
        }
        return new sub.fn.init(selector, context);
      };
      DomQuery.extend(sub, this);
      return sub;
    };
    var appendHooks = function (targetHooks, prop, hooks) {
      each$2(hooks, function (name, func) {
        targetHooks[name] = targetHooks[name] || {};
        targetHooks[name][prop] = func;
      });
    };
    if (Env.ie && Env.ie < 8) {
      appendHooks(attrHooks, 'get', {
        maxlength: function (elm) {
          var value = elm.maxLength;
          if (value === 2147483647) {
            return undefined;
          }
          return value;
        },
        size: function (elm) {
          var value = elm.size;
          if (value === 20) {
            return undefined;
          }
          return value;
        },
        class: function (elm) {
          return elm.className;
        },
        style: function (elm) {
          var value = elm.style.cssText;
          if (value.length === 0) {
            return undefined;
          }
          return value;
        }
      });
      appendHooks(attrHooks, 'set', {
        class: function (elm, value) {
          elm.className = value;
        },
        style: function (elm, value) {
          elm.style.cssText = value;
        }
      });
    }
    if (Env.ie && Env.ie < 9) {
      cssFix.float = 'styleFloat';
      appendHooks(cssHooks, 'set', {
        opacity: function (elm, value) {
          var style = elm.style;
          if (value === null || value === '') {
            style.removeAttribute('filter');
          } else {
            style.zoom = 1;
            style.filter = 'alpha(opacity=' + value * 100 + ')';
          }
        }
      });
    }
    DomQuery.attrHooks = attrHooks;
    DomQuery.cssHooks = cssHooks;

    var cached = function (f) {
      var called = false;
      var r;
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        if (!called) {
          called = true;
          r = f.apply(null, args);
        }
        return r;
      };
    };

    var firstMatch = function (regexes, s) {
      for (var i = 0; i < regexes.length; i++) {
        var x = regexes[i];
        if (x.test(s)) {
          return x;
        }
      }
      return undefined;
    };
    var find$2 = function (regexes, agent) {
      var r = firstMatch(regexes, agent);
      if (!r) {
        return {
          major: 0,
          minor: 0
        };
      }
      var group = function (i) {
        return Number(agent.replace(r, '$' + i));
      };
      return nu(group(1), group(2));
    };
    var detect = function (versionRegexes, agent) {
      var cleanedAgent = String(agent).toLowerCase();
      if (versionRegexes.length === 0) {
        return unknown();
      }
      return find$2(versionRegexes, cleanedAgent);
    };
    var unknown = function () {
      return nu(0, 0);
    };
    var nu = function (major, minor) {
      return {
        major: major,
        minor: minor
      };
    };
    var Version = {
      nu: nu,
      detect: detect,
      unknown: unknown
    };

    var edge = 'Edge';
    var chrome = 'Chrome';
    var ie$1 = 'IE';
    var opera$1 = 'Opera';
    var firefox = 'Firefox';
    var safari = 'Safari';
    var isBrowser = function (name, current) {
      return function () {
        return current === name;
      };
    };
    var unknown$1 = function () {
      return nu$1({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$1 = function (info) {
      var current = info.current;
      var version = info.version;
      return {
        current: current,
        version: version,
        isEdge: isBrowser(edge, current),
        isChrome: isBrowser(chrome, current),
        isIE: isBrowser(ie$1, current),
        isOpera: isBrowser(opera$1, current),
        isFirefox: isBrowser(firefox, current),
        isSafari: isBrowser(safari, current)
      };
    };
    var Browser = {
      unknown: unknown$1,
      nu: nu$1,
      edge: constant(edge),
      chrome: constant(chrome),
      ie: constant(ie$1),
      opera: constant(opera$1),
      firefox: constant(firefox),
      safari: constant(safari)
    };

    var windows = 'Windows';
    var ios = 'iOS';
    var android$1 = 'Android';
    var linux = 'Linux';
    var osx = 'OSX';
    var solaris = 'Solaris';
    var freebsd = 'FreeBSD';
    var isOS = function (name, current) {
      return function () {
        return current === name;
      };
    };
    var unknown$2 = function () {
      return nu$2({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$2 = function (info) {
      var current = info.current;
      var version = info.version;
      return {
        current: current,
        version: version,
        isWindows: isOS(windows, current),
        isiOS: isOS(ios, current),
        isAndroid: isOS(android$1, current),
        isOSX: isOS(osx, current),
        isLinux: isOS(linux, current),
        isSolaris: isOS(solaris, current),
        isFreeBSD: isOS(freebsd, current)
      };
    };
    var OperatingSystem = {
      unknown: unknown$2,
      nu: nu$2,
      windows: constant(windows),
      ios: constant(ios),
      android: constant(android$1),
      linux: constant(linux),
      osx: constant(osx),
      solaris: constant(solaris),
      freebsd: constant(freebsd)
    };

    var DeviceType = function (os, browser, userAgent) {
      var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
      var isiPhone = os.isiOS() && !isiPad;
      var isAndroid3 = os.isAndroid() && os.version.major === 3;
      var isAndroid4 = os.isAndroid() && os.version.major === 4;
      var isTablet = isiPad || isAndroid3 || isAndroid4 && /mobile/i.test(userAgent) === true;
      var isTouch = os.isiOS() || os.isAndroid();
      var isPhone = isTouch && !isTablet;
      var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
      return {
        isiPad: constant(isiPad),
        isiPhone: constant(isiPhone),
        isTablet: constant(isTablet),
        isPhone: constant(isPhone),
        isTouch: constant(isTouch),
        isAndroid: os.isAndroid,
        isiOS: os.isiOS,
        isWebView: constant(iOSwebview)
      };
    };

    var detect$1 = function (candidates, userAgent) {
      var agent = String(userAgent).toLowerCase();
      return find(candidates, function (candidate) {
        return candidate.search(agent);
      });
    };
    var detectBrowser = function (browsers, userAgent) {
      return detect$1(browsers, userAgent).map(function (browser) {
        var version = Version.detect(browser.versionRegexes, userAgent);
        return {
          current: browser.name,
          version: version
        };
      });
    };
    var detectOs = function (oses, userAgent) {
      return detect$1(oses, userAgent).map(function (os) {
        var version = Version.detect(os.versionRegexes, userAgent);
        return {
          current: os.name,
          version: version
        };
      });
    };
    var UaString = {
      detectBrowser: detectBrowser,
      detectOs: detectOs
    };

    var contains$2 = function (str, substr) {
      return str.indexOf(substr) !== -1;
    };
    var trim$2 = function (str) {
      return str.replace(/^\s+|\s+$/g, '');
    };
    var lTrim = function (str) {
      return str.replace(/^\s+/g, '');
    };
    var rTrim = function (str) {
      return str.replace(/\s+$/g, '');
    };

    var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
    var checkContains = function (target) {
      return function (uastring) {
        return contains$2(uastring, target);
      };
    };
    var browsers = [
      {
        name: 'Edge',
        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
        search: function (uastring) {
          return contains$2(uastring, 'edge/') && contains$2(uastring, 'chrome') && contains$2(uastring, 'safari') && contains$2(uastring, 'applewebkit');
        }
      },
      {
        name: 'Chrome',
        versionRegexes: [
          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
          normalVersionRegex
        ],
        search: function (uastring) {
          return contains$2(uastring, 'chrome') && !contains$2(uastring, 'chromeframe');
        }
      },
      {
        name: 'IE',
        versionRegexes: [
          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
          /.*?rv:([0-9]+)\.([0-9]+).*/
        ],
        search: function (uastring) {
          return contains$2(uastring, 'msie') || contains$2(uastring, 'trident');
        }
      },
      {
        name: 'Opera',
        versionRegexes: [
          normalVersionRegex,
          /.*?opera\/([0-9]+)\.([0-9]+).*/
        ],
        search: checkContains('opera')
      },
      {
        name: 'Firefox',
        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
        search: checkContains('firefox')
      },
      {
        name: 'Safari',
        versionRegexes: [
          normalVersionRegex,
          /.*?cpu os ([0-9]+)_([0-9]+).*/
        ],
        search: function (uastring) {
          return (contains$2(uastring, 'safari') || contains$2(uastring, 'mobile/')) && contains$2(uastring, 'applewebkit');
        }
      }
    ];
    var oses = [
      {
        name: 'Windows',
        search: checkContains('win'),
        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'iOS',
        search: function (uastring) {
          return contains$2(uastring, 'iphone') || contains$2(uastring, 'ipad');
        },
        versionRegexes: [
          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
          /.*cpu os ([0-9]+)_([0-9]+).*/,
          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
        ]
      },
      {
        name: 'Android',
        search: checkContains('android'),
        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'OSX',
        search: checkContains('os x'),
        versionRegexes: [/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]
      },
      {
        name: 'Linux',
        search: checkContains('linux'),
        versionRegexes: []
      },
      {
        name: 'Solaris',
        search: checkContains('sunos'),
        versionRegexes: []
      },
      {
        name: 'FreeBSD',
        search: checkContains('freebsd'),
        versionRegexes: []
      }
    ];
    var PlatformInfo = {
      browsers: constant(browsers),
      oses: constant(oses)
    };

    var detect$2 = function (userAgent) {
      var browsers = PlatformInfo.browsers();
      var oses = PlatformInfo.oses();
      var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu);
      var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
      var deviceType = DeviceType(os, browser, userAgent);
      return {
        browser: browser,
        os: os,
        deviceType: deviceType
      };
    };
    var PlatformDetection = { detect: detect$2 };

    var detect$3 = cached(function () {
      var userAgent = domGlobals.navigator.userAgent;
      return PlatformDetection.detect(userAgent);
    });
    var PlatformDetection$1 = { detect: detect$3 };

    var fromHtml = function (html, scope) {
      var doc = scope || domGlobals.document;
      var div = doc.createElement('div');
      div.innerHTML = html;
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
        domGlobals.console.error('HTML does not have a single root node', html);
        throw new Error('HTML must have a single root node');
      }
      return fromDom(div.childNodes[0]);
    };
    var fromTag = function (tag, scope) {
      var doc = scope || domGlobals.document;
      var node = doc.createElement(tag);
      return fromDom(node);
    };
    var fromText = function (text, scope) {
      var doc = scope || domGlobals.document;
      var node = doc.createTextNode(text);
      return fromDom(node);
    };
    var fromDom = function (node) {
      if (node === null || node === undefined) {
        throw new Error('Node cannot be null or undefined');
      }
      return { dom: constant(node) };
    };
    var fromPoint = function (docElm, x, y) {
      var doc = docElm.dom();
      return Option.from(doc.elementFromPoint(x, y)).map(fromDom);
    };
    var Element = {
      fromHtml: fromHtml,
      fromTag: fromTag,
      fromText: fromText,
      fromDom: fromDom,
      fromPoint: fromPoint
    };

    var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE;
    var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE;
    var COMMENT = domGlobals.Node.COMMENT_NODE;
    var DOCUMENT = domGlobals.Node.DOCUMENT_NODE;
    var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE;
    var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE;
    var ELEMENT = domGlobals.Node.ELEMENT_NODE;
    var TEXT = domGlobals.Node.TEXT_NODE;
    var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE;
    var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE;
    var ENTITY = domGlobals.Node.ENTITY_NODE;
    var NOTATION = domGlobals.Node.NOTATION_NODE;

    var name = function (element) {
      var r = element.dom().nodeName;
      return r.toLowerCase();
    };
    var type = function (element) {
      return element.dom().nodeType;
    };
    var isType$1 = function (t) {
      return function (element) {
        return type(element) === t;
      };
    };
    var isElement = isType$1(ELEMENT);
    var isText = isType$1(TEXT);

    var keys = Object.keys;
    var hasOwnProperty$1 = Object.hasOwnProperty;
    var each$3 = function (obj, f) {
      var props = keys(obj);
      for (var k = 0, len = props.length; k < len; k++) {
        var i = props[k];
        var x = obj[i];
        f(x, i);
      }
    };
    var map$2 = function (obj, f) {
      return tupleMap(obj, function (x, i) {
        return {
          k: i,
          v: f(x, i)
        };
      });
    };
    var tupleMap = function (obj, f) {
      var r = {};
      each$3(obj, function (x, i) {
        var tuple = f(x, i);
        r[tuple.k] = tuple.v;
      });
      return r;
    };
    var bifilter = function (obj, pred) {
      var t = {};
      var f = {};
      each$3(obj, function (x, i) {
        var branch = pred(x, i) ? t : f;
        branch[i] = x;
      });
      return {
        t: t,
        f: f
      };
    };
    var has = function (obj, key) {
      return hasOwnProperty$1.call(obj, key);
    };

    var isSupported = function (dom) {
      return dom.style !== undefined && isFunction(dom.style.getPropertyValue);
    };

    var inBody = function (element) {
      var dom = isText(element) ? element.dom().parentNode : element.dom();
      return dom !== undefined && dom !== null && dom.ownerDocument.body.contains(dom);
    };

    var rawSet = function (dom, key, value) {
      if (isString(value) || isBoolean(value) || isNumber(value)) {
        dom.setAttribute(key, value + '');
      } else {
        domGlobals.console.error('Invalid call to Attr.set. Key ', key, ':: Value ', value, ':: Element ', dom);
        throw new Error('Attribute value was not simple');
      }
    };
    var set = function (element, key, value) {
      rawSet(element.dom(), key, value);
    };
    var setAll = function (element, attrs) {
      var dom = element.dom();
      each$3(attrs, function (v, k) {
        rawSet(dom, k, v);
      });
    };
    var get = function (element, key) {
      var v = element.dom().getAttribute(key);
      return v === null ? undefined : v;
    };
    var has$1 = function (element, key) {
      var dom = element.dom();
      return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
    };
    var remove = function (element, key) {
      element.dom().removeAttribute(key);
    };

    var internalSet = function (dom, property, value) {
      if (!isString(value)) {
        domGlobals.console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
        throw new Error('CSS value must be a string: ' + value);
      }
      if (isSupported(dom)) {
        dom.style.setProperty(property, value);
      }
    };
    var setAll$1 = function (element, css) {
      var dom = element.dom();
      each$3(css, function (v, k) {
        internalSet(dom, k, v);
      });
    };
    var get$1 = function (element, property) {
      var dom = element.dom();
      var styles = domGlobals.window.getComputedStyle(dom);
      var r = styles.getPropertyValue(property);
      var v = r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
      return v === null ? undefined : v;
    };
    var getUnsafeProperty = function (dom, property) {
      return isSupported(dom) ? dom.style.getPropertyValue(property) : '';
    };
    var getRaw = function (element, property) {
      var dom = element.dom();
      var raw = getUnsafeProperty(dom, property);
      return Option.from(raw).filter(function (r) {
        return r.length > 0;
      });
    };
    var getAllRaw = function (element) {
      var css = {};
      var dom = element.dom();
      if (isSupported(dom)) {
        for (var i = 0; i < dom.style.length; i++) {
          var ruleName = dom.style.item(i);
          css[ruleName] = dom.style[ruleName];
        }
      }
      return css;
    };

    var Immutable = function () {
      var fields = [];
      for (var _i = 0; _i < arguments.length; _i++) {
        fields[_i] = arguments[_i];
      }
      return function () {
        var values = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          values[_i] = arguments[_i];
        }
        if (fields.length !== values.length) {
          throw new Error('Wrong number of arguments to struct. Expected "[' + fields.length + ']", got ' + values.length + ' arguments');
        }
        var struct = {};
        each(fields, function (name, i) {
          struct[name] = constant(values[i]);
        });
        return struct;
      };
    };

    var toArray$1 = function (target, f) {
      var r = [];
      var recurse = function (e) {
        r.push(e);
        return f(e);
      };
      var cur = f(target);
      do {
        cur = cur.bind(recurse);
      } while (cur.isSome());
      return r;
    };
    var Recurse = { toArray: toArray$1 };

    var node = function () {
      var f = Global$1.getOrDie('Node');
      return f;
    };
    var compareDocumentPosition = function (a, b, match) {
      return (a.compareDocumentPosition(b) & match) !== 0;
    };
    var documentPositionPreceding = function (a, b) {
      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_PRECEDING);
    };
    var documentPositionContainedBy = function (a, b) {
      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_CONTAINED_BY);
    };
    var Node = {
      documentPositionPreceding: documentPositionPreceding,
      documentPositionContainedBy: documentPositionContainedBy
    };

    var ELEMENT$1 = ELEMENT;
    var DOCUMENT$1 = DOCUMENT;
    var is$1 = function (element, selector) {
      var dom = element.dom();
      if (dom.nodeType !== ELEMENT$1) {
        return false;
      } else {
        var elem = dom;
        if (elem.matches !== undefined) {
          return elem.matches(selector);
        } else if (elem.msMatchesSelector !== undefined) {
          return elem.msMatchesSelector(selector);
        } else if (elem.webkitMatchesSelector !== undefined) {
          return elem.webkitMatchesSelector(selector);
        } else if (elem.mozMatchesSelector !== undefined) {
          return elem.mozMatchesSelector(selector);
        } else {
          throw new Error('Browser lacks native selectors');
        }
      }
    };
    var bypassSelector = function (dom) {
      return dom.nodeType !== ELEMENT$1 && dom.nodeType !== DOCUMENT$1 || dom.childElementCount === 0;
    };
    var all = function (selector, scope) {
      var base = scope === undefined ? domGlobals.document : scope.dom();
      return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), Element.fromDom);
    };
    var one = function (selector, scope) {
      var base = scope === undefined ? domGlobals.document : scope.dom();
      return bypassSelector(base) ? Option.none() : Option.from(base.querySelector(selector)).map(Element.fromDom);
    };

    var eq = function (e1, e2) {
      return e1.dom() === e2.dom();
    };
    var regularContains = function (e1, e2) {
      var d1 = e1.dom();
      var d2 = e2.dom();
      return d1 === d2 ? false : d1.contains(d2);
    };
    var ieContains = function (e1, e2) {
      return Node.documentPositionContainedBy(e1.dom(), e2.dom());
    };
    var browser = PlatformDetection$1.detect().browser;
    var contains$3 = browser.isIE() ? ieContains : regularContains;

    var owner = function (element) {
      return Element.fromDom(element.dom().ownerDocument);
    };
    var documentElement = function (element) {
      return Element.fromDom(element.dom().ownerDocument.documentElement);
    };
    var defaultView = function (element) {
      return Element.fromDom(element.dom().ownerDocument.defaultView);
    };
    var parent = function (element) {
      return Option.from(element.dom().parentNode).map(Element.fromDom);
    };
    var parents = function (element, isRoot) {
      var stop = isFunction(isRoot) ? isRoot : never;
      var dom = element.dom();
      var ret = [];
      while (dom.parentNode !== null && dom.parentNode !== undefined) {
        var rawParent = dom.parentNode;
        var p = Element.fromDom(rawParent);
        ret.push(p);
        if (stop(p) === true) {
          break;
        } else {
          dom = rawParent;
        }
      }
      return ret;
    };
    var prevSibling = function (element) {
      return Option.from(element.dom().previousSibling).map(Element.fromDom);
    };
    var nextSibling = function (element) {
      return Option.from(element.dom().nextSibling).map(Element.fromDom);
    };
    var prevSiblings = function (element) {
      return reverse(Recurse.toArray(element, prevSibling));
    };
    var nextSiblings = function (element) {
      return Recurse.toArray(element, nextSibling);
    };
    var children = function (element) {
      return map(element.dom().childNodes, Element.fromDom);
    };
    var child = function (element, index) {
      var cs = element.dom().childNodes;
      return Option.from(cs[index]).map(Element.fromDom);
    };
    var firstChild = function (element) {
      return child(element, 0);
    };
    var lastChild = function (element) {
      return child(element, element.dom().childNodes.length - 1);
    };
    var childNodesCount = function (element) {
      return element.dom().childNodes.length;
    };
    var spot = Immutable('element', 'offset');

    var browser$1 = PlatformDetection$1.detect().browser;
    var firstElement = function (nodes) {
      return find(nodes, isElement);
    };
    var getTableCaptionDeltaY = function (elm) {
      if (browser$1.isFirefox() && name(elm) === 'table') {
        return firstElement(children(elm)).filter(function (elm) {
          return name(elm) === 'caption';
        }).bind(function (caption) {
          return firstElement(nextSiblings(caption)).map(function (body) {
            var bodyTop = body.dom().offsetTop;
            var captionTop = caption.dom().offsetTop;
            var captionHeight = caption.dom().offsetHeight;
            return bodyTop <= captionTop ? -captionHeight : 0;
          });
        }).getOr(0);
      } else {
        return 0;
      }
    };
    var getPos = function (body, elm, rootElm) {
      var x = 0, y = 0, offsetParent;
      var doc = body.ownerDocument;
      var pos;
      rootElm = rootElm ? rootElm : body;
      if (elm) {
        if (rootElm === body && elm.getBoundingClientRect && get$1(Element.fromDom(body), 'position') === 'static') {
          pos = elm.getBoundingClientRect();
          x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - doc.documentElement.clientLeft;
          y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - doc.documentElement.clientTop;
          return {
            x: x,
            y: y
          };
        }
        offsetParent = elm;
        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType) {
          x += offsetParent.offsetLeft || 0;
          y += offsetParent.offsetTop || 0;
          offsetParent = offsetParent.offsetParent;
        }
        offsetParent = elm.parentNode;
        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType) {
          x -= offsetParent.scrollLeft || 0;
          y -= offsetParent.scrollTop || 0;
          offsetParent = offsetParent.parentNode;
        }
        y += getTableCaptionDeltaY(Element.fromDom(elm));
      }
      return {
        x: x,
        y: y
      };
    };
    var Position = { getPos: getPos };

    var exports$1 = {}, module$1 = { exports: exports$1 };
    (function (define, exports, module, 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.EphoxContactWrapper = f();
        }
      }(function () {
        return function () {
          function r(e, n, t) {
            function o(i, f) {
              if (!n[i]) {
                if (!e[i]) {
                  var c = 'function' == typeof require && require;
                  if (!f && c)
                    return c(i, !0);
                  if (u)
                    return u(i, !0);
                  var a = new Error('Cannot find module \'' + i + '\'');
                  throw a.code = 'MODULE_NOT_FOUND', a;
                }
                var p = n[i] = { exports: {} };
                e[i][0].call(p.exports, function (r) {
                  var n = e[i][1][r];
                  return o(n || r);
                }, p, p.exports, r, e, n, t);
              }
              return n[i].exports;
            }
            for (var u = 'function' == typeof require && require, i = 0; i < t.length; i++)
              o(t[i]);
            return o;
          }
          return r;
        }()({
          1: [
            function (require, module, exports) {
              var process = module.exports = {};
              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) {
                  return setTimeout(fun, 0);
                }
                if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
                  cachedSetTimeout = setTimeout;
                  return setTimeout(fun, 0);
                }
                try {
                  return cachedSetTimeout(fun, 0);
                } catch (e) {
                  try {
                    return cachedSetTimeout.call(null, fun, 0);
                  } catch (e) {
                    return cachedSetTimeout.call(this, fun, 0);
                  }
                }
              }
              function runClearTimeout(marker) {
                if (cachedClearTimeout === clearTimeout) {
                  return clearTimeout(marker);
                }
                if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
                  cachedClearTimeout = clearTimeout;
                  return clearTimeout(marker);
                }
                try {
                  return cachedClearTimeout(marker);
                } catch (e) {
                  try {
                    return cachedClearTimeout.call(null, marker);
                  } catch (e) {
                    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);
                }
              };
              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 = '';
              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.prependListener = noop;
              process.prependOnceListener = noop;
              process.listeners = function (name) {
                return [];
              };
              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;
              };
            },
            {}
          ],
          2: [
            function (require, module, exports) {
              (function (setImmediate) {
                (function (root) {
                  var setTimeoutFunc = setTimeout;
                  function noop() {
                  }
                  function bind(fn, thisArg) {
                    return function () {
                      fn.apply(thisArg, arguments);
                    };
                  }
                  function Promise(fn) {
                    if (typeof this !== 'object')
                      throw new TypeError('Promises must be constructed via new');
                    if (typeof fn !== 'function')
                      throw new TypeError('not a function');
                    this._state = 0;
                    this._handled = false;
                    this._value = undefined;
                    this._deferreds = [];
                    doResolve(fn, this);
                  }
                  function handle(self, deferred) {
                    while (self._state === 3) {
                      self = self._value;
                    }
                    if (self._state === 0) {
                      self._deferreds.push(deferred);
                      return;
                    }
                    self._handled = true;
                    Promise._immediateFn(function () {
                      var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
                      if (cb === null) {
                        (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
                        return;
                      }
                      var ret;
                      try {
                        ret = cb(self._value);
                      } catch (e) {
                        reject(deferred.promise, e);
                        return;
                      }
                      resolve(deferred.promise, ret);
                    });
                  }
                  function resolve(self, newValue) {
                    try {
                      if (newValue === self)
                        throw new TypeError('A promise cannot be resolved with itself.');
                      if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
                        var then = newValue.then;
                        if (newValue instanceof Promise) {
                          self._state = 3;
                          self._value = newValue;
                          finale(self);
                          return;
                        } else if (typeof then === 'function') {
                          doResolve(bind(then, newValue), self);
                          return;
                        }
                      }
                      self._state = 1;
                      self._value = newValue;
                      finale(self);
                    } catch (e) {
                      reject(self, e);
                    }
                  }
                  function reject(self, newValue) {
                    self._state = 2;
                    self._value = newValue;
                    finale(self);
                  }
                  function finale(self) {
                    if (self._state === 2 && self._deferreds.length === 0) {
                      Promise._immediateFn(function () {
                        if (!self._handled) {
                          Promise._unhandledRejectionFn(self._value);
                        }
                      });
                    }
                    for (var i = 0, len = self._deferreds.length; i < len; i++) {
                      handle(self, self._deferreds[i]);
                    }
                    self._deferreds = null;
                  }
                  function Handler(onFulfilled, onRejected, promise) {
                    this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
                    this.onRejected = typeof onRejected === 'function' ? onRejected : null;
                    this.promise = promise;
                  }
                  function doResolve(fn, self) {
                    var done = false;
                    try {
                      fn(function (value) {
                        if (done)
                          return;
                        done = true;
                        resolve(self, value);
                      }, function (reason) {
                        if (done)
                          return;
                        done = true;
                        reject(self, reason);
                      });
                    } catch (ex) {
                      if (done)
                        return;
                      done = true;
                      reject(self, ex);
                    }
                  }
                  Promise.prototype['catch'] = function (onRejected) {
                    return this.then(null, onRejected);
                  };
                  Promise.prototype.then = function (onFulfilled, onRejected) {
                    var prom = new this.constructor(noop);
                    handle(this, new Handler(onFulfilled, onRejected, prom));
                    return prom;
                  };
                  Promise.all = function (arr) {
                    var args = Array.prototype.slice.call(arr);
                    return new Promise(function (resolve, reject) {
                      if (args.length === 0)
                        return resolve([]);
                      var remaining = args.length;
                      function res(i, val) {
                        try {
                          if (val && (typeof val === 'object' || typeof val === 'function')) {
                            var then = val.then;
                            if (typeof then === 'function') {
                              then.call(val, function (val) {
                                res(i, val);
                              }, reject);
                              return;
                            }
                          }
                          args[i] = val;
                          if (--remaining === 0) {
                            resolve(args);
                          }
                        } catch (ex) {
                          reject(ex);
                        }
                      }
                      for (var i = 0; i < args.length; i++) {
                        res(i, args[i]);
                      }
                    });
                  };
                  Promise.resolve = function (value) {
                    if (value && typeof value === 'object' && value.constructor === Promise) {
                      return value;
                    }
                    return new Promise(function (resolve) {
                      resolve(value);
                    });
                  };
                  Promise.reject = function (value) {
                    return new Promise(function (resolve, reject) {
                      reject(value);
                    });
                  };
                  Promise.race = function (values) {
                    return new Promise(function (resolve, reject) {
                      for (var i = 0, len = values.length; i < len; i++) {
                        values[i].then(resolve, reject);
                      }
                    });
                  };
                  Promise._immediateFn = typeof setImmediate === 'function' ? function (fn) {
                    setImmediate(fn);
                  } : function (fn) {
                    setTimeoutFunc(fn, 0);
                  };
                  Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
                    if (typeof console !== 'undefined' && console) {
                      console.warn('Possible Unhandled Promise Rejection:', err);
                    }
                  };
                  Promise._setImmediateFn = function _setImmediateFn(fn) {
                    Promise._immediateFn = fn;
                  };
                  Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
                    Promise._unhandledRejectionFn = fn;
                  };
                  if (typeof module !== 'undefined' && module.exports) {
                    module.exports = Promise;
                  } else if (!root.Promise) {
                    root.Promise = Promise;
                  }
                }(this));
              }.call(this, require('timers').setImmediate));
            },
            { 'timers': 3 }
          ],
          3: [
            function (require, module, exports) {
              (function (setImmediate, clearImmediate) {
                var nextTick = require('process/browser.js').nextTick;
                var apply = Function.prototype.apply;
                var slice = Array.prototype.slice;
                var immediateIds = {};
                var nextImmediateId = 0;
                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) {
                  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);
                };
                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);
                  }
                };
                exports.setImmediate = typeof setImmediate === 'function' ? setImmediate : function (fn) {
                  var id = nextImmediateId++;
                  var args = arguments.length < 2 ? false : slice.call(arguments, 1);
                  immediateIds[id] = true;
                  nextTick(function onNextTick() {
                    if (immediateIds[id]) {
                      if (args) {
                        fn.apply(null, args);
                      } else {
                        fn.call(null);
                      }
                      exports.clearImmediate(id);
                    }
                  });
                  return id;
                };
                exports.clearImmediate = typeof clearImmediate === 'function' ? clearImmediate : function (id) {
                  delete immediateIds[id];
                };
              }.call(this, require('timers').setImmediate, require('timers').clearImmediate));
            },
            {
              'process/browser.js': 1,
              'timers': 3
            }
          ],
          4: [
            function (require, module, exports) {
              var promisePolyfill = require('promise-polyfill');
              var Global = function () {
                if (typeof window !== 'undefined') {
                  return window;
                } else {
                  return Function('return this;')();
                }
              }();
              module.exports = { boltExport: Global.Promise || promisePolyfill };
            },
            { 'promise-polyfill': 2 }
          ]
        }, {}, [4])(4);
      }));
    }(undefined, exports$1, module$1, undefined));
    var Promise = module$1.exports.boltExport;

    var nu$3 = function (baseFn) {
      var data = Option.none();
      var callbacks = [];
      var map = function (f) {
        return nu$3(function (nCallback) {
          get(function (data) {
            nCallback(f(data));
          });
        });
      };
      var get = function (nCallback) {
        if (isReady()) {
          call(nCallback);
        } else {
          callbacks.push(nCallback);
        }
      };
      var set = function (x) {
        data = Option.some(x);
        run(callbacks);
        callbacks = [];
      };
      var isReady = function () {
        return data.isSome();
      };
      var run = function (cbs) {
        each(cbs, call);
      };
      var call = function (cb) {
        data.each(function (x) {
          domGlobals.setTimeout(function () {
            cb(x);
          }, 0);
        });
      };
      baseFn(set);
      return {
        get: get,
        map: map,
        isReady: isReady
      };
    };
    var pure = function (a) {
      return nu$3(function (callback) {
        callback(a);
      });
    };
    var LazyValue = {
      nu: nu$3,
      pure: pure
    };

    var errorReporter = function (err) {
      domGlobals.setTimeout(function () {
        throw err;
      }, 0);
    };
    var make = function (run) {
      var get = function (callback) {
        run().then(callback, errorReporter);
      };
      var map = function (fab) {
        return make(function () {
          return run().then(fab);
        });
      };
      var bind = function (aFutureB) {
        return make(function () {
          return run().then(function (v) {
            return aFutureB(v).toPromise();
          });
        });
      };
      var anonBind = function (futureB) {
        return make(function () {
          return run().then(function () {
            return futureB.toPromise();
          });
        });
      };
      var toLazy = function () {
        return LazyValue.nu(get);
      };
      var toCached = function () {
        var cache = null;
        return make(function () {
          if (cache === null) {
            cache = run();
          }
          return cache;
        });
      };
      var toPromise = run;
      return {
        map: map,
        bind: bind,
        anonBind: anonBind,
        toLazy: toLazy,
        toCached: toCached,
        toPromise: toPromise,
        get: get
      };
    };
    var nu$4 = function (baseFn) {
      return make(function () {
        return new Promise(baseFn);
      });
    };
    var pure$1 = function (a) {
      return make(function () {
        return Promise.resolve(a);
      });
    };
    var Future = {
      nu: nu$4,
      pure: pure$1
    };

    var par = function (asyncValues, nu) {
      return nu(function (callback) {
        var r = [];
        var count = 0;
        var cb = function (i) {
          return function (value) {
            r[i] = value;
            count++;
            if (count >= asyncValues.length) {
              callback(r);
            }
          };
        };
        if (asyncValues.length === 0) {
          callback([]);
        } else {
          each(asyncValues, function (asyncValue, i) {
            asyncValue.get(cb(i));
          });
        }
      });
    };

    var par$1 = function (futures) {
      return par(futures, Future.nu);
    };

    var value = function (o) {
      var is = function (v) {
        return o === v;
      };
      var or = function (opt) {
        return value(o);
      };
      var orThunk = function (f) {
        return value(o);
      };
      var map = function (f) {
        return value(f(o));
      };
      var mapError = function (f) {
        return value(o);
      };
      var each = function (f) {
        f(o);
      };
      var bind = function (f) {
        return f(o);
      };
      var fold = function (_, onValue) {
        return onValue(o);
      };
      var exists = function (f) {
        return f(o);
      };
      var forall = function (f) {
        return f(o);
      };
      var toOption = function () {
        return Option.some(o);
      };
      return {
        is: is,
        isValue: always,
        isError: never,
        getOr: constant(o),
        getOrThunk: constant(o),
        getOrDie: constant(o),
        or: or,
        orThunk: orThunk,
        fold: fold,
        map: map,
        mapError: mapError,
        each: each,
        bind: bind,
        exists: exists,
        forall: forall,
        toOption: toOption
      };
    };
    var error = function (message) {
      var getOrThunk = function (f) {
        return f();
      };
      var getOrDie = function () {
        return die(String(message))();
      };
      var or = function (opt) {
        return opt;
      };
      var orThunk = function (f) {
        return f();
      };
      var map = function (f) {
        return error(message);
      };
      var mapError = function (f) {
        return error(f(message));
      };
      var bind = function (f) {
        return error(message);
      };
      var fold = function (onError, _) {
        return onError(message);
      };
      return {
        is: never,
        isValue: never,
        isError: always,
        getOr: identity,
        getOrThunk: getOrThunk,
        getOrDie: getOrDie,
        or: or,
        orThunk: orThunk,
        fold: fold,
        map: map,
        mapError: mapError,
        each: noop,
        bind: bind,
        exists: never,
        forall: always,
        toOption: Option.none
      };
    };
    var fromOption = function (opt, err) {
      return opt.fold(function () {
        return error(err);
      }, value);
    };
    var Result = {
      value: value,
      error: error,
      fromOption: fromOption
    };

    function StyleSheetLoader(document, settings) {
      if (settings === void 0) {
        settings = {};
      }
      var idCount = 0;
      var loadedStates = {};
      var maxLoadTime;
      maxLoadTime = settings.maxLoadTime || 5000;
      var appendToHead = function (node) {
        document.getElementsByTagName('head')[0].appendChild(node);
      };
      var load = function (url, loadedCallback, errorCallback) {
        var link, style, startTime, state;
        var passed = function () {
          var callbacks = state.passed;
          var i = callbacks.length;
          while (i--) {
            callbacks[i]();
          }
          state.status = 2;
          state.passed = [];
          state.failed = [];
        };
        var failed = function () {
          var callbacks = state.failed;
          var i = callbacks.length;
          while (i--) {
            callbacks[i]();
          }
          state.status = 3;
          state.passed = [];
          state.failed = [];
        };
        var isOldWebKit = function () {
          var webKitChunks = domGlobals.navigator.userAgent.match(/WebKit\/(\d*)/);
          return !!(webKitChunks && parseInt(webKitChunks[1], 10) < 536);
        };
        var wait = function (testCallback, waitCallback) {
          if (!testCallback()) {
            if (new Date().getTime() - startTime < maxLoadTime) {
              Delay.setTimeout(waitCallback);
            } else {
              failed();
            }
          }
        };
        var waitForWebKitLinkLoaded = function () {
          wait(function () {
            var styleSheets = document.styleSheets;
            var styleSheet, i = styleSheets.length, owner;
            while (i--) {
              styleSheet = styleSheets[i];
              owner = styleSheet.ownerNode ? styleSheet.ownerNode : styleSheet.owningElement;
              if (owner && owner.id === link.id) {
                passed();
                return true;
              }
            }
          }, waitForWebKitLinkLoaded);
        };
        var waitForGeckoLinkLoaded = function () {
          wait(function () {
            try {
              var cssRules = style.sheet.cssRules;
              passed();
              return !!cssRules;
            } catch (ex) {
            }
          }, waitForGeckoLinkLoaded);
        };
        url = Tools._addCacheSuffix(url);
        if (!loadedStates[url]) {
          state = {
            passed: [],
            failed: []
          };
          loadedStates[url] = state;
        } else {
          state = loadedStates[url];
        }
        if (loadedCallback) {
          state.passed.push(loadedCallback);
        }
        if (errorCallback) {
          state.failed.push(errorCallback);
        }
        if (state.status === 1) {
          return;
        }
        if (state.status === 2) {
          passed();
          return;
        }
        if (state.status === 3) {
          failed();
          return;
        }
        state.status = 1;
        link = document.createElement('link');
        link.rel = 'stylesheet';
        link.type = 'text/css';
        link.id = 'u' + idCount++;
        link.async = false;
        link.defer = false;
        startTime = new Date().getTime();
        if (settings.contentCssCors) {
          link.crossOrigin = 'anonymous';
        }
        if ('onload' in link && !isOldWebKit()) {
          link.onload = waitForWebKitLinkLoaded;
          link.onerror = failed;
        } else {
          if (domGlobals.navigator.userAgent.indexOf('Firefox') > 0) {
            style = document.createElement('style');
            style.textContent = '@import "' + url + '"';
            waitForGeckoLinkLoaded();
            appendToHead(style);
            return;
          }
          waitForWebKitLinkLoaded();
        }
        appendToHead(link);
        link.href = url;
      };
      var loadF = function (url) {
        return Future.nu(function (resolve) {
          load(url, compose(resolve, constant(Result.value(url))), compose(resolve, constant(Result.error(url))));
        });
      };
      var unbox = function (result) {
        return result.fold(identity, identity);
      };
      var loadAll = function (urls, success, failure) {
        par$1(map(urls, loadF)).get(function (result) {
          var parts = partition(result, function (r) {
            return r.isValue();
          });
          if (parts.fail.length > 0) {
            failure(parts.fail.map(unbox));
          } else {
            success(parts.pass.map(unbox));
          }
        });
      };
      return {
        load: load,
        loadAll: loadAll
      };
    }

    function TreeWalker (startNode, rootNode) {
      var node = startNode;
      var findSibling = function (node, startName, siblingName, shallow) {
        var sibling, parent;
        if (node) {
          if (!shallow && node[startName]) {
            return node[startName];
          }
          if (node !== rootNode) {
            sibling = node[siblingName];
            if (sibling) {
              return sibling;
            }
            for (parent = node.parentNode; parent && parent !== rootNode; parent = parent.parentNode) {
              sibling = parent[siblingName];
              if (sibling) {
                return sibling;
              }
            }
          }
        }
      };
      var findPreviousNode = function (node, startName, siblingName, shallow) {
        var sibling, parent, child;
        if (node) {
          sibling = node[siblingName];
          if (rootNode && sibling === rootNode) {
            return;
          }
          if (sibling) {
            if (!shallow) {
              for (child = sibling[startName]; child; child = child[startName]) {
                if (!child[startName]) {
                  return child;
                }
              }
            }
            return sibling;
          }
          parent = node.parentNode;
          if (parent && parent !== rootNode) {
            return parent;
          }
        }
      };
      this.current = function () {
        return node;
      };
      this.next = function (shallow) {
        node = findSibling(node, 'firstChild', 'nextSibling', shallow);
        return node;
      };
      this.prev = function (shallow) {
        node = findSibling(node, 'lastChild', 'previousSibling', shallow);
        return node;
      };
      this.prev2 = function (shallow) {
        node = findPreviousNode(node, 'lastChild', 'previousSibling', shallow);
        return node;
      };
    }

    var blocks = [
      'article',
      'aside',
      'details',
      'div',
      'dt',
      'figcaption',
      'footer',
      'form',
      'fieldset',
      'header',
      'hgroup',
      'html',
      'main',
      'nav',
      'section',
      'summary',
      'body',
      'p',
      'dl',
      'multicol',
      'dd',
      'figure',
      'address',
      'center',
      'blockquote',
      'h1',
      'h2',
      'h3',
      'h4',
      'h5',
      'h6',
      'listing',
      'xmp',
      'pre',
      'plaintext',
      'menu',
      'dir',
      'ul',
      'ol',
      'li',
      'hr',
      'table',
      'tbody',
      'thead',
      'tfoot',
      'th',
      'tr',
      'td',
      'caption'
    ];
    var voids = [
      'area',
      'base',
      'basefont',
      'br',
      'col',
      'frame',
      'hr',
      'img',
      'input',
      'isindex',
      'link',
      'meta',
      'param',
      'embed',
      'source',
      'wbr',
      'track'
    ];
    var tableCells = [
      'td',
      'th'
    ];
    var tableSections = [
      'thead',
      'tbody',
      'tfoot'
    ];
    var textBlocks = [
      'h1',
      'h2',
      'h3',
      'h4',
      'h5',
      'h6',
      'p',
      'div',
      'address',
      'pre',
      'form',
      'blockquote',
      'center',
      'dir',
      'fieldset',
      'header',
      'footer',
      'article',
      'section',
      'hgroup',
      'aside',
      'nav',
      'figure'
    ];
    var headings = [
      'h1',
      'h2',
      'h3',
      'h4',
      'h5',
      'h6'
    ];
    var listItems = [
      'li',
      'dd',
      'dt'
    ];
    var lists = [
      'ul',
      'ol',
      'dl'
    ];
    var wsElements = [
      'pre',
      'script',
      'textarea',
      'style'
    ];
    var lazyLookup = function (items) {
      var lookup;
      return function (node) {
        lookup = lookup ? lookup : mapToObject(items, constant(true));
        return lookup.hasOwnProperty(name(node));
      };
    };
    var isHeading = lazyLookup(headings);
    var isBlock = lazyLookup(blocks);
    var isInline = function (node) {
      return isElement(node) && !isBlock(node);
    };
    var isBr = function (node) {
      return isElement(node) && name(node) === 'br';
    };
    var isTextBlock = lazyLookup(textBlocks);
    var isList = lazyLookup(lists);
    var isListItem = lazyLookup(listItems);
    var isVoid = lazyLookup(voids);
    var isTableSection = lazyLookup(tableSections);
    var isTableCell = lazyLookup(tableCells);
    var isWsPreserveElement = lazyLookup(wsElements);

    var isNodeType = function (type) {
      return function (node) {
        return !!node && node.nodeType === type;
      };
    };
    var isRestrictedNode = function (node) {
      return !!node && !Object.getPrototypeOf(node);
    };
    var isElement$1 = isNodeType(1);
    var matchNodeNames = function (names) {
      var items = names.toLowerCase().split(' ');
      return function (node) {
        var i, name;
        if (node && node.nodeType) {
          name = node.nodeName.toLowerCase();
          for (i = 0; i < items.length; i++) {
            if (name === items[i]) {
              return true;
            }
          }
        }
        return false;
      };
    };
    var matchStyleValues = function (name, values) {
      var items = values.toLowerCase().split(' ');
      return function (node) {
        var i, cssValue;
        if (isElement$1(node)) {
          for (i = 0; i < items.length; i++) {
            var computed = node.ownerDocument.defaultView.getComputedStyle(node, null);
            cssValue = computed ? computed.getPropertyValue(name) : null;
            if (cssValue === items[i]) {
              return true;
            }
          }
        }
        return false;
      };
    };
    var hasPropValue = function (propName, propValue) {
      return function (node) {
        return isElement$1(node) && node[propName] === propValue;
      };
    };
    var hasAttribute = function (attrName, attrValue) {
      return function (node) {
        return isElement$1(node) && node.hasAttribute(attrName);
      };
    };
    var hasAttributeValue = function (attrName, attrValue) {
      return function (node) {
        return isElement$1(node) && node.getAttribute(attrName) === attrValue;
      };
    };
    var isBogus = function (node) {
      return isElement$1(node) && node.hasAttribute('data-mce-bogus');
    };
    var isBogusAll = function (node) {
      return isElement$1(node) && node.getAttribute('data-mce-bogus') === 'all';
    };
    var isTable = function (node) {
      return isElement$1(node) && node.tagName === 'TABLE';
    };
    var hasContentEditableState = function (value) {
      return function (node) {
        if (isElement$1(node)) {
          if (node.contentEditable === value) {
            return true;
          }
          if (node.getAttribute('data-mce-contenteditable') === value) {
            return true;
          }
        }
        return false;
      };
    };
    var isText$1 = isNodeType(3);
    var isComment = isNodeType(8);
    var isDocument = isNodeType(9);
    var isDocumentFragment = isNodeType(11);
    var isBr$1 = matchNodeNames('br');
    var isContentEditableTrue = hasContentEditableState('true');
    var isContentEditableFalse = hasContentEditableState('false');
    var NodeType = {
      isText: isText$1,
      isElement: isElement$1,
      isComment: isComment,
      isDocument: isDocument,
      isDocumentFragment: isDocumentFragment,
      isBr: isBr$1,
      isContentEditableTrue: isContentEditableTrue,
      isContentEditableFalse: isContentEditableFalse,
      isRestrictedNode: isRestrictedNode,
      matchNodeNames: matchNodeNames,
      hasPropValue: hasPropValue,
      hasAttribute: hasAttribute,
      hasAttributeValue: hasAttributeValue,
      matchStyleValues: matchStyleValues,
      isBogus: isBogus,
      isBogusAll: isBogusAll,
      isTable: isTable
    };

    var surroundedBySpans = function (node) {
      var previousIsSpan = node.previousSibling && node.previousSibling.nodeName === 'SPAN';
      var nextIsSpan = node.nextSibling && node.nextSibling.nodeName === 'SPAN';
      return previousIsSpan && nextIsSpan;
    };
    var isBookmarkNode = function (node) {
      return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
    };
    var trimNode = function (dom, node) {
      var i, children = node.childNodes;
      if (NodeType.isElement(node) && isBookmarkNode(node)) {
        return;
      }
      for (i = children.length - 1; i >= 0; i--) {
        trimNode(dom, children[i]);
      }
      if (NodeType.isDocument(node) === false) {
        if (NodeType.isText(node) && node.nodeValue.length > 0) {
          var trimmedLength = Tools.trim(node.nodeValue).length;
          if (dom.isBlock(node.parentNode) || trimmedLength > 0) {
            return;
          }
          if (trimmedLength === 0 && surroundedBySpans(node)) {
            return;
          }
        } else if (NodeType.isElement(node)) {
          children = node.childNodes;
          if (children.length === 1 && isBookmarkNode(children[0])) {
            node.parentNode.insertBefore(children[0], node);
          }
          if (children.length || isVoid(Element.fromDom(node))) {
            return;
          }
        }
        dom.remove(node);
      }
      return node;
    };
    var TrimNode = { trimNode: trimNode };

    var makeMap$1 = Tools.makeMap;
    var namedEntities, baseEntities, reverseEntities;
    var attrsCharsRegExp = /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
    var textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
    var rawCharsRegExp = /[<>&\"\']/g;
    var entityRegExp = /&#([a-z0-9]+);?|&([a-z0-9]+);/gi;
    var asciiMap = {
      128: '\u20AC',
      130: '\u201A',
      131: '\u0192',
      132: '\u201E',
      133: '\u2026',
      134: '\u2020',
      135: '\u2021',
      136: '\u02c6',
      137: '\u2030',
      138: '\u0160',
      139: '\u2039',
      140: '\u0152',
      142: '\u017d',
      145: '\u2018',
      146: '\u2019',
      147: '\u201C',
      148: '\u201D',
      149: '\u2022',
      150: '\u2013',
      151: '\u2014',
      152: '\u02DC',
      153: '\u2122',
      154: '\u0161',
      155: '\u203A',
      156: '\u0153',
      158: '\u017e',
      159: '\u0178'
    };
    baseEntities = {
      '"': '&quot;',
      '\'': '&#39;',
      '<': '&lt;',
      '>': '&gt;',
      '&': '&amp;',
      '`': '&#96;'
    };
    reverseEntities = {
      '&lt;': '<',
      '&gt;': '>',
      '&amp;': '&',
      '&quot;': '"',
      '&apos;': '\''
    };
    var nativeDecode = function (text) {
      var elm;
      elm = Element.fromTag('div').dom();
      elm.innerHTML = text;
      return elm.textContent || elm.innerText || text;
    };
    var buildEntitiesLookup = function (items, radix) {
      var i, chr, entity;
      var lookup = {};
      if (items) {
        items = items.split(',');
        radix = radix || 10;
        for (i = 0; i < items.length; i += 2) {
          chr = String.fromCharCode(parseInt(items[i], radix));
          if (!baseEntities[chr]) {
            entity = '&' + items[i + 1] + ';';
            lookup[chr] = entity;
            lookup[entity] = chr;
          }
        }
        return lookup;
      }
    };
    namedEntities = buildEntitiesLookup('50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' + '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' + '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' + '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' + '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' + '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' + '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' + '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' + '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' + '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' + 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' + 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' + 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' + 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' + 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' + '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' + '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' + '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' + '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' + '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' + 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' + 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' + 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' + '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' + '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32);
    var encodeRaw = function (text, attr) {
      return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
        return baseEntities[chr] || chr;
      });
    };
    var encodeAllRaw = function (text) {
      return ('' + text).replace(rawCharsRegExp, function (chr) {
        return baseEntities[chr] || chr;
      });
    };
    var encodeNumeric = function (text, attr) {
      return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
        if (chr.length > 1) {
          return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
        }
        return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
      });
    };
    var encodeNamed = function (text, attr, entities) {
      entities = entities || namedEntities;
      return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
        return baseEntities[chr] || entities[chr] || chr;
      });
    };
    var getEncodeFunc = function (name, entities) {
      var entitiesMap = buildEntitiesLookup(entities) || namedEntities;
      var encodeNamedAndNumeric = function (text, attr) {
        return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
          if (baseEntities[chr] !== undefined) {
            return baseEntities[chr];
          }
          if (entitiesMap[chr] !== undefined) {
            return entitiesMap[chr];
          }
          if (chr.length > 1) {
            return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
          }
          return '&#' + chr.charCodeAt(0) + ';';
        });
      };
      var encodeCustomNamed = function (text, attr) {
        return encodeNamed(text, attr, entitiesMap);
      };
      var nameMap = makeMap$1(name.replace(/\+/g, ','));
      if (nameMap.named && nameMap.numeric) {
        return encodeNamedAndNumeric;
      }
      if (nameMap.named) {
        if (entities) {
          return encodeCustomNamed;
        }
        return encodeNamed;
      }
      if (nameMap.numeric) {
        return encodeNumeric;
      }
      return encodeRaw;
    };
    var decode = function (text) {
      return text.replace(entityRegExp, function (all, numeric) {
        if (numeric) {
          if (numeric.charAt(0).toLowerCase() === 'x') {
            numeric = parseInt(numeric.substr(1), 16);
          } else {
            numeric = parseInt(numeric, 10);
          }
          if (numeric > 65535) {
            numeric -= 65536;
            return String.fromCharCode(55296 + (numeric >> 10), 56320 + (numeric & 1023));
          }
          return asciiMap[numeric] || String.fromCharCode(numeric);
        }
        return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
      });
    };
    var Entities = {
      encodeRaw: encodeRaw,
      encodeAllRaw: encodeAllRaw,
      encodeNumeric: encodeNumeric,
      encodeNamed: encodeNamed,
      getEncodeFunc: getEncodeFunc,
      decode: decode
    };

    var mapCache = {}, dummyObj = {};
    var makeMap$2 = Tools.makeMap, each$4 = Tools.each, extend$1 = Tools.extend, explode$1 = Tools.explode, inArray$1 = Tools.inArray;
    var split = function (items, delim) {
      items = Tools.trim(items);
      return items ? items.split(delim || ' ') : [];
    };
    var compileSchema = function (type) {
      var schema = {};
      var globalAttributes, blockContent;
      var phrasingContent, flowContent, html4BlockContent, html4PhrasingContent;
      var add = function (name, attributes, children) {
        var ni, attributesOrder, element;
        var arrayToMap = function (array, obj) {
          var map = {};
          var i, l;
          for (i = 0, l = array.length; i < l; i++) {
            map[array[i]] = obj || {};
          }
          return map;
        };
        children = children || [];
        attributes = attributes || '';
        if (typeof children === 'string') {
          children = split(children);
        }
        name = split(name);
        ni = name.length;
        while (ni--) {
          attributesOrder = split([
            globalAttributes,
            attributes
          ].join(' '));
          element = {
            attributes: arrayToMap(attributesOrder),
            attributesOrder: attributesOrder,
            children: arrayToMap(children, dummyObj)
          };
          schema[name[ni]] = element;
        }
      };
      var addAttrs = function (name, attributes) {
        var ni, schemaItem, i, l;
        name = split(name);
        ni = name.length;
        attributes = split(attributes);
        while (ni--) {
          schemaItem = schema[name[ni]];
          for (i = 0, l = attributes.length; i < l; i++) {
            schemaItem.attributes[attributes[i]] = {};
            schemaItem.attributesOrder.push(attributes[i]);
          }
        }
      };
      if (mapCache[type]) {
        return mapCache[type];
      }
      globalAttributes = 'id accesskey class dir lang style tabindex title role';
      blockContent = 'address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul';
      phrasingContent = 'a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd ' + 'label map noscript object q s samp script select small span strong sub sup ' + 'textarea u var #text #comment';
      if (type !== 'html4') {
        globalAttributes += ' contenteditable contextmenu draggable dropzone ' + 'hidden spellcheck translate';
        blockContent += ' article aside details dialog figure main header footer hgroup section nav';
        phrasingContent += ' audio canvas command datalist mark meter output picture ' + 'progress time wbr video ruby bdi keygen';
      }
      if (type !== 'html5-strict') {
        globalAttributes += ' xml:lang';
        html4PhrasingContent = 'acronym applet basefont big font strike tt';
        phrasingContent = [
          phrasingContent,
          html4PhrasingContent
        ].join(' ');
        each$4(split(html4PhrasingContent), function (name) {
          add(name, '', phrasingContent);
        });
        html4BlockContent = 'center dir isindex noframes';
        blockContent = [
          blockContent,
          html4BlockContent
        ].join(' ');
        flowContent = [
          blockContent,
          phrasingContent
        ].join(' ');
        each$4(split(html4BlockContent), function (name) {
          add(name, '', flowContent);
        });
      }
      flowContent = flowContent || [
        blockContent,
        phrasingContent
      ].join(' ');
      add('html', 'manifest', 'head body');
      add('head', '', 'base command link meta noscript script style title');
      add('title hr noscript br');
      add('base', 'href target');
      add('link', 'href rel media hreflang type sizes hreflang');
      add('meta', 'name http-equiv content charset');
      add('style', 'media type scoped');
      add('script', 'src async defer type charset');
      add('body', 'onafterprint onbeforeprint onbeforeunload onblur onerror onfocus ' + 'onhashchange onload onmessage onoffline ononline onpagehide onpageshow ' + 'onpopstate onresize onscroll onstorage onunload', flowContent);
      add('address dt dd div caption', '', flowContent);
      add('h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn', '', phrasingContent);
      add('blockquote', 'cite', flowContent);
      add('ol', 'reversed start type', 'li');
      add('ul', '', 'li');
      add('li', 'value', flowContent);
      add('dl', '', 'dt dd');
      add('a', 'href target rel media hreflang type', phrasingContent);
      add('q', 'cite', phrasingContent);
      add('ins del', 'cite datetime', flowContent);
      add('img', 'src sizes srcset alt usemap ismap width height');
      add('iframe', 'src name width height', flowContent);
      add('embed', 'src type width height');
      add('object', 'data type typemustmatch name usemap form width height', [
        flowContent,
        'param'
      ].join(' '));
      add('param', 'name value');
      add('map', 'name', [
        flowContent,
        'area'
      ].join(' '));
      add('area', 'alt coords shape href target rel media hreflang type');
      add('table', 'border', 'caption colgroup thead tfoot tbody tr' + (type === 'html4' ? ' col' : ''));
      add('colgroup', 'span', 'col');
      add('col', 'span');
      add('tbody thead tfoot', '', 'tr');
      add('tr', '', 'td th');
      add('td', 'colspan rowspan headers', flowContent);
      add('th', 'colspan rowspan headers scope abbr', flowContent);
      add('form', 'accept-charset action autocomplete enctype method name novalidate target', flowContent);
      add('fieldset', 'disabled form name', [
        flowContent,
        'legend'
      ].join(' '));
      add('label', 'form for', phrasingContent);
      add('input', 'accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate ' + 'formtarget height list max maxlength min multiple name pattern readonly required size src step type value width');
      add('button', 'disabled form formaction formenctype formmethod formnovalidate formtarget name type value', type === 'html4' ? flowContent : phrasingContent);
      add('select', 'disabled form multiple name required size', 'option optgroup');
      add('optgroup', 'disabled label', 'option');
      add('option', 'disabled label selected value');
      add('textarea', 'cols dirname disabled form maxlength name readonly required rows wrap');
      add('menu', 'type label', [
        flowContent,
        'li'
      ].join(' '));
      add('noscript', '', flowContent);
      if (type !== 'html4') {
        add('wbr');
        add('ruby', '', [
          phrasingContent,
          'rt rp'
        ].join(' '));
        add('figcaption', '', flowContent);
        add('mark rt rp summary bdi', '', phrasingContent);
        add('canvas', 'width height', flowContent);
        add('video', 'src crossorigin poster preload autoplay mediagroup loop ' + 'muted controls width height buffered', [
          flowContent,
          'track source'
        ].join(' '));
        add('audio', 'src crossorigin preload autoplay mediagroup loop muted controls ' + 'buffered volume', [
          flowContent,
          'track source'
        ].join(' '));
        add('picture', '', 'img source');
        add('source', 'src srcset type media sizes');
        add('track', 'kind src srclang label default');
        add('datalist', '', [
          phrasingContent,
          'option'
        ].join(' '));
        add('article section nav aside main header footer', '', flowContent);
        add('hgroup', '', 'h1 h2 h3 h4 h5 h6');
        add('figure', '', [
          flowContent,
          'figcaption'
        ].join(' '));
        add('time', 'datetime', phrasingContent);
        add('dialog', 'open', flowContent);
        add('command', 'type label icon disabled checked radiogroup command');
        add('output', 'for form name', phrasingContent);
        add('progress', 'value max', phrasingContent);
        add('meter', 'value min max low high optimum', phrasingContent);
        add('details', 'open', [
          flowContent,
          'summary'
        ].join(' '));
        add('keygen', 'autofocus challenge disabled form keytype name');
      }
      if (type !== 'html5-strict') {
        addAttrs('script', 'language xml:space');
        addAttrs('style', 'xml:space');
        addAttrs('object', 'declare classid code codebase codetype archive standby align border hspace vspace');
        addAttrs('embed', 'align name hspace vspace');
        addAttrs('param', 'valuetype type');
        addAttrs('a', 'charset name rev shape coords');
        addAttrs('br', 'clear');
        addAttrs('applet', 'codebase archive code object alt name width height align hspace vspace');
        addAttrs('img', 'name longdesc align border hspace vspace');
        addAttrs('iframe', 'longdesc frameborder marginwidth marginheight scrolling align');
        addAttrs('font basefont', 'size color face');
        addAttrs('input', 'usemap align');
        addAttrs('select', 'onchange');
        addAttrs('textarea');
        addAttrs('h1 h2 h3 h4 h5 h6 div p legend caption', 'align');
        addAttrs('ul', 'type compact');
        addAttrs('li', 'type');
        addAttrs('ol dl menu dir', 'compact');
        addAttrs('pre', 'width xml:space');
        addAttrs('hr', 'align noshade size width');
        addAttrs('isindex', 'prompt');
        addAttrs('table', 'summary width frame rules cellspacing cellpadding align bgcolor');
        addAttrs('col', 'width align char charoff valign');
        addAttrs('colgroup', 'width align char charoff valign');
        addAttrs('thead', 'align char charoff valign');
        addAttrs('tr', 'align char charoff valign bgcolor');
        addAttrs('th', 'axis align char charoff valign nowrap bgcolor width height');
        addAttrs('form', 'accept');
        addAttrs('td', 'abbr axis scope align char charoff valign nowrap bgcolor width height');
        addAttrs('tfoot', 'align char charoff valign');
        addAttrs('tbody', 'align char charoff valign');
        addAttrs('area', 'nohref');
        addAttrs('body', 'background bgcolor text link vlink alink');
      }
      if (type !== 'html4') {
        addAttrs('input button select textarea', 'autofocus');
        addAttrs('input textarea', 'placeholder');
        addAttrs('a', 'download');
        addAttrs('link script img', 'crossorigin');
        addAttrs('iframe', 'sandbox seamless allowfullscreen');
      }
      each$4(split('a form meter progress dfn'), function (name) {
        if (schema[name]) {
          delete schema[name].children[name];
        }
      });
      delete schema.caption.children.table;
      delete schema.script;
      mapCache[type] = schema;
      return schema;
    };
    var compileElementMap = function (value, mode) {
      var styles;
      if (value) {
        styles = {};
        if (typeof value === 'string') {
          value = { '*': value };
        }
        each$4(value, function (value, key) {
          styles[key] = styles[key.toUpperCase()] = mode === 'map' ? makeMap$2(value, /[, ]/) : explode$1(value, /[, ]/);
        });
      }
      return styles;
    };
    function Schema(settings) {
      var elements = {};
      var children = {};
      var patternElements = [];
      var validStyles;
      var invalidStyles;
      var schemaItems;
      var whiteSpaceElementsMap, selfClosingElementsMap, shortEndedElementsMap, boolAttrMap, validClasses;
      var blockElementsMap, nonEmptyElementsMap, moveCaretBeforeOnEnterElementsMap, textBlockElementsMap, textInlineElementsMap;
      var customElementsMap = {}, specialElements = {};
      var createLookupTable = function (option, defaultValue, extendWith) {
        var value = settings[option];
        if (!value) {
          value = mapCache[option];
          if (!value) {
            value = makeMap$2(defaultValue, ' ', makeMap$2(defaultValue.toUpperCase(), ' '));
            value = extend$1(value, extendWith);
            mapCache[option] = value;
          }
        } else {
          value = makeMap$2(value, /[, ]/, makeMap$2(value.toUpperCase(), /[, ]/));
        }
        return value;
      };
      settings = settings || {};
      schemaItems = compileSchema(settings.schema);
      if (settings.verify_html === false) {
        settings.valid_elements = '*[*]';
      }
      validStyles = compileElementMap(settings.valid_styles);
      invalidStyles = compileElementMap(settings.invalid_styles, 'map');
      validClasses = compileElementMap(settings.valid_classes, 'map');
      whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea video audio iframe object code');
      selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
      shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link ' + 'meta param embed source wbr track');
      boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' + 'noshade nowrap readonly selected autoplay loop controls');
      nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object ' + 'script pre code', shortEndedElementsMap);
      moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', 'table', nonEmptyElementsMap);
      textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' + 'blockquote center dir fieldset header footer article section hgroup aside main nav figure');
      blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' + 'th tr td li ol ul caption dl dt dd noscript menu isindex option ' + 'datalist select optgroup figcaption details summary', textBlockElementsMap);
      textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font strike u var cite ' + 'dfn code mark q sup sub samp');
      each$4((settings.special || 'script noscript iframe noframes noembed title style textarea xmp').split(' '), function (name) {
        specialElements[name] = new RegExp('</' + name + '[^>]*>', 'gi');
      });
      var patternToRegExp = function (str) {
        return new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$');
      };
      var addValidElements = function (validElements) {
        var ei, el, ai, al, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder, prefix, outputName, globalAttributes, globalAttributesOrder, key, value;
        var elementRuleRegExp = /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/, attrRuleRegExp = /^([!\-])?(\w+[\\:]:\w+|[^=:<]+)?(?:([=:<])(.*))?$/, hasPatternsRegExp = /[*?+]/;
        if (validElements) {
          validElements = split(validElements, ',');
          if (elements['@']) {
            globalAttributes = elements['@'].attributes;
            globalAttributesOrder = elements['@'].attributesOrder;
          }
          for (ei = 0, el = validElements.length; ei < el; ei++) {
            matches = elementRuleRegExp.exec(validElements[ei]);
            if (matches) {
              prefix = matches[1];
              elementName = matches[2];
              outputName = matches[3];
              attrData = matches[5];
              attributes = {};
              attributesOrder = [];
              element = {
                attributes: attributes,
                attributesOrder: attributesOrder
              };
              if (prefix === '#') {
                element.paddEmpty = true;
              }
              if (prefix === '-') {
                element.removeEmpty = true;
              }
              if (matches[4] === '!') {
                element.removeEmptyAttrs = true;
              }
              if (globalAttributes) {
                for (key in globalAttributes) {
                  attributes[key] = globalAttributes[key];
                }
                attributesOrder.push.apply(attributesOrder, globalAttributesOrder);
              }
              if (attrData) {
                attrData = split(attrData, '|');
                for (ai = 0, al = attrData.length; ai < al; ai++) {
                  matches = attrRuleRegExp.exec(attrData[ai]);
                  if (matches) {
                    attr = {};
                    attrType = matches[1];
                    attrName = matches[2].replace(/[\\:]:/g, ':');
                    prefix = matches[3];
                    value = matches[4];
                    if (attrType === '!') {
                      element.attributesRequired = element.attributesRequired || [];
                      element.attributesRequired.push(attrName);
                      attr.required = true;
                    }
                    if (attrType === '-') {
                      delete attributes[attrName];
                      attributesOrder.splice(inArray$1(attributesOrder, attrName), 1);
                      continue;
                    }
                    if (prefix) {
                      if (prefix === '=') {
                        element.attributesDefault = element.attributesDefault || [];
                        element.attributesDefault.push({
                          name: attrName,
                          value: value
                        });
                        attr.defaultValue = value;
                      }
                      if (prefix === ':') {
                        element.attributesForced = element.attributesForced || [];
                        element.attributesForced.push({
                          name: attrName,
                          value: value
                        });
                        attr.forcedValue = value;
                      }
                      if (prefix === '<') {
                        attr.validValues = makeMap$2(value, '?');
                      }
                    }
                    if (hasPatternsRegExp.test(attrName)) {
                      element.attributePatterns = element.attributePatterns || [];
                      attr.pattern = patternToRegExp(attrName);
                      element.attributePatterns.push(attr);
                    } else {
                      if (!attributes[attrName]) {
                        attributesOrder.push(attrName);
                      }
                      attributes[attrName] = attr;
                    }
                  }
                }
              }
              if (!globalAttributes && elementName === '@') {
                globalAttributes = attributes;
                globalAttributesOrder = attributesOrder;
              }
              if (outputName) {
                element.outputName = elementName;
                elements[outputName] = element;
              }
              if (hasPatternsRegExp.test(elementName)) {
                element.pattern = patternToRegExp(elementName);
                patternElements.push(element);
              } else {
                elements[elementName] = element;
              }
            }
          }
        }
      };
      var setValidElements = function (validElements) {
        elements = {};
        patternElements = [];
        addValidElements(validElements);
        each$4(schemaItems, function (element, name) {
          children[name] = element.children;
        });
      };
      var addCustomElements = function (customElements) {
        var customElementRegExp = /^(~)?(.+)$/;
        if (customElements) {
          mapCache.text_block_elements = mapCache.block_elements = null;
          each$4(split(customElements, ','), function (rule) {
            var matches = customElementRegExp.exec(rule), inline = matches[1] === '~', cloneName = inline ? 'span' : 'div', name = matches[2];
            children[name] = children[cloneName];
            customElementsMap[name] = cloneName;
            if (!inline) {
              blockElementsMap[name.toUpperCase()] = {};
              blockElementsMap[name] = {};
            }
            if (!elements[name]) {
              var customRule = elements[cloneName];
              customRule = extend$1({}, customRule);
              delete customRule.removeEmptyAttrs;
              delete customRule.removeEmpty;
              elements[name] = customRule;
            }
            each$4(children, function (element, elmName) {
              if (element[cloneName]) {
                children[elmName] = element = extend$1({}, children[elmName]);
                element[name] = element[cloneName];
              }
            });
          });
        }
      };
      var addValidChildren = function (validChildren) {
        var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/;
        mapCache[settings.schema] = null;
        if (validChildren) {
          each$4(split(validChildren, ','), function (rule) {
            var matches = childRuleRegExp.exec(rule);
            var parent, prefix;
            if (matches) {
              prefix = matches[1];
              if (prefix) {
                parent = children[matches[2]];
              } else {
                parent = children[matches[2]] = { '#comment': {} };
              }
              parent = children[matches[2]];
              each$4(split(matches[3], '|'), function (child) {
                if (prefix === '-') {
                  delete parent[child];
                } else {
                  parent[child] = {};
                }
              });
            }
          });
        }
      };
      var getElementRule = function (name) {
        var element = elements[name], i;
        if (element) {
          return element;
        }
        i = patternElements.length;
        while (i--) {
          element = patternElements[i];
          if (element.pattern.test(name)) {
            return element;
          }
        }
      };
      if (!settings.valid_elements) {
        each$4(schemaItems, function (element, name) {
          elements[name] = {
            attributes: element.attributes,
            attributesOrder: element.attributesOrder
          };
          children[name] = element.children;
        });
        if (settings.schema !== 'html5') {
          each$4(split('strong/b em/i'), function (item) {
            item = split(item, '/');
            elements[item[1]].outputName = item[0];
          });
        }
        each$4(split('ol ul sub sup blockquote span font a table tbody tr strong em b i'), function (name) {
          if (elements[name]) {
            elements[name].removeEmpty = true;
          }
        });
        each$4(split('p h1 h2 h3 h4 h5 h6 th td pre div address caption li'), function (name) {
          elements[name].paddEmpty = true;
        });
        each$4(split('span'), function (name) {
          elements[name].removeEmptyAttrs = true;
        });
      } else {
        setValidElements(settings.valid_elements);
      }
      addCustomElements(settings.custom_elements);
      addValidChildren(settings.valid_children);
      addValidElements(settings.extended_valid_elements);
      addValidChildren('+ol[ul|ol],+ul[ul|ol]');
      each$4({
        dd: 'dl',
        dt: 'dl',
        li: 'ul ol',
        td: 'tr',
        th: 'tr',
        tr: 'tbody thead tfoot',
        tbody: 'table',
        thead: 'table',
        tfoot: 'table',
        legend: 'fieldset',
        area: 'map',
        param: 'video audio object'
      }, function (parents, item) {
        if (elements[item]) {
          elements[item].parentsRequired = split(parents);
        }
      });
      if (settings.invalid_elements) {
        each$4(explode$1(settings.invalid_elements), function (item) {
          if (elements[item]) {
            delete elements[item];
          }
        });
      }
      if (!getElementRule('span')) {
        addValidElements('span[!data-mce-type|*]');
      }
      var getValidStyles = function () {
        return validStyles;
      };
      var getInvalidStyles = function () {
        return invalidStyles;
      };
      var getValidClasses = function () {
        return validClasses;
      };
      var getBoolAttrs = function () {
        return boolAttrMap;
      };
      var getBlockElements = function () {
        return blockElementsMap;
      };
      var getTextBlockElements = function () {
        return textBlockElementsMap;
      };
      var getTextInlineElements = function () {
        return textInlineElementsMap;
      };
      var getShortEndedElements = function () {
        return shortEndedElementsMap;
      };
      var getSelfClosingElements = function () {
        return selfClosingElementsMap;
      };
      var getNonEmptyElements = function () {
        return nonEmptyElementsMap;
      };
      var getMoveCaretBeforeOnEnterElements = function () {
        return moveCaretBeforeOnEnterElementsMap;
      };
      var getWhiteSpaceElements = function () {
        return whiteSpaceElementsMap;
      };
      var getSpecialElements = function () {
        return specialElements;
      };
      var isValidChild = function (name, child) {
        var parent = children[name.toLowerCase()];
        return !!(parent && parent[child.toLowerCase()]);
      };
      var isValid = function (name, attr) {
        var attrPatterns, i;
        var rule = getElementRule(name);
        if (rule) {
          if (attr) {
            if (rule.attributes[attr]) {
              return true;
            }
            attrPatterns = rule.attributePatterns;
            if (attrPatterns) {
              i = attrPatterns.length;
              while (i--) {
                if (attrPatterns[i].pattern.test(name)) {
                  return true;
                }
              }
            }
          } else {
            return true;
          }
        }
        return false;
      };
      var getCustomElements = function () {
        return customElementsMap;
      };
      return {
        children: children,
        elements: elements,
        getValidStyles: getValidStyles,
        getValidClasses: getValidClasses,
        getBlockElements: getBlockElements,
        getInvalidStyles: getInvalidStyles,
        getShortEndedElements: getShortEndedElements,
        getTextBlockElements: getTextBlockElements,
        getTextInlineElements: getTextInlineElements,
        getBoolAttrs: getBoolAttrs,
        getElementRule: getElementRule,
        getSelfClosingElements: getSelfClosingElements,
        getNonEmptyElements: getNonEmptyElements,
        getMoveCaretBeforeOnEnterElements: getMoveCaretBeforeOnEnterElements,
        getWhiteSpaceElements: getWhiteSpaceElements,
        getSpecialElements: getSpecialElements,
        isValidChild: isValidChild,
        isValid: isValid,
        getCustomElements: getCustomElements,
        addValidElements: addValidElements,
        setValidElements: setValidElements,
        addCustomElements: addCustomElements,
        addValidChildren: addValidChildren
      };
    }

    var toHex = function (match, r, g, b) {
      var hex = function (val) {
        val = parseInt(val, 10).toString(16);
        return val.length > 1 ? val : '0' + val;
      };
      return '#' + hex(r) + hex(g) + hex(b);
    };
    function Styles(settings, schema) {
      var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi;
      var urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi;
      var styleRegExp = /\s*([^:]+):\s*([^;]+);?/g;
      var trimRightRegExp = /\s+$/;
      var i;
      var encodingLookup = {};
      var encodingItems;
      var validStyles;
      var invalidStyles;
      var invisibleChar = '\uFEFF';
      settings = settings || {};
      if (schema) {
        validStyles = schema.getValidStyles();
        invalidStyles = schema.getInvalidStyles();
      }
      encodingItems = ('\\" \\\' \\; \\: ; : ' + invisibleChar).split(' ');
      for (i = 0; i < encodingItems.length; i++) {
        encodingLookup[encodingItems[i]] = invisibleChar + i;
        encodingLookup[invisibleChar + i] = encodingItems[i];
      }
      return {
        toHex: function (color) {
          return color.replace(rgbRegExp, toHex);
        },
        parse: function (css) {
          var styles = {};
          var matches, name, value, isEncoded;
          var urlConverter = settings.url_converter;
          var urlConverterScope = settings.url_converter_scope || this;
          var compress = function (prefix, suffix, noJoin) {
            var top, right, bottom, left;
            top = styles[prefix + '-top' + suffix];
            if (!top) {
              return;
            }
            right = styles[prefix + '-right' + suffix];
            if (!right) {
              return;
            }
            bottom = styles[prefix + '-bottom' + suffix];
            if (!bottom) {
              return;
            }
            left = styles[prefix + '-left' + suffix];
            if (!left) {
              return;
            }
            var box = [
              top,
              right,
              bottom,
              left
            ];
            i = box.length - 1;
            while (i--) {
              if (box[i] !== box[i + 1]) {
                break;
              }
            }
            if (i > -1 && noJoin) {
              return;
            }
            styles[prefix + suffix] = i === -1 ? box[0] : box.join(' ');
            delete styles[prefix + '-top' + suffix];
            delete styles[prefix + '-right' + suffix];
            delete styles[prefix + '-bottom' + suffix];
            delete styles[prefix + '-left' + suffix];
          };
          var canCompress = function (key) {
            var value = styles[key], i;
            if (!value) {
              return;
            }
            value = value.split(' ');
            i = value.length;
            while (i--) {
              if (value[i] !== value[0]) {
                return false;
              }
            }
            styles[key] = value[0];
            return true;
          };
          var compress2 = function (target, a, b, c) {
            if (!canCompress(a)) {
              return;
            }
            if (!canCompress(b)) {
              return;
            }
            if (!canCompress(c)) {
              return;
            }
            styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c];
            delete styles[a];
            delete styles[b];
            delete styles[c];
          };
          var encode = function (str) {
            isEncoded = true;
            return encodingLookup[str];
          };
          var decode = function (str, keepSlashes) {
            if (isEncoded) {
              str = str.replace(/\uFEFF[0-9]/g, function (str) {
                return encodingLookup[str];
              });
            }
            if (!keepSlashes) {
              str = str.replace(/\\([\'\";:])/g, '$1');
            }
            return str;
          };
          var decodeSingleHexSequence = function (escSeq) {
            return String.fromCharCode(parseInt(escSeq.slice(1), 16));
          };
          var decodeHexSequences = function (value) {
            return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence);
          };
          var processUrl = function (match, url, url2, url3, str, str2) {
            str = str || str2;
            if (str) {
              str = decode(str);
              return '\'' + str.replace(/\'/g, '\\\'') + '\'';
            }
            url = decode(url || url2 || url3);
            if (!settings.allow_script_urls) {
              var scriptUrl = url.replace(/[\s\r\n]+/g, '');
              if (/(java|vb)script:/i.test(scriptUrl)) {
                return '';
              }
              if (!settings.allow_svg_data_urls && /^data:image\/svg/i.test(scriptUrl)) {
                return '';
              }
            }
            if (urlConverter) {
              url = urlConverter.call(urlConverterScope, url, 'style');
            }
            return 'url(\'' + url.replace(/\'/g, '\\\'') + '\')';
          };
          if (css) {
            css = css.replace(/[\u0000-\u001F]/g, '');
            css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, function (str) {
              return str.replace(/[;:]/g, encode);
            });
            while (matches = styleRegExp.exec(css)) {
              styleRegExp.lastIndex = matches.index + matches[0].length;
              name = matches[1].replace(trimRightRegExp, '').toLowerCase();
              value = matches[2].replace(trimRightRegExp, '');
              if (name && value) {
                name = decodeHexSequences(name);
                value = decodeHexSequences(value);
                if (name.indexOf(invisibleChar) !== -1 || name.indexOf('"') !== -1) {
                  continue;
                }
                if (!settings.allow_script_urls && (name === 'behavior' || /expression\s*\(|\/\*|\*\//.test(value))) {
                  continue;
                }
                if (name === 'font-weight' && value === '700') {
                  value = 'bold';
                } else if (name === 'color' || name === 'background-color') {
                  value = value.toLowerCase();
                }
                value = value.replace(rgbRegExp, toHex);
                value = value.replace(urlOrStrRegExp, processUrl);
                styles[name] = isEncoded ? decode(value, true) : value;
              }
            }
            compress('border', '', true);
            compress('border', '-width');
            compress('border', '-color');
            compress('border', '-style');
            compress('padding', '');
            compress('margin', '');
            compress2('border', 'border-width', 'border-style', 'border-color');
            if (styles.border === 'medium none') {
              delete styles.border;
            }
            if (styles['border-image'] === 'none') {
              delete styles['border-image'];
            }
          }
          return styles;
        },
        serialize: function (styles, elementName) {
          var css = '', name, value;
          var serializeStyles = function (name) {
            var styleList, i, l, value;
            styleList = validStyles[name];
            if (styleList) {
              for (i = 0, l = styleList.length; i < l; i++) {
                name = styleList[i];
                value = styles[name];
                if (value) {
                  css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
                }
              }
            }
          };
          var isValid = function (name, elementName) {
            var styleMap;
            styleMap = invalidStyles['*'];
            if (styleMap && styleMap[name]) {
              return false;
            }
            styleMap = invalidStyles[elementName];
            if (styleMap && styleMap[name]) {
              return false;
            }
            return true;
          };
          if (elementName && validStyles) {
            serializeStyles('*');
            serializeStyles(elementName);
          } else {
            for (name in styles) {
              value = styles[name];
              if (value && (!invalidStyles || isValid(name, elementName))) {
                css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
              }
            }
          }
          return css;
        }
      };
    }

    var each$5 = Tools.each;
    var grep$1 = Tools.grep;
    var isIE = Env.ie;
    var simpleSelectorRe = /^([a-z0-9],?)+$/i;
    var whiteSpaceRegExp$2 = /^[ \t\r\n]*$/;
    var setupAttrHooks = function (styles, settings, getContext) {
      var attrHooks = {};
      var keepValues = settings.keep_values;
      var keepUrlHook = {
        set: function ($elm, value, name) {
          if (settings.url_converter) {
            value = settings.url_converter.call(settings.url_converter_scope || getContext(), value, name, $elm[0]);
          }
          $elm.attr('data-mce-' + name, value).attr(name, value);
        },
        get: function ($elm, name) {
          return $elm.attr('data-mce-' + name) || $elm.attr(name);
        }
      };
      attrHooks = {
        style: {
          set: function ($elm, value) {
            if (value !== null && typeof value === 'object') {
              $elm.css(value);
              return;
            }
            if (keepValues) {
              $elm.attr('data-mce-style', value);
            }
            $elm.attr('style', value);
          },
          get: function ($elm) {
            var value = $elm.attr('data-mce-style') || $elm.attr('style');
            value = styles.serialize(styles.parse(value), $elm[0].nodeName);
            return value;
          }
        }
      };
      if (keepValues) {
        attrHooks.href = attrHooks.src = keepUrlHook;
      }
      return attrHooks;
    };
    var updateInternalStyleAttr = function (styles, $elm) {
      var rawValue = $elm.attr('style');
      var value = styles.serialize(styles.parse(rawValue), $elm[0].nodeName);
      if (!value) {
        value = null;
      }
      $elm.attr('data-mce-style', value);
    };
    var findNodeIndex = function (node, normalized) {
      var idx = 0, lastNodeType, nodeType;
      if (node) {
        for (lastNodeType = node.nodeType, node = node.previousSibling; node; node = node.previousSibling) {
          nodeType = node.nodeType;
          if (normalized && nodeType === 3) {
            if (nodeType === lastNodeType || !node.nodeValue.length) {
              continue;
            }
          }
          idx++;
          lastNodeType = nodeType;
        }
      }
      return idx;
    };
    function DOMUtils(doc, settings) {
      var _this = this;
      if (settings === void 0) {
        settings = {};
      }
      var attrHooks;
      var addedStyles = {};
      var win = domGlobals.window;
      var files = {};
      var counter = 0;
      var stdMode = true;
      var boxModel = true;
      var styleSheetLoader = StyleSheetLoader(doc, { contentCssCors: settings.contentCssCors });
      var boundEvents = [];
      var schema = settings.schema ? settings.schema : Schema({});
      var styles = Styles({
        url_converter: settings.url_converter,
        url_converter_scope: settings.url_converter_scope
      }, settings.schema);
      var events = settings.ownEvents ? new EventUtils(settings.proxy) : EventUtils.Event;
      var blockElementsMap = schema.getBlockElements();
      var $ = DomQuery.overrideDefaults(function () {
        return {
          context: doc,
          element: self.getRoot()
        };
      });
      var isBlock = function (node) {
        if (typeof node === 'string') {
          return !!blockElementsMap[node];
        } else if (node) {
          var type = node.nodeType;
          if (type) {
            return !!(type === 1 && blockElementsMap[node.nodeName]);
          }
        }
        return false;
      };
      var get = function (elm) {
        if (elm && doc && typeof elm === 'string') {
          var node = doc.getElementById(elm);
          if (node && node.id !== elm) {
            return doc.getElementsByName(elm)[1];
          } else {
            return node;
          }
        }
        return elm;
      };
      var $$ = function (elm) {
        if (typeof elm === 'string') {
          elm = get(elm);
        }
        return $(elm);
      };
      var getAttrib = function (elm, name, defaultVal) {
        var hook, value;
        var $elm = $$(elm);
        if ($elm.length) {
          hook = attrHooks[name];
          if (hook && hook.get) {
            value = hook.get($elm, name);
          } else {
            value = $elm.attr(name);
          }
        }
        if (typeof value === 'undefined') {
          value = defaultVal || '';
        }
        return value;
      };
      var getAttribs = function (elm) {
        var node = get(elm);
        if (!node) {
          return [];
        }
        return node.attributes;
      };
      var setAttrib = function (elm, name, value) {
        var originalValue, hook;
        if (value === '') {
          value = null;
        }
        var $elm = $$(elm);
        originalValue = $elm.attr(name);
        if (!$elm.length) {
          return;
        }
        hook = attrHooks[name];
        if (hook && hook.set) {
          hook.set($elm, value, name);
        } else {
          $elm.attr(name, value);
        }
        if (originalValue !== value && settings.onSetAttrib) {
          settings.onSetAttrib({
            attrElm: $elm,
            attrName: name,
            attrValue: value
          });
        }
      };
      var clone = function (node, deep) {
        if (!isIE || node.nodeType !== 1 || deep) {
          return node.cloneNode(deep);
        }
        if (!deep) {
          var clone_1 = doc.createElement(node.nodeName);
          each$5(getAttribs(node), function (attr) {
            setAttrib(clone_1, attr.nodeName, getAttrib(node, attr.nodeName));
          });
          return clone_1;
        }
        return null;
      };
      var getRoot = function () {
        return settings.root_element || doc.body;
      };
      var getViewPort = function (argWin) {
        var actWin = !argWin ? win : argWin;
        var doc = actWin.document;
        var rootElm =  doc.documentElement ;
        return {
          x: actWin.pageXOffset || rootElm.scrollLeft,
          y: actWin.pageYOffset || rootElm.scrollTop,
          w: actWin.innerWidth || rootElm.clientWidth,
          h: actWin.innerHeight || rootElm.clientHeight
        };
      };
      var getPos = function (elm, rootElm) {
        return Position.getPos(doc.body, get(elm), rootElm);
      };
      var setStyle = function (elm, name, value) {
        var $elm = $$(elm).css(name, value);
        if (settings.update_styles) {
          updateInternalStyleAttr(styles, $elm);
        }
      };
      var setStyles = function (elm, stylesArg) {
        var $elm = $$(elm).css(stylesArg);
        if (settings.update_styles) {
          updateInternalStyleAttr(styles, $elm);
        }
      };
      var getStyle = function (elm, name, computed) {
        var $elm = $$(elm);
        if (computed) {
          return $elm.css(name);
        }
        name = name.replace(/-(\D)/g, function (a, b) {
          return b.toUpperCase();
        });
        if (name === 'float') {
          name = Env.ie && Env.ie < 12 ? 'styleFloat' : 'cssFloat';
        }
        return $elm[0] && $elm[0].style ? $elm[0].style[name] : undefined;
      };
      var getSize = function (elm) {
        var w, h;
        elm = get(elm);
        w = getStyle(elm, 'width');
        h = getStyle(elm, 'height');
        if (w.indexOf('px') === -1) {
          w = 0;
        }
        if (h.indexOf('px') === -1) {
          h = 0;
        }
        return {
          w: parseInt(w, 10) || elm.offsetWidth || elm.clientWidth,
          h: parseInt(h, 10) || elm.offsetHeight || elm.clientHeight
        };
      };
      var getRect = function (elm) {
        var pos, size;
        elm = get(elm);
        pos = getPos(elm);
        size = getSize(elm);
        return {
          x: pos.x,
          y: pos.y,
          w: size.w,
          h: size.h
        };
      };
      var is = function (elm, selector) {
        var i;
        if (!elm) {
          return false;
        }
        if (!Array.isArray(elm)) {
          if (selector === '*') {
            return elm.nodeType === 1;
          }
          if (simpleSelectorRe.test(selector)) {
            var selectors = selector.toLowerCase().split(/,/);
            var elmName = elm.nodeName.toLowerCase();
            for (i = selectors.length - 1; i >= 0; i--) {
              if (selectors[i] === elmName) {
                return true;
              }
            }
            return false;
          }
          if (elm.nodeType && elm.nodeType !== 1) {
            return false;
          }
        }
        var elms = !Array.isArray(elm) ? [elm] : elm;
        return Sizzle(selector, elms[0].ownerDocument || elms[0], null, elms).length > 0;
      };
      var getParents = function (elm, selector, root, collect) {
        var result = [];
        var selectorVal;
        var node = get(elm);
        collect = collect === undefined;
        root = root || (getRoot().nodeName !== 'BODY' ? getRoot().parentNode : null);
        if (Tools.is(selector, 'string')) {
          selectorVal = selector;
          if (selector === '*') {
            selector = function (node) {
              return node.nodeType === 1;
            };
          } else {
            selector = function (node) {
              return is(node, selectorVal);
            };
          }
        }
        while (node) {
          if (node === root || !node.nodeType || node.nodeType === 9) {
            break;
          }
          if (!selector || typeof selector === 'function' && selector(node)) {
            if (collect) {
              result.push(node);
            } else {
              return [node];
            }
          }
          node = node.parentNode;
        }
        return collect ? result : null;
      };
      var getParent = function (node, selector, root) {
        var parents = getParents(node, selector, root, false);
        return parents && parents.length > 0 ? parents[0] : null;
      };
      var _findSib = function (node, selector, name) {
        var func = selector;
        if (node) {
          if (typeof selector === 'string') {
            func = function (node) {
              return is(node, selector);
            };
          }
          for (node = node[name]; node; node = node[name]) {
            if (typeof func === 'function' && func(node)) {
              return node;
            }
          }
        }
        return null;
      };
      var getNext = function (node, selector) {
        return _findSib(node, selector, 'nextSibling');
      };
      var getPrev = function (node, selector) {
        return _findSib(node, selector, 'previousSibling');
      };
      var select = function (selector, scope) {
        return Sizzle(selector, get(scope) || settings.root_element || doc, []);
      };
      var run = function (elm, func, scope) {
        var result;
        var node = typeof elm === 'string' ? get(elm) : elm;
        if (!node) {
          return false;
        }
        if (Tools.isArray(node) && (node.length || node.length === 0)) {
          result = [];
          each$5(node, function (elm, i) {
            if (elm) {
              if (typeof elm === 'string') {
                elm = get(elm);
              }
              result.push(func.call(scope, elm, i));
            }
          });
          return result;
        }
        var context = scope ? scope : _this;
        return func.call(context, node);
      };
      var setAttribs = function (elm, attrs) {
        $$(elm).each(function (i, node) {
          each$5(attrs, function (value, name) {
            setAttrib(node, name, value);
          });
        });
      };
      var setHTML = function (elm, html) {
        var $elm = $$(elm);
        if (isIE) {
          $elm.each(function (i, target) {
            if (target.canHaveHTML === false) {
              return;
            }
            while (target.firstChild) {
              target.removeChild(target.firstChild);
            }
            try {
              target.innerHTML = '<br>' + html;
              target.removeChild(target.firstChild);
            } catch (ex) {
              DomQuery('<div></div>').html('<br>' + html).contents().slice(1).appendTo(target);
            }
            return html;
          });
        } else {
          $elm.html(html);
        }
      };
      var add = function (parentElm, name, attrs, html, create) {
        return run(parentElm, function (parentElm) {
          var newElm = typeof name === 'string' ? doc.createElement(name) : name;
          setAttribs(newElm, attrs);
          if (html) {
            if (typeof html !== 'string' && html.nodeType) {
              newElm.appendChild(html);
            } else if (typeof html === 'string') {
              setHTML(newElm, html);
            }
          }
          return !create ? parentElm.appendChild(newElm) : newElm;
        });
      };
      var create = function (name, attrs, html) {
        return add(doc.createElement(name), name, attrs, html, true);
      };
      var decode = Entities.decode;
      var encode = Entities.encodeAllRaw;
      var createHTML = function (name, attrs, html) {
        var outHtml = '', key;
        outHtml += '<' + name;
        for (key in attrs) {
          if (attrs.hasOwnProperty(key) && attrs[key] !== null && typeof attrs[key] !== 'undefined') {
            outHtml += ' ' + key + '="' + encode(attrs[key]) + '"';
          }
        }
        if (typeof html !== 'undefined') {
          return outHtml + '>' + html + '</' + name + '>';
        }
        return outHtml + ' />';
      };
      var createFragment = function (html) {
        var node;
        var container = doc.createElement('div');
        var frag = doc.createDocumentFragment();
        frag.appendChild(container);
        if (html) {
          container.innerHTML = html;
        }
        while (node = container.firstChild) {
          frag.appendChild(node);
        }
        frag.removeChild(container);
        return frag;
      };
      var remove = function (node, keepChildren) {
        var $node = $$(node);
        if (keepChildren) {
          $node.each(function () {
            var child;
            while (child = this.firstChild) {
              if (child.nodeType === 3 && child.data.length === 0) {
                this.removeChild(child);
              } else {
                this.parentNode.insertBefore(child, this);
              }
            }
          }).remove();
        } else {
          $node.remove();
        }
        return $node.length > 1 ? $node.toArray() : $node[0];
      };
      var removeAllAttribs = function (e) {
        return run(e, function (e) {
          var i;
          var attrs = e.attributes;
          for (i = attrs.length - 1; i >= 0; i--) {
            e.removeAttributeNode(attrs.item(i));
          }
        });
      };
      var parseStyle = function (cssText) {
        return styles.parse(cssText);
      };
      var serializeStyle = function (stylesArg, name) {
        return styles.serialize(stylesArg, name);
      };
      var addStyle = function (cssText) {
        var head, styleElm;
        if (self !== DOMUtils.DOM && doc === domGlobals.document) {
          if (addedStyles[cssText]) {
            return;
          }
          addedStyles[cssText] = true;
        }
        styleElm = doc.getElementById('mceDefaultStyles');
        if (!styleElm) {
          styleElm = doc.createElement('style');
          styleElm.id = 'mceDefaultStyles';
          styleElm.type = 'text/css';
          head = doc.getElementsByTagName('head')[0];
          if (head.firstChild) {
            head.insertBefore(styleElm, head.firstChild);
          } else {
            head.appendChild(styleElm);
          }
        }
        if (styleElm.styleSheet) {
          styleElm.styleSheet.cssText += cssText;
        } else {
          styleElm.appendChild(doc.createTextNode(cssText));
        }
      };
      var loadCSS = function (url) {
        var head;
        if (self !== DOMUtils.DOM && doc === domGlobals.document) {
          DOMUtils.DOM.loadCSS(url);
          return;
        }
        if (!url) {
          url = '';
        }
        head = doc.getElementsByTagName('head')[0];
        each$5(url.split(','), function (url) {
          var link;
          url = Tools._addCacheSuffix(url);
          if (files[url]) {
            return;
          }
          files[url] = true;
          link = create('link', {
            rel: 'stylesheet',
            href: url
          });
          head.appendChild(link);
        });
      };
      var toggleClass = function (elm, cls, state) {
        $$(elm).toggleClass(cls, state).each(function () {
          if (this.className === '') {
            DomQuery(this).attr('class', null);
          }
        });
      };
      var addClass = function (elm, cls) {
        $$(elm).addClass(cls);
      };
      var removeClass = function (elm, cls) {
        toggleClass(elm, cls, false);
      };
      var hasClass = function (elm, cls) {
        return $$(elm).hasClass(cls);
      };
      var show = function (elm) {
        $$(elm).show();
      };
      var hide = function (elm) {
        $$(elm).hide();
      };
      var isHidden = function (elm) {
        return $$(elm).css('display') === 'none';
      };
      var uniqueId = function (prefix) {
        return (!prefix ? 'mce_' : prefix) + counter++;
      };
      var getOuterHTML = function (elm) {
        var node = typeof elm === 'string' ? get(elm) : elm;
        return NodeType.isElement(node) ? node.outerHTML : DomQuery('<div></div>').append(DomQuery(node).clone()).html();
      };
      var setOuterHTML = function (elm, html) {
        $$(elm).each(function () {
          try {
            if ('outerHTML' in this) {
              this.outerHTML = html;
              return;
            }
          } catch (ex) {
          }
          remove(DomQuery(this).html(html), true);
        });
      };
      var insertAfter = function (node, reference) {
        var referenceNode = get(reference);
        return run(node, function (node) {
          var parent, nextSibling;
          parent = referenceNode.parentNode;
          nextSibling = referenceNode.nextSibling;
          if (nextSibling) {
            parent.insertBefore(node, nextSibling);
          } else {
            parent.appendChild(node);
          }
          return node;
        });
      };
      var replace = function (newElm, oldElm, keepChildren) {
        return run(oldElm, function (oldElm) {
          if (Tools.is(oldElm, 'array')) {
            newElm = newElm.cloneNode(true);
          }
          if (keepChildren) {
            each$5(grep$1(oldElm.childNodes), function (node) {
              newElm.appendChild(node);
            });
          }
          return oldElm.parentNode.replaceChild(newElm, oldElm);
        });
      };
      var rename = function (elm, name) {
        var newElm;
        if (elm.nodeName !== name.toUpperCase()) {
          newElm = create(name);
          each$5(getAttribs(elm), function (attrNode) {
            setAttrib(newElm, attrNode.nodeName, getAttrib(elm, attrNode.nodeName));
          });
          replace(newElm, elm, true);
        }
        return newElm || elm;
      };
      var findCommonAncestor = function (a, b) {
        var ps = a, pe;
        while (ps) {
          pe = b;
          while (pe && ps !== pe) {
            pe = pe.parentNode;
          }
          if (ps === pe) {
            break;
          }
          ps = ps.parentNode;
        }
        if (!ps && a.ownerDocument) {
          return a.ownerDocument.documentElement;
        }
        return ps;
      };
      var toHex = function (rgbVal) {
        return styles.toHex(Tools.trim(rgbVal));
      };
      var isEmpty = function (node, elements) {
        var i, attributes, type, whitespace, walker, name, brCount = 0;
        node = node.firstChild;
        if (node) {
          walker = new TreeWalker(node, node.parentNode);
          elements = elements || (schema ? schema.getNonEmptyElements() : null);
          whitespace = schema ? schema.getWhiteSpaceElements() : {};
          do {
            type = node.nodeType;
            if (NodeType.isElement(node)) {
              var bogusVal = node.getAttribute('data-mce-bogus');
              if (bogusVal) {
                node = walker.next(bogusVal === 'all');
                continue;
              }
              name = node.nodeName.toLowerCase();
              if (elements && elements[name]) {
                if (name === 'br') {
                  brCount++;
                  node = walker.next();
                  continue;
                }
                return false;
              }
              attributes = getAttribs(node);
              i = attributes.length;
              while (i--) {
                name = attributes[i].nodeName;
                if (name === 'name' || name === 'data-mce-bookmark') {
                  return false;
                }
              }
            }
            if (type === 8) {
              return false;
            }
            if (type === 3 && !whiteSpaceRegExp$2.test(node.nodeValue)) {
              return false;
            }
            if (type === 3 && node.parentNode && whitespace[node.parentNode.nodeName] && whiteSpaceRegExp$2.test(node.nodeValue)) {
              return false;
            }
            node = walker.next();
          } while (node);
        }
        return brCount <= 1;
      };
      var createRng = function () {
        return doc.createRange();
      };
      var split = function (parentElm, splitElm, replacementElm) {
        var r = createRng(), bef, aft, pa;
        if (parentElm && splitElm) {
          r.setStart(parentElm.parentNode, findNodeIndex(parentElm));
          r.setEnd(splitElm.parentNode, findNodeIndex(splitElm));
          bef = r.extractContents();
          r = createRng();
          r.setStart(splitElm.parentNode, findNodeIndex(splitElm) + 1);
          r.setEnd(parentElm.parentNode, findNodeIndex(parentElm) + 1);
          aft = r.extractContents();
          pa = parentElm.parentNode;
          pa.insertBefore(TrimNode.trimNode(self, bef), parentElm);
          if (replacementElm) {
            pa.insertBefore(replacementElm, parentElm);
          } else {
            pa.insertBefore(splitElm, parentElm);
          }
          pa.insertBefore(TrimNode.trimNode(self, aft), parentElm);
          remove(parentElm);
          return replacementElm || splitElm;
        }
      };
      var bind = function (target, name, func, scope) {
        if (Tools.isArray(target)) {
          var i = target.length;
          while (i--) {
            target[i] = bind(target[i], name, func, scope);
          }
          return target;
        }
        if (settings.collect && (target === doc || target === win)) {
          boundEvents.push([
            target,
            name,
            func,
            scope
          ]);
        }
        return events.bind(target, name, func, scope || self);
      };
      var unbind = function (target, name, func) {
        var i;
        if (Tools.isArray(target)) {
          i = target.length;
          while (i--) {
            target[i] = unbind(target[i], name, func);
          }
          return target;
        }
        if (boundEvents && (target === doc || target === win)) {
          i = boundEvents.length;
          while (i--) {
            var item = boundEvents[i];
            if (target === item[0] && (!name || name === item[1]) && (!func || func === item[2])) {
              events.unbind(item[0], item[1], item[2]);
            }
          }
        }
        return events.unbind(target, name, func);
      };
      var fire = function (target, name, evt) {
        return events.fire(target, name, evt);
      };
      var getContentEditable = function (node) {
        if (node && NodeType.isElement(node)) {
          var contentEditable = node.getAttribute('data-mce-contenteditable');
          if (contentEditable && contentEditable !== 'inherit') {
            return contentEditable;
          }
          return node.contentEditable !== 'inherit' ? node.contentEditable : null;
        } else {
          return null;
        }
      };
      var getContentEditableParent = function (node) {
        var root = getRoot();
        var state = null;
        for (; node && node !== root; node = node.parentNode) {
          state = getContentEditable(node);
          if (state !== null) {
            break;
          }
        }
        return state;
      };
      var destroy = function () {
        if (boundEvents) {
          var i = boundEvents.length;
          while (i--) {
            var item = boundEvents[i];
            events.unbind(item[0], item[1], item[2]);
          }
        }
        if (Sizzle.setDocument) {
          Sizzle.setDocument();
        }
      };
      var isChildOf = function (node, parent) {
        while (node) {
          if (parent === node) {
            return true;
          }
          node = node.parentNode;
        }
        return false;
      };
      var dumpRng = function (r) {
        return 'startContainer: ' + r.startContainer.nodeName + ', startOffset: ' + r.startOffset + ', endContainer: ' + r.endContainer.nodeName + ', endOffset: ' + r.endOffset;
      };
      var self = {
        doc: doc,
        settings: settings,
        win: win,
        files: files,
        stdMode: stdMode,
        boxModel: boxModel,
        styleSheetLoader: styleSheetLoader,
        boundEvents: boundEvents,
        styles: styles,
        schema: schema,
        events: events,
        isBlock: isBlock,
        $: $,
        $$: $$,
        root: null,
        clone: clone,
        getRoot: getRoot,
        getViewPort: getViewPort,
        getRect: getRect,
        getSize: getSize,
        getParent: getParent,
        getParents: getParents,
        get: get,
        getNext: getNext,
        getPrev: getPrev,
        select: select,
        is: is,
        add: add,
        create: create,
        createHTML: createHTML,
        createFragment: createFragment,
        remove: remove,
        setStyle: setStyle,
        getStyle: getStyle,
        setStyles: setStyles,
        removeAllAttribs: removeAllAttribs,
        setAttrib: setAttrib,
        setAttribs: setAttribs,
        getAttrib: getAttrib,
        getPos: getPos,
        parseStyle: parseStyle,
        serializeStyle: serializeStyle,
        addStyle: addStyle,
        loadCSS: loadCSS,
        addClass: addClass,
        removeClass: removeClass,
        hasClass: hasClass,
        toggleClass: toggleClass,
        show: show,
        hide: hide,
        isHidden: isHidden,
        uniqueId: uniqueId,
        setHTML: setHTML,
        getOuterHTML: getOuterHTML,
        setOuterHTML: setOuterHTML,
        decode: decode,
        encode: encode,
        insertAfter: insertAfter,
        replace: replace,
        rename: rename,
        findCommonAncestor: findCommonAncestor,
        toHex: toHex,
        run: run,
        getAttribs: getAttribs,
        isEmpty: isEmpty,
        createRng: createRng,
        nodeIndex: findNodeIndex,
        split: split,
        bind: bind,
        unbind: unbind,
        fire: fire,
        getContentEditable: getContentEditable,
        getContentEditableParent: getContentEditableParent,
        destroy: destroy,
        isChildOf: isChildOf,
        dumpRng: dumpRng
      };
      attrHooks = setupAttrHooks(styles, settings, function () {
        return self;
      });
      return self;
    }
    (function (DOMUtils) {
      DOMUtils.DOM = DOMUtils(domGlobals.document);
      DOMUtils.nodeIndex = findNodeIndex;
    }(DOMUtils || (DOMUtils = {})));
    var DOMUtils$1 = DOMUtils;

    var DOM = DOMUtils$1.DOM;
    var each$6 = Tools.each, grep$2 = Tools.grep;
    var isFunction$1 = function (f) {
      return typeof f === 'function';
    };
    var ScriptLoader = function () {
      var QUEUED = 0;
      var LOADING = 1;
      var LOADED = 2;
      var FAILED = 3;
      var states = {};
      var queue = [];
      var scriptLoadedCallbacks = {};
      var queueLoadedCallbacks = [];
      var loading = 0;
      var loadScript = function (url, success, failure) {
        var dom = DOM;
        var elm, id;
        var done = function () {
          dom.remove(id);
          if (elm) {
            elm.onreadystatechange = elm.onload = elm = null;
          }
          success();
        };
        var error = function () {
          if (isFunction$1(failure)) {
            failure();
          } else {
            if (typeof console !== 'undefined' && console.log) {
              console.log('Failed to load script: ' + url);
            }
          }
        };
        id = dom.uniqueId();
        elm = domGlobals.document.createElement('script');
        elm.id = id;
        elm.type = 'text/javascript';
        elm.src = Tools._addCacheSuffix(url);
        elm.onload = done;
        elm.onerror = error;
        (domGlobals.document.getElementsByTagName('head')[0] || domGlobals.document.body).appendChild(elm);
      };
      this.isDone = function (url) {
        return states[url] === LOADED;
      };
      this.markDone = function (url) {
        states[url] = LOADED;
      };
      this.add = this.load = function (url, success, scope, failure) {
        var state = states[url];
        if (state === undefined) {
          queue.push(url);
          states[url] = QUEUED;
        }
        if (success) {
          if (!scriptLoadedCallbacks[url]) {
            scriptLoadedCallbacks[url] = [];
          }
          scriptLoadedCallbacks[url].push({
            success: success,
            failure: failure,
            scope: scope || this
          });
        }
      };
      this.remove = function (url) {
        delete states[url];
        delete scriptLoadedCallbacks[url];
      };
      this.loadQueue = function (success, scope, failure) {
        this.loadScripts(queue, success, scope, failure);
      };
      this.loadScripts = function (scripts, success, scope, failure) {
        var loadScripts;
        var failures = [];
        var execCallbacks = function (name, url) {
          each$6(scriptLoadedCallbacks[url], function (callback) {
            if (isFunction$1(callback[name])) {
              callback[name].call(callback.scope);
            }
          });
          scriptLoadedCallbacks[url] = undefined;
        };
        queueLoadedCallbacks.push({
          success: success,
          failure: failure,
          scope: scope || this
        });
        loadScripts = function () {
          var loadingScripts = grep$2(scripts);
          scripts.length = 0;
          each$6(loadingScripts, function (url) {
            if (states[url] === LOADED) {
              execCallbacks('success', url);
              return;
            }
            if (states[url] === FAILED) {
              execCallbacks('failure', url);
              return;
            }
            if (states[url] !== LOADING) {
              states[url] = LOADING;
              loading++;
              loadScript(url, function () {
                states[url] = LOADED;
                loading--;
                execCallbacks('success', url);
                loadScripts();
              }, function () {
                states[url] = FAILED;
                loading--;
                failures.push(url);
                execCallbacks('failure', url);
                loadScripts();
              });
            }
          });
          if (!loading) {
            var notifyCallbacks = queueLoadedCallbacks.slice(0);
            queueLoadedCallbacks.length = 0;
            each$6(notifyCallbacks, function (callback) {
              if (failures.length === 0) {
                if (isFunction$1(callback.success)) {
                  callback.success.call(callback.scope);
                }
              } else {
                if (isFunction$1(callback.failure)) {
                  callback.failure.call(callback.scope, failures);
                }
              }
            });
          }
        };
        loadScripts();
      };
    };
    ScriptLoader.ScriptLoader = new ScriptLoader();

    var each$7 = Tools.each;
    function AddOnManager() {
      var _this = this;
      var items = [];
      var urls = {};
      var lookup = {};
      var _listeners = [];
      var get = function (name) {
        if (lookup[name]) {
          return lookup[name].instance;
        }
        return undefined;
      };
      var dependencies = function (name) {
        var result;
        if (lookup[name]) {
          result = lookup[name].dependencies;
        }
        return result || [];
      };
      var requireLangPack = function (name, languages) {
        var language = AddOnManager.language;
        if (language && AddOnManager.languageLoad !== false) {
          if (languages) {
            languages = ',' + languages + ',';
            if (languages.indexOf(',' + language.substr(0, 2) + ',') !== -1) {
              language = language.substr(0, 2);
            } else if (languages.indexOf(',' + language + ',') === -1) {
              return;
            }
          }
          ScriptLoader.ScriptLoader.add(urls[name] + '/langs/' + language + '.js');
        }
      };
      var add = function (id, addOn, dependencies) {
        items.push(addOn);
        lookup[id] = {
          instance: addOn,
          dependencies: dependencies
        };
        var result = partition(_listeners, function (listener) {
          return listener.name === id;
        });
        _listeners = result.fail;
        each$7(result.pass, function (listener) {
          listener.callback();
        });
        return addOn;
      };
      var remove = function (name) {
        delete urls[name];
        delete lookup[name];
      };
      var createUrl = function (baseUrl, dep) {
        if (typeof dep === 'object') {
          return dep;
        }
        return typeof baseUrl === 'string' ? {
          prefix: '',
          resource: dep,
          suffix: ''
        } : {
          prefix: baseUrl.prefix,
          resource: dep,
          suffix: baseUrl.suffix
        };
      };
      var addComponents = function (pluginName, scripts) {
        var pluginUrl = _this.urls[pluginName];
        each$7(scripts, function (script) {
          ScriptLoader.ScriptLoader.add(pluginUrl + '/' + script);
        });
      };
      var loadDependencies = function (name, addOnUrl, success, scope) {
        var deps = dependencies(name);
        each$7(deps, function (dep) {
          var newUrl = createUrl(addOnUrl, dep);
          load(newUrl.resource, newUrl, undefined, undefined);
        });
        if (success) {
          if (scope) {
            success.call(scope);
          } else {
            success.call(ScriptLoader);
          }
        }
      };
      var load = function (name, addOnUrl, success, scope, failure) {
        if (urls[name]) {
          return;
        }
        var urlString = typeof addOnUrl === 'string' ? addOnUrl : addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
        if (urlString.indexOf('/') !== 0 && urlString.indexOf('://') === -1) {
          urlString = AddOnManager.baseURL + '/' + urlString;
        }
        urls[name] = urlString.substring(0, urlString.lastIndexOf('/'));
        if (lookup[name]) {
          loadDependencies(name, addOnUrl, success, scope);
        } else {
          ScriptLoader.ScriptLoader.add(urlString, function () {
            return loadDependencies(name, addOnUrl, success, scope);
          }, scope, failure);
        }
      };
      var waitFor = function (name, callback) {
        if (lookup.hasOwnProperty(name)) {
          callback();
        } else {
          _listeners.push({
            name: name,
            callback: callback
          });
        }
      };
      return {
        items: items,
        urls: urls,
        lookup: lookup,
        _listeners: _listeners,
        get: get,
        dependencies: dependencies,
        requireLangPack: requireLangPack,
        add: add,
        remove: remove,
        createUrl: createUrl,
        addComponents: addComponents,
        load: load,
        waitFor: waitFor
      };
    }
    (function (AddOnManager) {
      AddOnManager.PluginManager = AddOnManager();
      AddOnManager.ThemeManager = AddOnManager();
    }(AddOnManager || (AddOnManager = {})));

    var before = function (marker, element) {
      var parent$1 = parent(marker);
      parent$1.each(function (v) {
        v.dom().insertBefore(element.dom(), marker.dom());
      });
    };
    var after = function (marker, element) {
      var sibling = nextSibling(marker);
      sibling.fold(function () {
        var parent$1 = parent(marker);
        parent$1.each(function (v) {
          append(v, element);
        });
      }, function (v) {
        before(v, element);
      });
    };
    var prepend = function (parent, element) {
      var firstChild$1 = firstChild(parent);
      firstChild$1.fold(function () {
        append(parent, element);
      }, function (v) {
        parent.dom().insertBefore(element.dom(), v.dom());
      });
    };
    var append = function (parent, element) {
      parent.dom().appendChild(element.dom());
    };
    var wrap$1 = function (element, wrapper) {
      before(element, wrapper);
      append(wrapper, element);
    };

    var before$1 = function (marker, elements) {
      each(elements, function (x) {
        before(marker, x);
      });
    };
    var append$1 = function (parent, elements) {
      each(elements, function (x) {
        append(parent, x);
      });
    };

    var empty = function (element) {
      element.dom().textContent = '';
      each(children(element), function (rogue) {
        remove$1(rogue);
      });
    };
    var remove$1 = function (element) {
      var dom = element.dom();
      if (dom.parentNode !== null) {
        dom.parentNode.removeChild(dom);
      }
    };
    var unwrap = function (wrapper) {
      var children$1 = children(wrapper);
      if (children$1.length > 0) {
        before$1(wrapper, children$1);
      }
      remove$1(wrapper);
    };

    var first = function (fn, rate) {
      var timer = null;
      var cancel = function () {
        if (timer !== null) {
          domGlobals.clearTimeout(timer);
          timer = null;
        }
      };
      var throttle = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        if (timer === null) {
          timer = domGlobals.setTimeout(function () {
            fn.apply(null, args);
            timer = null;
          }, rate);
        }
      };
      return {
        cancel: cancel,
        throttle: throttle
      };
    };
    var last$2 = function (fn, rate) {
      var timer = null;
      var cancel = function () {
        if (timer !== null) {
          domGlobals.clearTimeout(timer);
          timer = null;
        }
      };
      var throttle = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        if (timer !== null) {
          domGlobals.clearTimeout(timer);
        }
        timer = domGlobals.setTimeout(function () {
          fn.apply(null, args);
          timer = null;
        }, rate);
      };
      return {
        cancel: cancel,
        throttle: throttle
      };
    };

    var Cell = function (initial) {
      var value = initial;
      var get = function () {
        return value;
      };
      var set = function (v) {
        value = v;
      };
      var clone = function () {
        return Cell(get());
      };
      return {
        get: get,
        set: set,
        clone: clone
      };
    };

    var read = function (element, attr) {
      var value = get(element, attr);
      return value === undefined || value === '' ? [] : value.split(' ');
    };
    var add = function (element, attr, id) {
      var old = read(element, attr);
      var nu = old.concat([id]);
      set(element, attr, nu.join(' '));
      return true;
    };
    var remove$2 = function (element, attr, id) {
      var nu = filter(read(element, attr), function (v) {
        return v !== id;
      });
      if (nu.length > 0) {
        set(element, attr, nu.join(' '));
      } else {
        remove(element, attr);
      }
      return false;
    };

    var supports = function (element) {
      return element.dom().classList !== undefined;
    };
    var get$2 = function (element) {
      return read(element, 'class');
    };
    var add$1 = function (element, clazz) {
      return add(element, 'class', clazz);
    };
    var remove$3 = function (element, clazz) {
      return remove$2(element, 'class', clazz);
    };

    var add$2 = function (element, clazz) {
      if (supports(element)) {
        element.dom().classList.add(clazz);
      } else {
        add$1(element, clazz);
      }
    };
    var cleanClass = function (element) {
      var classList = supports(element) ? element.dom().classList : get$2(element);
      if (classList.length === 0) {
        remove(element, 'class');
      }
    };
    var remove$4 = function (element, clazz) {
      if (supports(element)) {
        var classList = element.dom().classList;
        classList.remove(clazz);
      } else {
        remove$3(element, clazz);
      }
      cleanClass(element);
    };
    var has$2 = function (element, clazz) {
      return supports(element) && element.dom().classList.contains(clazz);
    };

    var descendants = function (scope, predicate) {
      var result = [];
      each(children(scope), function (x) {
        if (predicate(x)) {
          result = result.concat([x]);
        }
        result = result.concat(descendants(x, predicate));
      });
      return result;
    };

    var descendants$1 = function (scope, selector) {
      return all(selector, scope);
    };

    function ClosestOrAncestor (is, ancestor, scope, a, isRoot) {
      return is(scope, a) ? Option.some(scope) : isFunction(isRoot) && isRoot(scope) ? Option.none() : ancestor(scope, a, isRoot);
    }

    var ancestor = function (scope, predicate, isRoot) {
      var element = scope.dom();
      var stop = isFunction(isRoot) ? isRoot : constant(false);
      while (element.parentNode) {
        element = element.parentNode;
        var el = Element.fromDom(element);
        if (predicate(el)) {
          return Option.some(el);
        } else if (stop(el)) {
          break;
        }
      }
      return Option.none();
    };
    var closest = function (scope, predicate, isRoot) {
      var is = function (s, test) {
        return test(s);
      };
      return ClosestOrAncestor(is, ancestor, scope, predicate, isRoot);
    };

    var ancestor$1 = function (scope, selector, isRoot) {
      return ancestor(scope, function (e) {
        return is$1(e, selector);
      }, isRoot);
    };
    var descendant = function (scope, selector) {
      return one(selector, scope);
    };
    var closest$1 = function (scope, selector, isRoot) {
      return ClosestOrAncestor(is$1, ancestor$1, scope, selector, isRoot);
    };

    var annotation = constant('mce-annotation');
    var dataAnnotation = constant('data-mce-annotation');
    var dataAnnotationId = constant('data-mce-annotation-uid');

    var identify = function (editor, annotationName) {
      var rng = editor.selection.getRng();
      var start = Element.fromDom(rng.startContainer);
      var root = Element.fromDom(editor.getBody());
      var selector = annotationName.fold(function () {
        return '.' + annotation();
      }, function (an) {
        return '[' + dataAnnotation() + '="' + an + '"]';
      });
      var newStart = child(start, rng.startOffset).getOr(start);
      var closest = closest$1(newStart, selector, function (n) {
        return eq(n, root);
      });
      var getAttr = function (c, property) {
        if (has$1(c, property)) {
          return Option.some(get(c, property));
        } else {
          return Option.none();
        }
      };
      return closest.bind(function (c) {
        return getAttr(c, '' + dataAnnotationId()).bind(function (uid) {
          return getAttr(c, '' + dataAnnotation()).map(function (name) {
            var elements = findMarkers(editor, uid);
            return {
              uid: uid,
              name: name,
              elements: elements
            };
          });
        });
      });
    };
    var isAnnotation = function (elem) {
      return isElement(elem) && has$2(elem, annotation());
    };
    var findMarkers = function (editor, uid) {
      var body = Element.fromDom(editor.getBody());
      return descendants$1(body, '[' + dataAnnotationId() + '="' + uid + '"]');
    };
    var findAll = function (editor, name) {
      var body = Element.fromDom(editor.getBody());
      var markers = descendants$1(body, '[' + dataAnnotation() + '="' + name + '"]');
      var directory = {};
      each(markers, function (m) {
        var uid = get(m, dataAnnotationId());
        var nodesAlready = directory.hasOwnProperty(uid) ? directory[uid] : [];
        directory[uid] = nodesAlready.concat([m]);
      });
      return directory;
    };

    var setup = function (editor, registry) {
      var changeCallbacks = Cell({});
      var initData = function () {
        return {
          listeners: [],
          previous: Cell(Option.none())
        };
      };
      var withCallbacks = function (name, f) {
        updateCallbacks(name, function (data) {
          f(data);
          return data;
        });
      };
      var updateCallbacks = function (name, f) {
        var callbackMap = changeCallbacks.get();
        var data = callbackMap.hasOwnProperty(name) ? callbackMap[name] : initData();
        var outputData = f(data);
        callbackMap[name] = outputData;
        changeCallbacks.set(callbackMap);
      };
      var fireCallbacks = function (name, uid, elements) {
        withCallbacks(name, function (data) {
          each(data.listeners, function (f) {
            return f(true, name, {
              uid: uid,
              nodes: map(elements, function (elem) {
                return elem.dom();
              })
            });
          });
        });
      };
      var fireNoAnnotation = function (name) {
        withCallbacks(name, function (data) {
          each(data.listeners, function (f) {
            return f(false, name);
          });
        });
      };
      var onNodeChange = last$2(function () {
        var callbackMap = changeCallbacks.get();
        var annotations = sort(keys(callbackMap));
        each(annotations, function (name) {
          updateCallbacks(name, function (data) {
            var prev = data.previous.get();
            identify(editor, Option.some(name)).fold(function () {
              if (prev.isSome()) {
                fireNoAnnotation(name);
                data.previous.set(Option.none());
              }
            }, function (_a) {
              var uid = _a.uid, name = _a.name, elements = _a.elements;
              if (!prev.is(uid)) {
                fireCallbacks(name, uid, elements);
                data.previous.set(Option.some(uid));
              }
            });
            return {
              previous: data.previous,
              listeners: data.listeners
            };
          });
        });
      }, 30);
      editor.on('remove', function () {
        onNodeChange.cancel();
      });
      editor.on('nodeChange', function () {
        onNodeChange.throttle();
      });
      var addListener = function (name, f) {
        updateCallbacks(name, function (data) {
          return {
            previous: data.previous,
            listeners: data.listeners.concat([f])
          };
        });
      };
      return { addListener: addListener };
    };

    var setup$1 = function (editor, registry) {
      var identifyParserNode = function (span) {
        var optAnnotation = Option.from(span.attributes.map[dataAnnotation()]);
        return optAnnotation.bind(registry.lookup);
      };
      editor.on('init', function () {
        editor.serializer.addNodeFilter('span', function (spans) {
          each(spans, function (span) {
            identifyParserNode(span).each(function (settings) {
              if (settings.persistent === false) {
                span.unwrap();
              }
            });
          });
        });
      });
    };

    var create$1 = function () {
      var annotations = {};
      var register = function (name, settings) {
        annotations[name] = {
          name: name,
          settings: settings
        };
      };
      var lookup = function (name) {
        return annotations.hasOwnProperty(name) ? Option.from(annotations[name]).map(function (a) {
          return a.settings;
        }) : Option.none();
      };
      return {
        register: register,
        lookup: lookup
      };
    };

    var __assign = function () {
      __assign = Object.assign || function __assign(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
          s = arguments[i];
          for (var p in s)
            if (Object.prototype.hasOwnProperty.call(s, p))
              t[p] = s[p];
        }
        return t;
      };
      return __assign.apply(this, arguments);
    };
    function __rest(s, e) {
      var t = {};
      for (var p in s)
        if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
          t[p] = s[p];
      if (s != null && typeof Object.getOwnPropertySymbols === 'function')
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
          if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
            t[p[i]] = s[p[i]];
        }
      return t;
    }
    function __spreadArrays() {
      for (var s = 0, i = 0, il = arguments.length; i < il; i++)
        s += arguments[i].length;
      for (var r = Array(s), k = 0, i = 0; i < il; i++)
        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
          r[k] = a[j];
      return r;
    }

    var unique = 0;
    var generate = function (prefix) {
      var date = new Date();
      var time = date.getTime();
      var random = Math.floor(Math.random() * 1000000000);
      unique++;
      return prefix + '_' + random + unique + String(time);
    };

    var add$3 = function (element, classes) {
      each(classes, function (x) {
        add$2(element, x);
      });
    };

    var clone = function (original, isDeep) {
      return Element.fromDom(original.dom().cloneNode(isDeep));
    };
    var shallow = function (original) {
      return clone(original, false);
    };
    var deep = function (original) {
      return clone(original, true);
    };

    var fromHtml$1 = function (html, scope) {
      var doc = scope || domGlobals.document;
      var div = doc.createElement('div');
      div.innerHTML = html;
      return children(Element.fromDom(div));
    };

    var get$3 = function (element) {
      return element.dom().innerHTML;
    };
    var set$1 = function (element, content) {
      var owner$1 = owner(element);
      var docDom = owner$1.dom();
      var fragment = Element.fromDom(docDom.createDocumentFragment());
      var contentElements = fromHtml$1(content, docDom);
      append$1(fragment, contentElements);
      empty(element);
      append(element, fragment);
    };

    var ZWSP = '\uFEFF';
    var isZwsp = function (chr) {
      return chr === ZWSP;
    };
    var trim$3 = function (text) {
      return text.replace(new RegExp(ZWSP, 'g'), '');
    };
    var Zwsp = {
      isZwsp: isZwsp,
      ZWSP: ZWSP,
      trim: trim$3
    };

    var isElement$2 = NodeType.isElement;
    var isText$2 = NodeType.isText;
    var isCaretContainerBlock = function (node) {
      if (isText$2(node)) {
        node = node.parentNode;
      }
      return isElement$2(node) && node.hasAttribute('data-mce-caret');
    };
    var isCaretContainerInline = function (node) {
      return isText$2(node) && Zwsp.isZwsp(node.data);
    };
    var isCaretContainer = function (node) {
      return isCaretContainerBlock(node) || isCaretContainerInline(node);
    };
    var hasContent = function (node) {
      return node.firstChild !== node.lastChild || !NodeType.isBr(node.firstChild);
    };
    var insertInline = function (node, before) {
      var doc, sibling, textNode, parentNode;
      doc = node.ownerDocument;
      textNode = doc.createTextNode(Zwsp.ZWSP);
      parentNode = node.parentNode;
      if (!before) {
        sibling = node.nextSibling;
        if (isText$2(sibling)) {
          if (isCaretContainer(sibling)) {
            return sibling;
          }
          if (startsWithCaretContainer(sibling)) {
            sibling.splitText(1);
            return sibling;
          }
        }
        if (node.nextSibling) {
          parentNode.insertBefore(textNode, node.nextSibling);
        } else {
          parentNode.appendChild(textNode);
        }
      } else {
        sibling = node.previousSibling;
        if (isText$2(sibling)) {
          if (isCaretContainer(sibling)) {
            return sibling;
          }
          if (endsWithCaretContainer(sibling)) {
            return sibling.splitText(sibling.data.length - 1);
          }
        }
        parentNode.insertBefore(textNode, node);
      }
      return textNode;
    };
    var isBeforeInline = function (pos) {
      var container = pos.container();
      if (!pos || !NodeType.isText(container)) {
        return false;
      }
      return container.data.charAt(pos.offset()) === Zwsp.ZWSP || pos.isAtStart() && isCaretContainerInline(container.previousSibling);
    };
    var isAfterInline = function (pos) {
      var container = pos.container();
      if (!pos || !NodeType.isText(container)) {
        return false;
      }
      return container.data.charAt(pos.offset() - 1) === Zwsp.ZWSP || pos.isAtEnd() && isCaretContainerInline(container.nextSibling);
    };
    var createBogusBr = function () {
      var br = domGlobals.document.createElement('br');
      br.setAttribute('data-mce-bogus', '1');
      return br;
    };
    var insertBlock = function (blockName, node, before) {
      var doc, blockNode, parentNode;
      doc = node.ownerDocument;
      blockNode = doc.createElement(blockName);
      blockNode.setAttribute('data-mce-caret', before ? 'before' : 'after');
      blockNode.setAttribute('data-mce-bogus', 'all');
      blockNode.appendChild(createBogusBr());
      parentNode = node.parentNode;
      if (!before) {
        if (node.nextSibling) {
          parentNode.insertBefore(blockNode, node.nextSibling);
        } else {
          parentNode.appendChild(blockNode);
        }
      } else {
        parentNode.insertBefore(blockNode, node);
      }
      return blockNode;
    };
    var startsWithCaretContainer = function (node) {
      return isText$2(node) && node.data[0] === Zwsp.ZWSP;
    };
    var endsWithCaretContainer = function (node) {
      return isText$2(node) && node.data[node.data.length - 1] === Zwsp.ZWSP;
    };
    var trimBogusBr = function (elm) {
      var brs = elm.getElementsByTagName('br');
      var lastBr = brs[brs.length - 1];
      if (NodeType.isBogus(lastBr)) {
        lastBr.parentNode.removeChild(lastBr);
      }
    };
    var showCaretContainerBlock = function (caretContainer) {
      if (caretContainer && caretContainer.hasAttribute('data-mce-caret')) {
        trimBogusBr(caretContainer);
        caretContainer.removeAttribute('data-mce-caret');
        caretContainer.removeAttribute('data-mce-bogus');
        caretContainer.removeAttribute('style');
        caretContainer.removeAttribute('_moz_abspos');
        return caretContainer;
      }
      return null;
    };
    var isRangeInCaretContainerBlock = function (range) {
      return isCaretContainerBlock(range.startContainer);
    };

    var isContentEditableTrue$1 = NodeType.isContentEditableTrue;
    var isContentEditableFalse$1 = NodeType.isContentEditableFalse;
    var isBr$2 = NodeType.isBr;
    var isText$3 = NodeType.isText;
    var isInvalidTextElement = NodeType.matchNodeNames('script style textarea');
    var isAtomicInline = NodeType.matchNodeNames('img input textarea hr iframe video audio object');
    var isTable$1 = NodeType.matchNodeNames('table');
    var isCaretContainer$1 = isCaretContainer;
    var isCaretCandidate = function (node) {
      if (isCaretContainer$1(node)) {
        return false;
      }
      if (isText$3(node)) {
        if (isInvalidTextElement(node.parentNode)) {
          return false;
        }
        return true;
      }
      return isAtomicInline(node) || isBr$2(node) || isTable$1(node) || isNonUiContentEditableFalse(node);
    };
    var isUnselectable = function (node) {
      return NodeType.isElement(node) && node.getAttribute('unselectable') === 'true';
    };
    var isNonUiContentEditableFalse = function (node) {
      return isUnselectable(node) === false && isContentEditableFalse$1(node);
    };
    var isInEditable = function (node, root) {
      for (node = node.parentNode; node && node !== root; node = node.parentNode) {
        if (isNonUiContentEditableFalse(node)) {
          return false;
        }
        if (isContentEditableTrue$1(node)) {
          return true;
        }
      }
      return true;
    };
    var isAtomicContentEditableFalse = function (node) {
      if (!isNonUiContentEditableFalse(node)) {
        return false;
      }
      return foldl(from$1(node.getElementsByTagName('*')), function (result, elm) {
        return result || isContentEditableTrue$1(elm);
      }, false) !== true;
    };
    var isAtomic = function (node) {
      return isAtomicInline(node) || isAtomicContentEditableFalse(node);
    };
    var isEditableCaretCandidate = function (node, root) {
      return isCaretCandidate(node) && isInEditable(node, root);
    };

    var round = Math.round;
    var clone$1 = function (rect) {
      if (!rect) {
        return {
          left: 0,
          top: 0,
          bottom: 0,
          right: 0,
          width: 0,
          height: 0
        };
      }
      return {
        left: round(rect.left),
        top: round(rect.top),
        bottom: round(rect.bottom),
        right: round(rect.right),
        width: round(rect.width),
        height: round(rect.height)
      };
    };
    var collapse = function (rect, toStart) {
      rect = clone$1(rect);
      if (toStart) {
        rect.right = rect.left;
      } else {
        rect.left = rect.left + rect.width;
        rect.right = rect.left;
      }
      rect.width = 0;
      return rect;
    };
    var isEqual = function (rect1, rect2) {
      return rect1.left === rect2.left && rect1.top === rect2.top && rect1.bottom === rect2.bottom && rect1.right === rect2.right;
    };
    var isValidOverflow = function (overflowY, rect1, rect2) {
      return overflowY >= 0 && overflowY <= Math.min(rect1.height, rect2.height) / 2;
    };
    var isAbove = function (rect1, rect2) {
      var halfHeight = Math.min(rect2.height / 2, rect1.height / 2);
      if (rect1.bottom - halfHeight < rect2.top) {
        return true;
      }
      if (rect1.top > rect2.bottom) {
        return false;
      }
      return isValidOverflow(rect2.top - rect1.bottom, rect1, rect2);
    };
    var isBelow = function (rect1, rect2) {
      if (rect1.top > rect2.bottom) {
        return true;
      }
      if (rect1.bottom < rect2.top) {
        return false;
      }
      return isValidOverflow(rect2.bottom - rect1.top, rect1, rect2);
    };
    var containsXY = function (rect, clientX, clientY) {
      return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
    };
    var overflowX = function (outer, inner) {
      if (inner.left > outer.left && inner.right < outer.right) {
        return 0;
      } else {
        return inner.left < outer.left ? inner.left - outer.left : inner.right - outer.right;
      }
    };
    var overflowY = function (outer, inner) {
      if (inner.top > outer.top && inner.bottom < outer.bottom) {
        return 0;
      } else {
        return inner.top < outer.top ? inner.top - outer.top : inner.bottom - outer.bottom;
      }
    };
    var getOverflow = function (outer, inner) {
      return {
        x: overflowX(outer, inner),
        y: overflowY(outer, inner)
      };
    };

    var getSelectedNode = function (range) {
      var startContainer = range.startContainer, startOffset = range.startOffset;
      if (startContainer.hasChildNodes() && range.endOffset === startOffset + 1) {
        return startContainer.childNodes[startOffset];
      }
      return null;
    };
    var getNode = function (container, offset) {
      if (container.nodeType === 1 && container.hasChildNodes()) {
        if (offset >= container.childNodes.length) {
          offset = container.childNodes.length - 1;
        }
        container = container.childNodes[offset];
      }
      return container;
    };

    var extendingChars = new RegExp('[\u0300-\u036f\u0483-\u0487\u0488-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a' + '\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0' + '\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0902\u093a\u093c' + '\u0941-\u0948\u094d\u0951-\u0957\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\u0c00\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56' + '\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d01\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\u0f8d-\u0f97' + '\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074' + '\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5' + '\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18' + '\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1ABE\u1b00-\u1b03\u1b34' + '\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9' + '\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9' + '\u1dc0-\u1df5\u1dfc-\u1dff\u200c-\u200d\u20d0-\u20dc\u20DD-\u20E0\u20e1\u20E2-\u20E4\u20e5-\u20f0\u2cef-\u2cf1' + '\u2d7f\u2de0-\u2dff\u302a-\u302d\u302e-\u302f\u3099-\u309a\ua66f\uA670-\uA672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1' + '\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc' + '\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1' + '\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f]');
    var isExtendingChar = function (ch) {
      return typeof ch === 'string' && ch.charCodeAt(0) >= 768 && extendingChars.test(ch);
    };

    var lift2 = function (oa, ob, f) {
      return oa.isSome() && ob.isSome() ? Option.some(f(oa.getOrDie(), ob.getOrDie())) : Option.none();
    };
    var lift3 = function (oa, ob, oc, f) {
      return oa.isSome() && ob.isSome() && oc.isSome() ? Option.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie())) : Option.none();
    };

    var slice$2 = [].slice;
    var or = function () {
      var x = [];
      for (var _i = 0; _i < arguments.length; _i++) {
        x[_i] = arguments[_i];
      }
      var args = slice$2.call(arguments);
      return function (x) {
        for (var i = 0; i < args.length; i++) {
          if (args[i](x)) {
            return true;
          }
        }
        return false;
      };
    };
    var and = function () {
      var x = [];
      for (var _i = 0; _i < arguments.length; _i++) {
        x[_i] = arguments[_i];
      }
      var args = slice$2.call(arguments);
      return function (x) {
        for (var i = 0; i < args.length; i++) {
          if (!args[i](x)) {
            return false;
          }
        }
        return true;
      };
    };
    var Predicate = {
      and: and,
      or: or
    };

    var isElement$3 = NodeType.isElement;
    var isCaretCandidate$1 = isCaretCandidate;
    var isBlock$1 = NodeType.matchStyleValues('display', 'block table');
    var isFloated = NodeType.matchStyleValues('float', 'left right');
    var isValidElementCaretCandidate = Predicate.and(isElement$3, isCaretCandidate$1, not(isFloated));
    var isNotPre = not(NodeType.matchStyleValues('white-space', 'pre pre-line pre-wrap'));
    var isText$4 = NodeType.isText;
    var isBr$3 = NodeType.isBr;
    var nodeIndex = DOMUtils$1.nodeIndex;
    var resolveIndex = getNode;
    var createRange = function (doc) {
      return 'createRange' in doc ? doc.createRange() : DOMUtils$1.DOM.createRng();
    };
    var isWhiteSpace = function (chr) {
      return chr && /[\r\n\t ]/.test(chr);
    };
    var isRange = function (rng) {
      return !!rng.setStart && !!rng.setEnd;
    };
    var isHiddenWhiteSpaceRange = function (range) {
      var container = range.startContainer;
      var offset = range.startOffset;
      var text;
      if (isWhiteSpace(range.toString()) && isNotPre(container.parentNode) && NodeType.isText(container)) {
        text = container.data;
        if (isWhiteSpace(text[offset - 1]) || isWhiteSpace(text[offset + 1])) {
          return true;
        }
      }
      return false;
    };
    var getBrClientRect = function (brNode) {
      var doc = brNode.ownerDocument;
      var rng = createRange(doc);
      var nbsp = doc.createTextNode('\xA0');
      var parentNode = brNode.parentNode;
      var clientRect;
      parentNode.insertBefore(nbsp, brNode);
      rng.setStart(nbsp, 0);
      rng.setEnd(nbsp, 1);
      clientRect = clone$1(rng.getBoundingClientRect());
      parentNode.removeChild(nbsp);
      return clientRect;
    };
    var getBoundingClientRectWebKitText = function (rng) {
      var sc = rng.startContainer;
      var ec = rng.endContainer;
      var so = rng.startOffset;
      var eo = rng.endOffset;
      if (sc === ec && NodeType.isText(ec) && so === 0 && eo === 1) {
        var newRng = rng.cloneRange();
        newRng.setEndAfter(ec);
        return getBoundingClientRect(newRng);
      } else {
        return null;
      }
    };
    var isZeroRect = function (r) {
      return r.left === 0 && r.right === 0 && r.top === 0 && r.bottom === 0;
    };
    var getBoundingClientRect = function (item) {
      var clientRect, clientRects;
      clientRects = item.getClientRects();
      if (clientRects.length > 0) {
        clientRect = clone$1(clientRects[0]);
      } else {
        clientRect = clone$1(item.getBoundingClientRect());
      }
      if (!isRange(item) && isBr$3(item) && isZeroRect(clientRect)) {
        return getBrClientRect(item);
      }
      if (isZeroRect(clientRect) && isRange(item)) {
        return getBoundingClientRectWebKitText(item);
      }
      return clientRect;
    };
    var collapseAndInflateWidth = function (clientRect, toStart) {
      var newClientRect = collapse(clientRect, toStart);
      newClientRect.width = 1;
      newClientRect.right = newClientRect.left + 1;
      return newClientRect;
    };
    var getCaretPositionClientRects = function (caretPosition) {
      var clientRects = [];
      var beforeNode, node;
      var addUniqueAndValidRect = function (clientRect) {
        if (clientRect.height === 0) {
          return;
        }
        if (clientRects.length > 0) {
          if (isEqual(clientRect, clientRects[clientRects.length - 1])) {
            return;
          }
        }
        clientRects.push(clientRect);
      };
      var addCharacterOffset = function (container, offset) {
        var range = createRange(container.ownerDocument);
        if (offset < container.data.length) {
          if (isExtendingChar(container.data[offset])) {
            return clientRects;
          }
          if (isExtendingChar(container.data[offset - 1])) {
            range.setStart(container, offset);
            range.setEnd(container, offset + 1);
            if (!isHiddenWhiteSpaceRange(range)) {
              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false));
              return clientRects;
            }
          }
        }
        if (offset > 0) {
          range.setStart(container, offset - 1);
          range.setEnd(container, offset);
          if (!isHiddenWhiteSpaceRange(range)) {
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false));
          }
        }
        if (offset < container.data.length) {
          range.setStart(container, offset);
          range.setEnd(container, offset + 1);
          if (!isHiddenWhiteSpaceRange(range)) {
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), true));
          }
        }
      };
      if (isText$4(caretPosition.container())) {
        addCharacterOffset(caretPosition.container(), caretPosition.offset());
        return clientRects;
      }
      if (isElement$3(caretPosition.container())) {
        if (caretPosition.isAtEnd()) {
          node = resolveIndex(caretPosition.container(), caretPosition.offset());
          if (isText$4(node)) {
            addCharacterOffset(node, node.data.length);
          }
          if (isValidElementCaretCandidate(node) && !isBr$3(node)) {
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false));
          }
        } else {
          node = resolveIndex(caretPosition.container(), caretPosition.offset());
          if (isText$4(node)) {
            addCharacterOffset(node, 0);
          }
          if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) {
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false));
            return clientRects;
          }
          beforeNode = resolveIndex(caretPosition.container(), caretPosition.offset() - 1);
          if (isValidElementCaretCandidate(beforeNode) && !isBr$3(beforeNode)) {
            if (isBlock$1(beforeNode) || isBlock$1(node) || !isValidElementCaretCandidate(node)) {
              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(beforeNode), false));
            }
          }
          if (isValidElementCaretCandidate(node)) {
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), true));
          }
        }
      }
      return clientRects;
    };
    function CaretPosition(container, offset, clientRects) {
      var isAtStart = function () {
        if (isText$4(container)) {
          return offset === 0;
        }
        return offset === 0;
      };
      var isAtEnd = function () {
        if (isText$4(container)) {
          return offset >= container.data.length;
        }
        return offset >= container.childNodes.length;
      };
      var toRange = function () {
        var range;
        range = createRange(container.ownerDocument);
        range.setStart(container, offset);
        range.setEnd(container, offset);
        return range;
      };
      var getClientRects = function () {
        if (!clientRects) {
          clientRects = getCaretPositionClientRects(CaretPosition(container, offset));
        }
        return clientRects;
      };
      var isVisible = function () {
        return getClientRects().length > 0;
      };
      var isEqual = function (caretPosition) {
        return caretPosition && container === caretPosition.container() && offset === caretPosition.offset();
      };
      var getNode = function (before) {
        return resolveIndex(container, before ? offset - 1 : offset);
      };
      return {
        container: constant(container),
        offset: constant(offset),
        toRange: toRange,
        getClientRects: getClientRects,
        isVisible: isVisible,
        isAtStart: isAtStart,
        isAtEnd: isAtEnd,
        isEqual: isEqual,
        getNode: getNode
      };
    }
    (function (CaretPosition) {
      CaretPosition.fromRangeStart = function (range) {
        return CaretPosition(range.startContainer, range.startOffset);
      };
      CaretPosition.fromRangeEnd = function (range) {
        return CaretPosition(range.endContainer, range.endOffset);
      };
      CaretPosition.after = function (node) {
        return CaretPosition(node.parentNode, nodeIndex(node) + 1);
      };
      CaretPosition.before = function (node) {
        return CaretPosition(node.parentNode, nodeIndex(node));
      };
      CaretPosition.isAbove = function (pos1, pos2) {
        return lift2(head(pos2.getClientRects()), last(pos1.getClientRects()), isAbove).getOr(false);
      };
      CaretPosition.isBelow = function (pos1, pos2) {
        return lift2(last(pos2.getClientRects()), head(pos1.getClientRects()), isBelow).getOr(false);
      };
      CaretPosition.isAtStart = function (pos) {
        return pos ? pos.isAtStart() : false;
      };
      CaretPosition.isAtEnd = function (pos) {
        return pos ? pos.isAtEnd() : false;
      };
      CaretPosition.isTextPosition = function (pos) {
        return pos ? NodeType.isText(pos.container()) : false;
      };
      CaretPosition.isElementPosition = function (pos) {
        return CaretPosition.isTextPosition(pos) === false;
      };
    }(CaretPosition || (CaretPosition = {})));
    var CaretPosition$1 = CaretPosition;

    var isText$5 = NodeType.isText;
    var isBogus$1 = NodeType.isBogus;
    var nodeIndex$1 = DOMUtils$1.nodeIndex;
    var normalizedParent = function (node) {
      var parentNode = node.parentNode;
      if (isBogus$1(parentNode)) {
        return normalizedParent(parentNode);
      }
      return parentNode;
    };
    var getChildNodes = function (node) {
      if (!node) {
        return [];
      }
      return ArrUtils.reduce(node.childNodes, function (result, node) {
        if (isBogus$1(node) && node.nodeName !== 'BR') {
          result = result.concat(getChildNodes(node));
        } else {
          result.push(node);
        }
        return result;
      }, []);
    };
    var normalizedTextOffset = function (node, offset) {
      while (node = node.previousSibling) {
        if (!isText$5(node)) {
          break;
        }
        offset += node.data.length;
      }
      return offset;
    };
    var equal = function (a) {
      return function (b) {
        return a === b;
      };
    };
    var normalizedNodeIndex = function (node) {
      var nodes, index, numTextFragments;
      nodes = getChildNodes(normalizedParent(node));
      index = ArrUtils.findIndex(nodes, equal(node), node);
      nodes = nodes.slice(0, index + 1);
      numTextFragments = ArrUtils.reduce(nodes, function (result, node, i) {
        if (isText$5(node) && isText$5(nodes[i - 1])) {
          result++;
        }
        return result;
      }, 0);
      nodes = ArrUtils.filter(nodes, NodeType.matchNodeNames(node.nodeName));
      index = ArrUtils.findIndex(nodes, equal(node), node);
      return index - numTextFragments;
    };
    var createPathItem = function (node) {
      var name;
      if (isText$5(node)) {
        name = 'text()';
      } else {
        name = node.nodeName.toLowerCase();
      }
      return name + '[' + normalizedNodeIndex(node) + ']';
    };
    var parentsUntil = function (root, node, predicate) {
      var parents = [];
      for (node = node.parentNode; node !== root; node = node.parentNode) {
        if (predicate && predicate(node)) {
          break;
        }
        parents.push(node);
      }
      return parents;
    };
    var create$2 = function (root, caretPosition) {
      var container, offset, path = [], outputOffset, childNodes, parents;
      container = caretPosition.container();
      offset = caretPosition.offset();
      if (isText$5(container)) {
        outputOffset = normalizedTextOffset(container, offset);
      } else {
        childNodes = container.childNodes;
        if (offset >= childNodes.length) {
          outputOffset = 'after';
          offset = childNodes.length - 1;
        } else {
          outputOffset = 'before';
        }
        container = childNodes[offset];
      }
      path.push(createPathItem(container));
      parents = parentsUntil(root, container);
      parents = ArrUtils.filter(parents, not(NodeType.isBogus));
      path = path.concat(ArrUtils.map(parents, function (node) {
        return createPathItem(node);
      }));
      return path.reverse().join('/') + ',' + outputOffset;
    };
    var resolvePathItem = function (node, name, index) {
      var nodes = getChildNodes(node);
      nodes = ArrUtils.filter(nodes, function (node, index) {
        return !isText$5(node) || !isText$5(nodes[index - 1]);
      });
      nodes = ArrUtils.filter(nodes, NodeType.matchNodeNames(name));
      return nodes[index];
    };
    var findTextPosition = function (container, offset) {
      var node = container, targetOffset = 0, dataLen;
      while (isText$5(node)) {
        dataLen = node.data.length;
        if (offset >= targetOffset && offset <= targetOffset + dataLen) {
          container = node;
          offset = offset - targetOffset;
          break;
        }
        if (!isText$5(node.nextSibling)) {
          container = node;
          offset = dataLen;
          break;
        }
        targetOffset += dataLen;
        node = node.nextSibling;
      }
      if (isText$5(container) && offset > container.data.length) {
        offset = container.data.length;
      }
      return CaretPosition$1(container, offset);
    };
    var resolve$2 = function (root, path) {
      var parts, container, offset;
      if (!path) {
        return null;
      }
      parts = path.split(',');
      path = parts[0].split('/');
      offset = parts.length > 1 ? parts[1] : 'before';
      container = ArrUtils.reduce(path, function (result, value) {
        value = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value);
        if (!value) {
          return null;
        }
        if (value[1] === 'text()') {
          value[1] = '#text';
        }
        return resolvePathItem(result, value[1], parseInt(value[2], 10));
      }, root);
      if (!container) {
        return null;
      }
      if (!isText$5(container)) {
        if (offset === 'after') {
          offset = nodeIndex$1(container) + 1;
        } else {
          offset = nodeIndex$1(container);
        }
        return CaretPosition$1(container.parentNode, offset);
      }
      return findTextPosition(container, parseInt(offset, 10));
    };

    var trimEmptyTextNode = function (dom, node) {
      if (NodeType.isText(node) && node.data.length === 0) {
        dom.remove(node);
      }
    };
    var insertNode = function (dom, rng, node) {
      rng.insertNode(node);
      trimEmptyTextNode(dom, node.previousSibling);
      trimEmptyTextNode(dom, node.nextSibling);
    };
    var insertFragment = function (dom, rng, frag) {
      var firstChild = Option.from(frag.firstChild);
      var lastChild = Option.from(frag.lastChild);
      rng.insertNode(frag);
      firstChild.each(function (child) {
        return trimEmptyTextNode(dom, child.previousSibling);
      });
      lastChild.each(function (child) {
        return trimEmptyTextNode(dom, child.nextSibling);
      });
    };
    var rangeInsertNode = function (dom, rng, node) {
      if (NodeType.isDocumentFragment(node)) {
        insertFragment(dom, rng, node);
      } else {
        insertNode(dom, rng, node);
      }
    };

    var isContentEditableFalse$2 = NodeType.isContentEditableFalse;
    var getNormalizedTextOffset = function (trim, container, offset) {
      var node, trimmedOffset;
      trimmedOffset = trim(container.data.slice(0, offset)).length;
      for (node = container.previousSibling; node && NodeType.isText(node); node = node.previousSibling) {
        trimmedOffset += trim(node.data).length;
      }
      return trimmedOffset;
    };
    var getPoint = function (dom, trim, normalized, rng, start) {
      var container = rng[start ? 'startContainer' : 'endContainer'];
      var offset = rng[start ? 'startOffset' : 'endOffset'];
      var point = [];
      var childNodes, after = 0;
      var root = dom.getRoot();
      if (NodeType.isText(container)) {
        point.push(normalized ? getNormalizedTextOffset(trim, container, offset) : offset);
      } else {
        childNodes = container.childNodes;
        if (offset >= childNodes.length && childNodes.length) {
          after = 1;
          offset = Math.max(0, childNodes.length - 1);
        }
        point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
      }
      for (; container && container !== root; container = container.parentNode) {
        point.push(dom.nodeIndex(container, normalized));
      }
      return point;
    };
    var getLocation = function (trim, selection, normalized, rng) {
      var dom = selection.dom, bookmark = {};
      bookmark.start = getPoint(dom, trim, normalized, rng, true);
      if (!selection.isCollapsed()) {
        bookmark.end = getPoint(dom, trim, normalized, rng, false);
      }
      return bookmark;
    };
    var findIndex$2 = function (dom, name, element) {
      var count = 0;
      Tools.each(dom.select(name), function (node) {
        if (node.getAttribute('data-mce-bogus') === 'all') {
          return;
        }
        if (node === element) {
          return false;
        }
        count++;
      });
      return count;
    };
    var moveEndPoint = function (rng, start) {
      var container, offset, childNodes;
      var prefix = start ? 'start' : 'end';
      container = rng[prefix + 'Container'];
      offset = rng[prefix + 'Offset'];
      if (NodeType.isElement(container) && container.nodeName === 'TR') {
        childNodes = container.childNodes;
        container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
        if (container) {
          offset = start ? 0 : container.childNodes.length;
          rng['set' + (start ? 'Start' : 'End')](container, offset);
        }
      }
    };
    var normalizeTableCellSelection = function (rng) {
      moveEndPoint(rng, true);
      moveEndPoint(rng, false);
      return rng;
    };
    var findSibling = function (node, offset) {
      var sibling;
      if (NodeType.isElement(node)) {
        node = getNode(node, offset);
        if (isContentEditableFalse$2(node)) {
          return node;
        }
      }
      if (isCaretContainer(node)) {
        if (NodeType.isText(node) && isCaretContainerBlock(node)) {
          node = node.parentNode;
        }
        sibling = node.previousSibling;
        if (isContentEditableFalse$2(sibling)) {
          return sibling;
        }
        sibling = node.nextSibling;
        if (isContentEditableFalse$2(sibling)) {
          return sibling;
        }
      }
    };
    var findAdjacentContentEditableFalseElm = function (rng) {
      return findSibling(rng.startContainer, rng.startOffset) || findSibling(rng.endContainer, rng.endOffset);
    };
    var getOffsetBookmark = function (trim, normalized, selection) {
      var element = selection.getNode();
      var name = element ? element.nodeName : null;
      var rng = selection.getRng();
      if (isContentEditableFalse$2(element) || name === 'IMG') {
        return {
          name: name,
          index: findIndex$2(selection.dom, name, element)
        };
      }
      var sibling = findAdjacentContentEditableFalseElm(rng);
      if (sibling) {
        name = sibling.tagName;
        return {
          name: name,
          index: findIndex$2(selection.dom, name, sibling)
        };
      }
      return getLocation(trim, selection, normalized, rng);
    };
    var getCaretBookmark = function (selection) {
      var rng = selection.getRng();
      return {
        start: create$2(selection.dom.getRoot(), CaretPosition$1.fromRangeStart(rng)),
        end: create$2(selection.dom.getRoot(), CaretPosition$1.fromRangeEnd(rng))
      };
    };
    var getRangeBookmark = function (selection) {
      return { rng: selection.getRng() };
    };
    var createBookmarkSpan = function (dom, id, filled) {
      var args = {
        'data-mce-type': 'bookmark',
        'id': id,
        'style': 'overflow:hidden;line-height:0px'
      };
      return filled ? dom.create('span', args, '&#xFEFF;') : dom.create('span', args);
    };
    var getPersistentBookmark = function (selection, filled) {
      var dom = selection.dom;
      var rng = selection.getRng();
      var id = dom.uniqueId();
      var collapsed = selection.isCollapsed();
      var element = selection.getNode();
      var name = element.nodeName;
      if (name === 'IMG') {
        return {
          name: name,
          index: findIndex$2(dom, name, element)
        };
      }
      var rng2 = normalizeTableCellSelection(rng.cloneRange());
      if (!collapsed) {
        rng2.collapse(false);
        var endBookmarkNode = createBookmarkSpan(dom, id + '_end', filled);
        rangeInsertNode(dom, rng2, endBookmarkNode);
      }
      rng = normalizeTableCellSelection(rng);
      rng.collapse(true);
      var startBookmarkNode = createBookmarkSpan(dom, id + '_start', filled);
      rangeInsertNode(dom, rng, startBookmarkNode);
      selection.moveToBookmark({
        id: id,
        keep: 1
      });
      return { id: id };
    };
    var getBookmark = function (selection, type, normalized) {
      if (type === 2) {
        return getOffsetBookmark(Zwsp.trim, normalized, selection);
      } else if (type === 3) {
        return getCaretBookmark(selection);
      } else if (type) {
        return getRangeBookmark(selection);
      } else {
        return getPersistentBookmark(selection, false);
      }
    };
    var GetBookmark = {
      getBookmark: getBookmark,
      getUndoBookmark: curry(getOffsetBookmark, identity, true),
      getPersistentBookmark: getPersistentBookmark
    };

    var CARET_ID = '_mce_caret';
    var isCaretNode = function (node) {
      return NodeType.isElement(node) && node.id === CARET_ID;
    };
    var getParentCaretContainer = function (body, node) {
      while (node && node !== body) {
        if (node.id === CARET_ID) {
          return node;
        }
        node = node.parentNode;
      }
      return null;
    };

    var isElement$4 = NodeType.isElement;
    var isText$6 = NodeType.isText;
    var removeNode = function (node) {
      var parentNode = node.parentNode;
      if (parentNode) {
        parentNode.removeChild(node);
      }
    };
    var getNodeValue = function (node) {
      try {
        return node.nodeValue;
      } catch (ex) {
        return '';
      }
    };
    var setNodeValue = function (node, text) {
      if (text.length === 0) {
        removeNode(node);
      } else {
        node.nodeValue = text;
      }
    };
    var trimCount = function (text) {
      var trimmedText = Zwsp.trim(text);
      return {
        count: text.length - trimmedText.length,
        text: trimmedText
      };
    };
    var removeUnchanged = function (caretContainer, pos) {
      remove$5(caretContainer);
      return pos;
    };
    var removeTextAndReposition = function (caretContainer, pos) {
      var before = trimCount(caretContainer.data.substr(0, pos.offset()));
      var after = trimCount(caretContainer.data.substr(pos.offset()));
      var text = before.text + after.text;
      if (text.length > 0) {
        setNodeValue(caretContainer, text);
        return CaretPosition$1(caretContainer, pos.offset() - before.count);
      } else {
        return pos;
      }
    };
    var removeElementAndReposition = function (caretContainer, pos) {
      var parentNode = pos.container();
      var newPosition = indexOf(from$1(parentNode.childNodes), caretContainer).map(function (index) {
        return index < pos.offset() ? CaretPosition$1(parentNode, pos.offset() - 1) : pos;
      }).getOr(pos);
      remove$5(caretContainer);
      return newPosition;
    };
    var removeTextCaretContainer = function (caretContainer, pos) {
      return isText$6(caretContainer) && pos.container() === caretContainer ? removeTextAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
    };
    var removeElementCaretContainer = function (caretContainer, pos) {
      return pos.container() === caretContainer.parentNode ? removeElementAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
    };
    var removeAndReposition = function (container, pos) {
      return CaretPosition$1.isTextPosition(pos) ? removeTextCaretContainer(container, pos) : removeElementCaretContainer(container, pos);
    };
    var remove$5 = function (caretContainerNode) {
      if (isElement$4(caretContainerNode) && isCaretContainer(caretContainerNode)) {
        if (hasContent(caretContainerNode)) {
          caretContainerNode.removeAttribute('data-mce-caret');
        } else {
          removeNode(caretContainerNode);
        }
      }
      if (isText$6(caretContainerNode)) {
        var text = Zwsp.trim(getNodeValue(caretContainerNode));
        setNodeValue(caretContainerNode, text);
      }
    };
    var CaretContainerRemove = {
      removeAndReposition: removeAndReposition,
      remove: remove$5
    };

    var browser$2 = PlatformDetection$1.detect().browser;
    var isContentEditableFalse$3 = NodeType.isContentEditableFalse;
    var isTableCell$1 = function (node) {
      return NodeType.isElement(node) && /^(TD|TH)$/i.test(node.tagName);
    };
    var getAbsoluteClientRect = function (root, element, before) {
      var clientRect = collapse(element.getBoundingClientRect(), before);
      var docElm, scrollX, scrollY, margin, rootRect;
      if (root.tagName === 'BODY') {
        docElm = root.ownerDocument.documentElement;
        scrollX = root.scrollLeft || docElm.scrollLeft;
        scrollY = root.scrollTop || docElm.scrollTop;
      } else {
        rootRect = root.getBoundingClientRect();
        scrollX = root.scrollLeft - rootRect.left;
        scrollY = root.scrollTop - rootRect.top;
      }
      clientRect.left += scrollX;
      clientRect.right += scrollX;
      clientRect.top += scrollY;
      clientRect.bottom += scrollY;
      clientRect.width = 1;
      margin = element.offsetWidth - element.clientWidth;
      if (margin > 0) {
        if (before) {
          margin *= -1;
        }
        clientRect.left += margin;
        clientRect.right += margin;
      }
      return clientRect;
    };
    var trimInlineCaretContainers = function (root) {
      var contentEditableFalseNodes, node, sibling, i, data;
      contentEditableFalseNodes = DomQuery('*[contentEditable=false]', root);
      for (i = 0; i < contentEditableFalseNodes.length; i++) {
        node = contentEditableFalseNodes[i];
        sibling = node.previousSibling;
        if (endsWithCaretContainer(sibling)) {
          data = sibling.data;
          if (data.length === 1) {
            sibling.parentNode.removeChild(sibling);
          } else {
            sibling.deleteData(data.length - 1, 1);
          }
        }
        sibling = node.nextSibling;
        if (startsWithCaretContainer(sibling)) {
          data = sibling.data;
          if (data.length === 1) {
            sibling.parentNode.removeChild(sibling);
          } else {
            sibling.deleteData(0, 1);
          }
        }
      }
    };
    var FakeCaret = function (root, isBlock, hasFocus) {
      var lastVisualCaret = Cell(Option.none());
      var cursorInterval, caretContainerNode;
      var show = function (before, element) {
        var clientRect, rng;
        hide();
        if (isTableCell$1(element)) {
          return null;
        }
        if (isBlock(element)) {
          caretContainerNode = insertBlock('p', element, before);
          clientRect = getAbsoluteClientRect(root, element, before);
          DomQuery(caretContainerNode).css('top', clientRect.top);
          var caret = DomQuery('<div class="mce-visual-caret" data-mce-bogus="all"></div>').css(clientRect).appendTo(root)[0];
          lastVisualCaret.set(Option.some({
            caret: caret,
            element: element,
            before: before
          }));
          lastVisualCaret.get().each(function (caretState) {
            if (before) {
              DomQuery(caretState.caret).addClass('mce-visual-caret-before');
            }
          });
          startBlink();
          rng = element.ownerDocument.createRange();
          rng.setStart(caretContainerNode, 0);
          rng.setEnd(caretContainerNode, 0);
        } else {
          caretContainerNode = insertInline(element, before);
          rng = element.ownerDocument.createRange();
          if (isContentEditableFalse$3(caretContainerNode.nextSibling)) {
            rng.setStart(caretContainerNode, 0);
            rng.setEnd(caretContainerNode, 0);
          } else {
            rng.setStart(caretContainerNode, 1);
            rng.setEnd(caretContainerNode, 1);
          }
          return rng;
        }
        return rng;
      };
      var hide = function () {
        trimInlineCaretContainers(root);
        if (caretContainerNode) {
          CaretContainerRemove.remove(caretContainerNode);
          caretContainerNode = null;
        }
        lastVisualCaret.get().each(function (caretState) {
          DomQuery(caretState.caret).remove();
          lastVisualCaret.set(Option.none());
        });
        clearInterval(cursorInterval);
      };
      var startBlink = function () {
        cursorInterval = Delay.setInterval(function () {
          if (hasFocus()) {
            DomQuery('div.mce-visual-caret', root).toggleClass('mce-visual-caret-hidden');
          } else {
            DomQuery('div.mce-visual-caret', root).addClass('mce-visual-caret-hidden');
          }
        }, 500);
      };
      var reposition = function () {
        lastVisualCaret.get().each(function (caretState) {
          var clientRect = getAbsoluteClientRect(root, caretState.element, caretState.before);
          DomQuery(caretState.caret).css(clientRect);
        });
      };
      var destroy = function () {
        return Delay.clearInterval(cursorInterval);
      };
      var getCss = function () {
        return '.mce-visual-caret {' + 'position: absolute;' + 'background-color: black;' + 'background-color: currentcolor;' + '}' + '.mce-visual-caret-hidden {' + 'display: none;' + '}' + '*[data-mce-caret] {' + 'position: absolute;' + 'left: -1000px;' + 'right: auto;' + 'top: 0;' + 'margin: 0;' + 'padding: 0;' + '}';
      };
      return {
        show: show,
        hide: hide,
        getCss: getCss,
        reposition: reposition,
        destroy: destroy
      };
    };
    var isFakeCaretTableBrowser = function () {
      return browser$2.isIE() || browser$2.isEdge() || browser$2.isFirefox();
    };
    var isFakeCaretTarget = function (node) {
      return isContentEditableFalse$3(node) || NodeType.isTable(node) && isFakeCaretTableBrowser();
    };

    var isContentEditableFalse$4 = NodeType.isContentEditableFalse;
    var isBlockLike = NodeType.matchStyleValues('display', 'block table table-cell table-caption list-item');
    var isCaretContainer$2 = isCaretContainer;
    var isCaretContainerBlock$1 = isCaretContainerBlock;
    var isElement$5 = NodeType.isElement;
    var isCaretCandidate$2 = isCaretCandidate;
    var isForwards = function (direction) {
      return direction > 0;
    };
    var isBackwards = function (direction) {
      return direction < 0;
    };
    var skipCaretContainers = function (walk, shallow) {
      var node;
      while (node = walk(shallow)) {
        if (!isCaretContainerBlock$1(node)) {
          return node;
        }
      }
      return null;
    };
    var findNode = function (node, direction, predicateFn, rootNode, shallow) {
      var walker = new TreeWalker(node, rootNode);
      if (isBackwards(direction)) {
        if (isContentEditableFalse$4(node) || isCaretContainerBlock$1(node)) {
          node = skipCaretContainers(walker.prev, true);
          if (predicateFn(node)) {
            return node;
          }
        }
        while (node = skipCaretContainers(walker.prev, shallow)) {
          if (predicateFn(node)) {
            return node;
          }
        }
      }
      if (isForwards(direction)) {
        if (isContentEditableFalse$4(node) || isCaretContainerBlock$1(node)) {
          node = skipCaretContainers(walker.next, true);
          if (predicateFn(node)) {
            return node;
          }
        }
        while (node = skipCaretContainers(walker.next, shallow)) {
          if (predicateFn(node)) {
            return node;
          }
        }
      }
      return null;
    };
    var getParentBlock = function (node, rootNode) {
      while (node && node !== rootNode) {
        if (isBlockLike(node)) {
          return node;
        }
        node = node.parentNode;
      }
      return null;
    };
    var isInSameBlock = function (caretPosition1, caretPosition2, rootNode) {
      return getParentBlock(caretPosition1.container(), rootNode) === getParentBlock(caretPosition2.container(), rootNode);
    };
    var getChildNodeAtRelativeOffset = function (relativeOffset, caretPosition) {
      var container, offset;
      if (!caretPosition) {
        return null;
      }
      container = caretPosition.container();
      offset = caretPosition.offset();
      if (!isElement$5(container)) {
        return null;
      }
      return container.childNodes[offset + relativeOffset];
    };
    var beforeAfter = function (before, node) {
      var range = node.ownerDocument.createRange();
      if (before) {
        range.setStartBefore(node);
        range.setEndBefore(node);
      } else {
        range.setStartAfter(node);
        range.setEndAfter(node);
      }
      return range;
    };
    var isNodesInSameBlock = function (root, node1, node2) {
      return getParentBlock(node1, root) === getParentBlock(node2, root);
    };
    var lean = function (left, root, node) {
      var sibling, siblingName;
      if (left) {
        siblingName = 'previousSibling';
      } else {
        siblingName = 'nextSibling';
      }
      while (node && node !== root) {
        sibling = node[siblingName];
        if (isCaretContainer$2(sibling)) {
          sibling = sibling[siblingName];
        }
        if (isContentEditableFalse$4(sibling)) {
          if (isNodesInSameBlock(root, sibling, node)) {
            return sibling;
          }
          break;
        }
        if (isCaretCandidate$2(sibling)) {
          break;
        }
        node = node.parentNode;
      }
      return null;
    };
    var before$2 = curry(beforeAfter, true);
    var after$1 = curry(beforeAfter, false);
    var normalizeRange = function (direction, root, range) {
      var node, container, offset, location;
      var leanLeft = curry(lean, true, root);
      var leanRight = curry(lean, false, root);
      container = range.startContainer;
      offset = range.startOffset;
      if (isCaretContainerBlock(container)) {
        if (!isElement$5(container)) {
          container = container.parentNode;
        }
        location = container.getAttribute('data-mce-caret');
        if (location === 'before') {
          node = container.nextSibling;
          if (isFakeCaretTarget(node)) {
            return before$2(node);
          }
        }
        if (location === 'after') {
          node = container.previousSibling;
          if (isFakeCaretTarget(node)) {
            return after$1(node);
          }
        }
      }
      if (!range.collapsed) {
        return range;
      }
      if (NodeType.isText(container)) {
        if (isCaretContainer$2(container)) {
          if (direction === 1) {
            node = leanRight(container);
            if (node) {
              return before$2(node);
            }
            node = leanLeft(container);
            if (node) {
              return after$1(node);
            }
          }
          if (direction === -1) {
            node = leanLeft(container);
            if (node) {
              return after$1(node);
            }
            node = leanRight(container);
            if (node) {
              return before$2(node);
            }
          }
          return range;
        }
        if (endsWithCaretContainer(container) && offset >= container.data.length - 1) {
          if (direction === 1) {
            node = leanRight(container);
            if (node) {
              return before$2(node);
            }
          }
          return range;
        }
        if (startsWithCaretContainer(container) && offset <= 1) {
          if (direction === -1) {
            node = leanLeft(container);
            if (node) {
              return after$1(node);
            }
          }
          return range;
        }
        if (offset === container.data.length) {
          node = leanRight(container);
          if (node) {
            return before$2(node);
          }
          return range;
        }
        if (offset === 0) {
          node = leanLeft(container);
          if (node) {
            return after$1(node);
          }
          return range;
        }
      }
      return range;
    };
    var getRelativeCefElm = function (forward, caretPosition) {
      return Option.from(getChildNodeAtRelativeOffset(forward ? 0 : -1, caretPosition)).filter(isContentEditableFalse$4);
    };
    var getNormalizedRangeEndPoint = function (direction, root, range) {
      var normalizedRange = normalizeRange(direction, root, range);
      if (direction === -1) {
        return CaretPosition.fromRangeStart(normalizedRange);
      }
      return CaretPosition.fromRangeEnd(normalizedRange);
    };
    var getElementFromPosition = function (pos) {
      return Option.from(pos.getNode()).map(Element.fromDom);
    };
    var getElementFromPrevPosition = function (pos) {
      return Option.from(pos.getNode(true)).map(Element.fromDom);
    };
    var getVisualCaretPosition = function (walkFn, caretPosition) {
      while (caretPosition = walkFn(caretPosition)) {
        if (caretPosition.isVisible()) {
          return caretPosition;
        }
      }
      return caretPosition;
    };
    var isMoveInsideSameBlock = function (from, to) {
      var inSameBlock = isInSameBlock(from, to);
      if (!inSameBlock && NodeType.isBr(from.getNode())) {
        return true;
      }
      return inSameBlock;
    };

    var HDirection;
    (function (HDirection) {
      HDirection[HDirection['Backwards'] = -1] = 'Backwards';
      HDirection[HDirection['Forwards'] = 1] = 'Forwards';
    }(HDirection || (HDirection = {})));
    var isContentEditableFalse$5 = NodeType.isContentEditableFalse;
    var isText$7 = NodeType.isText;
    var isElement$6 = NodeType.isElement;
    var isBr$4 = NodeType.isBr;
    var isCaretCandidate$3 = isCaretCandidate;
    var isAtomic$1 = isAtomic;
    var isEditableCaretCandidate$1 = isEditableCaretCandidate;
    var getParents = function (node, root) {
      var parents = [];
      while (node && node !== root) {
        parents.push(node);
        node = node.parentNode;
      }
      return parents;
    };
    var nodeAtIndex = function (container, offset) {
      if (container.hasChildNodes() && offset < container.childNodes.length) {
        return container.childNodes[offset];
      }
      return null;
    };
    var getCaretCandidatePosition = function (direction, node) {
      if (isForwards(direction)) {
        if (isCaretCandidate$3(node.previousSibling) && !isText$7(node.previousSibling)) {
          return CaretPosition$1.before(node);
        }
        if (isText$7(node)) {
          return CaretPosition$1(node, 0);
        }
      }
      if (isBackwards(direction)) {
        if (isCaretCandidate$3(node.nextSibling) && !isText$7(node.nextSibling)) {
          return CaretPosition$1.after(node);
        }
        if (isText$7(node)) {
          return CaretPosition$1(node, node.data.length);
        }
      }
      if (isBackwards(direction)) {
        if (isBr$4(node)) {
          return CaretPosition$1.before(node);
        }
        return CaretPosition$1.after(node);
      }
      return CaretPosition$1.before(node);
    };
    var moveForwardFromBr = function (root, nextNode) {
      var nextSibling = nextNode.nextSibling;
      if (nextSibling && isCaretCandidate$3(nextSibling)) {
        if (isText$7(nextSibling)) {
          return CaretPosition$1(nextSibling, 0);
        } else {
          return CaretPosition$1.before(nextSibling);
        }
      } else {
        return findCaretPosition(HDirection.Forwards, CaretPosition$1.after(nextNode), root);
      }
    };
    var findCaretPosition = function (direction, startPos, root) {
      var node, nextNode, innerNode;
      var rootContentEditableFalseElm, caretPosition;
      if (!isElement$6(root) || !startPos) {
        return null;
      }
      if (startPos.isEqual(CaretPosition$1.after(root)) && root.lastChild) {
        caretPosition = CaretPosition$1.after(root.lastChild);
        if (isBackwards(direction) && isCaretCandidate$3(root.lastChild) && isElement$6(root.lastChild)) {
          return isBr$4(root.lastChild) ? CaretPosition$1.before(root.lastChild) : caretPosition;
        }
      } else {
        caretPosition = startPos;
      }
      var container = caretPosition.container();
      var offset = caretPosition.offset();
      if (isText$7(container)) {
        if (isBackwards(direction) && offset > 0) {
          return CaretPosition$1(container, --offset);
        }
        if (isForwards(direction) && offset < container.length) {
          return CaretPosition$1(container, ++offset);
        }
        node = container;
      } else {
        if (isBackwards(direction) && offset > 0) {
          nextNode = nodeAtIndex(container, offset - 1);
          if (isCaretCandidate$3(nextNode)) {
            if (!isAtomic$1(nextNode)) {
              innerNode = findNode(nextNode, direction, isEditableCaretCandidate$1, nextNode);
              if (innerNode) {
                if (isText$7(innerNode)) {
                  return CaretPosition$1(innerNode, innerNode.data.length);
                }
                return CaretPosition$1.after(innerNode);
              }
            }
            if (isText$7(nextNode)) {
              return CaretPosition$1(nextNode, nextNode.data.length);
            }
            return CaretPosition$1.before(nextNode);
          }
        }
        if (isForwards(direction) && offset < container.childNodes.length) {
          nextNode = nodeAtIndex(container, offset);
          if (isCaretCandidate$3(nextNode)) {
            if (isBr$4(nextNode)) {
              return moveForwardFromBr(root, nextNode);
            }
            if (!isAtomic$1(nextNode)) {
              innerNode = findNode(nextNode, direction, isEditableCaretCandidate$1, nextNode);
              if (innerNode) {
                if (isText$7(innerNode)) {
                  return CaretPosition$1(innerNode, 0);
                }
                return CaretPosition$1.before(innerNode);
              }
            }
            if (isText$7(nextNode)) {
              return CaretPosition$1(nextNode, 0);
            }
            return CaretPosition$1.after(nextNode);
          }
        }
        node = nextNode ? nextNode : caretPosition.getNode();
      }
      if (isForwards(direction) && caretPosition.isAtEnd() || isBackwards(direction) && caretPosition.isAtStart()) {
        node = findNode(node, direction, constant(true), root, true);
        if (isEditableCaretCandidate$1(node, root)) {
          return getCaretCandidatePosition(direction, node);
        }
      }
      nextNode = findNode(node, direction, isEditableCaretCandidate$1, root);
      rootContentEditableFalseElm = ArrUtils.last(filter(getParents(container, root), isContentEditableFalse$5));
      if (rootContentEditableFalseElm && (!nextNode || !rootContentEditableFalseElm.contains(nextNode))) {
        if (isForwards(direction)) {
          caretPosition = CaretPosition$1.after(rootContentEditableFalseElm);
        } else {
          caretPosition = CaretPosition$1.before(rootContentEditableFalseElm);
        }
        return caretPosition;
      }
      if (nextNode) {
        return getCaretCandidatePosition(direction, nextNode);
      }
      return null;
    };
    var CaretWalker = function (root) {
      return {
        next: function (caretPosition) {
          return findCaretPosition(HDirection.Forwards, caretPosition, root);
        },
        prev: function (caretPosition) {
          return findCaretPosition(HDirection.Backwards, caretPosition, root);
        }
      };
    };

    var walkToPositionIn = function (forward, root, start) {
      var position = forward ? CaretPosition$1.before(start) : CaretPosition$1.after(start);
      return fromPosition(forward, root, position);
    };
    var afterElement = function (node) {
      return NodeType.isBr(node) ? CaretPosition$1.before(node) : CaretPosition$1.after(node);
    };
    var isBeforeOrStart = function (position) {
      if (CaretPosition$1.isTextPosition(position)) {
        return position.offset() === 0;
      } else {
        return isCaretCandidate(position.getNode());
      }
    };
    var isAfterOrEnd = function (position) {
      if (CaretPosition$1.isTextPosition(position)) {
        var container = position.container();
        return position.offset() === container.data.length;
      } else {
        return isCaretCandidate(position.getNode(true));
      }
    };
    var isBeforeAfterSameElement = function (from, to) {
      return !CaretPosition$1.isTextPosition(from) && !CaretPosition$1.isTextPosition(to) && from.getNode() === to.getNode(true);
    };
    var isAtBr = function (position) {
      return !CaretPosition$1.isTextPosition(position) && NodeType.isBr(position.getNode());
    };
    var shouldSkipPosition = function (forward, from, to) {
      if (forward) {
        return !isBeforeAfterSameElement(from, to) && !isAtBr(from) && isAfterOrEnd(from) && isBeforeOrStart(to);
      } else {
        return !isBeforeAfterSameElement(to, from) && isBeforeOrStart(from) && isAfterOrEnd(to);
      }
    };
    var fromPosition = function (forward, root, pos) {
      var walker = CaretWalker(root);
      return Option.from(forward ? walker.next(pos) : walker.prev(pos));
    };
    var navigate = function (forward, root, from) {
      return fromPosition(forward, root, from).bind(function (to) {
        if (isInSameBlock(from, to, root) && shouldSkipPosition(forward, from, to)) {
          return fromPosition(forward, root, to);
        } else {
          return Option.some(to);
        }
      });
    };
    var navigateIgnore = function (forward, root, from, ignoreFilter) {
      return navigate(forward, root, from).bind(function (pos) {
        return ignoreFilter(pos) ? navigateIgnore(forward, root, pos, ignoreFilter) : Option.some(pos);
      });
    };
    var positionIn = function (forward, element) {
      var startNode = forward ? element.firstChild : element.lastChild;
      if (NodeType.isText(startNode)) {
        return Option.some(CaretPosition$1(startNode, forward ? 0 : startNode.data.length));
      } else if (startNode) {
        if (isCaretCandidate(startNode)) {
          return Option.some(forward ? CaretPosition$1.before(startNode) : afterElement(startNode));
        } else {
          return walkToPositionIn(forward, element, startNode);
        }
      } else {
        return Option.none();
      }
    };
    var nextPosition = curry(fromPosition, true);
    var prevPosition = curry(fromPosition, false);
    var CaretFinder = {
      fromPosition: fromPosition,
      nextPosition: nextPosition,
      prevPosition: prevPosition,
      navigate: navigate,
      navigateIgnore: navigateIgnore,
      positionIn: positionIn,
      firstPositionIn: curry(positionIn, true),
      lastPositionIn: curry(positionIn, false)
    };

    var isStringPathBookmark = function (bookmark) {
      return typeof bookmark.start === 'string';
    };
    var isRangeBookmark = function (bookmark) {
      return bookmark.hasOwnProperty('rng');
    };
    var isIdBookmark = function (bookmark) {
      return bookmark.hasOwnProperty('id');
    };
    var isIndexBookmark = function (bookmark) {
      return bookmark.hasOwnProperty('name');
    };
    var isPathBookmark = function (bookmark) {
      return Tools.isArray(bookmark.start);
    };

    var addBogus = function (dom, node) {
      if (NodeType.isElement(node) && dom.isBlock(node) && !node.innerHTML && !Env.ie) {
        node.innerHTML = '<br data-mce-bogus="1" />';
      }
      return node;
    };
    var resolveCaretPositionBookmark = function (dom, bookmark) {
      var rng, pos;
      rng = dom.createRng();
      pos = resolve$2(dom.getRoot(), bookmark.start);
      rng.setStart(pos.container(), pos.offset());
      pos = resolve$2(dom.getRoot(), bookmark.end);
      rng.setEnd(pos.container(), pos.offset());
      return rng;
    };
    var insertZwsp = function (node, rng) {
      var textNode = node.ownerDocument.createTextNode(Zwsp.ZWSP);
      node.appendChild(textNode);
      rng.setStart(textNode, 0);
      rng.setEnd(textNode, 0);
    };
    var isEmpty = function (node) {
      return node.hasChildNodes() === false;
    };
    var tryFindRangePosition = function (node, rng) {
      return CaretFinder.lastPositionIn(node).fold(function () {
        return false;
      }, function (pos) {
        rng.setStart(pos.container(), pos.offset());
        rng.setEnd(pos.container(), pos.offset());
        return true;
      });
    };
    var padEmptyCaretContainer = function (root, node, rng) {
      if (isEmpty(node) && getParentCaretContainer(root, node)) {
        insertZwsp(node, rng);
        return true;
      } else {
        return false;
      }
    };
    var setEndPoint = function (dom, start, bookmark, rng) {
      var point = bookmark[start ? 'start' : 'end'];
      var i, node, offset, children;
      var root = dom.getRoot();
      if (point) {
        offset = point[0];
        for (node = root, i = point.length - 1; i >= 1; i--) {
          children = node.childNodes;
          if (padEmptyCaretContainer(root, node, rng)) {
            return true;
          }
          if (point[i] > children.length - 1) {
            if (padEmptyCaretContainer(root, node, rng)) {
              return true;
            }
            return tryFindRangePosition(node, rng);
          }
          node = children[point[i]];
        }
        if (node.nodeType === 3) {
          offset = Math.min(point[0], node.nodeValue.length);
        }
        if (node.nodeType === 1) {
          offset = Math.min(point[0], node.childNodes.length);
        }
        if (start) {
          rng.setStart(node, offset);
        } else {
          rng.setEnd(node, offset);
        }
      }
      return true;
    };
    var isValidTextNode = function (node) {
      return NodeType.isText(node) && node.data.length > 0;
    };
    var restoreEndPoint = function (dom, suffix, bookmark) {
      var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev;
      var keep = bookmark.keep;
      var container, offset;
      if (marker) {
        node = marker.parentNode;
        if (suffix === 'start') {
          if (!keep) {
            idx = dom.nodeIndex(marker);
          } else {
            if (marker.hasChildNodes()) {
              node = marker.firstChild;
              idx = 1;
            } else if (isValidTextNode(marker.nextSibling)) {
              node = marker.nextSibling;
              idx = 0;
            } else if (isValidTextNode(marker.previousSibling)) {
              node = marker.previousSibling;
              idx = marker.previousSibling.data.length;
            } else {
              node = marker.parentNode;
              idx = dom.nodeIndex(marker) + 1;
            }
          }
          container = node;
          offset = idx;
        } else {
          if (!keep) {
            idx = dom.nodeIndex(marker);
          } else {
            if (marker.hasChildNodes()) {
              node = marker.firstChild;
              idx = 1;
            } else if (isValidTextNode(marker.previousSibling)) {
              node = marker.previousSibling;
              idx = marker.previousSibling.data.length;
            } else {
              node = marker.parentNode;
              idx = dom.nodeIndex(marker);
            }
          }
          container = node;
          offset = idx;
        }
        if (!keep) {
          prev = marker.previousSibling;
          next = marker.nextSibling;
          Tools.each(Tools.grep(marker.childNodes), function (node) {
            if (NodeType.isText(node)) {
              node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
            }
          });
          while (marker = dom.get(bookmark.id + '_' + suffix)) {
            dom.remove(marker, true);
          }
          if (prev && next && prev.nodeType === next.nodeType && NodeType.isText(prev) && !Env.opera) {
            idx = prev.nodeValue.length;
            prev.appendData(next.nodeValue);
            dom.remove(next);
            if (suffix === 'start') {
              container = prev;
              offset = idx;
            } else {
              container = prev;
              offset = idx;
            }
          }
        }
        return Option.some(CaretPosition$1(container, offset));
      } else {
        return Option.none();
      }
    };
    var alt = function (o1, o2) {
      return o1.isSome() ? o1 : o2;
    };
    var resolvePaths = function (dom, bookmark) {
      var rng = dom.createRng();
      if (setEndPoint(dom, true, bookmark, rng) && setEndPoint(dom, false, bookmark, rng)) {
        return Option.some(rng);
      } else {
        return Option.none();
      }
    };
    var resolveId = function (dom, bookmark) {
      var startPos = restoreEndPoint(dom, 'start', bookmark);
      var endPos = restoreEndPoint(dom, 'end', bookmark);
      return lift2(startPos, alt(endPos, startPos), function (spos, epos) {
        var rng = dom.createRng();
        rng.setStart(addBogus(dom, spos.container()), spos.offset());
        rng.setEnd(addBogus(dom, epos.container()), epos.offset());
        return rng;
      });
    };
    var resolveIndex$1 = function (dom, bookmark) {
      return Option.from(dom.select(bookmark.name)[bookmark.index]).map(function (elm) {
        var rng = dom.createRng();
        rng.selectNode(elm);
        return rng;
      });
    };
    var resolve$3 = function (selection, bookmark) {
      var dom = selection.dom;
      if (bookmark) {
        if (isPathBookmark(bookmark)) {
          return resolvePaths(dom, bookmark);
        } else if (isStringPathBookmark(bookmark)) {
          return Option.some(resolveCaretPositionBookmark(dom, bookmark));
        } else if (isIdBookmark(bookmark)) {
          return resolveId(dom, bookmark);
        } else if (isIndexBookmark(bookmark)) {
          return resolveIndex$1(dom, bookmark);
        } else if (isRangeBookmark(bookmark)) {
          return Option.some(bookmark.rng);
        }
      }
      return Option.none();
    };
    var ResolveBookmark = { resolve: resolve$3 };

    var getBookmark$1 = function (selection, type, normalized) {
      return GetBookmark.getBookmark(selection, type, normalized);
    };
    var moveToBookmark = function (selection, bookmark) {
      ResolveBookmark.resolve(selection, bookmark).each(function (rng) {
        selection.setRng(rng);
      });
    };
    var isBookmarkNode$1 = function (node) {
      return NodeType.isElement(node) && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
    };
    var Bookmarks = {
      getBookmark: getBookmark$1,
      moveToBookmark: moveToBookmark,
      isBookmarkNode: isBookmarkNode$1
    };

    var isInlineBlock = function (node) {
      return node && /^(IMG)$/.test(node.nodeName);
    };
    var moveStart = function (dom, selection, rng) {
      var offset = rng.startOffset;
      var container = rng.startContainer, walker, node, nodes;
      if (rng.startContainer === rng.endContainer) {
        if (isInlineBlock(rng.startContainer.childNodes[rng.startOffset])) {
          return;
        }
      }
      if (container.nodeType === 1) {
        nodes = container.childNodes;
        if (offset < nodes.length) {
          container = nodes[offset];
          walker = new TreeWalker(container, dom.getParent(container, dom.isBlock));
        } else {
          container = nodes[nodes.length - 1];
          walker = new TreeWalker(container, dom.getParent(container, dom.isBlock));
          walker.next(true);
        }
        for (node = walker.current(); node; node = walker.next()) {
          if (node.nodeType === 3 && !isWhiteSpaceNode(node)) {
            rng.setStart(node, 0);
            selection.setRng(rng);
            return;
          }
        }
      }
    };
    var getNonWhiteSpaceSibling = function (node, next, inc) {
      if (node) {
        next = next ? 'nextSibling' : 'previousSibling';
        for (node = inc ? node : node[next]; node; node = node[next]) {
          if (node.nodeType === 1 || !isWhiteSpaceNode(node)) {
            return node;
          }
        }
      }
    };
    var isTextBlock$1 = function (editor, name) {
      if (name.nodeType) {
        name = name.nodeName;
      }
      return !!editor.schema.getTextBlockElements()[name.toLowerCase()];
    };
    var isValid = function (ed, parent, child) {
      return ed.schema.isValidChild(parent, child);
    };
    var isWhiteSpaceNode = function (node) {
      return node && node.nodeType === 3 && /^([\t \r\n]+|)$/.test(node.nodeValue);
    };
    var replaceVars = function (value, vars) {
      if (typeof value !== 'string') {
        value = value(vars);
      } else if (vars) {
        value = value.replace(/%(\w+)/g, function (str, name) {
          return vars[name] || str;
        });
      }
      return value;
    };
    var isEq = function (str1, str2) {
      str1 = str1 || '';
      str2 = str2 || '';
      str1 = '' + (str1.nodeName || str1);
      str2 = '' + (str2.nodeName || str2);
      return str1.toLowerCase() === str2.toLowerCase();
    };
    var normalizeStyleValue = function (dom, value, name) {
      if (name === 'color' || name === 'backgroundColor') {
        value = dom.toHex(value);
      }
      if (name === 'fontWeight' && value === 700) {
        value = 'bold';
      }
      if (name === 'fontFamily') {
        value = value.replace(/[\'\"]/g, '').replace(/,\s+/g, ',');
      }
      return '' + value;
    };
    var getStyle = function (dom, node, name) {
      return normalizeStyleValue(dom, dom.getStyle(node, name), name);
    };
    var getTextDecoration = function (dom, node) {
      var decoration;
      dom.getParent(node, function (n) {
        decoration = dom.getStyle(n, 'text-decoration');
        return decoration && decoration !== 'none';
      });
      return decoration;
    };
    var getParents$1 = function (dom, node, selector) {
      return dom.getParents(node, selector, dom.getRoot());
    };
    var FormatUtils = {
      isInlineBlock: isInlineBlock,
      moveStart: moveStart,
      getNonWhiteSpaceSibling: getNonWhiteSpaceSibling,
      isTextBlock: isTextBlock$1,
      isValid: isValid,
      isWhiteSpaceNode: isWhiteSpaceNode,
      replaceVars: replaceVars,
      isEq: isEq,
      normalizeStyleValue: normalizeStyleValue,
      getStyle: getStyle,
      getTextDecoration: getTextDecoration,
      getParents: getParents$1
    };

    var isBookmarkNode$2 = Bookmarks.isBookmarkNode;
    var getParents$2 = FormatUtils.getParents, isWhiteSpaceNode$1 = FormatUtils.isWhiteSpaceNode, isTextBlock$2 = FormatUtils.isTextBlock;
    var findLeaf = function (node, offset) {
      if (typeof offset === 'undefined') {
        offset = node.nodeType === 3 ? node.length : node.childNodes.length;
      }
      while (node && node.hasChildNodes()) {
        node = node.childNodes[offset];
        if (node) {
          offset = node.nodeType === 3 ? node.length : node.childNodes.length;
        }
      }
      return {
        node: node,
        offset: offset
      };
    };
    var excludeTrailingWhitespace = function (endContainer, endOffset) {
      var leaf = findLeaf(endContainer, endOffset);
      if (leaf.node) {
        while (leaf.node && leaf.offset === 0 && leaf.node.previousSibling) {
          leaf = findLeaf(leaf.node.previousSibling);
        }
        if (leaf.node && leaf.offset > 0 && leaf.node.nodeType === 3 && leaf.node.nodeValue.charAt(leaf.offset - 1) === ' ') {
          if (leaf.offset > 1) {
            endContainer = leaf.node;
            endContainer.splitText(leaf.offset - 1);
          }
        }
      }
      return endContainer;
    };
    var isBogusBr = function (node) {
      return node.nodeName === 'BR' && node.getAttribute('data-mce-bogus') && !node.nextSibling;
    };
    var findParentContentEditable = function (dom, node) {
      var parent = node;
      while (parent) {
        if (parent.nodeType === 1 && dom.getContentEditable(parent)) {
          return dom.getContentEditable(parent) === 'false' ? parent : node;
        }
        parent = parent.parentNode;
      }
      return node;
    };
    var findSpace = function (start, remove, node, offset) {
      var pos, pos2;
      var str = node.nodeValue;
      if (typeof offset === 'undefined') {
        offset = start ? str.length : 0;
      }
      if (start) {
        pos = str.lastIndexOf(' ', offset);
        pos2 = str.lastIndexOf('\xA0', offset);
        pos = pos > pos2 ? pos : pos2;
        if (pos !== -1 && !remove && (pos < offset || !start) && pos <= str.length) {
          pos++;
        }
      } else {
        pos = str.indexOf(' ', offset);
        pos2 = str.indexOf('\xA0', offset);
        pos = pos !== -1 && (pos2 === -1 || pos < pos2) ? pos : pos2;
      }
      return pos;
    };
    var findWordEndPoint = function (dom, body, container, offset, start, remove) {
      var walker, node, pos, lastTextNode;
      if (container.nodeType === 3) {
        pos = findSpace(start, remove, container, offset);
        if (pos !== -1) {
          return {
            container: container,
            offset: pos
          };
        }
        lastTextNode = container;
      }
      walker = new TreeWalker(container, dom.getParent(container, dom.isBlock) || body);
      while (node = walker[start ? 'prev' : 'next']()) {
        if (node.nodeType === 3 && !isBookmarkNode$2(node.parentNode)) {
          lastTextNode = node;
          pos = findSpace(start, remove, node);
          if (pos !== -1) {
            return {
              container: node,
              offset: pos
            };
          }
        } else if (dom.isBlock(node) || FormatUtils.isEq(node, 'BR')) {
          break;
        }
      }
      if (lastTextNode) {
        if (start) {
          offset = 0;
        } else {
          offset = lastTextNode.length;
        }
        return {
          container: lastTextNode,
          offset: offset
        };
      }
    };
    var findSelectorEndPoint = function (dom, format, rng, container, siblingName) {
      var parents, i, y, curFormat;
      if (container.nodeType === 3 && container.nodeValue.length === 0 && container[siblingName]) {
        container = container[siblingName];
      }
      parents = getParents$2(dom, container);
      for (i = 0; i < parents.length; i++) {
        for (y = 0; y < format.length; y++) {
          curFormat = format[y];
          if ('collapsed' in curFormat && curFormat.collapsed !== rng.collapsed) {
            continue;
          }
          if (dom.is(parents[i], curFormat.selector)) {
            return parents[i];
          }
        }
      }
      return container;
    };
    var findBlockEndPoint = function (editor, format, container, siblingName) {
      var node;
      var dom = editor.dom;
      var root = dom.getRoot();
      if (!format[0].wrapper) {
        node = dom.getParent(container, format[0].block, root);
      }
      if (!node) {
        var scopeRoot = dom.getParent(container, 'LI,TD,TH');
        node = dom.getParent(container.nodeType === 3 ? container.parentNode : container, function (node) {
          return node !== root && isTextBlock$2(editor, node);
        }, scopeRoot);
      }
      if (node && format[0].wrapper) {
        node = getParents$2(dom, node, 'ul,ol').reverse()[0] || node;
      }
      if (!node) {
        node = container;
        while (node[siblingName] && !dom.isBlock(node[siblingName])) {
          node = node[siblingName];
          if (FormatUtils.isEq(node, 'br')) {
            break;
          }
        }
      }
      return node || container;
    };
    var findParentContainer = function (dom, format, startContainer, startOffset, endContainer, endOffset, start) {
      var container, parent, sibling, siblingName, root;
      container = parent = start ? startContainer : endContainer;
      siblingName = start ? 'previousSibling' : 'nextSibling';
      root = dom.getRoot();
      if (container.nodeType === 3 && !isWhiteSpaceNode$1(container)) {
        if (start ? startOffset > 0 : endOffset < container.nodeValue.length) {
          return container;
        }
      }
      while (true) {
        if (!format[0].block_expand && dom.isBlock(parent)) {
          return parent;
        }
        for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
          if (!isBookmarkNode$2(sibling) && !isWhiteSpaceNode$1(sibling) && !isBogusBr(sibling)) {
            return parent;
          }
        }
        if (parent === root || parent.parentNode === root) {
          container = parent;
          break;
        }
        parent = parent.parentNode;
      }
      return container;
    };
    var expandRng = function (editor, rng, format, remove) {
      var endPoint, startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset;
      var dom = editor.dom;
      if (startContainer.nodeType === 1 && startContainer.hasChildNodes()) {
        startContainer = getNode(startContainer, startOffset);
        if (startContainer.nodeType === 3) {
          startOffset = 0;
        }
      }
      if (endContainer.nodeType === 1 && endContainer.hasChildNodes()) {
        endContainer = getNode(endContainer, rng.collapsed ? endOffset : endOffset - 1);
        if (endContainer.nodeType === 3) {
          endOffset = endContainer.nodeValue.length;
        }
      }
      startContainer = findParentContentEditable(dom, startContainer);
      endContainer = findParentContentEditable(dom, endContainer);
      if (isBookmarkNode$2(startContainer.parentNode) || isBookmarkNode$2(startContainer)) {
        startContainer = isBookmarkNode$2(startContainer) ? startContainer : startContainer.parentNode;
        if (rng.collapsed) {
          startContainer = startContainer.previousSibling || startContainer;
        } else {
          startContainer = startContainer.nextSibling || startContainer;
        }
        if (startContainer.nodeType === 3) {
          startOffset = rng.collapsed ? startContainer.length : 0;
        }
      }
      if (isBookmarkNode$2(endContainer.parentNode) || isBookmarkNode$2(endContainer)) {
        endContainer = isBookmarkNode$2(endContainer) ? endContainer : endContainer.parentNode;
        if (rng.collapsed) {
          endContainer = endContainer.nextSibling || endContainer;
        } else {
          endContainer = endContainer.previousSibling || endContainer;
        }
        if (endContainer.nodeType === 3) {
          endOffset = rng.collapsed ? 0 : endContainer.length;
        }
      }
      if (rng.collapsed) {
        endPoint = findWordEndPoint(dom, editor.getBody(), startContainer, startOffset, true, remove);
        if (endPoint) {
          startContainer = endPoint.container;
          startOffset = endPoint.offset;
        }
        endPoint = findWordEndPoint(dom, editor.getBody(), endContainer, endOffset, false, remove);
        if (endPoint) {
          endContainer = endPoint.container;
          endOffset = endPoint.offset;
        }
      }
      if (format[0].inline) {
        endContainer = remove ? endContainer : excludeTrailingWhitespace(endContainer, endOffset);
      }
      if (format[0].inline || format[0].block_expand) {
        if (!format[0].inline || (startContainer.nodeType !== 3 || startOffset === 0)) {
          startContainer = findParentContainer(dom, format, startContainer, startOffset, endContainer, endOffset, true);
        }
        if (!format[0].inline || (endContainer.nodeType !== 3 || endOffset === endContainer.nodeValue.length)) {
          endContainer = findParentContainer(dom, format, startContainer, startOffset, endContainer, endOffset, false);
        }
      }
      if (format[0].selector && format[0].expand !== false && !format[0].inline) {
        startContainer = findSelectorEndPoint(dom, format, rng, startContainer, 'previousSibling');
        endContainer = findSelectorEndPoint(dom, format, rng, endContainer, 'nextSibling');
      }
      if (format[0].block || format[0].selector) {
        startContainer = findBlockEndPoint(editor, format, startContainer, 'previousSibling');
        endContainer = findBlockEndPoint(editor, format, endContainer, 'nextSibling');
        if (format[0].block) {
          if (!dom.isBlock(startContainer)) {
            startContainer = findParentContainer(dom, format, startContainer, startOffset, endContainer, endOffset, true);
          }
          if (!dom.isBlock(endContainer)) {
            endContainer = findParentContainer(dom, format, startContainer, startOffset, endContainer, endOffset, false);
          }
        }
      }
      if (startContainer.nodeType === 1) {
        startOffset = dom.nodeIndex(startContainer);
        startContainer = startContainer.parentNode;
      }
      if (endContainer.nodeType === 1) {
        endOffset = dom.nodeIndex(endContainer) + 1;
        endContainer = endContainer.parentNode;
      }
      return {
        startContainer: startContainer,
        startOffset: startOffset,
        endContainer: endContainer,
        endOffset: endOffset
      };
    };
    var ExpandRange = { expandRng: expandRng };

    var each$8 = Tools.each;
    var getEndChild = function (container, index) {
      var childNodes = container.childNodes;
      index--;
      if (index > childNodes.length - 1) {
        index = childNodes.length - 1;
      } else if (index < 0) {
        index = 0;
      }
      return childNodes[index] || container;
    };
    var walk$1 = function (dom, rng, callback) {
      var startContainer = rng.startContainer;
      var startOffset = rng.startOffset;
      var endContainer = rng.endContainer;
      var endOffset = rng.endOffset;
      var ancestor;
      var startPoint;
      var endPoint;
      var node;
      var parent;
      var siblings;
      var nodes;
      nodes = dom.select('td[data-mce-selected],th[data-mce-selected]');
      if (nodes.length > 0) {
        each$8(nodes, function (node) {
          callback([node]);
        });
        return;
      }
      var exclude = function (nodes) {
        var node;
        node = nodes[0];
        if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) {
          nodes.splice(0, 1);
        }
        node = nodes[nodes.length - 1];
        if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) {
          nodes.splice(nodes.length - 1, 1);
        }
        return nodes;
      };
      var collectSiblings = function (node, name, endNode) {
        var siblings = [];
        for (; node && node !== endNode; node = node[name]) {
          siblings.push(node);
        }
        return siblings;
      };
      var findEndPoint = function (node, root) {
        do {
          if (node.parentNode === root) {
            return node;
          }
          node = node.parentNode;
        } while (node);
      };
      var walkBoundary = function (startNode, endNode, next) {
        var siblingName = next ? 'nextSibling' : 'previousSibling';
        for (node = startNode, parent = node.parentNode; node && node !== endNode; node = parent) {
          parent = node.parentNode;
          siblings = collectSiblings(node === startNode ? node : node[siblingName], siblingName);
          if (siblings.length) {
            if (!next) {
              siblings.reverse();
            }
            callback(exclude(siblings));
          }
        }
      };
      if (startContainer.nodeType === 1 && startContainer.hasChildNodes()) {
        startContainer = startContainer.childNodes[startOffset];
      }
      if (endContainer.nodeType === 1 && endContainer.hasChildNodes()) {
        endContainer = getEndChild(endContainer, endOffset);
      }
      if (startContainer === endContainer) {
        return callback(exclude([startContainer]));
      }
      ancestor = dom.findCommonAncestor(startContainer, endContainer);
      for (node = startContainer; node; node = node.parentNode) {
        if (node === endContainer) {
          return walkBoundary(startContainer, ancestor, true);
        }
        if (node === ancestor) {
          break;
        }
      }
      for (node = endContainer; node; node = node.parentNode) {
        if (node === startContainer) {
          return walkBoundary(endContainer, ancestor);
        }
        if (node === ancestor) {
          break;
        }
      }
      startPoint = findEndPoint(startContainer, ancestor) || startContainer;
      endPoint = findEndPoint(endContainer, ancestor) || endContainer;
      walkBoundary(startContainer, startPoint, true);
      siblings = collectSiblings(startPoint === startContainer ? startPoint : startPoint.nextSibling, 'nextSibling', endPoint === endContainer ? endPoint.nextSibling : endPoint);
      if (siblings.length) {
        callback(exclude(siblings));
      }
      walkBoundary(endContainer, endPoint);
    };
    var RangeWalk = { walk: walk$1 };

    var zeroWidth = function () {
      return '\uFEFF';
    };

    function NodeValue (is, name) {
      var get = function (element) {
        if (!is(element)) {
          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
        }
        return getOption(element).getOr('');
      };
      var getOption = function (element) {
        return is(element) ? Option.from(element.dom().nodeValue) : Option.none();
      };
      var set = function (element, value) {
        if (!is(element)) {
          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
        }
        element.dom().nodeValue = value;
      };
      return {
        get: get,
        getOption: getOption,
        set: set
      };
    }

    var api = NodeValue(isText, 'text');
    var get$4 = function (element) {
      return api.get(element);
    };

    var isZeroWidth = function (elem) {
      return isText(elem) && get$4(elem) === zeroWidth();
    };
    var context = function (editor, elem, wrapName, nodeName) {
      return parent(elem).fold(function () {
        return 'skipping';
      }, function (parent) {
        if (nodeName === 'br' || isZeroWidth(elem)) {
          return 'valid';
        } else if (isAnnotation(elem)) {
          return 'existing';
        } else if (isCaretNode(elem)) {
          return 'caret';
        } else if (!FormatUtils.isValid(editor, wrapName, nodeName) || !FormatUtils.isValid(editor, name(parent), wrapName)) {
          return 'invalid-child';
        } else {
          return 'valid';
        }
      });
    };

    var shouldApplyToTrailingSpaces = function (rng) {
      return rng.startContainer.nodeType === 3 && rng.startContainer.nodeValue.length >= rng.startOffset && rng.startContainer.nodeValue[rng.startOffset] === '\xA0';
    };
    var applyWordGrab = function (editor, rng) {
      var r = ExpandRange.expandRng(editor, rng, [{ inline: true }], shouldApplyToTrailingSpaces(rng));
      rng.setStart(r.startContainer, r.startOffset);
      rng.setEnd(r.endContainer, r.endOffset);
      editor.selection.setRng(rng);
    };
    var makeAnnotation = function (eDoc, _a, annotationName, decorate) {
      var _b = _a.uid, uid = _b === void 0 ? generate('mce-annotation') : _b, data = __rest(_a, ['uid']);
      var master = Element.fromTag('span', eDoc);
      add$2(master, annotation());
      set(master, '' + dataAnnotationId(), uid);
      set(master, '' + dataAnnotation(), annotationName);
      var _c = decorate(uid, data), _d = _c.attributes, attributes = _d === void 0 ? {} : _d, _e = _c.classes, classes = _e === void 0 ? [] : _e;
      setAll(master, attributes);
      add$3(master, classes);
      return master;
    };
    var annotate = function (editor, rng, annotationName, decorate, data) {
      var newWrappers = [];
      var master = makeAnnotation(editor.getDoc(), data, annotationName, decorate);
      var wrapper = Cell(Option.none());
      var finishWrapper = function () {
        wrapper.set(Option.none());
      };
      var getOrOpenWrapper = function () {
        return wrapper.get().getOrThunk(function () {
          var nu = shallow(master);
          newWrappers.push(nu);
          wrapper.set(Option.some(nu));
          return nu;
        });
      };
      var processElements = function (elems) {
        each(elems, processElement);
      };
      var processElement = function (elem) {
        var ctx = context(editor, elem, 'span', name(elem));
        switch (ctx) {
        case 'invalid-child': {
            finishWrapper();
            var children$1 = children(elem);
            processElements(children$1);
            finishWrapper();
            break;
          }
        case 'valid': {
            var w = getOrOpenWrapper();
            wrap$1(elem, w);
            break;
          }
        case 'skipping':
        case 'existing':
        case 'caret':
        }
      };
      var processNodes = function (nodes) {
        var elems = map(nodes, Element.fromDom);
        processElements(elems);
      };
      RangeWalk.walk(editor.dom, rng, function (nodes) {
        finishWrapper();
        processNodes(nodes);
      });
      return newWrappers;
    };
    var annotateWithBookmark = function (editor, name, settings, data) {
      editor.undoManager.transact(function () {
        var initialRng = editor.selection.getRng();
        if (initialRng.collapsed) {
          applyWordGrab(editor, initialRng);
        }
        if (editor.selection.getRng().collapsed) {
          var wrapper = makeAnnotation(editor.getDoc(), data, name, settings.decorate);
          set$1(wrapper, '\xA0');
          editor.selection.getRng().insertNode(wrapper.dom());
          editor.selection.select(wrapper.dom());
        } else {
          var bookmark = GetBookmark.getPersistentBookmark(editor.selection, false);
          var rng = editor.selection.getRng();
          annotate(editor, rng, name, settings.decorate, data);
          editor.selection.moveToBookmark(bookmark);
        }
      });
    };

    function Annotator (editor) {
      var registry = create$1();
      setup$1(editor, registry);
      var changes = setup(editor);
      return {
        register: function (name, settings) {
          registry.register(name, settings);
        },
        annotate: function (name, data) {
          registry.lookup(name).each(function (settings) {
            annotateWithBookmark(editor, name, settings, data);
          });
        },
        annotationChanged: function (name, callback) {
          changes.addListener(name, callback);
        },
        remove: function (name) {
          identify(editor, Option.some(name)).each(function (_a) {
            var elements = _a.elements;
            each(elements, unwrap);
          });
        },
        getAll: function (name) {
          var directory = findAll(editor, name);
          return map$2(directory, function (elems) {
            return map(elems, function (elem) {
              return elem.dom();
            });
          });
        }
      };
    }

    var hasOnlyOneChild = function (node) {
      return node.firstChild && node.firstChild === node.lastChild;
    };
    var isPaddingNode = function (node) {
      return node.name === 'br' || node.value === '\xA0';
    };
    var isPaddedEmptyBlock = function (schema, node) {
      var blockElements = schema.getBlockElements();
      return blockElements[node.name] && hasOnlyOneChild(node) && isPaddingNode(node.firstChild);
    };
    var isEmptyFragmentElement = function (schema, node) {
      var nonEmptyElements = schema.getNonEmptyElements();
      return node && (node.isEmpty(nonEmptyElements) || isPaddedEmptyBlock(schema, node));
    };
    var isListFragment = function (schema, fragment) {
      var firstChild = fragment.firstChild;
      var lastChild = fragment.lastChild;
      if (firstChild && firstChild.name === 'meta') {
        firstChild = firstChild.next;
      }
      if (lastChild && lastChild.attr('id') === 'mce_marker') {
        lastChild = lastChild.prev;
      }
      if (isEmptyFragmentElement(schema, lastChild)) {
        lastChild = lastChild.prev;
      }
      if (!firstChild || firstChild !== lastChild) {
        return false;
      }
      return firstChild.name === 'ul' || firstChild.name === 'ol';
    };
    var cleanupDomFragment = function (domFragment) {
      var firstChild = domFragment.firstChild;
      var lastChild = domFragment.lastChild;
      if (firstChild && firstChild.nodeName === 'META') {
        firstChild.parentNode.removeChild(firstChild);
      }
      if (lastChild && lastChild.id === 'mce_marker') {
        lastChild.parentNode.removeChild(lastChild);
      }
      return domFragment;
    };
    var toDomFragment = function (dom, serializer, fragment) {
      var html = serializer.serialize(fragment);
      var domFragment = dom.createFragment(html);
      return cleanupDomFragment(domFragment);
    };
    var listItems$1 = function (elm) {
      return Tools.grep(elm.childNodes, function (child) {
        return child.nodeName === 'LI';
      });
    };
    var isPadding = function (node) {
      return node.data === '\xA0' || NodeType.isBr(node);
    };
    var isListItemPadded = function (node) {
      return node && node.firstChild && node.firstChild === node.lastChild && isPadding(node.firstChild);
    };
    var isEmptyOrPadded = function (elm) {
      return !elm.firstChild || isListItemPadded(elm);
    };
    var trimListItems = function (elms) {
      return elms.length > 0 && isEmptyOrPadded(elms[elms.length - 1]) ? elms.slice(0, -1) : elms;
    };
    var getParentLi = function (dom, node) {
      var parentBlock = dom.getParent(node, dom.isBlock);
      return parentBlock && parentBlock.nodeName === 'LI' ? parentBlock : null;
    };
    var isParentBlockLi = function (dom, node) {
      return !!getParentLi(dom, node);
    };
    var getSplit = function (parentNode, rng) {
      var beforeRng = rng.cloneRange();
      var afterRng = rng.cloneRange();
      beforeRng.setStartBefore(parentNode);
      afterRng.setEndAfter(parentNode);
      return [
        beforeRng.cloneContents(),
        afterRng.cloneContents()
      ];
    };
    var findFirstIn = function (node, rootNode) {
      var caretPos = CaretPosition$1.before(node);
      var caretWalker = CaretWalker(rootNode);
      var newCaretPos = caretWalker.next(caretPos);
      return newCaretPos ? newCaretPos.toRange() : null;
    };
    var findLastOf = function (node, rootNode) {
      var caretPos = CaretPosition$1.after(node);
      var caretWalker = CaretWalker(rootNode);
      var newCaretPos = caretWalker.prev(caretPos);
      return newCaretPos ? newCaretPos.toRange() : null;
    };
    var insertMiddle = function (target, elms, rootNode, rng) {
      var parts = getSplit(target, rng);
      var parentElm = target.parentNode;
      parentElm.insertBefore(parts[0], target);
      Tools.each(elms, function (li) {
        parentElm.insertBefore(li, target);
      });
      parentElm.insertBefore(parts[1], target);
      parentElm.removeChild(target);
      return findLastOf(elms[elms.length - 1], rootNode);
    };
    var insertBefore = function (target, elms, rootNode) {
      var parentElm = target.parentNode;
      Tools.each(elms, function (elm) {
        parentElm.insertBefore(elm, target);
      });
      return findFirstIn(target, rootNode);
    };
    var insertAfter = function (target, elms, rootNode, dom) {
      dom.insertAfter(elms.reverse(), target);
      return findLastOf(elms[0], rootNode);
    };
    var insertAtCaret = function (serializer, dom, rng, fragment) {
      var domFragment = toDomFragment(dom, serializer, fragment);
      var liTarget = getParentLi(dom, rng.startContainer);
      var liElms = trimListItems(listItems$1(domFragment.firstChild));
      var BEGINNING = 1, END = 2;
      var rootNode = dom.getRoot();
      var isAt = function (location) {
        var caretPos = CaretPosition$1.fromRangeStart(rng);
        var caretWalker = CaretWalker(dom.getRoot());
        var newPos = location === BEGINNING ? caretWalker.prev(caretPos) : caretWalker.next(caretPos);
        return newPos ? getParentLi(dom, newPos.getNode()) !== liTarget : true;
      };
      if (isAt(BEGINNING)) {
        return insertBefore(liTarget, liElms, rootNode);
      } else if (isAt(END)) {
        return insertAfter(liTarget, liElms, rootNode, dom);
      }
      return insertMiddle(liTarget, liElms, rootNode, rng);
    };
    var InsertList = {
      isListFragment: isListFragment,
      insertAtCaret: insertAtCaret,
      isParentBlockLi: isParentBlockLi,
      trimListItems: trimListItems,
      listItems: listItems$1
    };

    var each$9 = Tools.each;
    var ElementUtils = function (dom) {
      this.compare = function (node1, node2) {
        if (node1.nodeName !== node2.nodeName) {
          return false;
        }
        var getAttribs = function (node) {
          var attribs = {};
          each$9(dom.getAttribs(node), function (attr) {
            var name = attr.nodeName.toLowerCase();
            if (name.indexOf('_') !== 0 && name !== 'style' && name.indexOf('data-') !== 0) {
              attribs[name] = dom.getAttrib(node, name);
            }
          });
          return attribs;
        };
        var compareObjects = function (obj1, obj2) {
          var value, name;
          for (name in obj1) {
            if (obj1.hasOwnProperty(name)) {
              value = obj2[name];
              if (typeof value === 'undefined') {
                return false;
              }
              if (obj1[name] !== value) {
                return false;
              }
              delete obj2[name];
            }
          }
          for (name in obj2) {
            if (obj2.hasOwnProperty(name)) {
              return false;
            }
          }
          return true;
        };
        if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
          return false;
        }
        if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) {
          return false;
        }
        return !Bookmarks.isBookmarkNode(node1) && !Bookmarks.isBookmarkNode(node2);
      };
    };

    var getLastChildren = function (elm) {
      var children = [];
      var rawNode = elm.dom();
      while (rawNode) {
        children.push(Element.fromDom(rawNode));
        rawNode = rawNode.lastChild;
      }
      return children;
    };
    var removeTrailingBr = function (elm) {
      var allBrs = descendants$1(elm, 'br');
      var brs = filter(getLastChildren(elm).slice(-1), isBr);
      if (allBrs.length === brs.length) {
        each(brs, remove$1);
      }
    };
    var fillWithPaddingBr = function (elm) {
      empty(elm);
      append(elm, Element.fromHtml('<br data-mce-bogus="1">'));
    };
    var isPaddingContents = function (elm) {
      return isText(elm) ? get$4(elm) === '\xA0' : isBr(elm);
    };
    var isPaddedElement = function (elm) {
      return filter(children(elm), isPaddingContents).length === 1;
    };
    var trimBlockTrailingBr = function (elm) {
      lastChild(elm).each(function (lastChild) {
        prevSibling(lastChild).each(function (lastChildPrevSibling) {
          if (isBlock(elm) && isBr(lastChild) && isBlock(lastChildPrevSibling)) {
            remove$1(lastChild);
          }
        });
      });
    };
    var PaddingBr = {
      removeTrailingBr: removeTrailingBr,
      fillWithPaddingBr: fillWithPaddingBr,
      isPaddedElement: isPaddedElement,
      trimBlockTrailingBr: trimBlockTrailingBr
    };

    var makeMap$3 = Tools.makeMap;
    function Writer (settings) {
      var html = [];
      var indent, indentBefore, indentAfter, encode, htmlOutput;
      settings = settings || {};
      indent = settings.indent;
      indentBefore = makeMap$3(settings.indent_before || '');
      indentAfter = makeMap$3(settings.indent_after || '');
      encode = Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities);
      htmlOutput = settings.element_format === 'html';
      return {
        start: function (name, attrs, empty) {
          var i, l, attr, value;
          if (indent && indentBefore[name] && html.length > 0) {
            value = html[html.length - 1];
            if (value.length > 0 && value !== '\n') {
              html.push('\n');
            }
          }
          html.push('<', name);
          if (attrs) {
            for (i = 0, l = attrs.length; i < l; i++) {
              attr = attrs[i];
              html.push(' ', attr.name, '="', encode(attr.value, true), '"');
            }
          }
          if (!empty || htmlOutput) {
            html[html.length] = '>';
          } else {
            html[html.length] = ' />';
          }
          if (empty && indent && indentAfter[name] && html.length > 0) {
            value = html[html.length - 1];
            if (value.length > 0 && value !== '\n') {
              html.push('\n');
            }
          }
        },
        end: function (name) {
          var value;
          html.push('</', name, '>');
          if (indent && indentAfter[name] && html.length > 0) {
            value = html[html.length - 1];
            if (value.length > 0 && value !== '\n') {
              html.push('\n');
            }
          }
        },
        text: function (text, raw) {
          if (text.length > 0) {
            html[html.length] = raw ? text : encode(text);
          }
        },
        cdata: function (text) {
          html.push('<![CDATA[', text, ']]>');
        },
        comment: function (text) {
          html.push('<!--', text, '-->');
        },
        pi: function (name, text) {
          if (text) {
            html.push('<?', name, ' ', encode(text), '?>');
          } else {
            html.push('<?', name, '?>');
          }
          if (indent) {
            html.push('\n');
          }
        },
        doctype: function (text) {
          html.push('<!DOCTYPE', text, '>', indent ? '\n' : '');
        },
        reset: function () {
          html.length = 0;
        },
        getContent: function () {
          return html.join('').replace(/\n$/, '');
        }
      };
    }

    function HtmlSerializer (settings, schema) {
      if (schema === void 0) {
        schema = Schema();
      }
      var writer = Writer(settings);
      settings = settings || {};
      settings.validate = 'validate' in settings ? settings.validate : true;
      var serialize = function (node) {
        var handlers, validate;
        validate = settings.validate;
        handlers = {
          3: function (node) {
            writer.text(node.value, node.raw);
          },
          8: function (node) {
            writer.comment(node.value);
          },
          7: function (node) {
            writer.pi(node.name, node.value);
          },
          10: function (node) {
            writer.doctype(node.value);
          },
          4: function (node) {
            writer.cdata(node.value);
          },
          11: function (node) {
            if (node = node.firstChild) {
              do {
                walk(node);
              } while (node = node.next);
            }
          }
        };
        writer.reset();
        var walk = function (node) {
          var handler = handlers[node.type];
          var name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule;
          if (!handler) {
            name = node.name;
            isEmpty = node.shortEnded;
            attrs = node.attributes;
            if (validate && attrs && attrs.length > 1) {
              sortedAttrs = [];
              sortedAttrs.map = {};
              elementRule = schema.getElementRule(node.name);
              if (elementRule) {
                for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) {
                  attrName = elementRule.attributesOrder[i];
                  if (attrName in attrs.map) {
                    attrValue = attrs.map[attrName];
                    sortedAttrs.map[attrName] = attrValue;
                    sortedAttrs.push({
                      name: attrName,
                      value: attrValue
                    });
                  }
                }
                for (i = 0, l = attrs.length; i < l; i++) {
                  attrName = attrs[i].name;
                  if (!(attrName in sortedAttrs.map)) {
                    attrValue = attrs.map[attrName];
                    sortedAttrs.map[attrName] = attrValue;
                    sortedAttrs.push({
                      name: attrName,
                      value: attrValue
                    });
                  }
                }
                attrs = sortedAttrs;
              }
            }
            writer.start(node.name, attrs, isEmpty);
            if (!isEmpty) {
              if (node = node.firstChild) {
                do {
                  walk(node);
                } while (node = node.next);
              }
              writer.end(name);
            }
          } else {
            handler(node);
          }
        };
        if (node.type === 1 && !settings.inner) {
          walk(node);
        } else {
          handlers[11](node);
        }
        return writer.getContent();
      };
      return { serialize: serialize };
    }

    var createRange$1 = function (sc, so, ec, eo) {
      var rng = domGlobals.document.createRange();
      rng.setStart(sc, so);
      rng.setEnd(ec, eo);
      return rng;
    };
    var normalizeBlockSelectionRange = function (rng) {
      var startPos = CaretPosition$1.fromRangeStart(rng);
      var endPos = CaretPosition$1.fromRangeEnd(rng);
      var rootNode = rng.commonAncestorContainer;
      return CaretFinder.fromPosition(false, rootNode, endPos).map(function (newEndPos) {
        if (!isInSameBlock(startPos, endPos, rootNode) && isInSameBlock(startPos, newEndPos, rootNode)) {
          return createRange$1(startPos.container(), startPos.offset(), newEndPos.container(), newEndPos.offset());
        } else {
          return rng;
        }
      }).getOr(rng);
    };
    var normalize = function (rng) {
      return rng.collapsed ? rng : normalizeBlockSelectionRange(rng);
    };
    var RangeNormalizer = { normalize: normalize };

    var isAfterNbsp = function (container, offset) {
      return NodeType.isText(container) && container.nodeValue[offset - 1] === '\xA0';
    };
    var trimOrPadLeftRight = function (rng, html) {
      var container, offset;
      container = rng.startContainer;
      offset = rng.startOffset;
      var hasSiblingText = function (siblingName) {
        return container[siblingName] && container[siblingName].nodeType === 3;
      };
      if (container.nodeType === 3) {
        if (offset > 0) {
          html = html.replace(/^&nbsp;/, ' ');
        } else if (!hasSiblingText('previousSibling')) {
          html = html.replace(/^ /, '&nbsp;');
        }
        if (offset < container.length) {
          html = html.replace(/&nbsp;(<br>|)$/, ' ');
        } else if (!hasSiblingText('nextSibling')) {
          html = html.replace(/(&nbsp;| )(<br>|)$/, '&nbsp;');
        }
      }
      return html;
    };
    var trimNbspAfterDeleteAndPadValue = function (rng, value) {
      var container, offset;
      container = rng.startContainer;
      offset = rng.startOffset;
      if (container.nodeType === 3 && rng.collapsed) {
        if (container.data[offset] === '\xA0') {
          container.deleteData(offset, 1);
          if (!/[\u00a0| ]$/.test(value)) {
            value += ' ';
          }
        } else if (container.data[offset - 1] === '\xA0') {
          container.deleteData(offset - 1, 1);
          if (!/[\u00a0| ]$/.test(value)) {
            value = ' ' + value;
          }
        }
      }
      return value;
    };

    var isTableCell$2 = NodeType.matchNodeNames('td th');
    var selectionSetContent = function (editor, content) {
      var rng = editor.selection.getRng();
      var container = rng.startContainer;
      var offset = rng.startOffset;
      if (rng.collapsed && isAfterNbsp(container, offset) && NodeType.isText(container)) {
        container.insertData(offset - 1, ' ');
        container.deleteData(offset, 1);
        rng.setStart(container, offset);
        rng.setEnd(container, offset);
        editor.selection.setRng(rng);
      }
      editor.selection.setContent(content);
    };
    var validInsertion = function (editor, value, parentNode) {
      if (parentNode.getAttribute('data-mce-bogus') === 'all') {
        parentNode.parentNode.insertBefore(editor.dom.createFragment(value), parentNode);
      } else {
        var node = parentNode.firstChild;
        var node2 = parentNode.lastChild;
        if (!node || node === node2 && node.nodeName === 'BR') {
          editor.dom.setHTML(parentNode, value);
        } else {
          selectionSetContent(editor, value);
        }
      }
    };
    var trimBrsFromTableCell = function (dom, elm) {
      Option.from(dom.getParent(elm, 'td,th')).map(Element.fromDom).each(PaddingBr.trimBlockTrailingBr);
    };
    var reduceInlineTextElements = function (editor, merge) {
      var textInlineElements = editor.schema.getTextInlineElements();
      var dom = editor.dom;
      if (merge) {
        var root_1 = editor.getBody(), elementUtils_1 = new ElementUtils(dom);
        Tools.each(dom.select('*[data-mce-fragment]'), function (node) {
          for (var testNode = node.parentNode; testNode && testNode !== root_1; testNode = testNode.parentNode) {
            if (textInlineElements[node.nodeName.toLowerCase()] && elementUtils_1.compare(testNode, node)) {
              dom.remove(node, true);
            }
          }
        });
      }
    };
    var markFragmentElements = function (fragment) {
      var node = fragment;
      while (node = node.walk()) {
        if (node.type === 1) {
          node.attr('data-mce-fragment', '1');
        }
      }
    };
    var umarkFragmentElements = function (elm) {
      Tools.each(elm.getElementsByTagName('*'), function (elm) {
        elm.removeAttribute('data-mce-fragment');
      });
    };
    var isPartOfFragment = function (node) {
      return !!node.getAttribute('data-mce-fragment');
    };
    var canHaveChildren = function (editor, node) {
      return node && !editor.schema.getShortEndedElements()[node.nodeName];
    };
    var moveSelectionToMarker = function (editor, marker) {
      var parentEditableFalseElm, parentBlock, nextRng;
      var dom = editor.dom, selection = editor.selection;
      var node, node2;
      var getContentEditableFalseParent = function (node) {
        var root = editor.getBody();
        for (; node && node !== root; node = node.parentNode) {
          if (editor.dom.getContentEditable(node) === 'false') {
            return node;
          }
        }
        return null;
      };
      if (!marker) {
        return;
      }
      editor.selection.scrollIntoView(marker);
      parentEditableFalseElm = getContentEditableFalseParent(marker);
      if (parentEditableFalseElm) {
        dom.remove(marker);
        selection.select(parentEditableFalseElm);
        return;
      }
      var rng = dom.createRng();
      node = marker.previousSibling;
      if (node && node.nodeType === 3) {
        rng.setStart(node, node.nodeValue.length);
        if (!Env.ie) {
          node2 = marker.nextSibling;
          if (node2 && node2.nodeType === 3) {
            node.appendData(node2.data);
            node2.parentNode.removeChild(node2);
          }
        }
      } else {
        rng.setStartBefore(marker);
        rng.setEndBefore(marker);
      }
      var findNextCaretRng = function (rng) {
        var caretPos = CaretPosition$1.fromRangeStart(rng);
        var caretWalker = CaretWalker(editor.getBody());
        caretPos = caretWalker.next(caretPos);
        if (caretPos) {
          return caretPos.toRange();
        }
      };
      parentBlock = dom.getParent(marker, dom.isBlock);
      dom.remove(marker);
      if (parentBlock && dom.isEmpty(parentBlock)) {
        editor.$(parentBlock).empty();
        rng.setStart(parentBlock, 0);
        rng.setEnd(parentBlock, 0);
        if (!isTableCell$2(parentBlock) && !isPartOfFragment(parentBlock) && (nextRng = findNextCaretRng(rng))) {
          rng = nextRng;
          dom.remove(parentBlock);
        } else {
          dom.add(parentBlock, dom.create('br', { 'data-mce-bogus': '1' }));
        }
      }
      selection.setRng(rng);
    };
    var insertHtmlAtCaret = function (editor, value, details) {
      var parser, serializer, parentNode, rootNode, fragment, args;
      var marker, rng, node, bookmarkHtml, merge;
      var selection = editor.selection, dom = editor.dom;
      if (/^ | $/.test(value)) {
        value = trimOrPadLeftRight(selection.getRng(), value);
      }
      parser = editor.parser;
      merge = details.merge;
      serializer = HtmlSerializer({ validate: editor.settings.validate }, editor.schema);
      bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;&#x200B;</span>';
      args = {
        content: value,
        format: 'html',
        selection: true,
        paste: details.paste
      };
      args = editor.fire('BeforeSetContent', args);
      if (args.isDefaultPrevented()) {
        editor.fire('SetContent', {
          content: args.content,
          format: 'html',
          selection: true,
          paste: details.paste
        });
        return;
      }
      value = args.content;
      if (value.indexOf('{$caret}') === -1) {
        value += '{$caret}';
      }
      value = value.replace(/\{\$caret\}/, bookmarkHtml);
      rng = selection.getRng();
      var caretElement = rng.startContainer || (rng.parentElement ? rng.parentElement() : null);
      var body = editor.getBody();
      if (caretElement === body && selection.isCollapsed()) {
        if (dom.isBlock(body.firstChild) && canHaveChildren(editor, body.firstChild) && dom.isEmpty(body.firstChild)) {
          rng = dom.createRng();
          rng.setStart(body.firstChild, 0);
          rng.setEnd(body.firstChild, 0);
          selection.setRng(rng);
        }
      }
      if (!selection.isCollapsed()) {
        editor.selection.setRng(RangeNormalizer.normalize(editor.selection.getRng()));
        editor.getDoc().execCommand('Delete', false, null);
        value = trimNbspAfterDeleteAndPadValue(editor.selection.getRng(), value);
      }
      parentNode = selection.getNode();
      var parserArgs = {
        context: parentNode.nodeName.toLowerCase(),
        data: details.data,
        insert: true
      };
      fragment = parser.parse(value, parserArgs);
      if (details.paste === true && InsertList.isListFragment(editor.schema, fragment) && InsertList.isParentBlockLi(dom, parentNode)) {
        rng = InsertList.insertAtCaret(serializer, dom, editor.selection.getRng(), fragment);
        editor.selection.setRng(rng);
        editor.fire('SetContent', args);
        return;
      }
      markFragmentElements(fragment);
      node = fragment.lastChild;
      if (node.attr('id') === 'mce_marker') {
        marker = node;
        for (node = node.prev; node; node = node.walk(true)) {
          if (node.type === 3 || !dom.isBlock(node.name)) {
            if (editor.schema.isValidChild(node.parent.name, 'span')) {
              node.parent.insert(marker, node, node.name === 'br');
            }
            break;
          }
        }
      }
      editor._selectionOverrides.showBlockCaretContainer(parentNode);
      if (!parserArgs.invalid) {
        value = serializer.serialize(fragment);
        validInsertion(editor, value, parentNode);
      } else {
        selectionSetContent(editor, bookmarkHtml);
        parentNode = selection.getNode();
        rootNode = editor.getBody();
        if (parentNode.nodeType === 9) {
          parentNode = node = rootNode;
        } else {
          node = parentNode;
        }
        while (node !== rootNode) {
          parentNode = node;
          node = node.parentNode;
        }
        value = parentNode === rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode);
        value = serializer.serialize(parser.parse(value.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i, function () {
          return serializer.serialize(fragment);
        })));
        if (parentNode === rootNode) {
          dom.setHTML(rootNode, value);
        } else {
          dom.setOuterHTML(parentNode, value);
        }
      }
      reduceInlineTextElements(editor, merge);
      moveSelectionToMarker(editor, dom.get('mce_marker'));
      umarkFragmentElements(editor.getBody());
      trimBrsFromTableCell(editor.dom, editor.selection.getStart());
      editor.fire('SetContent', args);
      editor.addVisual();
    };
    var processValue = function (value) {
      var details;
      if (typeof value !== 'string') {
        details = Tools.extend({
          paste: value.paste,
          data: { paste: value.paste }
        }, value);
        return {
          content: value.content,
          details: details
        };
      }
      return {
        content: value,
        details: {}
      };
    };
    var insertAtCaret$1 = function (editor, value) {
      var result = processValue(value);
      insertHtmlAtCaret(editor, result.content, result.details);
    };
    var InsertContent = { insertAtCaret: insertAtCaret$1 };

    var strongRtl = /[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/;
    var hasStrongRtl = function (text) {
      return strongRtl.test(text);
    };

    var getBodySetting = function (editor, name, defaultValue) {
      var value = editor.getParam(name, defaultValue);
      if (value.indexOf('=') !== -1) {
        var bodyObj = editor.getParam(name, '', 'hash');
        return bodyObj.hasOwnProperty(editor.id) ? bodyObj[editor.id] : defaultValue;
      } else {
        return value;
      }
    };
    var getIframeAttrs = function (editor) {
      return editor.getParam('iframe_attrs', {});
    };
    var getDocType = function (editor) {
      return editor.getParam('doctype', '<!DOCTYPE html>');
    };
    var getDocumentBaseUrl = function (editor) {
      return editor.getParam('document_base_url', '');
    };
    var getBodyId = function (editor) {
      return getBodySetting(editor, 'body_id', 'tinymce');
    };
    var getBodyClass = function (editor) {
      return getBodySetting(editor, 'body_class', '');
    };
    var getContentSecurityPolicy = function (editor) {
      return editor.getParam('content_security_policy', '');
    };
    var shouldPutBrInPre = function (editor) {
      return editor.getParam('br_in_pre', true);
    };
    var getForcedRootBlock = function (editor) {
      if (editor.getParam('force_p_newlines', false)) {
        return 'p';
      }
      var block = editor.getParam('forced_root_block', 'p');
      return block === false ? '' : block;
    };
    var getForcedRootBlockAttrs = function (editor) {
      return editor.getParam('forced_root_block_attrs', {});
    };
    var getBrNewLineSelector = function (editor) {
      return editor.getParam('br_newline_selector', '.mce-toc h2,figcaption,caption');
    };
    var getNoNewLineSelector = function (editor) {
      return editor.getParam('no_newline_selector', '');
    };
    var shouldKeepStyles = function (editor) {
      return editor.getParam('keep_styles', true);
    };
    var shouldEndContainerOnEmptyBlock = function (editor) {
      return editor.getParam('end_container_on_empty_block', false);
    };
    var getFontStyleValues = function (editor) {
      return Tools.explode(editor.getParam('font_size_style_values', ''));
    };
    var getFontSizeClasses = function (editor) {
      return Tools.explode(editor.getParam('font_size_classes', ''));
    };
    var getImagesDataImgFilter = function (editor) {
      return editor.getParam('images_dataimg_filter', constant(true), 'function');
    };
    var isAutomaticUploadsEnabled = function (editor) {
      return editor.getParam('automatic_uploads', true, 'boolean');
    };
    var shouldReuseFileName = function (editor) {
      return editor.getParam('images_reuse_filename', false, 'boolean');
    };
    var shouldReplaceBlobUris = function (editor) {
      return editor.getParam('images_replace_blob_uris', true, 'boolean');
    };
    var getImageUploadUrl = function (editor) {
      return editor.getParam('images_upload_url', '', 'string');
    };
    var getImageUploadBasePath = function (editor) {
      return editor.getParam('images_upload_base_path', '', 'string');
    };
    var getImagesUploadCredentials = function (editor) {
      return editor.getParam('images_upload_credentials', false, 'boolean');
    };
    var getImagesUploadHandler = function (editor) {
      return editor.getParam('images_upload_handler', null, 'function');
    };
    var shouldUseContentCssCors = function (editor) {
      return editor.getParam('content_css_cors', false, 'boolean');
    };
    var getInlineBoundarySelector = function (editor) {
      return editor.getParam('inline_boundaries_selector', 'a[href],code,.mce-annotation', 'string');
    };
    var Settings = {
      getIframeAttrs: getIframeAttrs,
      getDocType: getDocType,
      getDocumentBaseUrl: getDocumentBaseUrl,
      getBodyId: getBodyId,
      getBodyClass: getBodyClass,
      getContentSecurityPolicy: getContentSecurityPolicy,
      shouldPutBrInPre: shouldPutBrInPre,
      getForcedRootBlock: getForcedRootBlock,
      getForcedRootBlockAttrs: getForcedRootBlockAttrs,
      getBrNewLineSelector: getBrNewLineSelector,
      getNoNewLineSelector: getNoNewLineSelector,
      shouldKeepStyles: shouldKeepStyles,
      shouldEndContainerOnEmptyBlock: shouldEndContainerOnEmptyBlock,
      getFontStyleValues: getFontStyleValues,
      getFontSizeClasses: getFontSizeClasses,
      getImagesDataImgFilter: getImagesDataImgFilter,
      isAutomaticUploadsEnabled: isAutomaticUploadsEnabled,
      shouldReuseFileName: shouldReuseFileName,
      shouldReplaceBlobUris: shouldReplaceBlobUris,
      getImageUploadUrl: getImageUploadUrl,
      getImageUploadBasePath: getImageUploadBasePath,
      getImagesUploadCredentials: getImagesUploadCredentials,
      getImagesUploadHandler: getImagesUploadHandler,
      shouldUseContentCssCors: shouldUseContentCssCors,
      getInlineBoundarySelector: getInlineBoundarySelector
    };

    var isInlineTarget = function (editor, elm) {
      return is$1(Element.fromDom(elm), Settings.getInlineBoundarySelector(editor));
    };
    var isRtl = function (element) {
      return DOMUtils$1.DOM.getStyle(element, 'direction', true) === 'rtl' || hasStrongRtl(element.textContent);
    };
    var findInlineParents = function (isInlineTarget, rootNode, pos) {
      return filter(DOMUtils$1.DOM.getParents(pos.container(), '*', rootNode), isInlineTarget);
    };
    var findRootInline = function (isInlineTarget, rootNode, pos) {
      var parents = findInlineParents(isInlineTarget, rootNode, pos);
      return Option.from(parents[parents.length - 1]);
    };
    var hasSameParentBlock = function (rootNode, node1, node2) {
      var block1 = getParentBlock(node1, rootNode);
      var block2 = getParentBlock(node2, rootNode);
      return block1 && block1 === block2;
    };
    var isAtZwsp = function (pos) {
      return isBeforeInline(pos) || isAfterInline(pos);
    };
    var normalizePosition = function (forward, pos) {
      if (!pos) {
        return pos;
      }
      var container = pos.container(), offset = pos.offset();
      if (forward) {
        if (isCaretContainerInline(container)) {
          if (NodeType.isText(container.nextSibling)) {
            return CaretPosition$1(container.nextSibling, 0);
          } else {
            return CaretPosition$1.after(container);
          }
        } else {
          return isBeforeInline(pos) ? CaretPosition$1(container, offset + 1) : pos;
        }
      } else {
        if (isCaretContainerInline(container)) {
          if (NodeType.isText(container.previousSibling)) {
            return CaretPosition$1(container.previousSibling, container.previousSibling.data.length);
          } else {
            return CaretPosition$1.before(container);
          }
        } else {
          return isAfterInline(pos) ? CaretPosition$1(container, offset - 1) : pos;
        }
      }
    };
    var normalizeForwards = curry(normalizePosition, true);
    var normalizeBackwards = curry(normalizePosition, false);
    var InlineUtils = {
      isInlineTarget: isInlineTarget,
      findRootInline: findRootInline,
      isRtl: isRtl,
      isAtZwsp: isAtZwsp,
      normalizePosition: normalizePosition,
      normalizeForwards: normalizeForwards,
      normalizeBackwards: normalizeBackwards,
      hasSameParentBlock: hasSameParentBlock
    };

    var isBeforeRoot = function (rootNode) {
      return function (elm) {
        return eq(rootNode, Element.fromDom(elm.dom().parentNode));
      };
    };
    var getParentBlock$1 = function (rootNode, elm) {
      return contains$3(rootNode, elm) ? closest(elm, function (element) {
        return isTextBlock(element) || isListItem(element);
      }, isBeforeRoot(rootNode)) : Option.none();
    };
    var placeCaretInEmptyBody = function (editor) {
      var body = editor.getBody();
      var node = body.firstChild && editor.dom.isBlock(body.firstChild) ? body.firstChild : body;
      editor.selection.setCursorLocation(node, 0);
    };
    var paddEmptyBody = function (editor) {
      if (editor.dom.isEmpty(editor.getBody())) {
        editor.setContent('');
        placeCaretInEmptyBody(editor);
      }
    };
    var willDeleteLastPositionInElement = function (forward, fromPos, elm) {
      return lift2(CaretFinder.firstPositionIn(elm), CaretFinder.lastPositionIn(elm), function (firstPos, lastPos) {
        var normalizedFirstPos = InlineUtils.normalizePosition(true, firstPos);
        var normalizedLastPos = InlineUtils.normalizePosition(false, lastPos);
        var normalizedFromPos = InlineUtils.normalizePosition(false, fromPos);
        if (forward) {
          return CaretFinder.nextPosition(elm, normalizedFromPos).map(function (nextPos) {
            return nextPos.isEqual(normalizedLastPos) && fromPos.isEqual(normalizedFirstPos);
          }).getOr(false);
        } else {
          return CaretFinder.prevPosition(elm, normalizedFromPos).map(function (prevPos) {
            return prevPos.isEqual(normalizedFirstPos) && fromPos.isEqual(normalizedLastPos);
          }).getOr(false);
        }
      }).getOr(true);
    };
    var DeleteUtils = {
      getParentBlock: getParentBlock$1,
      paddEmptyBody: paddEmptyBody,
      willDeleteLastPositionInElement: willDeleteLastPositionInElement
    };

    var ancestor$2 = function (scope, selector, isRoot) {
      return ancestor$1(scope, selector, isRoot).isSome();
    };

    var hasWhitespacePreserveParent = function (rootNode, node) {
      var rootElement = Element.fromDom(rootNode);
      var startNode = Element.fromDom(node);
      return ancestor$2(startNode, 'pre,code', curry(eq, rootElement));
    };
    var isWhitespace = function (rootNode, node) {
      return NodeType.isText(node) && /^[ \t\r\n]*$/.test(node.data) && hasWhitespacePreserveParent(rootNode, node) === false;
    };
    var isNamedAnchor = function (node) {
      return NodeType.isElement(node) && node.nodeName === 'A' && node.hasAttribute('name');
    };
    var isContent = function (rootNode, node) {
      return isCaretCandidate(node) && isWhitespace(rootNode, node) === false || isNamedAnchor(node) || isBookmark(node);
    };
    var isBookmark = NodeType.hasAttribute('data-mce-bookmark');
    var isBogus$2 = NodeType.hasAttribute('data-mce-bogus');
    var isBogusAll$1 = NodeType.hasAttributeValue('data-mce-bogus', 'all');
    var isEmptyNode = function (targetNode) {
      var walker, node, brCount = 0;
      if (isContent(targetNode, targetNode)) {
        return false;
      } else {
        node = targetNode.firstChild;
        if (!node) {
          return true;
        }
        walker = new TreeWalker(node, targetNode);
        do {
          if (isBogusAll$1(node)) {
            node = walker.next(true);
            continue;
          }
          if (isBogus$2(node)) {
            node = walker.next();
            continue;
          }
          if (NodeType.isBr(node)) {
            brCount++;
            node = walker.next();
            continue;
          }
          if (isContent(targetNode, node)) {
            return false;
          }
          node = walker.next();
        } while (node);
        return brCount <= 1;
      }
    };
    var isEmpty$1 = function (elm) {
      return isEmptyNode(elm.dom());
    };
    var Empty = { isEmpty: isEmpty$1 };

    var BlockPosition = Immutable('block', 'position');
    var BlockBoundary = Immutable('from', 'to');
    var getBlockPosition = function (rootNode, pos) {
      var rootElm = Element.fromDom(rootNode);
      var containerElm = Element.fromDom(pos.container());
      return DeleteUtils.getParentBlock(rootElm, containerElm).map(function (block) {
        return BlockPosition(block, pos);
      });
    };
    var isDifferentBlocks = function (blockBoundary) {
      return eq(blockBoundary.from().block(), blockBoundary.to().block()) === false;
    };
    var hasSameParent = function (blockBoundary) {
      return parent(blockBoundary.from().block()).bind(function (parent1) {
        return parent(blockBoundary.to().block()).filter(function (parent2) {
          return eq(parent1, parent2);
        });
      }).isSome();
    };
    var isEditable = function (blockBoundary) {
      return NodeType.isContentEditableFalse(blockBoundary.from().block().dom()) === false && NodeType.isContentEditableFalse(blockBoundary.to().block().dom()) === false;
    };
    var skipLastBr = function (rootNode, forward, blockPosition) {
      if (NodeType.isBr(blockPosition.position().getNode()) && Empty.isEmpty(blockPosition.block()) === false) {
        return CaretFinder.positionIn(false, blockPosition.block().dom()).bind(function (lastPositionInBlock) {
          if (lastPositionInBlock.isEqual(blockPosition.position())) {
            return CaretFinder.fromPosition(forward, rootNode, lastPositionInBlock).bind(function (to) {
              return getBlockPosition(rootNode, to);
            });
          } else {
            return Option.some(blockPosition);
          }
        }).getOr(blockPosition);
      } else {
        return blockPosition;
      }
    };
    var readFromRange = function (rootNode, forward, rng) {
      var fromBlockPos = getBlockPosition(rootNode, CaretPosition$1.fromRangeStart(rng));
      var toBlockPos = fromBlockPos.bind(function (blockPos) {
        return CaretFinder.fromPosition(forward, rootNode, blockPos.position()).bind(function (to) {
          return getBlockPosition(rootNode, to).map(function (blockPos) {
            return skipLastBr(rootNode, forward, blockPos);
          });
        });
      });
      return lift2(fromBlockPos, toBlockPos, BlockBoundary).filter(function (blockBoundary) {
        return isDifferentBlocks(blockBoundary) && hasSameParent(blockBoundary) && isEditable(blockBoundary);
      });
    };
    var read$1 = function (rootNode, forward, rng) {
      return rng.collapsed ? readFromRange(rootNode, forward, rng) : Option.none();
    };
    var BlockMergeBoundary = { read: read$1 };

    var dropLast = function (xs) {
      return xs.slice(0, -1);
    };
    var parentsUntil$1 = function (start, root, predicate) {
      if (contains$3(root, start)) {
        return dropLast(parents(start, function (elm) {
          return predicate(elm) || eq(elm, root);
        }));
      } else {
        return [];
      }
    };
    var parents$1 = function (start, root) {
      return parentsUntil$1(start, root, constant(false));
    };
    var parentsAndSelf = function (start, root) {
      return [start].concat(parents$1(start, root));
    };
    var Parents = {
      parentsUntil: parentsUntil$1,
      parents: parents$1,
      parentsAndSelf: parentsAndSelf
    };

    var getChildrenUntilBlockBoundary = function (block) {
      var children$1 = children(block);
      return findIndex(children$1, isBlock).fold(function () {
        return children$1;
      }, function (index) {
        return children$1.slice(0, index);
      });
    };
    var extractChildren = function (block) {
      var children = getChildrenUntilBlockBoundary(block);
      each(children, remove$1);
      return children;
    };
    var removeEmptyRoot = function (rootNode, block) {
      var parents = Parents.parentsAndSelf(block, rootNode);
      return find(parents.reverse(), Empty.isEmpty).each(remove$1);
    };
    var isEmptyBefore = function (el) {
      return filter(prevSiblings(el), function (el) {
        return !Empty.isEmpty(el);
      }).length === 0;
    };
    var nestedBlockMerge = function (rootNode, fromBlock, toBlock, insertionPoint) {
      if (Empty.isEmpty(toBlock)) {
        PaddingBr.fillWithPaddingBr(toBlock);
        return CaretFinder.firstPositionIn(toBlock.dom());
      }
      if (isEmptyBefore(insertionPoint) && Empty.isEmpty(fromBlock)) {
        before(insertionPoint, Element.fromTag('br'));
      }
      var position = CaretFinder.prevPosition(toBlock.dom(), CaretPosition$1.before(insertionPoint.dom()));
      each(extractChildren(fromBlock), function (child) {
        before(insertionPoint, child);
      });
      removeEmptyRoot(rootNode, fromBlock);
      return position;
    };
    var sidelongBlockMerge = function (rootNode, fromBlock, toBlock) {
      if (Empty.isEmpty(toBlock)) {
        remove$1(toBlock);
        if (Empty.isEmpty(fromBlock)) {
          PaddingBr.fillWithPaddingBr(fromBlock);
        }
        return CaretFinder.firstPositionIn(fromBlock.dom());
      }
      var position = CaretFinder.lastPositionIn(toBlock.dom());
      each(extractChildren(fromBlock), function (child) {
        append(toBlock, child);
      });
      removeEmptyRoot(rootNode, fromBlock);
      return position;
    };
    var findInsertionPoint = function (toBlock, block) {
      var parentsAndSelf = Parents.parentsAndSelf(block, toBlock);
      return Option.from(parentsAndSelf[parentsAndSelf.length - 1]);
    };
    var getInsertionPoint = function (fromBlock, toBlock) {
      return contains$3(toBlock, fromBlock) ? findInsertionPoint(toBlock, fromBlock) : Option.none();
    };
    var trimBr = function (first, block) {
      CaretFinder.positionIn(first, block.dom()).map(function (position) {
        return position.getNode();
      }).map(Element.fromDom).filter(isBr).each(remove$1);
    };
    var mergeBlockInto = function (rootNode, fromBlock, toBlock) {
      trimBr(true, fromBlock);
      trimBr(false, toBlock);
      return getInsertionPoint(fromBlock, toBlock).fold(curry(sidelongBlockMerge, rootNode, fromBlock, toBlock), curry(nestedBlockMerge, rootNode, fromBlock, toBlock));
    };
    var mergeBlocks = function (rootNode, forward, block1, block2) {
      return forward ? mergeBlockInto(rootNode, block2, block1) : mergeBlockInto(rootNode, block1, block2);
    };
    var MergeBlocks = { mergeBlocks: mergeBlocks };

    var backspaceDelete = function (editor, forward) {
      var position;
      var rootNode = Element.fromDom(editor.getBody());
      position = BlockMergeBoundary.read(rootNode.dom(), forward, editor.selection.getRng()).bind(function (blockBoundary) {
        return MergeBlocks.mergeBlocks(rootNode, forward, blockBoundary.from().block(), blockBoundary.to().block());
      });
      position.each(function (pos) {
        editor.selection.setRng(pos.toRange());
      });
      return position.isSome();
    };
    var BlockBoundaryDelete = { backspaceDelete: backspaceDelete };

    var deleteRangeMergeBlocks = function (rootNode, selection) {
      var rng = selection.getRng();
      return lift2(DeleteUtils.getParentBlock(rootNode, Element.fromDom(rng.startContainer)), DeleteUtils.getParentBlock(rootNode, Element.fromDom(rng.endContainer)), function (block1, block2) {
        if (eq(block1, block2) === false) {
          rng.deleteContents();
          MergeBlocks.mergeBlocks(rootNode, true, block1, block2).each(function (pos) {
            selection.setRng(pos.toRange());
          });
          return true;
        } else {
          return false;
        }
      }).getOr(false);
    };
    var isRawNodeInTable = function (root, rawNode) {
      var node = Element.fromDom(rawNode);
      var isRoot = curry(eq, root);
      return ancestor(node, isTableCell, isRoot).isSome();
    };
    var isSelectionInTable = function (root, rng) {
      return isRawNodeInTable(root, rng.startContainer) || isRawNodeInTable(root, rng.endContainer);
    };
    var isEverythingSelected = function (root, rng) {
      var noPrevious = CaretFinder.prevPosition(root.dom(), CaretPosition$1.fromRangeStart(rng)).isNone();
      var noNext = CaretFinder.nextPosition(root.dom(), CaretPosition$1.fromRangeEnd(rng)).isNone();
      return !isSelectionInTable(root, rng) && noPrevious && noNext;
    };
    var emptyEditor = function (editor) {
      editor.setContent('');
      editor.selection.setCursorLocation();
      return true;
    };
    var deleteRange = function (editor) {
      var rootNode = Element.fromDom(editor.getBody());
      var rng = editor.selection.getRng();
      return isEverythingSelected(rootNode, rng) ? emptyEditor(editor) : deleteRangeMergeBlocks(rootNode, editor.selection);
    };
    var backspaceDelete$1 = function (editor, forward) {
      return editor.selection.isCollapsed() ? false : deleteRange(editor);
    };
    var BlockRangeDelete = { backspaceDelete: backspaceDelete$1 };

    var generate$1 = function (cases) {
      if (!isArray(cases)) {
        throw new Error('cases must be an array');
      }
      if (cases.length === 0) {
        throw new Error('there must be at least one case');
      }
      var constructors = [];
      var adt = {};
      each(cases, function (acase, count) {
        var keys$1 = keys(acase);
        if (keys$1.length !== 1) {
          throw new Error('one and only one name per case');
        }
        var key = keys$1[0];
        var value = acase[key];
        if (adt[key] !== undefined) {
          throw new Error('duplicate key detected:' + key);
        } else if (key === 'cata') {
          throw new Error('cannot have a case named cata (sorry)');
        } else if (!isArray(value)) {
          throw new Error('case arguments must be an array');
        }
        constructors.push(key);
        adt[key] = function () {
          var argLength = arguments.length;
          if (argLength !== value.length) {
            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
          }
          var args = new Array(argLength);
          for (var i = 0; i < args.length; i++) {
            args[i] = arguments[i];
          }
          var match = function (branches) {
            var branchKeys = keys(branches);
            if (constructors.length !== branchKeys.length) {
              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
            }
            var allReqd = forall(constructors, function (reqKey) {
              return contains(branchKeys, reqKey);
            });
            if (!allReqd) {
              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
            }
            return branches[key].apply(null, args);
          };
          return {
            fold: function () {
              if (arguments.length !== cases.length) {
                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + arguments.length);
              }
              var target = arguments[count];
              return target.apply(null, args);
            },
            match: match,
            log: function (label) {
              domGlobals.console.log(label, {
                constructors: constructors,
                constructor: key,
                params: args
              });
            }
          };
        };
      });
      return adt;
    };
    var Adt = { generate: generate$1 };

    var isBr$5 = function (pos) {
      return getElementFromPosition(pos).exists(isBr);
    };
    var findBr = function (forward, root, pos) {
      var parentBlocks = filter(Parents.parentsAndSelf(Element.fromDom(pos.container()), root), isBlock);
      var scope = head(parentBlocks).getOr(root);
      return CaretFinder.fromPosition(forward, scope.dom(), pos).filter(isBr$5);
    };
    var isBeforeBr = function (root, pos) {
      return getElementFromPosition(pos).exists(isBr) || findBr(true, root, pos).isSome();
    };
    var isAfterBr = function (root, pos) {
      return getElementFromPrevPosition(pos).exists(isBr) || findBr(false, root, pos).isSome();
    };
    var findPreviousBr = curry(findBr, false);
    var findNextBr = curry(findBr, true);

    var is$2 = function (expected) {
      return function (actual) {
        return expected === actual;
      };
    };
    var isNbsp = is$2('\xA0');
    var isWhiteSpace$1 = function (chr) {
      return /^[\r\n\t ]$/.test(chr);
    };
    var isContent$1 = function (chr) {
      return !isWhiteSpace$1(chr) && !isNbsp(chr);
    };

    var isChar = function (forward, predicate, pos) {
      return Option.from(pos.container()).filter(NodeType.isText).exists(function (text) {
        var delta = forward ? 0 : -1;
        return predicate(text.data.charAt(pos.offset() + delta));
      });
    };
    var isBeforeSpace = curry(isChar, true, isWhiteSpace$1);
    var isAfterSpace = curry(isChar, false, isWhiteSpace$1);
    var isEmptyText = function (pos) {
      var container = pos.container();
      return NodeType.isText(container) && container.data.length === 0;
    };
    var isNextToContentEditableFalse = function (relativeOffset, caretPosition) {
      var node = getChildNodeAtRelativeOffset(relativeOffset, caretPosition);
      return NodeType.isContentEditableFalse(node) && !NodeType.isBogusAll(node);
    };
    var isBeforeContentEditableFalse = curry(isNextToContentEditableFalse, 0);
    var isAfterContentEditableFalse = curry(isNextToContentEditableFalse, -1);
    var isNextToTable = function (relativeOffset, caretPosition) {
      return NodeType.isTable(getChildNodeAtRelativeOffset(relativeOffset, caretPosition));
    };
    var isBeforeTable = curry(isNextToTable, 0);
    var isAfterTable = curry(isNextToTable, -1);

    var isCompoundElement = function (node) {
      return isTableCell(Element.fromDom(node)) || isListItem(Element.fromDom(node));
    };
    var DeleteAction = Adt.generate([
      { remove: ['element'] },
      { moveToElement: ['element'] },
      { moveToPosition: ['position'] }
    ]);
    var isAtContentEditableBlockCaret = function (forward, from) {
      var elm = from.getNode(forward === false);
      var caretLocation = forward ? 'after' : 'before';
      return NodeType.isElement(elm) && elm.getAttribute('data-mce-caret') === caretLocation;
    };
    var isDeleteFromCefDifferentBlocks = function (root, forward, from, to) {
      var inSameBlock = function (elm) {
        return isInline(Element.fromDom(elm)) && !isInSameBlock(from, to, root);
      };
      return getRelativeCefElm(!forward, from).fold(function () {
        return getRelativeCefElm(forward, to).fold(constant(false), inSameBlock);
      }, inSameBlock);
    };
    var deleteEmptyBlockOrMoveToCef = function (root, forward, from, to) {
      var toCefElm = to.getNode(forward === false);
      return DeleteUtils.getParentBlock(Element.fromDom(root), Element.fromDom(from.getNode())).map(function (blockElm) {
        return Empty.isEmpty(blockElm) ? DeleteAction.remove(blockElm.dom()) : DeleteAction.moveToElement(toCefElm);
      }).orThunk(function () {
        return Option.some(DeleteAction.moveToElement(toCefElm));
      });
    };
    var findCefPosition = function (root, forward, from) {
      return CaretFinder.fromPosition(forward, root, from).bind(function (to) {
        if (isCompoundElement(to.getNode())) {
          return Option.none();
        } else if (isDeleteFromCefDifferentBlocks(root, forward, from, to)) {
          return Option.none();
        } else if (forward && NodeType.isContentEditableFalse(to.getNode())) {
          return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
        } else if (forward === false && NodeType.isContentEditableFalse(to.getNode(true))) {
          return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
        } else if (forward && isAfterContentEditableFalse(from)) {
          return Option.some(DeleteAction.moveToPosition(to));
        } else if (forward === false && isBeforeContentEditableFalse(from)) {
          return Option.some(DeleteAction.moveToPosition(to));
        } else {
          return Option.none();
        }
      });
    };
    var getContentEditableBlockAction = function (forward, elm) {
      if (forward && NodeType.isContentEditableFalse(elm.nextSibling)) {
        return Option.some(DeleteAction.moveToElement(elm.nextSibling));
      } else if (forward === false && NodeType.isContentEditableFalse(elm.previousSibling)) {
        return Option.some(DeleteAction.moveToElement(elm.previousSibling));
      } else {
        return Option.none();
      }
    };
    var skipMoveToActionFromInlineCefToContent = function (root, from, deleteAction) {
      return deleteAction.fold(function (elm) {
        return Option.some(DeleteAction.remove(elm));
      }, function (elm) {
        return Option.some(DeleteAction.moveToElement(elm));
      }, function (to) {
        if (isInSameBlock(from, to, root)) {
          return Option.none();
        } else {
          return Option.some(DeleteAction.moveToPosition(to));
        }
      });
    };
    var getContentEditableAction = function (root, forward, from) {
      if (isAtContentEditableBlockCaret(forward, from)) {
        return getContentEditableBlockAction(forward, from.getNode(forward === false)).fold(function () {
          return findCefPosition(root, forward, from);
        }, Option.some);
      } else {
        return findCefPosition(root, forward, from).bind(function (deleteAction) {
          return skipMoveToActionFromInlineCefToContent(root, from, deleteAction);
        });
      }
    };
    var read$2 = function (root, forward, rng) {
      var normalizedRange = normalizeRange(forward ? 1 : -1, root, rng);
      var from = CaretPosition$1.fromRangeStart(normalizedRange);
      var rootElement = Element.fromDom(root);
      if (forward === false && isAfterContentEditableFalse(from)) {
        return Option.some(DeleteAction.remove(from.getNode(true)));
      } else if (forward && isBeforeContentEditableFalse(from)) {
        return Option.some(DeleteAction.remove(from.getNode()));
      } else if (forward === false && isBeforeContentEditableFalse(from) && isAfterBr(rootElement, from)) {
        return findPreviousBr(rootElement, from).map(function (br) {
          return DeleteAction.remove(br.getNode());
        });
      } else if (forward && isAfterContentEditableFalse(from) && isBeforeBr(rootElement, from)) {
        return findNextBr(rootElement, from).map(function (br) {
          return DeleteAction.remove(br.getNode());
        });
      } else {
        return getContentEditableAction(root, forward, from);
      }
    };

    var isCollapsibleWhitespace = function (c) {
      return ' \f\n\r\t\x0B'.indexOf(c) !== -1;
    };
    var normalizeContent = function (content, isStartOfContent, isEndOfContent) {
      var result = foldl(content.split(''), function (acc, c) {
        if (isCollapsibleWhitespace(c) || c === '\xA0') {
          if (acc.previousCharIsSpace || acc.str === '' && isStartOfContent || acc.str.length === content.length - 1 && isEndOfContent) {
            return {
              previousCharIsSpace: false,
              str: acc.str + '\xA0'
            };
          } else {
            return {
              previousCharIsSpace: true,
              str: acc.str + ' '
            };
          }
        } else {
          return {
            previousCharIsSpace: false,
            str: acc.str + c
          };
        }
      }, {
        previousCharIsSpace: false,
        str: ''
      });
      return result.str;
    };
    var normalize$1 = function (node, offset, count) {
      if (count === 0) {
        return;
      }
      var whitespace = node.data.slice(offset, offset + count);
      var isEndOfContent = offset + count >= node.data.length;
      var isStartOfContent = offset === 0;
      node.replaceData(offset, count, normalizeContent(whitespace, isStartOfContent, isEndOfContent));
    };
    var normalizeWhitespaceAfter = function (node, offset) {
      var content = node.data.slice(offset);
      var whitespaceCount = content.length - lTrim(content).length;
      return normalize$1(node, offset, whitespaceCount);
    };
    var normalizeWhitespaceBefore = function (node, offset) {
      var content = node.data.slice(0, offset);
      var whitespaceCount = content.length - rTrim(content).length;
      return normalize$1(node, offset - whitespaceCount, whitespaceCount);
    };
    var mergeTextNodes = function (prevNode, nextNode, normalizeWhitespace) {
      var whitespaceOffset = rTrim(prevNode.data).length;
      prevNode.appendData(nextNode.data);
      remove$1(Element.fromDom(nextNode));
      if (normalizeWhitespace) {
        normalizeWhitespaceAfter(prevNode, whitespaceOffset);
      }
      return prevNode;
    };

    var needsReposition = function (pos, elm) {
      var container = pos.container();
      var offset = pos.offset();
      return CaretPosition$1.isTextPosition(pos) === false && container === elm.parentNode && offset > CaretPosition$1.before(elm).offset();
    };
    var reposition = function (elm, pos) {
      return needsReposition(pos, elm) ? CaretPosition$1(pos.container(), pos.offset() - 1) : pos;
    };
    var beforeOrStartOf = function (node) {
      return NodeType.isText(node) ? CaretPosition$1(node, 0) : CaretPosition$1.before(node);
    };
    var afterOrEndOf = function (node) {
      return NodeType.isText(node) ? CaretPosition$1(node, node.data.length) : CaretPosition$1.after(node);
    };
    var getPreviousSiblingCaretPosition = function (elm) {
      if (isCaretCandidate(elm.previousSibling)) {
        return Option.some(afterOrEndOf(elm.previousSibling));
      } else {
        return elm.previousSibling ? CaretFinder.lastPositionIn(elm.previousSibling) : Option.none();
      }
    };
    var getNextSiblingCaretPosition = function (elm) {
      if (isCaretCandidate(elm.nextSibling)) {
        return Option.some(beforeOrStartOf(elm.nextSibling));
      } else {
        return elm.nextSibling ? CaretFinder.firstPositionIn(elm.nextSibling) : Option.none();
      }
    };
    var findCaretPositionBackwardsFromElm = function (rootElement, elm) {
      var startPosition = CaretPosition$1.before(elm.previousSibling ? elm.previousSibling : elm.parentNode);
      return CaretFinder.prevPosition(rootElement, startPosition).fold(function () {
        return CaretFinder.nextPosition(rootElement, CaretPosition$1.after(elm));
      }, Option.some);
    };
    var findCaretPositionForwardsFromElm = function (rootElement, elm) {
      return CaretFinder.nextPosition(rootElement, CaretPosition$1.after(elm)).fold(function () {
        return CaretFinder.prevPosition(rootElement, CaretPosition$1.before(elm));
      }, Option.some);
    };
    var findCaretPositionBackwards = function (rootElement, elm) {
      return getPreviousSiblingCaretPosition(elm).orThunk(function () {
        return getNextSiblingCaretPosition(elm);
      }).orThunk(function () {
        return findCaretPositionBackwardsFromElm(rootElement, elm);
      });
    };
    var findCaretPositionForward = function (rootElement, elm) {
      return getNextSiblingCaretPosition(elm).orThunk(function () {
        return getPreviousSiblingCaretPosition(elm);
      }).orThunk(function () {
        return findCaretPositionForwardsFromElm(rootElement, elm);
      });
    };
    var findCaretPosition$1 = function (forward, rootElement, elm) {
      return forward ? findCaretPositionForward(rootElement, elm) : findCaretPositionBackwards(rootElement, elm);
    };
    var findCaretPosOutsideElmAfterDelete = function (forward, rootElement, elm) {
      return findCaretPosition$1(forward, rootElement, elm).map(curry(reposition, elm));
    };
    var setSelection = function (editor, forward, pos) {
      pos.fold(function () {
        editor.focus();
      }, function (pos) {
        editor.selection.setRng(pos.toRange(), forward);
      });
    };
    var eqRawNode = function (rawNode) {
      return function (elm) {
        return elm.dom() === rawNode;
      };
    };
    var isBlock$2 = function (editor, elm) {
      return elm && editor.schema.getBlockElements().hasOwnProperty(name(elm));
    };
    var paddEmptyBlock = function (elm) {
      if (Empty.isEmpty(elm)) {
        var br = Element.fromHtml('<br data-mce-bogus="1">');
        empty(elm);
        append(elm, br);
        return Option.some(CaretPosition$1.before(br.dom()));
      } else {
        return Option.none();
      }
    };
    var deleteNormalized = function (elm, afterDeletePosOpt, normalizeWhitespace) {
      var prevTextOpt = prevSibling(elm).filter(isText);
      var nextTextOpt = nextSibling(elm).filter(isText);
      remove$1(elm);
      return lift3(prevTextOpt, nextTextOpt, afterDeletePosOpt, function (prev, next, pos) {
        var prevNode = prev.dom(), nextNode = next.dom();
        var offset = prevNode.data.length;
        mergeTextNodes(prevNode, nextNode, normalizeWhitespace);
        return pos.container() === nextNode ? CaretPosition$1(prevNode, offset) : pos;
      }).orThunk(function () {
        if (normalizeWhitespace) {
          prevTextOpt.each(function (elm) {
            return normalizeWhitespaceBefore(elm.dom(), elm.dom().length);
          });
          nextTextOpt.each(function (elm) {
            return normalizeWhitespaceAfter(elm.dom(), 0);
          });
        }
        return afterDeletePosOpt;
      });
    };
    var isInlineElement = function (editor, element) {
      return has(editor.schema.getTextInlineElements(), name(element));
    };
    var deleteElement = function (editor, forward, elm, moveCaret) {
      if (moveCaret === void 0) {
        moveCaret = true;
      }
      var afterDeletePos = findCaretPosOutsideElmAfterDelete(forward, editor.getBody(), elm.dom());
      var parentBlock = ancestor(elm, curry(isBlock$2, editor), eqRawNode(editor.getBody()));
      var normalizedAfterDeletePos = deleteNormalized(elm, afterDeletePos, isInlineElement(editor, elm));
      if (editor.dom.isEmpty(editor.getBody())) {
        editor.setContent('');
        editor.selection.setCursorLocation();
      } else {
        parentBlock.bind(paddEmptyBlock).fold(function () {
          if (moveCaret) {
            setSelection(editor, forward, normalizedAfterDeletePos);
          }
        }, function (paddPos) {
          if (moveCaret) {
            setSelection(editor, forward, Option.some(paddPos));
          }
        });
      }
    };
    var DeleteElement = { deleteElement: deleteElement };

    var deleteElement$1 = function (editor, forward) {
      return function (element) {
        editor._selectionOverrides.hideFakeCaret();
        DeleteElement.deleteElement(editor, forward, Element.fromDom(element));
        return true;
      };
    };
    var moveToElement = function (editor, forward) {
      return function (element) {
        var pos = forward ? CaretPosition$1.before(element) : CaretPosition$1.after(element);
        editor.selection.setRng(pos.toRange());
        return true;
      };
    };
    var moveToPosition = function (editor) {
      return function (pos) {
        editor.selection.setRng(pos.toRange());
        return true;
      };
    };
    var backspaceDeleteCaret = function (editor, forward) {
      var result = read$2(editor.getBody(), forward, editor.selection.getRng()).map(function (deleteAction) {
        return deleteAction.fold(deleteElement$1(editor, forward), moveToElement(editor, forward), moveToPosition(editor));
      });
      return result.getOr(false);
    };
    var deleteOffscreenSelection = function (rootElement) {
      each(descendants$1(rootElement, '.mce-offscreen-selection'), remove$1);
    };
    var backspaceDeleteRange = function (editor, forward) {
      var selectedElement = editor.selection.getNode();
      if (NodeType.isContentEditableFalse(selectedElement)) {
        deleteOffscreenSelection(Element.fromDom(editor.getBody()));
        DeleteElement.deleteElement(editor, forward, Element.fromDom(editor.selection.getNode()));
        DeleteUtils.paddEmptyBody(editor);
        return true;
      } else {
        return false;
      }
    };
    var getContentEditableRoot = function (root, node) {
      while (node && node !== root) {
        if (NodeType.isContentEditableTrue(node) || NodeType.isContentEditableFalse(node)) {
          return node;
        }
        node = node.parentNode;
      }
      return null;
    };
    var paddEmptyElement = function (editor) {
      var br;
      var ceRoot = getContentEditableRoot(editor.getBody(), editor.selection.getNode());
      if (NodeType.isContentEditableTrue(ceRoot) && editor.dom.isBlock(ceRoot) && editor.dom.isEmpty(ceRoot)) {
        br = editor.dom.create('br', { 'data-mce-bogus': '1' });
        editor.dom.setHTML(ceRoot, '');
        ceRoot.appendChild(br);
        editor.selection.setRng(CaretPosition$1.before(br).toRange());
      }
      return true;
    };
    var backspaceDelete$2 = function (editor, forward) {
      if (editor.selection.isCollapsed()) {
        return backspaceDeleteCaret(editor, forward);
      } else {
        return backspaceDeleteRange(editor, forward);
      }
    };
    var CefDelete = {
      backspaceDelete: backspaceDelete$2,
      paddEmptyElement: paddEmptyElement
    };

    var isText$8 = NodeType.isText;
    var startsWithCaretContainer$1 = function (node) {
      return isText$8(node) && node.data[0] === Zwsp.ZWSP;
    };
    var endsWithCaretContainer$1 = function (node) {
      return isText$8(node) && node.data[node.data.length - 1] === Zwsp.ZWSP;
    };
    var createZwsp = function (node) {
      return node.ownerDocument.createTextNode(Zwsp.ZWSP);
    };
    var insertBefore$1 = function (node) {
      if (isText$8(node.previousSibling)) {
        if (endsWithCaretContainer$1(node.previousSibling)) {
          return node.previousSibling;
        } else {
          node.previousSibling.appendData(Zwsp.ZWSP);
          return node.previousSibling;
        }
      } else if (isText$8(node)) {
        if (startsWithCaretContainer$1(node)) {
          return node;
        } else {
          node.insertData(0, Zwsp.ZWSP);
          return node;
        }
      } else {
        var newNode = createZwsp(node);
        node.parentNode.insertBefore(newNode, node);
        return newNode;
      }
    };
    var insertAfter$1 = function (node) {
      if (isText$8(node.nextSibling)) {
        if (startsWithCaretContainer$1(node.nextSibling)) {
          return node.nextSibling;
        } else {
          node.nextSibling.insertData(0, Zwsp.ZWSP);
          return node.nextSibling;
        }
      } else if (isText$8(node)) {
        if (endsWithCaretContainer$1(node)) {
          return node;
        } else {
          node.appendData(Zwsp.ZWSP);
          return node;
        }
      } else {
        var newNode = createZwsp(node);
        if (node.nextSibling) {
          node.parentNode.insertBefore(newNode, node.nextSibling);
        } else {
          node.parentNode.appendChild(newNode);
        }
        return newNode;
      }
    };
    var insertInline$1 = function (before, node) {
      return before ? insertBefore$1(node) : insertAfter$1(node);
    };
    var insertInlineBefore = curry(insertInline$1, true);
    var insertInlineAfter = curry(insertInline$1, false);

    var insertInlinePos = function (pos, before) {
      if (NodeType.isText(pos.container())) {
        return insertInline$1(before, pos.container());
      } else {
        return insertInline$1(before, pos.getNode());
      }
    };
    var isPosCaretContainer = function (pos, caret) {
      var caretNode = caret.get();
      return caretNode && pos.container() === caretNode && isCaretContainerInline(caretNode);
    };
    var renderCaret = function (caret, location) {
      return location.fold(function (element) {
        CaretContainerRemove.remove(caret.get());
        var text = insertInlineBefore(element);
        caret.set(text);
        return Option.some(CaretPosition$1(text, text.length - 1));
      }, function (element) {
        return CaretFinder.firstPositionIn(element).map(function (pos) {
          if (!isPosCaretContainer(pos, caret)) {
            CaretContainerRemove.remove(caret.get());
            var text = insertInlinePos(pos, true);
            caret.set(text);
            return CaretPosition$1(text, 1);
          } else {
            return CaretPosition$1(caret.get(), 1);
          }
        });
      }, function (element) {
        return CaretFinder.lastPositionIn(element).map(function (pos) {
          if (!isPosCaretContainer(pos, caret)) {
            CaretContainerRemove.remove(caret.get());
            var text = insertInlinePos(pos, false);
            caret.set(text);
            return CaretPosition$1(text, text.length - 1);
          } else {
            return CaretPosition$1(caret.get(), caret.get().length - 1);
          }
        });
      }, function (element) {
        CaretContainerRemove.remove(caret.get());
        var text = insertInlineAfter(element);
        caret.set(text);
        return Option.some(CaretPosition$1(text, 1));
      });
    };
    var BoundaryCaret = { renderCaret: renderCaret };

    var evaluateUntil = function (fns, args) {
      for (var i = 0; i < fns.length; i++) {
        var result = fns[i].apply(null, args);
        if (result.isSome()) {
          return result;
        }
      }
      return Option.none();
    };
    var LazyEvaluator = { evaluateUntil: evaluateUntil };

    var Location = Adt.generate([
      { before: ['element'] },
      { start: ['element'] },
      { end: ['element'] },
      { after: ['element'] }
    ]);
    var rescope = function (rootNode, node) {
      var parentBlock = getParentBlock(node, rootNode);
      return parentBlock ? parentBlock : rootNode;
    };
    var before$3 = function (isInlineTarget, rootNode, pos) {
      var nPos = InlineUtils.normalizeForwards(pos);
      var scope = rescope(rootNode, nPos.container());
      return InlineUtils.findRootInline(isInlineTarget, scope, nPos).fold(function () {
        return CaretFinder.nextPosition(scope, nPos).bind(curry(InlineUtils.findRootInline, isInlineTarget, scope)).map(function (inline) {
          return Location.before(inline);
        });
      }, Option.none);
    };
    var isNotInsideFormatCaretContainer = function (rootNode, elm) {
      return getParentCaretContainer(rootNode, elm) === null;
    };
    var findInsideRootInline = function (isInlineTarget, rootNode, pos) {
      return InlineUtils.findRootInline(isInlineTarget, rootNode, pos).filter(curry(isNotInsideFormatCaretContainer, rootNode));
    };
    var start = function (isInlineTarget, rootNode, pos) {
      var nPos = InlineUtils.normalizeBackwards(pos);
      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(function (inline) {
        var prevPos = CaretFinder.prevPosition(inline, nPos);
        return prevPos.isNone() ? Option.some(Location.start(inline)) : Option.none();
      });
    };
    var end = function (isInlineTarget, rootNode, pos) {
      var nPos = InlineUtils.normalizeForwards(pos);
      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(function (inline) {
        var nextPos = CaretFinder.nextPosition(inline, nPos);
        return nextPos.isNone() ? Option.some(Location.end(inline)) : Option.none();
      });
    };
    var after$2 = function (isInlineTarget, rootNode, pos) {
      var nPos = InlineUtils.normalizeBackwards(pos);
      var scope = rescope(rootNode, nPos.container());
      return InlineUtils.findRootInline(isInlineTarget, scope, nPos).fold(function () {
        return CaretFinder.prevPosition(scope, nPos).bind(curry(InlineUtils.findRootInline, isInlineTarget, scope)).map(function (inline) {
          return Location.after(inline);
        });
      }, Option.none);
    };
    var isValidLocation = function (location) {
      return InlineUtils.isRtl(getElement(location)) === false;
    };
    var readLocation = function (isInlineTarget, rootNode, pos) {
      var location = LazyEvaluator.evaluateUntil([
        before$3,
        start,
        end,
        after$2
      ], [
        isInlineTarget,
        rootNode,
        pos
      ]);
      return location.filter(isValidLocation);
    };
    var getElement = function (location) {
      return location.fold(identity, identity, identity, identity);
    };
    var getName = function (location) {
      return location.fold(constant('before'), constant('start'), constant('end'), constant('after'));
    };
    var outside = function (location) {
      return location.fold(Location.before, Location.before, Location.after, Location.after);
    };
    var inside = function (location) {
      return location.fold(Location.start, Location.start, Location.end, Location.end);
    };
    var isEq$1 = function (location1, location2) {
      return getName(location1) === getName(location2) && getElement(location1) === getElement(location2);
    };
    var betweenInlines = function (forward, isInlineTarget, rootNode, from, to, location) {
      return lift2(InlineUtils.findRootInline(isInlineTarget, rootNode, from), InlineUtils.findRootInline(isInlineTarget, rootNode, to), function (fromInline, toInline) {
        if (fromInline !== toInline && InlineUtils.hasSameParentBlock(rootNode, fromInline, toInline)) {
          return Location.after(forward ? fromInline : toInline);
        } else {
          return location;
        }
      }).getOr(location);
    };
    var skipNoMovement = function (fromLocation, toLocation) {
      return fromLocation.fold(constant(true), function (fromLocation) {
        return !isEq$1(fromLocation, toLocation);
      });
    };
    var findLocationTraverse = function (forward, isInlineTarget, rootNode, fromLocation, pos) {
      var from = InlineUtils.normalizePosition(forward, pos);
      var to = CaretFinder.fromPosition(forward, rootNode, from).map(curry(InlineUtils.normalizePosition, forward));
      var location = to.fold(function () {
        return fromLocation.map(outside);
      }, function (to) {
        return readLocation(isInlineTarget, rootNode, to).map(curry(betweenInlines, forward, isInlineTarget, rootNode, from, to)).filter(curry(skipNoMovement, fromLocation));
      });
      return location.filter(isValidLocation);
    };
    var findLocationSimple = function (forward, location) {
      if (forward) {
        return location.fold(compose(Option.some, Location.start), Option.none, compose(Option.some, Location.after), Option.none);
      } else {
        return location.fold(Option.none, compose(Option.some, Location.before), Option.none, compose(Option.some, Location.end));
      }
    };
    var findLocation = function (forward, isInlineTarget, rootNode, pos) {
      var from = InlineUtils.normalizePosition(forward, pos);
      var fromLocation = readLocation(isInlineTarget, rootNode, from);
      return readLocation(isInlineTarget, rootNode, from).bind(curry(findLocationSimple, forward)).orThunk(function () {
        return findLocationTraverse(forward, isInlineTarget, rootNode, fromLocation, pos);
      });
    };
    var BoundaryLocation = {
      readLocation: readLocation,
      findLocation: findLocation,
      prevLocation: curry(findLocation, false),
      nextLocation: curry(findLocation, true),
      getElement: getElement,
      outside: outside,
      inside: inside
    };

    var hasSelectionModifyApi = function (editor) {
      return isFunction(editor.selection.getSel().modify);
    };
    var moveRel = function (forward, selection, pos) {
      var delta = forward ? 1 : -1;
      selection.setRng(CaretPosition$1(pos.container(), pos.offset() + delta).toRange());
      selection.getSel().modify('move', forward ? 'forward' : 'backward', 'word');
      return true;
    };
    var moveByWord = function (forward, editor) {
      var rng = editor.selection.getRng();
      var pos = forward ? CaretPosition$1.fromRangeEnd(rng) : CaretPosition$1.fromRangeStart(rng);
      if (!hasSelectionModifyApi(editor)) {
        return false;
      } else if (forward && isBeforeInline(pos)) {
        return moveRel(true, editor.selection, pos);
      } else if (!forward && isAfterInline(pos)) {
        return moveRel(false, editor.selection, pos);
      } else {
        return false;
      }
    };
    var WordSelection = {
      hasSelectionModifyApi: hasSelectionModifyApi,
      moveByWord: moveByWord
    };

    var setCaretPosition = function (editor, pos) {
      var rng = editor.dom.createRng();
      rng.setStart(pos.container(), pos.offset());
      rng.setEnd(pos.container(), pos.offset());
      editor.selection.setRng(rng);
    };
    var isFeatureEnabled = function (editor) {
      return editor.settings.inline_boundaries !== false;
    };
    var setSelected = function (state, elm) {
      if (state) {
        elm.setAttribute('data-mce-selected', 'inline-boundary');
      } else {
        elm.removeAttribute('data-mce-selected');
      }
    };
    var renderCaretLocation = function (editor, caret, location) {
      return BoundaryCaret.renderCaret(caret, location).map(function (pos) {
        setCaretPosition(editor, pos);
        return location;
      });
    };
    var findLocation$1 = function (editor, caret, forward) {
      var rootNode = editor.getBody();
      var from = CaretPosition$1.fromRangeStart(editor.selection.getRng());
      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
      var location = BoundaryLocation.findLocation(forward, isInlineTarget, rootNode, from);
      return location.bind(function (location) {
        return renderCaretLocation(editor, caret, location);
      });
    };
    var toggleInlines = function (isInlineTarget, dom, elms) {
      var selectedInlines = filter(dom.select('*[data-mce-selected="inline-boundary"]'), isInlineTarget);
      var targetInlines = filter(elms, isInlineTarget);
      each(difference(selectedInlines, targetInlines), curry(setSelected, false));
      each(difference(targetInlines, selectedInlines), curry(setSelected, true));
    };
    var safeRemoveCaretContainer = function (editor, caret) {
      if (editor.selection.isCollapsed() && editor.composing !== true && caret.get()) {
        var pos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
        if (CaretPosition$1.isTextPosition(pos) && InlineUtils.isAtZwsp(pos) === false) {
          setCaretPosition(editor, CaretContainerRemove.removeAndReposition(caret.get(), pos));
          caret.set(null);
        }
      }
    };
    var renderInsideInlineCaret = function (isInlineTarget, editor, caret, elms) {
      if (editor.selection.isCollapsed()) {
        var inlines = filter(elms, isInlineTarget);
        each(inlines, function (inline) {
          var pos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
          BoundaryLocation.readLocation(isInlineTarget, editor.getBody(), pos).bind(function (location) {
            return renderCaretLocation(editor, caret, location);
          });
        });
      }
    };
    var move = function (editor, caret, forward) {
      return function () {
        return isFeatureEnabled(editor) ? findLocation$1(editor, caret, forward).isSome() : false;
      };
    };
    var moveWord = function (forward, editor, caret) {
      return function () {
        return isFeatureEnabled(editor) ? WordSelection.moveByWord(forward, editor) : false;
      };
    };
    var setupSelectedState = function (editor) {
      var caret = Cell(null);
      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
      editor.on('NodeChange', function (e) {
        if (isFeatureEnabled(editor)) {
          toggleInlines(isInlineTarget, editor.dom, e.parents);
          safeRemoveCaretContainer(editor, caret);
          renderInsideInlineCaret(isInlineTarget, editor, caret, e.parents);
        }
      });
      return caret;
    };
    var moveNextWord = curry(moveWord, true);
    var movePrevWord = curry(moveWord, false);
    var BoundarySelection = {
      move: move,
      moveNextWord: moveNextWord,
      movePrevWord: movePrevWord,
      setupSelectedState: setupSelectedState,
      setCaretPosition: setCaretPosition
    };

    var isFeatureEnabled$1 = function (editor) {
      return editor.settings.inline_boundaries !== false;
    };
    var rangeFromPositions = function (from, to) {
      var range = domGlobals.document.createRange();
      range.setStart(from.container(), from.offset());
      range.setEnd(to.container(), to.offset());
      return range;
    };
    var hasOnlyTwoOrLessPositionsLeft = function (elm) {
      return lift2(CaretFinder.firstPositionIn(elm), CaretFinder.lastPositionIn(elm), function (firstPos, lastPos) {
        var normalizedFirstPos = InlineUtils.normalizePosition(true, firstPos);
        var normalizedLastPos = InlineUtils.normalizePosition(false, lastPos);
        return CaretFinder.nextPosition(elm, normalizedFirstPos).map(function (pos) {
          return pos.isEqual(normalizedLastPos);
        }).getOr(true);
      }).getOr(true);
    };
    var setCaretLocation = function (editor, caret) {
      return function (location) {
        return BoundaryCaret.renderCaret(caret, location).map(function (pos) {
          BoundarySelection.setCaretPosition(editor, pos);
          return true;
        }).getOr(false);
      };
    };
    var deleteFromTo = function (editor, caret, from, to) {
      var rootNode = editor.getBody();
      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
      editor.undoManager.ignore(function () {
        editor.selection.setRng(rangeFromPositions(from, to));
        editor.execCommand('Delete');
        BoundaryLocation.readLocation(isInlineTarget, rootNode, CaretPosition$1.fromRangeStart(editor.selection.getRng())).map(BoundaryLocation.inside).map(setCaretLocation(editor, caret));
      });
      editor.nodeChanged();
    };
    var rescope$1 = function (rootNode, node) {
      var parentBlock = getParentBlock(node, rootNode);
      return parentBlock ? parentBlock : rootNode;
    };
    var backspaceDeleteCollapsed = function (editor, caret, forward, from) {
      var rootNode = rescope$1(editor.getBody(), from.container());
      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
      var fromLocation = BoundaryLocation.readLocation(isInlineTarget, rootNode, from);
      return fromLocation.bind(function (location) {
        if (forward) {
          return location.fold(constant(Option.some(BoundaryLocation.inside(location))), Option.none, constant(Option.some(BoundaryLocation.outside(location))), Option.none);
        } else {
          return location.fold(Option.none, constant(Option.some(BoundaryLocation.outside(location))), Option.none, constant(Option.some(BoundaryLocation.inside(location))));
        }
      }).map(setCaretLocation(editor, caret)).getOrThunk(function () {
        var toPosition = CaretFinder.navigate(forward, rootNode, from);
        var toLocation = toPosition.bind(function (pos) {
          return BoundaryLocation.readLocation(isInlineTarget, rootNode, pos);
        });
        if (fromLocation.isSome() && toLocation.isSome()) {
          return InlineUtils.findRootInline(isInlineTarget, rootNode, from).map(function (elm) {
            if (hasOnlyTwoOrLessPositionsLeft(elm)) {
              DeleteElement.deleteElement(editor, forward, Element.fromDom(elm));
              return true;
            } else {
              return false;
            }
          }).getOr(false);
        } else {
          return toLocation.bind(function (_) {
            return toPosition.map(function (to) {
              if (forward) {
                deleteFromTo(editor, caret, from, to);
              } else {
                deleteFromTo(editor, caret, to, from);
              }
              return true;
            });
          }).getOr(false);
        }
      });
    };
    var backspaceDelete$3 = function (editor, caret, forward) {
      if (editor.selection.isCollapsed() && isFeatureEnabled$1(editor)) {
        var from = CaretPosition$1.fromRangeStart(editor.selection.getRng());
        return backspaceDeleteCollapsed(editor, caret, forward, from);
      }
      return false;
    };
    var InlineBoundaryDelete = { backspaceDelete: backspaceDelete$3 };

    var tableCellRng = Immutable('start', 'end');
    var tableSelection = Immutable('rng', 'table', 'cells');
    var deleteAction = Adt.generate([
      { removeTable: ['element'] },
      { emptyCells: ['cells'] }
    ]);
    var isRootFromElement = function (root) {
      return curry(eq, root);
    };
    var getClosestCell = function (container, isRoot) {
      return closest$1(Element.fromDom(container), 'td,th', isRoot);
    };
    var getClosestTable = function (cell, isRoot) {
      return ancestor$1(cell, 'table', isRoot);
    };
    var isExpandedCellRng = function (cellRng) {
      return eq(cellRng.start(), cellRng.end()) === false;
    };
    var getTableFromCellRng = function (cellRng, isRoot) {
      return getClosestTable(cellRng.start(), isRoot).bind(function (startParentTable) {
        return getClosestTable(cellRng.end(), isRoot).bind(function (endParentTable) {
          return eq(startParentTable, endParentTable) ? Option.some(startParentTable) : Option.none();
        });
      });
    };
    var getTableCells = function (table) {
      return descendants$1(table, 'td,th');
    };
    var getCellRangeFromStartTable = function (cellRng, isRoot) {
      return getClosestTable(cellRng.start(), isRoot).bind(function (table) {
        return last(getTableCells(table)).map(function (endCell) {
          return tableCellRng(cellRng.start(), endCell);
        });
      });
    };
    var partialSelection = function (isRoot, rng) {
      var startCell = getClosestCell(rng.startContainer, isRoot);
      var endCell = getClosestCell(rng.endContainer, isRoot);
      return rng.collapsed ? Option.none() : lift2(startCell, endCell, tableCellRng).fold(function () {
        return startCell.fold(function () {
          return endCell.bind(function (endCell) {
            return getClosestTable(endCell, isRoot).bind(function (table) {
              return head(getTableCells(table)).map(function (startCell) {
                return tableCellRng(startCell, endCell);
              });
            });
          });
        }, function (startCell) {
          return getClosestTable(startCell, isRoot).bind(function (table) {
            return last(getTableCells(table)).map(function (endCell) {
              return tableCellRng(startCell, endCell);
            });
          });
        });
      }, function (cellRng) {
        return isWithinSameTable(isRoot, cellRng) ? Option.none() : getCellRangeFromStartTable(cellRng, isRoot);
      });
    };
    var isWithinSameTable = function (isRoot, cellRng) {
      return getTableFromCellRng(cellRng, isRoot).isSome();
    };
    var getCellRng = function (rng, isRoot) {
      var startCell = getClosestCell(rng.startContainer, isRoot);
      var endCell = getClosestCell(rng.endContainer, isRoot);
      return lift2(startCell, endCell, tableCellRng).filter(isExpandedCellRng).filter(function (cellRng) {
        return isWithinSameTable(isRoot, cellRng);
      }).orThunk(function () {
        return partialSelection(isRoot, rng);
      });
    };
    var getTableSelectionFromCellRng = function (cellRng, isRoot) {
      return getTableFromCellRng(cellRng, isRoot).map(function (table) {
        return tableSelection(cellRng, table, getTableCells(table));
      });
    };
    var getTableSelectionFromRng = function (root, rng) {
      var isRoot = isRootFromElement(root);
      return getCellRng(rng, isRoot).bind(function (cellRng) {
        return getTableSelectionFromCellRng(cellRng, isRoot);
      });
    };
    var getCellIndex = function (cells, cell) {
      return findIndex(cells, function (x) {
        return eq(x, cell);
      });
    };
    var getSelectedCells = function (tableSelection) {
      return lift2(getCellIndex(tableSelection.cells(), tableSelection.rng().start()), getCellIndex(tableSelection.cells(), tableSelection.rng().end()), function (startIndex, endIndex) {
        return tableSelection.cells().slice(startIndex, endIndex + 1);
      });
    };
    var getAction = function (tableSelection) {
      return getSelectedCells(tableSelection).map(function (selected) {
        var cells = tableSelection.cells();
        return selected.length === cells.length ? deleteAction.removeTable(tableSelection.table()) : deleteAction.emptyCells(selected);
      });
    };
    var getActionFromCells = function (cells) {
      return deleteAction.emptyCells(cells);
    };
    var getActionFromRange = function (root, rng) {
      return getTableSelectionFromRng(root, rng).bind(getAction);
    };
    var TableDeleteAction = {
      getActionFromRange: getActionFromRange,
      getActionFromCells: getActionFromCells
    };

    var getRanges = function (selection) {
      var ranges = [];
      if (selection) {
        for (var i = 0; i < selection.rangeCount; i++) {
          ranges.push(selection.getRangeAt(i));
        }
      }
      return ranges;
    };
    var getSelectedNodes = function (ranges) {
      return bind(ranges, function (range) {
        var node = getSelectedNode(range);
        return node ? [Element.fromDom(node)] : [];
      });
    };
    var hasMultipleRanges = function (selection) {
      return getRanges(selection).length > 1;
    };
    var MultiRange = {
      getRanges: getRanges,
      getSelectedNodes: getSelectedNodes,
      hasMultipleRanges: hasMultipleRanges
    };

    var getCellsFromRanges = function (ranges) {
      return filter(MultiRange.getSelectedNodes(ranges), isTableCell);
    };
    var getCellsFromElement = function (elm) {
      var selectedCells = descendants$1(elm, 'td[data-mce-selected],th[data-mce-selected]');
      return selectedCells;
    };
    var getCellsFromElementOrRanges = function (ranges, element) {
      var selectedCells = getCellsFromElement(element);
      var rangeCells = getCellsFromRanges(ranges);
      return selectedCells.length > 0 ? selectedCells : rangeCells;
    };
    var getCellsFromEditor = function (editor) {
      return getCellsFromElementOrRanges(MultiRange.getRanges(editor.selection.getSel()), Element.fromDom(editor.getBody()));
    };
    var TableCellSelection = {
      getCellsFromRanges: getCellsFromRanges,
      getCellsFromElement: getCellsFromElement,
      getCellsFromElementOrRanges: getCellsFromElementOrRanges,
      getCellsFromEditor: getCellsFromEditor
    };

    var emptyCells = function (editor, cells) {
      each(cells, PaddingBr.fillWithPaddingBr);
      editor.selection.setCursorLocation(cells[0].dom(), 0);
      return true;
    };
    var deleteTableElement = function (editor, table) {
      DeleteElement.deleteElement(editor, false, table);
      return true;
    };
    var deleteCellRange = function (editor, rootElm, rng) {
      return TableDeleteAction.getActionFromRange(rootElm, rng).map(function (action) {
        return action.fold(curry(deleteTableElement, editor), curry(emptyCells, editor));
      });
    };
    var deleteCaptionRange = function (editor, caption) {
      return emptyElement(editor, caption);
    };
    var deleteTableRange = function (editor, rootElm, rng, startElm) {
      return getParentCaption(rootElm, startElm).fold(function () {
        return deleteCellRange(editor, rootElm, rng);
      }, function (caption) {
        return deleteCaptionRange(editor, caption);
      }).getOr(false);
    };
    var deleteRange$1 = function (editor, startElm) {
      var rootNode = Element.fromDom(editor.getBody());
      var rng = editor.selection.getRng();
      var selectedCells = TableCellSelection.getCellsFromEditor(editor);
      return selectedCells.length !== 0 ? emptyCells(editor, selectedCells) : deleteTableRange(editor, rootNode, rng, startElm);
    };
    var getParentCell = function (rootElm, elm) {
      return find(Parents.parentsAndSelf(elm, rootElm), isTableCell);
    };
    var getParentCaption = function (rootElm, elm) {
      return find(Parents.parentsAndSelf(elm, rootElm), function (elm) {
        return name(elm) === 'caption';
      });
    };
    var deleteBetweenCells = function (editor, rootElm, forward, fromCell, from) {
      return CaretFinder.navigate(forward, editor.getBody(), from).bind(function (to) {
        return getParentCell(rootElm, Element.fromDom(to.getNode())).map(function (toCell) {
          return eq(toCell, fromCell) === false;
        });
      });
    };
    var emptyElement = function (editor, elm) {
      PaddingBr.fillWithPaddingBr(elm);
      editor.selection.setCursorLocation(elm.dom(), 0);
      return Option.some(true);
    };
    var isDeleteOfLastCharPos = function (fromCaption, forward, from, to) {
      return CaretFinder.firstPositionIn(fromCaption.dom()).bind(function (first) {
        return CaretFinder.lastPositionIn(fromCaption.dom()).map(function (last) {
          return forward ? from.isEqual(first) && to.isEqual(last) : from.isEqual(last) && to.isEqual(first);
        });
      }).getOr(true);
    };
    var emptyCaretCaption = function (editor, elm) {
      return emptyElement(editor, elm);
    };
    var validateCaretCaption = function (rootElm, fromCaption, to) {
      return getParentCaption(rootElm, Element.fromDom(to.getNode())).map(function (toCaption) {
        return eq(toCaption, fromCaption) === false;
      });
    };
    var deleteCaretInsideCaption = function (editor, rootElm, forward, fromCaption, from) {
      return CaretFinder.navigate(forward, editor.getBody(), from).bind(function (to) {
        return isDeleteOfLastCharPos(fromCaption, forward, from, to) ? emptyCaretCaption(editor, fromCaption) : validateCaretCaption(rootElm, fromCaption, to);
      }).or(Option.some(true));
    };
    var deleteCaretCells = function (editor, forward, rootElm, startElm) {
      var from = CaretPosition$1.fromRangeStart(editor.selection.getRng());
      return getParentCell(rootElm, startElm).bind(function (fromCell) {
        return Empty.isEmpty(fromCell) ? emptyElement(editor, fromCell) : deleteBetweenCells(editor, rootElm, forward, fromCell, from);
      });
    };
    var deleteCaretCaption = function (editor, forward, rootElm, fromCaption) {
      var from = CaretPosition$1.fromRangeStart(editor.selection.getRng());
      return Empty.isEmpty(fromCaption) ? emptyElement(editor, fromCaption) : deleteCaretInsideCaption(editor, rootElm, forward, fromCaption, from);
    };
    var deleteCaret = function (editor, forward, startElm) {
      var rootElm = Element.fromDom(editor.getBody());
      return getParentCaption(rootElm, startElm).fold(function () {
        return deleteCaretCells(editor, forward, rootElm, startElm);
      }, function (fromCaption) {
        return deleteCaretCaption(editor, forward, rootElm, fromCaption);
      }).getOr(false);
    };
    var backspaceDelete$4 = function (editor, forward) {
      var startElm = Element.fromDom(editor.selection.getStart(true));
      var cells = TableCellSelection.getCellsFromEditor(editor);
      return editor.selection.isCollapsed() && cells.length === 0 ? deleteCaret(editor, forward, startElm) : deleteRange$1(editor, startElm);
    };
    var TableDelete = { backspaceDelete: backspaceDelete$4 };

    var isEq$2 = FormatUtils.isEq;
    var matchesUnInheritedFormatSelector = function (ed, node, name) {
      var formatList = ed.formatter.get(name);
      if (formatList) {
        for (var i = 0; i < formatList.length; i++) {
          if (formatList[i].inherit === false && ed.dom.is(node, formatList[i].selector)) {
            return true;
          }
        }
      }
      return false;
    };
    var matchParents = function (editor, node, name, vars) {
      var root = editor.dom.getRoot();
      if (node === root) {
        return false;
      }
      node = editor.dom.getParent(node, function (node) {
        if (matchesUnInheritedFormatSelector(editor, node, name)) {
          return true;
        }
        return node.parentNode === root || !!matchNode(editor, node, name, vars, true);
      });
      return matchNode(editor, node, name, vars);
    };
    var matchName = function (dom, node, format) {
      if (isEq$2(node, format.inline)) {
        return true;
      }
      if (isEq$2(node, format.block)) {
        return true;
      }
      if (format.selector) {
        return node.nodeType === 1 && dom.is(node, format.selector);
      }
    };
    var matchItems = function (dom, node, format, itemName, similar, vars) {
      var key, value;
      var items = format[itemName];
      var i;
      if (format.onmatch) {
        return format.onmatch(node, format, itemName);
      }
      if (items) {
        if (typeof items.length === 'undefined') {
          for (key in items) {
            if (items.hasOwnProperty(key)) {
              if (itemName === 'attributes') {
                value = dom.getAttrib(node, key);
              } else {
                value = FormatUtils.getStyle(dom, node, key);
              }
              if (similar && !value && !format.exact) {
                return;
              }
              if ((!similar || format.exact) && !isEq$2(value, FormatUtils.normalizeStyleValue(dom, FormatUtils.replaceVars(items[key], vars), key))) {
                return;
              }
            }
          }
        } else {
          for (i = 0; i < items.length; i++) {
            if (itemName === 'attributes' ? dom.getAttrib(node, items[i]) : FormatUtils.getStyle(dom, node, items[i])) {
              return format;
            }
          }
        }
      }
      return format;
    };
    var matchNode = function (ed, node, name, vars, similar) {
      var formatList = ed.formatter.get(name);
      var format, i, x, classes;
      var dom = ed.dom;
      if (formatList && node) {
        for (i = 0; i < formatList.length; i++) {
          format = formatList[i];
          if (matchName(ed.dom, node, format) && matchItems(dom, node, format, 'attributes', similar, vars) && matchItems(dom, node, format, 'styles', similar, vars)) {
            if (classes = format.classes) {
              for (x = 0; x < classes.length; x++) {
                if (!ed.dom.hasClass(node, classes[x])) {
                  return;
                }
              }
            }
            return format;
          }
        }
      }
    };
    var match = function (editor, name, vars, node) {
      var startNode;
      if (node) {
        return matchParents(editor, node, name, vars);
      }
      node = editor.selection.getNode();
      if (matchParents(editor, node, name, vars)) {
        return true;
      }
      startNode = editor.selection.getStart();
      if (startNode !== node) {
        if (matchParents(editor, startNode, name, vars)) {
          return true;
        }
      }
      return false;
    };
    var matchAll = function (editor, names, vars) {
      var startElement;
      var matchedFormatNames = [];
      var checkedMap = {};
      startElement = editor.selection.getStart();
      editor.dom.getParent(startElement, function (node) {
        var i, name;
        for (i = 0; i < names.length; i++) {
          name = names[i];
          if (!checkedMap[name] && matchNode(editor, node, name, vars)) {
            checkedMap[name] = true;
            matchedFormatNames.push(name);
          }
        }
      }, editor.dom.getRoot());
      return matchedFormatNames;
    };
    var canApply = function (editor, name) {
      var formatList = editor.formatter.get(name);
      var startNode, parents, i, x, selector;
      var dom = editor.dom;
      if (formatList) {
        startNode = editor.selection.getStart();
        parents = FormatUtils.getParents(dom, startNode);
        for (x = formatList.length - 1; x >= 0; x--) {
          selector = formatList[x].selector;
          if (!selector || formatList[x].defaultBlock) {
            return true;
          }
          for (i = parents.length - 1; i >= 0; i--) {
            if (dom.is(parents[i], selector)) {
              return true;
            }
          }
        }
      }
      return false;
    };
    var MatchFormat = {
      matchNode: matchNode,
      matchName: matchName,
      match: match,
      matchAll: matchAll,
      canApply: canApply,
      matchesUnInheritedFormatSelector: matchesUnInheritedFormatSelector
    };

    var splitText = function (node, offset) {
      return node.splitText(offset);
    };
    var split$1 = function (rng) {
      var startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset;
      if (startContainer === endContainer && NodeType.isText(startContainer)) {
        if (startOffset > 0 && startOffset < startContainer.nodeValue.length) {
          endContainer = splitText(startContainer, startOffset);
          startContainer = endContainer.previousSibling;
          if (endOffset > startOffset) {
            endOffset = endOffset - startOffset;
            startContainer = endContainer = splitText(endContainer, endOffset).previousSibling;
            endOffset = endContainer.nodeValue.length;
            startOffset = 0;
          } else {
            endOffset = 0;
          }
        }
      } else {
        if (NodeType.isText(startContainer) && startOffset > 0 && startOffset < startContainer.nodeValue.length) {
          startContainer = splitText(startContainer, startOffset);
          startOffset = 0;
        }
        if (NodeType.isText(endContainer) && endOffset > 0 && endOffset < endContainer.nodeValue.length) {
          endContainer = splitText(endContainer, endOffset).previousSibling;
          endOffset = endContainer.nodeValue.length;
        }
      }
      return {
        startContainer: startContainer,
        startOffset: startOffset,
        endContainer: endContainer,
        endOffset: endOffset
      };
    };
    var SplitRange = { split: split$1 };

    var ZWSP$1 = Zwsp.ZWSP, CARET_ID$1 = '_mce_caret';
    var importNode = function (ownerDocument, node) {
      return ownerDocument.importNode(node, true);
    };
    var getEmptyCaretContainers = function (node) {
      var nodes = [];
      while (node) {
        if (node.nodeType === 3 && node.nodeValue !== ZWSP$1 || node.childNodes.length > 1) {
          return [];
        }
        if (node.nodeType === 1) {
          nodes.push(node);
        }
        node = node.firstChild;
      }
      return nodes;
    };
    var isCaretContainerEmpty = function (node) {
      return getEmptyCaretContainers(node).length > 0;
    };
    var findFirstTextNode = function (node) {
      var walker;
      if (node) {
        walker = new TreeWalker(node, node);
        for (node = walker.current(); node; node = walker.next()) {
          if (node.nodeType === 3) {
            return node;
          }
        }
      }
      return null;
    };
    var createCaretContainer = function (fill) {
      var caretContainer = Element.fromTag('span');
      setAll(caretContainer, {
        'id': CARET_ID$1,
        'data-mce-bogus': '1',
        'data-mce-type': 'format-caret'
      });
      if (fill) {
        append(caretContainer, Element.fromText(ZWSP$1));
      }
      return caretContainer;
    };
    var trimZwspFromCaretContainer = function (caretContainerNode) {
      var textNode = findFirstTextNode(caretContainerNode);
      if (textNode && textNode.nodeValue.charAt(0) === ZWSP$1) {
        textNode.deleteData(0, 1);
      }
      return textNode;
    };
    var removeCaretContainerNode = function (editor, node, moveCaret) {
      if (moveCaret === void 0) {
        moveCaret = true;
      }
      var dom = editor.dom, selection = editor.selection;
      if (isCaretContainerEmpty(node)) {
        DeleteElement.deleteElement(editor, false, Element.fromDom(node), moveCaret);
      } else {
        var rng = selection.getRng();
        var block = dom.getParent(node, dom.isBlock);
        var textNode = trimZwspFromCaretContainer(node);
        if (rng.startContainer === textNode && rng.startOffset > 0) {
          rng.setStart(textNode, rng.startOffset - 1);
        }
        if (rng.endContainer === textNode && rng.endOffset > 0) {
          rng.setEnd(textNode, rng.endOffset - 1);
        }
        dom.remove(node, true);
        if (block && dom.isEmpty(block)) {
          PaddingBr.fillWithPaddingBr(Element.fromDom(block));
        }
        selection.setRng(rng);
      }
    };
    var removeCaretContainer = function (editor, node, moveCaret) {
      if (moveCaret === void 0) {
        moveCaret = true;
      }
      var dom = editor.dom, selection = editor.selection;
      if (!node) {
        node = getParentCaretContainer(editor.getBody(), selection.getStart());
        if (!node) {
          while (node = dom.get(CARET_ID$1)) {
            removeCaretContainerNode(editor, node, false);
          }
        }
      } else {
        removeCaretContainerNode(editor, node, moveCaret);
      }
    };
    var insertCaretContainerNode = function (editor, caretContainer, formatNode) {
      var dom = editor.dom, block = dom.getParent(formatNode, curry(FormatUtils.isTextBlock, editor));
      if (block && dom.isEmpty(block)) {
        formatNode.parentNode.replaceChild(caretContainer, formatNode);
      } else {
        PaddingBr.removeTrailingBr(Element.fromDom(formatNode));
        if (dom.isEmpty(formatNode)) {
          formatNode.parentNode.replaceChild(caretContainer, formatNode);
        } else {
          dom.insertAfter(caretContainer, formatNode);
        }
      }
    };
    var appendNode = function (parentNode, node) {
      parentNode.appendChild(node);
      return node;
    };
    var insertFormatNodesIntoCaretContainer = function (formatNodes, caretContainer) {
      var innerMostFormatNode = foldr(formatNodes, function (parentNode, formatNode) {
        return appendNode(parentNode, formatNode.cloneNode(false));
      }, caretContainer);
      return appendNode(innerMostFormatNode, innerMostFormatNode.ownerDocument.createTextNode(ZWSP$1));
    };
    var applyCaretFormat = function (editor, name, vars) {
      var rng, caretContainer, textNode, offset, bookmark, container, text;
      var selection = editor.selection;
      rng = selection.getRng(true);
      offset = rng.startOffset;
      container = rng.startContainer;
      text = container.nodeValue;
      caretContainer = getParentCaretContainer(editor.getBody(), selection.getStart());
      if (caretContainer) {
        textNode = findFirstTextNode(caretContainer);
      }
      var wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/;
      if (text && offset > 0 && offset < text.length && wordcharRegex.test(text.charAt(offset)) && wordcharRegex.test(text.charAt(offset - 1))) {
        bookmark = selection.getBookmark();
        rng.collapse(true);
        rng = ExpandRange.expandRng(editor, rng, editor.formatter.get(name));
        rng = SplitRange.split(rng);
        editor.formatter.apply(name, vars, rng);
        selection.moveToBookmark(bookmark);
      } else {
        if (!caretContainer || textNode.nodeValue !== ZWSP$1) {
          caretContainer = importNode(editor.getDoc(), createCaretContainer(true).dom());
          textNode = caretContainer.firstChild;
          rng.insertNode(caretContainer);
          offset = 1;
          editor.formatter.apply(name, vars, caretContainer);
        } else {
          editor.formatter.apply(name, vars, caretContainer);
        }
        selection.setCursorLocation(textNode, offset);
      }
    };
    var removeCaretFormat = function (editor, name, vars, similar) {
      var dom = editor.dom, selection = editor.selection;
      var container, offset, bookmark;
      var hasContentAfter, node, formatNode;
      var parents = [], rng = selection.getRng();
      var caretContainer;
      container = rng.startContainer;
      offset = rng.startOffset;
      node = container;
      if (container.nodeType === 3) {
        if (offset !== container.nodeValue.length) {
          hasContentAfter = true;
        }
        node = node.parentNode;
      }
      while (node) {
        if (MatchFormat.matchNode(editor, node, name, vars, similar)) {
          formatNode = node;
          break;
        }
        if (node.nextSibling) {
          hasContentAfter = true;
        }
        parents.push(node);
        node = node.parentNode;
      }
      if (!formatNode) {
        return;
      }
      if (hasContentAfter) {
        bookmark = selection.getBookmark();
        rng.collapse(true);
        var expandedRng = ExpandRange.expandRng(editor, rng, editor.formatter.get(name), true);
        expandedRng = SplitRange.split(expandedRng);
        editor.formatter.remove(name, vars, expandedRng);
        selection.moveToBookmark(bookmark);
      } else {
        caretContainer = getParentCaretContainer(editor.getBody(), formatNode);
        var newCaretContainer = createCaretContainer(false).dom();
        var caretNode = insertFormatNodesIntoCaretContainer(parents, newCaretContainer);
        if (caretContainer) {
          insertCaretContainerNode(editor, newCaretContainer, caretContainer);
        } else {
          insertCaretContainerNode(editor, newCaretContainer, formatNode);
        }
        removeCaretContainerNode(editor, caretContainer, false);
        selection.setCursorLocation(caretNode, 1);
        if (dom.isEmpty(formatNode)) {
          dom.remove(formatNode);
        }
      }
    };
    var disableCaretContainer = function (editor, keyCode) {
      var selection = editor.selection, body = editor.getBody();
      removeCaretContainer(editor, null, false);
      if ((keyCode === 8 || keyCode === 46) && selection.isCollapsed() && selection.getStart().innerHTML === ZWSP$1) {
        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()));
      }
      if (keyCode === 37 || keyCode === 39) {
        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()));
      }
    };
    var setup$2 = function (editor) {
      editor.on('mouseup keydown', function (e) {
        disableCaretContainer(editor, e.keyCode);
      });
    };
    var replaceWithCaretFormat = function (targetNode, formatNodes) {
      var caretContainer = createCaretContainer(false);
      var innerMost = insertFormatNodesIntoCaretContainer(formatNodes, caretContainer.dom());
      before(Element.fromDom(targetNode), caretContainer);
      remove$1(Element.fromDom(targetNode));
      return CaretPosition$1(innerMost, 0);
    };
    var isFormatElement = function (editor, element) {
      var inlineElements = editor.schema.getTextInlineElements();
      return inlineElements.hasOwnProperty(name(element)) && !isCaretNode(element.dom()) && !NodeType.isBogus(element.dom());
    };
    var isEmptyCaretFormatElement = function (element) {
      return isCaretNode(element.dom()) && isCaretContainerEmpty(element.dom());
    };

    var getParentInlines = function (rootElm, startElm) {
      var parents = Parents.parentsAndSelf(startElm, rootElm);
      return findIndex(parents, isBlock).fold(constant(parents), function (index) {
        return parents.slice(0, index);
      });
    };
    var hasOnlyOneChild$1 = function (elm) {
      return children(elm).length === 1;
    };
    var deleteLastPosition = function (forward, editor, target, parentInlines) {
      var isFormatElement$1 = curry(isFormatElement, editor);
      var formatNodes = map(filter(parentInlines, isFormatElement$1), function (elm) {
        return elm.dom();
      });
      if (formatNodes.length === 0) {
        DeleteElement.deleteElement(editor, forward, target);
      } else {
        var pos = replaceWithCaretFormat(target.dom(), formatNodes);
        editor.selection.setRng(pos.toRange());
      }
    };
    var deleteCaret$1 = function (editor, forward) {
      var rootElm = Element.fromDom(editor.getBody());
      var startElm = Element.fromDom(editor.selection.getStart());
      var parentInlines = filter(getParentInlines(rootElm, startElm), hasOnlyOneChild$1);
      return last(parentInlines).map(function (target) {
        var fromPos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
        if (DeleteUtils.willDeleteLastPositionInElement(forward, fromPos, target.dom()) && !isEmptyCaretFormatElement(target)) {
          deleteLastPosition(forward, editor, target, parentInlines);
          return true;
        } else {
          return false;
        }
      }).getOr(false);
    };
    var backspaceDelete$5 = function (editor, forward) {
      return editor.selection.isCollapsed() ? deleteCaret$1(editor, forward) : false;
    };
    var InlineFormatDelete = { backspaceDelete: backspaceDelete$5 };

    var getPos$1 = function (elm) {
      var x = 0, y = 0;
      var offsetParent = elm;
      while (offsetParent && offsetParent.nodeType) {
        x += offsetParent.offsetLeft || 0;
        y += offsetParent.offsetTop || 0;
        offsetParent = offsetParent.offsetParent;
      }
      return {
        x: x,
        y: y
      };
    };
    var fireScrollIntoViewEvent = function (editor, elm, alignToTop) {
      var scrollEvent = {
        elm: elm,
        alignToTop: alignToTop
      };
      editor.fire('scrollIntoView', scrollEvent);
      return scrollEvent.isDefaultPrevented();
    };
    var scrollElementIntoView = function (editor, elm, alignToTop) {
      var y, viewPort;
      var dom = editor.dom;
      var root = dom.getRoot();
      var viewPortY, viewPortH, offsetY = 0;
      if (fireScrollIntoViewEvent(editor, elm, alignToTop)) {
        return;
      }
      if (!NodeType.isElement(elm)) {
        return;
      }
      if (alignToTop === false) {
        offsetY = elm.offsetHeight;
      }
      if (root.nodeName !== 'BODY') {
        var scrollContainer = editor.selection.getScrollContainer();
        if (scrollContainer) {
          y = getPos$1(elm).y - getPos$1(scrollContainer).y + offsetY;
          viewPortH = scrollContainer.clientHeight;
          viewPortY = scrollContainer.scrollTop;
          if (y < viewPortY || y + 25 > viewPortY + viewPortH) {
            scrollContainer.scrollTop = y < viewPortY ? y : y - viewPortH + 25;
          }
          return;
        }
      }
      viewPort = dom.getViewPort(editor.getWin());
      y = dom.getPos(elm).y + offsetY;
      viewPortY = viewPort.y;
      viewPortH = viewPort.h;
      if (y < viewPort.y || y + 25 > viewPortY + viewPortH) {
        editor.getWin().scrollTo(0, y < viewPortY ? y : y - viewPortH + 25);
      }
    };
    var getViewPortRect = function (editor) {
      if (editor.inline) {
        return editor.getBody().getBoundingClientRect();
      } else {
        var win = editor.getWin();
        return {
          left: 0,
          right: win.innerWidth,
          top: 0,
          bottom: win.innerHeight,
          width: win.innerWidth,
          height: win.innerHeight
        };
      }
    };
    var scrollBy = function (editor, dx, dy) {
      if (editor.inline) {
        editor.getBody().scrollLeft += dx;
        editor.getBody().scrollTop += dy;
      } else {
        editor.getWin().scrollBy(dx, dy);
      }
    };
    var scrollRangeIntoView = function (editor, rng) {
      head(CaretPosition.fromRangeStart(rng).getClientRects()).each(function (rngRect) {
        var bodyRect = getViewPortRect(editor);
        var overflow = getOverflow(bodyRect, rngRect);
        var margin = 4;
        var dx = overflow.x > 0 ? overflow.x + margin : overflow.x - margin;
        var dy = overflow.y > 0 ? overflow.y + margin : overflow.y - margin;
        scrollBy(editor, overflow.x !== 0 ? dx : 0, overflow.y !== 0 ? dy : 0);
      });
    };
    var ScrollIntoView = {
      scrollElementIntoView: scrollElementIntoView,
      scrollRangeIntoView: scrollRangeIntoView
    };

    var isContentEditableTrue$2 = NodeType.isContentEditableTrue;
    var isContentEditableFalse$6 = NodeType.isContentEditableFalse;
    var showCaret = function (direction, editor, node, before, scrollIntoView) {
      return editor._selectionOverrides.showCaret(direction, node, before, scrollIntoView);
    };
    var getNodeRange = function (node) {
      var rng = node.ownerDocument.createRange();
      rng.selectNode(node);
      return rng;
    };
    var selectNode = function (editor, node) {
      var e = editor.fire('BeforeObjectSelected', { target: node });
      if (e.isDefaultPrevented()) {
        return null;
      }
      return getNodeRange(node);
    };
    var renderCaretAtRange = function (editor, range, scrollIntoView) {
      var normalizedRange = normalizeRange(1, editor.getBody(), range);
      var caretPosition = CaretPosition$1.fromRangeStart(normalizedRange);
      var caretPositionNode = caretPosition.getNode();
      if (isContentEditableFalse$6(caretPositionNode)) {
        return showCaret(1, editor, caretPositionNode, !caretPosition.isAtEnd(), false);
      }
      var caretPositionBeforeNode = caretPosition.getNode(true);
      if (isContentEditableFalse$6(caretPositionBeforeNode)) {
        return showCaret(1, editor, caretPositionBeforeNode, false, false);
      }
      var ceRoot = editor.dom.getParent(caretPosition.getNode(), function (node) {
        return isContentEditableFalse$6(node) || isContentEditableTrue$2(node);
      });
      if (isContentEditableFalse$6(ceRoot)) {
        return showCaret(1, editor, ceRoot, false, scrollIntoView);
      }
      return null;
    };
    var renderRangeCaret = function (editor, range, scrollIntoView) {
      if (!range || !range.collapsed) {
        return range;
      }
      var caretRange = renderCaretAtRange(editor, range, scrollIntoView);
      if (caretRange) {
        return caretRange;
      }
      return range;
    };
    var moveToRange = function (editor, rng) {
      editor.selection.setRng(rng);
      ScrollIntoView.scrollRangeIntoView(editor, editor.selection.getRng());
    };

    var trimEmptyTextNode$1 = function (dom, node) {
      if (NodeType.isText(node) && node.data.length === 0) {
        dom.remove(node);
      }
    };
    var deleteContentAndShowCaret = function (editor, range, node, direction, forward, peekCaretPosition) {
      var caretRange = showCaret(direction, editor, peekCaretPosition.getNode(!forward), forward, true);
      if (range.collapsed) {
        var deleteRange = range.cloneRange();
        if (forward) {
          deleteRange.setEnd(caretRange.startContainer, caretRange.startOffset);
        } else {
          deleteRange.setStart(caretRange.endContainer, caretRange.endOffset);
        }
        deleteRange.deleteContents();
      } else {
        range.deleteContents();
      }
      editor.selection.setRng(caretRange);
      trimEmptyTextNode$1(editor.dom, node);
      return true;
    };
    var deleteCefBoundaryText = function (editor, forward) {
      var range = editor.selection.getRng();
      if (!NodeType.isText(range.commonAncestorContainer)) {
        return false;
      }
      var direction = forward ? HDirection.Forwards : HDirection.Backwards;
      var caretWalker = CaretWalker(editor.getBody());
      var getNextVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.next);
      var getPrevVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.prev);
      var getNextPosFn = forward ? getNextVisualCaretPosition : getPrevVisualCaretPosition;
      var isBeforeContentEditableFalseFn = forward ? isBeforeContentEditableFalse : isAfterContentEditableFalse;
      var caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
      var nextCaretPosition = InlineUtils.normalizePosition(forward, getNextPosFn(caretPosition));
      if (!nextCaretPosition) {
        return false;
      } else if (isBeforeContentEditableFalseFn(nextCaretPosition)) {
        return deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, nextCaretPosition);
      }
      var peekCaretPosition = getNextPosFn(nextCaretPosition);
      if (peekCaretPosition && isBeforeContentEditableFalseFn(peekCaretPosition)) {
        if (isMoveInsideSameBlock(nextCaretPosition, peekCaretPosition)) {
          return deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, peekCaretPosition);
        }
      }
      return false;
    };
    var backspaceDelete$6 = function (editor, forward) {
      return deleteCefBoundaryText(editor, forward);
    };
    var CefBoundaryDelete = { backspaceDelete: backspaceDelete$6 };

    var nativeCommand = function (editor, command) {
      editor.getDoc().execCommand(command, false, null);
    };
    var deleteCommand = function (editor) {
      if (CefDelete.backspaceDelete(editor, false)) {
        return;
      } else if (CefBoundaryDelete.backspaceDelete(editor, false)) {
        return;
      } else if (InlineBoundaryDelete.backspaceDelete(editor, false)) {
        return;
      } else if (BlockBoundaryDelete.backspaceDelete(editor, false)) {
        return;
      } else if (TableDelete.backspaceDelete(editor)) {
        return;
      } else if (BlockRangeDelete.backspaceDelete(editor, false)) {
        return;
      } else if (InlineFormatDelete.backspaceDelete(editor, false)) {
        return;
      } else {
        nativeCommand(editor, 'Delete');
        DeleteUtils.paddEmptyBody(editor);
      }
    };
    var forwardDeleteCommand = function (editor) {
      if (CefDelete.backspaceDelete(editor, true)) {
        return;
      } else if (CefBoundaryDelete.backspaceDelete(editor, true)) {
        return;
      } else if (InlineBoundaryDelete.backspaceDelete(editor, true)) {
        return;
      } else if (BlockBoundaryDelete.backspaceDelete(editor, true)) {
        return;
      } else if (TableDelete.backspaceDelete(editor)) {
        return;
      } else if (BlockRangeDelete.backspaceDelete(editor, true)) {
        return;
      } else if (InlineFormatDelete.backspaceDelete(editor, true)) {
        return;
      } else {
        nativeCommand(editor, 'ForwardDelete');
      }
    };
    var DeleteCommands = {
      deleteCommand: deleteCommand,
      forwardDeleteCommand: forwardDeleteCommand
    };

    var getSpecifiedFontProp = function (propName, rootElm, elm) {
      var getProperty = function (elm) {
        return getRaw(elm, propName);
      };
      var isRoot = function (elm) {
        return eq(Element.fromDom(rootElm), elm);
      };
      return closest(Element.fromDom(elm), function (elm) {
        return getProperty(elm).isSome();
      }, isRoot).bind(getProperty);
    };
    var round$1 = function (number, precision) {
      var factor = Math.pow(10, precision);
      return Math.round(number * factor) / factor;
    };
    var toPt = function (fontSize, precision) {
      if (/[0-9.]+px$/.test(fontSize)) {
        return round$1(parseInt(fontSize, 10) * 72 / 96, precision || 0) + 'pt';
      }
      return fontSize;
    };
    var normalizeFontFamily = function (fontFamily) {
      return fontFamily.replace(/[\'\"\\]/g, '').replace(/,\s+/g, ',');
    };
    var getComputedFontProp = function (propName, elm) {
      return Option.from(DOMUtils$1.DOM.getStyle(elm, propName, true));
    };
    var getFontProp = function (propName) {
      return function (rootElm, elm) {
        return Option.from(elm).map(Element.fromDom).filter(isElement).bind(function (element) {
          return getSpecifiedFontProp(propName, rootElm, element.dom()).or(getComputedFontProp(propName, element.dom()));
        }).getOr('');
      };
    };
    var FontInfo = {
      getFontSize: getFontProp('font-size'),
      getFontFamily: compose(normalizeFontFamily, getFontProp('font-family')),
      toPt: toPt
    };

    var findFirstCaretElement = function (editor) {
      return CaretFinder.firstPositionIn(editor.getBody()).map(function (caret) {
        var container = caret.container();
        return NodeType.isText(container) ? container.parentNode : container;
      });
    };
    var isRangeAtStartOfNode = function (rng, root) {
      return rng.startContainer === root && rng.startOffset === 0;
    };
    var getCaretElement = function (editor) {
      return Option.from(editor.selection.getRng()).bind(function (rng) {
        var root = editor.getBody();
        return isRangeAtStartOfNode(rng, root) ? Option.none() : Option.from(editor.selection.getStart(true));
      });
    };
    var fromFontSizeNumber = function (editor, value) {
      if (/^[0-9\.]+$/.test(value)) {
        var fontSizeNumber = parseInt(value, 10);
        if (fontSizeNumber >= 1 && fontSizeNumber <= 7) {
          var fontSizes = Settings.getFontStyleValues(editor);
          var fontClasses = Settings.getFontSizeClasses(editor);
          if (fontClasses) {
            return fontClasses[fontSizeNumber - 1] || value;
          } else {
            return fontSizes[fontSizeNumber - 1] || value;
          }
        } else {
          return value;
        }
      } else {
        return value;
      }
    };
    var fontNameAction = function (editor, value) {
      editor.formatter.toggle('fontname', { value: fromFontSizeNumber(editor, value) });
      editor.nodeChanged();
    };
    var fontNameQuery = function (editor) {
      return getCaretElement(editor).fold(function () {
        return findFirstCaretElement(editor).map(function (caretElement) {
          return FontInfo.getFontFamily(editor.getBody(), caretElement);
        }).getOr('');
      }, function (caretElement) {
        return FontInfo.getFontFamily(editor.getBody(), caretElement);
      });
    };
    var fontSizeAction = function (editor, value) {
      editor.formatter.toggle('fontsize', { value: fromFontSizeNumber(editor, value) });
      editor.nodeChanged();
    };
    var fontSizeQuery = function (editor) {
      return getCaretElement(editor).fold(function () {
        return findFirstCaretElement(editor).map(function (caretElement) {
          return FontInfo.getFontSize(editor.getBody(), caretElement);
        }).getOr('');
      }, function (caretElement) {
        return FontInfo.getFontSize(editor.getBody(), caretElement);
      });
    };

    var isEq$3 = function (rng1, rng2) {
      return rng1 && rng2 && (rng1.startContainer === rng2.startContainer && rng1.startOffset === rng2.startOffset) && (rng1.endContainer === rng2.endContainer && rng1.endOffset === rng2.endOffset);
    };
    var RangeCompare = { isEq: isEq$3 };

    var findParent = function (node, rootNode, predicate) {
      while (node && node !== rootNode) {
        if (predicate(node)) {
          return node;
        }
        node = node.parentNode;
      }
      return null;
    };
    var hasParent = function (node, rootNode, predicate) {
      return findParent(node, rootNode, predicate) !== null;
    };
    var hasParentWithName = function (node, rootNode, name) {
      return hasParent(node, rootNode, function (node) {
        return node.nodeName === name;
      });
    };
    var isTable$2 = function (node) {
      return node && node.nodeName === 'TABLE';
    };
    var isTableCell$3 = function (node) {
      return node && /^(TD|TH|CAPTION)$/.test(node.nodeName);
    };
    var isCeFalseCaretContainer = function (node, rootNode) {
      return isCaretContainer(node) && hasParent(node, rootNode, isCaretNode) === false;
    };
    var hasBrBeforeAfter = function (dom, node, left) {
      var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || dom.getRoot());
      while (node = walker[left ? 'prev' : 'next']()) {
        if (NodeType.isBr(node)) {
          return true;
        }
      }
    };
    var isPrevNode = function (node, name) {
      return node.previousSibling && node.previousSibling.nodeName === name;
    };
    var hasContentEditableFalseParent = function (body, node) {
      while (node && node !== body) {
        if (NodeType.isContentEditableFalse(node)) {
          return true;
        }
        node = node.parentNode;
      }
      return false;
    };
    var findTextNodeRelative = function (dom, isAfterNode, collapsed, left, startNode) {
      var walker, lastInlineElement, parentBlockContainer;
      var body = dom.getRoot();
      var node;
      var nonEmptyElementsMap = dom.schema.getNonEmptyElements();
      parentBlockContainer = dom.getParent(startNode.parentNode, dom.isBlock) || body;
      if (left && NodeType.isBr(startNode) && isAfterNode && dom.isEmpty(parentBlockContainer)) {
        return Option.some(CaretPosition(startNode.parentNode, dom.nodeIndex(startNode)));
      }
      walker = new TreeWalker(startNode, parentBlockContainer);
      while (node = walker[left ? 'prev' : 'next']()) {
        if (dom.getContentEditableParent(node) === 'false' || isCeFalseCaretContainer(node, body)) {
          return Option.none();
        }
        if (NodeType.isText(node) && node.nodeValue.length > 0) {
          if (hasParentWithName(node, body, 'A') === false) {
            return Option.some(CaretPosition(node, left ? node.nodeValue.length : 0));
          }
          return Option.none();
        }
        if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
          return Option.none();
        }
        lastInlineElement = node;
      }
      if (collapsed && lastInlineElement) {
        return Option.some(CaretPosition(lastInlineElement, 0));
      }
      return Option.none();
    };
    var normalizeEndPoint = function (dom, collapsed, start, rng) {
      var container, offset, walker;
      var body = dom.getRoot();
      var node, nonEmptyElementsMap;
      var directionLeft, isAfterNode, normalized = false;
      container = rng[(start ? 'start' : 'end') + 'Container'];
      offset = rng[(start ? 'start' : 'end') + 'Offset'];
      isAfterNode = NodeType.isElement(container) && offset === container.childNodes.length;
      nonEmptyElementsMap = dom.schema.getNonEmptyElements();
      directionLeft = start;
      if (isCaretContainer(container)) {
        return Option.none();
      }
      if (NodeType.isElement(container) && offset > container.childNodes.length - 1) {
        directionLeft = false;
      }
      if (NodeType.isDocument(container)) {
        container = body;
        offset = 0;
      }
      if (container === body) {
        if (directionLeft) {
          node = container.childNodes[offset > 0 ? offset - 1 : 0];
          if (node) {
            if (isCaretContainer(node)) {
              return Option.none();
            }
            if (nonEmptyElementsMap[node.nodeName] || isTable$2(node)) {
              return Option.none();
            }
          }
        }
        if (container.hasChildNodes()) {
          offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
          container = container.childNodes[offset];
          offset = NodeType.isText(container) && isAfterNode ? container.data.length : 0;
          if (!collapsed && container === body.lastChild && isTable$2(container)) {
            return Option.none();
          }
          if (hasContentEditableFalseParent(body, container) || isCaretContainer(container)) {
            return Option.none();
          }
          if (container.hasChildNodes() && isTable$2(container) === false) {
            node = container;
            walker = new TreeWalker(container, body);
            do {
              if (NodeType.isContentEditableFalse(node) || isCaretContainer(node)) {
                normalized = false;
                break;
              }
              if (NodeType.isText(node) && node.nodeValue.length > 0) {
                offset = directionLeft ? 0 : node.nodeValue.length;
                container = node;
                normalized = true;
                break;
              }
              if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCell$3(node)) {
                offset = dom.nodeIndex(node);
                container = node.parentNode;
                if (!directionLeft) {
                  offset++;
                }
                normalized = true;
                break;
              }
            } while (node = directionLeft ? walker.next() : walker.prev());
          }
        }
      }
      if (collapsed) {
        if (NodeType.isText(container) && offset === 0) {
          findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(function (pos) {
            container = pos.container();
            offset = pos.offset();
            normalized = true;
          });
        }
        if (NodeType.isElement(container)) {
          node = container.childNodes[offset];
          if (!node) {
            node = container.childNodes[offset - 1];
          }
          if (node && NodeType.isBr(node) && !isPrevNode(node, 'A') && !hasBrBeforeAfter(dom, node, false) && !hasBrBeforeAfter(dom, node, true)) {
            findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(function (pos) {
              container = pos.container();
              offset = pos.offset();
              normalized = true;
            });
          }
        }
      }
      if (directionLeft && !collapsed && NodeType.isText(container) && offset === container.nodeValue.length) {
        findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(function (pos) {
          container = pos.container();
          offset = pos.offset();
          normalized = true;
        });
      }
      return normalized ? Option.some(CaretPosition(container, offset)) : Option.none();
    };
    var normalize$2 = function (dom, rng) {
      var collapsed = rng.collapsed, normRng = rng.cloneRange();
      var startPos = CaretPosition.fromRangeStart(rng);
      normalizeEndPoint(dom, collapsed, true, normRng).each(function (pos) {
        if (!collapsed || !CaretPosition.isAbove(startPos, pos)) {
          normRng.setStart(pos.container(), pos.offset());
        }
      });
      if (!collapsed) {
        normalizeEndPoint(dom, collapsed, false, normRng).each(function (pos) {
          normRng.setEnd(pos.container(), pos.offset());
        });
      }
      if (collapsed) {
        normRng.collapse(true);
      }
      return RangeCompare.isEq(rng, normRng) ? Option.none() : Option.some(normRng);
    };
    var NormalizeRange = { normalize: normalize$2 };

    var hasRightSideContent = function (schema, container, parentBlock) {
      var walker = new TreeWalker(container, parentBlock);
      var node;
      var nonEmptyElementsMap = schema.getNonEmptyElements();
      while (node = walker.next()) {
        if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || node.length > 0) {
          return true;
        }
      }
    };
    var scrollToBr = function (dom, selection, brElm) {
      var marker = dom.create('span', {}, '&nbsp;');
      brElm.parentNode.insertBefore(marker, brElm);
      selection.scrollIntoView(marker);
      dom.remove(marker);
    };
    var moveSelectionToBr = function (dom, selection, brElm, extraBr) {
      var rng = dom.createRng();
      if (!extraBr) {
        rng.setStartAfter(brElm);
        rng.setEndAfter(brElm);
      } else {
        rng.setStartBefore(brElm);
        rng.setEndBefore(brElm);
      }
      selection.setRng(rng);
    };
    var insertBrAtCaret = function (editor, evt) {
      var selection = editor.selection;
      var dom = editor.dom;
      var rng = selection.getRng();
      var brElm;
      var extraBr;
      NormalizeRange.normalize(dom, rng).each(function (normRng) {
        rng.setStart(normRng.startContainer, normRng.startOffset);
        rng.setEnd(normRng.endContainer, normRng.endOffset);
      });
      var offset = rng.startOffset;
      var container = rng.startContainer;
      if (container.nodeType === 1 && container.hasChildNodes()) {
        var isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
        if (isAfterLastNodeInContainer && container.nodeType === 3) {
          offset = container.nodeValue.length;
        } else {
          offset = 0;
        }
      }
      var parentBlock = dom.getParent(container, dom.isBlock);
      var containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
      var containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
      var isControlKey = evt && evt.ctrlKey;
      if (containerBlockName === 'LI' && !isControlKey) {
        parentBlock = containerBlock;
      }
      if (container && container.nodeType === 3 && offset >= container.nodeValue.length) {
        if (!hasRightSideContent(editor.schema, container, parentBlock)) {
          brElm = dom.create('br');
          rng.insertNode(brElm);
          rng.setStartAfter(brElm);
          rng.setEndAfter(brElm);
          extraBr = true;
        }
      }
      brElm = dom.create('br');
      rangeInsertNode(dom, rng, brElm);
      scrollToBr(dom, selection, brElm);
      moveSelectionToBr(dom, selection, brElm, extraBr);
      editor.undoManager.add();
    };
    var insertBrBefore = function (editor, inline) {
      var br = Element.fromTag('br');
      before(Element.fromDom(inline), br);
      editor.undoManager.add();
    };
    var insertBrAfter = function (editor, inline) {
      if (!hasBrAfter(editor.getBody(), inline)) {
        after(Element.fromDom(inline), Element.fromTag('br'));
      }
      var br = Element.fromTag('br');
      after(Element.fromDom(inline), br);
      scrollToBr(editor.dom, editor.selection, br.dom());
      moveSelectionToBr(editor.dom, editor.selection, br.dom(), false);
      editor.undoManager.add();
    };
    var isBeforeBr$1 = function (pos) {
      return NodeType.isBr(pos.getNode());
    };
    var hasBrAfter = function (rootNode, startNode) {
      if (isBeforeBr$1(CaretPosition$1.after(startNode))) {
        return true;
      } else {
        return CaretFinder.nextPosition(rootNode, CaretPosition$1.after(startNode)).map(function (pos) {
          return NodeType.isBr(pos.getNode());
        }).getOr(false);
      }
    };
    var isAnchorLink = function (elm) {
      return elm && elm.nodeName === 'A' && 'href' in elm;
    };
    var isInsideAnchor = function (location) {
      return location.fold(constant(false), isAnchorLink, isAnchorLink, constant(false));
    };
    var readInlineAnchorLocation = function (editor) {
      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
      var position = CaretPosition$1.fromRangeStart(editor.selection.getRng());
      return BoundaryLocation.readLocation(isInlineTarget, editor.getBody(), position).filter(isInsideAnchor);
    };
    var insertBrOutsideAnchor = function (editor, location) {
      location.fold(noop, curry(insertBrBefore, editor), curry(insertBrAfter, editor), noop);
    };
    var insert = function (editor, evt) {
      var anchorLocation = readInlineAnchorLocation(editor);
      if (anchorLocation.isSome()) {
        anchorLocation.each(curry(insertBrOutsideAnchor, editor));
      } else {
        insertBrAtCaret(editor, evt);
      }
    };
    var InsertBr = { insert: insert };

    var create$3 = Immutable('start', 'soffset', 'finish', 'foffset');
    var SimRange = { create: create$3 };

    var adt = Adt.generate([
      { before: ['element'] },
      {
        on: [
          'element',
          'offset'
        ]
      },
      { after: ['element'] }
    ]);
    var cata = function (subject, onBefore, onOn, onAfter) {
      return subject.fold(onBefore, onOn, onAfter);
    };
    var getStart = function (situ) {
      return situ.fold(identity, identity, identity);
    };
    var before$4 = adt.before;
    var on = adt.on;
    var after$3 = adt.after;
    var Situ = {
      before: before$4,
      on: on,
      after: after$3,
      cata: cata,
      getStart: getStart
    };

    var adt$1 = Adt.generate([
      { domRange: ['rng'] },
      {
        relative: [
          'startSitu',
          'finishSitu'
        ]
      },
      {
        exact: [
          'start',
          'soffset',
          'finish',
          'foffset'
        ]
      }
    ]);
    var exactFromRange = function (simRange) {
      return adt$1.exact(simRange.start(), simRange.soffset(), simRange.finish(), simRange.foffset());
    };
    var getStart$1 = function (selection) {
      return selection.match({
        domRange: function (rng) {
          return Element.fromDom(rng.startContainer);
        },
        relative: function (startSitu, finishSitu) {
          return Situ.getStart(startSitu);
        },
        exact: function (start, soffset, finish, foffset) {
          return start;
        }
      });
    };
    var domRange = adt$1.domRange;
    var relative = adt$1.relative;
    var exact = adt$1.exact;
    var getWin = function (selection) {
      var start = getStart$1(selection);
      return defaultView(start);
    };
    var range = SimRange.create;
    var Selection = {
      domRange: domRange,
      relative: relative,
      exact: exact,
      exactFromRange: exactFromRange,
      getWin: getWin,
      range: range
    };

    var browser$3 = PlatformDetection$1.detect().browser;
    var clamp = function (offset, element) {
      var max = isText(element) ? get$4(element).length : children(element).length + 1;
      if (offset > max) {
        return max;
      } else if (offset < 0) {
        return 0;
      }
      return offset;
    };
    var normalizeRng = function (rng) {
      return Selection.range(rng.start(), clamp(rng.soffset(), rng.start()), rng.finish(), clamp(rng.foffset(), rng.finish()));
    };
    var isOrContains = function (root, elm) {
      return !NodeType.isRestrictedNode(elm.dom()) && (contains$3(root, elm) || eq(root, elm));
    };
    var isRngInRoot = function (root) {
      return function (rng) {
        return isOrContains(root, rng.start()) && isOrContains(root, rng.finish());
      };
    };
    var shouldStore = function (editor) {
      return editor.inline === true || browser$3.isIE();
    };
    var nativeRangeToSelectionRange = function (r) {
      return Selection.range(Element.fromDom(r.startContainer), r.startOffset, Element.fromDom(r.endContainer), r.endOffset);
    };
    var readRange = function (win) {
      var selection = win.getSelection();
      var rng = !selection || selection.rangeCount === 0 ? Option.none() : Option.from(selection.getRangeAt(0));
      return rng.map(nativeRangeToSelectionRange);
    };
    var getBookmark$2 = function (root) {
      var win = defaultView(root);
      return readRange(win.dom()).filter(isRngInRoot(root));
    };
    var validate = function (root, bookmark) {
      return Option.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng);
    };
    var bookmarkToNativeRng = function (bookmark) {
      var rng = domGlobals.document.createRange();
      try {
        rng.setStart(bookmark.start().dom(), bookmark.soffset());
        rng.setEnd(bookmark.finish().dom(), bookmark.foffset());
        return Option.some(rng);
      } catch (_) {
        return Option.none();
      }
    };
    var store = function (editor) {
      var newBookmark = shouldStore(editor) ? getBookmark$2(Element.fromDom(editor.getBody())) : Option.none();
      editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
    };
    var storeNative = function (editor, rng) {
      var root = Element.fromDom(editor.getBody());
      var range = shouldStore(editor) ? Option.from(rng) : Option.none();
      var newBookmark = range.map(nativeRangeToSelectionRange).filter(isRngInRoot(root));
      editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
    };
    var getRng = function (editor) {
      var bookmark = editor.bookmark ? editor.bookmark : Option.none();
      return bookmark.bind(curry(validate, Element.fromDom(editor.getBody()))).bind(bookmarkToNativeRng);
    };
    var restore = function (editor) {
      getRng(editor).each(function (rng) {
        editor.selection.setRng(rng);
      });
    };
    var SelectionBookmark = {
      store: store,
      storeNative: storeNative,
      readRange: readRange,
      restore: restore,
      getRng: getRng,
      getBookmark: getBookmark$2,
      validate: validate
    };

    var indentElement = function (dom, command, useMargin, value, unit, element) {
      if (dom.getContentEditable(element) === 'false') {
        return;
      }
      var indentStyleName = useMargin ? 'margin' : 'padding';
      indentStyleName = element.nodeName === 'TABLE' ? 'margin' : indentStyleName;
      indentStyleName += dom.getStyle(element, 'direction', true) === 'rtl' ? 'Right' : 'Left';
      if (command === 'outdent') {
        var styleValue = Math.max(0, parseInt(element.style[indentStyleName] || 0, 10) - value);
        dom.setStyle(element, indentStyleName, styleValue ? styleValue + unit : '');
      } else {
        var styleValue = parseInt(element.style[indentStyleName] || 0, 10) + value + unit;
        dom.setStyle(element, indentStyleName, styleValue);
      }
    };
    var isListComponent = function (el) {
      return isList(el) || isListItem(el);
    };
    var parentIsListComponent = function (el) {
      return parent(el).map(isListComponent).getOr(false);
    };
    var getBlocksToIndent = function (editor) {
      return filter(map(editor.selection.getSelectedBlocks(), Element.fromDom), function (el) {
        return !isListComponent(el) && !parentIsListComponent(el);
      });
    };
    var handle = function (editor, command) {
      var settings = editor.settings, dom = editor.dom, selection = editor.selection, formatter = editor.formatter;
      var indentUnit = /[a-z%]+$/i.exec(settings.indentation)[0];
      var indentValue = parseInt(settings.indentation, 10);
      var useMargin = editor.getParam('indent_use_margin', false);
      if (!editor.queryCommandState('InsertUnorderedList') && !editor.queryCommandState('InsertOrderedList')) {
        if (!settings.forced_root_block && !dom.getParent(selection.getNode(), dom.isBlock)) {
          formatter.apply('div');
        }
      }
      each(getBlocksToIndent(editor), function (block) {
        indentElement(dom, command, useMargin, indentValue, indentUnit, block.dom());
      });
    };

    var each$a = Tools.each, extend$2 = Tools.extend;
    var map$3 = Tools.map, inArray$2 = Tools.inArray;
    function EditorCommands (editor) {
      var dom, selection, formatter;
      var commands = {
        state: {},
        exec: {},
        value: {}
      };
      var settings = editor.settings, bookmark;
      editor.on('PreInit', function () {
        dom = editor.dom;
        selection = editor.selection;
        settings = editor.settings;
        formatter = editor.formatter;
      });
      var execCommand = function (command, ui, value, args) {
        var func, customCommand, state = false;
        if (editor.removed) {
          return;
        }
        if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(command) && (!args || !args.skip_focus)) {
          editor.focus();
        } else {
          SelectionBookmark.restore(editor);
        }
        args = editor.fire('BeforeExecCommand', {
          command: command,
          ui: ui,
          value: value
        });
        if (args.isDefaultPrevented()) {
          return false;
        }
        customCommand = command.toLowerCase();
        if (func = commands.exec[customCommand]) {
          func(customCommand, ui, value);
          editor.fire('ExecCommand', {
            command: command,
            ui: ui,
            value: value
          });
          return true;
        }
        each$a(editor.plugins, function (p) {
          if (p.execCommand && p.execCommand(command, ui, value)) {
            editor.fire('ExecCommand', {
              command: command,
              ui: ui,
              value: value
            });
            state = true;
            return false;
          }
        });
        if (state) {
          return state;
        }
        if (editor.theme && editor.theme.execCommand && editor.theme.execCommand(command, ui, value)) {
          editor.fire('ExecCommand', {
            command: command,
            ui: ui,
            value: value
          });
          return true;
        }
        try {
          state = editor.getDoc().execCommand(command, ui, value);
        } catch (ex) {
        }
        if (state) {
          editor.fire('ExecCommand', {
            command: command,
            ui: ui,
            value: value
          });
          return true;
        }
        return false;
      };
      var queryCommandState = function (command) {
        var func;
        if (editor.quirks.isHidden() || editor.removed) {
          return;
        }
        command = command.toLowerCase();
        if (func = commands.state[command]) {
          return func(command);
        }
        try {
          return editor.getDoc().queryCommandState(command);
        } catch (ex) {
        }
        return false;
      };
      var queryCommandValue = function (command) {
        var func;
        if (editor.quirks.isHidden() || editor.removed) {
          return;
        }
        command = command.toLowerCase();
        if (func = commands.value[command]) {
          return func(command);
        }
        try {
          return editor.getDoc().queryCommandValue(command);
        } catch (ex) {
        }
      };
      var addCommands = function (commandList, type) {
        type = type || 'exec';
        each$a(commandList, function (callback, command) {
          each$a(command.toLowerCase().split(','), function (command) {
            commands[type][command] = callback;
          });
        });
      };
      var addCommand = function (command, callback, scope) {
        command = command.toLowerCase();
        commands.exec[command] = function (command, ui, value, args) {
          return callback.call(scope || editor, ui, value, args);
        };
      };
      var queryCommandSupported = function (command) {
        command = command.toLowerCase();
        if (commands.exec[command]) {
          return true;
        }
        try {
          return editor.getDoc().queryCommandSupported(command);
        } catch (ex) {
        }
        return false;
      };
      var addQueryStateHandler = function (command, callback, scope) {
        command = command.toLowerCase();
        commands.state[command] = function () {
          return callback.call(scope || editor);
        };
      };
      var addQueryValueHandler = function (command, callback, scope) {
        command = command.toLowerCase();
        commands.value[command] = function () {
          return callback.call(scope || editor);
        };
      };
      var hasCustomCommand = function (command) {
        command = command.toLowerCase();
        return !!commands.exec[command];
      };
      extend$2(this, {
        execCommand: execCommand,
        queryCommandState: queryCommandState,
        queryCommandValue: queryCommandValue,
        queryCommandSupported: queryCommandSupported,
        addCommands: addCommands,
        addCommand: addCommand,
        addQueryStateHandler: addQueryStateHandler,
        addQueryValueHandler: addQueryValueHandler,
        hasCustomCommand: hasCustomCommand
      });
      var execNativeCommand = function (command, ui, value) {
        if (ui === undefined) {
          ui = false;
        }
        if (value === undefined) {
          value = null;
        }
        return editor.getDoc().execCommand(command, ui, value);
      };
      var isFormatMatch = function (name) {
        return formatter.match(name);
      };
      var toggleFormat = function (name, value) {
        formatter.toggle(name, value ? { value: value } : undefined);
        editor.nodeChanged();
      };
      var storeSelection = function (type) {
        bookmark = selection.getBookmark(type);
      };
      var restoreSelection = function () {
        selection.moveToBookmark(bookmark);
      };
      addCommands({
        'mceResetDesignMode,mceBeginUndoLevel': function () {
        },
        'mceEndUndoLevel,mceAddUndoLevel': function () {
          editor.undoManager.add();
        },
        'Cut,Copy,Paste': function (command) {
          var doc = editor.getDoc();
          var failed;
          try {
            execNativeCommand(command);
          } catch (ex) {
            failed = true;
          }
          if (command === 'paste' && !doc.queryCommandEnabled(command)) {
            failed = true;
          }
          if (failed || !doc.queryCommandSupported(command)) {
            var msg = editor.translate('Your browser doesn\'t support direct access to the clipboard. ' + 'Please use the Ctrl+X/C/V keyboard shortcuts instead.');
            if (Env.mac) {
              msg = msg.replace(/Ctrl\+/g, '\u2318+');
            }
            editor.notificationManager.open({
              text: msg,
              type: 'error'
            });
          }
        },
        'unlink': function () {
          if (selection.isCollapsed()) {
            var elm = editor.dom.getParent(editor.selection.getStart(), 'a');
            if (elm) {
              editor.dom.remove(elm, true);
            }
            return;
          }
          formatter.remove('link');
        },
        'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull,JustifyNone': function (command) {
          var align = command.substring(7);
          if (align === 'full') {
            align = 'justify';
          }
          each$a('left,center,right,justify'.split(','), function (name) {
            if (align !== name) {
              formatter.remove('align' + name);
            }
          });
          if (align !== 'none') {
            toggleFormat('align' + align);
          }
        },
        'InsertUnorderedList,InsertOrderedList': function (command) {
          var listElm, listParent;
          execNativeCommand(command);
          listElm = dom.getParent(selection.getNode(), 'ol,ul');
          if (listElm) {
            listParent = listElm.parentNode;
            if (/^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) {
              storeSelection();
              dom.split(listParent, listElm);
              restoreSelection();
            }
          }
        },
        'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': function (command) {
          toggleFormat(command);
        },
        'ForeColor,HiliteColor': function (command, ui, value) {
          toggleFormat(command, value);
        },
        'FontName': function (command, ui, value) {
          fontNameAction(editor, value);
        },
        'FontSize': function (command, ui, value) {
          fontSizeAction(editor, value);
        },
        'RemoveFormat': function (command) {
          formatter.remove(command);
        },
        'mceBlockQuote': function () {
          toggleFormat('blockquote');
        },
        'FormatBlock': function (command, ui, value) {
          return toggleFormat(value || 'p');
        },
        'mceCleanup': function () {
          var bookmark = selection.getBookmark();
          editor.setContent(editor.getContent());
          selection.moveToBookmark(bookmark);
        },
        'mceRemoveNode': function (command, ui, value) {
          var node = value || selection.getNode();
          if (node !== editor.getBody()) {
            storeSelection();
            editor.dom.remove(node, true);
            restoreSelection();
          }
        },
        'mceSelectNodeDepth': function (command, ui, value) {
          var counter = 0;
          dom.getParent(selection.getNode(), function (node) {
            if (node.nodeType === 1 && counter++ === value) {
              selection.select(node);
              return false;
            }
          }, editor.getBody());
        },
        'mceSelectNode': function (command, ui, value) {
          selection.select(value);
        },
        'mceInsertContent': function (command, ui, value) {
          InsertContent.insertAtCaret(editor, value);
        },
        'mceInsertRawHTML': function (command, ui, value) {
          selection.setContent('tiny_mce_marker');
          var content = editor.getContent();
          editor.setContent(content.replace(/tiny_mce_marker/g, function () {
            return value;
          }));
        },
        'mceToggleFormat': function (command, ui, value) {
          toggleFormat(value);
        },
        'mceSetContent': function (command, ui, value) {
          editor.setContent(value);
        },
        'Indent,Outdent': function (command) {
          handle(editor, command);
        },
        'mceRepaint': function () {
        },
        'InsertHorizontalRule': function () {
          editor.execCommand('mceInsertContent', false, '<hr />');
        },
        'mceToggleVisualAid': function () {
          editor.hasVisual = !editor.hasVisual;
          editor.addVisual();
        },
        'mceReplaceContent': function (command, ui, value) {
          editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({ format: 'text' })));
        },
        'mceInsertLink': function (command, ui, value) {
          var anchor;
          if (typeof value === 'string') {
            value = { href: value };
          }
          anchor = dom.getParent(selection.getNode(), 'a');
          value.href = value.href.replace(' ', '%20');
          if (!anchor || !value.href) {
            formatter.remove('link');
          }
          if (value.href) {
            formatter.apply('link', value, anchor);
          }
        },
        'selectAll': function () {
          var editingHost = dom.getParent(selection.getStart(), NodeType.isContentEditableTrue);
          if (editingHost) {
            var rng = dom.createRng();
            rng.selectNodeContents(editingHost);
            selection.setRng(rng);
          }
        },
        'delete': function () {
          DeleteCommands.deleteCommand(editor);
        },
        'forwardDelete': function () {
          DeleteCommands.forwardDeleteCommand(editor);
        },
        'mceNewDocument': function () {
          editor.setContent('');
        },
        'InsertLineBreak': function (command, ui, value) {
          InsertBr.insert(editor, value);
          return true;
        }
      });
      var alignStates = function (name) {
        return function () {
          var nodes = selection.isCollapsed() ? [dom.getParent(selection.getNode(), dom.isBlock)] : selection.getSelectedBlocks();
          var matches = map$3(nodes, function (node) {
            return !!formatter.matchNode(node, name);
          });
          return inArray$2(matches, true) !== -1;
        };
      };
      addCommands({
        'JustifyLeft': alignStates('alignleft'),
        'JustifyCenter': alignStates('aligncenter'),
        'JustifyRight': alignStates('alignright'),
        'JustifyFull': alignStates('alignjustify'),
        'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': function (command) {
          return isFormatMatch(command);
        },
        'mceBlockQuote': function () {
          return isFormatMatch('blockquote');
        },
        'Outdent': function () {
          var node;
          if (settings.inline_styles) {
            if ((node = dom.getParent(selection.getStart(), dom.isBlock)) && parseInt(node.style.paddingLeft, 10) > 0) {
              return true;
            }
            if ((node = dom.getParent(selection.getEnd(), dom.isBlock)) && parseInt(node.style.paddingLeft, 10) > 0) {
              return true;
            }
          }
          return queryCommandState('InsertUnorderedList') || queryCommandState('InsertOrderedList') || !settings.inline_styles && !!dom.getParent(selection.getNode(), 'BLOCKQUOTE');
        },
        'InsertUnorderedList,InsertOrderedList': function (command) {
          var list = dom.getParent(selection.getNode(), 'ul,ol');
          return list && (command === 'insertunorderedlist' && list.tagName === 'UL' || command === 'insertorderedlist' && list.tagName === 'OL');
        }
      }, 'state');
      addCommands({
        Undo: function () {
          editor.undoManager.undo();
        },
        Redo: function () {
          editor.undoManager.redo();
        }
      });
      addQueryValueHandler('FontName', function () {
        return fontNameQuery(editor);
      }, this);
      addQueryValueHandler('FontSize', function () {
        return fontSizeQuery(editor);
      }, this);
    }

    var nativeEvents = Tools.makeMap('focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange ' + 'mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover ' + 'draggesture dragdrop drop drag submit ' + 'compositionstart compositionend compositionupdate touchstart touchmove touchend', ' ');
    var Dispatcher = function (settings) {
      var self = this;
      var scope, bindings = {}, toggleEvent;
      var returnFalse = function () {
        return false;
      };
      var returnTrue = function () {
        return true;
      };
      settings = settings || {};
      scope = settings.scope || self;
      toggleEvent = settings.toggleEvent || returnFalse;
      var fire = function (name, args) {
        var handlers, i, l, callback;
        name = name.toLowerCase();
        args = args || {};
        args.type = name;
        if (!args.target) {
          args.target = scope;
        }
        if (!args.preventDefault) {
          args.preventDefault = function () {
            args.isDefaultPrevented = returnTrue;
          };
          args.stopPropagation = function () {
            args.isPropagationStopped = returnTrue;
          };
          args.stopImmediatePropagation = function () {
            args.isImmediatePropagationStopped = returnTrue;
          };
          args.isDefaultPrevented = returnFalse;
          args.isPropagationStopped = returnFalse;
          args.isImmediatePropagationStopped = returnFalse;
        }
        if (settings.beforeFire) {
          settings.beforeFire(args);
        }
        handlers = bindings[name];
        if (handlers) {
          for (i = 0, l = handlers.length; i < l; i++) {
            callback = handlers[i];
            if (callback.once) {
              off(name, callback.func);
            }
            if (args.isImmediatePropagationStopped()) {
              args.stopPropagation();
              return args;
            }
            if (callback.func.call(scope, args) === false) {
              args.preventDefault();
              return args;
            }
          }
        }
        return args;
      };
      var on = function (name, callback, prepend, extra) {
        var handlers, names, i;
        if (callback === false) {
          callback = returnFalse;
        }
        if (callback) {
          callback = { func: callback };
          if (extra) {
            Tools.extend(callback, extra);
          }
          names = name.toLowerCase().split(' ');
          i = names.length;
          while (i--) {
            name = names[i];
            handlers = bindings[name];
            if (!handlers) {
              handlers = bindings[name] = [];
              toggleEvent(name, true);
            }
            if (prepend) {
              handlers.unshift(callback);
            } else {
              handlers.push(callback);
            }
          }
        }
        return self;
      };
      var off = function (name, callback) {
        var i, handlers, bindingName, names, hi;
        if (name) {
          names = name.toLowerCase().split(' ');
          i = names.length;
          while (i--) {
            name = names[i];
            handlers = bindings[name];
            if (!name) {
              for (bindingName in bindings) {
                toggleEvent(bindingName, false);
                delete bindings[bindingName];
              }
              return self;
            }
            if (handlers) {
              if (!callback) {
                handlers.length = 0;
              } else {
                hi = handlers.length;
                while (hi--) {
                  if (handlers[hi].func === callback) {
                    handlers = handlers.slice(0, hi).concat(handlers.slice(hi + 1));
                    bindings[name] = handlers;
                  }
                }
              }
              if (!handlers.length) {
                toggleEvent(name, false);
                delete bindings[name];
              }
            }
          }
        } else {
          for (name in bindings) {
            toggleEvent(name, false);
          }
          bindings = {};
        }
        return self;
      };
      var once = function (name, callback, prepend) {
        return on(name, callback, prepend, { once: true });
      };
      var has = function (name) {
        name = name.toLowerCase();
        return !(!bindings[name] || bindings[name].length === 0);
      };
      self.fire = fire;
      self.on = on;
      self.off = off;
      self.once = once;
      self.has = has;
    };
    Dispatcher.isNative = function (name) {
      return !!nativeEvents[name.toLowerCase()];
    };

    var getEventDispatcher = function (obj) {
      if (!obj._eventDispatcher) {
        obj._eventDispatcher = new Dispatcher({
          scope: obj,
          toggleEvent: function (name, state) {
            if (Dispatcher.isNative(name) && obj.toggleNativeEvent) {
              obj.toggleNativeEvent(name, state);
            }
          }
        });
      }
      return obj._eventDispatcher;
    };
    var Observable = {
      fire: function (name, args, bubble) {
        var self = this;
        if (self.removed && name !== 'remove' && name !== 'detach') {
          return args;
        }
        args = getEventDispatcher(self).fire(name, args, bubble);
        if (bubble !== false && self.parent) {
          var parent = self.parent();
          while (parent && !args.isPropagationStopped()) {
            parent.fire(name, args, false);
            parent = parent.parent();
          }
        }
        return args;
      },
      on: function (name, callback, prepend) {
        return getEventDispatcher(this).on(name, callback, prepend);
      },
      off: function (name, callback) {
        return getEventDispatcher(this).off(name, callback);
      },
      once: function (name, callback) {
        return getEventDispatcher(this).once(name, callback);
      },
      hasEventListeners: function (name) {
        return getEventDispatcher(this).has(name);
      }
    };

    var firePreProcess = function (editor, args) {
      return editor.fire('PreProcess', args);
    };
    var firePostProcess = function (editor, args) {
      return editor.fire('PostProcess', args);
    };
    var fireRemove = function (editor) {
      return editor.fire('remove');
    };
    var fireDetach = function (editor) {
      return editor.fire('detach');
    };
    var fireSwitchMode = function (editor, mode) {
      return editor.fire('SwitchMode', { mode: mode });
    };
    var fireObjectResizeStart = function (editor, target, width, height) {
      editor.fire('ObjectResizeStart', {
        target: target,
        width: width,
        height: height
      });
    };
    var fireObjectResized = function (editor, target, width, height) {
      editor.fire('ObjectResized', {
        target: target,
        width: width,
        height: height
      });
    };
    var Events = {
      firePreProcess: firePreProcess,
      firePostProcess: firePostProcess,
      fireRemove: fireRemove,
      fireDetach: fireDetach,
      fireSwitchMode: fireSwitchMode,
      fireObjectResizeStart: fireObjectResizeStart,
      fireObjectResized: fireObjectResized
    };

    var setEditorCommandState = function (editor, cmd, state) {
      try {
        editor.getDoc().execCommand(cmd, false, state);
      } catch (ex) {
      }
    };
    var toggleClass = function (elm, cls, state) {
      if (has$2(elm, cls) && state === false) {
        remove$4(elm, cls);
      } else if (state) {
        add$2(elm, cls);
      }
    };
    var toggleReadOnly = function (editor, state) {
      toggleClass(Element.fromDom(editor.getBody()), 'mce-content-readonly', state);
      if (state) {
        editor.selection.controlSelection.hideResizeRect();
        editor.readonly = true;
        editor.getBody().contentEditable = 'false';
      } else {
        editor.readonly = false;
        editor.getBody().contentEditable = 'true';
        setEditorCommandState(editor, 'StyleWithCSS', false);
        setEditorCommandState(editor, 'enableInlineTableEditing', false);
        setEditorCommandState(editor, 'enableObjectResizing', false);
        editor.focus();
        editor.nodeChanged();
      }
    };
    var setMode = function (editor, mode) {
      if (mode === getMode(editor)) {
        return;
      }
      if (editor.initialized) {
        toggleReadOnly(editor, mode === 'readonly');
      } else {
        editor.on('init', function () {
          toggleReadOnly(editor, mode === 'readonly');
        });
      }
      Events.fireSwitchMode(editor, mode);
    };
    var getMode = function (editor) {
      return editor.readonly ? 'readonly' : 'design';
    };
    var isReadOnly = function (editor) {
      return editor.readonly === true;
    };

    var DOM$1 = DOMUtils$1.DOM;
    var customEventRootDelegates;
    var getEventTarget = function (editor, eventName) {
      if (eventName === 'selectionchange') {
        return editor.getDoc();
      }
      if (!editor.inline && /^mouse|touch|click|contextmenu|drop|dragover|dragend/.test(eventName)) {
        return editor.getDoc().documentElement;
      }
      if (editor.settings.event_root) {
        if (!editor.eventRoot) {
          editor.eventRoot = DOM$1.select(editor.settings.event_root)[0];
        }
        return editor.eventRoot;
      }
      return editor.getBody();
    };
    var isListening = function (editor) {
      return !editor.hidden && !editor.readonly;
    };
    var fireEvent = function (editor, eventName, e) {
      if (isListening(editor)) {
        editor.fire(eventName, e);
      } else if (isReadOnly(editor)) {
        e.preventDefault();
      }
    };
    var bindEventDelegate = function (editor, eventName) {
      var eventRootElm, delegate;
      if (!editor.delegates) {
        editor.delegates = {};
      }
      if (editor.delegates[eventName] || editor.removed) {
        return;
      }
      eventRootElm = getEventTarget(editor, eventName);
      if (editor.settings.event_root) {
        if (!customEventRootDelegates) {
          customEventRootDelegates = {};
          editor.editorManager.on('removeEditor', function () {
            var name;
            if (!editor.editorManager.activeEditor) {
              if (customEventRootDelegates) {
                for (name in customEventRootDelegates) {
                  editor.dom.unbind(getEventTarget(editor, name));
                }
                customEventRootDelegates = null;
              }
            }
          });
        }
        if (customEventRootDelegates[eventName]) {
          return;
        }
        delegate = function (e) {
          var target = e.target;
          var editors = editor.editorManager.get();
          var i = editors.length;
          while (i--) {
            var body = editors[i].getBody();
            if (body === target || DOM$1.isChildOf(target, body)) {
              fireEvent(editors[i], eventName, e);
            }
          }
        };
        customEventRootDelegates[eventName] = delegate;
        DOM$1.bind(eventRootElm, eventName, delegate);
      } else {
        delegate = function (e) {
          fireEvent(editor, eventName, e);
        };
        DOM$1.bind(eventRootElm, eventName, delegate);
        editor.delegates[eventName] = delegate;
      }
    };
    var EditorObservable = {
      bindPendingEventDelegates: function () {
        var self = this;
        Tools.each(self._pendingNativeEvents, function (name) {
          bindEventDelegate(self, name);
        });
      },
      toggleNativeEvent: function (name, state) {
        var self = this;
        if (name === 'focus' || name === 'blur') {
          return;
        }
        if (state) {
          if (self.initialized) {
            bindEventDelegate(self, name);
          } else {
            if (!self._pendingNativeEvents) {
              self._pendingNativeEvents = [name];
            } else {
              self._pendingNativeEvents.push(name);
            }
          }
        } else if (self.initialized) {
          self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
          delete self.delegates[name];
        }
      },
      unbindAllNativeEvents: function () {
        var self = this;
        var body = self.getBody();
        var dom = self.dom;
        var name;
        if (self.delegates) {
          for (name in self.delegates) {
            self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
          }
          delete self.delegates;
        }
        if (!self.inline && body && dom) {
          body.onload = null;
          dom.unbind(self.getWin());
          dom.unbind(self.getDoc());
        }
        if (dom) {
          dom.unbind(body);
          dom.unbind(self.getContainer());
        }
      }
    };
    EditorObservable = Tools.extend({}, Observable, EditorObservable);
    var EditorObservable$1 = EditorObservable;

    var sectionResult = Immutable('sections', 'settings');
    var detection = PlatformDetection$1.detect();
    var isTouch = detection.deviceType.isTouch();
    var mobilePlugins = [
      'lists',
      'autolink',
      'autosave'
    ];
    var defaultMobileSettings = { theme: 'mobile' };
    var normalizePlugins = function (plugins) {
      var pluginNames = isArray(plugins) ? plugins.join(' ') : plugins;
      var trimmedPlugins = map(isString(pluginNames) ? pluginNames.split(' ') : [], trim$2);
      return filter(trimmedPlugins, function (item) {
        return item.length > 0;
      });
    };
    var filterMobilePlugins = function (plugins) {
      return filter(plugins, curry(contains, mobilePlugins));
    };
    var extractSections = function (keys, settings) {
      var result = bifilter(settings, function (value, key) {
        return contains(keys, key);
      });
      return sectionResult(result.t, result.f);
    };
    var getSection = function (sectionResult, name, defaults) {
      var sections = sectionResult.sections();
      var sectionSettings = sections.hasOwnProperty(name) ? sections[name] : {};
      return Tools.extend({}, defaults, sectionSettings);
    };
    var hasSection = function (sectionResult, name) {
      return sectionResult.sections().hasOwnProperty(name);
    };
    var getDefaultSettings = function (id, documentBaseUrl, editor) {
      return {
        id: id,
        theme: 'modern',
        delta_width: 0,
        delta_height: 0,
        popup_css: '',
        plugins: '',
        document_base_url: documentBaseUrl,
        add_form_submit_trigger: true,
        submit_patch: true,
        add_unload_trigger: true,
        convert_urls: true,
        relative_urls: true,
        remove_script_host: true,
        object_resizing: true,
        doctype: '<!DOCTYPE html>',
        visual: true,
        font_size_style_values: 'xx-small,x-small,small,medium,large,x-large,xx-large',
        font_size_legacy_values: 'xx-small,small,medium,large,x-large,xx-large,300%',
        forced_root_block: 'p',
        hidden_input: true,
        render_ui: true,
        indentation: '40px',
        inline_styles: true,
        convert_fonts_to_spans: true,
        indent: 'simple',
        indent_before: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,' + 'tfoot,tbody,tr,section,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist',
        indent_after: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,' + 'tfoot,tbody,tr,section,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist',
        entity_encoding: 'named',
        url_converter: editor.convertURL,
        url_converter_scope: editor,
        ie7_compat: true
      };
    };
    var getExternalPlugins = function (overrideSettings, settings) {
      var userDefinedExternalPlugins = settings.external_plugins ? settings.external_plugins : {};
      if (overrideSettings && overrideSettings.external_plugins) {
        return Tools.extend({}, overrideSettings.external_plugins, userDefinedExternalPlugins);
      } else {
        return userDefinedExternalPlugins;
      }
    };
    var combinePlugins = function (forcedPlugins, plugins) {
      return [].concat(normalizePlugins(forcedPlugins)).concat(normalizePlugins(plugins));
    };
    var processPlugins = function (isTouchDevice, sectionResult, defaultOverrideSettings, settings) {
      var forcedPlugins = normalizePlugins(defaultOverrideSettings.forced_plugins);
      var plugins = normalizePlugins(settings.plugins);
      var platformPlugins = isTouchDevice && hasSection(sectionResult, 'mobile') ? filterMobilePlugins(plugins) : plugins;
      var combinedPlugins = combinePlugins(forcedPlugins, platformPlugins);
      return Tools.extend(settings, { plugins: combinedPlugins.join(' ') });
    };
    var isOnMobile = function (isTouchDevice, sectionResult) {
      var isInline = sectionResult.settings().inline;
      return isTouchDevice && hasSection(sectionResult, 'mobile') && !isInline;
    };
    var combineSettings = function (isTouchDevice, defaultSettings, defaultOverrideSettings, settings) {
      var sectionResult = extractSections(['mobile'], settings);
      var extendedSettings = Tools.extend(defaultSettings, defaultOverrideSettings, sectionResult.settings(), isOnMobile(isTouchDevice, sectionResult) ? getSection(sectionResult, 'mobile', defaultMobileSettings) : {}, {
        validate: true,
        content_editable: sectionResult.settings().inline,
        external_plugins: getExternalPlugins(defaultOverrideSettings, sectionResult.settings())
      });
      return processPlugins(isTouchDevice, sectionResult, defaultOverrideSettings, extendedSettings);
    };
    var getEditorSettings = function (editor, id, documentBaseUrl, defaultOverrideSettings, settings) {
      var defaultSettings = getDefaultSettings(id, documentBaseUrl, editor);
      return combineSettings(isTouch, defaultSettings, defaultOverrideSettings, settings);
    };
    var getFiltered = function (predicate, editor, name) {
      return Option.from(editor.settings[name]).filter(predicate);
    };
    var getParamObject = function (value) {
      var output = {};
      if (typeof value === 'string') {
        each(value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(','), function (val) {
          var arr = val.split('=');
          if (arr.length > 1) {
            output[Tools.trim(arr[0])] = Tools.trim(arr[1]);
          } else {
            output[Tools.trim(arr[0])] = Tools.trim(arr);
          }
        });
      } else {
        output = value;
      }
      return output;
    };
    var isArrayOf = function (p) {
      return function (a) {
        return isArray(a) && forall(a, p);
      };
    };
    var getParam = function (editor, name, defaultVal, type) {
      var value = name in editor.settings ? editor.settings[name] : defaultVal;
      if (type === 'hash') {
        return getParamObject(value);
      } else if (type === 'string') {
        return getFiltered(isString, editor, name).getOr(defaultVal);
      } else if (type === 'number') {
        return getFiltered(isNumber, editor, name).getOr(defaultVal);
      } else if (type === 'boolean') {
        return getFiltered(isBoolean, editor, name).getOr(defaultVal);
      } else if (type === 'object') {
        return getFiltered(isObject, editor, name).getOr(defaultVal);
      } else if (type === 'array') {
        return getFiltered(isArray, editor, name).getOr(defaultVal);
      } else if (type === 'string[]') {
        return getFiltered(isArrayOf(isString), editor, name).getOr(defaultVal);
      } else if (type === 'function') {
        return getFiltered(isFunction, editor, name).getOr(defaultVal);
      } else {
        return value;
      }
    };

    var each$b = Tools.each, explode$2 = Tools.explode;
    var keyCodeLookup = {
      f1: 112,
      f2: 113,
      f3: 114,
      f4: 115,
      f5: 116,
      f6: 117,
      f7: 118,
      f8: 119,
      f9: 120,
      f10: 121,
      f11: 122,
      f12: 123
    };
    var modifierNames = Tools.makeMap('alt,ctrl,shift,meta,access');
    function Shortcuts (editor) {
      var self = this;
      var shortcuts = {};
      var pendingPatterns = [];
      var parseShortcut = function (pattern) {
        var id, key;
        var shortcut = {};
        each$b(explode$2(pattern, '+'), function (value) {
          if (value in modifierNames) {
            shortcut[value] = true;
          } else {
            if (/^[0-9]{2,}$/.test(value)) {
              shortcut.keyCode = parseInt(value, 10);
            } else {
              shortcut.charCode = value.charCodeAt(0);
              shortcut.keyCode = keyCodeLookup[value] || value.toUpperCase().charCodeAt(0);
            }
          }
        });
        id = [shortcut.keyCode];
        for (key in modifierNames) {
          if (shortcut[key]) {
            id.push(key);
          } else {
            shortcut[key] = false;
          }
        }
        shortcut.id = id.join(',');
        if (shortcut.access) {
          shortcut.alt = true;
          if (Env.mac) {
            shortcut.ctrl = true;
          } else {
            shortcut.shift = true;
          }
        }
        if (shortcut.meta) {
          if (Env.mac) {
            shortcut.meta = true;
          } else {
            shortcut.ctrl = true;
            shortcut.meta = false;
          }
        }
        return shortcut;
      };
      var createShortcut = function (pattern, desc, cmdFunc, scope) {
        var shortcuts;
        shortcuts = Tools.map(explode$2(pattern, '>'), parseShortcut);
        shortcuts[shortcuts.length - 1] = Tools.extend(shortcuts[shortcuts.length - 1], {
          func: cmdFunc,
          scope: scope || editor
        });
        return Tools.extend(shortcuts[0], {
          desc: editor.translate(desc),
          subpatterns: shortcuts.slice(1)
        });
      };
      var hasModifier = function (e) {
        return e.altKey || e.ctrlKey || e.metaKey;
      };
      var isFunctionKey = function (e) {
        return e.type === 'keydown' && e.keyCode >= 112 && e.keyCode <= 123;
      };
      var matchShortcut = function (e, shortcut) {
        if (!shortcut) {
          return false;
        }
        if (shortcut.ctrl !== e.ctrlKey || shortcut.meta !== e.metaKey) {
          return false;
        }
        if (shortcut.alt !== e.altKey || shortcut.shift !== e.shiftKey) {
          return false;
        }
        if (e.keyCode === shortcut.keyCode || e.charCode && e.charCode === shortcut.charCode) {
          e.preventDefault();
          return true;
        }
        return false;
      };
      var executeShortcutAction = function (shortcut) {
        return shortcut.func ? shortcut.func.call(shortcut.scope) : null;
      };
      editor.on('keyup keypress keydown', function (e) {
        if ((hasModifier(e) || isFunctionKey(e)) && !e.isDefaultPrevented()) {
          each$b(shortcuts, function (shortcut) {
            if (matchShortcut(e, shortcut)) {
              pendingPatterns = shortcut.subpatterns.slice(0);
              if (e.type === 'keydown') {
                executeShortcutAction(shortcut);
              }
              return true;
            }
          });
          if (matchShortcut(e, pendingPatterns[0])) {
            if (pendingPatterns.length === 1) {
              if (e.type === 'keydown') {
                executeShortcutAction(pendingPatterns[0]);
              }
            }
            pendingPatterns.shift();
          }
        }
      });
      self.add = function (pattern, desc, cmdFunc, scope) {
        var cmd;
        cmd = cmdFunc;
        if (typeof cmdFunc === 'string') {
          cmdFunc = function () {
            editor.execCommand(cmd, false, null);
          };
        } else if (Tools.isArray(cmd)) {
          cmdFunc = function () {
            editor.execCommand(cmd[0], cmd[1], cmd[2]);
          };
        }
        each$b(explode$2(Tools.trim(pattern.toLowerCase())), function (pattern) {
          var shortcut = createShortcut(pattern, desc, cmdFunc, scope);
          shortcuts[shortcut.id] = shortcut;
        });
        return true;
      };
      self.remove = function (pattern) {
        var shortcut = createShortcut(pattern);
        if (shortcuts[shortcut.id]) {
          delete shortcuts[shortcut.id];
          return true;
        }
        return false;
      };
    }

    var hasFocus = function (element) {
      var doc = owner(element).dom();
      return element.dom() === doc.activeElement;
    };
    var active = function (_doc) {
      var doc = _doc !== undefined ? _doc.dom() : domGlobals.document;
      return Option.from(doc.activeElement).map(Element.fromDom);
    };
    var search = function (element) {
      return active(owner(element)).filter(function (e) {
        return element.dom().contains(e.dom());
      });
    };

    var getContentEditableHost = function (editor, node) {
      return editor.dom.getParent(node, function (node) {
        return editor.dom.getContentEditable(node) === 'true';
      });
    };
    var getCollapsedNode = function (rng) {
      return rng.collapsed ? Option.from(getNode(rng.startContainer, rng.startOffset)).map(Element.fromDom) : Option.none();
    };
    var getFocusInElement = function (root, rng) {
      return getCollapsedNode(rng).bind(function (node) {
        if (isTableSection(node)) {
          return Option.some(node);
        } else if (contains$3(root, node) === false) {
          return Option.some(root);
        } else {
          return Option.none();
        }
      });
    };
    var normalizeSelection = function (editor, rng) {
      getFocusInElement(Element.fromDom(editor.getBody()), rng).bind(function (elm) {
        return CaretFinder.firstPositionIn(elm.dom());
      }).fold(function () {
        editor.selection.normalize();
        return;
      }, function (caretPos) {
        return editor.selection.setRng(caretPos.toRange());
      });
    };
    var focusBody = function (body) {
      if (body.setActive) {
        try {
          body.setActive();
        } catch (ex) {
          body.focus();
        }
      } else {
        body.focus();
      }
    };
    var hasElementFocus = function (elm) {
      return hasFocus(elm) || search(elm).isSome();
    };
    var hasIframeFocus = function (editor) {
      return editor.iframeElement && hasFocus(Element.fromDom(editor.iframeElement));
    };
    var hasInlineFocus = function (editor) {
      var rawBody = editor.getBody();
      return rawBody && hasElementFocus(Element.fromDom(rawBody));
    };
    var hasFocus$1 = function (editor) {
      return editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor);
    };
    var focusEditor = function (editor) {
      var selection = editor.selection, contentEditable = editor.settings.content_editable;
      var body = editor.getBody();
      var rng = selection.getRng();
      editor.quirks.refreshContentEditable();
      var contentEditableHost = getContentEditableHost(editor, selection.getNode());
      if (editor.$.contains(body, contentEditableHost)) {
        focusBody(contentEditableHost);
        normalizeSelection(editor, rng);
        activateEditor(editor);
        return;
      }
      if (editor.bookmark !== undefined && hasFocus$1(editor) === false) {
        SelectionBookmark.getRng(editor).each(function (bookmarkRng) {
          editor.selection.setRng(bookmarkRng);
          rng = bookmarkRng;
        });
      }
      if (!contentEditable) {
        if (!Env.opera) {
          focusBody(body);
        }
        editor.getWin().focus();
      }
      if (Env.gecko || contentEditable) {
        focusBody(body);
        normalizeSelection(editor, rng);
      }
      activateEditor(editor);
    };
    var activateEditor = function (editor) {
      return editor.editorManager.setActive(editor);
    };
    var focus = function (editor, skipFocus) {
      if (editor.removed) {
        return;
      }
      skipFocus ? activateEditor(editor) : focusEditor(editor);
    };
    var EditorFocus = {
      focus: focus,
      hasFocus: hasFocus$1
    };

    var getProp = function (propName, elm) {
      var rawElm = elm.dom();
      return rawElm[propName];
    };
    var getComputedSizeProp = function (propName, elm) {
      return parseInt(get$1(elm, propName), 10);
    };
    var getClientWidth = curry(getProp, 'clientWidth');
    var getClientHeight = curry(getProp, 'clientHeight');
    var getMarginTop = curry(getComputedSizeProp, 'margin-top');
    var getMarginLeft = curry(getComputedSizeProp, 'margin-left');
    var getBoundingClientRect$1 = function (elm) {
      return elm.dom().getBoundingClientRect();
    };
    var isInsideElementContentArea = function (bodyElm, clientX, clientY) {
      var clientWidth = getClientWidth(bodyElm);
      var clientHeight = getClientHeight(bodyElm);
      return clientX >= 0 && clientY >= 0 && clientX <= clientWidth && clientY <= clientHeight;
    };
    var transpose = function (inline, elm, clientX, clientY) {
      var clientRect = getBoundingClientRect$1(elm);
      var deltaX = inline ? clientRect.left + elm.dom().clientLeft + getMarginLeft(elm) : 0;
      var deltaY = inline ? clientRect.top + elm.dom().clientTop + getMarginTop(elm) : 0;
      var x = clientX - deltaX;
      var y = clientY - deltaY;
      return {
        x: x,
        y: y
      };
    };
    var isXYInContentArea = function (editor, clientX, clientY) {
      var bodyElm = Element.fromDom(editor.getBody());
      var targetElm = editor.inline ? bodyElm : documentElement(bodyElm);
      var transposedPoint = transpose(editor.inline, targetElm, clientX, clientY);
      return isInsideElementContentArea(targetElm, transposedPoint.x, transposedPoint.y);
    };
    var fromDomSafe = function (node) {
      return Option.from(node).map(Element.fromDom);
    };
    var isEditorAttachedToDom = function (editor) {
      var rawContainer = editor.inline ? editor.getBody() : editor.getContentAreaContainer();
      return fromDomSafe(rawContainer).map(function (container) {
        return contains$3(owner(container), container);
      }).getOr(false);
    };
    var EditorView = {
      isXYInContentArea: isXYInContentArea,
      isEditorAttachedToDom: isEditorAttachedToDom
    };

    function NotificationManagerImpl () {
      var unimplemented = function () {
        throw new Error('Theme did not provide a NotificationManager implementation.');
      };
      return {
        open: unimplemented,
        close: unimplemented,
        reposition: unimplemented,
        getArgs: unimplemented
      };
    }

    function NotificationManager (editor) {
      var notifications = [];
      var getImplementation = function () {
        var theme = editor.theme;
        return theme && theme.getNotificationManagerImpl ? theme.getNotificationManagerImpl() : NotificationManagerImpl();
      };
      var getTopNotification = function () {
        return Option.from(notifications[0]);
      };
      var isEqual = function (a, b) {
        return a.type === b.type && a.text === b.text && !a.progressBar && !a.timeout && !b.progressBar && !b.timeout;
      };
      var reposition = function () {
        if (notifications.length > 0) {
          getImplementation().reposition(notifications);
        }
      };
      var addNotification = function (notification) {
        notifications.push(notification);
      };
      var closeNotification = function (notification) {
        findIndex(notifications, function (otherNotification) {
          return otherNotification === notification;
        }).each(function (index) {
          notifications.splice(index, 1);
        });
      };
      var open = function (args) {
        if (editor.removed || !EditorView.isEditorAttachedToDom(editor)) {
          return;
        }
        return find(notifications, function (notification) {
          return isEqual(getImplementation().getArgs(notification), args);
        }).getOrThunk(function () {
          editor.editorManager.setActive(editor);
          var notification = getImplementation().open(args, function () {
            closeNotification(notification);
            reposition();
          });
          addNotification(notification);
          reposition();
          return notification;
        });
      };
      var close = function () {
        getTopNotification().each(function (notification) {
          getImplementation().close(notification);
          closeNotification(notification);
          reposition();
        });
      };
      var getNotifications = function () {
        return notifications;
      };
      var registerEvents = function (editor) {
        editor.on('SkinLoaded', function () {
          var serviceMessage = editor.settings.service_message;
          if (serviceMessage) {
            open({
              text: serviceMessage,
              type: 'warning',
              timeout: 0,
              icon: ''
            });
          }
        });
        editor.on('ResizeEditor ResizeWindow', function () {
          Delay.requestAnimationFrame(reposition);
        });
        editor.on('remove', function () {
          each(notifications.slice(), function (notification) {
            getImplementation().close(notification);
          });
        });
      };
      registerEvents(editor);
      return {
        open: open,
        close: close,
        getNotifications: getNotifications
      };
    }

    function WindowManagerImpl () {
      var unimplemented = function () {
        throw new Error('Theme did not provide a WindowManager implementation.');
      };
      return {
        open: unimplemented,
        alert: unimplemented,
        confirm: unimplemented,
        close: unimplemented,
        getParams: unimplemented,
        setParams: unimplemented
      };
    }

    function WindowManager (editor) {
      var windows = [];
      var getImplementation = function () {
        var theme = editor.theme;
        return theme && theme.getWindowManagerImpl ? theme.getWindowManagerImpl() : WindowManagerImpl();
      };
      var funcBind = function (scope, f) {
        return function () {
          return f ? f.apply(scope, arguments) : undefined;
        };
      };
      var fireOpenEvent = function (win) {
        editor.fire('OpenWindow', { win: win });
      };
      var fireCloseEvent = function (win) {
        editor.fire('CloseWindow', { win: win });
      };
      var addWindow = function (win) {
        windows.push(win);
        fireOpenEvent(win);
      };
      var closeWindow = function (win) {
        findIndex(windows, function (otherWindow) {
          return otherWindow === win;
        }).each(function (index) {
          windows.splice(index, 1);
          fireCloseEvent(win);
          if (windows.length === 0) {
            editor.focus();
          }
        });
      };
      var getTopWindow = function () {
        return Option.from(windows[windows.length - 1]);
      };
      var open = function (args, params) {
        editor.editorManager.setActive(editor);
        SelectionBookmark.store(editor);
        var win = getImplementation().open(args, params, closeWindow);
        addWindow(win);
        return win;
      };
      var alert = function (message, callback, scope) {
        var win = getImplementation().alert(message, funcBind(scope ? scope : this, callback), closeWindow);
        addWindow(win);
      };
      var confirm = function (message, callback, scope) {
        var win = getImplementation().confirm(message, funcBind(scope ? scope : this, callback), closeWindow);
        addWindow(win);
      };
      var close = function () {
        getTopWindow().each(function (win) {
          getImplementation().close(win);
          closeWindow(win);
        });
      };
      var getParams = function () {
        return getTopWindow().map(getImplementation().getParams).getOr(null);
      };
      var setParams = function (params) {
        getTopWindow().each(function (win) {
          getImplementation().setParams(win, params);
        });
      };
      var getWindows = function () {
        return windows;
      };
      editor.on('remove', function () {
        each(windows.slice(0), function (win) {
          getImplementation().close(win);
        });
      });
      return {
        windows: windows,
        open: open,
        alert: alert,
        confirm: confirm,
        close: close,
        getParams: getParams,
        setParams: setParams,
        getWindows: getWindows
      };
    }

    var data = {};
    var code = 'en';
    var I18n = {
      setCode: function (newCode) {
        if (newCode) {
          code = newCode;
          this.rtl = this.data[newCode] ? this.data[newCode]._dir === 'rtl' : false;
        }
      },
      getCode: function () {
        return code;
      },
      rtl: false,
      add: function (code, items) {
        var langData = data[code];
        if (!langData) {
          data[code] = langData = {};
        }
        for (var name in items) {
          langData[name] = items[name];
        }
        this.setCode(code);
      },
      translate: function (text) {
        var langData = data[code] || {};
        var toString = function (obj) {
          if (Tools.is(obj, 'function')) {
            return Object.prototype.toString.call(obj);
          }
          return !isEmpty(obj) ? '' + obj : '';
        };
        var isEmpty = function (text) {
          return text === '' || text === null || Tools.is(text, 'undefined');
        };
        var getLangData = function (text) {
          text = toString(text);
          return Tools.hasOwn(langData, text) ? toString(langData[text]) : text;
        };
        if (isEmpty(text)) {
          return '';
        }
        if (Tools.is(text, 'object') && Tools.hasOwn(text, 'raw')) {
          return toString(text.raw);
        }
        if (Tools.is(text, 'array')) {
          var values_1 = text.slice(1);
          text = getLangData(text[0]).replace(/\{([0-9]+)\}/g, function ($1, $2) {
            return Tools.hasOwn(values_1, $2) ? toString(values_1[$2]) : $1;
          });
        }
        return getLangData(text).replace(/{context:\w+}$/, '');
      },
      data: data
    };

    var PluginManager = AddOnManager.PluginManager;
    var resolvePluginName = function (targetUrl, suffix) {
      for (var name in PluginManager.urls) {
        var matchUrl = PluginManager.urls[name] + '/plugin' + suffix + '.js';
        if (matchUrl === targetUrl) {
          return name;
        }
      }
      return null;
    };
    var pluginUrlToMessage = function (editor, url) {
      var plugin = resolvePluginName(url, editor.suffix);
      return plugin ? I18n.translate([
        'Failed to load plugin: {0} from url {1}',
        plugin,
        url
      ]) : I18n.translate([
        'Failed to load plugin url: {0}',
        url
      ]);
    };
    var displayNotification = function (editor, message) {
      editor.notificationManager.open({
        type: 'error',
        text: message
      });
    };
    var displayError = function (editor, message) {
      if (editor._skinLoaded) {
        displayNotification(editor, message);
      } else {
        editor.on('SkinLoaded', function () {
          displayNotification(editor, message);
        });
      }
    };
    var uploadError = function (editor, message) {
      displayError(editor, I18n.translate([
        'Failed to upload image: {0}',
        message
      ]));
    };
    var pluginLoadError = function (editor, url) {
      displayError(editor, pluginUrlToMessage(editor, url));
    };
    var pluginInitError = function (editor, name, err) {
      var message = I18n.translate([
        'Failed to initialize plugin: {0}',
        name
      ]);
      initError(message, err);
      displayError(editor, message);
    };
    var initError = function (message) {
      var x = [];
      for (var _i = 1; _i < arguments.length; _i++) {
        x[_i - 1] = arguments[_i];
      }
      var console = domGlobals.window.console;
      if (console) {
        if (console.error) {
          console.error.apply(console, arguments);
        } else {
          console.log.apply(console, arguments);
        }
      }
    };
    var ErrorReporter = {
      pluginLoadError: pluginLoadError,
      pluginInitError: pluginInitError,
      uploadError: uploadError,
      displayError: displayError,
      initError: initError
    };

    var PluginManager$1 = AddOnManager.PluginManager;

    var ThemeManager = AddOnManager.ThemeManager;

    function XMLHttpRequest () {
      var f = Global$1.getOrDie('XMLHttpRequest');
      return new f();
    }

    function Uploader (uploadStatus, settings) {
      var pendingPromises = {};
      var pathJoin = function (path1, path2) {
        if (path1) {
          return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '');
        }
        return path2;
      };
      var defaultHandler = function (blobInfo, success, failure, progress) {
        var xhr, formData;
        xhr = XMLHttpRequest();
        xhr.open('POST', settings.url);
        xhr.withCredentials = settings.credentials;
        xhr.upload.onprogress = function (e) {
          progress(e.loaded / e.total * 100);
        };
        xhr.onerror = function () {
          failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
        };
        xhr.onload = function () {
          var json;
          if (xhr.status < 200 || xhr.status >= 300) {
            failure('HTTP Error: ' + xhr.status);
            return;
          }
          json = JSON.parse(xhr.responseText);
          if (!json || typeof json.location !== 'string') {
            failure('Invalid JSON: ' + xhr.responseText);
            return;
          }
          success(pathJoin(settings.basePath, json.location));
        };
        formData = new domGlobals.FormData();
        formData.append('file', blobInfo.blob(), blobInfo.filename());
        xhr.send(formData);
      };
      var noUpload = function () {
        return new promiseObj(function (resolve) {
          resolve([]);
        });
      };
      var handlerSuccess = function (blobInfo, url) {
        return {
          url: url,
          blobInfo: blobInfo,
          status: true
        };
      };
      var handlerFailure = function (blobInfo, error) {
        return {
          url: '',
          blobInfo: blobInfo,
          status: false,
          error: error
        };
      };
      var resolvePending = function (blobUri, result) {
        Tools.each(pendingPromises[blobUri], function (resolve) {
          resolve(result);
        });
        delete pendingPromises[blobUri];
      };
      var uploadBlobInfo = function (blobInfo, handler, openNotification) {
        uploadStatus.markPending(blobInfo.blobUri());
        return new promiseObj(function (resolve) {
          var notification, progress;
          var noop = function () {
          };
          try {
            var closeNotification_1 = function () {
              if (notification) {
                notification.close();
                progress = noop;
              }
            };
            var success = function (url) {
              closeNotification_1();
              uploadStatus.markUploaded(blobInfo.blobUri(), url);
              resolvePending(blobInfo.blobUri(), handlerSuccess(blobInfo, url));
              resolve(handlerSuccess(blobInfo, url));
            };
            var failure = function (error) {
              closeNotification_1();
              uploadStatus.removeFailed(blobInfo.blobUri());
              resolvePending(blobInfo.blobUri(), handlerFailure(blobInfo, error));
              resolve(handlerFailure(blobInfo, error));
            };
            progress = function (percent) {
              if (percent < 0 || percent > 100) {
                return;
              }
              if (!notification) {
                notification = openNotification();
              }
              notification.progressBar.value(percent);
            };
            handler(blobInfo, success, failure, progress);
          } catch (ex) {
            resolve(handlerFailure(blobInfo, ex.message));
          }
        });
      };
      var isDefaultHandler = function (handler) {
        return handler === defaultHandler;
      };
      var pendingUploadBlobInfo = function (blobInfo) {
        var blobUri = blobInfo.blobUri();
        return new promiseObj(function (resolve) {
          pendingPromises[blobUri] = pendingPromises[blobUri] || [];
          pendingPromises[blobUri].push(resolve);
        });
      };
      var uploadBlobs = function (blobInfos, openNotification) {
        blobInfos = Tools.grep(blobInfos, function (blobInfo) {
          return !uploadStatus.isUploaded(blobInfo.blobUri());
        });
        return promiseObj.all(Tools.map(blobInfos, function (blobInfo) {
          return uploadStatus.isPending(blobInfo.blobUri()) ? pendingUploadBlobInfo(blobInfo) : uploadBlobInfo(blobInfo, settings.handler, openNotification);
        }));
      };
      var upload = function (blobInfos, openNotification) {
        return !settings.url && isDefaultHandler(settings.handler) ? noUpload() : uploadBlobs(blobInfos, openNotification);
      };
      if (isFunction(settings.handler) === false) {
        settings.handler = defaultHandler;
      }
      return { upload: upload };
    }

    function FileReader () {
      var f = Global$1.getOrDie('FileReader');
      return new f();
    }

    function Uint8Array (arr) {
      var f = Global$1.getOrDie('Uint8Array');
      return new f(arr);
    }

    var requestAnimationFrame$1 = function (callback) {
      var f = Global$1.getOrDie('requestAnimationFrame');
      f(callback);
    };
    var atob = function (base64) {
      var f = Global$1.getOrDie('atob');
      return f(base64);
    };
    var Window = {
      atob: atob,
      requestAnimationFrame: requestAnimationFrame$1
    };

    var blobUriToBlob = function (url) {
      return new promiseObj(function (resolve, reject) {
        var rejectWithError = function () {
          reject('Cannot convert ' + url + ' to Blob. Resource might not exist or is inaccessible.');
        };
        try {
          var xhr = XMLHttpRequest();
          xhr.open('GET', url, true);
          xhr.responseType = 'blob';
          xhr.onload = function () {
            if (this.status === 200) {
              resolve(this.response);
            } else {
              rejectWithError();
            }
          };
          xhr.onerror = rejectWithError;
          xhr.send();
        } catch (ex) {
          rejectWithError();
        }
      });
    };
    var parseDataUri = function (uri) {
      var type, matches;
      var uriParts = decodeURIComponent(uri).split(',');
      matches = /data:([^;]+)/.exec(uriParts[0]);
      if (matches) {
        type = matches[1];
      }
      return {
        type: type,
        data: uriParts[1]
      };
    };
    var dataUriToBlob = function (uri) {
      return new promiseObj(function (resolve) {
        var str, arr, i;
        var uriParts = parseDataUri(uri);
        try {
          str = Window.atob(uriParts.data);
        } catch (e) {
          resolve(new domGlobals.Blob([]));
          return;
        }
        arr = Uint8Array(str.length);
        for (i = 0; i < arr.length; i++) {
          arr[i] = str.charCodeAt(i);
        }
        resolve(new domGlobals.Blob([arr], { type: uriParts.type }));
      });
    };
    var uriToBlob = function (url) {
      if (url.indexOf('blob:') === 0) {
        return blobUriToBlob(url);
      }
      if (url.indexOf('data:') === 0) {
        return dataUriToBlob(url);
      }
      return null;
    };
    var blobToDataUri = function (blob) {
      return new promiseObj(function (resolve) {
        var reader = FileReader();
        reader.onloadend = function () {
          resolve(reader.result);
        };
        reader.readAsDataURL(blob);
      });
    };
    var Conversions = {
      uriToBlob: uriToBlob,
      blobToDataUri: blobToDataUri,
      parseDataUri: parseDataUri
    };

    var count = 0;
    var uniqueId = function (prefix) {
      return (prefix || 'blobid') + count++;
    };
    var imageToBlobInfo = function (blobCache, img, resolve, reject) {
      var base64, blobInfo;
      if (img.src.indexOf('blob:') === 0) {
        blobInfo = blobCache.getByUri(img.src);
        if (blobInfo) {
          resolve({
            image: img,
            blobInfo: blobInfo
          });
        } else {
          Conversions.uriToBlob(img.src).then(function (blob) {
            Conversions.blobToDataUri(blob).then(function (dataUri) {
              base64 = Conversions.parseDataUri(dataUri).data;
              blobInfo = blobCache.create(uniqueId(), blob, base64);
              blobCache.add(blobInfo);
              resolve({
                image: img,
                blobInfo: blobInfo
              });
            });
          }, function (err) {
            reject(err);
          });
        }
        return;
      }
      base64 = Conversions.parseDataUri(img.src).data;
      blobInfo = blobCache.findFirst(function (cachedBlobInfo) {
        return cachedBlobInfo.base64() === base64;
      });
      if (blobInfo) {
        resolve({
          image: img,
          blobInfo: blobInfo
        });
      } else {
        Conversions.uriToBlob(img.src).then(function (blob) {
          blobInfo = blobCache.create(uniqueId(), blob, base64);
          blobCache.add(blobInfo);
          resolve({
            image: img,
            blobInfo: blobInfo
          });
        }, function (err) {
          reject(err);
        });
      }
    };
    var getAllImages = function (elm) {
      return elm ? from$1(elm.getElementsByTagName('img')) : [];
    };
    function ImageScanner (uploadStatus, blobCache) {
      var cachedPromises = {};
      var findAll = function (elm, predicate) {
        var images;
        if (!predicate) {
          predicate = constant(true);
        }
        images = filter(getAllImages(elm), function (img) {
          var src = img.src;
          if (!Env.fileApi) {
            return false;
          }
          if (img.hasAttribute('data-mce-bogus')) {
            return false;
          }
          if (img.hasAttribute('data-mce-placeholder')) {
            return false;
          }
          if (!src || src === Env.transparentSrc) {
            return false;
          }
          if (src.indexOf('blob:') === 0) {
            return !uploadStatus.isUploaded(src) && predicate(img);
          }
          if (src.indexOf('data:') === 0) {
            return predicate(img);
          }
          return false;
        });
        var promises = map(images, function (img) {
          if (cachedPromises[img.src]) {
            return new promiseObj(function (resolve) {
              cachedPromises[img.src].then(function (imageInfo) {
                if (typeof imageInfo === 'string') {
                  return imageInfo;
                }
                resolve({
                  image: img,
                  blobInfo: imageInfo.blobInfo
                });
              });
            });
          }
          var newPromise = new promiseObj(function (resolve, reject) {
            imageToBlobInfo(blobCache, img, resolve, reject);
          }).then(function (result) {
            delete cachedPromises[result.image.src];
            return result;
          }).catch(function (error) {
            delete cachedPromises[img.src];
            return error;
          });
          cachedPromises[img.src] = newPromise;
          return newPromise;
        });
        return promiseObj.all(promises);
      };
      return { findAll: findAll };
    }

    var count$1 = 0;
    var seed = function () {
      var rnd = function () {
        return Math.round(Math.random() * 4294967295).toString(36);
      };
      var now = new Date().getTime();
      return 's' + now.toString(36) + rnd() + rnd() + rnd();
    };
    var uuid = function (prefix) {
      return prefix + count$1++ + seed();
    };
    var Uuid = { uuid: uuid };

    function BlobCache () {
      var cache = [];
      var mimeToExt = function (mime) {
        var mimes = {
          'image/jpeg': 'jpg',
          'image/jpg': 'jpg',
          'image/gif': 'gif',
          'image/png': 'png'
        };
        return mimes[mime.toLowerCase()] || 'dat';
      };
      var create = function (o, blob, base64, filename) {
        if (isString(o)) {
          var id = o;
          return toBlobInfo({
            id: id,
            name: filename,
            blob: blob,
            base64: base64
          });
        } else if (isObject(o)) {
          return toBlobInfo(o);
        } else {
          throw new Error('Unknown input type');
        }
      };
      var toBlobInfo = function (o) {
        var id, name;
        if (!o.blob || !o.base64) {
          throw new Error('blob and base64 representations of the image are required for BlobInfo to be created');
        }
        id = o.id || Uuid.uuid('blobid');
        name = o.name || id;
        return {
          id: constant(id),
          name: constant(name),
          filename: constant(name + '.' + mimeToExt(o.blob.type)),
          blob: constant(o.blob),
          base64: constant(o.base64),
          blobUri: constant(o.blobUri || URL.createObjectURL(o.blob)),
          uri: constant(o.uri)
        };
      };
      var add = function (blobInfo) {
        if (!get(blobInfo.id())) {
          cache.push(blobInfo);
        }
      };
      var get = function (id) {
        return findFirst(function (cachedBlobInfo) {
          return cachedBlobInfo.id() === id;
        });
      };
      var findFirst = function (predicate) {
        return filter(cache, predicate)[0];
      };
      var getByUri = function (blobUri) {
        return findFirst(function (blobInfo) {
          return blobInfo.blobUri() === blobUri;
        });
      };
      var removeByUri = function (blobUri) {
        cache = filter(cache, function (blobInfo) {
          if (blobInfo.blobUri() === blobUri) {
            URL.revokeObjectURL(blobInfo.blobUri());
            return false;
          }
          return true;
        });
      };
      var destroy = function () {
        each(cache, function (cachedBlobInfo) {
          URL.revokeObjectURL(cachedBlobInfo.blobUri());
        });
        cache = [];
      };
      return {
        create: create,
        add: add,
        get: get,
        getByUri: getByUri,
        findFirst: findFirst,
        removeByUri: removeByUri,
        destroy: destroy
      };
    }

    function UploadStatus () {
      var PENDING = 1, UPLOADED = 2;
      var blobUriStatuses = {};
      var createStatus = function (status, resultUri) {
        return {
          status: status,
          resultUri: resultUri
        };
      };
      var hasBlobUri = function (blobUri) {
        return blobUri in blobUriStatuses;
      };
      var getResultUri = function (blobUri) {
        var result = blobUriStatuses[blobUri];
        return result ? result.resultUri : null;
      };
      var isPending = function (blobUri) {
        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === PENDING : false;
      };
      var isUploaded = function (blobUri) {
        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === UPLOADED : false;
      };
      var markPending = function (blobUri) {
        blobUriStatuses[blobUri] = createStatus(PENDING, null);
      };
      var markUploaded = function (blobUri, resultUri) {
        blobUriStatuses[blobUri] = createStatus(UPLOADED, resultUri);
      };
      var removeFailed = function (blobUri) {
        delete blobUriStatuses[blobUri];
      };
      var destroy = function () {
        blobUriStatuses = {};
      };
      return {
        hasBlobUri: hasBlobUri,
        getResultUri: getResultUri,
        isPending: isPending,
        isUploaded: isUploaded,
        markPending: markPending,
        markUploaded: markUploaded,
        removeFailed: removeFailed,
        destroy: destroy
      };
    }

    function EditorUpload (editor) {
      var blobCache = BlobCache();
      var uploader, imageScanner;
      var uploadStatus = UploadStatus();
      var urlFilters = [];
      var aliveGuard = function (callback) {
        return function (result) {
          if (editor.selection) {
            return callback(result);
          }
          return [];
        };
      };
      var cacheInvalidator = function () {
        return '?' + new Date().getTime();
      };
      var replaceString = function (content, search, replace) {
        var index = 0;
        do {
          index = content.indexOf(search, index);
          if (index !== -1) {
            content = content.substring(0, index) + replace + content.substr(index + search.length);
            index += replace.length - search.length + 1;
          }
        } while (index !== -1);
        return content;
      };
      var replaceImageUrl = function (content, targetUrl, replacementUrl) {
        content = replaceString(content, 'src="' + targetUrl + '"', 'src="' + replacementUrl + '"');
        content = replaceString(content, 'data-mce-src="' + targetUrl + '"', 'data-mce-src="' + replacementUrl + '"');
        return content;
      };
      var replaceUrlInUndoStack = function (targetUrl, replacementUrl) {
        each(editor.undoManager.data, function (level) {
          if (level.type === 'fragmented') {
            level.fragments = map(level.fragments, function (fragment) {
              return replaceImageUrl(fragment, targetUrl, replacementUrl);
            });
          } else {
            level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
          }
        });
      };
      var openNotification = function () {
        return editor.notificationManager.open({
          text: editor.translate('Image uploading...'),
          type: 'info',
          timeout: -1,
          progressBar: true
        });
      };
      var replaceImageUri = function (image, resultUri) {
        blobCache.removeByUri(image.src);
        replaceUrlInUndoStack(image.src, resultUri);
        editor.$(image).attr({
          'src': Settings.shouldReuseFileName(editor) ? resultUri + cacheInvalidator() : resultUri,
          'data-mce-src': editor.convertURL(resultUri, 'src')
        });
      };
      var uploadImages = function (callback) {
        if (!uploader) {
          uploader = Uploader(uploadStatus, {
            url: Settings.getImageUploadUrl(editor),
            basePath: Settings.getImageUploadBasePath(editor),
            credentials: Settings.getImagesUploadCredentials(editor),
            handler: Settings.getImagesUploadHandler(editor)
          });
        }
        return scanForImages().then(aliveGuard(function (imageInfos) {
          var blobInfos;
          blobInfos = map(imageInfos, function (imageInfo) {
            return imageInfo.blobInfo;
          });
          return uploader.upload(blobInfos, openNotification).then(aliveGuard(function (result) {
            var filteredResult = map(result, function (uploadInfo, index) {
              var image = imageInfos[index].image;
              if (uploadInfo.status && Settings.shouldReplaceBlobUris(editor)) {
                replaceImageUri(image, uploadInfo.url);
              } else if (uploadInfo.error) {
                ErrorReporter.uploadError(editor, uploadInfo.error);
              }
              return {
                element: image,
                status: uploadInfo.status
              };
            });
            if (callback) {
              callback(filteredResult);
            }
            return filteredResult;
          }));
        }));
      };
      var uploadImagesAuto = function (callback) {
        if (Settings.isAutomaticUploadsEnabled(editor)) {
          return uploadImages(callback);
        }
      };
      var isValidDataUriImage = function (imgElm) {
        if (forall(urlFilters, function (filter) {
            return filter(imgElm);
          }) === false) {
          return false;
        }
        if (imgElm.getAttribute('src').indexOf('data:') === 0) {
          var dataImgFilter = Settings.getImagesDataImgFilter(editor);
          return dataImgFilter(imgElm);
        }
        return true;
      };
      var addFilter = function (filter) {
        urlFilters.push(filter);
      };
      var scanForImages = function () {
        if (!imageScanner) {
          imageScanner = ImageScanner(uploadStatus, blobCache);
        }
        return imageScanner.findAll(editor.getBody(), isValidDataUriImage).then(aliveGuard(function (result) {
          result = filter(result, function (resultItem) {
            if (typeof resultItem === 'string') {
              ErrorReporter.displayError(editor, resultItem);
              return false;
            }
            return true;
          });
          each(result, function (resultItem) {
            replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
            resultItem.image.src = resultItem.blobInfo.blobUri();
            resultItem.image.removeAttribute('data-mce-src');
          });
          return result;
        }));
      };
      var destroy = function () {
        blobCache.destroy();
        uploadStatus.destroy();
        imageScanner = uploader = null;
      };
      var replaceBlobUris = function (content) {
        return content.replace(/src="(blob:[^"]+)"/g, function (match, blobUri) {
          var resultUri = uploadStatus.getResultUri(blobUri);
          if (resultUri) {
            return 'src="' + resultUri + '"';
          }
          var blobInfo = blobCache.getByUri(blobUri);
          if (!blobInfo) {
            blobInfo = foldl(editor.editorManager.get(), function (result, editor) {
              return result || editor.editorUpload && editor.editorUpload.blobCache.getByUri(blobUri);
            }, null);
          }
          if (blobInfo) {
            var blob = blobInfo.blob();
            return 'src="data:' + blob.type + ';base64,' + blobInfo.base64() + '"';
          }
          return match;
        });
      };
      editor.on('setContent', function () {
        if (Settings.isAutomaticUploadsEnabled(editor)) {
          uploadImagesAuto();
        } else {
          scanForImages();
        }
      });
      editor.on('RawSaveContent', function (e) {
        e.content = replaceBlobUris(e.content);
      });
      editor.on('getContent', function (e) {
        if (e.source_view || e.format === 'raw') {
          return;
        }
        e.content = replaceBlobUris(e.content);
      });
      editor.on('PostRender', function () {
        editor.parser.addNodeFilter('img', function (images) {
          each(images, function (img) {
            var src = img.attr('src');
            if (blobCache.getByUri(src)) {
              return;
            }
            var resultUri = uploadStatus.getResultUri(src);
            if (resultUri) {
              img.attr('src', resultUri);
            }
          });
        });
      });
      return {
        blobCache: blobCache,
        addFilter: addFilter,
        uploadImages: uploadImages,
        uploadImagesAuto: uploadImagesAuto,
        scanForImages: scanForImages,
        destroy: destroy
      };
    }

    var isBlockElement = function (blockElements, node) {
      return blockElements.hasOwnProperty(node.nodeName);
    };
    var isValidTarget = function (blockElements, node) {
      if (NodeType.isText(node)) {
        return true;
      } else if (NodeType.isElement(node)) {
        return !isBlockElement(blockElements, node) && !Bookmarks.isBookmarkNode(node);
      } else {
        return false;
      }
    };
    var hasBlockParent = function (blockElements, root, node) {
      return exists(Parents.parents(Element.fromDom(node), Element.fromDom(root)), function (elm) {
        return isBlockElement(blockElements, elm.dom());
      });
    };
    var shouldRemoveTextNode = function (blockElements, node) {
      if (NodeType.isText(node)) {
        if (node.nodeValue.length === 0) {
          return true;
        } else if (/^\s+$/.test(node.nodeValue) && (!node.nextSibling || isBlockElement(blockElements, node.nextSibling))) {
          return true;
        }
      }
      return false;
    };
    var addRootBlocks = function (editor) {
      var settings = editor.settings, dom = editor.dom, selection = editor.selection;
      var schema = editor.schema, blockElements = schema.getBlockElements();
      var node = selection.getStart();
      var rootNode = editor.getBody();
      var rng;
      var startContainer, startOffset, endContainer, endOffset, rootBlockNode;
      var tempNode, wrapped, restoreSelection;
      var rootNodeName, forcedRootBlock;
      forcedRootBlock = settings.forced_root_block;
      if (!node || !NodeType.isElement(node) || !forcedRootBlock) {
        return;
      }
      rootNodeName = rootNode.nodeName.toLowerCase();
      if (!schema.isValidChild(rootNodeName, forcedRootBlock.toLowerCase()) || hasBlockParent(blockElements, rootNode, node)) {
        return;
      }
      rng = selection.getRng();
      startContainer = rng.startContainer;
      startOffset = rng.startOffset;
      endContainer = rng.endContainer;
      endOffset = rng.endOffset;
      restoreSelection = EditorFocus.hasFocus(editor);
      node = rootNode.firstChild;
      while (node) {
        if (isValidTarget(blockElements, node)) {
          if (shouldRemoveTextNode(blockElements, node)) {
            tempNode = node;
            node = node.nextSibling;
            dom.remove(tempNode);
            continue;
          }
          if (!rootBlockNode) {
            rootBlockNode = dom.create(forcedRootBlock, editor.settings.forced_root_block_attrs);
            node.parentNode.insertBefore(rootBlockNode, node);
            wrapped = true;
          }
          tempNode = node;
          node = node.nextSibling;
          rootBlockNode.appendChild(tempNode);
        } else {
          rootBlockNode = null;
          node = node.nextSibling;
        }
      }
      if (wrapped && restoreSelection) {
        rng.setStart(startContainer, startOffset);
        rng.setEnd(endContainer, endOffset);
        selection.setRng(rng);
        editor.nodeChanged();
      }
    };
    var setup$3 = function (editor) {
      if (editor.settings.forced_root_block) {
        editor.on('NodeChange', curry(addRootBlocks, editor));
      }
    };
    var ForceBlocks = { setup: setup$3 };

    var getStartNode = function (rng) {
      var sc = rng.startContainer, so = rng.startOffset;
      if (NodeType.isText(sc)) {
        return so === 0 ? Option.some(Element.fromDom(sc)) : Option.none();
      } else {
        return Option.from(sc.childNodes[so]).map(Element.fromDom);
      }
    };
    var getEndNode = function (rng) {
      var ec = rng.endContainer, eo = rng.endOffset;
      if (NodeType.isText(ec)) {
        return eo === ec.data.length ? Option.some(Element.fromDom(ec)) : Option.none();
      } else {
        return Option.from(ec.childNodes[eo - 1]).map(Element.fromDom);
      }
    };
    var getFirstChildren = function (node) {
      return firstChild(node).fold(constant([node]), function (child) {
        return [node].concat(getFirstChildren(child));
      });
    };
    var getLastChildren$1 = function (node) {
      return lastChild(node).fold(constant([node]), function (child) {
        if (name(child) === 'br') {
          return prevSibling(child).map(function (sibling) {
            return [node].concat(getLastChildren$1(sibling));
          }).getOr([]);
        } else {
          return [node].concat(getLastChildren$1(child));
        }
      });
    };
    var hasAllContentsSelected = function (elm, rng) {
      return lift2(getStartNode(rng), getEndNode(rng), function (startNode, endNode) {
        var start = find(getFirstChildren(elm), curry(eq, startNode));
        var end = find(getLastChildren$1(elm), curry(eq, endNode));
        return start.isSome() && end.isSome();
      }).getOr(false);
    };
    var moveEndPoint$1 = function (dom, rng, node, start) {
      var root = node, walker = new TreeWalker(node, root);
      var nonEmptyElementsMap = dom.schema.getNonEmptyElements();
      do {
        if (node.nodeType === 3 && Tools.trim(node.nodeValue).length !== 0) {
          if (start) {
            rng.setStart(node, 0);
          } else {
            rng.setEnd(node, node.nodeValue.length);
          }
          return;
        }
        if (nonEmptyElementsMap[node.nodeName] && !/^(TD|TH)$/.test(node.nodeName)) {
          if (start) {
            rng.setStartBefore(node);
          } else {
            if (node.nodeName === 'BR') {
              rng.setEndBefore(node);
            } else {
              rng.setEndAfter(node);
            }
          }
          return;
        }
        if (Env.ie && Env.ie < 11 && dom.isBlock(node) && dom.isEmpty(node)) {
          if (start) {
            rng.setStart(node, 0);
          } else {
            rng.setEnd(node, 0);
          }
          return;
        }
      } while (node = start ? walker.next() : walker.prev());
      if (root.nodeName === 'BODY') {
        if (start) {
          rng.setStart(root, 0);
        } else {
          rng.setEnd(root, root.childNodes.length);
        }
      }
    };
    var hasAnyRanges = function (editor) {
      var sel = editor.selection.getSel();
      return sel && sel.rangeCount > 0;
    };

    function NodeChange (editor) {
      var lastRng, lastPath = [];
      var isSameElementPath = function (startElm) {
        var i, currentPath;
        currentPath = editor.$(startElm).parentsUntil(editor.getBody()).add(startElm);
        if (currentPath.length === lastPath.length) {
          for (i = currentPath.length; i >= 0; i--) {
            if (currentPath[i] !== lastPath[i]) {
              break;
            }
          }
          if (i === -1) {
            lastPath = currentPath;
            return true;
          }
        }
        lastPath = currentPath;
        return false;
      };
      if (!('onselectionchange' in editor.getDoc())) {
        editor.on('NodeChange Click MouseUp KeyUp Focus', function (e) {
          var nativeRng, fakeRng;
          nativeRng = editor.selection.getRng();
          fakeRng = {
            startContainer: nativeRng.startContainer,
            startOffset: nativeRng.startOffset,
            endContainer: nativeRng.endContainer,
            endOffset: nativeRng.endOffset
          };
          if (e.type === 'nodechange' || !RangeCompare.isEq(fakeRng, lastRng)) {
            editor.fire('SelectionChange');
          }
          lastRng = fakeRng;
        });
      }
      editor.on('contextmenu', function () {
        editor.fire('SelectionChange');
      });
      editor.on('SelectionChange', function () {
        var startElm = editor.selection.getStart(true);
        if (!startElm || !Env.range && editor.selection.isCollapsed()) {
          return;
        }
        if (hasAnyRanges(editor) && !isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
          editor.nodeChanged({ selectionChange: true });
        }
      });
      editor.on('MouseUp', function (e) {
        if (!e.isDefaultPrevented() && hasAnyRanges(editor)) {
          if (editor.selection.getNode().nodeName === 'IMG') {
            Delay.setEditorTimeout(editor, function () {
              editor.nodeChanged();
            });
          } else {
            editor.nodeChanged();
          }
        }
      });
      this.nodeChanged = function (args) {
        var selection = editor.selection;
        var node, parents, root;
        if (editor.initialized && selection && !editor.settings.disable_nodechange && !editor.readonly) {
          root = editor.getBody();
          node = selection.getStart(true) || root;
          if (node.ownerDocument !== editor.getDoc() || !editor.dom.isChildOf(node, root)) {
            node = root;
          }
          parents = [];
          editor.dom.getParent(node, function (node) {
            if (node === root) {
              return true;
            }
            parents.push(node);
          });
          args = args || {};
          args.element = node;
          args.parents = parents;
          editor.fire('NodeChange', args);
        }
      };
    }

    var VK = {
      BACKSPACE: 8,
      DELETE: 46,
      DOWN: 40,
      ENTER: 13,
      LEFT: 37,
      RIGHT: 39,
      SPACEBAR: 32,
      TAB: 9,
      UP: 38,
      END: 35,
      HOME: 36,
      modifierPressed: function (e) {
        return e.shiftKey || e.ctrlKey || e.altKey || this.metaKeyPressed(e);
      },
      metaKeyPressed: function (e) {
        return Env.mac ? e.metaKey : e.ctrlKey && !e.altKey;
      }
    };

    var getNodeClientRects = function (node) {
      var toArrayWithNode = function (clientRects) {
        return map(clientRects, function (clientRect) {
          clientRect = clone$1(clientRect);
          clientRect.node = node;
          return clientRect;
        });
      };
      if (NodeType.isElement(node)) {
        return toArrayWithNode(node.getClientRects());
      }
      if (NodeType.isText(node)) {
        var rng = node.ownerDocument.createRange();
        rng.setStart(node, 0);
        rng.setEnd(node, node.data.length);
        return toArrayWithNode(rng.getClientRects());
      }
    };
    var getClientRects = function (node) {
      return foldl(node, function (result, node) {
        return result.concat(getNodeClientRects(node));
      }, []);
    };

    var VDirection;
    (function (VDirection) {
      VDirection[VDirection['Up'] = -1] = 'Up';
      VDirection[VDirection['Down'] = 1] = 'Down';
    }(VDirection || (VDirection = {})));
    var findUntil = function (direction, root, predicateFn, node) {
      while (node = findNode(node, direction, isEditableCaretCandidate, root)) {
        if (predicateFn(node)) {
          return;
        }
      }
    };
    var walkUntil = function (direction, isAboveFn, isBeflowFn, root, predicateFn, caretPosition) {
      var line = 0, node;
      var result = [];
      var targetClientRect;
      var add = function (node) {
        var i, clientRect, clientRects;
        clientRects = getClientRects([node]);
        if (direction === -1) {
          clientRects = clientRects.reverse();
        }
        for (i = 0; i < clientRects.length; i++) {
          clientRect = clientRects[i];
          if (isBeflowFn(clientRect, targetClientRect)) {
            continue;
          }
          if (result.length > 0 && isAboveFn(clientRect, ArrUtils.last(result))) {
            line++;
          }
          clientRect.line = line;
          if (predicateFn(clientRect)) {
            return true;
          }
          result.push(clientRect);
        }
      };
      targetClientRect = ArrUtils.last(caretPosition.getClientRects());
      if (!targetClientRect) {
        return result;
      }
      node = caretPosition.getNode();
      add(node);
      findUntil(direction, root, add, node);
      return result;
    };
    var aboveLineNumber = function (lineNumber, clientRect) {
      return clientRect.line > lineNumber;
    };
    var isLineNumber = function (lineNumber, clientRect) {
      return clientRect.line === lineNumber;
    };
    var upUntil = curry(walkUntil, VDirection.Up, isAbove, isBelow);
    var downUntil = curry(walkUntil, VDirection.Down, isBelow, isAbove);
    var positionsUntil = function (direction, root, predicateFn, node) {
      var caretWalker = CaretWalker(root);
      var walkFn, isBelowFn, isAboveFn, caretPosition;
      var result = [];
      var line = 0, clientRect, targetClientRect;
      var getClientRect = function (caretPosition) {
        if (direction === 1) {
          return ArrUtils.last(caretPosition.getClientRects());
        }
        return ArrUtils.last(caretPosition.getClientRects());
      };
      if (direction === 1) {
        walkFn = caretWalker.next;
        isBelowFn = isBelow;
        isAboveFn = isAbove;
        caretPosition = CaretPosition$1.after(node);
      } else {
        walkFn = caretWalker.prev;
        isBelowFn = isAbove;
        isAboveFn = isBelow;
        caretPosition = CaretPosition$1.before(node);
      }
      targetClientRect = getClientRect(caretPosition);
      do {
        if (!caretPosition.isVisible()) {
          continue;
        }
        clientRect = getClientRect(caretPosition);
        if (isAboveFn(clientRect, targetClientRect)) {
          continue;
        }
        if (result.length > 0 && isBelowFn(clientRect, ArrUtils.last(result))) {
          line++;
        }
        clientRect = clone$1(clientRect);
        clientRect.position = caretPosition;
        clientRect.line = line;
        if (predicateFn(clientRect)) {
          return result;
        }
        result.push(clientRect);
      } while (caretPosition = walkFn(caretPosition));
      return result;
    };
    var isAboveLine = function (lineNumber) {
      return function (clientRect) {
        return aboveLineNumber(lineNumber, clientRect);
      };
    };
    var isLine = function (lineNumber) {
      return function (clientRect) {
        return isLineNumber(lineNumber, clientRect);
      };
    };

    var isContentEditableFalse$7 = NodeType.isContentEditableFalse;
    var findNode$1 = findNode;
    var distanceToRectLeft = function (clientRect, clientX) {
      return Math.abs(clientRect.left - clientX);
    };
    var distanceToRectRight = function (clientRect, clientX) {
      return Math.abs(clientRect.right - clientX);
    };
    var isInside = function (clientX, clientRect) {
      return clientX >= clientRect.left && clientX <= clientRect.right;
    };
    var findClosestClientRect = function (clientRects, clientX) {
      return ArrUtils.reduce(clientRects, function (oldClientRect, clientRect) {
        var oldDistance, newDistance;
        oldDistance = Math.min(distanceToRectLeft(oldClientRect, clientX), distanceToRectRight(oldClientRect, clientX));
        newDistance = Math.min(distanceToRectLeft(clientRect, clientX), distanceToRectRight(clientRect, clientX));
        if (isInside(clientX, clientRect)) {
          return clientRect;
        }
        if (isInside(clientX, oldClientRect)) {
          return oldClientRect;
        }
        if (newDistance === oldDistance && isContentEditableFalse$7(clientRect.node)) {
          return clientRect;
        }
        if (newDistance < oldDistance) {
          return clientRect;
        }
        return oldClientRect;
      });
    };
    var walkUntil$1 = function (direction, root, predicateFn, node) {
      while (node = findNode$1(node, direction, isEditableCaretCandidate, root)) {
        if (predicateFn(node)) {
          return;
        }
      }
    };
    var findLineNodeRects = function (root, targetNodeRect) {
      var clientRects = [];
      var collect = function (checkPosFn, node) {
        var lineRects;
        lineRects = filter(getClientRects([node]), function (clientRect) {
          return !checkPosFn(clientRect, targetNodeRect);
        });
        clientRects = clientRects.concat(lineRects);
        return lineRects.length === 0;
      };
      clientRects.push(targetNodeRect);
      walkUntil$1(VDirection.Up, root, curry(collect, isAbove), targetNodeRect.node);
      walkUntil$1(VDirection.Down, root, curry(collect, isBelow), targetNodeRect.node);
      return clientRects;
    };
    var getFakeCaretTargets = function (root) {
      return filter(from$1(root.getElementsByTagName('*')), isFakeCaretTarget);
    };
    var caretInfo = function (clientRect, clientX) {
      return {
        node: clientRect.node,
        before: distanceToRectLeft(clientRect, clientX) < distanceToRectRight(clientRect, clientX)
      };
    };
    var closestCaret = function (root, clientX, clientY) {
      var closestNodeRect;
      var contentEditableFalseNodeRects = getClientRects(getFakeCaretTargets(root));
      var targetNodeRects = filter(contentEditableFalseNodeRects, function (rect) {
        return clientY >= rect.top && clientY <= rect.bottom;
      });
      closestNodeRect = findClosestClientRect(targetNodeRects, clientX);
      if (closestNodeRect) {
        closestNodeRect = findClosestClientRect(findLineNodeRects(root, closestNodeRect), clientX);
        if (closestNodeRect && isFakeCaretTarget(closestNodeRect.node)) {
          return caretInfo(closestNodeRect, clientX);
        }
      }
      return null;
    };

    var isXYWithinRange = function (clientX, clientY, range) {
      if (range.collapsed) {
        return false;
      }
      if (Env.ie && Env.ie <= 11 && range.startOffset === range.endOffset - 1 && range.startContainer === range.endContainer) {
        var elm = range.startContainer.childNodes[range.startOffset];
        if (NodeType.isElement(elm)) {
          return exists(elm.getClientRects(), function (rect) {
            return containsXY(rect, clientX, clientY);
          });
        }
      }
      return exists(range.getClientRects(), function (rect) {
        return containsXY(rect, clientX, clientY);
      });
    };
    var RangePoint = { isXYWithinRange: isXYWithinRange };

    var getAbsolutePosition = function (elm) {
      var doc, docElem, win, clientRect;
      clientRect = elm.getBoundingClientRect();
      doc = elm.ownerDocument;
      docElem = doc.documentElement;
      win = doc.defaultView;
      return {
        top: clientRect.top + win.pageYOffset - docElem.clientTop,
        left: clientRect.left + win.pageXOffset - docElem.clientLeft
      };
    };
    var getBodyPosition = function (editor) {
      return editor.inline ? getAbsolutePosition(editor.getBody()) : {
        left: 0,
        top: 0
      };
    };
    var getScrollPosition = function (editor) {
      var body = editor.getBody();
      return editor.inline ? {
        left: body.scrollLeft,
        top: body.scrollTop
      } : {
        left: 0,
        top: 0
      };
    };
    var getBodyScroll = function (editor) {
      var body = editor.getBody(), docElm = editor.getDoc().documentElement;
      var inlineScroll = {
        left: body.scrollLeft,
        top: body.scrollTop
      };
      var iframeScroll = {
        left: body.scrollLeft || docElm.scrollLeft,
        top: body.scrollTop || docElm.scrollTop
      };
      return editor.inline ? inlineScroll : iframeScroll;
    };
    var getMousePosition = function (editor, event) {
      if (event.target.ownerDocument !== editor.getDoc()) {
        var iframePosition = getAbsolutePosition(editor.getContentAreaContainer());
        var scrollPosition = getBodyScroll(editor);
        return {
          left: event.pageX - iframePosition.left + scrollPosition.left,
          top: event.pageY - iframePosition.top + scrollPosition.top
        };
      }
      return {
        left: event.pageX,
        top: event.pageY
      };
    };
    var calculatePosition = function (bodyPosition, scrollPosition, mousePosition) {
      return {
        pageX: mousePosition.left - bodyPosition.left + scrollPosition.left,
        pageY: mousePosition.top - bodyPosition.top + scrollPosition.top
      };
    };
    var calc = function (editor, event) {
      return calculatePosition(getBodyPosition(editor), getScrollPosition(editor), getMousePosition(editor, event));
    };
    var MousePosition = { calc: calc };

    var isContentEditableFalse$8 = NodeType.isContentEditableFalse, isContentEditableTrue$3 = NodeType.isContentEditableTrue;
    var isDraggable = function (rootElm, elm) {
      return isContentEditableFalse$8(elm) && elm !== rootElm;
    };
    var isValidDropTarget = function (editor, targetElement, dragElement) {
      if (targetElement === dragElement || editor.dom.isChildOf(targetElement, dragElement)) {
        return false;
      }
      if (isContentEditableFalse$8(targetElement)) {
        return false;
      }
      return true;
    };
    var cloneElement = function (elm) {
      var cloneElm = elm.cloneNode(true);
      cloneElm.removeAttribute('data-mce-selected');
      return cloneElm;
    };
    var createGhost = function (editor, elm, width, height) {
      var clonedElm = elm.cloneNode(true);
      editor.dom.setStyles(clonedElm, {
        width: width,
        height: height
      });
      editor.dom.setAttrib(clonedElm, 'data-mce-selected', null);
      var ghostElm = editor.dom.create('div', {
        'class': 'mce-drag-container',
        'data-mce-bogus': 'all',
        'unselectable': 'on',
        'contenteditable': 'false'
      });
      editor.dom.setStyles(ghostElm, {
        position: 'absolute',
        opacity: 0.5,
        overflow: 'hidden',
        border: 0,
        padding: 0,
        margin: 0,
        width: width,
        height: height
      });
      editor.dom.setStyles(clonedElm, {
        margin: 0,
        boxSizing: 'border-box'
      });
      ghostElm.appendChild(clonedElm);
      return ghostElm;
    };
    var appendGhostToBody = function (ghostElm, bodyElm) {
      if (ghostElm.parentNode !== bodyElm) {
        bodyElm.appendChild(ghostElm);
      }
    };
    var moveGhost = function (ghostElm, position, width, height, maxX, maxY) {
      var overflowX = 0, overflowY = 0;
      ghostElm.style.left = position.pageX + 'px';
      ghostElm.style.top = position.pageY + 'px';
      if (position.pageX + width > maxX) {
        overflowX = position.pageX + width - maxX;
      }
      if (position.pageY + height > maxY) {
        overflowY = position.pageY + height - maxY;
      }
      ghostElm.style.width = width - overflowX + 'px';
      ghostElm.style.height = height - overflowY + 'px';
    };
    var removeElement = function (elm) {
      if (elm && elm.parentNode) {
        elm.parentNode.removeChild(elm);
      }
    };
    var isLeftMouseButtonPressed = function (e) {
      return e.button === 0;
    };
    var hasDraggableElement = function (state) {
      return state.element;
    };
    var applyRelPos = function (state, position) {
      return {
        pageX: position.pageX - state.relX,
        pageY: position.pageY + 5
      };
    };
    var start$1 = function (state, editor) {
      return function (e) {
        if (isLeftMouseButtonPressed(e)) {
          var ceElm = find(editor.dom.getParents(e.target), Predicate.or(isContentEditableFalse$8, isContentEditableTrue$3)).getOr(null);
          if (isDraggable(editor.getBody(), ceElm)) {
            var elmPos = editor.dom.getPos(ceElm);
            var bodyElm = editor.getBody();
            var docElm = editor.getDoc().documentElement;
            state.element = ceElm;
            state.screenX = e.screenX;
            state.screenY = e.screenY;
            state.maxX = (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2;
            state.maxY = (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2;
            state.relX = e.pageX - elmPos.x;
            state.relY = e.pageY - elmPos.y;
            state.width = ceElm.offsetWidth;
            state.height = ceElm.offsetHeight;
            state.ghost = createGhost(editor, ceElm, state.width, state.height);
          }
        }
      };
    };
    var move$1 = function (state, editor) {
      var throttledPlaceCaretAt = Delay.throttle(function (clientX, clientY) {
        editor._selectionOverrides.hideFakeCaret();
        editor.selection.placeCaretAt(clientX, clientY);
      }, 0);
      return function (e) {
        var movement = Math.max(Math.abs(e.screenX - state.screenX), Math.abs(e.screenY - state.screenY));
        if (hasDraggableElement(state) && !state.dragging && movement > 10) {
          var args = editor.fire('dragstart', { target: state.element });
          if (args.isDefaultPrevented()) {
            return;
          }
          state.dragging = true;
          editor.focus();
        }
        if (state.dragging) {
          var targetPos = applyRelPos(state, MousePosition.calc(editor, e));
          appendGhostToBody(state.ghost, editor.getBody());
          moveGhost(state.ghost, targetPos, state.width, state.height, state.maxX, state.maxY);
          throttledPlaceCaretAt(e.clientX, e.clientY);
        }
      };
    };
    var getRawTarget = function (selection) {
      var rng = selection.getSel().getRangeAt(0);
      var startContainer = rng.startContainer;
      return startContainer.nodeType === 3 ? startContainer.parentNode : startContainer;
    };
    var drop = function (state, editor) {
      return function (e) {
        if (state.dragging) {
          if (isValidDropTarget(editor, getRawTarget(editor.selection), state.element)) {
            var targetClone_1 = cloneElement(state.element);
            var args = editor.fire('drop', {
              targetClone: targetClone_1,
              clientX: e.clientX,
              clientY: e.clientY
            });
            if (!args.isDefaultPrevented()) {
              targetClone_1 = args.targetClone;
              editor.undoManager.transact(function () {
                removeElement(state.element);
                editor.insertContent(editor.dom.getOuterHTML(targetClone_1));
                editor._selectionOverrides.hideFakeCaret();
              });
            }
          }
        }
        removeDragState(state);
      };
    };
    var stop = function (state, editor) {
      return function () {
        if (state.dragging) {
          editor.fire('dragend');
        }
        removeDragState(state);
      };
    };
    var removeDragState = function (state) {
      state.dragging = false;
      state.element = null;
      removeElement(state.ghost);
    };
    var bindFakeDragEvents = function (editor) {
      var state = {};
      var pageDom, dragStartHandler, dragHandler, dropHandler, dragEndHandler, rootDocument;
      pageDom = DOMUtils$1.DOM;
      rootDocument = domGlobals.document;
      dragStartHandler = start$1(state, editor);
      dragHandler = move$1(state, editor);
      dropHandler = drop(state, editor);
      dragEndHandler = stop(state, editor);
      editor.on('mousedown', dragStartHandler);
      editor.on('mousemove', dragHandler);
      editor.on('mouseup', dropHandler);
      pageDom.bind(rootDocument, 'mousemove', dragHandler);
      pageDom.bind(rootDocument, 'mouseup', dragEndHandler);
      editor.on('remove', function () {
        pageDom.unbind(rootDocument, 'mousemove', dragHandler);
        pageDom.unbind(rootDocument, 'mouseup', dragEndHandler);
      });
    };
    var blockIeDrop = function (editor) {
      editor.on('drop', function (e) {
        var realTarget = typeof e.clientX !== 'undefined' ? editor.getDoc().elementFromPoint(e.clientX, e.clientY) : null;
        if (isContentEditableFalse$8(realTarget) || isContentEditableFalse$8(editor.dom.getContentEditableParent(realTarget))) {
          e.preventDefault();
        }
      });
    };
    var init = function (editor) {
      bindFakeDragEvents(editor);
      blockIeDrop(editor);
    };
    var DragDropOverrides = { init: init };

    var setup$4 = function (editor) {
      var renderFocusCaret = first(function () {
        if (!editor.removed) {
          var rng = editor.selection.getRng();
          if (rng.collapsed) {
            var caretRange = renderRangeCaret(editor, editor.selection.getRng(), false);
            editor.selection.setRng(caretRange);
          }
        }
      }, 0);
      editor.on('focus', function () {
        renderFocusCaret.throttle();
      });
      editor.on('blur', function () {
        renderFocusCaret.cancel();
      });
    };
    var CefFocus = { setup: setup$4 };

    var isContentEditableTrue$4 = NodeType.isContentEditableTrue;
    var isContentEditableFalse$9 = NodeType.isContentEditableFalse;
    var getContentEditableRoot$1 = function (editor, node) {
      var root = editor.getBody();
      while (node && node !== root) {
        if (isContentEditableTrue$4(node) || isContentEditableFalse$9(node)) {
          return node;
        }
        node = node.parentNode;
      }
      return null;
    };
    var SelectionOverrides = function (editor) {
      var isBlock = function (node) {
        return editor.dom.isBlock(node);
      };
      var rootNode = editor.getBody();
      var fakeCaret = FakeCaret(editor.getBody(), isBlock, function () {
        return EditorFocus.hasFocus(editor);
      });
      var realSelectionId = 'sel-' + editor.dom.uniqueId();
      var selectedContentEditableNode;
      var isFakeSelectionElement = function (elm) {
        return editor.dom.hasClass(elm, 'mce-offscreen-selection');
      };
      var getRealSelectionElement = function () {
        var container = editor.dom.get(realSelectionId);
        return container ? container.getElementsByTagName('*')[0] : container;
      };
      var setRange = function (range) {
        if (range) {
          editor.selection.setRng(range);
        }
      };
      var getRange = function () {
        return editor.selection.getRng();
      };
      var showCaret = function (direction, node, before, scrollIntoView) {
        if (scrollIntoView === void 0) {
          scrollIntoView = true;
        }
        var e;
        e = editor.fire('ShowCaret', {
          target: node,
          direction: direction,
          before: before
        });
        if (e.isDefaultPrevented()) {
          return null;
        }
        if (scrollIntoView) {
          editor.selection.scrollIntoView(node, direction === -1);
        }
        return fakeCaret.show(before, node);
      };
      var getNormalizedRangeEndPoint = function (direction, range) {
        range = normalizeRange(direction, rootNode, range);
        if (direction === -1) {
          return CaretPosition$1.fromRangeStart(range);
        }
        return CaretPosition$1.fromRangeEnd(range);
      };
      var showBlockCaretContainer = function (blockCaretContainer) {
        if (blockCaretContainer.hasAttribute('data-mce-caret')) {
          showCaretContainerBlock(blockCaretContainer);
          setRange(getRange());
          editor.selection.scrollIntoView(blockCaretContainer[0]);
        }
      };
      var registerEvents = function () {
        editor.on('mouseup', function (e) {
          var range = getRange();
          if (range.collapsed && EditorView.isXYInContentArea(editor, e.clientX, e.clientY)) {
            setRange(renderCaretAtRange(editor, range, false));
          }
        });
        editor.on('click', function (e) {
          var contentEditableRoot;
          contentEditableRoot = getContentEditableRoot$1(editor, e.target);
          if (contentEditableRoot) {
            if (isContentEditableFalse$9(contentEditableRoot)) {
              e.preventDefault();
              editor.focus();
            }
            if (isContentEditableTrue$4(contentEditableRoot)) {
              if (editor.dom.isChildOf(contentEditableRoot, editor.selection.getNode())) {
                removeContentEditableSelection();
              }
            }
          }
        });
        editor.on('blur NewBlock', function () {
          removeContentEditableSelection();
        });
        editor.on('ResizeWindow FullscreenStateChanged', function () {
          return fakeCaret.reposition();
        });
        var handleTouchSelect = function (editor) {
          var moved = false;
          editor.on('touchstart', function () {
            moved = false;
          });
          editor.on('touchmove', function () {
            moved = true;
          });
          editor.on('touchend', function (e) {
            var contentEditableRoot = getContentEditableRoot$1(editor, e.target);
            if (isContentEditableFalse$9(contentEditableRoot)) {
              if (!moved) {
                e.preventDefault();
                setContentEditableSelection(selectNode(editor, contentEditableRoot));
              }
            }
          });
        };
        var hasNormalCaretPosition = function (elm) {
          var caretWalker = CaretWalker(elm);
          if (!elm.firstChild) {
            return false;
          }
          var startPos = CaretPosition$1.before(elm.firstChild);
          var newPos = caretWalker.next(startPos);
          return newPos && !isBeforeContentEditableFalse(newPos) && !isAfterContentEditableFalse(newPos);
        };
        var isInSameBlock = function (node1, node2) {
          var block1 = editor.dom.getParent(node1, editor.dom.isBlock);
          var block2 = editor.dom.getParent(node2, editor.dom.isBlock);
          return block1 === block2;
        };
        var hasBetterMouseTarget = function (targetNode, caretNode) {
          var targetBlock = editor.dom.getParent(targetNode, editor.dom.isBlock);
          var caretBlock = editor.dom.getParent(caretNode, editor.dom.isBlock);
          if (targetBlock && editor.dom.isChildOf(targetBlock, caretBlock) && isContentEditableFalse$9(getContentEditableRoot$1(editor, targetBlock)) === false) {
            return true;
          }
          return targetBlock && !isInSameBlock(targetBlock, caretBlock) && hasNormalCaretPosition(targetBlock);
        };
        handleTouchSelect(editor);
        editor.on('mousedown', function (e) {
          var contentEditableRoot;
          var targetElm = e.target;
          if (targetElm !== rootNode && targetElm.nodeName !== 'HTML' && !editor.dom.isChildOf(targetElm, rootNode)) {
            return;
          }
          if (EditorView.isXYInContentArea(editor, e.clientX, e.clientY) === false) {
            return;
          }
          contentEditableRoot = getContentEditableRoot$1(editor, targetElm);
          if (contentEditableRoot) {
            if (isContentEditableFalse$9(contentEditableRoot)) {
              e.preventDefault();
              setContentEditableSelection(selectNode(editor, contentEditableRoot));
            } else {
              removeContentEditableSelection();
              if (!(isContentEditableTrue$4(contentEditableRoot) && e.shiftKey) && !RangePoint.isXYWithinRange(e.clientX, e.clientY, editor.selection.getRng())) {
                hideFakeCaret();
                editor.selection.placeCaretAt(e.clientX, e.clientY);
              }
            }
          } else if (isFakeCaretTarget(targetElm) === false) {
            removeContentEditableSelection();
            hideFakeCaret();
            var caretInfo = closestCaret(rootNode, e.clientX, e.clientY);
            if (caretInfo) {
              if (!hasBetterMouseTarget(e.target, caretInfo.node)) {
                e.preventDefault();
                var range = showCaret(1, caretInfo.node, caretInfo.before, false);
                editor.getBody().focus();
                setRange(range);
              }
            }
          }
        });
        editor.on('keypress', function (e) {
          if (VK.modifierPressed(e)) {
            return;
          }
          switch (e.keyCode) {
          default:
            if (isContentEditableFalse$9(editor.selection.getNode())) {
              e.preventDefault();
            }
            break;
          }
        });
        editor.on('getSelectionRange', function (e) {
          var rng = e.range;
          if (selectedContentEditableNode) {
            if (!selectedContentEditableNode.parentNode) {
              selectedContentEditableNode = null;
              return;
            }
            rng = rng.cloneRange();
            rng.selectNode(selectedContentEditableNode);
            e.range = rng;
          }
        });
        editor.on('setSelectionRange', function (e) {
          e.range = normalizeShortEndedElementSelection(e.range);
          var rng = setContentEditableSelection(e.range, e.forward);
          if (rng) {
            e.range = rng;
          }
        });
        var isPasteBin = function (node) {
          return node.id === 'mcepastebin';
        };
        editor.on('AfterSetSelectionRange', function (e) {
          var rng = e.range;
          if (!isRangeInCaretContainer(rng) && !isPasteBin(rng.startContainer.parentNode)) {
            hideFakeCaret();
          }
          if (!isFakeSelectionElement(rng.startContainer.parentNode)) {
            removeContentEditableSelection();
          }
        });
        editor.on('copy', function (e) {
          var clipboardData = e.clipboardData;
          if (!e.isDefaultPrevented() && e.clipboardData && !Env.ie) {
            var realSelectionElement = getRealSelectionElement();
            if (realSelectionElement) {
              e.preventDefault();
              clipboardData.clearData();
              clipboardData.setData('text/html', realSelectionElement.outerHTML);
              clipboardData.setData('text/plain', realSelectionElement.outerText);
            }
          }
        });
        DragDropOverrides.init(editor);
        CefFocus.setup(editor);
      };
      var addCss = function () {
        var styles = editor.contentStyles, rootClass = '.mce-content-body';
        styles.push(fakeCaret.getCss());
        styles.push(rootClass + ' .mce-offscreen-selection {' + 'position: absolute;' + 'left: -9999999999px;' + 'max-width: 1000000px;' + '}' + rootClass + ' *[contentEditable=false] {' + 'cursor: default;' + '}' + rootClass + ' *[contentEditable=true] {' + 'cursor: text;' + '}');
      };
      var isWithinCaretContainer = function (node) {
        return isCaretContainer(node) || startsWithCaretContainer(node) || endsWithCaretContainer(node);
      };
      var isRangeInCaretContainer = function (rng) {
        return isWithinCaretContainer(rng.startContainer) || isWithinCaretContainer(rng.endContainer);
      };
      var normalizeShortEndedElementSelection = function (rng) {
        var shortEndedElements = editor.schema.getShortEndedElements();
        var newRng = editor.dom.createRng();
        var startContainer = rng.startContainer;
        var startOffset = rng.startOffset;
        var endContainer = rng.endContainer;
        var endOffset = rng.endOffset;
        if (has(shortEndedElements, startContainer.nodeName.toLowerCase())) {
          if (startOffset === 0) {
            newRng.setStartBefore(startContainer);
          } else {
            newRng.setStartAfter(startContainer);
          }
        } else {
          newRng.setStart(startContainer, startOffset);
        }
        if (has(shortEndedElements, endContainer.nodeName.toLowerCase())) {
          if (endOffset === 0) {
            newRng.setEndBefore(endContainer);
          } else {
            newRng.setEndAfter(endContainer);
          }
        } else {
          newRng.setEnd(endContainer, endOffset);
        }
        return newRng;
      };
      var setContentEditableSelection = function (range, forward) {
        var node;
        var $ = editor.$;
        var dom = editor.dom;
        var $realSelectionContainer, sel, startContainer, startOffset, endOffset, e, caretPosition, targetClone, origTargetClone;
        if (!range) {
          return null;
        }
        if (range.collapsed) {
          if (!isRangeInCaretContainer(range)) {
            if (forward === false) {
              caretPosition = getNormalizedRangeEndPoint(-1, range);
              if (isFakeCaretTarget(caretPosition.getNode(true))) {
                return showCaret(-1, caretPosition.getNode(true), false, false);
              }
              if (isFakeCaretTarget(caretPosition.getNode())) {
                return showCaret(-1, caretPosition.getNode(), !caretPosition.isAtEnd(), false);
              }
            } else {
              caretPosition = getNormalizedRangeEndPoint(1, range);
              if (isFakeCaretTarget(caretPosition.getNode())) {
                return showCaret(1, caretPosition.getNode(), !caretPosition.isAtEnd(), false);
              }
              if (isFakeCaretTarget(caretPosition.getNode(true))) {
                return showCaret(1, caretPosition.getNode(true), false, false);
              }
            }
          }
          return null;
        }
        startContainer = range.startContainer;
        startOffset = range.startOffset;
        endOffset = range.endOffset;
        if (startContainer.nodeType === 3 && startOffset === 0 && isContentEditableFalse$9(startContainer.parentNode)) {
          startContainer = startContainer.parentNode;
          startOffset = dom.nodeIndex(startContainer);
          startContainer = startContainer.parentNode;
        }
        if (startContainer.nodeType !== 1) {
          return null;
        }
        if (endOffset === startOffset + 1 && startContainer === range.endContainer) {
          node = startContainer.childNodes[startOffset];
        }
        if (!isContentEditableFalse$9(node)) {
          return null;
        }
        targetClone = origTargetClone = node.cloneNode(true);
        e = editor.fire('ObjectSelected', {
          target: node,
          targetClone: targetClone
        });
        if (e.isDefaultPrevented()) {
          return null;
        }
        $realSelectionContainer = descendant(Element.fromDom(editor.getBody()), '#' + realSelectionId).fold(function () {
          return $([]);
        }, function (elm) {
          return $([elm.dom()]);
        });
        targetClone = e.targetClone;
        if ($realSelectionContainer.length === 0) {
          $realSelectionContainer = $('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>').attr('id', realSelectionId);
          $realSelectionContainer.appendTo(editor.getBody());
        }
        range = editor.dom.createRng();
        if (targetClone === origTargetClone && Env.ie) {
          $realSelectionContainer.empty().append('<p style="font-size: 0" data-mce-bogus="all">\xA0</p>').append(targetClone);
          range.setStartAfter($realSelectionContainer[0].firstChild.firstChild);
          range.setEndAfter(targetClone);
        } else {
          $realSelectionContainer.empty().append('\xA0').append(targetClone).append('\xA0');
          range.setStart($realSelectionContainer[0].firstChild, 1);
          range.setEnd($realSelectionContainer[0].lastChild, 0);
        }
        $realSelectionContainer.css({ top: dom.getPos(node, editor.getBody()).y });
        $realSelectionContainer[0].focus();
        sel = editor.selection.getSel();
        sel.removeAllRanges();
        sel.addRange(range);
        each(descendants$1(Element.fromDom(editor.getBody()), '*[data-mce-selected]'), function (elm) {
          remove(elm, 'data-mce-selected');
        });
        node.setAttribute('data-mce-selected', '1');
        selectedContentEditableNode = node;
        hideFakeCaret();
        return range;
      };
      var removeContentEditableSelection = function () {
        if (selectedContentEditableNode) {
          selectedContentEditableNode.removeAttribute('data-mce-selected');
          descendant(Element.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$1);
          selectedContentEditableNode = null;
        }
        descendant(Element.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$1);
        selectedContentEditableNode = null;
      };
      var destroy = function () {
        fakeCaret.destroy();
        selectedContentEditableNode = null;
      };
      var hideFakeCaret = function () {
        fakeCaret.hide();
      };
      if (Env.ceFalse) {
        registerEvents();
        addCss();
      }
      return {
        showCaret: showCaret,
        showBlockCaretContainer: showBlockCaretContainer,
        hideFakeCaret: hideFakeCaret,
        destroy: destroy
      };
    };

    var isValidPrefixAttrName = function (name) {
      return name.indexOf('data-') === 0 || name.indexOf('aria-') === 0;
    };
    var trimComments = function (text) {
      var sanitizedText = text;
      while (/<!--|--!?>/g.test(sanitizedText)) {
        sanitizedText = sanitizedText.replace(/<!--|--!?>/g, '');
      }
      return sanitizedText;
    };
    var isInvalidUri = function (settings, uri) {
      if (settings.allow_html_data_urls) {
        return false;
      } else if (/^data:image\//i.test(uri)) {
        return settings.allow_svg_data_urls === false && /^data:image\/svg\+xml/i.test(uri);
      } else {
        return /^data:/i.test(uri);
      }
    };
    var findEndTagIndex = function (schema, html, startIndex) {
      var count = 1, index, matches, tokenRegExp, shortEndedElements;
      shortEndedElements = schema.getShortEndedElements();
      tokenRegExp = /<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g;
      tokenRegExp.lastIndex = index = startIndex;
      while (matches = tokenRegExp.exec(html)) {
        index = tokenRegExp.lastIndex;
        if (matches[1] === '/') {
          count--;
        } else if (!matches[1]) {
          if (matches[2] in shortEndedElements) {
            continue;
          }
          count++;
        }
        if (count === 0) {
          break;
        }
      }
      return index;
    };
    var checkBogusAttribute = function (regExp, attrString) {
      var matches = regExp.exec(attrString);
      if (matches) {
        var name = matches[1];
        var value = matches[2];
        return typeof name === 'string' && name.toLowerCase() === 'data-mce-bogus' ? value : null;
      } else {
        return null;
      }
    };
    function SaxParser(settings, schema) {
      if (schema === void 0) {
        schema = Schema();
      }
      var noop = function () {
      };
      settings = settings || {};
      if (settings.fix_self_closing !== false) {
        settings.fix_self_closing = true;
      }
      var comment = settings.comment ? settings.comment : noop;
      var cdata = settings.cdata ? settings.cdata : noop;
      var text = settings.text ? settings.text : noop;
      var start = settings.start ? settings.start : noop;
      var end = settings.end ? settings.end : noop;
      var pi = settings.pi ? settings.pi : noop;
      var doctype = settings.doctype ? settings.doctype : noop;
      var parse = function (html) {
        var matches, index = 0, value, endRegExp;
        var stack = [];
        var attrList, i, textData, name;
        var isInternalElement, removeInternalElements, shortEndedElements, fillAttrsMap, isShortEnded;
        var validate, elementRule, isValidElement, attr, attribsValue, validAttributesMap, validAttributePatterns;
        var attributesRequired, attributesDefault, attributesForced, processHtml;
        var anyAttributesRequired, selfClosing, tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0;
        var decode = Entities.decode;
        var fixSelfClosing;
        var filteredUrlAttrs = Tools.makeMap('src,href,data,background,formaction,poster,xlink:href');
        var scriptUriRegExp = /((java|vb)script|mhtml):/i;
        var processEndTag = function (name) {
          var pos, i;
          pos = stack.length;
          while (pos--) {
            if (stack[pos].name === name) {
              break;
            }
          }
          if (pos >= 0) {
            for (i = stack.length - 1; i >= pos; i--) {
              name = stack[i];
              if (name.valid) {
                end(name.name);
              }
            }
            stack.length = pos;
          }
        };
        var parseAttribute = function (match, name, value, val2, val3) {
          var attrRule, i;
          var trimRegExp = /[\s\u0000-\u001F]+/g;
          name = name.toLowerCase();
          value = name in fillAttrsMap ? name : decode(value || val2 || val3 || '');
          if (validate && !isInternalElement && isValidPrefixAttrName(name) === false) {
            attrRule = validAttributesMap[name];
            if (!attrRule && validAttributePatterns) {
              i = validAttributePatterns.length;
              while (i--) {
                attrRule = validAttributePatterns[i];
                if (attrRule.pattern.test(name)) {
                  break;
                }
              }
              if (i === -1) {
                attrRule = null;
              }
            }
            if (!attrRule) {
              return;
            }
            if (attrRule.validValues && !(value in attrRule.validValues)) {
              return;
            }
          }
          if (filteredUrlAttrs[name] && !settings.allow_script_urls) {
            var uri = value.replace(trimRegExp, '');
            try {
              uri = decodeURIComponent(uri);
            } catch (ex) {
              uri = unescape(uri);
            }
            if (scriptUriRegExp.test(uri)) {
              return;
            }
            if (isInvalidUri(settings, uri)) {
              return;
            }
          }
          if (isInternalElement && (name in filteredUrlAttrs || name.indexOf('on') === 0)) {
            return;
          }
          attrList.map[name] = value;
          attrList.push({
            name: name,
            value: value
          });
        };
        tokenRegExp = new RegExp('<(?:' + '(?:!--([\\w\\W]*?)--!?>)|' + '(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|' + '(?:!DOCTYPE([\\w\\W]*?)>)|' + '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + '(?:\\/([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)>)|' + '(?:([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + ')', 'g');
        attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
        shortEndedElements = schema.getShortEndedElements();
        selfClosing = settings.self_closing_elements || schema.getSelfClosingElements();
        fillAttrsMap = schema.getBoolAttrs();
        validate = settings.validate;
        removeInternalElements = settings.remove_internals;
        fixSelfClosing = settings.fix_self_closing;
        specialElements = schema.getSpecialElements();
        processHtml = html + '>';
        while (matches = tokenRegExp.exec(processHtml)) {
          if (index < matches.index) {
            text(decode(html.substr(index, matches.index - index)));
          }
          if (value = matches[6]) {
            value = value.toLowerCase();
            if (value.charAt(0) === ':') {
              value = value.substr(1);
            }
            processEndTag(value);
          } else if (value = matches[7]) {
            if (matches.index + matches[0].length > html.length) {
              text(decode(html.substr(matches.index)));
              index = matches.index + matches[0].length;
              continue;
            }
            value = value.toLowerCase();
            if (value.charAt(0) === ':') {
              value = value.substr(1);
            }
            isShortEnded = value in shortEndedElements;
            if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value) {
              processEndTag(value);
            }
            var bogusValue = checkBogusAttribute(attrRegExp, matches[8]);
            if (bogusValue !== null) {
              if (bogusValue === 'all') {
                index = findEndTagIndex(schema, html, tokenRegExp.lastIndex);
                tokenRegExp.lastIndex = index;
                continue;
              }
              isValidElement = false;
            }
            if (!validate || (elementRule = schema.getElementRule(value))) {
              isValidElement = true;
              if (validate) {
                validAttributesMap = elementRule.attributes;
                validAttributePatterns = elementRule.attributePatterns;
              }
              if (attribsValue = matches[8]) {
                isInternalElement = attribsValue.indexOf('data-mce-type') !== -1;
                if (isInternalElement && removeInternalElements) {
                  isValidElement = false;
                }
                attrList = [];
                attrList.map = {};
                attribsValue.replace(attrRegExp, parseAttribute);
              } else {
                attrList = [];
                attrList.map = {};
              }
              if (validate && !isInternalElement) {
                attributesRequired = elementRule.attributesRequired;
                attributesDefault = elementRule.attributesDefault;
                attributesForced = elementRule.attributesForced;
                anyAttributesRequired = elementRule.removeEmptyAttrs;
                if (anyAttributesRequired && !attrList.length) {
                  isValidElement = false;
                }
                if (attributesForced) {
                  i = attributesForced.length;
                  while (i--) {
                    attr = attributesForced[i];
                    name = attr.name;
                    attrValue = attr.value;
                    if (attrValue === '{$uid}') {
                      attrValue = 'mce_' + idCount++;
                    }
                    attrList.map[name] = attrValue;
                    attrList.push({
                      name: name,
                      value: attrValue
                    });
                  }
                }
                if (attributesDefault) {
                  i = attributesDefault.length;
                  while (i--) {
                    attr = attributesDefault[i];
                    name = attr.name;
                    if (!(name in attrList.map)) {
                      attrValue = attr.value;
                      if (attrValue === '{$uid}') {
                        attrValue = 'mce_' + idCount++;
                      }
                      attrList.map[name] = attrValue;
                      attrList.push({
                        name: name,
                        value: attrValue
                      });
                    }
                  }
                }
                if (attributesRequired) {
                  i = attributesRequired.length;
                  while (i--) {
                    if (attributesRequired[i] in attrList.map) {
                      break;
                    }
                  }
                  if (i === -1) {
                    isValidElement = false;
                  }
                }
                if (attr = attrList.map['data-mce-bogus']) {
                  if (attr === 'all') {
                    index = findEndTagIndex(schema, html, tokenRegExp.lastIndex);
                    tokenRegExp.lastIndex = index;
                    continue;
                  }
                  isValidElement = false;
                }
              }
              if (isValidElement) {
                start(value, attrList, isShortEnded);
              }
            } else {
              isValidElement = false;
            }
            if (endRegExp = specialElements[value]) {
              endRegExp.lastIndex = index = matches.index + matches[0].length;
              if (matches = endRegExp.exec(html)) {
                if (isValidElement) {
                  textData = html.substr(index, matches.index - index);
                }
                index = matches.index + matches[0].length;
              } else {
                textData = html.substr(index);
                index = html.length;
              }
              if (isValidElement) {
                if (textData.length > 0) {
                  text(textData, true);
                }
                end(value);
              }
              tokenRegExp.lastIndex = index;
              continue;
            }
            if (!isShortEnded) {
              if (!attribsValue || attribsValue.indexOf('/') !== attribsValue.length - 1) {
                stack.push({
                  name: value,
                  valid: isValidElement
                });
              } else if (isValidElement) {
                end(value);
              }
            }
          } else if (value = matches[1]) {
            if (value.charAt(0) === '>') {
              value = ' ' + value;
            }
            if (!settings.allow_conditional_comments && value.substr(0, 3).toLowerCase() === '[if') {
              value = ' ' + value;
            }
            comment(value);
          } else if (value = matches[2]) {
            cdata(trimComments(value));
          } else if (value = matches[3]) {
            doctype(value);
          } else if (value = matches[4]) {
            pi(value, matches[5]);
          }
          index = matches.index + matches[0].length;
        }
        if (index < html.length) {
          text(decode(html.substr(index)));
        }
        for (i = stack.length - 1; i >= 0; i--) {
          value = stack[i];
          if (value.valid) {
            end(value.name);
          }
        }
      };
      return { parse: parse };
    }
    (function (SaxParser) {
      SaxParser.findEndTag = findEndTagIndex;
    }(SaxParser || (SaxParser = {})));
    var SaxParser$1 = SaxParser;

    var trimHtml = function (tempAttrs, html) {
      var trimContentRegExp = new RegExp(['\\s?(' + tempAttrs.join('|') + ')="[^"]+"'].join('|'), 'gi');
      return html.replace(trimContentRegExp, '');
    };
    var trimInternal = function (serializer, html) {
      var content = html;
      var bogusAllRegExp = /<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g;
      var endTagIndex, index, matchLength, matches, shortEndedElements;
      var schema = serializer.schema;
      content = trimHtml(serializer.getTempAttrs(), content);
      shortEndedElements = schema.getShortEndedElements();
      while (matches = bogusAllRegExp.exec(content)) {
        index = bogusAllRegExp.lastIndex;
        matchLength = matches[0].length;
        if (shortEndedElements[matches[1]]) {
          endTagIndex = index;
        } else {
          endTagIndex = SaxParser$1.findEndTag(schema, content, index);
        }
        content = content.substring(0, index - matchLength) + content.substring(endTagIndex);
        bogusAllRegExp.lastIndex = index - matchLength;
      }
      return Zwsp.trim(content);
    };
    var trimExternal = trimInternal;
    var TrimHtml = {
      trimExternal: trimExternal,
      trimInternal: trimInternal
    };

    var KEEP = 0, INSERT = 1, DELETE = 2;
    var diff = function (left, right) {
      var size = left.length + right.length + 2;
      var vDown = new Array(size);
      var vUp = new Array(size);
      var snake = function (start, end, diag) {
        return {
          start: start,
          end: end,
          diag: diag
        };
      };
      var buildScript = function (start1, end1, start2, end2, script) {
        var middle = getMiddleSnake(start1, end1, start2, end2);
        if (middle === null || middle.start === end1 && middle.diag === end1 - end2 || middle.end === start1 && middle.diag === start1 - start2) {
          var i = start1;
          var j = start2;
          while (i < end1 || j < end2) {
            if (i < end1 && j < end2 && left[i] === right[j]) {
              script.push([
                KEEP,
                left[i]
              ]);
              ++i;
              ++j;
            } else {
              if (end1 - start1 > end2 - start2) {
                script.push([
                  DELETE,
                  left[i]
                ]);
                ++i;
              } else {
                script.push([
                  INSERT,
                  right[j]
                ]);
                ++j;
              }
            }
          }
        } else {
          buildScript(start1, middle.start, start2, middle.start - middle.diag, script);
          for (var i2 = middle.start; i2 < middle.end; ++i2) {
            script.push([
              KEEP,
              left[i2]
            ]);
          }
          buildScript(middle.end, end1, middle.end - middle.diag, end2, script);
        }
      };
      var buildSnake = function (start, diag, end1, end2) {
        var end = start;
        while (end - diag < end2 && end < end1 && left[end] === right[end - diag]) {
          ++end;
        }
        return snake(start, end, diag);
      };
      var getMiddleSnake = function (start1, end1, start2, end2) {
        var m = end1 - start1;
        var n = end2 - start2;
        if (m === 0 || n === 0) {
          return null;
        }
        var delta = m - n;
        var sum = n + m;
        var offset = (sum % 2 === 0 ? sum : sum + 1) / 2;
        vDown[1 + offset] = start1;
        vUp[1 + offset] = end1 + 1;
        var d, k, i, x, y;
        for (d = 0; d <= offset; ++d) {
          for (k = -d; k <= d; k += 2) {
            i = k + offset;
            if (k === -d || k !== d && vDown[i - 1] < vDown[i + 1]) {
              vDown[i] = vDown[i + 1];
            } else {
              vDown[i] = vDown[i - 1] + 1;
            }
            x = vDown[i];
            y = x - start1 + start2 - k;
            while (x < end1 && y < end2 && left[x] === right[y]) {
              vDown[i] = ++x;
              ++y;
            }
            if (delta % 2 !== 0 && delta - d <= k && k <= delta + d) {
              if (vUp[i - delta] <= vDown[i]) {
                return buildSnake(vUp[i - delta], k + start1 - start2, end1, end2);
              }
            }
          }
          for (k = delta - d; k <= delta + d; k += 2) {
            i = k + offset - delta;
            if (k === delta - d || k !== delta + d && vUp[i + 1] <= vUp[i - 1]) {
              vUp[i] = vUp[i + 1] - 1;
            } else {
              vUp[i] = vUp[i - 1];
            }
            x = vUp[i] - 1;
            y = x - start1 + start2 - k;
            while (x >= start1 && y >= start2 && left[x] === right[y]) {
              vUp[i] = x--;
              y--;
            }
            if (delta % 2 === 0 && -d <= k && k <= d) {
              if (vUp[i] <= vDown[i + delta]) {
                return buildSnake(vUp[i], k + start1 - start2, end1, end2);
              }
            }
          }
        }
      };
      var script = [];
      buildScript(0, left.length, 0, right.length, script);
      return script;
    };
    var Diff = {
      KEEP: KEEP,
      DELETE: DELETE,
      INSERT: INSERT,
      diff: diff
    };

    var getOuterHtml = function (elm) {
      if (NodeType.isElement(elm)) {
        return elm.outerHTML;
      } else if (NodeType.isText(elm)) {
        return Entities.encodeRaw(elm.data, false);
      } else if (NodeType.isComment(elm)) {
        return '<!--' + elm.data + '-->';
      }
      return '';
    };
    var createFragment$1 = function (html) {
      var frag, node, container;
      container = domGlobals.document.createElement('div');
      frag = domGlobals.document.createDocumentFragment();
      if (html) {
        container.innerHTML = html;
      }
      while (node = container.firstChild) {
        frag.appendChild(node);
      }
      return frag;
    };
    var insertAt = function (elm, html, index) {
      var fragment = createFragment$1(html);
      if (elm.hasChildNodes() && index < elm.childNodes.length) {
        var target = elm.childNodes[index];
        target.parentNode.insertBefore(fragment, target);
      } else {
        elm.appendChild(fragment);
      }
    };
    var removeAt = function (elm, index) {
      if (elm.hasChildNodes() && index < elm.childNodes.length) {
        var target = elm.childNodes[index];
        target.parentNode.removeChild(target);
      }
    };
    var applyDiff = function (diff, elm) {
      var index = 0;
      each(diff, function (action) {
        if (action[0] === Diff.KEEP) {
          index++;
        } else if (action[0] === Diff.INSERT) {
          insertAt(elm, action[1], index);
          index++;
        } else if (action[0] === Diff.DELETE) {
          removeAt(elm, index);
        }
      });
    };
    var read$3 = function (elm) {
      return filter(map(from$1(elm.childNodes), getOuterHtml), function (item) {
        return item.length > 0;
      });
    };
    var write = function (fragments, elm) {
      var currentFragments = map(from$1(elm.childNodes), getOuterHtml);
      applyDiff(Diff.diff(currentFragments, fragments), elm);
      return elm;
    };
    var Fragments = {
      read: read$3,
      write: write
    };

    var undoLevelDocument = Cell(Option.none());
    var lazyTempDocument = function () {
      return undoLevelDocument.get().getOrThunk(function () {
        var doc = domGlobals.document.implementation.createHTMLDocument('undo');
        undoLevelDocument.set(Option.some(doc));
        return doc;
      });
    };
    var hasIframes = function (html) {
      return html.indexOf('</iframe>') !== -1;
    };
    var createFragmentedLevel = function (fragments) {
      return {
        type: 'fragmented',
        fragments: fragments,
        content: '',
        bookmark: null,
        beforeBookmark: null
      };
    };
    var createCompleteLevel = function (content) {
      return {
        type: 'complete',
        fragments: null,
        content: content,
        bookmark: null,
        beforeBookmark: null
      };
    };
    var createFromEditor = function (editor) {
      var fragments, content, trimmedFragments;
      fragments = Fragments.read(editor.getBody());
      trimmedFragments = bind(fragments, function (html) {
        var trimmed = TrimHtml.trimInternal(editor.serializer, html);
        return trimmed.length > 0 ? [trimmed] : [];
      });
      content = trimmedFragments.join('');
      return hasIframes(content) ? createFragmentedLevel(trimmedFragments) : createCompleteLevel(content);
    };
    var applyToEditor = function (editor, level, before) {
      if (level.type === 'fragmented') {
        Fragments.write(level.fragments, editor.getBody());
      } else {
        editor.setContent(level.content, { format: 'raw' });
      }
      editor.selection.moveToBookmark(before ? level.beforeBookmark : level.bookmark);
    };
    var getLevelContent = function (level) {
      return level.type === 'fragmented' ? level.fragments.join('') : level.content;
    };
    var getCleanLevelContent = function (level) {
      var elm = Element.fromTag('body', lazyTempDocument());
      set$1(elm, getLevelContent(level));
      each(descendants$1(elm, '*[data-mce-bogus]'), unwrap);
      return get$3(elm);
    };
    var hasEqualContent = function (level1, level2) {
      return getLevelContent(level1) === getLevelContent(level2);
    };
    var hasEqualCleanedContent = function (level1, level2) {
      return getCleanLevelContent(level1) === getCleanLevelContent(level2);
    };
    var isEq$4 = function (level1, level2) {
      if (!level1 || !level2) {
        return false;
      } else if (hasEqualContent(level1, level2)) {
        return true;
      } else {
        return hasEqualCleanedContent(level1, level2);
      }
    };
    var Levels = {
      createFragmentedLevel: createFragmentedLevel,
      createCompleteLevel: createCompleteLevel,
      createFromEditor: createFromEditor,
      applyToEditor: applyToEditor,
      isEq: isEq$4
    };

    function UndoManager (editor) {
      var self = this, index = 0, data = [], beforeBookmark, isFirstTypedCharacter, locks = 0;
      var isUnlocked = function () {
        return locks === 0;
      };
      var setTyping = function (typing) {
        if (isUnlocked()) {
          self.typing = typing;
        }
      };
      var setDirty = function (state) {
        editor.setDirty(state);
      };
      var addNonTypingUndoLevel = function (e) {
        setTyping(false);
        self.add({}, e);
      };
      var endTyping = function () {
        if (self.typing) {
          setTyping(false);
          self.add();
        }
      };
      editor.on('init', function () {
        self.add();
      });
      editor.on('BeforeExecCommand', function (e) {
        var cmd = e.command;
        if (cmd !== 'Undo' && cmd !== 'Redo' && cmd !== 'mceRepaint') {
          endTyping();
          self.beforeChange();
        }
      });
      editor.on('ExecCommand', function (e) {
        var cmd = e.command;
        if (cmd !== 'Undo' && cmd !== 'Redo' && cmd !== 'mceRepaint') {
          addNonTypingUndoLevel(e);
        }
      });
      editor.on('ObjectResizeStart Cut', function () {
        self.beforeChange();
      });
      editor.on('SaveContent ObjectResized blur', addNonTypingUndoLevel);
      editor.on('DragEnd', addNonTypingUndoLevel);
      editor.on('KeyUp', function (e) {
        var keyCode = e.keyCode;
        if (e.isDefaultPrevented()) {
          return;
        }
        if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45 || e.ctrlKey) {
          addNonTypingUndoLevel();
          editor.nodeChanged();
        }
        if (keyCode === 46 || keyCode === 8) {
          editor.nodeChanged();
        }
        if (isFirstTypedCharacter && self.typing && Levels.isEq(Levels.createFromEditor(editor), data[0]) === false) {
          if (editor.isDirty() === false) {
            setDirty(true);
            editor.fire('change', {
              level: data[0],
              lastLevel: null
            });
          }
          editor.fire('TypingUndo');
          isFirstTypedCharacter = false;
          editor.nodeChanged();
        }
      });
      editor.on('KeyDown', function (e) {
        var keyCode = e.keyCode;
        if (e.isDefaultPrevented()) {
          return;
        }
        if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45) {
          if (self.typing) {
            addNonTypingUndoLevel(e);
          }
          return;
        }
        var modKey = e.ctrlKey && !e.altKey || e.metaKey;
        if ((keyCode < 16 || keyCode > 20) && keyCode !== 224 && keyCode !== 91 && !self.typing && !modKey) {
          self.beforeChange();
          setTyping(true);
          self.add({}, e);
          isFirstTypedCharacter = true;
        }
      });
      editor.on('MouseDown', function (e) {
        if (self.typing) {
          addNonTypingUndoLevel(e);
        }
      });
      var isInsertReplacementText = function (event) {
        return event.inputType === 'insertReplacementText';
      };
      var isInsertTextDataNull = function (event) {
        return event.inputType === 'insertText' && event.data === null;
      };
      editor.on('input', function (e) {
        if (e.inputType && (isInsertReplacementText(e) || isInsertTextDataNull(e))) {
          addNonTypingUndoLevel(e);
        }
      });
      editor.addShortcut('meta+z', '', 'Undo');
      editor.addShortcut('meta+y,meta+shift+z', '', 'Redo');
      editor.on('AddUndo Undo Redo ClearUndos', function (e) {
        if (!e.isDefaultPrevented()) {
          editor.nodeChanged();
        }
      });
      self = {
        data: data,
        typing: false,
        beforeChange: function () {
          if (isUnlocked()) {
            beforeBookmark = GetBookmark.getUndoBookmark(editor.selection);
          }
        },
        add: function (level, event) {
          var i;
          var settings = editor.settings;
          var lastLevel, currentLevel;
          currentLevel = Levels.createFromEditor(editor);
          level = level || {};
          level = Tools.extend(level, currentLevel);
          if (isUnlocked() === false || editor.removed) {
            return null;
          }
          lastLevel = data[index];
          if (editor.fire('BeforeAddUndo', {
              level: level,
              lastLevel: lastLevel,
              originalEvent: event
            }).isDefaultPrevented()) {
            return null;
          }
          if (lastLevel && Levels.isEq(lastLevel, level)) {
            return null;
          }
          if (data[index]) {
            data[index].beforeBookmark = beforeBookmark;
          }
          if (settings.custom_undo_redo_levels) {
            if (data.length > settings.custom_undo_redo_levels) {
              for (i = 0; i < data.length - 1; i++) {
                data[i] = data[i + 1];
              }
              data.length--;
              index = data.length;
            }
          }
          level.bookmark = GetBookmark.getUndoBookmark(editor.selection);
          if (index < data.length - 1) {
            data.length = index + 1;
          }
          data.push(level);
          index = data.length - 1;
          var args = {
            level: level,
            lastLevel: lastLevel,
            originalEvent: event
          };
          editor.fire('AddUndo', args);
          if (index > 0) {
            setDirty(true);
            editor.fire('change', args);
          }
          return level;
        },
        undo: function () {
          var level;
          if (self.typing) {
            self.add();
            self.typing = false;
            setTyping(false);
          }
          if (index > 0) {
            level = data[--index];
            Levels.applyToEditor(editor, level, true);
            setDirty(true);
            editor.fire('undo', { level: level });
          }
          return level;
        },
        redo: function () {
          var level;
          if (index < data.length - 1) {
            level = data[++index];
            Levels.applyToEditor(editor, level, false);
            setDirty(true);
            editor.fire('redo', { level: level });
          }
          return level;
        },
        clear: function () {
          data = [];
          index = 0;
          self.typing = false;
          self.data = data;
          editor.fire('ClearUndos');
        },
        hasUndo: function () {
          return index > 0 || self.typing && data[0] && !Levels.isEq(Levels.createFromEditor(editor), data[0]);
        },
        hasRedo: function () {
          return index < data.length - 1 && !self.typing;
        },
        transact: function (callback) {
          endTyping();
          self.beforeChange();
          self.ignore(callback);
          return self.add();
        },
        ignore: function (callback) {
          try {
            locks++;
            callback();
          } finally {
            locks--;
          }
        },
        extra: function (callback1, callback2) {
          var lastLevel, bookmark;
          if (self.transact(callback1)) {
            bookmark = data[index].bookmark;
            lastLevel = data[index - 1];
            Levels.applyToEditor(editor, lastLevel, true);
            if (self.transact(callback2)) {
              data[index - 1].beforeBookmark = bookmark;
            }
          }
        }
      };
      return self;
    }

    var postProcessHooks = {}, filter$2 = ArrUtils.filter, each$c = ArrUtils.each;
    var addPostProcessHook = function (name, hook) {
      var hooks = postProcessHooks[name];
      if (!hooks) {
        postProcessHooks[name] = hooks = [];
      }
      postProcessHooks[name].push(hook);
    };
    var postProcess = function (name, editor) {
      each$c(postProcessHooks[name], function (hook) {
        hook(editor);
      });
    };
    addPostProcessHook('pre', function (editor) {
      var rng = editor.selection.getRng();
      var isPre, blocks;
      var hasPreSibling = function (pre) {
        return isPre(pre.previousSibling) && ArrUtils.indexOf(blocks, pre.previousSibling) !== -1;
      };
      var joinPre = function (pre1, pre2) {
        DomQuery(pre2).remove();
        DomQuery(pre1).append('<br><br>').append(pre2.childNodes);
      };
      isPre = NodeType.matchNodeNames('pre');
      if (!rng.collapsed) {
        blocks = editor.selection.getSelectedBlocks();
        each$c(filter$2(filter$2(blocks, isPre), hasPreSibling), function (pre) {
          joinPre(pre.previousSibling, pre);
        });
      }
    });
    var Hooks = { postProcess: postProcess };

    var MCE_ATTR_RE = /^(src|href|style)$/;
    var each$d = Tools.each;
    var isEq$5 = FormatUtils.isEq;
    var isTableCell$4 = function (node) {
      return /^(TH|TD)$/.test(node.nodeName);
    };
    var isChildOfInlineParent = function (dom, node, parent) {
      return dom.isChildOf(node, parent) && node !== parent && !dom.isBlock(parent);
    };
    var getContainer = function (ed, rng, start) {
      var container, offset, lastIdx;
      container = rng[start ? 'startContainer' : 'endContainer'];
      offset = rng[start ? 'startOffset' : 'endOffset'];
      if (NodeType.isElement(container)) {
        lastIdx = container.childNodes.length - 1;
        if (!start && offset) {
          offset--;
        }
        container = container.childNodes[offset > lastIdx ? lastIdx : offset];
      }
      if (NodeType.isText(container) && start && offset >= container.nodeValue.length) {
        container = new TreeWalker(container, ed.getBody()).next() || container;
      }
      if (NodeType.isText(container) && !start && offset === 0) {
        container = new TreeWalker(container, ed.getBody()).prev() || container;
      }
      return container;
    };
    var wrap$2 = function (dom, node, name, attrs) {
      var wrapper = dom.create(name, attrs);
      node.parentNode.insertBefore(wrapper, node);
      wrapper.appendChild(node);
      return wrapper;
    };
    var wrapWithSiblings = function (dom, node, next, name, attrs) {
      var start = Element.fromDom(node);
      var wrapper = Element.fromDom(dom.create(name, attrs));
      var siblings = next ? nextSiblings(start) : prevSiblings(start);
      append$1(wrapper, siblings);
      if (next) {
        before(start, wrapper);
        prepend(wrapper, start);
      } else {
        after(start, wrapper);
        append(wrapper, start);
      }
      return wrapper.dom();
    };
    var matchName$1 = function (dom, node, format) {
      if (isEq$5(node, format.inline)) {
        return true;
      }
      if (isEq$5(node, format.block)) {
        return true;
      }
      if (format.selector) {
        return NodeType.isElement(node) && dom.is(node, format.selector);
      }
    };
    var isColorFormatAndAnchor = function (node, format) {
      return format.links && node.tagName === 'A';
    };
    var find$3 = function (dom, node, next, inc) {
      node = FormatUtils.getNonWhiteSpaceSibling(node, next, inc);
      return !node || (node.nodeName === 'BR' || dom.isBlock(node));
    };
    var removeNode$1 = function (ed, node, format) {
      var parentNode = node.parentNode;
      var rootBlockElm;
      var dom = ed.dom, forcedRootBlock = ed.settings.forced_root_block;
      if (format.block) {
        if (!forcedRootBlock) {
          if (dom.isBlock(node) && !dom.isBlock(parentNode)) {
            if (!find$3(dom, node, false) && !find$3(dom, node.firstChild, true, 1)) {
              node.insertBefore(dom.create('br'), node.firstChild);
            }
            if (!find$3(dom, node, true) && !find$3(dom, node.lastChild, false, 1)) {
              node.appendChild(dom.create('br'));
            }
          }
        } else {
          if (parentNode === dom.getRoot()) {
            if (!format.list_block || !isEq$5(node, format.list_block)) {
              each$d(Tools.grep(node.childNodes), function (node) {
                if (FormatUtils.isValid(ed, forcedRootBlock, node.nodeName.toLowerCase())) {
                  if (!rootBlockElm) {
                    rootBlockElm = wrap$2(dom, node, forcedRootBlock);
                    dom.setAttribs(rootBlockElm, ed.settings.forced_root_block_attrs);
                  } else {
                    rootBlockElm.appendChild(node);
                  }
                } else {
                  rootBlockElm = 0;
                }
              });
            }
          }
        }
      }
      if (format.selector && format.inline && !isEq$5(format.inline, node)) {
        return;
      }
      dom.remove(node, 1);
    };
    var removeFormat = function (ed, format, vars, node, compareNode) {
      var i, attrs, stylesModified;
      var dom = ed.dom;
      if (!matchName$1(dom, node, format) && !isColorFormatAndAnchor(node, format)) {
        return false;
      }
      if (format.remove !== 'all') {
        each$d(format.styles, function (value, name) {
          value = FormatUtils.normalizeStyleValue(dom, FormatUtils.replaceVars(value, vars), name);
          if (typeof name === 'number') {
            name = value;
            compareNode = 0;
          }
          if (format.remove_similar || (!compareNode || isEq$5(FormatUtils.getStyle(dom, compareNode, name), value))) {
            dom.setStyle(node, name, '');
          }
          stylesModified = 1;
        });
        if (stylesModified && dom.getAttrib(node, 'style') === '') {
          node.removeAttribute('style');
          node.removeAttribute('data-mce-style');
        }
        each$d(format.attributes, function (value, name) {
          var valueOut;
          value = FormatUtils.replaceVars(value, vars);
          if (typeof name === 'number') {
            name = value;
            compareNode = 0;
          }
          if (!compareNode || isEq$5(dom.getAttrib(compareNode, name), value)) {
            if (name === 'class') {
              value = dom.getAttrib(node, name);
              if (value) {
                valueOut = '';
                each$d(value.split(/\s+/), function (cls) {
                  if (/mce\-\w+/.test(cls)) {
                    valueOut += (valueOut ? ' ' : '') + cls;
                  }
                });
                if (valueOut) {
                  dom.setAttrib(node, name, valueOut);
                  return;
                }
              }
            }
            if (name === 'class') {
              node.removeAttribute('className');
            }
            if (MCE_ATTR_RE.test(name)) {
              node.removeAttribute('data-mce-' + name);
            }
            node.removeAttribute(name);
          }
        });
        each$d(format.classes, function (value) {
          value = FormatUtils.replaceVars(value, vars);
          if (!compareNode || dom.hasClass(compareNode, value)) {
            dom.removeClass(node, value);
          }
        });
        attrs = dom.getAttribs(node);
        for (i = 0; i < attrs.length; i++) {
          var attrName = attrs[i].nodeName;
          if (attrName.indexOf('_') !== 0 && attrName.indexOf('data-') !== 0) {
            return false;
          }
        }
      }
      if (format.remove !== 'none') {
        removeNode$1(ed, node, format);
        return true;
      }
    };
    var findFormatRoot = function (editor, container, name, vars, similar) {
      var formatRoot;
      each$d(FormatUtils.getParents(editor.dom, container.parentNode).reverse(), function (parent) {
        var format;
        if (!formatRoot && parent.id !== '_start' && parent.id !== '_end') {
          format = MatchFormat.matchNode(editor, parent, name, vars, similar);
          if (format && format.split !== false) {
            formatRoot = parent;
          }
        }
      });
      return formatRoot;
    };
    var wrapAndSplit = function (editor, formatList, formatRoot, container, target, split, format, vars) {
      var parent, clone, lastClone, firstClone, i, formatRootParent;
      var dom = editor.dom;
      if (formatRoot) {
        formatRootParent = formatRoot.parentNode;
        for (parent = container.parentNode; parent && parent !== formatRootParent; parent = parent.parentNode) {
          clone = dom.clone(parent, false);
          for (i = 0; i < formatList.length; i++) {
            if (removeFormat(editor, formatList[i], vars, clone, clone)) {
              clone = 0;
              break;
            }
          }
          if (clone) {
            if (lastClone) {
              clone.appendChild(lastClone);
            }
            if (!firstClone) {
              firstClone = clone;
            }
            lastClone = clone;
          }
        }
        if (split && (!format.mixed || !dom.isBlock(formatRoot))) {
          container = dom.split(formatRoot, container);
        }
        if (lastClone) {
          target.parentNode.insertBefore(lastClone, target);
          firstClone.appendChild(target);
        }
      }
      return container;
    };
    var remove$6 = function (ed, name, vars, node, similar) {
      var formatList = ed.formatter.get(name), format = formatList[0];
      var bookmark, rng, contentEditable = true;
      var dom = ed.dom;
      var selection = ed.selection;
      var splitToFormatRoot = function (container) {
        var formatRoot = findFormatRoot(ed, container, name, vars, similar);
        return wrapAndSplit(ed, formatList, formatRoot, container, container, true, format, vars);
      };
      var isRemoveBookmarkNode = function (node) {
        return Bookmarks.isBookmarkNode(node) && NodeType.isElement(node) && (node.id === '_start' || node.id === '_end');
      };
      var process = function (node) {
        var children, i, l, lastContentEditable, hasContentEditableState;
        if (NodeType.isElement(node) && dom.getContentEditable(node)) {
          lastContentEditable = contentEditable;
          contentEditable = dom.getContentEditable(node) === 'true';
          hasContentEditableState = true;
        }
        children = Tools.grep(node.childNodes);
        if (contentEditable && !hasContentEditableState) {
          for (i = 0, l = formatList.length; i < l; i++) {
            if (removeFormat(ed, formatList[i], vars, node, node)) {
              break;
            }
          }
        }
        if (format.deep) {
          if (children.length) {
            for (i = 0, l = children.length; i < l; i++) {
              process(children[i]);
            }
            if (hasContentEditableState) {
              contentEditable = lastContentEditable;
            }
          }
        }
      };
      var unwrap = function (start) {
        var node = dom.get(start ? '_start' : '_end');
        var out = node[start ? 'firstChild' : 'lastChild'];
        if (isRemoveBookmarkNode(out)) {
          out = out[start ? 'firstChild' : 'lastChild'];
        }
        if (NodeType.isText(out) && out.data.length === 0) {
          out = start ? node.previousSibling || node.nextSibling : node.nextSibling || node.previousSibling;
        }
        dom.remove(node, true);
        return out;
      };
      var removeRngStyle = function (rng) {
        var startContainer, endContainer;
        var commonAncestorContainer = rng.commonAncestorContainer;
        rng = ExpandRange.expandRng(ed, rng, formatList, true);
        if (format.split) {
          rng = SplitRange.split(rng);
          startContainer = getContainer(ed, rng, true);
          endContainer = getContainer(ed, rng);
          if (startContainer !== endContainer) {
            if (/^(TR|TH|TD)$/.test(startContainer.nodeName) && startContainer.firstChild) {
              if (startContainer.nodeName === 'TR') {
                startContainer = startContainer.firstChild.firstChild || startContainer;
              } else {
                startContainer = startContainer.firstChild || startContainer;
              }
            }
            if (commonAncestorContainer && /^T(HEAD|BODY|FOOT|R)$/.test(commonAncestorContainer.nodeName) && isTableCell$4(endContainer) && endContainer.firstChild) {
              endContainer = endContainer.firstChild || endContainer;
            }
            if (isChildOfInlineParent(dom, startContainer, endContainer)) {
              var marker = Option.from(startContainer.firstChild).getOr(startContainer);
              splitToFormatRoot(wrapWithSiblings(dom, marker, true, 'span', {
                'id': '_start',
                'data-mce-type': 'bookmark'
              }));
              unwrap(true);
              return;
            }
            if (isChildOfInlineParent(dom, endContainer, startContainer)) {
              var marker = Option.from(endContainer.lastChild).getOr(endContainer);
              splitToFormatRoot(wrapWithSiblings(dom, marker, false, 'span', {
                'id': '_end',
                'data-mce-type': 'bookmark'
              }));
              unwrap(false);
              return;
            }
            startContainer = wrap$2(dom, startContainer, 'span', {
              'id': '_start',
              'data-mce-type': 'bookmark'
            });
            endContainer = wrap$2(dom, endContainer, 'span', {
              'id': '_end',
              'data-mce-type': 'bookmark'
            });
            splitToFormatRoot(startContainer);
            splitToFormatRoot(endContainer);
            startContainer = unwrap(true);
            endContainer = unwrap();
          } else {
            startContainer = endContainer = splitToFormatRoot(startContainer);
          }
          rng.startContainer = startContainer.parentNode ? startContainer.parentNode : startContainer;
          rng.startOffset = dom.nodeIndex(startContainer);
          rng.endContainer = endContainer.parentNode ? endContainer.parentNode : endContainer;
          rng.endOffset = dom.nodeIndex(endContainer) + 1;
        }
        RangeWalk.walk(dom, rng, function (nodes) {
          each$d(nodes, function (node) {
            process(node);
            if (NodeType.isElement(node) && ed.dom.getStyle(node, 'text-decoration') === 'underline' && node.parentNode && FormatUtils.getTextDecoration(dom, node.parentNode) === 'underline') {
              removeFormat(ed, {
                deep: false,
                exact: true,
                inline: 'span',
                styles: { textDecoration: 'underline' }
              }, null, node);
            }
          });
        });
      };
      if (node) {
        if (node.nodeType) {
          rng = dom.createRng();
          rng.setStartBefore(node);
          rng.setEndAfter(node);
          removeRngStyle(rng);
        } else {
          removeRngStyle(node);
        }
        return;
      }
      if (dom.getContentEditable(selection.getNode()) === 'false') {
        node = selection.getNode();
        for (var i = 0, l = formatList.length; i < l; i++) {
          if (formatList[i].ceFalseOverride) {
            if (removeFormat(ed, formatList[i], vars, node, node)) {
              break;
            }
          }
        }
        return;
      }
      if (!selection.isCollapsed() || !format.inline || dom.select('td[data-mce-selected],th[data-mce-selected]').length) {
        bookmark = GetBookmark.getPersistentBookmark(ed.selection, true);
        removeRngStyle(selection.getRng());
        selection.moveToBookmark(bookmark);
        if (format.inline && MatchFormat.match(ed, name, vars, selection.getStart())) {
          FormatUtils.moveStart(dom, selection, selection.getRng());
        }
        ed.nodeChanged();
      } else {
        removeCaretFormat(ed, name, vars, similar);
      }
    };
    var RemoveFormat = {
      removeFormat: removeFormat,
      remove: remove$6
    };

    var each$e = Tools.each;
    var isElementNode = function (node) {
      return node && node.nodeType === 1 && !Bookmarks.isBookmarkNode(node) && !isCaretNode(node) && !NodeType.isBogus(node);
    };
    var findElementSibling = function (node, siblingName) {
      var sibling;
      for (sibling = node; sibling; sibling = sibling[siblingName]) {
        if (sibling.nodeType === 3 && sibling.nodeValue.length !== 0) {
          return node;
        }
        if (sibling.nodeType === 1 && !Bookmarks.isBookmarkNode(sibling)) {
          return sibling;
        }
      }
      return node;
    };
    var mergeSiblingsNodes = function (dom, prev, next) {
      var sibling, tmpSibling;
      var elementUtils = new ElementUtils(dom);
      if (prev && next) {
        prev = findElementSibling(prev, 'previousSibling');
        next = findElementSibling(next, 'nextSibling');
        if (elementUtils.compare(prev, next)) {
          for (sibling = prev.nextSibling; sibling && sibling !== next;) {
            tmpSibling = sibling;
            sibling = sibling.nextSibling;
            prev.appendChild(tmpSibling);
          }
          dom.remove(next);
          Tools.each(Tools.grep(next.childNodes), function (node) {
            prev.appendChild(node);
          });
          return prev;
        }
      }
      return next;
    };
    var processChildElements = function (node, filter, process) {
      each$e(node.childNodes, function (node) {
        if (isElementNode(node)) {
          if (filter(node)) {
            process(node);
          }
          if (node.hasChildNodes()) {
            processChildElements(node, filter, process);
          }
        }
      });
    };
    var hasStyle = function (dom, name) {
      return curry(function (name, node) {
        return !!(node && FormatUtils.getStyle(dom, node, name));
      }, name);
    };
    var applyStyle = function (dom, name, value) {
      return curry(function (name, value, node) {
        dom.setStyle(node, name, value);
        if (node.getAttribute('style') === '') {
          node.removeAttribute('style');
        }
        unwrapEmptySpan(dom, node);
      }, name, value);
    };
    var unwrapEmptySpan = function (dom, node) {
      if (node.nodeName === 'SPAN' && dom.getAttribs(node).length === 0) {
        dom.remove(node, true);
      }
    };
    var processUnderlineAndColor = function (dom, node) {
      var textDecoration;
      if (node.nodeType === 1 && node.parentNode && node.parentNode.nodeType === 1) {
        textDecoration = FormatUtils.getTextDecoration(dom, node.parentNode);
        if (dom.getStyle(node, 'color') && textDecoration) {
          dom.setStyle(node, 'text-decoration', textDecoration);
        } else if (dom.getStyle(node, 'text-decoration') === textDecoration) {
          dom.setStyle(node, 'text-decoration', null);
        }
      }
    };
    var mergeUnderlineAndColor = function (dom, format, vars, node) {
      if (format.styles.color || format.styles.textDecoration) {
        Tools.walk(node, curry(processUnderlineAndColor, dom), 'childNodes');
        processUnderlineAndColor(dom, node);
      }
    };
    var mergeBackgroundColorAndFontSize = function (dom, format, vars, node) {
      if (format.styles && format.styles.backgroundColor) {
        processChildElements(node, hasStyle(dom, 'fontSize'), applyStyle(dom, 'backgroundColor', FormatUtils.replaceVars(format.styles.backgroundColor, vars)));
      }
    };
    var mergeSubSup = function (dom, format, vars, node) {
      if (format.inline === 'sub' || format.inline === 'sup') {
        processChildElements(node, hasStyle(dom, 'fontSize'), applyStyle(dom, 'fontSize', ''));
        dom.remove(dom.select(format.inline === 'sup' ? 'sub' : 'sup', node), true);
      }
    };
    var mergeSiblings = function (dom, format, vars, node) {
      if (node && format.merge_siblings !== false) {
        node = mergeSiblingsNodes(dom, FormatUtils.getNonWhiteSpaceSibling(node), node);
        node = mergeSiblingsNodes(dom, node, FormatUtils.getNonWhiteSpaceSibling(node, true));
      }
    };
    var clearChildStyles = function (dom, format, node) {
      if (format.clear_child_styles) {
        var selector = format.links ? '*:not(a)' : '*';
        each$e(dom.select(selector, node), function (node) {
          if (isElementNode(node)) {
            each$e(format.styles, function (value, name) {
              dom.setStyle(node, name, '');
            });
          }
        });
      }
    };
    var mergeWithChildren = function (editor, formatList, vars, node) {
      each$e(formatList, function (format) {
        each$e(editor.dom.select(format.inline, node), function (child) {
          if (!isElementNode(child)) {
            return;
          }
          RemoveFormat.removeFormat(editor, format, vars, child, format.exact ? child : null);
        });
        clearChildStyles(editor.dom, format, node);
      });
    };
    var mergeWithParents = function (editor, format, name, vars, node) {
      if (MatchFormat.matchNode(editor, node.parentNode, name, vars)) {
        if (RemoveFormat.removeFormat(editor, format, vars, node)) {
          return;
        }
      }
      if (format.merge_with_parents) {
        editor.dom.getParent(node.parentNode, function (parent) {
          if (MatchFormat.matchNode(editor, parent, name, vars)) {
            RemoveFormat.removeFormat(editor, format, vars, node);
            return true;
          }
        });
      }
    };
    var MergeFormats = {
      mergeWithChildren: mergeWithChildren,
      mergeUnderlineAndColor: mergeUnderlineAndColor,
      mergeBackgroundColorAndFontSize: mergeBackgroundColorAndFontSize,
      mergeSubSup: mergeSubSup,
      mergeSiblings: mergeSiblings,
      mergeWithParents: mergeWithParents
    };

    var each$f = Tools.each;
    var isElementNode$1 = function (node) {
      return node && node.nodeType === 1 && !Bookmarks.isBookmarkNode(node) && !isCaretNode(node) && !NodeType.isBogus(node);
    };
    var applyFormat = function (ed, name, vars, node) {
      var formatList = ed.formatter.get(name);
      var format = formatList[0];
      var bookmark, rng;
      var isCollapsed = !node && ed.selection.isCollapsed();
      var dom = ed.dom, selection = ed.selection;
      var setElementFormat = function (elm, fmt) {
        fmt = fmt || format;
        if (elm) {
          if (fmt.onformat) {
            fmt.onformat(elm, fmt, vars, node);
          }
          each$f(fmt.styles, function (value, name) {
            dom.setStyle(elm, name, FormatUtils.replaceVars(value, vars));
          });
          if (fmt.styles) {
            var styleVal = dom.getAttrib(elm, 'style');
            if (styleVal) {
              elm.setAttribute('data-mce-style', styleVal);
            }
          }
          each$f(fmt.attributes, function (value, name) {
            dom.setAttrib(elm, name, FormatUtils.replaceVars(value, vars));
          });
          each$f(fmt.classes, function (value) {
            value = FormatUtils.replaceVars(value, vars);
            if (!dom.hasClass(elm, value)) {
              dom.addClass(elm, value);
            }
          });
        }
      };
      var applyNodeStyle = function (formatList, node) {
        var found = false;
        if (!format.selector) {
          return false;
        }
        each$f(formatList, function (format) {
          if ('collapsed' in format && format.collapsed !== isCollapsed) {
            return;
          }
          if (dom.is(node, format.selector) && !isCaretNode(node)) {
            setElementFormat(node, format);
            found = true;
            return false;
          }
        });
        return found;
      };
      var applyRngStyle = function (dom, rng, bookmark, nodeSpecific) {
        var newWrappers = [];
        var wrapName, wrapElm, contentEditable = true;
        wrapName = format.inline || format.block;
        wrapElm = dom.create(wrapName);
        setElementFormat(wrapElm);
        RangeWalk.walk(dom, rng, function (nodes) {
          var currentWrapElm;
          var process = function (node) {
            var nodeName, parentName, hasContentEditableState, lastContentEditable;
            lastContentEditable = contentEditable;
            nodeName = node.nodeName.toLowerCase();
            parentName = node.parentNode.nodeName.toLowerCase();
            if (node.nodeType === 1 && dom.getContentEditable(node)) {
              lastContentEditable = contentEditable;
              contentEditable = dom.getContentEditable(node) === 'true';
              hasContentEditableState = true;
            }
            if (FormatUtils.isEq(nodeName, 'br')) {
              currentWrapElm = 0;
              if (format.block) {
                dom.remove(node);
              }
              return;
            }
            if (format.wrapper && MatchFormat.matchNode(ed, node, name, vars)) {
              currentWrapElm = 0;
              return;
            }
            if (contentEditable && !hasContentEditableState && format.block && !format.wrapper && FormatUtils.isTextBlock(ed, nodeName) && FormatUtils.isValid(ed, parentName, wrapName)) {
              node = dom.rename(node, wrapName);
              setElementFormat(node);
              newWrappers.push(node);
              currentWrapElm = 0;
              return;
            }
            if (format.selector) {
              var found = applyNodeStyle(formatList, node);
              if (!format.inline || found) {
                currentWrapElm = 0;
                return;
              }
            }
            if (contentEditable && !hasContentEditableState && FormatUtils.isValid(ed, wrapName, nodeName) && FormatUtils.isValid(ed, parentName, wrapName) && !(!nodeSpecific && node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279) && !isCaretNode(node) && (!format.inline || !dom.isBlock(node))) {
              if (!currentWrapElm) {
                currentWrapElm = dom.clone(wrapElm, false);
                node.parentNode.insertBefore(currentWrapElm, node);
                newWrappers.push(currentWrapElm);
              }
              currentWrapElm.appendChild(node);
            } else {
              currentWrapElm = 0;
              each$f(Tools.grep(node.childNodes), process);
              if (hasContentEditableState) {
                contentEditable = lastContentEditable;
              }
              currentWrapElm = 0;
            }
          };
          each$f(nodes, process);
        });
        if (format.links === true) {
          each$f(newWrappers, function (node) {
            var process = function (node) {
              if (node.nodeName === 'A') {
                setElementFormat(node, format);
              }
              each$f(Tools.grep(node.childNodes), process);
            };
            process(node);
          });
        }
        each$f(newWrappers, function (node) {
          var childCount;
          var getChildCount = function (node) {
            var count = 0;
            each$f(node.childNodes, function (node) {
              if (!FormatUtils.isWhiteSpaceNode(node) && !Bookmarks.isBookmarkNode(node)) {
                count++;
              }
            });
            return count;
          };
          var getChildElementNode = function (root) {
            var child = false;
            each$f(root.childNodes, function (node) {
              if (isElementNode$1(node)) {
                child = node;
                return false;
              }
            });
            return child;
          };
          var mergeStyles = function (node) {
            var child, clone;
            child = getChildElementNode(node);
            if (child && !Bookmarks.isBookmarkNode(child) && MatchFormat.matchName(dom, child, format)) {
              clone = dom.clone(child, false);
              setElementFormat(clone);
              dom.replace(clone, node, true);
              dom.remove(child, 1);
            }
            return clone || node;
          };
          childCount = getChildCount(node);
          if ((newWrappers.length > 1 || !dom.isBlock(node)) && childCount === 0) {
            dom.remove(node, 1);
            return;
          }
          if (format.inline || format.wrapper) {
            if (!format.exact && childCount === 1) {
              node = mergeStyles(node);
            }
            MergeFormats.mergeWithChildren(ed, formatList, vars, node);
            MergeFormats.mergeWithParents(ed, format, name, vars, node);
            MergeFormats.mergeBackgroundColorAndFontSize(dom, format, vars, node);
            MergeFormats.mergeSubSup(dom, format, vars, node);
            MergeFormats.mergeSiblings(dom, format, vars, node);
          }
        });
      };
      if (dom.getContentEditable(selection.getNode()) === 'false') {
        node = selection.getNode();
        for (var i = 0, l = formatList.length; i < l; i++) {
          if (formatList[i].ceFalseOverride && dom.is(node, formatList[i].selector)) {
            setElementFormat(node, formatList[i]);
            return;
          }
        }
        return;
      }
      if (format) {
        if (node) {
          if (node.nodeType) {
            if (!applyNodeStyle(formatList, node)) {
              rng = dom.createRng();
              rng.setStartBefore(node);
              rng.setEndAfter(node);
              applyRngStyle(dom, ExpandRange.expandRng(ed, rng, formatList), null, true);
            }
          } else {
            applyRngStyle(dom, node, null, true);
          }
        } else {
          if (!isCollapsed || !format.inline || dom.select('td[data-mce-selected],th[data-mce-selected]').length) {
            var curSelNode = ed.selection.getNode();
            if (!ed.settings.forced_root_block && formatList[0].defaultBlock && !dom.getParent(curSelNode, dom.isBlock)) {
              applyFormat(ed, formatList[0].defaultBlock);
            }
            ed.selection.setRng(RangeNormalizer.normalize(ed.selection.getRng()));
            bookmark = GetBookmark.getPersistentBookmark(ed.selection, true);
            applyRngStyle(dom, ExpandRange.expandRng(ed, selection.getRng(), formatList));
            if (format.styles) {
              MergeFormats.mergeUnderlineAndColor(dom, format, vars, curSelNode);
            }
            selection.moveToBookmark(bookmark);
            FormatUtils.moveStart(dom, selection, selection.getRng());
            ed.nodeChanged();
          } else {
            applyCaretFormat(ed, name, vars);
          }
        }
        Hooks.postProcess(name, ed);
      }
    };
    var ApplyFormat = { applyFormat: applyFormat };

    var each$g = Tools.each;
    var setup$5 = function (formatChangeData, editor) {
      var currentFormats = {};
      formatChangeData.set({});
      editor.on('NodeChange', function (e) {
        var parents = FormatUtils.getParents(editor.dom, e.element);
        var matchedFormats = {};
        parents = Tools.grep(parents, function (node) {
          return node.nodeType === 1 && !node.getAttribute('data-mce-bogus');
        });
        each$g(formatChangeData.get(), function (callbacks, format) {
          each$g(parents, function (node) {
            if (editor.formatter.matchNode(node, format, {}, callbacks.similar)) {
              if (!currentFormats[format]) {
                each$g(callbacks, function (callback) {
                  callback(true, {
                    node: node,
                    format: format,
                    parents: parents
                  });
                });
                currentFormats[format] = callbacks;
              }
              matchedFormats[format] = callbacks;
              return false;
            }
            if (MatchFormat.matchesUnInheritedFormatSelector(editor, node, format)) {
              return false;
            }
          });
        });
        each$g(currentFormats, function (callbacks, format) {
          if (!matchedFormats[format]) {
            delete currentFormats[format];
            each$g(callbacks, function (callback) {
              callback(false, {
                node: e.element,
                format: format,
                parents: parents
              });
            });
          }
        });
      });
    };
    var addListeners = function (formatChangeData, formats, callback, similar) {
      var formatChangeItems = formatChangeData.get();
      each$g(formats.split(','), function (format) {
        if (!formatChangeItems[format]) {
          formatChangeItems[format] = [];
          formatChangeItems[format].similar = similar;
        }
        formatChangeItems[format].push(callback);
      });
      formatChangeData.set(formatChangeItems);
    };
    var formatChanged = function (editor, formatChangeState, formats, callback, similar) {
      if (formatChangeState.get() === null) {
        setup$5(formatChangeState, editor);
      }
      addListeners(formatChangeState, formats, callback, similar);
    };
    var FormatChanged = { formatChanged: formatChanged };

    var get$5 = function (dom) {
      var formats = {
        valigntop: [{
            selector: 'td,th',
            styles: { verticalAlign: 'top' }
          }],
        valignmiddle: [{
            selector: 'td,th',
            styles: { verticalAlign: 'middle' }
          }],
        valignbottom: [{
            selector: 'td,th',
            styles: { verticalAlign: 'bottom' }
          }],
        alignleft: [
          {
            selector: 'figure.image',
            collapsed: false,
            classes: 'align-left',
            ceFalseOverride: true,
            preview: 'font-family font-size'
          },
          {
            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
            styles: { textAlign: 'left' },
            inherit: false,
            preview: false,
            defaultBlock: 'div'
          },
          {
            selector: 'img,table',
            collapsed: false,
            styles: { float: 'left' },
            preview: 'font-family font-size'
          }
        ],
        aligncenter: [
          {
            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
            styles: { textAlign: 'center' },
            inherit: false,
            preview: 'font-family font-size',
            defaultBlock: 'div'
          },
          {
            selector: 'figure.image',
            collapsed: false,
            classes: 'align-center',
            ceFalseOverride: true,
            preview: 'font-family font-size'
          },
          {
            selector: 'img',
            collapsed: false,
            styles: {
              display: 'block',
              marginLeft: 'auto',
              marginRight: 'auto'
            },
            preview: false
          },
          {
            selector: 'table',
            collapsed: false,
            styles: {
              marginLeft: 'auto',
              marginRight: 'auto'
            },
            preview: 'font-family font-size'
          }
        ],
        alignright: [
          {
            selector: 'figure.image',
            collapsed: false,
            classes: 'align-right',
            ceFalseOverride: true,
            preview: 'font-family font-size'
          },
          {
            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
            styles: { textAlign: 'right' },
            inherit: false,
            preview: 'font-family font-size',
            defaultBlock: 'div'
          },
          {
            selector: 'img,table',
            collapsed: false,
            styles: { float: 'right' },
            preview: 'font-family font-size'
          }
        ],
        alignjustify: [{
            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
            styles: { textAlign: 'justify' },
            inherit: false,
            defaultBlock: 'div',
            preview: 'font-family font-size'
          }],
        bold: [
          {
            inline: 'strong',
            remove: 'all'
          },
          {
            inline: 'span',
            styles: { fontWeight: 'bold' }
          },
          {
            inline: 'b',
            remove: 'all'
          }
        ],
        italic: [
          {
            inline: 'em',
            remove: 'all'
          },
          {
            inline: 'span',
            styles: { fontStyle: 'italic' }
          },
          {
            inline: 'i',
            remove: 'all'
          }
        ],
        underline: [
          {
            inline: 'span',
            styles: { textDecoration: 'underline' },
            exact: true
          },
          {
            inline: 'u',
            remove: 'all'
          }
        ],
        strikethrough: [
          {
            inline: 'span',
            styles: { textDecoration: 'line-through' },
            exact: true
          },
          {
            inline: 'strike',
            remove: 'all'
          }
        ],
        forecolor: {
          inline: 'span',
          styles: { color: '%value' },
          links: true,
          remove_similar: true,
          clear_child_styles: true
        },
        hilitecolor: {
          inline: 'span',
          styles: { backgroundColor: '%value' },
          links: true,
          remove_similar: true,
          clear_child_styles: true
        },
        fontname: {
          inline: 'span',
          toggle: false,
          styles: { fontFamily: '%value' },
          clear_child_styles: true
        },
        fontsize: {
          inline: 'span',
          toggle: false,
          styles: { fontSize: '%value' },
          clear_child_styles: true
        },
        fontsize_class: {
          inline: 'span',
          attributes: { class: '%value' }
        },
        blockquote: {
          block: 'blockquote',
          wrapper: 1,
          remove: 'all'
        },
        subscript: { inline: 'sub' },
        superscript: { inline: 'sup' },
        code: { inline: 'code' },
        link: {
          inline: 'a',
          selector: 'a',
          remove: 'all',
          split: true,
          deep: true,
          onmatch: function () {
            return true;
          },
          onformat: function (elm, fmt, vars) {
            Tools.each(vars, function (value, key) {
              dom.setAttrib(elm, key, value);
            });
          }
        },
        removeformat: [
          {
            selector: 'b,strong,em,i,font,u,strike,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins',
            remove: 'all',
            split: true,
            expand: false,
            block_expand: true,
            deep: true
          },
          {
            selector: 'span',
            attributes: [
              'style',
              'class'
            ],
            remove: 'empty',
            split: true,
            expand: false,
            deep: true
          },
          {
            selector: '*',
            attributes: [
              'style',
              'class'
            ],
            split: false,
            expand: false,
            deep: true
          }
        ]
      };
      Tools.each('p h1 h2 h3 h4 h5 h6 div address pre div dt dd samp'.split(/\s/), function (name) {
        formats[name] = {
          block: name,
          remove: 'all'
        };
      });
      return formats;
    };
    var DefaultFormats = { get: get$5 };

    function FormatRegistry (editor) {
      var formats = {};
      var get = function (name) {
        return name ? formats[name] : formats;
      };
      var register = function (name, format) {
        if (name) {
          if (typeof name !== 'string') {
            Tools.each(name, function (format, name) {
              register(name, format);
            });
          } else {
            format = format.length ? format : [format];
            Tools.each(format, function (format) {
              if (typeof format.deep === 'undefined') {
                format.deep = !format.selector;
              }
              if (typeof format.split === 'undefined') {
                format.split = !format.selector || format.inline;
              }
              if (typeof format.remove === 'undefined' && format.selector && !format.inline) {
                format.remove = 'none';
              }
              if (format.selector && format.inline) {
                format.mixed = true;
                format.block_expand = true;
              }
              if (typeof format.classes === 'string') {
                format.classes = format.classes.split(/\s+/);
              }
            });
            formats[name] = format;
          }
        }
      };
      var unregister = function (name) {
        if (name && formats[name]) {
          delete formats[name];
        }
        return formats;
      };
      register(DefaultFormats.get(editor.dom));
      register(editor.settings.formats);
      return {
        get: get,
        register: register,
        unregister: unregister
      };
    }

    var each$h = Tools.each;
    var dom = DOMUtils$1.DOM;
    var parsedSelectorToHtml = function (ancestry, editor) {
      var elm, item, fragment;
      var schema = editor && editor.schema || Schema({});
      var decorate = function (elm, item) {
        if (item.classes.length) {
          dom.addClass(elm, item.classes.join(' '));
        }
        dom.setAttribs(elm, item.attrs);
      };
      var createElement = function (sItem) {
        var elm;
        item = typeof sItem === 'string' ? {
          name: sItem,
          classes: [],
          attrs: {}
        } : sItem;
        elm = dom.create(item.name);
        decorate(elm, item);
        return elm;
      };
      var getRequiredParent = function (elm, candidate) {
        var name = typeof elm !== 'string' ? elm.nodeName.toLowerCase() : elm;
        var elmRule = schema.getElementRule(name);
        var parentsRequired = elmRule && elmRule.parentsRequired;
        if (parentsRequired && parentsRequired.length) {
          return candidate && Tools.inArray(parentsRequired, candidate) !== -1 ? candidate : parentsRequired[0];
        } else {
          return false;
        }
      };
      var wrapInHtml = function (elm, ancestry, siblings) {
        var parent, parentCandidate, parentRequired;
        var ancestor = ancestry.length > 0 && ancestry[0];
        var ancestorName = ancestor && ancestor.name;
        parentRequired = getRequiredParent(elm, ancestorName);
        if (parentRequired) {
          if (ancestorName === parentRequired) {
            parentCandidate = ancestry[0];
            ancestry = ancestry.slice(1);
          } else {
            parentCandidate = parentRequired;
          }
        } else if (ancestor) {
          parentCandidate = ancestry[0];
          ancestry = ancestry.slice(1);
        } else if (!siblings) {
          return elm;
        }
        if (parentCandidate) {
          parent = createElement(parentCandidate);
          parent.appendChild(elm);
        }
        if (siblings) {
          if (!parent) {
            parent = dom.create('div');
            parent.appendChild(elm);
          }
          Tools.each(siblings, function (sibling) {
            var siblingElm = createElement(sibling);
            parent.insertBefore(siblingElm, elm);
          });
        }
        return wrapInHtml(parent, ancestry, parentCandidate && parentCandidate.siblings);
      };
      if (ancestry && ancestry.length) {
        item = ancestry[0];
        elm = createElement(item);
        fragment = dom.create('div');
        fragment.appendChild(wrapInHtml(elm, ancestry.slice(1), item.siblings));
        return fragment;
      } else {
        return '';
      }
    };
    var selectorToHtml = function (selector, editor) {
      return parsedSelectorToHtml(parseSelector(selector), editor);
    };
    var parseSelectorItem = function (item) {
      var tagName;
      var obj = {
        classes: [],
        attrs: {}
      };
      item = obj.selector = Tools.trim(item);
      if (item !== '*') {
        tagName = item.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g, function ($0, $1, $2, $3, $4) {
          switch ($1) {
          case '#':
            obj.attrs.id = $2;
            break;
          case '.':
            obj.classes.push($2);
            break;
          case ':':
            if (Tools.inArray('checked disabled enabled read-only required'.split(' '), $2) !== -1) {
              obj.attrs[$2] = $2;
            }
            break;
          }
          if ($3 === '[') {
            var m = $4.match(/([\w\-]+)(?:\=\"([^\"]+))?/);
            if (m) {
              obj.attrs[m[1]] = m[2];
            }
          }
          return '';
        });
      }
      obj.name = tagName || 'div';
      return obj;
    };
    var parseSelector = function (selector) {
      if (!selector || typeof selector !== 'string') {
        return [];
      }
      selector = selector.split(/\s*,\s*/)[0];
      selector = selector.replace(/\s*(~\+|~|\+|>)\s*/g, '$1');
      return Tools.map(selector.split(/(?:>|\s+(?![^\[\]]+\]))/), function (item) {
        var siblings = Tools.map(item.split(/(?:~\+|~|\+)/), parseSelectorItem);
        var obj = siblings.pop();
        if (siblings.length) {
          obj.siblings = siblings;
        }
        return obj;
      }).reverse();
    };
    var getCssText = function (editor, format) {
      var name, previewFrag, previewElm, items;
      var previewCss = '', parentFontSize, previewStyles;
      previewStyles = editor.settings.preview_styles;
      if (previewStyles === false) {
        return '';
      }
      if (typeof previewStyles !== 'string') {
        previewStyles = 'font-family font-size font-weight font-style text-decoration ' + 'text-transform color background-color border border-radius outline text-shadow';
      }
      var removeVars = function (val) {
        return val.replace(/%(\w+)/g, '');
      };
      if (typeof format === 'string') {
        format = editor.formatter.get(format);
        if (!format) {
          return;
        }
        format = format[0];
      }
      if ('preview' in format) {
        previewStyles = format.preview;
        if (previewStyles === false) {
          return '';
        }
      }
      name = format.block || format.inline || 'span';
      items = parseSelector(format.selector);
      if (items.length) {
        if (!items[0].name) {
          items[0].name = name;
        }
        name = format.selector;
        previewFrag = parsedSelectorToHtml(items, editor);
      } else {
        previewFrag = parsedSelectorToHtml([name], editor);
      }
      previewElm = dom.select(name, previewFrag)[0] || previewFrag.firstChild;
      each$h(format.styles, function (value, name) {
        value = removeVars(value);
        if (value) {
          dom.setStyle(previewElm, name, value);
        }
      });
      each$h(format.attributes, function (value, name) {
        value = removeVars(value);
        if (value) {
          dom.setAttrib(previewElm, name, value);
        }
      });
      each$h(format.classes, function (value) {
        value = removeVars(value);
        if (!dom.hasClass(previewElm, value)) {
          dom.addClass(previewElm, value);
        }
      });
      editor.fire('PreviewFormats');
      dom.setStyles(previewFrag, {
        position: 'absolute',
        left: -65535
      });
      editor.getBody().appendChild(previewFrag);
      parentFontSize = dom.getStyle(editor.getBody(), 'fontSize', true);
      parentFontSize = /px$/.test(parentFontSize) ? parseInt(parentFontSize, 10) : 0;
      each$h(previewStyles.split(' '), function (name) {
        var value = dom.getStyle(previewElm, name, true);
        if (name === 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) {
          value = dom.getStyle(editor.getBody(), name, true);
          if (dom.toHex(value).toLowerCase() === '#ffffff') {
            return;
          }
        }
        if (name === 'color') {
          if (dom.toHex(value).toLowerCase() === '#000000') {
            return;
          }
        }
        if (name === 'font-size') {
          if (/em|%$/.test(value)) {
            if (parentFontSize === 0) {
              return;
            }
            var numValue = parseFloat(value) / (/%$/.test(value) ? 100 : 1);
            value = numValue * parentFontSize + 'px';
          }
        }
        if (name === 'border' && value) {
          previewCss += 'padding:0 2px;';
        }
        previewCss += name + ':' + value + ';';
      });
      editor.fire('AfterPreviewFormats');
      dom.remove(previewFrag);
      return previewCss;
    };
    var Preview = {
      getCssText: getCssText,
      parseSelector: parseSelector,
      selectorToHtml: selectorToHtml
    };

    var toggle = function (editor, formats, name, vars, node) {
      var fmt = formats.get(name);
      if (MatchFormat.match(editor, name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) {
        RemoveFormat.remove(editor, name, vars, node);
      } else {
        ApplyFormat.applyFormat(editor, name, vars, node);
      }
    };
    var ToggleFormat = { toggle: toggle };

    var setup$6 = function (editor) {
      editor.addShortcut('meta+b', '', 'Bold');
      editor.addShortcut('meta+i', '', 'Italic');
      editor.addShortcut('meta+u', '', 'Underline');
      for (var i = 1; i <= 6; i++) {
        editor.addShortcut('access+' + i, '', [
          'FormatBlock',
          false,
          'h' + i
        ]);
      }
      editor.addShortcut('access+7', '', [
        'FormatBlock',
        false,
        'p'
      ]);
      editor.addShortcut('access+8', '', [
        'FormatBlock',
        false,
        'div'
      ]);
      editor.addShortcut('access+9', '', [
        'FormatBlock',
        false,
        'address'
      ]);
    };
    var FormatShortcuts = { setup: setup$6 };

    function Formatter (editor) {
      var formats = FormatRegistry(editor);
      var formatChangeState = Cell(null);
      FormatShortcuts.setup(editor);
      setup$2(editor);
      return {
        get: formats.get,
        register: formats.register,
        unregister: formats.unregister,
        apply: curry(ApplyFormat.applyFormat, editor),
        remove: curry(RemoveFormat.remove, editor),
        toggle: curry(ToggleFormat.toggle, editor, formats),
        match: curry(MatchFormat.match, editor),
        matchAll: curry(MatchFormat.matchAll, editor),
        matchNode: curry(MatchFormat.matchNode, editor),
        canApply: curry(MatchFormat.canApply, editor),
        formatChanged: curry(FormatChanged.formatChanged, editor, formatChangeState),
        getCssText: curry(Preview.getCssText, editor)
      };
    }

    var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
    var shallow$1 = function (old, nu) {
      return nu;
    };
    var baseMerge = function (merger) {
      return function () {
        var objects = new Array(arguments.length);
        for (var i = 0; i < objects.length; i++) {
          objects[i] = arguments[i];
        }
        if (objects.length === 0) {
          throw new Error('Can\'t merge zero objects');
        }
        var ret = {};
        for (var j = 0; j < objects.length; j++) {
          var curObject = objects[j];
          for (var key in curObject) {
            if (hasOwnProperty$2.call(curObject, key)) {
              ret[key] = merger(ret[key], curObject[key]);
            }
          }
        }
        return ret;
      };
    };
    var merge = baseMerge(shallow$1);

    var register = function (htmlParser, settings, dom) {
      htmlParser.addAttributeFilter('data-mce-tabindex', function (nodes, name) {
        var i = nodes.length, node;
        while (i--) {
          node = nodes[i];
          node.attr('tabindex', node.attributes.map['data-mce-tabindex']);
          node.attr(name, null);
        }
      });
      htmlParser.addAttributeFilter('src,href,style', function (nodes, name) {
        var i = nodes.length, node, value;
        var internalName = 'data-mce-' + name;
        var urlConverter = settings.url_converter;
        var urlConverterScope = settings.url_converter_scope;
        while (i--) {
          node = nodes[i];
          value = node.attributes.map[internalName];
          if (value !== undefined) {
            node.attr(name, value.length > 0 ? value : null);
            node.attr(internalName, null);
          } else {
            value = node.attributes.map[name];
            if (name === 'style') {
              value = dom.serializeStyle(dom.parseStyle(value), node.name);
            } else if (urlConverter) {
              value = urlConverter.call(urlConverterScope, value, name, node.name);
            }
            node.attr(name, value.length > 0 ? value : null);
          }
        }
      });
      htmlParser.addAttributeFilter('class', function (nodes) {
        var i = nodes.length, node, value;
        while (i--) {
          node = nodes[i];
          value = node.attr('class');
          if (value) {
            value = node.attr('class').replace(/(?:^|\s)mce-item-\w+(?!\S)/g, '');
            node.attr('class', value.length > 0 ? value : null);
          }
        }
      });
      htmlParser.addAttributeFilter('data-mce-type', function (nodes, name, args) {
        var i = nodes.length, node;
        while (i--) {
          node = nodes[i];
          if (node.attributes.map['data-mce-type'] === 'bookmark' && !args.cleanup) {
            var hasChildren = Option.from(node.firstChild).exists(function (firstChild) {
              return !Zwsp.isZwsp(firstChild.value);
            });
            if (hasChildren) {
              node.unwrap();
            } else {
              node.remove();
            }
          }
        }
      });
      htmlParser.addNodeFilter('noscript', function (nodes) {
        var i = nodes.length, node;
        while (i--) {
          node = nodes[i].firstChild;
          if (node) {
            node.value = Entities.decode(node.value);
          }
        }
      });
      htmlParser.addNodeFilter('script,style', function (nodes, name) {
        var i = nodes.length, node, value, type;
        var trim = function (value) {
          return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n').replace(/^[\r\n]*|[\r\n]*$/g, '').replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi, '').replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, '');
        };
        while (i--) {
          node = nodes[i];
          value = node.firstChild ? node.firstChild.value : '';
          if (name === 'script') {
            type = node.attr('type');
            if (type) {
              node.attr('type', type === 'mce-no/type' ? null : type.replace(/^mce\-/, ''));
            }
            if (settings.element_format === 'xhtml' && value.length > 0) {
              node.firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>';
            }
          } else {
            if (settings.element_format === 'xhtml' && value.length > 0) {
              node.firstChild.value = '<!--\n' + trim(value) + '\n-->';
            }
          }
        }
      });
      htmlParser.addNodeFilter('#comment', function (nodes) {
        var i = nodes.length, node;
        while (i--) {
          node = nodes[i];
          if (node.value.indexOf('[CDATA[') === 0) {
            node.name = '#cdata';
            node.type = 4;
            node.value = node.value.replace(/^\[CDATA\[|\]\]$/g, '');
          } else if (node.value.indexOf('mce:protected ') === 0) {
            node.name = '#text';
            node.type = 3;
            node.raw = true;
            node.value = unescape(node.value).substr(14);
          }
        }
      });
      htmlParser.addNodeFilter('xml:namespace,input', function (nodes, name) {
        var i = nodes.length, node;
        while (i--) {
          node = nodes[i];
          if (node.type === 7) {
            node.remove();
          } else if (node.type === 1) {
            if (name === 'input' && !('type' in node.attributes.map)) {
              node.attr('type', 'text');
            }
          }
        }
      });
      htmlParser.addAttributeFilter('data-mce-type', function (nodes) {
        each(nodes, function (node) {
          if (node.attr('data-mce-type') === 'format-caret') {
            if (node.isEmpty(htmlParser.schema.getNonEmptyElements())) {
              node.remove();
            } else {
              node.unwrap();
            }
          }
        });
      });
      htmlParser.addAttributeFilter('data-mce-src,data-mce-href,data-mce-style,' + 'data-mce-selected,data-mce-expando,' + 'data-mce-type,data-mce-resize', function (nodes, name) {
        var i = nodes.length;
        while (i--) {
          nodes[i].attr(name, null);
        }
      });
    };
    var trimTrailingBr = function (rootNode) {
      var brNode1, brNode2;
      var isBr = function (node) {
        return node && node.name === 'br';
      };
      brNode1 = rootNode.lastChild;
      if (isBr(brNode1)) {
        brNode2 = brNode1.prev;
        if (isBr(brNode2)) {
          brNode1.remove();
          brNode2.remove();
        }
      }
    };
    var DomSerializerFilters = {
      register: register,
      trimTrailingBr: trimTrailingBr
    };

    var preProcess = function (editor, node, args) {
      var impl, doc, oldDoc;
      var dom = editor.dom;
      node = node.cloneNode(true);
      impl = domGlobals.document.implementation;
      if (impl.createHTMLDocument) {
        doc = impl.createHTMLDocument('');
        Tools.each(node.nodeName === 'BODY' ? node.childNodes : [node], function (node) {
          doc.body.appendChild(doc.importNode(node, true));
        });
        if (node.nodeName !== 'BODY') {
          node = doc.body.firstChild;
        } else {
          node = doc.body;
        }
        oldDoc = dom.doc;
        dom.doc = doc;
      }
      Events.firePreProcess(editor, merge(args, { node: node }));
      if (oldDoc) {
        dom.doc = oldDoc;
      }
      return node;
    };
    var shouldFireEvent = function (editor, args) {
      return editor && editor.hasEventListeners('PreProcess') && !args.no_events;
    };
    var process = function (editor, node, args) {
      return shouldFireEvent(editor, args) ? preProcess(editor, node, args) : node;
    };
    var DomSerializerPreProcess = { process: process };

    var removeAttrs = function (node, names) {
      each(names, function (name) {
        node.attr(name, null);
      });
    };
    var addFontToSpansFilter = function (domParser, styles, fontSizes) {
      domParser.addNodeFilter('font', function (nodes) {
        each(nodes, function (node) {
          var props = styles.parse(node.attr('style'));
          var color = node.attr('color');
          var face = node.attr('face');
          var size = node.attr('size');
          if (color) {
            props.color = color;
          }
          if (face) {
            props['font-family'] = face;
          }
          if (size) {
            props['font-size'] = fontSizes[parseInt(node.attr('size'), 10) - 1];
          }
          node.name = 'span';
          node.attr('style', styles.serialize(props));
          removeAttrs(node, [
            'color',
            'face',
            'size'
          ]);
        });
      });
    };
    var addStrikeToSpanFilter = function (domParser, styles) {
      domParser.addNodeFilter('strike', function (nodes) {
        each(nodes, function (node) {
          var props = styles.parse(node.attr('style'));
          props['text-decoration'] = 'line-through';
          node.name = 'span';
          node.attr('style', styles.serialize(props));
        });
      });
    };
    var addFilters = function (domParser, settings) {
      var styles = Styles();
      if (settings.convert_fonts_to_spans) {
        addFontToSpansFilter(domParser, styles, Tools.explode(settings.font_size_legacy_values));
      }
      addStrikeToSpanFilter(domParser, styles);
    };
    var register$1 = function (domParser, settings) {
      if (settings.inline_styles) {
        addFilters(domParser, settings);
      }
    };
    var LegacyFilter = { register: register$1 };

    var whiteSpaceRegExp$3 = /^[ \t\r\n]*$/;
    var typeLookup = {
      '#text': 3,
      '#comment': 8,
      '#cdata': 4,
      '#pi': 7,
      '#doctype': 10,
      '#document-fragment': 11
    };
    var walk$2 = function (node, root, prev) {
      var sibling;
      var parent;
      var startName = prev ? 'lastChild' : 'firstChild';
      var siblingName = prev ? 'prev' : 'next';
      if (node[startName]) {
        return node[startName];
      }
      if (node !== root) {
        sibling = node[siblingName];
        if (sibling) {
          return sibling;
        }
        for (parent = node.parent; parent && parent !== root; parent = parent.parent) {
          sibling = parent[siblingName];
          if (sibling) {
            return sibling;
          }
        }
      }
    };
    var Node$1 = function () {
      function Node(name, type) {
        this.name = name;
        this.type = type;
        if (type === 1) {
          this.attributes = [];
          this.attributes.map = {};
        }
      }
      Node.create = function (name, attrs) {
        var node, attrName;
        node = new Node(name, typeLookup[name] || 1);
        if (attrs) {
          for (attrName in attrs) {
            node.attr(attrName, attrs[attrName]);
          }
        }
        return node;
      };
      Node.prototype.replace = function (node) {
        var self = this;
        if (node.parent) {
          node.remove();
        }
        self.insert(node, self);
        self.remove();
        return self;
      };
      Node.prototype.attr = function (name, value) {
        var self = this;
        var attrs, i;
        if (typeof name !== 'string') {
          for (i in name) {
            self.attr(i, name[i]);
          }
          return self;
        }
        if (attrs = self.attributes) {
          if (value !== undefined) {
            if (value === null) {
              if (name in attrs.map) {
                delete attrs.map[name];
                i = attrs.length;
                while (i--) {
                  if (attrs[i].name === name) {
                    attrs = attrs.splice(i, 1);
                    return self;
                  }
                }
              }
              return self;
            }
            if (name in attrs.map) {
              i = attrs.length;
              while (i--) {
                if (attrs[i].name === name) {
                  attrs[i].value = value;
                  break;
                }
              }
            } else {
              attrs.push({
                name: name,
                value: value
              });
            }
            attrs.map[name] = value;
            return self;
          }
          return attrs.map[name];
        }
      };
      Node.prototype.clone = function () {
        var self = this;
        var clone = new Node(self.name, self.type);
        var i, l, selfAttrs, selfAttr, cloneAttrs;
        if (selfAttrs = self.attributes) {
          cloneAttrs = [];
          cloneAttrs.map = {};
          for (i = 0, l = selfAttrs.length; i < l; i++) {
            selfAttr = selfAttrs[i];
            if (selfAttr.name !== 'id') {
              cloneAttrs[cloneAttrs.length] = {
                name: selfAttr.name,
                value: selfAttr.value
              };
              cloneAttrs.map[selfAttr.name] = selfAttr.value;
            }
          }
          clone.attributes = cloneAttrs;
        }
        clone.value = self.value;
        clone.shortEnded = self.shortEnded;
        return clone;
      };
      Node.prototype.wrap = function (wrapper) {
        var self = this;
        self.parent.insert(wrapper, self);
        wrapper.append(self);
        return self;
      };
      Node.prototype.unwrap = function () {
        var self = this;
        var node, next;
        for (node = self.firstChild; node;) {
          next = node.next;
          self.insert(node, self, true);
          node = next;
        }
        self.remove();
      };
      Node.prototype.remove = function () {
        var self = this, parent = self.parent, next = self.next, prev = self.prev;
        if (parent) {
          if (parent.firstChild === self) {
            parent.firstChild = next;
            if (next) {
              next.prev = null;
            }
          } else {
            prev.next = next;
          }
          if (parent.lastChild === self) {
            parent.lastChild = prev;
            if (prev) {
              prev.next = null;
            }
          } else {
            next.prev = prev;
          }
          self.parent = self.next = self.prev = null;
        }
        return self;
      };
      Node.prototype.append = function (node) {
        var self = this;
        var last;
        if (node.parent) {
          node.remove();
        }
        last = self.lastChild;
        if (last) {
          last.next = node;
          node.prev = last;
          self.lastChild = node;
        } else {
          self.lastChild = self.firstChild = node;
        }
        node.parent = self;
        return node;
      };
      Node.prototype.insert = function (node, refNode, before) {
        var parent;
        if (node.parent) {
          node.remove();
        }
        parent = refNode.parent || this;
        if (before) {
          if (refNode === parent.firstChild) {
            parent.firstChild = node;
          } else {
            refNode.prev.next = node;
          }
          node.prev = refNode.prev;
          node.next = refNode;
          refNode.prev = node;
        } else {
          if (refNode === parent.lastChild) {
            parent.lastChild = node;
          } else {
            refNode.next.prev = node;
          }
          node.next = refNode.next;
          node.prev = refNode;
          refNode.next = node;
        }
        node.parent = parent;
        return node;
      };
      Node.prototype.getAll = function (name) {
        var self = this;
        var node;
        var collection = [];
        for (node = self.firstChild; node; node = walk$2(node, self)) {
          if (node.name === name) {
            collection.push(node);
          }
        }
        return collection;
      };
      Node.prototype.empty = function () {
        var self = this;
        var nodes, i, node;
        if (self.firstChild) {
          nodes = [];
          for (node = self.firstChild; node; node = walk$2(node, self)) {
            nodes.push(node);
          }
          i = nodes.length;
          while (i--) {
            node = nodes[i];
            node.parent = node.firstChild = node.lastChild = node.next = node.prev = null;
          }
        }
        self.firstChild = self.lastChild = null;
        return self;
      };
      Node.prototype.isEmpty = function (elements, whitespace, predicate) {
        var self = this;
        var node = self.firstChild, i, name;
        whitespace = whitespace || {};
        if (node) {
          do {
            if (node.type === 1) {
              if (node.attributes.map['data-mce-bogus']) {
                continue;
              }
              if (elements[node.name]) {
                return false;
              }
              i = node.attributes.length;
              while (i--) {
                name = node.attributes[i].name;
                if (name === 'name' || name.indexOf('data-mce-bookmark') === 0) {
                  return false;
                }
              }
            }
            if (node.type === 8) {
              return false;
            }
            if (node.type === 3 && !whiteSpaceRegExp$3.test(node.value)) {
              return false;
            }
            if (node.type === 3 && node.parent && whitespace[node.parent.name] && whiteSpaceRegExp$3.test(node.value)) {
              return false;
            }
            if (predicate && predicate(node)) {
              return false;
            }
          } while (node = walk$2(node, self));
        }
        return true;
      };
      Node.prototype.walk = function (prev) {
        return walk$2(this, null, prev);
      };
      return Node;
    }();

    var paddEmptyNode = function (settings, args, blockElements, node) {
      var brPreferred = settings.padd_empty_with_br || args.insert;
      if (brPreferred && blockElements[node.name]) {
        node.empty().append(new Node$1('br', 1)).shortEnded = true;
      } else {
        node.empty().append(new Node$1('#text', 3)).value = '\xA0';
      }
    };
    var isPaddedWithNbsp = function (node) {
      return hasOnlyChild(node, '#text') && node.firstChild.value === '\xA0';
    };
    var hasOnlyChild = function (node, name) {
      return node && node.firstChild && node.firstChild === node.lastChild && node.firstChild.name === name;
    };
    var isPadded = function (schema, node) {
      var rule = schema.getElementRule(node.name);
      return rule && rule.paddEmpty;
    };
    var isEmpty$2 = function (schema, nonEmptyElements, whitespaceElements, node) {
      return node.isEmpty(nonEmptyElements, whitespaceElements, function (node) {
        return isPadded(schema, node);
      });
    };
    var isLineBreakNode = function (node, blockElements) {
      return node && (blockElements[node.name] || node.name === 'br');
    };

    var register$2 = function (parser, settings) {
      var schema = parser.schema;
      if (settings.remove_trailing_brs) {
        parser.addNodeFilter('br', function (nodes, _, args) {
          var i;
          var l = nodes.length;
          var node;
          var blockElements = Tools.extend({}, schema.getBlockElements());
          var nonEmptyElements = schema.getNonEmptyElements();
          var parent, lastParent, prev, prevName;
          var whiteSpaceElements = schema.getWhiteSpaceElements();
          var elementRule, textNode;
          blockElements.body = 1;
          for (i = 0; i < l; i++) {
            node = nodes[i];
            parent = node.parent;
            if (blockElements[node.parent.name] && node === parent.lastChild) {
              prev = node.prev;
              while (prev) {
                prevName = prev.name;
                if (prevName !== 'span' || prev.attr('data-mce-type') !== 'bookmark') {
                  if (prevName !== 'br') {
                    break;
                  }
                  if (prevName === 'br') {
                    node = null;
                    break;
                  }
                }
                prev = prev.prev;
              }
              if (node) {
                node.remove();
                if (isEmpty$2(schema, nonEmptyElements, whiteSpaceElements, parent)) {
                  elementRule = schema.getElementRule(parent.name);
                  if (elementRule) {
                    if (elementRule.removeEmpty) {
                      parent.remove();
                    } else if (elementRule.paddEmpty) {
                      paddEmptyNode(settings, args, blockElements, parent);
                    }
                  }
                }
              }
            } else {
              lastParent = node;
              while (parent && parent.firstChild === lastParent && parent.lastChild === lastParent) {
                lastParent = parent;
                if (blockElements[parent.name]) {
                  break;
                }
                parent = parent.parent;
              }
              if (lastParent === parent && settings.padd_empty_with_br !== true) {
                textNode = new Node$1('#text', 3);
                textNode.value = '\xA0';
                node.replace(textNode);
              }
            }
          }
        });
      }
      parser.addAttributeFilter('href', function (nodes) {
        var i = nodes.length, node;
        var appendRel = function (rel) {
          var parts = rel.split(' ').filter(function (p) {
            return p.length > 0;
          });
          return parts.concat(['noopener']).sort().join(' ');
        };
        var addNoOpener = function (rel) {
          var newRel = rel ? Tools.trim(rel) : '';
          if (!/\b(noopener)\b/g.test(newRel)) {
            return appendRel(newRel);
          } else {
            return newRel;
          }
        };
        if (!settings.allow_unsafe_link_target) {
          while (i--) {
            node = nodes[i];
            if (node.name === 'a' && node.attr('target') === '_blank') {
              node.attr('rel', addNoOpener(node.attr('rel')));
            }
          }
        }
      });
      if (!settings.allow_html_in_named_anchor) {
        parser.addAttributeFilter('id,name', function (nodes) {
          var i = nodes.length, sibling, prevSibling, parent, node;
          while (i--) {
            node = nodes[i];
            if (node.name === 'a' && node.firstChild && !node.attr('href')) {
              parent = node.parent;
              sibling = node.lastChild;
              do {
                prevSibling = sibling.prev;
                parent.insert(sibling, node);
                sibling = prevSibling;
              } while (sibling);
            }
          }
        });
      }
      if (settings.fix_list_elements) {
        parser.addNodeFilter('ul,ol', function (nodes) {
          var i = nodes.length, node, parentNode;
          while (i--) {
            node = nodes[i];
            parentNode = node.parent;
            if (parentNode.name === 'ul' || parentNode.name === 'ol') {
              if (node.prev && node.prev.name === 'li') {
                node.prev.append(node);
              } else {
                var li = new Node$1('li', 1);
                li.attr('style', 'list-style-type: none');
                node.wrap(li);
              }
            }
          }
        });
      }
      if (settings.validate && schema.getValidClasses()) {
        parser.addAttributeFilter('class', function (nodes) {
          var i = nodes.length, node, classList, ci, className, classValue;
          var validClasses = schema.getValidClasses();
          var validClassesMap, valid;
          while (i--) {
            node = nodes[i];
            classList = node.attr('class').split(' ');
            classValue = '';
            for (ci = 0; ci < classList.length; ci++) {
              className = classList[ci];
              valid = false;
              validClassesMap = validClasses['*'];
              if (validClassesMap && validClassesMap[className]) {
                valid = true;
              }
              validClassesMap = validClasses[node.name];
              if (!valid && validClassesMap && validClassesMap[className]) {
                valid = true;
              }
              if (valid) {
                if (classValue) {
                  classValue += ' ';
                }
                classValue += className;
              }
            }
            if (!classValue.length) {
              classValue = null;
            }
            node.attr('class', classValue);
          }
        });
      }
    };

    var makeMap$4 = Tools.makeMap, each$i = Tools.each, explode$3 = Tools.explode, extend$3 = Tools.extend;
    function DomParser (settings, schema) {
      if (schema === void 0) {
        schema = Schema();
      }
      var nodeFilters = {};
      var attributeFilters = [];
      var matchedNodes = {};
      var matchedAttributes = {};
      settings = settings || {};
      settings.validate = 'validate' in settings ? settings.validate : true;
      settings.root_name = settings.root_name || 'body';
      var fixInvalidChildren = function (nodes) {
        var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i;
        var nonEmptyElements, whitespaceElements, nonSplitableElements, textBlockElements, specialElements, sibling, nextNode;
        nonSplitableElements = makeMap$4('tr,td,th,tbody,thead,tfoot,table');
        nonEmptyElements = schema.getNonEmptyElements();
        whitespaceElements = schema.getWhiteSpaceElements();
        textBlockElements = schema.getTextBlockElements();
        specialElements = schema.getSpecialElements();
        for (ni = 0; ni < nodes.length; ni++) {
          node = nodes[ni];
          if (!node.parent || node.fixed) {
            continue;
          }
          if (textBlockElements[node.name] && node.parent.name === 'li') {
            sibling = node.next;
            while (sibling) {
              if (textBlockElements[sibling.name]) {
                sibling.name = 'li';
                sibling.fixed = true;
                node.parent.insert(sibling, node.parent);
              } else {
                break;
              }
              sibling = sibling.next;
            }
            node.unwrap(node);
            continue;
          }
          parents = [node];
          for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && !nonSplitableElements[parent.name]; parent = parent.parent) {
            parents.push(parent);
          }
          if (parent && parents.length > 1) {
            parents.reverse();
            newParent = currentNode = filterNode(parents[0].clone());
            for (i = 0; i < parents.length - 1; i++) {
              if (schema.isValidChild(currentNode.name, parents[i].name)) {
                tempNode = filterNode(parents[i].clone());
                currentNode.append(tempNode);
              } else {
                tempNode = currentNode;
              }
              for (childNode = parents[i].firstChild; childNode && childNode !== parents[i + 1];) {
                nextNode = childNode.next;
                tempNode.append(childNode);
                childNode = nextNode;
              }
              currentNode = tempNode;
            }
            if (!isEmpty$2(schema, nonEmptyElements, whitespaceElements, newParent)) {
              parent.insert(newParent, parents[0], true);
              parent.insert(node, newParent);
            } else {
              parent.insert(node, parents[0], true);
            }
            parent = parents[0];
            if (isEmpty$2(schema, nonEmptyElements, whitespaceElements, parent) || hasOnlyChild(parent, 'br')) {
              parent.empty().remove();
            }
          } else if (node.parent) {
            if (node.name === 'li') {
              sibling = node.prev;
              if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) {
                sibling.append(node);
                continue;
              }
              sibling = node.next;
              if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) {
                sibling.insert(node, sibling.firstChild, true);
                continue;
              }
              node.wrap(filterNode(new Node$1('ul', 1)));
              continue;
            }
            if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) {
              node.wrap(filterNode(new Node$1('div', 1)));
            } else {
              if (specialElements[node.name]) {
                node.empty().remove();
              } else {
                node.unwrap();
              }
            }
          }
        }
      };
      var filterNode = function (node) {
        var i, name, list;
        name = node.name;
        if (name in nodeFilters) {
          list = matchedNodes[name];
          if (list) {
            list.push(node);
          } else {
            matchedNodes[name] = [node];
          }
        }
        i = attributeFilters.length;
        while (i--) {
          name = attributeFilters[i].name;
          if (name in node.attributes.map) {
            list = matchedAttributes[name];
            if (list) {
              list.push(node);
            } else {
              matchedAttributes[name] = [node];
            }
          }
        }
        return node;
      };
      var addNodeFilter = function (name, callback) {
        each$i(explode$3(name), function (name) {
          var list = nodeFilters[name];
          if (!list) {
            nodeFilters[name] = list = [];
          }
          list.push(callback);
        });
      };
      var getNodeFilters = function () {
        var out = [];
        for (var name in nodeFilters) {
          if (nodeFilters.hasOwnProperty(name)) {
            out.push({
              name: name,
              callbacks: nodeFilters[name]
            });
          }
        }
        return out;
      };
      var addAttributeFilter = function (name, callback) {
        each$i(explode$3(name), function (name) {
          var i;
          for (i = 0; i < attributeFilters.length; i++) {
            if (attributeFilters[i].name === name) {
              attributeFilters[i].callbacks.push(callback);
              return;
            }
          }
          attributeFilters.push({
            name: name,
            callbacks: [callback]
          });
        });
      };
      var getAttributeFilters = function () {
        return [].concat(attributeFilters);
      };
      var parse = function (html, args) {
        var parser, nodes, i, l, fi, fl, list, name;
        var blockElements;
        var invalidChildren = [];
        var isInWhiteSpacePreservedElement;
        var node;
        args = args || {};
        matchedNodes = {};
        matchedAttributes = {};
        blockElements = extend$3(makeMap$4('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
        var nonEmptyElements = schema.getNonEmptyElements();
        var children = schema.children;
        var validate = settings.validate;
        var rootBlockName = 'forced_root_block' in args ? args.forced_root_block : settings.forced_root_block;
        var whiteSpaceElements = schema.getWhiteSpaceElements();
        var startWhiteSpaceRegExp = /^[ \t\r\n]+/;
        var endWhiteSpaceRegExp = /[ \t\r\n]+$/;
        var allWhiteSpaceRegExp = /[ \t\r\n]+/g;
        var isAllWhiteSpaceRegExp = /^[ \t\r\n]+$/;
        isInWhiteSpacePreservedElement = whiteSpaceElements.hasOwnProperty(args.context) || whiteSpaceElements.hasOwnProperty(settings.root_name);
        var addRootBlocks = function () {
          var node = rootNode.firstChild, next, rootBlockNode;
          var trim = function (rootBlockNode) {
            if (rootBlockNode) {
              node = rootBlockNode.firstChild;
              if (node && node.type === 3) {
                node.value = node.value.replace(startWhiteSpaceRegExp, '');
              }
              node = rootBlockNode.lastChild;
              if (node && node.type === 3) {
                node.value = node.value.replace(endWhiteSpaceRegExp, '');
              }
            }
          };
          if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) {
            return;
          }
          while (node) {
            next = node.next;
            if (node.type === 3 || node.type === 1 && node.name !== 'p' && !blockElements[node.name] && !node.attr('data-mce-type')) {
              if (!rootBlockNode) {
                rootBlockNode = createNode(rootBlockName, 1);
                rootBlockNode.attr(settings.forced_root_block_attrs);
                rootNode.insert(rootBlockNode, node);
                rootBlockNode.append(node);
              } else {
                rootBlockNode.append(node);
              }
            } else {
              trim(rootBlockNode);
              rootBlockNode = null;
            }
            node = next;
          }
          trim(rootBlockNode);
        };
        var createNode = function (name, type) {
          var node = new Node$1(name, type);
          var list;
          if (name in nodeFilters) {
            list = matchedNodes[name];
            if (list) {
              list.push(node);
            } else {
              matchedNodes[name] = [node];
            }
          }
          return node;
        };
        var removeWhitespaceBefore = function (node) {
          var textNode, textNodeNext, textVal, sibling;
          var blockElements = schema.getBlockElements();
          for (textNode = node.prev; textNode && textNode.type === 3;) {
            textVal = textNode.value.replace(endWhiteSpaceRegExp, '');
            if (textVal.length > 0) {
              textNode.value = textVal;
              return;
            }
            textNodeNext = textNode.next;
            if (textNodeNext) {
              if (textNodeNext.type === 3 && textNodeNext.value.length) {
                textNode = textNode.prev;
                continue;
              }
              if (!blockElements[textNodeNext.name] && textNodeNext.name !== 'script' && textNodeNext.name !== 'style') {
                textNode = textNode.prev;
                continue;
              }
            }
            sibling = textNode.prev;
            textNode.remove();
            textNode = sibling;
          }
        };
        var cloneAndExcludeBlocks = function (input) {
          var name;
          var output = {};
          for (name in input) {
            if (name !== 'li' && name !== 'p') {
              output[name] = input[name];
            }
          }
          return output;
        };
        parser = SaxParser$1({
          validate: validate,
          allow_script_urls: settings.allow_script_urls,
          allow_conditional_comments: settings.allow_conditional_comments,
          self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()),
          cdata: function (text) {
            node.append(createNode('#cdata', 4)).value = text;
          },
          text: function (text, raw) {
            var textNode;
            if (!isInWhiteSpacePreservedElement) {
              text = text.replace(allWhiteSpaceRegExp, ' ');
              if (isLineBreakNode(node.lastChild, blockElements)) {
                text = text.replace(startWhiteSpaceRegExp, '');
              }
            }
            if (text.length !== 0) {
              textNode = createNode('#text', 3);
              textNode.raw = !!raw;
              node.append(textNode).value = text;
            }
          },
          comment: function (text) {
            node.append(createNode('#comment', 8)).value = text;
          },
          pi: function (name, text) {
            node.append(createNode(name, 7)).value = text;
            removeWhitespaceBefore(node);
          },
          doctype: function (text) {
            var newNode;
            newNode = node.append(createNode('#doctype', 10));
            newNode.value = text;
            removeWhitespaceBefore(node);
          },
          start: function (name, attrs, empty) {
            var newNode, attrFiltersLen, elementRule, attrName, parent;
            elementRule = validate ? schema.getElementRule(name) : {};
            if (elementRule) {
              newNode = createNode(elementRule.outputName || name, 1);
              newNode.attributes = attrs;
              newNode.shortEnded = empty;
              node.append(newNode);
              parent = children[node.name];
              if (parent && children[newNode.name] && !parent[newNode.name]) {
                invalidChildren.push(newNode);
              }
              attrFiltersLen = attributeFilters.length;
              while (attrFiltersLen--) {
                attrName = attributeFilters[attrFiltersLen].name;
                if (attrName in attrs.map) {
                  list = matchedAttributes[attrName];
                  if (list) {
                    list.push(newNode);
                  } else {
                    matchedAttributes[attrName] = [newNode];
                  }
                }
              }
              if (blockElements[name]) {
                removeWhitespaceBefore(newNode);
              }
              if (!empty) {
                node = newNode;
              }
              if (!isInWhiteSpacePreservedElement && whiteSpaceElements[name]) {
                isInWhiteSpacePreservedElement = true;
              }
            }
          },
          end: function (name) {
            var textNode, elementRule, text, sibling, tempNode;
            elementRule = validate ? schema.getElementRule(name) : {};
            if (elementRule) {
              if (blockElements[name]) {
                if (!isInWhiteSpacePreservedElement) {
                  textNode = node.firstChild;
                  if (textNode && textNode.type === 3) {
                    text = textNode.value.replace(startWhiteSpaceRegExp, '');
                    if (text.length > 0) {
                      textNode.value = text;
                      textNode = textNode.next;
                    } else {
                      sibling = textNode.next;
                      textNode.remove();
                      textNode = sibling;
                      while (textNode && textNode.type === 3) {
                        text = textNode.value;
                        sibling = textNode.next;
                        if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
                          textNode.remove();
                          textNode = sibling;
                        }
                        textNode = sibling;
                      }
                    }
                  }
                  textNode = node.lastChild;
                  if (textNode && textNode.type === 3) {
                    text = textNode.value.replace(endWhiteSpaceRegExp, '');
                    if (text.length > 0) {
                      textNode.value = text;
                      textNode = textNode.prev;
                    } else {
                      sibling = textNode.prev;
                      textNode.remove();
                      textNode = sibling;
                      while (textNode && textNode.type === 3) {
                        text = textNode.value;
                        sibling = textNode.prev;
                        if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
                          textNode.remove();
                          textNode = sibling;
                        }
                        textNode = sibling;
                      }
                    }
                  }
                }
              }
              if (isInWhiteSpacePreservedElement && whiteSpaceElements[name]) {
                isInWhiteSpacePreservedElement = false;
              }
              if (elementRule.removeEmpty && isEmpty$2(schema, nonEmptyElements, whiteSpaceElements, node)) {
                if (!node.attributes.map.name && !node.attr('id')) {
                  tempNode = node.parent;
                  if (blockElements[node.name]) {
                    node.empty().remove();
                  } else {
                    node.unwrap();
                  }
                  node = tempNode;
                  return;
                }
              }
              if (elementRule.paddEmpty && (isPaddedWithNbsp(node) || isEmpty$2(schema, nonEmptyElements, whiteSpaceElements, node))) {
                paddEmptyNode(settings, args, blockElements, node);
              }
              node = node.parent;
            }
          }
        }, schema);
        var rootNode = node = new Node$1(args.context || settings.root_name, 11);
        parser.parse(html);
        if (validate && invalidChildren.length) {
          if (!args.context) {
            fixInvalidChildren(invalidChildren);
          } else {
            args.invalid = true;
          }
        }
        if (rootBlockName && (rootNode.name === 'body' || args.isRootContent)) {
          addRootBlocks();
        }
        if (!args.invalid) {
          for (name in matchedNodes) {
            list = nodeFilters[name];
            nodes = matchedNodes[name];
            fi = nodes.length;
            while (fi--) {
              if (!nodes[fi].parent) {
                nodes.splice(fi, 1);
              }
            }
            for (i = 0, l = list.length; i < l; i++) {
              list[i](nodes, name, args);
            }
          }
          for (i = 0, l = attributeFilters.length; i < l; i++) {
            list = attributeFilters[i];
            if (list.name in matchedAttributes) {
              nodes = matchedAttributes[list.name];
              fi = nodes.length;
              while (fi--) {
                if (!nodes[fi].parent) {
                  nodes.splice(fi, 1);
                }
              }
              for (fi = 0, fl = list.callbacks.length; fi < fl; fi++) {
                list.callbacks[fi](nodes, list.name, args);
              }
            }
          }
        }
        return rootNode;
      };
      var exports = {
        schema: schema,
        addAttributeFilter: addAttributeFilter,
        getAttributeFilters: getAttributeFilters,
        addNodeFilter: addNodeFilter,
        getNodeFilters: getNodeFilters,
        filterNode: filterNode,
        parse: parse
      };
      register$2(exports, settings);
      LegacyFilter.register(exports, settings);
      return exports;
    }

    var addTempAttr = function (htmlParser, tempAttrs, name) {
      if (Tools.inArray(tempAttrs, name) === -1) {
        htmlParser.addAttributeFilter(name, function (nodes, name) {
          var i = nodes.length;
          while (i--) {
            nodes[i].attr(name, null);
          }
        });
        tempAttrs.push(name);
      }
    };
    var postProcess$1 = function (editor, args, content) {
      if (!args.no_events && editor) {
        var outArgs = Events.firePostProcess(editor, merge(args, { content: content }));
        return outArgs.content;
      } else {
        return content;
      }
    };
    var getHtmlFromNode = function (dom, node, args) {
      var html = Zwsp.trim(args.getInner ? node.innerHTML : dom.getOuterHTML(node));
      return args.selection || isWsPreserveElement(Element.fromDom(node)) ? html : Tools.trim(html);
    };
    var parseHtml = function (htmlParser, html, args) {
      var parserArgs = args.selection ? merge({ forced_root_block: false }, args) : args;
      var rootNode = htmlParser.parse(html, parserArgs);
      DomSerializerFilters.trimTrailingBr(rootNode);
      return rootNode;
    };
    var serializeNode = function (settings, schema, node) {
      var htmlSerializer = HtmlSerializer(settings, schema);
      return htmlSerializer.serialize(node);
    };
    var toHtml = function (editor, settings, schema, rootNode, args) {
      var content = serializeNode(settings, schema, rootNode);
      return postProcess$1(editor, args, content);
    };
    function DomSerializer (settings, editor) {
      var dom, schema, htmlParser;
      var tempAttrs = ['data-mce-selected'];
      dom = editor && editor.dom ? editor.dom : DOMUtils$1.DOM;
      schema = editor && editor.schema ? editor.schema : Schema(settings);
      settings.entity_encoding = settings.entity_encoding || 'named';
      settings.remove_trailing_brs = 'remove_trailing_brs' in settings ? settings.remove_trailing_brs : true;
      htmlParser = DomParser(settings, schema);
      DomSerializerFilters.register(htmlParser, settings, dom);
      var serialize = function (node, parserArgs) {
        var args = merge({ format: 'html' }, parserArgs ? parserArgs : {});
        var targetNode = DomSerializerPreProcess.process(editor, node, args);
        var html = getHtmlFromNode(dom, targetNode, args);
        var rootNode = parseHtml(htmlParser, html, args);
        return args.format === 'tree' ? rootNode : toHtml(editor, settings, schema, rootNode, args);
      };
      return {
        schema: schema,
        addNodeFilter: htmlParser.addNodeFilter,
        addAttributeFilter: htmlParser.addAttributeFilter,
        serialize: serialize,
        addRules: function (rules) {
          schema.addValidElements(rules);
        },
        setRules: function (rules) {
          schema.setValidElements(rules);
        },
        addTempAttr: curry(addTempAttr, htmlParser, tempAttrs),
        getTempAttrs: function () {
          return tempAttrs;
        }
      };
    }

    function DomSerializer$1 (settings, editor) {
      var domSerializer = DomSerializer(settings, editor);
      return {
        schema: domSerializer.schema,
        addNodeFilter: domSerializer.addNodeFilter,
        addAttributeFilter: domSerializer.addAttributeFilter,
        serialize: domSerializer.serialize,
        addRules: domSerializer.addRules,
        setRules: domSerializer.setRules,
        addTempAttr: domSerializer.addTempAttr,
        getTempAttrs: domSerializer.getTempAttrs
      };
    }

    function BookmarkManager(selection) {
      return {
        getBookmark: curry(Bookmarks.getBookmark, selection),
        moveToBookmark: curry(Bookmarks.moveToBookmark, selection)
      };
    }
    (function (BookmarkManager) {
      BookmarkManager.isBookmarkNode = Bookmarks.isBookmarkNode;
    }(BookmarkManager || (BookmarkManager = {})));
    var BookmarkManager$1 = BookmarkManager;

    var isContentEditableFalse$a = NodeType.isContentEditableFalse;
    var isContentEditableTrue$5 = NodeType.isContentEditableTrue;
    var getContentEditableRoot$2 = function (root, node) {
      while (node && node !== root) {
        if (isContentEditableTrue$5(node) || isContentEditableFalse$a(node)) {
          return node;
        }
        node = node.parentNode;
      }
      return null;
    };
    var ControlSelection = function (selection, editor) {
      var dom = editor.dom, each = Tools.each;
      var selectedElm, selectedElmGhost, resizeHelper, resizeHandles, selectedHandle;
      var startX, startY, selectedElmX, selectedElmY, startW, startH, ratio, resizeStarted;
      var width, height;
      var editableDoc = editor.getDoc(), rootDocument = domGlobals.document;
      var abs = Math.abs, round = Math.round, rootElement = editor.getBody();
      var startScrollWidth, startScrollHeight;
      resizeHandles = {
        nw: [
          0,
          0,
          -1,
          -1
        ],
        ne: [
          1,
          0,
          1,
          -1
        ],
        se: [
          1,
          1,
          1,
          1
        ],
        sw: [
          0,
          1,
          -1,
          1
        ]
      };
      var rootClass = '.mce-content-body';
      editor.contentStyles.push(rootClass + ' div.mce-resizehandle {' + 'position: absolute;' + 'border: 1px solid black;' + 'box-sizing: content-box;' + 'background: #FFF;' + 'width: 7px;' + 'height: 7px;' + 'z-index: 10000' + '}' + rootClass + ' .mce-resizehandle:hover {' + 'background: #000' + '}' + rootClass + ' img[data-mce-selected],' + rootClass + ' hr[data-mce-selected] {' + 'outline: 1px solid black;' + 'resize: none' + '}' + rootClass + ' .mce-clonedresizable {' + 'position: absolute;' + (Env.gecko ? '' : 'outline: 1px dashed black;') + 'opacity: .5;' + 'filter: alpha(opacity=50);' + 'z-index: 10000' + '}' + rootClass + ' .mce-resize-helper {' + 'background: #555;' + 'background: rgba(0,0,0,0.75);' + 'border-radius: 3px;' + 'border: 1px;' + 'color: white;' + 'display: none;' + 'font-family: sans-serif;' + 'font-size: 12px;' + 'white-space: nowrap;' + 'line-height: 14px;' + 'margin: 5px 10px;' + 'padding: 5px;' + 'position: absolute;' + 'z-index: 10001' + '}');
      var isImage = function (elm) {
        return elm && (elm.nodeName === 'IMG' || editor.dom.is(elm, 'figure.image'));
      };
      var isEventOnImageOutsideRange = function (evt, range) {
        return isImage(evt.target) && !RangePoint.isXYWithinRange(evt.clientX, evt.clientY, range);
      };
      var contextMenuSelectImage = function (evt) {
        var target = evt.target;
        if (isEventOnImageOutsideRange(evt, editor.selection.getRng()) && !evt.isDefaultPrevented()) {
          editor.selection.select(target);
        }
      };
      var getResizeTarget = function (elm) {
        return editor.dom.is(elm, 'figure.image') ? elm.querySelector('img') : elm;
      };
      var isResizable = function (elm) {
        var selector = editor.settings.object_resizing;
        if (selector === false || Env.iOS) {
          return false;
        }
        if (typeof selector !== 'string') {
          selector = 'table,img,figure.image,div';
        }
        if (elm.getAttribute('data-mce-resize') === 'false') {
          return false;
        }
        if (elm === editor.getBody()) {
          return false;
        }
        return is$1(Element.fromDom(elm), selector);
      };
      var resizeGhostElement = function (e) {
        var deltaX, deltaY, proportional;
        var resizeHelperX, resizeHelperY;
        deltaX = e.screenX - startX;
        deltaY = e.screenY - startY;
        width = deltaX * selectedHandle[2] + startW;
        height = deltaY * selectedHandle[3] + startH;
        width = width < 5 ? 5 : width;
        height = height < 5 ? 5 : height;
        if (isImage(selectedElm) && editor.settings.resize_img_proportional !== false) {
          proportional = !VK.modifierPressed(e);
        } else {
          proportional = VK.modifierPressed(e) || isImage(selectedElm) && selectedHandle[2] * selectedHandle[3] !== 0;
        }
        if (proportional) {
          if (abs(deltaX) > abs(deltaY)) {
            height = round(width * ratio);
            width = round(height / ratio);
          } else {
            width = round(height / ratio);
            height = round(width * ratio);
          }
        }
        dom.setStyles(getResizeTarget(selectedElmGhost), {
          width: width,
          height: height
        });
        resizeHelperX = selectedHandle.startPos.x + deltaX;
        resizeHelperY = selectedHandle.startPos.y + deltaY;
        resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
        resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
        dom.setStyles(resizeHelper, {
          left: resizeHelperX,
          top: resizeHelperY,
          display: 'block'
        });
        resizeHelper.innerHTML = width + ' &times; ' + height;
        if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
          dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
        }
        if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
          dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
        }
        deltaX = rootElement.scrollWidth - startScrollWidth;
        deltaY = rootElement.scrollHeight - startScrollHeight;
        if (deltaX + deltaY !== 0) {
          dom.setStyles(resizeHelper, {
            left: resizeHelperX - deltaX,
            top: resizeHelperY - deltaY
          });
        }
        if (!resizeStarted) {
          Events.fireObjectResizeStart(editor, selectedElm, startW, startH);
          resizeStarted = true;
        }
      };
      var endGhostResize = function () {
        resizeStarted = false;
        var setSizeProp = function (name, value) {
          if (value) {
            if (selectedElm.style[name] || !editor.schema.isValid(selectedElm.nodeName.toLowerCase(), name)) {
              dom.setStyle(getResizeTarget(selectedElm), name, value);
            } else {
              dom.setAttrib(getResizeTarget(selectedElm), name, value);
            }
          }
        };
        setSizeProp('width', width);
        setSizeProp('height', height);
        dom.unbind(editableDoc, 'mousemove', resizeGhostElement);
        dom.unbind(editableDoc, 'mouseup', endGhostResize);
        if (rootDocument !== editableDoc) {
          dom.unbind(rootDocument, 'mousemove', resizeGhostElement);
          dom.unbind(rootDocument, 'mouseup', endGhostResize);
        }
        dom.remove(selectedElmGhost);
        dom.remove(resizeHelper);
        showResizeRect(selectedElm);
        Events.fireObjectResized(editor, selectedElm, width, height);
        dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
        editor.nodeChanged();
      };
      var showResizeRect = function (targetElm) {
        var position, targetWidth, targetHeight, e, rect;
        hideResizeRect();
        unbindResizeHandleEvents();
        position = dom.getPos(targetElm, rootElement);
        selectedElmX = position.x;
        selectedElmY = position.y;
        rect = targetElm.getBoundingClientRect();
        targetWidth = rect.width || rect.right - rect.left;
        targetHeight = rect.height || rect.bottom - rect.top;
        if (selectedElm !== targetElm) {
          selectedElm = targetElm;
          width = height = 0;
        }
        e = editor.fire('ObjectSelected', { target: targetElm });
        if (isResizable(targetElm) && !e.isDefaultPrevented()) {
          each(resizeHandles, function (handle, name) {
            var handleElm;
            var startDrag = function (e) {
              startX = e.screenX;
              startY = e.screenY;
              startW = getResizeTarget(selectedElm).clientWidth;
              startH = getResizeTarget(selectedElm).clientHeight;
              ratio = startH / startW;
              selectedHandle = handle;
              handle.startPos = {
                x: targetWidth * handle[0] + selectedElmX,
                y: targetHeight * handle[1] + selectedElmY
              };
              startScrollWidth = rootElement.scrollWidth;
              startScrollHeight = rootElement.scrollHeight;
              selectedElmGhost = selectedElm.cloneNode(true);
              dom.addClass(selectedElmGhost, 'mce-clonedresizable');
              dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all');
              selectedElmGhost.contentEditable = false;
              selectedElmGhost.unSelectabe = true;
              dom.setStyles(selectedElmGhost, {
                left: selectedElmX,
                top: selectedElmY,
                margin: 0
              });
              selectedElmGhost.removeAttribute('data-mce-selected');
              rootElement.appendChild(selectedElmGhost);
              dom.bind(editableDoc, 'mousemove', resizeGhostElement);
              dom.bind(editableDoc, 'mouseup', endGhostResize);
              if (rootDocument !== editableDoc) {
                dom.bind(rootDocument, 'mousemove', resizeGhostElement);
                dom.bind(rootDocument, 'mouseup', endGhostResize);
              }
              resizeHelper = dom.add(rootElement, 'div', {
                'class': 'mce-resize-helper',
                'data-mce-bogus': 'all'
              }, startW + ' &times; ' + startH);
            };
            handleElm = dom.get('mceResizeHandle' + name);
            if (handleElm) {
              dom.remove(handleElm);
            }
            handleElm = dom.add(rootElement, 'div', {
              'id': 'mceResizeHandle' + name,
              'data-mce-bogus': 'all',
              'class': 'mce-resizehandle',
              'unselectable': true,
              'style': 'cursor:' + name + '-resize; margin:0; padding:0'
            });
            if (Env.ie === 11) {
              handleElm.contentEditable = false;
            }
            dom.bind(handleElm, 'mousedown', function (e) {
              e.stopImmediatePropagation();
              e.preventDefault();
              startDrag(e);
            });
            handle.elm = handleElm;
            dom.setStyles(handleElm, {
              left: targetWidth * handle[0] + selectedElmX - handleElm.offsetWidth / 2,
              top: targetHeight * handle[1] + selectedElmY - handleElm.offsetHeight / 2
            });
          });
        } else {
          hideResizeRect();
        }
        selectedElm.setAttribute('data-mce-selected', '1');
      };
      var hideResizeRect = function () {
        var name, handleElm;
        unbindResizeHandleEvents();
        if (selectedElm) {
          selectedElm.removeAttribute('data-mce-selected');
        }
        for (name in resizeHandles) {
          handleElm = dom.get('mceResizeHandle' + name);
          if (handleElm) {
            dom.unbind(handleElm);
            dom.remove(handleElm);
          }
        }
      };
      var updateResizeRect = function (e) {
        var startElm, controlElm;
        var isChildOrEqual = function (node, parent) {
          if (node) {
            do {
              if (node === parent) {
                return true;
              }
            } while (node = node.parentNode);
          }
        };
        if (resizeStarted || editor.removed) {
          return;
        }
        each(dom.select('img[data-mce-selected],hr[data-mce-selected]'), function (img) {
          img.removeAttribute('data-mce-selected');
        });
        controlElm = e.type === 'mousedown' ? e.target : selection.getNode();
        controlElm = dom.$(controlElm).closest('table,img,figure.image,hr')[0];
        if (isChildOrEqual(controlElm, rootElement)) {
          disableGeckoResize();
          startElm = selection.getStart(true);
          if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
            showResizeRect(controlElm);
            return;
          }
        }
        hideResizeRect();
      };
      var isWithinContentEditableFalse = function (elm) {
        return isContentEditableFalse$a(getContentEditableRoot$2(editor.getBody(), elm));
      };
      var unbindResizeHandleEvents = function () {
        for (var name in resizeHandles) {
          var handle = resizeHandles[name];
          if (handle.elm) {
            dom.unbind(handle.elm);
            delete handle.elm;
          }
        }
      };
      var disableGeckoResize = function () {
        try {
          editor.getDoc().execCommand('enableObjectResizing', false, false);
        } catch (ex) {
        }
      };
      editor.on('init', function () {
        disableGeckoResize();
        if (Env.ie && Env.ie >= 11) {
          editor.on('mousedown click', function (e) {
            var target = e.target, nodeName = target.nodeName;
            if (!resizeStarted && /^(TABLE|IMG|HR)$/.test(nodeName) && !isWithinContentEditableFalse(target)) {
              if (e.button !== 2) {
                editor.selection.select(target, nodeName === 'TABLE');
              }
              if (e.type === 'mousedown') {
                editor.nodeChanged();
              }
            }
          });
          editor.dom.bind(rootElement, 'mscontrolselect', function (e) {
            var delayedSelect = function (node) {
              Delay.setEditorTimeout(editor, function () {
                editor.selection.select(node);
              });
            };
            if (isWithinContentEditableFalse(e.target)) {
              e.preventDefault();
              delayedSelect(e.target);
              return;
            }
            if (/^(TABLE|IMG|HR)$/.test(e.target.nodeName)) {
              e.preventDefault();
              if (e.target.tagName === 'IMG') {
                delayedSelect(e.target);
              }
            }
          });
        }
        var throttledUpdateResizeRect = Delay.throttle(function (e) {
          if (!editor.composing) {
            updateResizeRect(e);
          }
        });
        editor.on('nodechange ResizeEditor ResizeWindow drop FullscreenStateChanged', throttledUpdateResizeRect);
        editor.on('keyup compositionend', function (e) {
          if (selectedElm && selectedElm.nodeName === 'TABLE') {
            throttledUpdateResizeRect(e);
          }
        });
        editor.on('hide blur', hideResizeRect);
        editor.on('contextmenu', contextMenuSelectImage);
      });
      editor.on('remove', unbindResizeHandleEvents);
      var destroy = function () {
        selectedElm = selectedElmGhost = null;
      };
      return {
        isResizable: isResizable,
        showResizeRect: showResizeRect,
        hideResizeRect: hideResizeRect,
        updateResizeRect: updateResizeRect,
        destroy: destroy
      };
    };

    var hasCeProperty = function (node) {
      return NodeType.isContentEditableTrue(node) || NodeType.isContentEditableFalse(node);
    };
    var findParent$1 = function (node, rootNode, predicate) {
      while (node && node !== rootNode) {
        if (predicate(node)) {
          return node;
        }
        node = node.parentNode;
      }
      return null;
    };
    var findClosestIeRange = function (clientX, clientY, doc) {
      var element, rng, rects;
      element = doc.elementFromPoint(clientX, clientY);
      rng = doc.body.createTextRange();
      if (!element || element.tagName === 'HTML') {
        element = doc.body;
      }
      rng.moveToElementText(element);
      rects = Tools.toArray(rng.getClientRects());
      rects = rects.sort(function (a, b) {
        a = Math.abs(Math.max(a.top - clientY, a.bottom - clientY));
        b = Math.abs(Math.max(b.top - clientY, b.bottom - clientY));
        return a - b;
      });
      if (rects.length > 0) {
        clientY = (rects[0].bottom + rects[0].top) / 2;
        try {
          rng.moveToPoint(clientX, clientY);
          rng.collapse(true);
          return rng;
        } catch (ex) {
        }
      }
      return null;
    };
    var moveOutOfContentEditableFalse = function (rng, rootNode) {
      var parentElement = rng && rng.parentElement ? rng.parentElement() : null;
      return NodeType.isContentEditableFalse(findParent$1(parentElement, rootNode, hasCeProperty)) ? null : rng;
    };
    var fromPoint$1 = function (clientX, clientY, doc) {
      var rng, point;
      var pointDoc = doc;
      if (pointDoc.caretPositionFromPoint) {
        point = pointDoc.caretPositionFromPoint(clientX, clientY);
        if (point) {
          rng = doc.createRange();
          rng.setStart(point.offsetNode, point.offset);
          rng.collapse(true);
        }
      } else if (doc.caretRangeFromPoint) {
        rng = doc.caretRangeFromPoint(clientX, clientY);
      } else if (pointDoc.body.createTextRange) {
        rng = pointDoc.body.createTextRange();
        try {
          rng.moveToPoint(clientX, clientY);
          rng.collapse(true);
        } catch (ex) {
          rng = findClosestIeRange(clientX, clientY, doc);
        }
        return moveOutOfContentEditableFalse(rng, doc.body);
      }
      return rng;
    };
    var CaretRangeFromPoint = { fromPoint: fromPoint$1 };

    var processRanges = function (editor, ranges) {
      return map(ranges, function (range) {
        var evt = editor.fire('GetSelectionRange', { range: range });
        return evt.range !== range ? evt.range : range;
      });
    };
    var EventProcessRanges = { processRanges: processRanges };

    var fromElements = function (elements, scope) {
      var doc = scope || domGlobals.document;
      var fragment = doc.createDocumentFragment();
      each(elements, function (element) {
        fragment.appendChild(element.dom());
      });
      return Element.fromDom(fragment);
    };

    var tableModel = Immutable('element', 'width', 'rows');
    var tableRow = Immutable('element', 'cells');
    var cellPosition = Immutable('x', 'y');
    var getSpan = function (td, key) {
      var value = parseInt(get(td, key), 10);
      return isNaN(value) ? 1 : value;
    };
    var fillout = function (table, x, y, tr, td) {
      var rowspan = getSpan(td, 'rowspan');
      var colspan = getSpan(td, 'colspan');
      var rows = table.rows();
      for (var y2 = y; y2 < y + rowspan; y2++) {
        if (!rows[y2]) {
          rows[y2] = tableRow(deep(tr), []);
        }
        for (var x2 = x; x2 < x + colspan; x2++) {
          var cells = rows[y2].cells();
          cells[x2] = y2 === y && x2 === x ? td : shallow(td);
        }
      }
    };
    var cellExists = function (table, x, y) {
      var rows = table.rows();
      var cells = rows[y] ? rows[y].cells() : [];
      return !!cells[x];
    };
    var skipCellsX = function (table, x, y) {
      while (cellExists(table, x, y)) {
        x++;
      }
      return x;
    };
    var getWidth = function (rows) {
      return foldl(rows, function (acc, row) {
        return row.cells().length > acc ? row.cells().length : acc;
      }, 0);
    };
    var findElementPos = function (table, element) {
      var rows = table.rows();
      for (var y = 0; y < rows.length; y++) {
        var cells = rows[y].cells();
        for (var x = 0; x < cells.length; x++) {
          if (eq(cells[x], element)) {
            return Option.some(cellPosition(x, y));
          }
        }
      }
      return Option.none();
    };
    var extractRows = function (table, sx, sy, ex, ey) {
      var newRows = [];
      var rows = table.rows();
      for (var y = sy; y <= ey; y++) {
        var cells = rows[y].cells();
        var slice = sx < ex ? cells.slice(sx, ex + 1) : cells.slice(ex, sx + 1);
        newRows.push(tableRow(rows[y].element(), slice));
      }
      return newRows;
    };
    var subTable = function (table, startPos, endPos) {
      var sx = startPos.x(), sy = startPos.y();
      var ex = endPos.x(), ey = endPos.y();
      var newRows = sy < ey ? extractRows(table, sx, sy, ex, ey) : extractRows(table, sx, ey, ex, sy);
      return tableModel(table.element(), getWidth(newRows), newRows);
    };
    var createDomTable = function (table, rows) {
      var tableElement = shallow(table.element());
      var tableBody = Element.fromTag('tbody');
      append$1(tableBody, rows);
      append(tableElement, tableBody);
      return tableElement;
    };
    var modelRowsToDomRows = function (table) {
      return map(table.rows(), function (row) {
        var cells = map(row.cells(), function (cell) {
          var td = deep(cell);
          remove(td, 'colspan');
          remove(td, 'rowspan');
          return td;
        });
        var tr = shallow(row.element());
        append$1(tr, cells);
        return tr;
      });
    };
    var fromDom$1 = function (tableElm) {
      var table = tableModel(shallow(tableElm), 0, []);
      each(descendants$1(tableElm, 'tr'), function (tr, y) {
        each(descendants$1(tr, 'td,th'), function (td, x) {
          fillout(table, skipCellsX(table, x, y), y, tr, td);
        });
      });
      return tableModel(table.element(), getWidth(table.rows()), table.rows());
    };
    var toDom = function (table) {
      return createDomTable(table, modelRowsToDomRows(table));
    };
    var subsection = function (table, startElement, endElement) {
      return findElementPos(table, startElement).bind(function (startPos) {
        return findElementPos(table, endElement).map(function (endPos) {
          return subTable(table, startPos, endPos);
        });
      });
    };
    var SimpleTableModel = {
      fromDom: fromDom$1,
      toDom: toDom,
      subsection: subsection
    };

    var findParentListContainer = function (parents) {
      return find(parents, function (elm) {
        return name(elm) === 'ul' || name(elm) === 'ol';
      });
    };
    var getFullySelectedListWrappers = function (parents, rng) {
      return find(parents, function (elm) {
        return name(elm) === 'li' && hasAllContentsSelected(elm, rng);
      }).fold(constant([]), function (li) {
        return findParentListContainer(parents).map(function (listCont) {
          return [
            Element.fromTag('li'),
            Element.fromTag(name(listCont))
          ];
        }).getOr([]);
      });
    };
    var wrap$3 = function (innerElm, elms) {
      var wrapped = foldl(elms, function (acc, elm) {
        append(elm, acc);
        return elm;
      }, innerElm);
      return elms.length > 0 ? fromElements([wrapped]) : wrapped;
    };
    var directListWrappers = function (commonAnchorContainer) {
      if (isListItem(commonAnchorContainer)) {
        return parent(commonAnchorContainer).filter(isList).fold(constant([]), function (listElm) {
          return [
            commonAnchorContainer,
            listElm
          ];
        });
      } else {
        return isList(commonAnchorContainer) ? [commonAnchorContainer] : [];
      }
    };
    var getWrapElements = function (rootNode, rng) {
      var commonAnchorContainer = Element.fromDom(rng.commonAncestorContainer);
      var parents = Parents.parentsAndSelf(commonAnchorContainer, rootNode);
      var wrapElements = filter(parents, function (elm) {
        return isInline(elm) || isHeading(elm);
      });
      var listWrappers = getFullySelectedListWrappers(parents, rng);
      var allWrappers = wrapElements.concat(listWrappers.length ? listWrappers : directListWrappers(commonAnchorContainer));
      return map(allWrappers, shallow);
    };
    var emptyFragment = function () {
      return fromElements([]);
    };
    var getFragmentFromRange = function (rootNode, rng) {
      return wrap$3(Element.fromDom(rng.cloneContents()), getWrapElements(rootNode, rng));
    };
    var getParentTable = function (rootElm, cell) {
      return ancestor$1(cell, 'table', curry(eq, rootElm));
    };
    var getTableFragment = function (rootNode, selectedTableCells) {
      return getParentTable(rootNode, selectedTableCells[0]).bind(function (tableElm) {
        var firstCell = selectedTableCells[0];
        var lastCell = selectedTableCells[selectedTableCells.length - 1];
        var fullTableModel = SimpleTableModel.fromDom(tableElm);
        return SimpleTableModel.subsection(fullTableModel, firstCell, lastCell).map(function (sectionedTableModel) {
          return fromElements([SimpleTableModel.toDom(sectionedTableModel)]);
        });
      }).getOrThunk(emptyFragment);
    };
    var getSelectionFragment = function (rootNode, ranges) {
      return ranges.length > 0 && ranges[0].collapsed ? emptyFragment() : getFragmentFromRange(rootNode, ranges[0]);
    };
    var read$4 = function (rootNode, ranges) {
      var selectedCells = TableCellSelection.getCellsFromElementOrRanges(ranges, rootNode);
      return selectedCells.length > 0 ? getTableFragment(rootNode, selectedCells) : getSelectionFragment(rootNode, ranges);
    };
    var FragmentReader = { read: read$4 };

    var getTextContent = function (editor) {
      return Option.from(editor.selection.getRng()).map(function (rng) {
        var bin = editor.dom.add(editor.getBody(), 'div', {
          'data-mce-bogus': 'all',
          'style': 'overflow: hidden; opacity: 0;'
        }, rng.cloneContents());
        var text = Zwsp.trim(bin.innerText);
        editor.dom.remove(bin);
        return text;
      }).getOr('');
    };
    var getHtmlContent = function (editor, args) {
      var rng = editor.selection.getRng(), tmpElm = editor.dom.create('body');
      var sel = editor.selection.getSel();
      var fragment;
      var ranges = EventProcessRanges.processRanges(editor, MultiRange.getRanges(sel));
      fragment = args.contextual ? FragmentReader.read(Element.fromDom(editor.getBody()), ranges).dom() : rng.cloneContents();
      if (fragment) {
        tmpElm.appendChild(fragment);
      }
      return editor.selection.serializer.serialize(tmpElm, args);
    };
    var getContent = function (editor, args) {
      if (args === void 0) {
        args = {};
      }
      args.get = true;
      args.format = args.format || 'html';
      args.selection = true;
      args = editor.fire('BeforeGetContent', args);
      if (args.isDefaultPrevented()) {
        editor.fire('GetContent', args);
        return args.content;
      }
      if (args.format === 'text') {
        return getTextContent(editor);
      } else {
        args.getInner = true;
        var content = getHtmlContent(editor, args);
        if (args.format === 'tree') {
          return content;
        } else {
          args.content = editor.selection.isCollapsed() ? '' : content;
          editor.fire('GetContent', args);
          return args.content;
        }
      }
    };
    var GetSelectionContent = { getContent: getContent };

    var setupArgs = function (args, content) {
      return __assign(__assign({ format: 'html' }, args), {
        set: true,
        selection: true,
        content: content
      });
    };
    var cleanContent = function (editor, args) {
      if (args.format !== 'raw') {
        var node = editor.parser.parse(args.content, __assign({
          isRootContent: true,
          forced_root_block: false
        }, args));
        return HtmlSerializer({ validate: editor.validate }, editor.schema).serialize(node);
      } else {
        return args.content;
      }
    };
    var setContent = function (editor, content, args) {
      var contentArgs = setupArgs(args, content);
      var rng = editor.selection.getRng(), caretNode;
      var doc = editor.getDoc();
      var frag, temp;
      if (!contentArgs.no_events) {
        contentArgs = editor.fire('BeforeSetContent', contentArgs);
        if (contentArgs.isDefaultPrevented()) {
          editor.fire('SetContent', contentArgs);
          return;
        }
      }
      content = cleanContent(editor, contentArgs);
      if (rng.insertNode) {
        content += '<span id="__caret">_</span>';
        if (rng.startContainer === doc && rng.endContainer === doc) {
          doc.body.innerHTML = content;
        } else {
          rng.deleteContents();
          if (doc.body.childNodes.length === 0) {
            doc.body.innerHTML = content;
          } else {
            if (rng.createContextualFragment) {
              rng.insertNode(rng.createContextualFragment(content));
            } else {
              frag = doc.createDocumentFragment();
              temp = doc.createElement('div');
              frag.appendChild(temp);
              temp.outerHTML = content;
              rng.insertNode(frag);
            }
          }
        }
        caretNode = editor.dom.get('__caret');
        rng = doc.createRange();
        rng.setStartBefore(caretNode);
        rng.setEndBefore(caretNode);
        editor.selection.setRng(rng);
        editor.dom.remove('__caret');
        try {
          editor.selection.setRng(rng);
        } catch (ex) {
        }
      } else {
        var anyRng = rng;
        if (anyRng.item) {
          doc.execCommand('Delete', false, null);
          anyRng = editor.selection.getRng();
        }
        if (/^\s+/.test(content)) {
          anyRng.pasteHTML('<span id="__mce_tmp">_</span>' + content);
          editor.dom.remove('__mce_tmp');
        } else {
          anyRng.pasteHTML(content);
        }
      }
      if (!contentArgs.no_events) {
        editor.fire('SetContent', contentArgs);
      }
    };
    var SetSelectionContent = { setContent: setContent };

    var getEndpointElement = function (root, rng, start, real, resolve) {
      var container = start ? rng.startContainer : rng.endContainer;
      var offset = start ? rng.startOffset : rng.endOffset;
      return Option.from(container).map(Element.fromDom).map(function (elm) {
        return !real || !rng.collapsed ? child(elm, resolve(elm, offset)).getOr(elm) : elm;
      }).bind(function (elm) {
        return isElement(elm) ? Option.some(elm) : parent(elm);
      }).map(function (elm) {
        return elm.dom();
      }).getOr(root);
    };
    var getStart$2 = function (root, rng, real) {
      return getEndpointElement(root, rng, true, real, function (elm, offset) {
        return Math.min(childNodesCount(elm), offset);
      });
    };
    var getEnd = function (root, rng, real) {
      return getEndpointElement(root, rng, false, real, function (elm, offset) {
        return offset > 0 ? offset - 1 : offset;
      });
    };
    var skipEmptyTextNodes = function (node, forwards) {
      var orig = node;
      while (node && NodeType.isText(node) && node.length === 0) {
        node = forwards ? node.nextSibling : node.previousSibling;
      }
      return node || orig;
    };
    var getNode$1 = function (root, rng) {
      var elm, startContainer, endContainer, startOffset, endOffset;
      if (!rng) {
        return root;
      }
      startContainer = rng.startContainer;
      endContainer = rng.endContainer;
      startOffset = rng.startOffset;
      endOffset = rng.endOffset;
      elm = rng.commonAncestorContainer;
      if (!rng.collapsed) {
        if (startContainer === endContainer) {
          if (endOffset - startOffset < 2) {
            if (startContainer.hasChildNodes()) {
              elm = startContainer.childNodes[startOffset];
            }
          }
        }
        if (startContainer.nodeType === 3 && endContainer.nodeType === 3) {
          if (startContainer.length === startOffset) {
            startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
          } else {
            startContainer = startContainer.parentNode;
          }
          if (endOffset === 0) {
            endContainer = skipEmptyTextNodes(endContainer.previousSibling, false);
          } else {
            endContainer = endContainer.parentNode;
          }
          if (startContainer && startContainer === endContainer) {
            return startContainer;
          }
        }
      }
      if (elm && elm.nodeType === 3) {
        return elm.parentNode;
      }
      return elm;
    };
    var getSelectedBlocks = function (dom, rng, startElm, endElm) {
      var node, root;
      var selectedBlocks = [];
      root = dom.getRoot();
      startElm = dom.getParent(startElm || getStart$2(root, rng, rng.collapsed), dom.isBlock);
      endElm = dom.getParent(endElm || getEnd(root, rng, rng.collapsed), dom.isBlock);
      if (startElm && startElm !== root) {
        selectedBlocks.push(startElm);
      }
      if (startElm && endElm && startElm !== endElm) {
        node = startElm;
        var walker = new TreeWalker(startElm, root);
        while ((node = walker.next()) && node !== endElm) {
          if (dom.isBlock(node)) {
            selectedBlocks.push(node);
          }
        }
      }
      if (endElm && startElm !== endElm && endElm !== root) {
        selectedBlocks.push(endElm);
      }
      return selectedBlocks;
    };
    var select$1 = function (dom, node, content) {
      return Option.from(node).map(function (node) {
        var idx = dom.nodeIndex(node);
        var rng = dom.createRng();
        rng.setStart(node.parentNode, idx);
        rng.setEnd(node.parentNode, idx + 1);
        if (content) {
          moveEndPoint$1(dom, rng, node, true);
          moveEndPoint$1(dom, rng, node, false);
        }
        return rng;
      });
    };

    var each$j = Tools.each;
    var isNativeIeSelection = function (rng) {
      return !!rng.select;
    };
    var isAttachedToDom = function (node) {
      return !!(node && node.ownerDocument) && contains$3(Element.fromDom(node.ownerDocument), Element.fromDom(node));
    };
    var isValidRange = function (rng) {
      if (!rng) {
        return false;
      } else if (isNativeIeSelection(rng)) {
        return true;
      } else {
        return isAttachedToDom(rng.startContainer) && isAttachedToDom(rng.endContainer);
      }
    };
    var Selection$1 = function (dom, win, serializer, editor) {
      var bookmarkManager, controlSelection;
      var selectedRange, explicitRange, selectorChangedData;
      var setCursorLocation = function (node, offset) {
        var rng = dom.createRng();
        if (!node) {
          moveEndPoint$1(dom, rng, editor.getBody(), true);
          setRng(rng);
        } else {
          rng.setStart(node, offset);
          rng.setEnd(node, offset);
          setRng(rng);
          collapse(false);
        }
      };
      var getContent = function (args) {
        return GetSelectionContent.getContent(editor, args);
      };
      var setContent = function (content, args) {
        return SetSelectionContent.setContent(editor, content, args);
      };
      var getStart = function (real) {
        return getStart$2(editor.getBody(), getRng(), real);
      };
      var getEnd$1 = function (real) {
        return getEnd(editor.getBody(), getRng(), real);
      };
      var getBookmark = function (type, normalized) {
        return bookmarkManager.getBookmark(type, normalized);
      };
      var moveToBookmark = function (bookmark) {
        return bookmarkManager.moveToBookmark(bookmark);
      };
      var select = function (node, content) {
        select$1(dom, node, content).each(setRng);
        return node;
      };
      var isCollapsed = function () {
        var rng = getRng(), sel = getSel();
        if (!rng || rng.item) {
          return false;
        }
        if (rng.compareEndPoints) {
          return rng.compareEndPoints('StartToEnd', rng) === 0;
        }
        return !sel || rng.collapsed;
      };
      var collapse = function (toStart) {
        var rng = getRng();
        rng.collapse(!!toStart);
        setRng(rng);
      };
      var getSel = function () {
        return win.getSelection ? win.getSelection() : win.document.selection;
      };
      var getRng = function () {
        var selection, rng, elm, doc;
        var tryCompareBoundaryPoints = function (how, sourceRange, destinationRange) {
          try {
            return sourceRange.compareBoundaryPoints(how, destinationRange);
          } catch (ex) {
            return -1;
          }
        };
        if (!win) {
          return null;
        }
        doc = win.document;
        if (typeof doc === 'undefined' || doc === null) {
          return null;
        }
        if (editor.bookmark !== undefined && EditorFocus.hasFocus(editor) === false) {
          var bookmark = SelectionBookmark.getRng(editor);
          if (bookmark.isSome()) {
            return bookmark.map(function (r) {
              return EventProcessRanges.processRanges(editor, [r])[0];
            }).getOr(doc.createRange());
          }
        }
        try {
          if ((selection = getSel()) && !NodeType.isRestrictedNode(selection.anchorNode)) {
            if (selection.rangeCount > 0) {
              rng = selection.getRangeAt(0);
            } else {
              rng = selection.createRange ? selection.createRange() : doc.createRange();
            }
          }
        } catch (ex) {
        }
        rng = EventProcessRanges.processRanges(editor, [rng])[0];
        if (!rng) {
          rng = doc.createRange ? doc.createRange() : doc.body.createTextRange();
        }
        if (rng.setStart && rng.startContainer.nodeType === 9 && rng.collapsed) {
          elm = dom.getRoot();
          rng.setStart(elm, 0);
          rng.setEnd(elm, 0);
        }
        if (selectedRange && explicitRange) {
          if (tryCompareBoundaryPoints(rng.START_TO_START, rng, selectedRange) === 0 && tryCompareBoundaryPoints(rng.END_TO_END, rng, selectedRange) === 0) {
            rng = explicitRange;
          } else {
            selectedRange = null;
            explicitRange = null;
          }
        }
        return rng;
      };
      var setRng = function (rng, forward) {
        var sel, node, evt;
        if (!isValidRange(rng)) {
          return;
        }
        var ieRange = isNativeIeSelection(rng) ? rng : null;
        if (ieRange) {
          explicitRange = null;
          try {
            ieRange.select();
          } catch (ex) {
          }
          return;
        }
        sel = getSel();
        evt = editor.fire('SetSelectionRange', {
          range: rng,
          forward: forward
        });
        rng = evt.range;
        if (sel) {
          explicitRange = rng;
          try {
            sel.removeAllRanges();
            sel.addRange(rng);
          } catch (ex) {
          }
          if (forward === false && sel.extend) {
            sel.collapse(rng.endContainer, rng.endOffset);
            sel.extend(rng.startContainer, rng.startOffset);
          }
          selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
        }
        if (!rng.collapsed && rng.startContainer === rng.endContainer && sel.setBaseAndExtent && !Env.ie) {
          if (rng.endOffset - rng.startOffset < 2) {
            if (rng.startContainer.hasChildNodes()) {
              node = rng.startContainer.childNodes[rng.startOffset];
              if (node && node.tagName === 'IMG') {
                sel.setBaseAndExtent(rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset);
                if (sel.anchorNode !== rng.startContainer || sel.focusNode !== rng.endContainer) {
                  sel.setBaseAndExtent(node, 0, node, 1);
                }
              }
            }
          }
        }
        editor.fire('AfterSetSelectionRange', {
          range: rng,
          forward: forward
        });
      };
      var setNode = function (elm) {
        setContent(dom.getOuterHTML(elm));
        return elm;
      };
      var getNode = function () {
        return getNode$1(editor.getBody(), getRng());
      };
      var getSelectedBlocks$1 = function (startElm, endElm) {
        return getSelectedBlocks(dom, getRng(), startElm, endElm);
      };
      var isForward = function () {
        var sel = getSel();
        var anchorRange, focusRange;
        if (!sel || !sel.anchorNode || !sel.focusNode) {
          return true;
        }
        anchorRange = dom.createRng();
        anchorRange.setStart(sel.anchorNode, sel.anchorOffset);
        anchorRange.collapse(true);
        focusRange = dom.createRng();
        focusRange.setStart(sel.focusNode, sel.focusOffset);
        focusRange.collapse(true);
        return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
      };
      var normalize = function () {
        var rng = getRng();
        var sel = getSel();
        if (!MultiRange.hasMultipleRanges(sel) && hasAnyRanges(editor)) {
          var normRng = NormalizeRange.normalize(dom, rng);
          normRng.each(function (normRng) {
            setRng(normRng, isForward());
          });
          return normRng.getOr(rng);
        }
        return rng;
      };
      var selectorChanged = function (selector, callback) {
        var currentSelectors;
        if (!selectorChangedData) {
          selectorChangedData = {};
          currentSelectors = {};
          editor.on('NodeChange', function (e) {
            var node = e.element, parents = dom.getParents(node, null, dom.getRoot()), matchedSelectors = {};
            each$j(selectorChangedData, function (callbacks, selector) {
              each$j(parents, function (node) {
                if (dom.is(node, selector)) {
                  if (!currentSelectors[selector]) {
                    each$j(callbacks, function (callback) {
                      callback(true, {
                        node: node,
                        selector: selector,
                        parents: parents
                      });
                    });
                    currentSelectors[selector] = callbacks;
                  }
                  matchedSelectors[selector] = callbacks;
                  return false;
                }
              });
            });
            each$j(currentSelectors, function (callbacks, selector) {
              if (!matchedSelectors[selector]) {
                delete currentSelectors[selector];
                each$j(callbacks, function (callback) {
                  callback(false, {
                    node: node,
                    selector: selector,
                    parents: parents
                  });
                });
              }
            });
          });
        }
        if (!selectorChangedData[selector]) {
          selectorChangedData[selector] = [];
        }
        selectorChangedData[selector].push(callback);
        return exports;
      };
      var getScrollContainer = function () {
        var scrollContainer;
        var node = dom.getRoot();
        while (node && node.nodeName !== 'BODY') {
          if (node.scrollHeight > node.clientHeight) {
            scrollContainer = node;
            break;
          }
          node = node.parentNode;
        }
        return scrollContainer;
      };
      var scrollIntoView = function (elm, alignToTop) {
        return ScrollIntoView.scrollElementIntoView(editor, elm, alignToTop);
      };
      var placeCaretAt = function (clientX, clientY) {
        return setRng(CaretRangeFromPoint.fromPoint(clientX, clientY, editor.getDoc()));
      };
      var getBoundingClientRect = function () {
        var rng = getRng();
        return rng.collapsed ? CaretPosition$1.fromRangeStart(rng).getClientRects()[0] : rng.getBoundingClientRect();
      };
      var destroy = function () {
        win = selectedRange = explicitRange = null;
        controlSelection.destroy();
      };
      var exports = {
        bookmarkManager: null,
        controlSelection: null,
        dom: dom,
        win: win,
        serializer: serializer,
        editor: editor,
        collapse: collapse,
        setCursorLocation: setCursorLocation,
        getContent: getContent,
        setContent: setContent,
        getBookmark: getBookmark,
        moveToBookmark: moveToBookmark,
        select: select,
        isCollapsed: isCollapsed,
        isForward: isForward,
        setNode: setNode,
        getNode: getNode,
        getSel: getSel,
        setRng: setRng,
        getRng: getRng,
        getStart: getStart,
        getEnd: getEnd$1,
        getSelectedBlocks: getSelectedBlocks$1,
        normalize: normalize,
        selectorChanged: selectorChanged,
        getScrollContainer: getScrollContainer,
        scrollIntoView: scrollIntoView,
        placeCaretAt: placeCaretAt,
        getBoundingClientRect: getBoundingClientRect,
        destroy: destroy
      };
      bookmarkManager = BookmarkManager$1(exports);
      controlSelection = ControlSelection(exports, editor);
      exports.bookmarkManager = bookmarkManager;
      exports.controlSelection = controlSelection;
      return exports;
    };

    var BreakType;
    (function (BreakType) {
      BreakType[BreakType['Br'] = 0] = 'Br';
      BreakType[BreakType['Block'] = 1] = 'Block';
      BreakType[BreakType['Wrap'] = 2] = 'Wrap';
      BreakType[BreakType['Eol'] = 3] = 'Eol';
    }(BreakType || (BreakType = {})));
    var flip = function (direction, positions) {
      return direction === HDirection.Backwards ? positions.reverse() : positions;
    };
    var walk$3 = function (direction, caretWalker, pos) {
      return direction === HDirection.Forwards ? caretWalker.next(pos) : caretWalker.prev(pos);
    };
    var getBreakType = function (scope, direction, currentPos, nextPos) {
      if (NodeType.isBr(nextPos.getNode(direction === HDirection.Forwards))) {
        return BreakType.Br;
      } else if (isInSameBlock(currentPos, nextPos) === false) {
        return BreakType.Block;
      } else {
        return BreakType.Wrap;
      }
    };
    var getPositionsUntil = function (predicate, direction, scope, start) {
      var caretWalker = CaretWalker(scope);
      var currentPos = start, nextPos;
      var positions = [];
      while (currentPos) {
        nextPos = walk$3(direction, caretWalker, currentPos);
        if (!nextPos) {
          break;
        }
        if (NodeType.isBr(nextPos.getNode(false))) {
          if (direction === HDirection.Forwards) {
            return {
              positions: flip(direction, positions).concat([nextPos]),
              breakType: BreakType.Br,
              breakAt: Option.some(nextPos)
            };
          } else {
            return {
              positions: flip(direction, positions),
              breakType: BreakType.Br,
              breakAt: Option.some(nextPos)
            };
          }
        }
        if (!nextPos.isVisible()) {
          currentPos = nextPos;
          continue;
        }
        if (predicate(currentPos, nextPos)) {
          var breakType = getBreakType(scope, direction, currentPos, nextPos);
          return {
            positions: flip(direction, positions),
            breakType: breakType,
            breakAt: Option.some(nextPos)
          };
        }
        positions.push(nextPos);
        currentPos = nextPos;
      }
      return {
        positions: flip(direction, positions),
        breakType: BreakType.Eol,
        breakAt: Option.none()
      };
    };
    var getAdjacentLinePositions = function (direction, getPositionsUntilBreak, scope, start) {
      return getPositionsUntilBreak(scope, start).breakAt.map(function (pos) {
        var positions = getPositionsUntilBreak(scope, pos).positions;
        return direction === HDirection.Backwards ? positions.concat(pos) : [pos].concat(positions);
      }).getOr([]);
    };
    var findClosestHorizontalPositionFromPoint = function (positions, x) {
      return foldl(positions, function (acc, newPos) {
        return acc.fold(function () {
          return Option.some(newPos);
        }, function (lastPos) {
          return lift2(head(lastPos.getClientRects()), head(newPos.getClientRects()), function (lastRect, newRect) {
            var lastDist = Math.abs(x - lastRect.left);
            var newDist = Math.abs(x - newRect.left);
            return newDist <= lastDist ? newPos : lastPos;
          }).or(acc);
        });
      }, Option.none());
    };
    var findClosestHorizontalPosition = function (positions, pos) {
      return head(pos.getClientRects()).bind(function (targetRect) {
        return findClosestHorizontalPositionFromPoint(positions, targetRect.left);
      });
    };
    var getPositionsUntilPreviousLine = curry(getPositionsUntil, CaretPosition.isAbove, -1);
    var getPositionsUntilNextLine = curry(getPositionsUntil, CaretPosition.isBelow, 1);
    var isAtFirstLine = function (scope, pos) {
      return getPositionsUntilPreviousLine(scope, pos).breakAt.isNone();
    };
    var isAtLastLine = function (scope, pos) {
      return getPositionsUntilNextLine(scope, pos).breakAt.isNone();
    };
    var getPositionsAbove = curry(getAdjacentLinePositions, -1, getPositionsUntilPreviousLine);
    var getPositionsBelow = curry(getAdjacentLinePositions, 1, getPositionsUntilNextLine);
    var getFirstLinePositions = function (scope) {
      return CaretFinder.firstPositionIn(scope).map(function (pos) {
        return [pos].concat(getPositionsUntilNextLine(scope, pos).positions);
      }).getOr([]);
    };
    var getLastLinePositions = function (scope) {
      return CaretFinder.lastPositionIn(scope).map(function (pos) {
        return getPositionsUntilPreviousLine(scope, pos).positions.concat(pos);
      }).getOr([]);
    };

    var isContentEditableFalse$b = NodeType.isContentEditableFalse;
    var getSelectedNode$1 = getSelectedNode;
    var moveToCeFalseHorizontally = function (direction, editor, getNextPosFn, range) {
      var forwards = direction === HDirection.Forwards;
      var isBeforeContentEditableFalseFn = forwards ? isBeforeContentEditableFalse : isAfterContentEditableFalse;
      if (!range.collapsed) {
        var node = getSelectedNode$1(range);
        if (isContentEditableFalse$b(node)) {
          return showCaret(direction, editor, node, direction === HDirection.Backwards, true);
        }
      }
      var rangeIsInContainerBlock = isRangeInCaretContainerBlock(range);
      var caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
      if (isBeforeContentEditableFalseFn(caretPosition)) {
        return selectNode(editor, caretPosition.getNode(!forwards));
      }
      var nextCaretPosition = InlineUtils.normalizePosition(forwards, getNextPosFn(caretPosition));
      if (!nextCaretPosition) {
        if (rangeIsInContainerBlock) {
          return range;
        }
        return null;
      }
      if (isBeforeContentEditableFalseFn(nextCaretPosition)) {
        return showCaret(direction, editor, nextCaretPosition.getNode(!forwards), forwards, true);
      }
      var peekCaretPosition = getNextPosFn(nextCaretPosition);
      if (peekCaretPosition && isBeforeContentEditableFalseFn(peekCaretPosition)) {
        if (isMoveInsideSameBlock(nextCaretPosition, peekCaretPosition)) {
          return showCaret(direction, editor, peekCaretPosition.getNode(!forwards), forwards, true);
        }
      }
      if (rangeIsInContainerBlock) {
        return renderRangeCaret(editor, nextCaretPosition.toRange(), true);
      }
      return null;
    };
    var moveToCeFalseVertically = function (direction, editor, walkerFn, range) {
      var caretPosition, linePositions, nextLinePositions;
      var closestNextLineRect, caretClientRect, clientX;
      var dist1, dist2, contentEditableFalseNode;
      contentEditableFalseNode = getSelectedNode$1(range);
      caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
      linePositions = walkerFn(editor.getBody(), isAboveLine(1), caretPosition);
      nextLinePositions = filter(linePositions, isLine(1));
      caretClientRect = ArrUtils.last(caretPosition.getClientRects());
      if (isBeforeContentEditableFalse(caretPosition) || isBeforeTable(caretPosition)) {
        contentEditableFalseNode = caretPosition.getNode();
      }
      if (isAfterContentEditableFalse(caretPosition) || isAfterTable(caretPosition)) {
        contentEditableFalseNode = caretPosition.getNode(true);
      }
      if (!caretClientRect) {
        return null;
      }
      clientX = caretClientRect.left;
      closestNextLineRect = findClosestClientRect(nextLinePositions, clientX);
      if (closestNextLineRect) {
        if (isContentEditableFalse$b(closestNextLineRect.node)) {
          dist1 = Math.abs(clientX - closestNextLineRect.left);
          dist2 = Math.abs(clientX - closestNextLineRect.right);
          return showCaret(direction, editor, closestNextLineRect.node, dist1 < dist2, true);
        }
      }
      if (contentEditableFalseNode) {
        var caretPositions = positionsUntil(direction, editor.getBody(), isAboveLine(1), contentEditableFalseNode);
        closestNextLineRect = findClosestClientRect(filter(caretPositions, isLine(1)), clientX);
        if (closestNextLineRect) {
          return renderRangeCaret(editor, closestNextLineRect.position.toRange(), true);
        }
        closestNextLineRect = ArrUtils.last(filter(caretPositions, isLine(0)));
        if (closestNextLineRect) {
          return renderRangeCaret(editor, closestNextLineRect.position.toRange(), true);
        }
      }
    };
    var createTextBlock = function (editor) {
      var textBlock = editor.dom.create(Settings.getForcedRootBlock(editor));
      if (!Env.ie || Env.ie >= 11) {
        textBlock.innerHTML = '<br data-mce-bogus="1">';
      }
      return textBlock;
    };
    var exitPreBlock = function (editor, direction, range) {
      var pre, caretPos, newBlock;
      var caretWalker = CaretWalker(editor.getBody());
      var getNextVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.next);
      var getPrevVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.prev);
      if (range.collapsed && editor.settings.forced_root_block) {
        pre = editor.dom.getParent(range.startContainer, 'PRE');
        if (!pre) {
          return;
        }
        if (direction === 1) {
          caretPos = getNextVisualCaretPosition(CaretPosition$1.fromRangeStart(range));
        } else {
          caretPos = getPrevVisualCaretPosition(CaretPosition$1.fromRangeStart(range));
        }
        if (!caretPos) {
          newBlock = createTextBlock(editor);
          if (direction === 1) {
            editor.$(pre).after(newBlock);
          } else {
            editor.$(pre).before(newBlock);
          }
          editor.selection.select(newBlock, true);
          editor.selection.collapse();
        }
      }
    };
    var getHorizontalRange = function (editor, forward) {
      var caretWalker = CaretWalker(editor.getBody());
      var getNextVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.next);
      var getPrevVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.prev);
      var newRange;
      var direction = forward ? HDirection.Forwards : HDirection.Backwards;
      var getNextPosFn = forward ? getNextVisualCaretPosition : getPrevVisualCaretPosition;
      var range = editor.selection.getRng();
      newRange = moveToCeFalseHorizontally(direction, editor, getNextPosFn, range);
      if (newRange) {
        return newRange;
      }
      newRange = exitPreBlock(editor, direction, range);
      if (newRange) {
        return newRange;
      }
      return null;
    };
    var getVerticalRange = function (editor, down) {
      var newRange;
      var direction = down ? 1 : -1;
      var walkerFn = down ? downUntil : upUntil;
      var range = editor.selection.getRng();
      newRange = moveToCeFalseVertically(direction, editor, walkerFn, range);
      if (newRange) {
        return newRange;
      }
      newRange = exitPreBlock(editor, direction, range);
      if (newRange) {
        return newRange;
      }
      return null;
    };
    var moveH = function (editor, forward) {
      return function () {
        var newRng = getHorizontalRange(editor, forward);
        if (newRng) {
          moveToRange(editor, newRng);
          return true;
        } else {
          return false;
        }
      };
    };
    var moveV = function (editor, down) {
      return function () {
        var newRng = getVerticalRange(editor, down);
        if (newRng) {
          moveToRange(editor, newRng);
          return true;
        } else {
          return false;
        }
      };
    };
    var isCefPosition = function (forward) {
      return function (pos) {
        return forward ? isAfterContentEditableFalse(pos) : isBeforeContentEditableFalse(pos);
      };
    };
    var moveToLineEndPoint = function (editor, forward) {
      return function () {
        var from = forward ? CaretPosition$1.fromRangeEnd(editor.selection.getRng()) : CaretPosition$1.fromRangeStart(editor.selection.getRng());
        var result = forward ? getPositionsUntilNextLine(editor.getBody(), from) : getPositionsUntilPreviousLine(editor.getBody(), from);
        var to = forward ? last(result.positions) : head(result.positions);
        return to.filter(isCefPosition(forward)).fold(constant(false), function (pos) {
          editor.selection.setRng(pos.toRange());
          return true;
        });
      };
    };

    var deflate = function (rect, delta) {
      return {
        left: rect.left - delta,
        top: rect.top - delta,
        right: rect.right + delta * 2,
        bottom: rect.bottom + delta * 2,
        width: rect.width + delta,
        height: rect.height + delta
      };
    };
    var getCorners = function (getYAxisValue, tds) {
      return bind(tds, function (td) {
        var rect = deflate(clone$1(td.getBoundingClientRect()), -1);
        return [
          {
            x: rect.left,
            y: getYAxisValue(rect),
            cell: td
          },
          {
            x: rect.right,
            y: getYAxisValue(rect),
            cell: td
          }
        ];
      });
    };
    var findClosestCorner = function (corners, x, y) {
      return foldl(corners, function (acc, newCorner) {
        return acc.fold(function () {
          return Option.some(newCorner);
        }, function (oldCorner) {
          var oldDist = Math.sqrt(Math.abs(oldCorner.x - x) + Math.abs(oldCorner.y - y));
          var newDist = Math.sqrt(Math.abs(newCorner.x - x) + Math.abs(newCorner.y - y));
          return Option.some(newDist < oldDist ? newCorner : oldCorner);
        });
      }, Option.none());
    };
    var getClosestCell$1 = function (getYAxisValue, isTargetCorner, table, x, y) {
      var cells = descendants$1(Element.fromDom(table), 'td,th,caption').map(function (e) {
        return e.dom();
      });
      var corners = filter(getCorners(getYAxisValue, cells), function (corner) {
        return isTargetCorner(corner, y);
      });
      return findClosestCorner(corners, x, y).map(function (corner) {
        return corner.cell;
      });
    };
    var getBottomValue = function (rect) {
      return rect.bottom;
    };
    var getTopValue = function (rect) {
      return rect.top;
    };
    var isAbove$1 = function (corner, y) {
      return corner.y < y;
    };
    var isBelow$1 = function (corner, y) {
      return corner.y > y;
    };
    var getClosestCellAbove = curry(getClosestCell$1, getBottomValue, isAbove$1);
    var getClosestCellBelow = curry(getClosestCell$1, getTopValue, isBelow$1);
    var findClosestPositionInAboveCell = function (table, pos) {
      return head(pos.getClientRects()).bind(function (rect) {
        return getClosestCellAbove(table, rect.left, rect.top);
      }).bind(function (cell) {
        return findClosestHorizontalPosition(getLastLinePositions(cell), pos);
      });
    };
    var findClosestPositionInBelowCell = function (table, pos) {
      return last(pos.getClientRects()).bind(function (rect) {
        return getClosestCellBelow(table, rect.left, rect.top);
      }).bind(function (cell) {
        return findClosestHorizontalPosition(getFirstLinePositions(cell), pos);
      });
    };

    var hasNextBreak = function (getPositionsUntil, scope, lineInfo) {
      return lineInfo.breakAt.map(function (breakPos) {
        return getPositionsUntil(scope, breakPos).breakAt.isSome();
      }).getOr(false);
    };
    var startsWithWrapBreak = function (lineInfo) {
      return lineInfo.breakType === BreakType.Wrap && lineInfo.positions.length === 0;
    };
    var startsWithBrBreak = function (lineInfo) {
      return lineInfo.breakType === BreakType.Br && lineInfo.positions.length === 1;
    };
    var isAtTableCellLine = function (getPositionsUntil, scope, pos) {
      var lineInfo = getPositionsUntil(scope, pos);
      if (startsWithWrapBreak(lineInfo) || !NodeType.isBr(pos.getNode()) && startsWithBrBreak(lineInfo)) {
        return !hasNextBreak(getPositionsUntil, scope, lineInfo);
      } else {
        return lineInfo.breakAt.isNone();
      }
    };
    var isAtFirstTableCellLine = curry(isAtTableCellLine, getPositionsUntilPreviousLine);
    var isAtLastTableCellLine = curry(isAtTableCellLine, getPositionsUntilNextLine);
    var isCaretAtStartOrEndOfTable = function (forward, rng, table) {
      var caretPos = CaretPosition$1.fromRangeStart(rng);
      return CaretFinder.positionIn(!forward, table).map(function (pos) {
        return pos.isEqual(caretPos);
      }).getOr(false);
    };
    var navigateHorizontally = function (editor, forward, table, td) {
      var rng = editor.selection.getRng();
      var direction = forward ? 1 : -1;
      if (isFakeCaretTableBrowser() && isCaretAtStartOrEndOfTable(forward, rng, table)) {
        var newRng = showCaret(direction, editor, table, !forward, true);
        moveToRange(editor, newRng);
        return true;
      }
      return false;
    };
    var getClosestAbovePosition = function (root, table, start) {
      return findClosestPositionInAboveCell(table, start).orThunk(function () {
        return head(start.getClientRects()).bind(function (rect) {
          return findClosestHorizontalPositionFromPoint(getPositionsAbove(root, CaretPosition$1.before(table)), rect.left);
        });
      }).getOr(CaretPosition$1.before(table));
    };
    var getClosestBelowPosition = function (root, table, start) {
      return findClosestPositionInBelowCell(table, start).orThunk(function () {
        return head(start.getClientRects()).bind(function (rect) {
          return findClosestHorizontalPositionFromPoint(getPositionsBelow(root, CaretPosition$1.after(table)), rect.left);
        });
      }).getOr(CaretPosition$1.after(table));
    };
    var getTable = function (previous, pos) {
      var node = pos.getNode(previous);
      return NodeType.isElement(node) && node.nodeName === 'TABLE' ? Option.some(node) : Option.none();
    };
    var renderBlock = function (down, editor, table, pos) {
      var forcedRootBlock = Settings.getForcedRootBlock(editor);
      if (forcedRootBlock) {
        editor.undoManager.transact(function () {
          var element = Element.fromTag(forcedRootBlock);
          setAll(element, Settings.getForcedRootBlockAttrs(editor));
          append(element, Element.fromTag('br'));
          if (down) {
            after(Element.fromDom(table), element);
          } else {
            before(Element.fromDom(table), element);
          }
          var rng = editor.dom.createRng();
          rng.setStart(element.dom(), 0);
          rng.setEnd(element.dom(), 0);
          moveToRange(editor, rng);
        });
      } else {
        moveToRange(editor, pos.toRange());
      }
    };
    var moveCaret = function (editor, down, pos) {
      var table = down ? getTable(true, pos) : getTable(false, pos);
      var last = down === false;
      table.fold(function () {
        return moveToRange(editor, pos.toRange());
      }, function (table) {
        return CaretFinder.positionIn(last, editor.getBody()).filter(function (lastPos) {
          return lastPos.isEqual(pos);
        }).fold(function () {
          return moveToRange(editor, pos.toRange());
        }, function (_) {
          return renderBlock(down, editor, table, pos);
        });
      });
    };
    var navigateVertically = function (editor, down, table, td) {
      var rng = editor.selection.getRng();
      var pos = CaretPosition$1.fromRangeStart(rng);
      var root = editor.getBody();
      if (!down && isAtFirstTableCellLine(td, pos)) {
        var newPos = getClosestAbovePosition(root, table, pos);
        moveCaret(editor, down, newPos);
        return true;
      } else if (down && isAtLastTableCellLine(td, pos)) {
        var newPos = getClosestBelowPosition(root, table, pos);
        moveCaret(editor, down, newPos);
        return true;
      } else {
        return false;
      }
    };
    var moveH$1 = function (editor, forward) {
      return function () {
        return Option.from(editor.dom.getParent(editor.selection.getNode(), 'td,th')).bind(function (td) {
          return Option.from(editor.dom.getParent(td, 'table')).map(function (table) {
            return navigateHorizontally(editor, forward, table);
          });
        }).getOr(false);
      };
    };
    var moveV$1 = function (editor, forward) {
      return function () {
        return Option.from(editor.dom.getParent(editor.selection.getNode(), 'td,th')).bind(function (td) {
          return Option.from(editor.dom.getParent(td, 'table')).map(function (table) {
            return navigateVertically(editor, forward, table, td);
          });
        }).getOr(false);
      };
    };

    var isTarget = function (node) {
      return contains(['figcaption'], name(node));
    };
    var rangeBefore = function (target) {
      var rng = domGlobals.document.createRange();
      rng.setStartBefore(target.dom());
      rng.setEndBefore(target.dom());
      return rng;
    };
    var insertElement = function (root, elm, forward) {
      if (forward) {
        append(root, elm);
      } else {
        prepend(root, elm);
      }
    };
    var insertBr = function (root, forward) {
      var br = Element.fromTag('br');
      insertElement(root, br, forward);
      return rangeBefore(br);
    };
    var insertBlock$1 = function (root, forward, blockName, attrs) {
      var block = Element.fromTag(blockName);
      var br = Element.fromTag('br');
      setAll(block, attrs);
      append(block, br);
      insertElement(root, block, forward);
      return rangeBefore(br);
    };
    var insertEmptyLine = function (root, rootBlockName, attrs, forward) {
      if (rootBlockName === '') {
        return insertBr(root, forward);
      } else {
        return insertBlock$1(root, forward, rootBlockName, attrs);
      }
    };
    var getClosestTargetBlock = function (pos, root) {
      var isRoot = curry(eq, root);
      return closest(Element.fromDom(pos.container()), isBlock, isRoot).filter(isTarget);
    };
    var isAtFirstOrLastLine = function (root, forward, pos) {
      return forward ? isAtLastLine(root.dom(), pos) : isAtFirstLine(root.dom(), pos);
    };
    var moveCaretToNewEmptyLine = function (editor, forward) {
      var root = Element.fromDom(editor.getBody());
      var pos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
      var rootBlock = Settings.getForcedRootBlock(editor);
      var rootBlockAttrs = Settings.getForcedRootBlockAttrs(editor);
      return getClosestTargetBlock(pos, root).exists(function () {
        if (isAtFirstOrLastLine(root, forward, pos)) {
          var rng = insertEmptyLine(root, rootBlock, rootBlockAttrs, forward);
          editor.selection.setRng(rng);
          return true;
        } else {
          return false;
        }
      });
    };
    var moveV$2 = function (editor, forward) {
      return function () {
        if (editor.selection.isCollapsed()) {
          return moveCaretToNewEmptyLine(editor, forward);
        } else {
          return false;
        }
      };
    };

    var defaultPatterns = function (patterns) {
      return map(patterns, function (pattern) {
        return merge({
          shiftKey: false,
          altKey: false,
          ctrlKey: false,
          metaKey: false,
          keyCode: 0,
          action: noop
        }, pattern);
      });
    };
    var matchesEvent = function (pattern, evt) {
      return evt.keyCode === pattern.keyCode && evt.shiftKey === pattern.shiftKey && evt.altKey === pattern.altKey && evt.ctrlKey === pattern.ctrlKey && evt.metaKey === pattern.metaKey;
    };
    var match$1 = function (patterns, evt) {
      return bind(defaultPatterns(patterns), function (pattern) {
        return matchesEvent(pattern, evt) ? [pattern] : [];
      });
    };
    var action = function (f) {
      var x = [];
      for (var _i = 1; _i < arguments.length; _i++) {
        x[_i - 1] = arguments[_i];
      }
      var args = Array.prototype.slice.call(arguments, 1);
      return function () {
        return f.apply(null, args);
      };
    };
    var execute = function (patterns, evt) {
      return find(match$1(patterns, evt), function (pattern) {
        return pattern.action();
      });
    };
    var MatchKeys = {
      match: match$1,
      action: action,
      execute: execute
    };

    var executeKeydownOverride = function (editor, caret, evt) {
      var os = PlatformDetection$1.detect().os;
      MatchKeys.execute([
        {
          keyCode: VK.RIGHT,
          action: moveH(editor, true)
        },
        {
          keyCode: VK.LEFT,
          action: moveH(editor, false)
        },
        {
          keyCode: VK.UP,
          action: moveV(editor, false)
        },
        {
          keyCode: VK.DOWN,
          action: moveV(editor, true)
        },
        {
          keyCode: VK.RIGHT,
          action: moveH$1(editor, true)
        },
        {
          keyCode: VK.LEFT,
          action: moveH$1(editor, false)
        },
        {
          keyCode: VK.UP,
          action: moveV$1(editor, false)
        },
        {
          keyCode: VK.DOWN,
          action: moveV$1(editor, true)
        },
        {
          keyCode: VK.RIGHT,
          action: BoundarySelection.move(editor, caret, true)
        },
        {
          keyCode: VK.LEFT,
          action: BoundarySelection.move(editor, caret, false)
        },
        {
          keyCode: VK.RIGHT,
          ctrlKey: !os.isOSX(),
          altKey: os.isOSX(),
          action: BoundarySelection.moveNextWord(editor, caret)
        },
        {
          keyCode: VK.LEFT,
          ctrlKey: !os.isOSX(),
          altKey: os.isOSX(),
          action: BoundarySelection.movePrevWord(editor, caret)
        },
        {
          keyCode: VK.UP,
          action: moveV$2(editor, false)
        },
        {
          keyCode: VK.DOWN,
          action: moveV$2(editor, true)
        }
      ], evt).each(function (_) {
        evt.preventDefault();
      });
    };
    var setup$7 = function (editor, caret) {
      editor.on('keydown', function (evt) {
        if (evt.isDefaultPrevented() === false) {
          executeKeydownOverride(editor, caret, evt);
        }
      });
    };
    var ArrowKeys = { setup: setup$7 };

    var executeKeydownOverride$1 = function (editor, caret, evt) {
      MatchKeys.execute([
        {
          keyCode: VK.BACKSPACE,
          action: MatchKeys.action(CefDelete.backspaceDelete, editor, false)
        },
        {
          keyCode: VK.DELETE,
          action: MatchKeys.action(CefDelete.backspaceDelete, editor, true)
        },
        {
          keyCode: VK.BACKSPACE,
          action: MatchKeys.action(CefBoundaryDelete.backspaceDelete, editor, false)
        },
        {
          keyCode: VK.DELETE,
          action: MatchKeys.action(CefBoundaryDelete.backspaceDelete, editor, true)
        },
        {
          keyCode: VK.BACKSPACE,
          action: MatchKeys.action(InlineBoundaryDelete.backspaceDelete, editor, caret, false)
        },
        {
          keyCode: VK.DELETE,
          action: MatchKeys.action(InlineBoundaryDelete.backspaceDelete, editor, caret, true)
        },
        {
          keyCode: VK.BACKSPACE,
          action: MatchKeys.action(TableDelete.backspaceDelete, editor, false)
        },
        {
          keyCode: VK.DELETE,
          action: MatchKeys.action(TableDelete.backspaceDelete, editor, true)
        },
        {
          keyCode: VK.BACKSPACE,
          action: MatchKeys.action(BlockRangeDelete.backspaceDelete, editor, false)
        },
        {
          keyCode: VK.DELETE,
          action: MatchKeys.action(BlockRangeDelete.backspaceDelete, editor, true)
        },
        {
          keyCode: VK.BACKSPACE,
          action: MatchKeys.action(BlockBoundaryDelete.backspaceDelete, editor, false)
        },
        {
          keyCode: VK.DELETE,
          action: MatchKeys.action(BlockBoundaryDelete.backspaceDelete, editor, true)
        },
        {
          keyCode: VK.BACKSPACE,
          action: MatchKeys.action(InlineFormatDelete.backspaceDelete, editor, false)
        },
        {
          keyCode: VK.DELETE,
          action: MatchKeys.action(InlineFormatDelete.backspaceDelete, editor, true)
        }
      ], evt).each(function (_) {
        evt.preventDefault();
      });
    };
    var executeKeyupOverride = function (editor, evt) {
      MatchKeys.execute([
        {
          keyCode: VK.BACKSPACE,
          action: MatchKeys.action(CefDelete.paddEmptyElement, editor)
        },
        {
          keyCode: VK.DELETE,
          action: MatchKeys.action(CefDelete.paddEmptyElement, editor)
        }
      ], evt);
    };
    var setup$8 = function (editor, caret) {
      editor.on('keydown', function (evt) {
        if (evt.isDefaultPrevented() === false) {
          executeKeydownOverride$1(editor, caret, evt);
        }
      });
      editor.on('keyup', function (evt) {
        if (evt.isDefaultPrevented() === false) {
          executeKeyupOverride(editor, evt);
        }
      });
    };
    var DeleteBackspaceKeys = { setup: setup$8 };

    var firstNonWhiteSpaceNodeSibling = function (node) {
      while (node) {
        if (node.nodeType === 1 || node.nodeType === 3 && node.data && /[\r\n\s]/.test(node.data)) {
          return node;
        }
        node = node.nextSibling;
      }
    };
    var moveToCaretPosition = function (editor, root) {
      var walker, node, rng, lastNode = root, tempElm;
      var dom = editor.dom;
      var moveCaretBeforeOnEnterElementsMap = editor.schema.getMoveCaretBeforeOnEnterElements();
      if (!root) {
        return;
      }
      if (/^(LI|DT|DD)$/.test(root.nodeName)) {
        var firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
        if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) {
          root.insertBefore(dom.doc.createTextNode('\xA0'), root.firstChild);
        }
      }
      rng = dom.createRng();
      root.normalize();
      if (root.hasChildNodes()) {
        walker = new TreeWalker(root, root);
        while (node = walker.current()) {
          if (NodeType.isText(node)) {
            rng.setStart(node, 0);
            rng.setEnd(node, 0);
            break;
          }
          if (moveCaretBeforeOnEnterElementsMap[node.nodeName.toLowerCase()]) {
            rng.setStartBefore(node);
            rng.setEndBefore(node);
            break;
          }
          lastNode = node;
          node = walker.next();
        }
        if (!node) {
          rng.setStart(lastNode, 0);
          rng.setEnd(lastNode, 0);
        }
      } else {
        if (NodeType.isBr(root)) {
          if (root.nextSibling && dom.isBlock(root.nextSibling)) {
            rng.setStartBefore(root);
            rng.setEndBefore(root);
          } else {
            rng.setStartAfter(root);
            rng.setEndAfter(root);
          }
        } else {
          rng.setStart(root, 0);
          rng.setEnd(root, 0);
        }
      }
      editor.selection.setRng(rng);
      dom.remove(tempElm);
      editor.selection.scrollIntoView(root);
    };
    var getEditableRoot = function (dom, node) {
      var root = dom.getRoot();
      var parent, editableRoot;
      parent = node;
      while (parent !== root && dom.getContentEditable(parent) !== 'false') {
        if (dom.getContentEditable(parent) === 'true') {
          editableRoot = parent;
        }
        parent = parent.parentNode;
      }
      return parent !== root ? editableRoot : root;
    };
    var getParentBlock$2 = function (editor) {
      return Option.from(editor.dom.getParent(editor.selection.getStart(true), editor.dom.isBlock));
    };
    var getParentBlockName = function (editor) {
      return getParentBlock$2(editor).fold(constant(''), function (parentBlock) {
        return parentBlock.nodeName.toUpperCase();
      });
    };
    var isListItemParentBlock = function (editor) {
      return getParentBlock$2(editor).filter(function (elm) {
        return isListItem(Element.fromDom(elm));
      }).isSome();
    };
    var NewLineUtils = {
      moveToCaretPosition: moveToCaretPosition,
      getEditableRoot: getEditableRoot,
      getParentBlock: getParentBlock$2,
      getParentBlockName: getParentBlockName,
      isListItemParentBlock: isListItemParentBlock
    };

    var hasFirstChild = function (elm, name) {
      return elm.firstChild && elm.firstChild.nodeName === name;
    };
    var hasParent$1 = function (elm, parentName) {
      return elm && elm.parentNode && elm.parentNode.nodeName === parentName;
    };
    var isListBlock = function (elm) {
      return elm && /^(OL|UL|LI)$/.test(elm.nodeName);
    };
    var isNestedList = function (elm) {
      return isListBlock(elm) && isListBlock(elm.parentNode);
    };
    var getContainerBlock = function (containerBlock) {
      var containerBlockParent = containerBlock.parentNode;
      if (/^(LI|DT|DD)$/.test(containerBlockParent.nodeName)) {
        return containerBlockParent;
      }
      return containerBlock;
    };
    var isFirstOrLastLi = function (containerBlock, parentBlock, first) {
      var node = containerBlock[first ? 'firstChild' : 'lastChild'];
      while (node) {
        if (NodeType.isElement(node)) {
          break;
        }
        node = node[first ? 'nextSibling' : 'previousSibling'];
      }
      return node === parentBlock;
    };
    var insert$1 = function (editor, createNewBlock, containerBlock, parentBlock, newBlockName) {
      var dom = editor.dom;
      var rng = editor.selection.getRng();
      if (containerBlock === editor.getBody()) {
        return;
      }
      if (isNestedList(containerBlock)) {
        newBlockName = 'LI';
      }
      var newBlock = newBlockName ? createNewBlock(newBlockName) : dom.create('BR');
      if (isFirstOrLastLi(containerBlock, parentBlock, true) && isFirstOrLastLi(containerBlock, parentBlock, false)) {
        if (hasParent$1(containerBlock, 'LI')) {
          dom.insertAfter(newBlock, getContainerBlock(containerBlock));
        } else {
          dom.replace(newBlock, containerBlock);
        }
      } else if (isFirstOrLastLi(containerBlock, parentBlock, true)) {
        if (hasParent$1(containerBlock, 'LI')) {
          dom.insertAfter(newBlock, getContainerBlock(containerBlock));
          newBlock.appendChild(dom.doc.createTextNode(' '));
          newBlock.appendChild(containerBlock);
        } else {
          containerBlock.parentNode.insertBefore(newBlock, containerBlock);
        }
      } else if (isFirstOrLastLi(containerBlock, parentBlock, false)) {
        dom.insertAfter(newBlock, getContainerBlock(containerBlock));
      } else {
        containerBlock = getContainerBlock(containerBlock);
        var tmpRng = rng.cloneRange();
        tmpRng.setStartAfter(parentBlock);
        tmpRng.setEndAfter(containerBlock);
        var fragment = tmpRng.extractContents();
        if (newBlockName === 'LI' && hasFirstChild(fragment, 'LI')) {
          newBlock = fragment.firstChild;
          dom.insertAfter(fragment, containerBlock);
        } else {
          dom.insertAfter(fragment, containerBlock);
          dom.insertAfter(newBlock, containerBlock);
        }
      }
      dom.remove(parentBlock);
      NewLineUtils.moveToCaretPosition(editor, newBlock);
    };
    var InsertLi = { insert: insert$1 };

    var trimZwsp = function (fragment) {
      each(descendants(Element.fromDom(fragment), isText), function (text) {
        var rawNode = text.dom();
        rawNode.nodeValue = Zwsp.trim(rawNode.nodeValue);
      });
    };
    var isEmptyAnchor = function (dom, elm) {
      return elm && elm.nodeName === 'A' && dom.isEmpty(elm);
    };
    var isTableCell$5 = function (node) {
      return node && /^(TD|TH|CAPTION)$/.test(node.nodeName);
    };
    var emptyBlock = function (elm) {
      elm.innerHTML = '<br data-mce-bogus="1">';
    };
    var containerAndSiblingName = function (container, nodeName) {
      return container.nodeName === nodeName || container.previousSibling && container.previousSibling.nodeName === nodeName;
    };
    var canSplitBlock = function (dom, node) {
      return node && dom.isBlock(node) && !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) && !/^(fixed|absolute)/i.test(node.style.position) && dom.getContentEditable(node) !== 'true';
    };
    var trimInlineElementsOnLeftSideOfBlock = function (dom, nonEmptyElementsMap, block) {
      var node = block;
      var firstChilds = [];
      var i;
      if (!node) {
        return;
      }
      while (node = node.firstChild) {
        if (dom.isBlock(node)) {
          return;
        }
        if (NodeType.isElement(node) && !nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
          firstChilds.push(node);
        }
      }
      i = firstChilds.length;
      while (i--) {
        node = firstChilds[i];
        if (!node.hasChildNodes() || node.firstChild === node.lastChild && node.firstChild.nodeValue === '') {
          dom.remove(node);
        } else {
          if (isEmptyAnchor(dom, node)) {
            dom.remove(node);
          }
        }
      }
    };
    var normalizeZwspOffset = function (start, container, offset) {
      if (NodeType.isText(container) === false) {
        return offset;
      } else if (start) {
        return offset === 1 && container.data.charAt(offset - 1) === Zwsp.ZWSP ? 0 : offset;
      } else {
        return offset === container.data.length - 1 && container.data.charAt(offset) === Zwsp.ZWSP ? container.data.length : offset;
      }
    };
    var includeZwspInRange = function (rng) {
      var newRng = rng.cloneRange();
      newRng.setStart(rng.startContainer, normalizeZwspOffset(true, rng.startContainer, rng.startOffset));
      newRng.setEnd(rng.endContainer, normalizeZwspOffset(false, rng.endContainer, rng.endOffset));
      return newRng;
    };
    var trimLeadingLineBreaks = function (node) {
      do {
        if (NodeType.isText(node)) {
          node.nodeValue = node.nodeValue.replace(/^[\r\n]+/, '');
        }
        node = node.firstChild;
      } while (node);
    };
    var getEditableRoot$1 = function (dom, node) {
      var root = dom.getRoot();
      var parent, editableRoot;
      parent = node;
      while (parent !== root && dom.getContentEditable(parent) !== 'false') {
        if (dom.getContentEditable(parent) === 'true') {
          editableRoot = parent;
        }
        parent = parent.parentNode;
      }
      return parent !== root ? editableRoot : root;
    };
    var applyAttributes = function (editor, node, forcedRootBlockAttrs) {
      Option.from(forcedRootBlockAttrs.style).map(editor.dom.parseStyle).each(function (attrStyles) {
        var currentStyles = getAllRaw(Element.fromDom(node));
        var newStyles = __assign(__assign({}, currentStyles), attrStyles);
        editor.dom.setStyles(node, newStyles);
      });
      var attrClassesOpt = Option.from(forcedRootBlockAttrs.class).map(function (attrClasses) {
        return attrClasses.split(/\s+/);
      });
      var currentClassesOpt = Option.from(node.className).map(function (currentClasses) {
        return filter(currentClasses.split(/\s+/), function (clazz) {
          return clazz !== '';
        });
      });
      lift2(attrClassesOpt, currentClassesOpt, function (attrClasses, currentClasses) {
        var filteredClasses = filter(currentClasses, function (clazz) {
          return !contains(attrClasses, clazz);
        });
        var newClasses = __spreadArrays(attrClasses, filteredClasses);
        editor.dom.setAttrib(node, 'class', newClasses.join(' '));
      });
      var appliedAttrs = [
        'style',
        'class'
      ];
      var remainingAttrs = bifilter(forcedRootBlockAttrs, function (_, attrs) {
        return !contains(appliedAttrs, attrs);
      }).t;
      editor.dom.setAttribs(node, remainingAttrs);
    };
    var setForcedBlockAttrs = function (editor, node) {
      var forcedRootBlockName = Settings.getForcedRootBlock(editor);
      if (forcedRootBlockName && forcedRootBlockName.toLowerCase() === node.tagName.toLowerCase()) {
        var forcedRootBlockAttrs = Settings.getForcedRootBlockAttrs(editor);
        applyAttributes(editor, node, forcedRootBlockAttrs);
      }
    };
    var wrapSelfAndSiblingsInDefaultBlock = function (editor, newBlockName, rng, container, offset) {
      var newBlock, parentBlock, startNode, node, next, rootBlockName;
      var blockName = newBlockName || 'P';
      var dom = editor.dom, editableRoot = getEditableRoot$1(dom, container);
      parentBlock = dom.getParent(container, dom.isBlock);
      if (!parentBlock || !canSplitBlock(dom, parentBlock)) {
        parentBlock = parentBlock || editableRoot;
        if (parentBlock === editor.getBody() || isTableCell$5(parentBlock)) {
          rootBlockName = parentBlock.nodeName.toLowerCase();
        } else {
          rootBlockName = parentBlock.parentNode.nodeName.toLowerCase();
        }
        if (!parentBlock.hasChildNodes()) {
          newBlock = dom.create(blockName);
          setForcedBlockAttrs(editor, newBlock);
          parentBlock.appendChild(newBlock);
          rng.setStart(newBlock, 0);
          rng.setEnd(newBlock, 0);
          return newBlock;
        }
        node = container;
        while (node.parentNode !== parentBlock) {
          node = node.parentNode;
        }
        while (node && !dom.isBlock(node)) {
          startNode = node;
          node = node.previousSibling;
        }
        if (startNode && editor.schema.isValidChild(rootBlockName, blockName.toLowerCase())) {
          newBlock = dom.create(blockName);
          setForcedBlockAttrs(editor, newBlock);
          startNode.parentNode.insertBefore(newBlock, startNode);
          node = startNode;
          while (node && !dom.isBlock(node)) {
            next = node.nextSibling;
            newBlock.appendChild(node);
            node = next;
          }
          rng.setStart(container, offset);
          rng.setEnd(container, offset);
        }
      }
      return container;
    };
    var addBrToBlockIfNeeded = function (dom, block) {
      var lastChild;
      block.normalize();
      lastChild = block.lastChild;
      if (!lastChild || /^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true))) {
        dom.add(block, 'br');
      }
    };
    var insert$2 = function (editor, evt) {
      var tmpRng, editableRoot, container, offset, parentBlock, shiftKey;
      var newBlock, fragment, containerBlock, parentBlockName, containerBlockName, newBlockName, isAfterLastNodeInContainer;
      var dom = editor.dom;
      var schema = editor.schema, nonEmptyElementsMap = schema.getNonEmptyElements();
      var rng = editor.selection.getRng();
      var createNewBlock = function (name) {
        var node = container, block, clonedNode, caretNode;
        var textInlineElements = schema.getTextInlineElements();
        if (name || parentBlockName === 'TABLE' || parentBlockName === 'HR') {
          block = dom.create(name || newBlockName);
        } else {
          block = parentBlock.cloneNode(false);
        }
        caretNode = block;
        if (Settings.shouldKeepStyles(editor) === false) {
          dom.setAttrib(block, 'style', null);
          dom.setAttrib(block, 'class', null);
        } else {
          do {
            if (textInlineElements[node.nodeName]) {
              if (isCaretNode(node) || Bookmarks.isBookmarkNode(node)) {
                continue;
              }
              clonedNode = node.cloneNode(false);
              dom.setAttrib(clonedNode, 'id', '');
              if (block.hasChildNodes()) {
                clonedNode.appendChild(block.firstChild);
                block.appendChild(clonedNode);
              } else {
                caretNode = clonedNode;
                block.appendChild(clonedNode);
              }
            }
          } while ((node = node.parentNode) && node !== editableRoot);
        }
        setForcedBlockAttrs(editor, block);
        emptyBlock(caretNode);
        return block;
      };
      var isCaretAtStartOrEndOfBlock = function (start) {
        var walker, node, name, normalizedOffset;
        normalizedOffset = normalizeZwspOffset(start, container, offset);
        if (NodeType.isText(container) && (start ? normalizedOffset > 0 : normalizedOffset < container.nodeValue.length)) {
          return false;
        }
        if (container.parentNode === parentBlock && isAfterLastNodeInContainer && !start) {
          return true;
        }
        if (start && NodeType.isElement(container) && container === parentBlock.firstChild) {
          return true;
        }
        if (containerAndSiblingName(container, 'TABLE') || containerAndSiblingName(container, 'HR')) {
          return isAfterLastNodeInContainer && !start || !isAfterLastNodeInContainer && start;
        }
        walker = new TreeWalker(container, parentBlock);
        if (NodeType.isText(container)) {
          if (start && normalizedOffset === 0) {
            walker.prev();
          } else if (!start && normalizedOffset === container.nodeValue.length) {
            walker.next();
          }
        }
        while (node = walker.current()) {
          if (NodeType.isElement(node)) {
            if (!node.getAttribute('data-mce-bogus')) {
              name = node.nodeName.toLowerCase();
              if (nonEmptyElementsMap[name] && name !== 'br') {
                return false;
              }
            }
          } else if (NodeType.isText(node) && !/^[ \t\r\n]*$/.test(node.nodeValue)) {
            return false;
          }
          if (start) {
            walker.prev();
          } else {
            walker.next();
          }
        }
        return true;
      };
      var insertNewBlockAfter = function () {
        if (/^(H[1-6]|PRE|FIGURE)$/.test(parentBlockName) && containerBlockName !== 'HGROUP') {
          newBlock = createNewBlock(newBlockName);
        } else {
          newBlock = createNewBlock();
        }
        if (Settings.shouldEndContainerOnEmptyBlock(editor) && canSplitBlock(dom, containerBlock) && dom.isEmpty(parentBlock)) {
          newBlock = dom.split(containerBlock, parentBlock);
        } else {
          dom.insertAfter(newBlock, parentBlock);
        }
        NewLineUtils.moveToCaretPosition(editor, newBlock);
      };
      NormalizeRange.normalize(dom, rng).each(function (normRng) {
        rng.setStart(normRng.startContainer, normRng.startOffset);
        rng.setEnd(normRng.endContainer, normRng.endOffset);
      });
      container = rng.startContainer;
      offset = rng.startOffset;
      newBlockName = Settings.getForcedRootBlock(editor);
      shiftKey = evt.shiftKey;
      if (NodeType.isElement(container) && container.hasChildNodes()) {
        isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
        if (isAfterLastNodeInContainer && NodeType.isText(container)) {
          offset = container.nodeValue.length;
        } else {
          offset = 0;
        }
      }
      editableRoot = getEditableRoot$1(dom, container);
      if (!editableRoot) {
        return;
      }
      if (newBlockName && !shiftKey || !newBlockName && shiftKey) {
        container = wrapSelfAndSiblingsInDefaultBlock(editor, newBlockName, rng, container, offset);
      }
      parentBlock = dom.getParent(container, dom.isBlock);
      containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
      parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : '';
      containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
      if (containerBlockName === 'LI' && !evt.ctrlKey) {
        parentBlock = containerBlock;
        containerBlock = containerBlock.parentNode;
        parentBlockName = containerBlockName;
      }
      if (/^(LI|DT|DD)$/.test(parentBlockName)) {
        if (dom.isEmpty(parentBlock)) {
          InsertLi.insert(editor, createNewBlock, containerBlock, parentBlock, newBlockName);
          return;
        }
      }
      if (newBlockName && parentBlock === editor.getBody()) {
        return;
      }
      newBlockName = newBlockName || 'P';
      if (isCaretContainerBlock(parentBlock)) {
        newBlock = showCaretContainerBlock(parentBlock);
        if (dom.isEmpty(parentBlock)) {
          emptyBlock(parentBlock);
        }
        setForcedBlockAttrs(editor, newBlock);
        NewLineUtils.moveToCaretPosition(editor, newBlock);
      } else if (isCaretAtStartOrEndOfBlock()) {
        insertNewBlockAfter();
      } else if (isCaretAtStartOrEndOfBlock(true)) {
        newBlock = parentBlock.parentNode.insertBefore(createNewBlock(), parentBlock);
        NewLineUtils.moveToCaretPosition(editor, containerAndSiblingName(parentBlock, 'HR') ? newBlock : parentBlock);
      } else {
        tmpRng = includeZwspInRange(rng).cloneRange();
        tmpRng.setEndAfter(parentBlock);
        fragment = tmpRng.extractContents();
        trimZwsp(fragment);
        trimLeadingLineBreaks(fragment);
        newBlock = fragment.firstChild;
        dom.insertAfter(fragment, parentBlock);
        trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock);
        addBrToBlockIfNeeded(dom, parentBlock);
        if (dom.isEmpty(parentBlock)) {
          emptyBlock(parentBlock);
        }
        newBlock.normalize();
        if (dom.isEmpty(newBlock)) {
          dom.remove(newBlock);
          insertNewBlockAfter();
        } else {
          setForcedBlockAttrs(editor, newBlock);
          NewLineUtils.moveToCaretPosition(editor, newBlock);
        }
      }
      dom.setAttrib(newBlock, 'id', '');
      editor.fire('NewBlock', { newBlock: newBlock });
    };
    var InsertBlock = { insert: insert$2 };

    var matchesSelector = function (editor, selector) {
      return NewLineUtils.getParentBlock(editor).filter(function (parentBlock) {
        return selector.length > 0 && is$1(Element.fromDom(parentBlock), selector);
      }).isSome();
    };
    var shouldInsertBr = function (editor) {
      return matchesSelector(editor, Settings.getBrNewLineSelector(editor));
    };
    var shouldBlockNewLine = function (editor) {
      return matchesSelector(editor, Settings.getNoNewLineSelector(editor));
    };
    var ContextSelectors = {
      shouldInsertBr: shouldInsertBr,
      shouldBlockNewLine: shouldBlockNewLine
    };

    var newLineAction = Adt.generate([
      { br: [] },
      { block: [] },
      { none: [] }
    ]);
    var shouldBlockNewLine$1 = function (editor, shiftKey) {
      return ContextSelectors.shouldBlockNewLine(editor);
    };
    var isBrMode = function (requiredState) {
      return function (editor, shiftKey) {
        var brMode = Settings.getForcedRootBlock(editor) === '';
        return brMode === requiredState;
      };
    };
    var inListBlock = function (requiredState) {
      return function (editor, shiftKey) {
        return NewLineUtils.isListItemParentBlock(editor) === requiredState;
      };
    };
    var inBlock = function (blockName, requiredState) {
      return function (editor, shiftKey) {
        var state = NewLineUtils.getParentBlockName(editor) === blockName.toUpperCase();
        return state === requiredState;
      };
    };
    var inPreBlock = function (requiredState) {
      return inBlock('pre', requiredState);
    };
    var inSummaryBlock = function () {
      return inBlock('summary', true);
    };
    var shouldPutBrInPre$1 = function (requiredState) {
      return function (editor, shiftKey) {
        return Settings.shouldPutBrInPre(editor) === requiredState;
      };
    };
    var inBrContext = function (editor, shiftKey) {
      return ContextSelectors.shouldInsertBr(editor);
    };
    var hasShiftKey = function (editor, shiftKey) {
      return shiftKey;
    };
    var canInsertIntoEditableRoot = function (editor) {
      var forcedRootBlock = Settings.getForcedRootBlock(editor);
      var rootEditable = NewLineUtils.getEditableRoot(editor.dom, editor.selection.getStart());
      return rootEditable && editor.schema.isValidChild(rootEditable.nodeName, forcedRootBlock ? forcedRootBlock : 'P');
    };
    var match$2 = function (predicates, action) {
      return function (editor, shiftKey) {
        var isMatch = foldl(predicates, function (res, p) {
          return res && p(editor, shiftKey);
        }, true);
        return isMatch ? Option.some(action) : Option.none();
      };
    };
    var getAction$1 = function (editor, evt) {
      return LazyEvaluator.evaluateUntil([
        match$2([shouldBlockNewLine$1], newLineAction.none()),
        match$2([inSummaryBlock()], newLineAction.br()),
        match$2([
          inPreBlock(true),
          shouldPutBrInPre$1(false),
          hasShiftKey
        ], newLineAction.br()),
        match$2([
          inPreBlock(true),
          shouldPutBrInPre$1(false)
        ], newLineAction.block()),
        match$2([
          inPreBlock(true),
          shouldPutBrInPre$1(true),
          hasShiftKey
        ], newLineAction.block()),
        match$2([
          inPreBlock(true),
          shouldPutBrInPre$1(true)
        ], newLineAction.br()),
        match$2([
          inListBlock(true),
          hasShiftKey
        ], newLineAction.br()),
        match$2([inListBlock(true)], newLineAction.block()),
        match$2([
          isBrMode(true),
          hasShiftKey,
          canInsertIntoEditableRoot
        ], newLineAction.block()),
        match$2([isBrMode(true)], newLineAction.br()),
        match$2([inBrContext], newLineAction.br()),
        match$2([
          isBrMode(false),
          hasShiftKey
        ], newLineAction.br()),
        match$2([canInsertIntoEditableRoot], newLineAction.block())
      ], [
        editor,
        evt.shiftKey
      ]).getOr(newLineAction.none());
    };
    var NewLineAction = { getAction: getAction$1 };

    var insert$3 = function (editor, evt) {
      NewLineAction.getAction(editor, evt).fold(function () {
        InsertBr.insert(editor, evt);
      }, function () {
        InsertBlock.insert(editor, evt);
      }, noop);
    };
    var InsertNewLine = { insert: insert$3 };

    var endTypingLevel = function (undoManager) {
      if (undoManager.typing) {
        undoManager.typing = false;
        undoManager.add();
      }
    };
    var handleEnterKeyEvent = function (editor, event) {
      if (event.isDefaultPrevented()) {
        return;
      }
      event.preventDefault();
      endTypingLevel(editor.undoManager);
      editor.undoManager.transact(function () {
        if (editor.selection.isCollapsed() === false) {
          editor.execCommand('Delete');
        }
        InsertNewLine.insert(editor, event);
      });
    };
    var setup$9 = function (editor) {
      editor.on('keydown', function (event) {
        if (event.keyCode === VK.ENTER) {
          handleEnterKeyEvent(editor, event);
        }
      });
    };
    var EnterKey = { setup: setup$9 };

    var insertTextAtPosition = function (text, pos) {
      var container = pos.container();
      var offset = pos.offset();
      if (NodeType.isText(container)) {
        container.insertData(offset, text);
        return Option.some(CaretPosition(container, offset + text.length));
      } else {
        return getElementFromPosition(pos).map(function (elm) {
          var textNode = Element.fromText(text);
          if (pos.isAtEnd()) {
            after(elm, textNode);
          } else {
            before(elm, textNode);
          }
          return CaretPosition(textNode.dom(), text.length);
        });
      }
    };
    var insertNbspAtPosition = curry(insertTextAtPosition, '\xA0');
    var insertSpaceAtPosition = curry(insertTextAtPosition, ' ');

    var navigateIgnoreEmptyTextNodes = function (forward, root, from) {
      return CaretFinder.navigateIgnore(forward, root, from, isEmptyText);
    };
    var getClosestBlock = function (root, pos) {
      return find(Parents.parentsAndSelf(Element.fromDom(pos.container()), root), isBlock);
    };
    var isAtBeforeAfterBlockBoundary = function (forward, root, pos) {
      return navigateIgnoreEmptyTextNodes(forward, root.dom(), pos).forall(function (newPos) {
        return getClosestBlock(root, pos).fold(function () {
          return isInSameBlock(newPos, pos, root.dom()) === false;
        }, function (fromBlock) {
          return isInSameBlock(newPos, pos, root.dom()) === false && contains$3(fromBlock, Element.fromDom(newPos.container()));
        });
      });
    };
    var isAtBlockBoundary = function (forward, root, pos) {
      return getClosestBlock(root, pos).fold(function () {
        return navigateIgnoreEmptyTextNodes(forward, root.dom(), pos).forall(function (newPos) {
          return isInSameBlock(newPos, pos, root.dom()) === false;
        });
      }, function (parent) {
        return navigateIgnoreEmptyTextNodes(forward, parent.dom(), pos).isNone();
      });
    };
    var isAtStartOfBlock = curry(isAtBlockBoundary, false);
    var isAtEndOfBlock = curry(isAtBlockBoundary, true);
    var isBeforeBlock = curry(isAtBeforeAfterBlockBoundary, false);
    var isAfterBlock = curry(isAtBeforeAfterBlockBoundary, true);

    var nbsp = '\xA0';
    var isInMiddleOfText = function (pos) {
      return CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd();
    };
    var getClosestBlock$1 = function (root, pos) {
      var parentBlocks = filter(Parents.parentsAndSelf(Element.fromDom(pos.container()), root), isBlock);
      return head(parentBlocks).getOr(root);
    };
    var hasSpaceBefore = function (root, pos) {
      if (isInMiddleOfText(pos)) {
        return isAfterSpace(pos);
      } else {
        return isAfterSpace(pos) || CaretFinder.prevPosition(getClosestBlock$1(root, pos).dom(), pos).exists(isAfterSpace);
      }
    };
    var hasSpaceAfter = function (root, pos) {
      if (isInMiddleOfText(pos)) {
        return isBeforeSpace(pos);
      } else {
        return isBeforeSpace(pos) || CaretFinder.nextPosition(getClosestBlock$1(root, pos).dom(), pos).exists(isBeforeSpace);
      }
    };
    var isPreValue = function (value) {
      return contains([
        'pre',
        'pre-wrap'
      ], value);
    };
    var isInPre = function (pos) {
      return getElementFromPosition(pos).bind(function (elm) {
        return closest(elm, isElement);
      }).exists(function (elm) {
        return isPreValue(get$1(elm, 'white-space'));
      });
    };
    var isAtBeginningOfBody = function (root, pos) {
      return CaretFinder.prevPosition(root.dom(), pos).isNone();
    };
    var isAtEndOfBody = function (root, pos) {
      return CaretFinder.nextPosition(root.dom(), pos).isNone();
    };
    var isAtLineBoundary = function (root, pos) {
      return isAtBeginningOfBody(root, pos) || isAtEndOfBody(root, pos) || isAtStartOfBlock(root, pos) || isAtEndOfBlock(root, pos) || isAfterBr(root, pos) || isBeforeBr(root, pos);
    };
    var needsToHaveNbsp = function (root, pos) {
      if (isInPre(pos)) {
        return false;
      } else {
        return isAtLineBoundary(root, pos) || hasSpaceBefore(root, pos) || hasSpaceAfter(root, pos);
      }
    };
    var needsToBeNbspLeft = function (root, pos) {
      if (isInPre(pos)) {
        return false;
      } else {
        return isAtStartOfBlock(root, pos) || isBeforeBlock(root, pos) || isAfterBr(root, pos) || hasSpaceBefore(root, pos);
      }
    };
    var leanRight = function (pos) {
      var container = pos.container();
      var offset = pos.offset();
      if (NodeType.isText(container) && offset < container.data.length) {
        return CaretPosition(container, offset + 1);
      } else {
        return pos;
      }
    };
    var needsToBeNbspRight = function (root, pos) {
      var afterPos = leanRight(pos);
      if (isInPre(afterPos)) {
        return false;
      } else {
        return isAtEndOfBlock(root, afterPos) || isAfterBlock(root, afterPos) || isBeforeBr(root, afterPos) || hasSpaceAfter(root, afterPos);
      }
    };
    var needsToBeNbsp = function (root, pos) {
      return needsToBeNbspLeft(root, pos) || needsToBeNbspRight(root, pos);
    };
    var isNbspAt = function (text, offset) {
      return isNbsp(text.charAt(offset));
    };
    var hasNbsp = function (pos) {
      var container = pos.container();
      return NodeType.isText(container) && contains$2(container.data, nbsp);
    };
    var normalizeNbspMiddle = function (text) {
      var chars = text.split('');
      return map(chars, function (chr, i) {
        if (isNbsp(chr) && i > 0 && i < chars.length - 1 && isContent$1(chars[i - 1]) && isContent$1(chars[i + 1])) {
          return ' ';
        } else {
          return chr;
        }
      }).join('');
    };
    var normalizeNbspAtStart = function (root, node) {
      var text = node.data;
      var firstPos = CaretPosition(node, 0);
      if (isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos)) {
        node.data = ' ' + text.slice(1);
        return true;
      } else {
        return false;
      }
    };
    var normalizeNbspInMiddleOfTextNode = function (node) {
      var text = node.data;
      var newText = normalizeNbspMiddle(text);
      if (newText !== text) {
        node.data = newText;
        return true;
      } else {
        return false;
      }
    };
    var normalizeNbspAtEnd = function (root, node) {
      var text = node.data;
      var lastPos = CaretPosition(node, text.length - 1);
      if (isNbspAt(text, text.length - 1) && !needsToBeNbsp(root, lastPos)) {
        node.data = text.slice(0, -1) + ' ';
        return true;
      } else {
        return false;
      }
    };
    var normalizeNbsps = function (root, pos) {
      return Option.some(pos).filter(hasNbsp).bind(function (pos) {
        var container = pos.container();
        var normalized = normalizeNbspAtStart(root, container) || normalizeNbspInMiddleOfTextNode(container) || normalizeNbspAtEnd(root, container);
        return normalized ? Option.some(pos) : Option.none();
      });
    };
    var normalizeNbspsInEditor = function (editor) {
      var root = Element.fromDom(editor.getBody());
      if (editor.selection.isCollapsed()) {
        normalizeNbsps(root, CaretPosition.fromRangeStart(editor.selection.getRng())).each(function (pos) {
          editor.selection.setRng(pos.toRange());
        });
      }
    };

    var locationToCaretPosition = function (root) {
      return function (location) {
        return location.fold(function (element) {
          return CaretFinder.prevPosition(root.dom(), CaretPosition$1.before(element));
        }, function (element) {
          return CaretFinder.firstPositionIn(element);
        }, function (element) {
          return CaretFinder.lastPositionIn(element);
        }, function (element) {
          return CaretFinder.nextPosition(root.dom(), CaretPosition$1.after(element));
        });
      };
    };
    var insertInlineBoundarySpaceOrNbsp = function (root, pos) {
      return function (checkPos) {
        return needsToHaveNbsp(root, checkPos) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
      };
    };
    var setSelection$1 = function (editor) {
      return function (pos) {
        editor.selection.setRng(pos.toRange());
        editor.nodeChanged();
        return true;
      };
    };
    var insertSpaceOrNbspAtSelection = function (editor) {
      var pos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
      var root = Element.fromDom(editor.getBody());
      if (editor.selection.isCollapsed()) {
        var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
        var caretPosition = CaretPosition$1.fromRangeStart(editor.selection.getRng());
        return BoundaryLocation.readLocation(isInlineTarget, editor.getBody(), caretPosition).bind(locationToCaretPosition(root)).bind(insertInlineBoundarySpaceOrNbsp(root, pos)).exists(setSelection$1(editor));
      } else {
        return false;
      }
    };

    var executeKeydownOverride$2 = function (editor, evt) {
      MatchKeys.execute([{
          keyCode: VK.SPACEBAR,
          action: MatchKeys.action(insertSpaceOrNbspAtSelection, editor)
        }], evt).each(function (_) {
        evt.preventDefault();
      });
    };
    var setup$a = function (editor) {
      editor.on('keydown', function (evt) {
        if (evt.isDefaultPrevented() === false) {
          executeKeydownOverride$2(editor, evt);
        }
      });
    };
    var SpaceKey = { setup: setup$a };

    var findBlockCaretContainer = function (editor) {
      return descendant(Element.fromDom(editor.getBody()), '*[data-mce-caret]').fold(constant(null), function (elm) {
        return elm.dom();
      });
    };
    var removeIeControlRect = function (editor) {
      editor.selection.setRng(editor.selection.getRng());
    };
    var showBlockCaretContainer = function (editor, blockCaretContainer) {
      if (blockCaretContainer.hasAttribute('data-mce-caret')) {
        showCaretContainerBlock(blockCaretContainer);
        removeIeControlRect(editor);
        editor.selection.scrollIntoView(blockCaretContainer);
      }
    };
    var handleBlockContainer = function (editor, e) {
      var blockCaretContainer = findBlockCaretContainer(editor);
      if (!blockCaretContainer) {
        return;
      }
      if (e.type === 'compositionstart') {
        e.preventDefault();
        e.stopPropagation();
        showBlockCaretContainer(editor, blockCaretContainer);
        return;
      }
      if (hasContent(blockCaretContainer)) {
        showBlockCaretContainer(editor, blockCaretContainer);
        editor.undoManager.add();
      }
    };
    var setup$b = function (editor) {
      editor.on('keyup compositionstart', curry(handleBlockContainer, editor));
    };
    var CaretContainerInput = { setup: setup$b };

    var browser$4 = PlatformDetection$1.detect().browser;
    var setupIeInput = function (editor) {
      var keypressThrotter = first(function () {
        if (!editor.composing) {
          normalizeNbspsInEditor(editor);
        }
      }, 0);
      if (browser$4.isIE()) {
        editor.on('keypress', function (e) {
          keypressThrotter.throttle();
        });
        editor.on('remove', function (e) {
          keypressThrotter.cancel();
        });
      }
    };
    var setup$c = function (editor) {
      setupIeInput(editor);
      editor.on('input', function (e) {
        if (e.isComposing === false) {
          normalizeNbspsInEditor(editor);
        }
      });
    };

    var executeKeydownOverride$3 = function (editor, evt) {
      MatchKeys.execute([
        {
          keyCode: VK.END,
          action: moveToLineEndPoint(editor, true)
        },
        {
          keyCode: VK.HOME,
          action: moveToLineEndPoint(editor, false)
        }
      ], evt).each(function (_) {
        evt.preventDefault();
      });
    };
    var setup$d = function (editor) {
      editor.on('keydown', function (evt) {
        if (evt.isDefaultPrevented() === false) {
          executeKeydownOverride$3(editor, evt);
        }
      });
    };
    var HomeEndKeys = { setup: setup$d };

    var setup$e = function (editor) {
      var caret = BoundarySelection.setupSelectedState(editor);
      CaretContainerInput.setup(editor);
      ArrowKeys.setup(editor, caret);
      DeleteBackspaceKeys.setup(editor, caret);
      EnterKey.setup(editor);
      SpaceKey.setup(editor);
      setup$c(editor);
      HomeEndKeys.setup(editor);
    };
    var KeyboardOverrides = { setup: setup$e };

    function Quirks (editor) {
      var each = Tools.each;
      var BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, settings = editor.settings, parser = editor.parser;
      var isGecko = Env.gecko, isIE = Env.ie, isWebKit = Env.webkit;
      var mceInternalUrlPrefix = 'data:text/mce-internal,';
      var mceInternalDataType = isIE ? 'Text' : 'URL';
      var setEditorCommandState = function (cmd, state) {
        try {
          editor.getDoc().execCommand(cmd, false, state);
        } catch (ex) {
        }
      };
      var isDefaultPrevented = function (e) {
        return e.isDefaultPrevented();
      };
      var setMceInternalContent = function (e) {
        var selectionHtml, internalContent;
        if (e.dataTransfer) {
          if (editor.selection.isCollapsed() && e.target.tagName === 'IMG') {
            selection.select(e.target);
          }
          selectionHtml = editor.selection.getContent();
          if (selectionHtml.length > 0) {
            internalContent = mceInternalUrlPrefix + escape(editor.id) + ',' + escape(selectionHtml);
            e.dataTransfer.setData(mceInternalDataType, internalContent);
          }
        }
      };
      var getMceInternalContent = function (e) {
        var internalContent;
        if (e.dataTransfer) {
          internalContent = e.dataTransfer.getData(mceInternalDataType);
          if (internalContent && internalContent.indexOf(mceInternalUrlPrefix) >= 0) {
            internalContent = internalContent.substr(mceInternalUrlPrefix.length).split(',');
            return {
              id: unescape(internalContent[0]),
              html: unescape(internalContent[1])
            };
          }
        }
        return null;
      };
      var insertClipboardContents = function (content, internal) {
        if (editor.queryCommandSupported('mceInsertClipboardContent')) {
          editor.execCommand('mceInsertClipboardContent', false, {
            content: content,
            internal: internal
          });
        } else {
          editor.execCommand('mceInsertContent', false, content);
        }
      };
      var emptyEditorWhenDeleting = function () {
        var serializeRng = function (rng) {
          var body = dom.create('body');
          var contents = rng.cloneContents();
          body.appendChild(contents);
          return selection.serializer.serialize(body, { format: 'html' });
        };
        var allContentsSelected = function (rng) {
          var selection = serializeRng(rng);
          var allRng = dom.createRng();
          allRng.selectNode(editor.getBody());
          var allSelection = serializeRng(allRng);
          return selection === allSelection;
        };
        editor.on('keydown', function (e) {
          var keyCode = e.keyCode;
          var isCollapsed, body;
          if (!isDefaultPrevented(e) && (keyCode === DELETE || keyCode === BACKSPACE)) {
            isCollapsed = editor.selection.isCollapsed();
            body = editor.getBody();
            if (isCollapsed && !dom.isEmpty(body)) {
              return;
            }
            if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
              return;
            }
            e.preventDefault();
            editor.setContent('');
            if (body.firstChild && dom.isBlock(body.firstChild)) {
              editor.selection.setCursorLocation(body.firstChild, 0);
            } else {
              editor.selection.setCursorLocation(body, 0);
            }
            editor.nodeChanged();
          }
        });
      };
      var selectAll = function () {
        editor.shortcuts.add('meta+a', null, 'SelectAll');
      };
      var inputMethodFocus = function () {
        if (!editor.settings.content_editable) {
          dom.bind(editor.getDoc(), 'mousedown mouseup', function (e) {
            var rng;
            if (e.target === editor.getDoc().documentElement) {
              rng = selection.getRng();
              editor.getBody().focus();
              if (e.type === 'mousedown') {
                if (isCaretContainer(rng.startContainer)) {
                  return;
                }
                selection.placeCaretAt(e.clientX, e.clientY);
              } else {
                selection.setRng(rng);
              }
            }
          });
        }
      };
      var removeHrOnBackspace = function () {
        editor.on('keydown', function (e) {
          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
            if (!editor.getBody().getElementsByTagName('hr').length) {
              return;
            }
            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
              var node = selection.getNode();
              var previousSibling = node.previousSibling;
              if (node.nodeName === 'HR') {
                dom.remove(node);
                e.preventDefault();
                return;
              }
              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'hr') {
                dom.remove(previousSibling);
                e.preventDefault();
              }
            }
          }
        });
      };
      var focusBody = function () {
        if (!domGlobals.Range.prototype.getClientRects) {
          editor.on('mousedown', function (e) {
            if (!isDefaultPrevented(e) && e.target.nodeName === 'HTML') {
              var body_1 = editor.getBody();
              body_1.blur();
              Delay.setEditorTimeout(editor, function () {
                body_1.focus();
              });
            }
          });
        }
      };
      var selectControlElements = function () {
        editor.on('click', function (e) {
          var target = e.target;
          if (/^(IMG|HR)$/.test(target.nodeName) && dom.getContentEditableParent(target) !== 'false') {
            e.preventDefault();
            editor.selection.select(target);
            editor.nodeChanged();
          }
          if (target.nodeName === 'A' && dom.hasClass(target, 'mce-item-anchor')) {
            e.preventDefault();
            selection.select(target);
          }
        });
      };
      var removeStylesWhenDeletingAcrossBlockElements = function () {
        var getAttributeApplyFunction = function () {
          var template = dom.getAttribs(selection.getStart().cloneNode(false));
          return function () {
            var target = selection.getStart();
            if (target !== editor.getBody()) {
              dom.setAttrib(target, 'style', null);
              each(template, function (attr) {
                target.setAttributeNode(attr.cloneNode(true));
              });
            }
          };
        };
        var isSelectionAcrossElements = function () {
          return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) !== dom.getParent(selection.getEnd(), dom.isBlock);
        };
        editor.on('keypress', function (e) {
          var applyAttributes;
          if (!isDefaultPrevented(e) && (e.keyCode === 8 || e.keyCode === 46) && isSelectionAcrossElements()) {
            applyAttributes = getAttributeApplyFunction();
            editor.getDoc().execCommand('delete', false, null);
            applyAttributes();
            e.preventDefault();
            return false;
          }
        });
        dom.bind(editor.getDoc(), 'cut', function (e) {
          var applyAttributes;
          if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
            applyAttributes = getAttributeApplyFunction();
            Delay.setEditorTimeout(editor, function () {
              applyAttributes();
            });
          }
        });
      };
      var disableBackspaceIntoATable = function () {
        editor.on('keydown', function (e) {
          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
              var previousSibling = selection.getNode().previousSibling;
              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'table') {
                e.preventDefault();
                return false;
              }
            }
          }
        });
      };
      var removeBlockQuoteOnBackSpace = function () {
        editor.on('keydown', function (e) {
          var rng, container, offset, root, parent;
          if (isDefaultPrevented(e) || e.keyCode !== VK.BACKSPACE) {
            return;
          }
          rng = selection.getRng();
          container = rng.startContainer;
          offset = rng.startOffset;
          root = dom.getRoot();
          parent = container;
          if (!rng.collapsed || offset !== 0) {
            return;
          }
          while (parent && parent.parentNode && parent.parentNode.firstChild === parent && parent.parentNode !== root) {
            parent = parent.parentNode;
          }
          if (parent.tagName === 'BLOCKQUOTE') {
            editor.formatter.toggle('blockquote', null, parent);
            rng = dom.createRng();
            rng.setStart(container, 0);
            rng.setEnd(container, 0);
            selection.setRng(rng);
          }
        });
      };
      var setGeckoEditingOptions = function () {
        var setOpts = function () {
          setEditorCommandState('StyleWithCSS', false);
          setEditorCommandState('enableInlineTableEditing', false);
          if (!settings.object_resizing) {
            setEditorCommandState('enableObjectResizing', false);
          }
        };
        if (!settings.readonly) {
          editor.on('BeforeExecCommand MouseDown', setOpts);
        }
      };
      var addBrAfterLastLinks = function () {
        var fixLinks = function () {
          each(dom.select('a'), function (node) {
            var parentNode = node.parentNode;
            var root = dom.getRoot();
            if (parentNode.lastChild === node) {
              while (parentNode && !dom.isBlock(parentNode)) {
                if (parentNode.parentNode.lastChild !== parentNode || parentNode === root) {
                  return;
                }
                parentNode = parentNode.parentNode;
              }
              dom.add(parentNode, 'br', { 'data-mce-bogus': 1 });
            }
          });
        };
        editor.on('SetContent ExecCommand', function (e) {
          if (e.type === 'setcontent' || e.command === 'mceInsertLink') {
            fixLinks();
          }
        });
      };
      var setDefaultBlockType = function () {
        if (settings.forced_root_block) {
          editor.on('init', function () {
            setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block);
          });
        }
      };
      var normalizeSelection = function () {
        editor.on('keyup focusin mouseup', function (e) {
          if (!VK.modifierPressed(e)) {
            selection.normalize();
          }
        }, true);
      };
      var showBrokenImageIcon = function () {
        editor.contentStyles.push('img:-moz-broken {' + '-moz-force-broken-image-icon:1;' + 'min-width:24px;' + 'min-height:24px' + '}');
      };
      var restoreFocusOnKeyDown = function () {
        if (!editor.inline) {
          editor.on('keydown', function () {
            if (domGlobals.document.activeElement === domGlobals.document.body) {
              editor.getWin().focus();
            }
          });
        }
      };
      var bodyHeight = function () {
        if (!editor.inline) {
          editor.contentStyles.push('body {min-height: 150px}');
          editor.on('click', function (e) {
            var rng;
            if (e.target.nodeName === 'HTML') {
              if (Env.ie > 11) {
                editor.getBody().focus();
                return;
              }
              rng = editor.selection.getRng();
              editor.getBody().focus();
              editor.selection.setRng(rng);
              editor.selection.normalize();
              editor.nodeChanged();
            }
          });
        }
      };
      var blockCmdArrowNavigation = function () {
        if (Env.mac) {
          editor.on('keydown', function (e) {
            if (VK.metaKeyPressed(e) && !e.shiftKey && (e.keyCode === 37 || e.keyCode === 39)) {
              e.preventDefault();
              editor.selection.getSel().modify('move', e.keyCode === 37 ? 'backward' : 'forward', 'lineboundary');
            }
          });
        }
      };
      var disableAutoUrlDetect = function () {
        setEditorCommandState('AutoUrlDetect', false);
      };
      var tapLinksAndImages = function () {
        editor.on('click', function (e) {
          var elm = e.target;
          do {
            if (elm.tagName === 'A') {
              e.preventDefault();
              return;
            }
          } while (elm = elm.parentNode);
        });
        editor.contentStyles.push('.mce-content-body {-webkit-touch-callout: none}');
      };
      var blockFormSubmitInsideEditor = function () {
        editor.on('init', function () {
          editor.dom.bind(editor.getBody(), 'submit', function (e) {
            e.preventDefault();
          });
        });
      };
      var removeAppleInterchangeBrs = function () {
        parser.addNodeFilter('br', function (nodes) {
          var i = nodes.length;
          while (i--) {
            if (nodes[i].attr('class') === 'Apple-interchange-newline') {
              nodes[i].remove();
            }
          }
        });
      };
      var ieInternalDragAndDrop = function () {
        editor.on('dragstart', function (e) {
          setMceInternalContent(e);
        });
        editor.on('drop', function (e) {
          if (!isDefaultPrevented(e)) {
            var internalContent = getMceInternalContent(e);
            if (internalContent && internalContent.id !== editor.id) {
              e.preventDefault();
              var rng = CaretRangeFromPoint.fromPoint(e.x, e.y, editor.getDoc());
              selection.setRng(rng);
              insertClipboardContents(internalContent.html, true);
            }
          }
        });
      };
      var refreshContentEditable = function () {
      };
      var isHidden = function () {
        var sel;
        if (!isGecko || editor.removed) {
          return 0;
        }
        sel = editor.selection.getSel();
        return !sel || !sel.rangeCount || sel.rangeCount === 0;
      };
      removeBlockQuoteOnBackSpace();
      emptyEditorWhenDeleting();
      if (!Env.windowsPhone) {
        normalizeSelection();
      }
      if (isWebKit) {
        inputMethodFocus();
        selectControlElements();
        setDefaultBlockType();
        blockFormSubmitInsideEditor();
        disableBackspaceIntoATable();
        removeAppleInterchangeBrs();
        if (Env.iOS) {
          restoreFocusOnKeyDown();
          bodyHeight();
          tapLinksAndImages();
        } else {
          selectAll();
        }
      }
      if (Env.ie >= 11) {
        bodyHeight();
        disableBackspaceIntoATable();
      }
      if (Env.ie) {
        selectAll();
        disableAutoUrlDetect();
        ieInternalDragAndDrop();
      }
      if (isGecko) {
        removeHrOnBackspace();
        focusBody();
        removeStylesWhenDeletingAcrossBlockElements();
        setGeckoEditingOptions();
        addBrAfterLastLinks();
        showBrokenImageIcon();
        blockCmdArrowNavigation();
        disableBackspaceIntoATable();
      }
      return {
        refreshContentEditable: refreshContentEditable,
        isHidden: isHidden
      };
    }

    var isTextBlockNode = function (node) {
      return NodeType.isElement(node) && isTextBlock(Element.fromDom(node));
    };
    var normalizeSelection$1 = function (editor) {
      var rng = editor.selection.getRng();
      var startPos = CaretPosition.fromRangeStart(rng);
      var endPos = CaretPosition.fromRangeEnd(rng);
      if (CaretPosition.isElementPosition(startPos)) {
        var container = startPos.container();
        if (isTextBlockNode(container)) {
          CaretFinder.firstPositionIn(container).each(function (pos) {
            return rng.setStart(pos.container(), pos.offset());
          });
        }
      }
      if (CaretPosition.isElementPosition(endPos)) {
        var container = startPos.container();
        if (isTextBlockNode(container)) {
          CaretFinder.lastPositionIn(container).each(function (pos) {
            return rng.setEnd(pos.container(), pos.offset());
          });
        }
      }
      editor.selection.setRng(RangeNormalizer.normalize(rng));
    };
    var setup$f = function (editor) {
      editor.on('click', function (e) {
        if (e.detail >= 3) {
          normalizeSelection$1(editor);
        }
      });
    };

    var preventSummaryToggle = function (editor) {
      editor.on('click', function (e) {
        if (editor.dom.getParent(e.target, 'details')) {
          e.preventDefault();
        }
      });
    };
    var filterDetails = function (editor) {
      editor.parser.addNodeFilter('details', function (elms) {
        each(elms, function (details) {
          details.attr('data-mce-open', details.attr('open'));
          details.attr('open', 'open');
        });
      });
      editor.serializer.addNodeFilter('details', function (elms) {
        each(elms, function (details) {
          var open = details.attr('data-mce-open');
          details.attr('open', isString(open) ? open : null);
          details.attr('data-mce-open', null);
        });
      });
    };
    var setup$g = function (editor) {
      preventSummaryToggle(editor);
      filterDetails(editor);
    };

    var DOM$2 = DOMUtils$1.DOM;
    var appendStyle = function (editor, text) {
      var head = Element.fromDom(editor.getDoc().head);
      var tag = Element.fromTag('style');
      set(tag, 'type', 'text/css');
      append(tag, Element.fromText(text));
      append(head, tag);
    };
    var createParser = function (editor) {
      var parser = DomParser(editor.settings, editor.schema);
      parser.addAttributeFilter('src,href,style,tabindex', function (nodes, name) {
        var i = nodes.length, node;
        var dom = editor.dom;
        var value, internalName;
        while (i--) {
          node = nodes[i];
          value = node.attr(name);
          internalName = 'data-mce-' + name;
          if (!node.attributes.map[internalName]) {
            if (value.indexOf('data:') === 0 || value.indexOf('blob:') === 0) {
              continue;
            }
            if (name === 'style') {
              value = dom.serializeStyle(dom.parseStyle(value), node.name);
              if (!value.length) {
                value = null;
              }
              node.attr(internalName, value);
              node.attr(name, value);
            } else if (name === 'tabindex') {
              node.attr(internalName, value);
              node.attr(name, null);
            } else {
              node.attr(internalName, editor.convertURL(value, name, node.name));
            }
          }
        }
      });
      parser.addNodeFilter('script', function (nodes) {
        var i = nodes.length, node, type;
        while (i--) {
          node = nodes[i];
          type = node.attr('type') || 'no/type';
          if (type.indexOf('mce-') !== 0) {
            node.attr('type', 'mce-' + type);
          }
        }
      });
      parser.addNodeFilter('#cdata', function (nodes) {
        var i = nodes.length, node;
        while (i--) {
          node = nodes[i];
          node.type = 8;
          node.name = '#comment';
          node.value = '[CDATA[' + node.value + ']]';
        }
      });
      parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', function (nodes) {
        var i = nodes.length, node;
        var nonEmptyElements = editor.schema.getNonEmptyElements();
        while (i--) {
          node = nodes[i];
          if (node.isEmpty(nonEmptyElements) && node.getAll('br').length === 0) {
            node.append(new Node$1('br', 1)).shortEnded = true;
          }
        }
      });
      return parser;
    };
    var autoFocus = function (editor) {
      if (editor.settings.auto_focus) {
        Delay.setEditorTimeout(editor, function () {
          var focusEditor;
          if (editor.settings.auto_focus === true) {
            focusEditor = editor;
          } else {
            focusEditor = editor.editorManager.get(editor.settings.auto_focus);
          }
          if (!focusEditor.destroyed) {
            focusEditor.focus();
          }
        }, 100);
      }
    };
    var initEditor = function (editor) {
      editor.bindPendingEventDelegates();
      editor.initialized = true;
      editor.fire('init');
      editor.focus(true);
      editor.nodeChanged({ initial: true });
      editor.execCallback('init_instance_callback', editor);
      autoFocus(editor);
    };
    var getStyleSheetLoader = function (editor) {
      return editor.inline ? DOM$2.styleSheetLoader : editor.dom.styleSheetLoader;
    };
    var initContentBody = function (editor, skipWrite) {
      var settings = editor.settings;
      var targetElm = editor.getElement();
      var doc = editor.getDoc(), body, contentCssText;
      if (!settings.inline) {
        editor.getElement().style.visibility = editor.orgVisibility;
      }
      if (!skipWrite && !settings.content_editable) {
        doc.open();
        doc.write(editor.iframeHTML);
        doc.close();
      }
      if (settings.content_editable) {
        editor.on('remove', function () {
          var bodyEl = this.getBody();
          DOM$2.removeClass(bodyEl, 'mce-content-body');
          DOM$2.removeClass(bodyEl, 'mce-edit-focus');
          DOM$2.setAttrib(bodyEl, 'contentEditable', null);
        });
        DOM$2.addClass(targetElm, 'mce-content-body');
        editor.contentDocument = doc = settings.content_document || domGlobals.document;
        editor.contentWindow = settings.content_window || domGlobals.window;
        editor.bodyElement = targetElm;
        settings.content_document = settings.content_window = null;
        settings.root_name = targetElm.nodeName.toLowerCase();
      }
      body = editor.getBody();
      body.disabled = true;
      editor.readonly = settings.readonly;
      if (!editor.readonly) {
        if (editor.inline && DOM$2.getStyle(body, 'position', true) === 'static') {
          body.style.position = 'relative';
        }
        body.contentEditable = editor.getParam('content_editable_state', true);
      }
      body.disabled = false;
      editor.editorUpload = EditorUpload(editor);
      editor.schema = Schema(settings);
      editor.dom = DOMUtils$1(doc, {
        keep_values: true,
        url_converter: editor.convertURL,
        url_converter_scope: editor,
        hex_colors: settings.force_hex_style_colors,
        class_filter: settings.class_filter,
        update_styles: true,
        root_element: editor.inline ? editor.getBody() : null,
        collect: settings.content_editable,
        schema: editor.schema,
        contentCssCors: Settings.shouldUseContentCssCors(editor),
        onSetAttrib: function (e) {
          editor.fire('SetAttrib', e);
        }
      });
      editor.parser = createParser(editor);
      editor.serializer = DomSerializer$1(settings, editor);
      editor.selection = Selection$1(editor.dom, editor.getWin(), editor.serializer, editor);
      editor.annotator = Annotator(editor);
      editor.formatter = Formatter(editor);
      editor.undoManager = UndoManager(editor);
      editor._nodeChangeDispatcher = new NodeChange(editor);
      editor._selectionOverrides = SelectionOverrides(editor);
      setup$g(editor);
      setup$f(editor);
      KeyboardOverrides.setup(editor);
      ForceBlocks.setup(editor);
      editor.fire('PreInit');
      if (!settings.browser_spellcheck && !settings.gecko_spellcheck) {
        doc.body.spellcheck = false;
        DOM$2.setAttrib(body, 'spellcheck', 'false');
      }
      editor.quirks = Quirks(editor);
      editor.fire('PostRender');
      if (settings.directionality) {
        body.dir = settings.directionality;
      }
      if (settings.nowrap) {
        body.style.whiteSpace = 'nowrap';
      }
      if (settings.protect) {
        editor.on('BeforeSetContent', function (e) {
          Tools.each(settings.protect, function (pattern) {
            e.content = e.content.replace(pattern, function (str) {
              return '<!--mce:protected ' + escape(str) + '-->';
            });
          });
        });
      }
      editor.on('SetContent', function () {
        editor.addVisual(editor.getBody());
      });
      editor.load({
        initial: true,
        format: 'html'
      });
      editor.startContent = editor.getContent({ format: 'raw' });
      editor.on('compositionstart compositionend', function (e) {
        editor.composing = e.type === 'compositionstart';
      });
      if (editor.contentStyles.length > 0) {
        contentCssText = '';
        Tools.each(editor.contentStyles, function (style) {
          contentCssText += style + '\r\n';
        });
        editor.dom.addStyle(contentCssText);
      }
      getStyleSheetLoader(editor).loadAll(editor.contentCSS, function (_) {
        initEditor(editor);
      }, function (urls) {
        initEditor(editor);
      });
      if (settings.content_style) {
        appendStyle(editor, settings.content_style);
      }
    };
    var InitContentBody = { initContentBody: initContentBody };

    var DOM$3 = DOMUtils$1.DOM;
    var relaxDomain = function (editor, ifr) {
      if (domGlobals.document.domain !== domGlobals.window.location.hostname && Env.ie && Env.ie < 12) {
        var bodyUuid = Uuid.uuid('mce');
        editor[bodyUuid] = function () {
          InitContentBody.initContentBody(editor);
        };
        var domainRelaxUrl = 'javascript:(function(){' + 'document.open();document.domain="' + domGlobals.document.domain + '";' + 'var ed = window.parent.tinymce.get("' + editor.id + '");document.write(ed.iframeHTML);' + 'document.close();ed.' + bodyUuid + '(true);})()';
        DOM$3.setAttrib(ifr, 'src', domainRelaxUrl);
        return true;
      }
      return false;
    };
    var normalizeHeight = function (height) {
      var normalizedHeight = typeof height === 'number' ? height + 'px' : height;
      return normalizedHeight ? normalizedHeight : '';
    };
    var createIframeElement = function (id, title, height, customAttrs) {
      var iframe = Element.fromTag('iframe');
      setAll(iframe, customAttrs);
      setAll(iframe, {
        id: id + '_ifr',
        frameBorder: '0',
        allowTransparency: 'true',
        title: title
      });
      setAll$1(iframe, {
        width: '100%',
        height: normalizeHeight(height),
        display: 'block'
      });
      return iframe;
    };
    var getIframeHtml = function (editor) {
      var bodyId, bodyClass, iframeHTML;
      iframeHTML = Settings.getDocType(editor) + '<html><head>';
      if (Settings.getDocumentBaseUrl(editor) !== editor.documentBaseUrl) {
        iframeHTML += '<base href="' + editor.documentBaseURI.getURI() + '" />';
      }
      iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
      bodyId = Settings.getBodyId(editor);
      bodyClass = Settings.getBodyClass(editor);
      if (Settings.getContentSecurityPolicy(editor)) {
        iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + Settings.getContentSecurityPolicy(editor) + '" />';
      }
      iframeHTML += '</head><body id="' + bodyId + '" class="mce-content-body ' + bodyClass + '" data-id="' + editor.id + '"><br></body></html>';
      return iframeHTML;
    };
    var createIframe = function (editor, o) {
      var title = editor.editorManager.translate('Rich Text Area. Press ALT-F9 for menu. ' + 'Press ALT-F10 for toolbar. Press ALT-0 for help');
      var ifr = createIframeElement(editor.id, title, o.height, Settings.getIframeAttrs(editor)).dom();
      ifr.onload = function () {
        ifr.onload = null;
        editor.fire('load');
      };
      var isDomainRelaxed = relaxDomain(editor, ifr);
      editor.contentAreaContainer = o.iframeContainer;
      editor.iframeElement = ifr;
      editor.iframeHTML = getIframeHtml(editor);
      DOM$3.add(o.iframeContainer, ifr);
      return isDomainRelaxed;
    };
    var init$1 = function (editor, boxInfo) {
      var isDomainRelaxed = createIframe(editor, boxInfo);
      if (boxInfo.editorContainer) {
        DOM$3.get(boxInfo.editorContainer).style.display = editor.orgDisplay;
        editor.hidden = DOM$3.isHidden(boxInfo.editorContainer);
      }
      editor.getElement().style.display = 'none';
      DOM$3.setAttrib(editor.id, 'aria-hidden', 'true');
      if (!isDomainRelaxed) {
        InitContentBody.initContentBody(editor);
      }
    };
    var InitIframe = { init: init$1 };

    var DOM$4 = DOMUtils$1.DOM;
    var initPlugin = function (editor, initializedPlugins, plugin) {
      var Plugin = PluginManager$1.get(plugin);
      var pluginUrl = PluginManager$1.urls[plugin] || editor.documentBaseUrl.replace(/\/$/, '');
      plugin = Tools.trim(plugin);
      if (Plugin && Tools.inArray(initializedPlugins, plugin) === -1) {
        Tools.each(PluginManager$1.dependencies(plugin), function (dep) {
          initPlugin(editor, initializedPlugins, dep);
        });
        if (editor.plugins[plugin]) {
          return;
        }
        try {
          var pluginInstance = new Plugin(editor, pluginUrl, editor.$);
          editor.plugins[plugin] = pluginInstance;
          if (pluginInstance.init) {
            pluginInstance.init(editor, pluginUrl);
            initializedPlugins.push(plugin);
          }
        } catch (e) {
          ErrorReporter.pluginInitError(editor, plugin, e);
        }
      }
    };
    var trimLegacyPrefix = function (name) {
      return name.replace(/^\-/, '');
    };
    var initPlugins = function (editor) {
      var initializedPlugins = [];
      Tools.each(editor.settings.plugins.split(/[ ,]/), function (name) {
        initPlugin(editor, initializedPlugins, trimLegacyPrefix(name));
      });
    };
    var initTheme = function (editor) {
      var Theme;
      var theme = editor.settings.theme;
      if (isString(theme)) {
        editor.settings.theme = trimLegacyPrefix(theme);
        Theme = ThemeManager.get(theme);
        editor.theme = new Theme(editor, ThemeManager.urls[theme]);
        if (editor.theme.init) {
          editor.theme.init(editor, ThemeManager.urls[theme] || editor.documentBaseUrl.replace(/\/$/, ''), editor.$);
        }
      } else {
        editor.theme = {};
      }
    };
    var renderFromLoadedTheme = function (editor) {
      var w, h, minHeight, re, info;
      var settings = editor.settings;
      var elm = editor.getElement();
      w = settings.width || DOM$4.getStyle(elm, 'width') || '100%';
      h = settings.height || DOM$4.getStyle(elm, 'height') || elm.offsetHeight;
      minHeight = settings.min_height || 100;
      re = /^[0-9\.]+(|px)$/i;
      if (re.test('' + w)) {
        w = Math.max(parseInt(w, 10), 100);
      }
      if (re.test('' + h)) {
        h = Math.max(parseInt(h, 10), minHeight);
      }
      info = editor.theme.renderUI({
        targetNode: elm,
        width: w,
        height: h,
        deltaWidth: settings.delta_width,
        deltaHeight: settings.delta_height
      });
      if (!settings.content_editable) {
        h = (info.iframeHeight || h) + (typeof h === 'number' ? info.deltaHeight || 0 : '');
        if (h < minHeight) {
          h = minHeight;
        }
      }
      info.height = h;
      return info;
    };
    var renderFromThemeFunc = function (editor) {
      var info;
      var elm = editor.getElement();
      info = editor.settings.theme(editor, elm);
      if (info.editorContainer.nodeType) {
        info.editorContainer.id = info.editorContainer.id || editor.id + '_parent';
      }
      if (info.iframeContainer && info.iframeContainer.nodeType) {
        info.iframeContainer.id = info.iframeContainer.id || editor.id + '_iframecontainer';
      }
      info.height = info.iframeHeight ? info.iframeHeight : elm.offsetHeight;
      return info;
    };
    var createThemeFalseResult = function (element) {
      return {
        editorContainer: element,
        iframeContainer: element
      };
    };
    var renderThemeFalseIframe = function (targetElement) {
      var iframeContainer = DOM$4.create('div');
      DOM$4.insertAfter(iframeContainer, targetElement);
      return createThemeFalseResult(iframeContainer);
    };
    var renderThemeFalse = function (editor) {
      var targetElement = editor.getElement();
      return editor.inline ? createThemeFalseResult(null) : renderThemeFalseIframe(targetElement);
    };
    var renderThemeUi = function (editor) {
      var settings = editor.settings, elm = editor.getElement();
      editor.orgDisplay = elm.style.display;
      if (isString(settings.theme)) {
        return renderFromLoadedTheme(editor);
      } else if (isFunction(settings.theme)) {
        return renderFromThemeFunc(editor);
      } else {
        return renderThemeFalse(editor);
      }
    };
    var init$2 = function (editor) {
      var settings = editor.settings;
      var elm = editor.getElement();
      var boxInfo;
      editor.rtl = settings.rtl_ui || editor.editorManager.i18n.rtl;
      editor.editorManager.i18n.setCode(settings.language);
      settings.aria_label = settings.aria_label || DOM$4.getAttrib(elm, 'aria-label', editor.getLang('aria.rich_text_area'));
      editor.fire('ScriptsLoaded');
      initTheme(editor);
      initPlugins(editor);
      boxInfo = renderThemeUi(editor);
      editor.editorContainer = boxInfo.editorContainer ? boxInfo.editorContainer : null;
      if (settings.content_css) {
        Tools.each(Tools.explode(settings.content_css), function (u) {
          editor.contentCSS.push(editor.documentBaseURI.toAbsolute(u));
        });
      }
      if (settings.content_editable) {
        return InitContentBody.initContentBody(editor);
      } else {
        return InitIframe.init(editor, boxInfo);
      }
    };
    var Init = { init: init$2 };

    var DOM$5 = DOMUtils$1.DOM;
    var hasSkipLoadPrefix = function (name) {
      return name.charAt(0) === '-';
    };
    var loadLanguage = function (scriptLoader, editor) {
      var settings = editor.settings;
      if (settings.language && settings.language !== 'en' && !settings.language_url) {
        settings.language_url = editor.editorManager.baseURL + '/langs/' + settings.language + '.js';
      }
      if (settings.language_url && !editor.editorManager.i18n.data[settings.language]) {
        scriptLoader.add(settings.language_url);
      }
    };
    var loadTheme = function (scriptLoader, editor, suffix, callback) {
      var settings = editor.settings, theme = settings.theme;
      if (isString(theme)) {
        if (!hasSkipLoadPrefix(theme) && !ThemeManager.urls.hasOwnProperty(theme)) {
          var themeUrl = settings.theme_url;
          if (themeUrl) {
            ThemeManager.load(theme, editor.documentBaseURI.toAbsolute(themeUrl));
          } else {
            ThemeManager.load(theme, 'themes/' + theme + '/theme' + suffix + '.js');
          }
        }
        scriptLoader.loadQueue(function () {
          ThemeManager.waitFor(theme, callback);
        });
      } else {
        callback();
      }
    };
    var loadPlugins = function (settings, suffix) {
      if (Tools.isArray(settings.plugins)) {
        settings.plugins = settings.plugins.join(' ');
      }
      Tools.each(settings.external_plugins, function (url, name) {
        PluginManager$1.load(name, url);
        settings.plugins += ' ' + name;
      });
      Tools.each(settings.plugins.split(/[ ,]/), function (plugin) {
        plugin = Tools.trim(plugin);
        if (plugin && !PluginManager$1.urls[plugin]) {
          if (hasSkipLoadPrefix(plugin)) {
            plugin = plugin.substr(1, plugin.length);
            var dependencies = PluginManager$1.dependencies(plugin);
            Tools.each(dependencies, function (dep) {
              var defaultSettings = {
                prefix: 'plugins/',
                resource: dep,
                suffix: '/plugin' + suffix + '.js'
              };
              dep = PluginManager$1.createUrl(defaultSettings, dep);
              PluginManager$1.load(dep.resource, dep);
            });
          } else {
            PluginManager$1.load(plugin, {
              prefix: 'plugins/',
              resource: plugin,
              suffix: '/plugin' + suffix + '.js'
            });
          }
        }
      });
    };
    var loadScripts = function (editor, suffix) {
      var scriptLoader = ScriptLoader.ScriptLoader;
      loadTheme(scriptLoader, editor, suffix, function () {
        loadLanguage(scriptLoader, editor);
        loadPlugins(editor.settings, suffix);
        scriptLoader.loadQueue(function () {
          if (!editor.removed) {
            Init.init(editor);
          }
        }, editor, function (urls) {
          ErrorReporter.pluginLoadError(editor, urls[0]);
          if (!editor.removed) {
            Init.init(editor);
          }
        });
      });
    };
    var render = function (editor) {
      var settings = editor.settings, id = editor.id;
      var readyHandler = function () {
        DOM$5.unbind(domGlobals.window, 'ready', readyHandler);
        editor.render();
      };
      if (!EventUtils.Event.domLoaded) {
        DOM$5.bind(domGlobals.window, 'ready', readyHandler);
        return;
      }
      if (!editor.getElement()) {
        return;
      }
      if (!Env.contentEditable) {
        return;
      }
      if (!settings.inline) {
        editor.orgVisibility = editor.getElement().style.visibility;
        editor.getElement().style.visibility = 'hidden';
      } else {
        editor.inline = true;
      }
      var form = editor.getElement().form || DOM$5.getParent(id, 'form');
      if (form) {
        editor.formElement = form;
        if (settings.hidden_input && !/TEXTAREA|INPUT/i.test(editor.getElement().nodeName)) {
          DOM$5.insertAfter(DOM$5.create('input', {
            type: 'hidden',
            name: id
          }), id);
          editor.hasHiddenInput = true;
        }
        editor.formEventDelegate = function (e) {
          editor.fire(e.type, e);
        };
        DOM$5.bind(form, 'submit reset', editor.formEventDelegate);
        editor.on('reset', function () {
          editor.setContent(editor.startContent, { format: 'raw' });
        });
        if (settings.submit_patch && !form.submit.nodeType && !form.submit.length && !form._mceOldSubmit) {
          form._mceOldSubmit = form.submit;
          form.submit = function () {
            editor.editorManager.triggerSave();
            editor.setDirty(false);
            return form._mceOldSubmit(form);
          };
        }
      }
      editor.windowManager = WindowManager(editor);
      editor.notificationManager = NotificationManager(editor);
      if (settings.encoding === 'xml') {
        editor.on('GetContent', function (e) {
          if (e.save) {
            e.content = DOM$5.encode(e.content);
          }
        });
      }
      if (settings.add_form_submit_trigger) {
        editor.on('submit', function () {
          if (editor.initialized) {
            editor.save();
          }
        });
      }
      if (settings.add_unload_trigger) {
        editor._beforeUnload = function () {
          if (editor.initialized && !editor.destroyed && !editor.isHidden()) {
            editor.save({
              format: 'raw',
              no_events: true,
              set_dirty: false
            });
          }
        };
        editor.editorManager.on('BeforeUnload', editor._beforeUnload);
      }
      editor.editorManager.add(editor);
      loadScripts(editor, editor.suffix);
    };
    var Render = { render: render };

    var add$4 = function (editor, name, settings) {
      var sidebars = editor.sidebars ? editor.sidebars : [];
      sidebars.push({
        name: name,
        settings: settings
      });
      editor.sidebars = sidebars;
    };
    var Sidebar = { add: add$4 };

    var each$k = Tools.each, trim$4 = Tools.trim;
    var queryParts = 'source protocol authority userInfo user password host port relative path directory file query anchor'.split(' ');
    var DEFAULT_PORTS = {
      ftp: 21,
      http: 80,
      https: 443,
      mailto: 25
    };
    var URI = function (url, settings) {
      var self = this;
      var baseUri, baseUrl;
      url = trim$4(url);
      settings = self.settings = settings || {};
      baseUri = settings.base_uri;
      if (/^([\w\-]+):([^\/]{2})/i.test(url) || /^\s*#/.test(url)) {
        self.source = url;
        return;
      }
      var isProtocolRelative = url.indexOf('//') === 0;
      if (url.indexOf('/') === 0 && !isProtocolRelative) {
        url = (baseUri ? baseUri.protocol || 'http' : 'http') + '://mce_host' + url;
      }
      if (!/^[\w\-]*:?\/\//.test(url)) {
        baseUrl = settings.base_uri ? settings.base_uri.path : new URI(domGlobals.document.location.href).directory;
        if (settings.base_uri.protocol == '') {
          url = '//mce_host' + self.toAbsPath(baseUrl, url);
        } else {
          url = /([^#?]*)([#?]?.*)/.exec(url);
          url = (baseUri && baseUri.protocol || 'http') + '://mce_host' + self.toAbsPath(baseUrl, url[1]) + url[2];
        }
      }
      url = url.replace(/@@/g, '(mce_at)');
      url = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url);
      each$k(queryParts, function (v, i) {
        var part = url[i];
        if (part) {
          part = part.replace(/\(mce_at\)/g, '@@');
        }
        self[v] = part;
      });
      if (baseUri) {
        if (!self.protocol) {
          self.protocol = baseUri.protocol;
        }
        if (!self.userInfo) {
          self.userInfo = baseUri.userInfo;
        }
        if (!self.port && self.host === 'mce_host') {
          self.port = baseUri.port;
        }
        if (!self.host || self.host === 'mce_host') {
          self.host = baseUri.host;
        }
        self.source = '';
      }
      if (isProtocolRelative) {
        self.protocol = '';
      }
    };
    URI.prototype = {
      setPath: function (path) {
        var self = this;
        path = /^(.*?)\/?(\w+)?$/.exec(path);
        self.path = path[0];
        self.directory = path[1];
        self.file = path[2];
        self.source = '';
        self.getURI();
      },
      toRelative: function (uri) {
        var self = this;
        var output;
        if (uri === './') {
          return uri;
        }
        uri = new URI(uri, { base_uri: self });
        if (uri.host !== 'mce_host' && self.host !== uri.host && uri.host || self.port !== uri.port || self.protocol !== uri.protocol && uri.protocol !== '') {
          return uri.getURI();
        }
        var tu = self.getURI(), uu = uri.getURI();
        if (tu === uu || tu.charAt(tu.length - 1) === '/' && tu.substr(0, tu.length - 1) === uu) {
          return tu;
        }
        output = self.toRelPath(self.path, uri.path);
        if (uri.query) {
          output += '?' + uri.query;
        }
        if (uri.anchor) {
          output += '#' + uri.anchor;
        }
        return output;
      },
      toAbsolute: function (uri, noHost) {
        uri = new URI(uri, { base_uri: this });
        return uri.getURI(noHost && this.isSameOrigin(uri));
      },
      isSameOrigin: function (uri) {
        if (this.host == uri.host && this.protocol == uri.protocol) {
          if (this.port == uri.port) {
            return true;
          }
          var defaultPort = DEFAULT_PORTS[this.protocol];
          if (defaultPort && (this.port || defaultPort) == (uri.port || defaultPort)) {
            return true;
          }
        }
        return false;
      },
      toRelPath: function (base, path) {
        var items, breakPoint = 0, out = '', i, l;
        base = base.substring(0, base.lastIndexOf('/'));
        base = base.split('/');
        items = path.split('/');
        if (base.length >= items.length) {
          for (i = 0, l = base.length; i < l; i++) {
            if (i >= items.length || base[i] !== items[i]) {
              breakPoint = i + 1;
              break;
            }
          }
        }
        if (base.length < items.length) {
          for (i = 0, l = items.length; i < l; i++) {
            if (i >= base.length || base[i] !== items[i]) {
              breakPoint = i + 1;
              break;
            }
          }
        }
        if (breakPoint === 1) {
          return path;
        }
        for (i = 0, l = base.length - (breakPoint - 1); i < l; i++) {
          out += '../';
        }
        for (i = breakPoint - 1, l = items.length; i < l; i++) {
          if (i !== breakPoint - 1) {
            out += '/' + items[i];
          } else {
            out += items[i];
          }
        }
        return out;
      },
      toAbsPath: function (base, path) {
        var i, nb = 0, o = [], tr, outPath;
        tr = /\/$/.test(path) ? '/' : '';
        base = base.split('/');
        path = path.split('/');
        each$k(base, function (k) {
          if (k) {
            o.push(k);
          }
        });
        base = o;
        for (i = path.length - 1, o = []; i >= 0; i--) {
          if (path[i].length === 0 || path[i] === '.') {
            continue;
          }
          if (path[i] === '..') {
            nb++;
            continue;
          }
          if (nb > 0) {
            nb--;
            continue;
          }
          o.push(path[i]);
        }
        i = base.length - nb;
        if (i <= 0) {
          outPath = o.reverse().join('/');
        } else {
          outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/');
        }
        if (outPath.indexOf('/') !== 0) {
          outPath = '/' + outPath;
        }
        if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) {
          outPath += tr;
        }
        return outPath;
      },
      getURI: function (noProtoHost) {
        var s;
        var self = this;
        if (!self.source || noProtoHost) {
          s = '';
          if (!noProtoHost) {
            if (self.protocol) {
              s += self.protocol + '://';
            } else {
              s += '//';
            }
            if (self.userInfo) {
              s += self.userInfo + '@';
            }
            if (self.host) {
              s += self.host;
            }
            if (self.port) {
              s += ':' + self.port;
            }
          }
          if (self.path) {
            s += self.path;
          }
          if (self.query) {
            s += '?' + self.query;
          }
          if (self.anchor) {
            s += '#' + self.anchor;
          }
          self.source = s;
        }
        return self.source;
      }
    };
    URI.parseDataUri = function (uri) {
      var type, matches;
      uri = decodeURIComponent(uri).split(',');
      matches = /data:([^;]+)/.exec(uri[0]);
      if (matches) {
        type = matches[1];
      }
      return {
        type: type,
        data: uri[1]
      };
    };
    URI.getDocumentBaseUrl = function (loc) {
      var baseUrl;
      if (loc.protocol.indexOf('http') !== 0 && loc.protocol !== 'file:') {
        baseUrl = loc.href;
      } else {
        baseUrl = loc.protocol + '//' + loc.host + loc.pathname;
      }
      if (/^[^:]+:\/\/\/?[^\/]+\//.test(baseUrl)) {
        baseUrl = baseUrl.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
        if (!/[\/\\]$/.test(baseUrl)) {
          baseUrl += '/';
        }
      }
      return baseUrl;
    };

    var defaultFormat = 'html';
    var trimEmptyContents = function (editor, html) {
      var blockName = Settings.getForcedRootBlock(editor);
      var emptyRegExp = new RegExp('^(<' + blockName + '[^>]*>(&nbsp;|&#160;|\\s|\xA0|<br \\/>|)<\\/' + blockName + '>[\r\n]*|<br \\/>[\r\n]*)$');
      return html.replace(emptyRegExp, '');
    };
    var getContentFromBody = function (editor, args, body) {
      var content;
      args.format = args.format ? args.format : defaultFormat;
      args.get = true;
      args.getInner = true;
      if (!args.no_events) {
        editor.fire('BeforeGetContent', args);
      }
      if (args.format === 'raw') {
        content = Tools.trim(TrimHtml.trimExternal(editor.serializer, body.innerHTML));
      } else if (args.format === 'text') {
        content = Zwsp.trim(body.innerText || body.textContent);
      } else if (args.format === 'tree') {
        return editor.serializer.serialize(body, args);
      } else {
        content = trimEmptyContents(editor, editor.serializer.serialize(body, args));
      }
      if (args.format !== 'text' && !isWsPreserveElement(Element.fromDom(body))) {
        args.content = Tools.trim(content);
      } else {
        args.content = content;
      }
      if (!args.no_events) {
        editor.fire('GetContent', args);
      }
      return args.content;
    };
    var getContent$1 = function (editor, args) {
      if (args === void 0) {
        args = {};
      }
      return Option.from(editor.getBody()).fold(constant(args.format === 'tree' ? new Node$1('body', 11) : ''), function (body) {
        return getContentFromBody(editor, args, body);
      });
    };

    var traverse = function (node, fn) {
      fn(node);
      if (node.firstChild) {
        traverse(node.firstChild, fn);
      }
      if (node.next) {
        traverse(node.next, fn);
      }
    };
    var findMatchingNodes = function (nodeFilters, attributeFilters, node) {
      var nodeMatches = {};
      var attrMatches = {};
      var matches = [];
      if (node.firstChild) {
        traverse(node.firstChild, function (node) {
          each(nodeFilters, function (filter) {
            if (filter.name === node.name) {
              if (nodeMatches[filter.name]) {
                nodeMatches[filter.name].nodes.push(node);
              } else {
                nodeMatches[filter.name] = {
                  filter: filter,
                  nodes: [node]
                };
              }
            }
          });
          each(attributeFilters, function (filter) {
            if (typeof node.attr(filter.name) === 'string') {
              if (attrMatches[filter.name]) {
                attrMatches[filter.name].nodes.push(node);
              } else {
                attrMatches[filter.name] = {
                  filter: filter,
                  nodes: [node]
                };
              }
            }
          });
        });
      }
      for (var name in nodeMatches) {
        if (nodeMatches.hasOwnProperty(name)) {
          matches.push(nodeMatches[name]);
        }
      }
      for (var name in attrMatches) {
        if (attrMatches.hasOwnProperty(name)) {
          matches.push(attrMatches[name]);
        }
      }
      return matches;
    };
    var filter$3 = function (nodeFilters, attributeFilters, node) {
      var matches = findMatchingNodes(nodeFilters, attributeFilters, node);
      each(matches, function (match) {
        each(match.filter.callbacks, function (callback) {
          callback(match.nodes, match.filter.name, {});
        });
      });
    };

    var defaultFormat$1 = 'html';
    var isTreeNode = function (content) {
      return content instanceof Node$1;
    };
    var moveSelection = function (editor) {
      if (EditorFocus.hasFocus(editor)) {
        CaretFinder.firstPositionIn(editor.getBody()).each(function (pos) {
          var node = pos.getNode();
          var caretPos = NodeType.isTable(node) ? CaretFinder.firstPositionIn(node).getOr(pos) : pos;
          editor.selection.setRng(caretPos.toRange());
        });
      }
    };
    var setEditorHtml = function (editor, html) {
      editor.dom.setHTML(editor.getBody(), html);
      moveSelection(editor);
    };
    var setContentString = function (editor, body, content, args) {
      var forcedRootBlockName, padd;
      if (content.length === 0 || /^\s+$/.test(content)) {
        padd = '<br data-mce-bogus="1">';
        if (body.nodeName === 'TABLE') {
          content = '<tr><td>' + padd + '</td></tr>';
        } else if (/^(UL|OL)$/.test(body.nodeName)) {
          content = '<li>' + padd + '</li>';
        }
        forcedRootBlockName = Settings.getForcedRootBlock(editor);
        if (forcedRootBlockName && editor.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
          content = padd;
          content = editor.dom.createHTML(forcedRootBlockName, editor.settings.forced_root_block_attrs, content);
        } else if (!content) {
          content = '<br data-mce-bogus="1">';
        }
        setEditorHtml(editor, content);
        editor.fire('SetContent', args);
      } else {
        if (args.format !== 'raw') {
          content = HtmlSerializer({ validate: editor.validate }, editor.schema).serialize(editor.parser.parse(content, {
            isRootContent: true,
            insert: true
          }));
        }
        args.content = isWsPreserveElement(Element.fromDom(body)) ? content : Tools.trim(content);
        setEditorHtml(editor, args.content);
        if (!args.no_events) {
          editor.fire('SetContent', args);
        }
      }
      return args.content;
    };
    var setContentTree = function (editor, body, content, args) {
      filter$3(editor.parser.getNodeFilters(), editor.parser.getAttributeFilters(), content);
      var html = HtmlSerializer({ validate: editor.validate }, editor.schema).serialize(content);
      args.content = isWsPreserveElement(Element.fromDom(body)) ? html : Tools.trim(html);
      setEditorHtml(editor, args.content);
      if (!args.no_events) {
        editor.fire('SetContent', args);
      }
      return content;
    };
    var setContent$1 = function (editor, content, args) {
      if (args === void 0) {
        args = {};
      }
      args.format = args.format ? args.format : defaultFormat$1;
      args.set = true;
      args.content = isTreeNode(content) ? '' : content;
      if (!isTreeNode(content) && !args.no_events) {
        editor.fire('BeforeSetContent', args);
        content = args.content;
      }
      return Option.from(editor.getBody()).fold(constant(content), function (body) {
        return isTreeNode(content) ? setContentTree(editor, body, content, args) : setContentString(editor, body, content, args);
      });
    };

    var DOM$6 = DOMUtils$1.DOM;
    var restoreOriginalStyles = function (editor) {
      DOM$6.setStyle(editor.id, 'display', editor.orgDisplay);
    };
    var safeDestroy = function (x) {
      return Option.from(x).each(function (x) {
        return x.destroy();
      });
    };
    var clearDomReferences = function (editor) {
      editor.contentAreaContainer = editor.formElement = editor.container = editor.editorContainer = null;
      editor.bodyElement = editor.contentDocument = editor.contentWindow = null;
      editor.iframeElement = editor.targetElm = null;
      if (editor.selection) {
        editor.selection = editor.selection.win = editor.selection.dom = editor.selection.dom.doc = null;
      }
    };
    var restoreForm = function (editor) {
      var form = editor.formElement;
      if (form) {
        if (form._mceOldSubmit) {
          form.submit = form._mceOldSubmit;
          form._mceOldSubmit = null;
        }
        DOM$6.unbind(form, 'submit reset', editor.formEventDelegate);
      }
    };
    var remove$7 = function (editor) {
      if (!editor.removed) {
        var _selectionOverrides = editor._selectionOverrides, editorUpload = editor.editorUpload;
        var body = editor.getBody();
        var element = editor.getElement();
        if (body) {
          editor.save({ is_removing: true });
        }
        editor.removed = true;
        editor.unbindAllNativeEvents();
        if (editor.hasHiddenInput && element) {
          DOM$6.remove(element.nextSibling);
        }
        Events.fireRemove(editor);
        editor.editorManager.remove(editor);
        if (!editor.inline && body) {
          restoreOriginalStyles(editor);
        }
        Events.fireDetach(editor);
        DOM$6.remove(editor.getContainer());
        safeDestroy(_selectionOverrides);
        safeDestroy(editorUpload);
        editor.destroy();
      }
    };
    var destroy = function (editor, automatic) {
      var selection = editor.selection, dom = editor.dom;
      if (editor.destroyed) {
        return;
      }
      if (!automatic && !editor.removed) {
        editor.remove();
        return;
      }
      if (!automatic) {
        editor.editorManager.off('beforeunload', editor._beforeUnload);
        if (editor.theme && editor.theme.destroy) {
          editor.theme.destroy();
        }
        safeDestroy(selection);
        safeDestroy(dom);
      }
      restoreForm(editor);
      clearDomReferences(editor);
      editor.destroyed = true;
    };

    var DOM$7 = DOMUtils$1.DOM;
    var extend$4 = Tools.extend, each$l = Tools.each;
    var resolve$4 = Tools.resolve;
    var ie$2 = Env.ie;
    var Editor = function (id, settings, editorManager) {
      var self = this;
      var documentBaseUrl = self.documentBaseUrl = editorManager.documentBaseURL;
      var baseUri = editorManager.baseURI;
      settings = getEditorSettings(self, id, documentBaseUrl, editorManager.defaultSettings, settings);
      self.settings = settings;
      AddOnManager.language = settings.language || 'en';
      AddOnManager.languageLoad = settings.language_load;
      AddOnManager.baseURL = editorManager.baseURL;
      self.id = id;
      self.setDirty(false);
      self.plugins = {};
      self.documentBaseURI = new URI(settings.document_base_url, { base_uri: baseUri });
      self.baseURI = baseUri;
      self.contentCSS = [];
      self.contentStyles = [];
      self.shortcuts = new Shortcuts(self);
      self.loadedCSS = {};
      self.editorCommands = new EditorCommands(self);
      self.suffix = editorManager.suffix;
      self.editorManager = editorManager;
      self.inline = settings.inline;
      self.buttons = {};
      self.menuItems = {};
      if (settings.cache_suffix) {
        Env.cacheSuffix = settings.cache_suffix.replace(/^[\?\&]+/, '');
      }
      if (settings.override_viewport === false) {
        Env.overrideViewPort = false;
      }
      editorManager.fire('SetupEditor', { editor: self });
      self.execCallback('setup', self);
      self.$ = DomQuery.overrideDefaults(function () {
        return {
          context: self.inline ? self.getBody() : self.getDoc(),
          element: self.getBody()
        };
      });
    };
    Editor.prototype = {
      render: function () {
        Render.render(this);
      },
      focus: function (skipFocus) {
        EditorFocus.focus(this, skipFocus);
      },
      hasFocus: function () {
        return EditorFocus.hasFocus(this);
      },
      execCallback: function (name) {
        var x = [];
        for (var _i = 1; _i < arguments.length; _i++) {
          x[_i - 1] = arguments[_i];
        }
        var self = this;
        var callback = self.settings[name], scope;
        if (!callback) {
          return;
        }
        if (self.callbackLookup && (scope = self.callbackLookup[name])) {
          callback = scope.func;
          scope = scope.scope;
        }
        if (typeof callback === 'string') {
          scope = callback.replace(/\.\w+$/, '');
          scope = scope ? resolve$4(scope) : 0;
          callback = resolve$4(callback);
          self.callbackLookup = self.callbackLookup || {};
          self.callbackLookup[name] = {
            func: callback,
            scope: scope
          };
        }
        return callback.apply(scope || self, Array.prototype.slice.call(arguments, 1));
      },
      translate: function (text) {
        if (text && Tools.is(text, 'string')) {
          var lang_1 = this.settings.language || 'en', i18n_1 = this.editorManager.i18n;
          text = i18n_1.data[lang_1 + '.' + text] || text.replace(/\{\#([^\}]+)\}/g, function (a, b) {
            return i18n_1.data[lang_1 + '.' + b] || '{#' + b + '}';
          });
        }
        return this.editorManager.translate(text);
      },
      getLang: function (name, defaultVal) {
        return this.editorManager.i18n.data[(this.settings.language || 'en') + '.' + name] || (defaultVal !== undefined ? defaultVal : '{#' + name + '}');
      },
      getParam: function (name, defaultVal, type) {
        return getParam(this, name, defaultVal, type);
      },
      nodeChanged: function (args) {
        this._nodeChangeDispatcher.nodeChanged(args);
      },
      addButton: function (name, settings) {
        var self = this;
        if (settings.cmd) {
          settings.onclick = function () {
            self.execCommand(settings.cmd);
          };
        }
        if (settings.stateSelector && typeof settings.active === 'undefined') {
          settings.active = false;
        }
        if (!settings.text && !settings.icon) {
          settings.icon = name;
        }
        settings.tooltip = settings.tooltip || settings.title;
        self.buttons[name] = settings;
      },
      addSidebar: function (name, settings) {
        return Sidebar.add(this, name, settings);
      },
      addMenuItem: function (name, settings) {
        var self = this;
        if (settings.cmd) {
          settings.onclick = function () {
            self.execCommand(settings.cmd);
          };
        }
        self.menuItems[name] = settings;
      },
      addContextToolbar: function (predicate, items) {
        var self = this;
        var selector;
        self.contextToolbars = self.contextToolbars || [];
        if (typeof predicate === 'string') {
          selector = predicate;
          predicate = function (elm) {
            return self.dom.is(elm, selector);
          };
        }
        self.contextToolbars.push({
          id: Uuid.uuid('mcet'),
          predicate: predicate,
          items: items
        });
      },
      addCommand: function (name, callback, scope) {
        this.editorCommands.addCommand(name, callback, scope);
      },
      addQueryStateHandler: function (name, callback, scope) {
        this.editorCommands.addQueryStateHandler(name, callback, scope);
      },
      addQueryValueHandler: function (name, callback, scope) {
        this.editorCommands.addQueryValueHandler(name, callback, scope);
      },
      addShortcut: function (pattern, desc, cmdFunc, scope) {
        this.shortcuts.add(pattern, desc, cmdFunc, scope);
      },
      execCommand: function (cmd, ui, value, args) {
        return this.editorCommands.execCommand(cmd, ui, value, args);
      },
      queryCommandState: function (cmd) {
        return this.editorCommands.queryCommandState(cmd);
      },
      queryCommandValue: function (cmd) {
        return this.editorCommands.queryCommandValue(cmd);
      },
      queryCommandSupported: function (cmd) {
        return this.editorCommands.queryCommandSupported(cmd);
      },
      show: function () {
        var self = this;
        if (self.hidden) {
          self.hidden = false;
          if (self.inline) {
            self.getBody().contentEditable = true;
          } else {
            DOM$7.show(self.getContainer());
            DOM$7.hide(self.id);
          }
          self.load();
          self.fire('show');
        }
      },
      hide: function () {
        var self = this, doc = self.getDoc();
        if (!self.hidden) {
          if (ie$2 && doc && !self.inline) {
            doc.execCommand('SelectAll');
          }
          self.save();
          if (self.inline) {
            self.getBody().contentEditable = false;
            if (self === self.editorManager.focusedEditor) {
              self.editorManager.focusedEditor = null;
            }
          } else {
            DOM$7.hide(self.getContainer());
            DOM$7.setStyle(self.id, 'display', self.orgDisplay);
          }
          self.hidden = true;
          self.fire('hide');
        }
      },
      isHidden: function () {
        return !!this.hidden;
      },
      setProgressState: function (state, time) {
        this.fire('ProgressState', {
          state: state,
          time: time
        });
      },
      load: function (args) {
        var self = this;
        var elm = self.getElement(), html;
        if (self.removed) {
          return '';
        }
        if (elm) {
          args = args || {};
          args.load = true;
          html = self.setContent(elm.value !== undefined ? elm.value : elm.innerHTML, args);
          args.element = elm;
          if (!args.no_events) {
            self.fire('LoadContent', args);
          }
          args.element = elm = null;
          return html;
        }
      },
      save: function (args) {
        var self = this;
        var elm = self.getElement(), html, form;
        if (!elm || !self.initialized || self.removed) {
          return;
        }
        args = args || {};
        args.save = true;
        args.element = elm;
        html = args.content = self.getContent(args);
        if (!args.no_events) {
          self.fire('SaveContent', args);
        }
        if (args.format === 'raw') {
          self.fire('RawSaveContent', args);
        }
        html = args.content;
        if (!/TEXTAREA|INPUT/i.test(elm.nodeName)) {
          if (args.is_removing || !self.inline) {
            elm.innerHTML = html;
          }
          if (form = DOM$7.getParent(self.id, 'form')) {
            each$l(form.elements, function (elm) {
              if (elm.name === self.id) {
                elm.value = html;
                return false;
              }
            });
          }
        } else {
          elm.value = html;
        }
        args.element = elm = null;
        if (args.set_dirty !== false) {
          self.setDirty(false);
        }
        return html;
      },
      setContent: function (content, args) {
        return setContent$1(this, content, args);
      },
      getContent: function (args) {
        return getContent$1(this, args);
      },
      insertContent: function (content, args) {
        if (args) {
          content = extend$4({ content: content }, args);
        }
        this.execCommand('mceInsertContent', false, content);
      },
      isDirty: function () {
        return !this.isNotDirty;
      },
      setDirty: function (state) {
        var oldState = !this.isNotDirty;
        this.isNotDirty = !state;
        if (state && state !== oldState) {
          this.fire('dirty');
        }
      },
      setMode: function (mode) {
        setMode(this, mode);
      },
      getContainer: function () {
        var self = this;
        if (!self.container) {
          self.container = DOM$7.get(self.editorContainer || self.id + '_parent');
        }
        return self.container;
      },
      getContentAreaContainer: function () {
        return this.contentAreaContainer;
      },
      getElement: function () {
        if (!this.targetElm) {
          this.targetElm = DOM$7.get(this.id);
        }
        return this.targetElm;
      },
      getWin: function () {
        var self = this;
        var elm;
        if (!self.contentWindow) {
          elm = self.iframeElement;
          if (elm) {
            self.contentWindow = elm.contentWindow;
          }
        }
        return self.contentWindow;
      },
      getDoc: function () {
        var self = this;
        var win;
        if (!self.contentDocument) {
          win = self.getWin();
          if (win) {
            self.contentDocument = win.document;
          }
        }
        return self.contentDocument;
      },
      getBody: function () {
        var doc = this.getDoc();
        return this.bodyElement || (doc ? doc.body : null);
      },
      convertURL: function (url, name, elm) {
        var self = this, settings = self.settings;
        if (settings.urlconverter_callback) {
          return self.execCallback('urlconverter_callback', url, elm, true, name);
        }
        if (!settings.convert_urls || elm && elm.nodeName === 'LINK' || url.indexOf('file:') === 0 || url.length === 0) {
          return url;
        }
        if (settings.relative_urls) {
          return self.documentBaseURI.toRelative(url);
        }
        url = self.documentBaseURI.toAbsolute(url, settings.remove_script_host);
        return url;
      },
      addVisual: function (elm) {
        var self = this;
        var settings = self.settings;
        var dom = self.dom;
        var cls;
        elm = elm || self.getBody();
        if (self.hasVisual === undefined) {
          self.hasVisual = settings.visual;
        }
        each$l(dom.select('table,a', elm), function (elm) {
          var value;
          switch (elm.nodeName) {
          case 'TABLE':
            cls = settings.visual_table_class || 'mce-item-table';
            value = dom.getAttrib(elm, 'border');
            if ((!value || value === '0') && self.hasVisual) {
              dom.addClass(elm, cls);
            } else {
              dom.removeClass(elm, cls);
            }
            return;
          case 'A':
            if (!dom.getAttrib(elm, 'href')) {
              value = dom.getAttrib(elm, 'name') || elm.id;
              cls = settings.visual_anchor_class || 'mce-item-anchor';
              if (value && self.hasVisual) {
                dom.addClass(elm, cls);
              } else {
                dom.removeClass(elm, cls);
              }
            }
            return;
          }
        });
        self.fire('VisualAid', {
          element: elm,
          hasVisual: self.hasVisual
        });
      },
      remove: function () {
        remove$7(this);
      },
      destroy: function (automatic) {
        destroy(this, automatic);
      },
      uploadImages: function (callback) {
        return this.editorUpload.uploadImages(callback);
      },
      _scanForImages: function () {
        return this.editorUpload.scanForImages();
      }
    };
    extend$4(Editor.prototype, EditorObservable$1);

    var isEditorUIElement = function (elm) {
      return elm.className.toString().indexOf('mce-') !== -1;
    };
    var FocusManager = { isEditorUIElement: isEditorUIElement };

    var isManualNodeChange = function (e) {
      return e.type === 'nodechange' && e.selectionChange;
    };
    var registerPageMouseUp = function (editor, throttledStore) {
      var mouseUpPage = function () {
        throttledStore.throttle();
      };
      DOMUtils$1.DOM.bind(domGlobals.document, 'mouseup', mouseUpPage);
      editor.on('remove', function () {
        DOMUtils$1.DOM.unbind(domGlobals.document, 'mouseup', mouseUpPage);
      });
    };
    var registerFocusOut = function (editor) {
      editor.on('focusout', function () {
        SelectionBookmark.store(editor);
      });
    };
    var registerMouseUp = function (editor, throttledStore) {
      editor.on('mouseup touchend', function (e) {
        throttledStore.throttle();
      });
    };
    var registerEditorEvents = function (editor, throttledStore) {
      var browser = PlatformDetection$1.detect().browser;
      if (browser.isIE()) {
        registerFocusOut(editor);
      } else {
        registerMouseUp(editor, throttledStore);
      }
      editor.on('keyup nodechange', function (e) {
        if (!isManualNodeChange(e)) {
          SelectionBookmark.store(editor);
        }
      });
    };
    var register$3 = function (editor) {
      var throttledStore = first(function () {
        SelectionBookmark.store(editor);
      }, 0);
      if (editor.inline) {
        registerPageMouseUp(editor, throttledStore);
      }
      editor.on('init', function () {
        registerEditorEvents(editor, throttledStore);
      });
      editor.on('remove', function () {
        throttledStore.cancel();
      });
    };
    var SelectionRestore = { register: register$3 };

    var documentFocusInHandler;
    var DOM$8 = DOMUtils$1.DOM;
    var isEditorUIElement$1 = function (elm) {
      return FocusManager.isEditorUIElement(elm);
    };
    var isUIElement = function (editor, elm) {
      var customSelector = editor ? editor.settings.custom_ui_selector : '';
      var parent = DOM$8.getParent(elm, function (elm) {
        return isEditorUIElement$1(elm) || (customSelector ? editor.dom.is(elm, customSelector) : false);
      });
      return parent !== null;
    };
    var getActiveElement = function () {
      try {
        return domGlobals.document.activeElement;
      } catch (ex) {
        return domGlobals.document.body;
      }
    };
    var registerEvents = function (editorManager, e) {
      var editor = e.editor;
      SelectionRestore.register(editor);
      editor.on('focusin', function () {
        var self = this;
        var focusedEditor = editorManager.focusedEditor;
        if (focusedEditor !== self) {
          if (focusedEditor) {
            focusedEditor.fire('blur', { focusedEditor: self });
          }
          editorManager.setActive(self);
          editorManager.focusedEditor = self;
          self.fire('focus', { blurredEditor: focusedEditor });
          self.focus(true);
        }
      });
      editor.on('focusout', function () {
        var self = this;
        Delay.setEditorTimeout(self, function () {
          var focusedEditor = editorManager.focusedEditor;
          if (!isUIElement(self, getActiveElement()) && focusedEditor === self) {
            self.fire('blur', { focusedEditor: null });
            editorManager.focusedEditor = null;
          }
        });
      });
      if (!documentFocusInHandler) {
        documentFocusInHandler = function (e) {
          var activeEditor = editorManager.activeEditor;
          var target;
          target = e.target;
          if (activeEditor && target.ownerDocument === domGlobals.document) {
            if (target !== domGlobals.document.body && !isUIElement(activeEditor, target) && editorManager.focusedEditor === activeEditor) {
              activeEditor.fire('blur', { focusedEditor: null });
              editorManager.focusedEditor = null;
            }
          }
        };
        DOM$8.bind(domGlobals.document, 'focusin', documentFocusInHandler);
      }
    };
    var unregisterDocumentEvents = function (editorManager, e) {
      if (editorManager.focusedEditor === e.editor) {
        editorManager.focusedEditor = null;
      }
      if (!editorManager.activeEditor) {
        DOM$8.unbind(domGlobals.document, 'focusin', documentFocusInHandler);
        documentFocusInHandler = null;
      }
    };
    var setup$h = function (editorManager) {
      editorManager.on('AddEditor', curry(registerEvents, editorManager));
      editorManager.on('RemoveEditor', curry(unregisterDocumentEvents, editorManager));
    };
    var FocusController = {
      setup: setup$h,
      isEditorUIElement: isEditorUIElement$1,
      isUIElement: isUIElement
    };

    var DOM$9 = DOMUtils$1.DOM;
    var explode$4 = Tools.explode, each$m = Tools.each, extend$5 = Tools.extend;
    var instanceCounter = 0, beforeUnloadDelegate, EditorManager, boundGlobalEvents = false;
    var legacyEditors = [];
    var editors = [];
    var isValidLegacyKey = function (id) {
      return id !== 'length';
    };
    var globalEventDelegate = function (e) {
      var type = e.type;
      each$m(EditorManager.get(), function (editor) {
        switch (type) {
        case 'scroll':
          editor.fire('ScrollWindow', e);
          break;
        case 'resize':
          editor.fire('ResizeWindow', e);
          break;
        }
      });
    };
    var toggleGlobalEvents = function (state) {
      if (state !== boundGlobalEvents) {
        if (state) {
          DomQuery(window).on('resize scroll', globalEventDelegate);
        } else {
          DomQuery(window).off('resize scroll', globalEventDelegate);
        }
        boundGlobalEvents = state;
      }
    };
    var removeEditorFromList = function (targetEditor) {
      var oldEditors = editors;
      delete legacyEditors[targetEditor.id];
      for (var i = 0; i < legacyEditors.length; i++) {
        if (legacyEditors[i] === targetEditor) {
          legacyEditors.splice(i, 1);
          break;
        }
      }
      editors = filter(editors, function (editor) {
        return targetEditor !== editor;
      });
      if (EditorManager.activeEditor === targetEditor) {
        EditorManager.activeEditor = editors.length > 0 ? editors[0] : null;
      }
      if (EditorManager.focusedEditor === targetEditor) {
        EditorManager.focusedEditor = null;
      }
      return oldEditors.length !== editors.length;
    };
    var purgeDestroyedEditor = function (editor) {
      if (editor && editor.initialized && !(editor.getContainer() || editor.getBody()).parentNode) {
        removeEditorFromList(editor);
        editor.unbindAllNativeEvents();
        editor.destroy(true);
        editor.removed = true;
        editor = null;
      }
      return editor;
    };
    EditorManager = {
      defaultSettings: {},
      $: DomQuery,
      majorVersion: '4',
      minorVersion: '9.11',
      releaseDate: '2020-07-13',
      editors: legacyEditors,
      i18n: I18n,
      activeEditor: null,
      settings: {},
      setup: function () {
        var self = this;
        var baseURL, documentBaseURL, suffix = '';
        documentBaseURL = URI.getDocumentBaseUrl(domGlobals.document.location);
        if (/^[^:]+:\/\/\/?[^\/]+\//.test(documentBaseURL)) {
          documentBaseURL = documentBaseURL.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
          if (!/[\/\\]$/.test(documentBaseURL)) {
            documentBaseURL += '/';
          }
        }
        var preInit = window.tinymce || window.tinyMCEPreInit;
        if (preInit) {
          baseURL = preInit.base || preInit.baseURL;
          suffix = preInit.suffix;
        } else {
          var scripts = domGlobals.document.getElementsByTagName('script');
          for (var i = 0; i < scripts.length; i++) {
            var src = scripts[i].src || '';
            if (src === '') {
              continue;
            }
            var srcScript = src.substring(src.lastIndexOf('/'));
            if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
              if (srcScript.indexOf('.min') !== -1) {
                suffix = '.min';
              }
              baseURL = src.substring(0, src.lastIndexOf('/'));
              break;
            }
          }
          if (!baseURL && domGlobals.document.currentScript) {
            var src = domGlobals.document.currentScript.src;
            if (src.indexOf('.min') !== -1) {
              suffix = '.min';
            }
            baseURL = src.substring(0, src.lastIndexOf('/'));
          }
        }
        self.baseURL = new URI(documentBaseURL).toAbsolute(baseURL);
        self.documentBaseURL = documentBaseURL;
        self.baseURI = new URI(self.baseURL);
        self.suffix = suffix;
        FocusController.setup(self);
      },
      overrideDefaults: function (defaultSettings) {
        var baseUrl, suffix;
        baseUrl = defaultSettings.base_url;
        if (baseUrl) {
          this.baseURL = new URI(this.documentBaseURL).toAbsolute(baseUrl.replace(/\/+$/, ''));
          this.baseURI = new URI(this.baseURL);
        }
        suffix = defaultSettings.suffix;
        if (defaultSettings.suffix) {
          this.suffix = suffix;
        }
        this.defaultSettings = defaultSettings;
        var pluginBaseUrls = defaultSettings.plugin_base_urls;
        for (var name in pluginBaseUrls) {
          AddOnManager.PluginManager.urls[name] = pluginBaseUrls[name];
        }
      },
      init: function (settings) {
        var self = this;
        var result, invalidInlineTargets;
        invalidInlineTargets = Tools.makeMap('area base basefont br col frame hr img input isindex link meta param embed source wbr track ' + 'colgroup option tbody tfoot thead tr script noscript style textarea video audio iframe object menu', ' ');
        var isInvalidInlineTarget = function (settings, elm) {
          return settings.inline && elm.tagName.toLowerCase() in invalidInlineTargets;
        };
        var createId = function (elm) {
          var id = elm.id;
          if (!id) {
            id = elm.name;
            if (id && !DOM$9.get(id)) {
              id = elm.name;
            } else {
              id = DOM$9.uniqueId();
            }
            elm.setAttribute('id', id);
          }
          return id;
        };
        var execCallback = function (name) {
          var callback = settings[name];
          if (!callback) {
            return;
          }
          return callback.apply(self, Array.prototype.slice.call(arguments, 2));
        };
        var hasClass = function (elm, className) {
          return className.constructor === RegExp ? className.test(elm.className) : DOM$9.hasClass(elm, className);
        };
        var findTargets = function (settings) {
          var l, targets = [];
          if (Env.ie && Env.ie < 11) {
            ErrorReporter.initError('TinyMCE does not support the browser you are using. For a list of supported' + ' browsers please see: https://www.tinymce.com/docs/get-started/system-requirements/');
            return [];
          }
          if (settings.types) {
            each$m(settings.types, function (type) {
              targets = targets.concat(DOM$9.select(type.selector));
            });
            return targets;
          } else if (settings.selector) {
            return DOM$9.select(settings.selector);
          } else if (settings.target) {
            return [settings.target];
          }
          switch (settings.mode) {
          case 'exact':
            l = settings.elements || '';
            if (l.length > 0) {
              each$m(explode$4(l), function (id) {
                var elm;
                if (elm = DOM$9.get(id)) {
                  targets.push(elm);
                } else {
                  each$m(domGlobals.document.forms, function (f) {
                    each$m(f.elements, function (e) {
                      if (e.name === id) {
                        id = 'mce_editor_' + instanceCounter++;
                        DOM$9.setAttrib(e, 'id', id);
                        targets.push(e);
                      }
                    });
                  });
                }
              });
            }
            break;
          case 'textareas':
          case 'specific_textareas':
            each$m(DOM$9.select('textarea'), function (elm) {
              if (settings.editor_deselector && hasClass(elm, settings.editor_deselector)) {
                return;
              }
              if (!settings.editor_selector || hasClass(elm, settings.editor_selector)) {
                targets.push(elm);
              }
            });
            break;
          }
          return targets;
        };
        var provideResults = function (editors) {
          result = editors;
        };
        var initEditors = function () {
          var initCount = 0;
          var editors = [];
          var targets;
          var createEditor = function (id, settings, targetElm) {
            var editor = new Editor(id, settings, self);
            editors.push(editor);
            editor.on('init', function () {
              if (++initCount === targets.length) {
                provideResults(editors);
              }
            });
            editor.targetElm = editor.targetElm || targetElm;
            editor.render();
          };
          DOM$9.unbind(window, 'ready', initEditors);
          execCallback('onpageload');
          targets = DomQuery.unique(findTargets(settings));
          if (settings.types) {
            each$m(settings.types, function (type) {
              Tools.each(targets, function (elm) {
                if (DOM$9.is(elm, type.selector)) {
                  createEditor(createId(elm), extend$5({}, settings, type), elm);
                  return false;
                }
                return true;
              });
            });
            return;
          }
          Tools.each(targets, function (elm) {
            purgeDestroyedEditor(self.get(elm.id));
          });
          targets = Tools.grep(targets, function (elm) {
            return !self.get(elm.id);
          });
          if (targets.length === 0) {
            provideResults([]);
          } else {
            each$m(targets, function (elm) {
              if (isInvalidInlineTarget(settings, elm)) {
                ErrorReporter.initError('Could not initialize inline editor on invalid inline target element', elm);
              } else {
                createEditor(createId(elm), settings, elm);
              }
            });
          }
        };
        self.settings = settings;
        DOM$9.bind(window, 'ready', initEditors);
        return new promiseObj(function (resolve) {
          if (result) {
            resolve(result);
          } else {
            provideResults = function (editors) {
              resolve(editors);
            };
          }
        });
      },
      get: function (id) {
        if (arguments.length === 0) {
          return editors.slice(0);
        } else if (isString(id)) {
          return find(editors, function (editor) {
            return editor.id === id;
          }).getOr(null);
        } else if (isNumber(id)) {
          return editors[id] ? editors[id] : null;
        } else {
          return null;
        }
      },
      add: function (editor) {
        var self = this;
        var existingEditor;
        existingEditor = legacyEditors[editor.id];
        if (existingEditor === editor) {
          return editor;
        }
        if (self.get(editor.id) === null) {
          if (isValidLegacyKey(editor.id)) {
            legacyEditors[editor.id] = editor;
          }
          legacyEditors.push(editor);
          editors.push(editor);
        }
        toggleGlobalEvents(true);
        self.activeEditor = editor;
        self.fire('AddEditor', { editor: editor });
        if (!beforeUnloadDelegate) {
          beforeUnloadDelegate = function () {
            self.fire('BeforeUnload');
          };
          DOM$9.bind(window, 'beforeunload', beforeUnloadDelegate);
        }
        return editor;
      },
      createEditor: function (id, settings) {
        return this.add(new Editor(id, settings, this));
      },
      remove: function (selector) {
        var self = this;
        var i, editor;
        if (!selector) {
          for (i = editors.length - 1; i >= 0; i--) {
            self.remove(editors[i]);
          }
          return;
        }
        if (isString(selector)) {
          each$m(DOM$9.select(selector), function (elm) {
            editor = self.get(elm.id);
            if (editor) {
              self.remove(editor);
            }
          });
          return;
        }
        editor = selector;
        if (isNull(self.get(editor.id))) {
          return null;
        }
        if (removeEditorFromList(editor)) {
          self.fire('RemoveEditor', { editor: editor });
        }
        if (editors.length === 0) {
          DOM$9.unbind(window, 'beforeunload', beforeUnloadDelegate);
        }
        editor.remove();
        toggleGlobalEvents(editors.length > 0);
        return editor;
      },
      execCommand: function (cmd, ui, value) {
        var self = this, editor = self.get(value);
        switch (cmd) {
        case 'mceAddEditor':
          if (!self.get(value)) {
            new Editor(value, self.settings, self).render();
          }
          return true;
        case 'mceRemoveEditor':
          if (editor) {
            editor.remove();
          }
          return true;
        case 'mceToggleEditor':
          if (!editor) {
            self.execCommand('mceAddEditor', 0, value);
            return true;
          }
          if (editor.isHidden()) {
            editor.show();
          } else {
            editor.hide();
          }
          return true;
        }
        if (self.activeEditor) {
          return self.activeEditor.execCommand(cmd, ui, value);
        }
        return false;
      },
      triggerSave: function () {
        each$m(editors, function (editor) {
          editor.save();
        });
      },
      addI18n: function (code, items) {
        I18n.add(code, items);
      },
      translate: function (text) {
        return I18n.translate(text);
      },
      setActive: function (editor) {
        var activeEditor = this.activeEditor;
        if (this.activeEditor !== editor) {
          if (activeEditor) {
            activeEditor.fire('deactivate', { relatedTarget: editor });
          }
          editor.fire('activate', { relatedTarget: activeEditor });
        }
        this.activeEditor = editor;
      }
    };
    extend$5(EditorManager, Observable);
    EditorManager.setup();
    var EditorManager$1 = EditorManager;

    function RangeUtils(dom) {
      var walk = function (rng, callback) {
        return RangeWalk.walk(dom, rng, callback);
      };
      var split = SplitRange.split;
      var normalize = function (rng) {
        return NormalizeRange.normalize(dom, rng).fold(constant(false), function (normalizedRng) {
          rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset);
          rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset);
          return true;
        });
      };
      return {
        walk: walk,
        split: split,
        normalize: normalize
      };
    }
    (function (RangeUtils) {
      RangeUtils.compareRanges = RangeCompare.isEq;
      RangeUtils.getCaretRangeFromPoint = CaretRangeFromPoint.fromPoint;
      RangeUtils.getSelectedNode = getSelectedNode;
      RangeUtils.getNode = getNode;
    }(RangeUtils || (RangeUtils = {})));
    var RangeUtils$1 = RangeUtils;

    var min = Math.min, max = Math.max, round$2 = Math.round;
    var relativePosition = function (rect, targetRect, rel) {
      var x, y, w, h, targetW, targetH;
      x = targetRect.x;
      y = targetRect.y;
      w = rect.w;
      h = rect.h;
      targetW = targetRect.w;
      targetH = targetRect.h;
      rel = (rel || '').split('');
      if (rel[0] === 'b') {
        y += targetH;
      }
      if (rel[1] === 'r') {
        x += targetW;
      }
      if (rel[0] === 'c') {
        y += round$2(targetH / 2);
      }
      if (rel[1] === 'c') {
        x += round$2(targetW / 2);
      }
      if (rel[3] === 'b') {
        y -= h;
      }
      if (rel[4] === 'r') {
        x -= w;
      }
      if (rel[3] === 'c') {
        y -= round$2(h / 2);
      }
      if (rel[4] === 'c') {
        x -= round$2(w / 2);
      }
      return create$4(x, y, w, h);
    };
    var findBestRelativePosition = function (rect, targetRect, constrainRect, rels) {
      var pos, i;
      for (i = 0; i < rels.length; i++) {
        pos = relativePosition(rect, targetRect, rels[i]);
        if (pos.x >= constrainRect.x && pos.x + pos.w <= constrainRect.w + constrainRect.x && pos.y >= constrainRect.y && pos.y + pos.h <= constrainRect.h + constrainRect.y) {
          return rels[i];
        }
      }
      return null;
    };
    var inflate = function (rect, w, h) {
      return create$4(rect.x - w, rect.y - h, rect.w + w * 2, rect.h + h * 2);
    };
    var intersect = function (rect, cropRect) {
      var x1, y1, x2, y2;
      x1 = max(rect.x, cropRect.x);
      y1 = max(rect.y, cropRect.y);
      x2 = min(rect.x + rect.w, cropRect.x + cropRect.w);
      y2 = min(rect.y + rect.h, cropRect.y + cropRect.h);
      if (x2 - x1 < 0 || y2 - y1 < 0) {
        return null;
      }
      return create$4(x1, y1, x2 - x1, y2 - y1);
    };
    var clamp$1 = function (rect, clampRect, fixedSize) {
      var underflowX1, underflowY1, overflowX2, overflowY2, x1, y1, x2, y2, cx2, cy2;
      x1 = rect.x;
      y1 = rect.y;
      x2 = rect.x + rect.w;
      y2 = rect.y + rect.h;
      cx2 = clampRect.x + clampRect.w;
      cy2 = clampRect.y + clampRect.h;
      underflowX1 = max(0, clampRect.x - x1);
      underflowY1 = max(0, clampRect.y - y1);
      overflowX2 = max(0, x2 - cx2);
      overflowY2 = max(0, y2 - cy2);
      x1 += underflowX1;
      y1 += underflowY1;
      if (fixedSize) {
        x2 += underflowX1;
        y2 += underflowY1;
        x1 -= overflowX2;
        y1 -= overflowY2;
      }
      x2 -= overflowX2;
      y2 -= overflowY2;
      return create$4(x1, y1, x2 - x1, y2 - y1);
    };
    var create$4 = function (x, y, w, h) {
      return {
        x: x,
        y: y,
        w: w,
        h: h
      };
    };
    var fromClientRect = function (clientRect) {
      return create$4(clientRect.left, clientRect.top, clientRect.width, clientRect.height);
    };
    var Rect = {
      inflate: inflate,
      relativePosition: relativePosition,
      findBestRelativePosition: findBestRelativePosition,
      intersect: intersect,
      clamp: clamp$1,
      create: create$4,
      fromClientRect: fromClientRect
    };

    var types = {};
    var Factory = {
      add: function (type, typeClass) {
        types[type.toLowerCase()] = typeClass;
      },
      has: function (type) {
        return !!types[type.toLowerCase()];
      },
      get: function (type) {
        var lctype = type.toLowerCase();
        var controlType = types.hasOwnProperty(lctype) ? types[lctype] : null;
        if (controlType === null) {
          throw new Error('Could not find module for type: ' + type);
        }
        return controlType;
      },
      create: function (type, settings) {
        var ControlType;
        if (typeof type === 'string') {
          settings = settings || {};
          settings.type = type;
        } else {
          settings = type;
          type = settings.type;
        }
        type = type.toLowerCase();
        ControlType = types[type];
        if (!ControlType) {
          throw new Error('Could not find control by type: ' + type);
        }
        ControlType = new ControlType(settings);
        ControlType.type = type;
        return ControlType;
      }
    };

    var each$n = Tools.each, extend$6 = Tools.extend;
    var extendClass, initializing;
    var Class = function () {
    };
    Class.extend = extendClass = function (prop) {
      var self = this;
      var _super = self.prototype;
      var prototype, name, member;
      var Class = function () {
        var i, mixins, mixin;
        var self = this;
        if (!initializing) {
          if (self.init) {
            self.init.apply(self, arguments);
          }
          mixins = self.Mixins;
          if (mixins) {
            i = mixins.length;
            while (i--) {
              mixin = mixins[i];
              if (mixin.init) {
                mixin.init.apply(self, arguments);
              }
            }
          }
        }
      };
      var dummy = function () {
        return this;
      };
      var createMethod = function (name, fn) {
        return function () {
          var self = this;
          var tmp = self._super;
          var ret;
          self._super = _super[name];
          ret = fn.apply(self, arguments);
          self._super = tmp;
          return ret;
        };
      };
      initializing = true;
      prototype = new self();
      initializing = false;
      if (prop.Mixins) {
        each$n(prop.Mixins, function (mixin) {
          for (var name_1 in mixin) {
            if (name_1 !== 'init') {
              prop[name_1] = mixin[name_1];
            }
          }
        });
        if (_super.Mixins) {
          prop.Mixins = _super.Mixins.concat(prop.Mixins);
        }
      }
      if (prop.Methods) {
        each$n(prop.Methods.split(','), function (name) {
          prop[name] = dummy;
        });
      }
      if (prop.Properties) {
        each$n(prop.Properties.split(','), function (name) {
          var fieldName = '_' + name;
          prop[name] = function (value) {
            var self = this;
            if (value !== undefined) {
              self[fieldName] = value;
              return self;
            }
            return self[fieldName];
          };
        });
      }
      if (prop.Statics) {
        each$n(prop.Statics, function (func, name) {
          Class[name] = func;
        });
      }
      if (prop.Defaults && _super.Defaults) {
        prop.Defaults = extend$6({}, _super.Defaults, prop.Defaults);
      }
      for (name in prop) {
        member = prop[name];
        if (typeof member === 'function' && _super[name]) {
          prototype[name] = createMethod(name, member);
        } else {
          prototype[name] = member;
        }
      }
      Class.prototype = prototype;
      Class.constructor = Class;
      Class.extend = extendClass;
      return Class;
    };

    var min$1 = Math.min, max$1 = Math.max, round$3 = Math.round;
    var Color = function (value) {
      var self = {};
      var r = 0, g = 0, b = 0;
      var rgb2hsv = function (r, g, b) {
        var h, s, v, d, minRGB, maxRGB;
        h = 0;
        s = 0;
        v = 0;
        r = r / 255;
        g = g / 255;
        b = b / 255;
        minRGB = min$1(r, min$1(g, b));
        maxRGB = max$1(r, max$1(g, b));
        if (minRGB === maxRGB) {
          v = minRGB;
          return {
            h: 0,
            s: 0,
            v: v * 100
          };
        }
        d = r === minRGB ? g - b : b === minRGB ? r - g : b - r;
        h = r === minRGB ? 3 : b === minRGB ? 1 : 5;
        h = 60 * (h - d / (maxRGB - minRGB));
        s = (maxRGB - minRGB) / maxRGB;
        v = maxRGB;
        return {
          h: round$3(h),
          s: round$3(s * 100),
          v: round$3(v * 100)
        };
      };
      var hsvToRgb = function (hue, saturation, brightness) {
        var side, chroma, x, match;
        hue = (parseInt(hue, 10) || 0) % 360;
        saturation = parseInt(saturation, 10) / 100;
        brightness = parseInt(brightness, 10) / 100;
        saturation = max$1(0, min$1(saturation, 1));
        brightness = max$1(0, min$1(brightness, 1));
        if (saturation === 0) {
          r = g = b = round$3(255 * brightness);
          return;
        }
        side = hue / 60;
        chroma = brightness * saturation;
        x = chroma * (1 - Math.abs(side % 2 - 1));
        match = brightness - chroma;
        switch (Math.floor(side)) {
        case 0:
          r = chroma;
          g = x;
          b = 0;
          break;
        case 1:
          r = x;
          g = chroma;
          b = 0;
          break;
        case 2:
          r = 0;
          g = chroma;
          b = x;
          break;
        case 3:
          r = 0;
          g = x;
          b = chroma;
          break;
        case 4:
          r = x;
          g = 0;
          b = chroma;
          break;
        case 5:
          r = chroma;
          g = 0;
          b = x;
          break;
        default:
          r = g = b = 0;
        }
        r = round$3(255 * (r + match));
        g = round$3(255 * (g + match));
        b = round$3(255 * (b + match));
      };
      var toHex = function () {
        var hex = function (val) {
          val = parseInt(val, 10).toString(16);
          return val.length > 1 ? val : '0' + val;
        };
        return '#' + hex(r) + hex(g) + hex(b);
      };
      var toRgb = function () {
        return {
          r: r,
          g: g,
          b: b
        };
      };
      var toHsv = function () {
        return rgb2hsv(r, g, b);
      };
      var parse = function (value) {
        var matches;
        if (typeof value === 'object') {
          if ('r' in value) {
            r = value.r;
            g = value.g;
            b = value.b;
          } else if ('v' in value) {
            hsvToRgb(value.h, value.s, value.v);
          }
        } else {
          if (matches = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(value)) {
            r = parseInt(matches[1], 10);
            g = parseInt(matches[2], 10);
            b = parseInt(matches[3], 10);
          } else if (matches = /#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(value)) {
            r = parseInt(matches[1], 16);
            g = parseInt(matches[2], 16);
            b = parseInt(matches[3], 16);
          } else if (matches = /#([0-F])([0-F])([0-F])/gi.exec(value)) {
            r = parseInt(matches[1] + matches[1], 16);
            g = parseInt(matches[2] + matches[2], 16);
            b = parseInt(matches[3] + matches[3], 16);
          }
        }
        r = r < 0 ? 0 : r > 255 ? 255 : r;
        g = g < 0 ? 0 : g > 255 ? 255 : g;
        b = b < 0 ? 0 : b > 255 ? 255 : b;
        return self;
      };
      if (value) {
        parse(value);
      }
      self.toRgb = toRgb;
      self.toHsv = toHsv;
      self.toHex = toHex;
      self.parse = parse;
      return self;
    };

    var serialize = function (o, quote) {
      var i, v, t, name;
      quote = quote || '"';
      if (o === null) {
        return 'null';
      }
      t = typeof o;
      if (t === 'string') {
        v = '\bb\tt\nn\ff\rr""\'\'\\\\';
        return quote + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g, function (a, b) {
          if (quote === '"' && a === '\'') {
            return a;
          }
          i = v.indexOf(b);
          if (i + 1) {
            return '\\' + v.charAt(i + 1);
          }
          a = b.charCodeAt().toString(16);
          return '\\u' + '0000'.substring(a.length) + a;
        }) + quote;
      }
      if (t === 'object') {
        if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') {
          for (i = 0, v = '['; i < o.length; i++) {
            v += (i > 0 ? ',' : '') + serialize(o[i], quote);
          }
          return v + ']';
        }
        v = '{';
        for (name in o) {
          if (o.hasOwnProperty(name)) {
            v += typeof o[name] !== 'function' ? (v.length > 1 ? ',' + quote : quote) + name + quote + ':' + serialize(o[name], quote) : '';
          }
        }
        return v + '}';
      }
      return '' + o;
    };
    var JSON$1 = {
      serialize: serialize,
      parse: function (text) {
        try {
          return JSON.parse(text);
        } catch (ex) {
        }
      }
    };

    var JSONP = {
      callbacks: {},
      count: 0,
      send: function (settings) {
        var self = this, dom = DOMUtils$1.DOM, count = settings.count !== undefined ? settings.count : self.count;
        var id = 'tinymce_jsonp_' + count;
        self.callbacks[count] = function (json) {
          dom.remove(id);
          delete self.callbacks[count];
          settings.callback(json);
        };
        dom.add(dom.doc.body, 'script', {
          id: id,
          src: settings.url,
          type: 'text/javascript'
        });
        self.count++;
      }
    };

    var XHR = {
      send: function (settings) {
        var xhr, count = 0;
        var ready = function () {
          if (!settings.async || xhr.readyState === 4 || count++ > 10000) {
            if (settings.success && count < 10000 && xhr.status === 200) {
              settings.success.call(settings.success_scope, '' + xhr.responseText, xhr, settings);
            } else if (settings.error) {
              settings.error.call(settings.error_scope, count > 10000 ? 'TIMED_OUT' : 'GENERAL', xhr, settings);
            }
            xhr = null;
          } else {
            setTimeout(ready, 10);
          }
        };
        settings.scope = settings.scope || this;
        settings.success_scope = settings.success_scope || settings.scope;
        settings.error_scope = settings.error_scope || settings.scope;
        settings.async = settings.async === false ? false : true;
        settings.data = settings.data || '';
        XHR.fire('beforeInitialize', { settings: settings });
        xhr = XMLHttpRequest();
        if (xhr) {
          if (xhr.overrideMimeType) {
            xhr.overrideMimeType(settings.content_type);
          }
          xhr.open(settings.type || (settings.data ? 'POST' : 'GET'), settings.url, settings.async);
          if (settings.crossDomain) {
            xhr.withCredentials = true;
          }
          if (settings.content_type) {
            xhr.setRequestHeader('Content-Type', settings.content_type);
          }
          if (settings.requestheaders) {
            Tools.each(settings.requestheaders, function (header) {
              xhr.setRequestHeader(header.key, header.value);
            });
          }
          xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
          xhr = XHR.fire('beforeSend', {
            xhr: xhr,
            settings: settings
          }).xhr;
          xhr.send(settings.data);
          if (!settings.async) {
            return ready();
          }
          setTimeout(ready, 10);
        }
      }
    };
    Tools.extend(XHR, Observable);

    var extend$7 = Tools.extend;
    var JSONRequest = function (settings) {
      this.settings = extend$7({}, settings);
      this.count = 0;
    };
    JSONRequest.sendRPC = function (o) {
      return new JSONRequest().send(o);
    };
    JSONRequest.prototype = {
      send: function (args) {
        var ecb = args.error, scb = args.success;
        args = extend$7(this.settings, args);
        args.success = function (c, x) {
          c = JSON$1.parse(c);
          if (typeof c === 'undefined') {
            c = { error: 'JSON Parse error.' };
          }
          if (c.error) {
            ecb.call(args.error_scope || args.scope, c.error, x);
          } else {
            scb.call(args.success_scope || args.scope, c.result);
          }
        };
        args.error = function (ty, x) {
          if (ecb) {
            ecb.call(args.error_scope || args.scope, ty, x);
          }
        };
        args.data = JSON$1.serialize({
          id: args.id || 'c' + this.count++,
          method: args.method,
          params: args.params
        });
        args.content_type = 'application/json';
        XHR.send(args);
      }
    };

    var create$5 = function () {
      return function () {
        var data = {};
        var keys = [];
        var storage = {
          getItem: function (key) {
            var item = data[key];
            return item ? item : null;
          },
          setItem: function (key, value) {
            keys.push(key);
            data[key] = String(value);
          },
          key: function (index) {
            return keys[index];
          },
          removeItem: function (key) {
            keys = keys.filter(function (k) {
              return k === key;
            });
            delete data[key];
          },
          clear: function () {
            keys = [];
            data = {};
          },
          length: 0
        };
        Object.defineProperty(storage, 'length', {
          get: function () {
            return keys.length;
          },
          configurable: false,
          enumerable: false
        });
        return storage;
      }();
    };

    var localStorage;
    try {
      localStorage = domGlobals.window.localStorage;
    } catch (e) {
      localStorage = create$5();
    }
    var LocalStorage = localStorage;

    var tinymce = EditorManager$1;
    var publicApi = {
      geom: { Rect: Rect },
      util: {
        Promise: promiseObj,
        Delay: Delay,
        Tools: Tools,
        VK: VK,
        URI: URI,
        Class: Class,
        EventDispatcher: Dispatcher,
        Observable: Observable,
        I18n: I18n,
        XHR: XHR,
        JSON: JSON$1,
        JSONRequest: JSONRequest,
        JSONP: JSONP,
        LocalStorage: LocalStorage,
        Color: Color
      },
      dom: {
        EventUtils: EventUtils,
        Sizzle: Sizzle,
        DomQuery: DomQuery,
        TreeWalker: TreeWalker,
        DOMUtils: DOMUtils$1,
        ScriptLoader: ScriptLoader,
        RangeUtils: RangeUtils$1,
        Serializer: DomSerializer$1,
        ControlSelection: ControlSelection,
        BookmarkManager: BookmarkManager$1,
        Selection: Selection$1,
        Event: EventUtils.Event
      },
      html: {
        Styles: Styles,
        Entities: Entities,
        Node: Node$1,
        Schema: Schema,
        SaxParser: SaxParser$1,
        DomParser: DomParser,
        Writer: Writer,
        Serializer: HtmlSerializer
      },
      ui: { Factory: Factory },
      Env: Env,
      AddOnManager: AddOnManager,
      Annotator: Annotator,
      Formatter: Formatter,
      UndoManager: UndoManager,
      EditorCommands: EditorCommands,
      WindowManager: WindowManager,
      NotificationManager: NotificationManager,
      EditorObservable: EditorObservable$1,
      Shortcuts: Shortcuts,
      Editor: Editor,
      FocusManager: FocusManager,
      EditorManager: EditorManager$1,
      DOM: DOMUtils$1.DOM,
      ScriptLoader: ScriptLoader.ScriptLoader,
      PluginManager: AddOnManager.PluginManager,
      ThemeManager: AddOnManager.ThemeManager,
      trim: Tools.trim,
      isArray: Tools.isArray,
      is: Tools.is,
      toArray: Tools.toArray,
      makeMap: Tools.makeMap,
      each: Tools.each,
      map: Tools.map,
      grep: Tools.grep,
      inArray: Tools.inArray,
      extend: Tools.extend,
      create: Tools.create,
      walk: Tools.walk,
      createNS: Tools.createNS,
      resolve: Tools.resolve,
      explode: Tools.explode,
      _addCacheSuffix: Tools._addCacheSuffix,
      isOpera: Env.opera,
      isWebKit: Env.webkit,
      isIE: Env.ie,
      isGecko: Env.gecko,
      isMac: Env.mac
    };
    tinymce = Tools.extend(tinymce, publicApi);
    var Tinymce = tinymce;

    var exportToModuleLoaders = function (tinymce) {
      if (true) {
        try {
          module.exports = tinymce;
        } catch (_) {
        }
      }
    };
    var exportToWindowGlobal = function (tinymce) {
      window.tinymce = tinymce;
      window.tinyMCE = tinymce;
    };
    exportToWindowGlobal(Tinymce);
    exportToModuleLoaders(Tinymce);

}(window));
})();

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(108).setImmediate, __webpack_require__(5), __webpack_require__(6)))

/***/ }),

/***/ 559:
/***/ (function(module, exports) {

(function () {
var modern = (function (domGlobals) {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.ThemeManager');

    var global$1 = tinymce.util.Tools.resolve('tinymce.EditorManager');

    var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    var isBrandingEnabled = function (editor) {
      return editor.getParam('branding', true, 'boolean');
    };
    var hasMenubar = function (editor) {
      return getMenubar(editor) !== false;
    };
    var getMenubar = function (editor) {
      return editor.getParam('menubar');
    };
    var hasStatusbar = function (editor) {
      return editor.getParam('statusbar', true, 'boolean');
    };
    var getToolbarSize = function (editor) {
      return editor.getParam('toolbar_items_size');
    };
    var isReadOnly = function (editor) {
      return editor.getParam('readonly', false, 'boolean');
    };
    var getFixedToolbarContainer = function (editor) {
      return editor.getParam('fixed_toolbar_container');
    };
    var getInlineToolbarPositionHandler = function (editor) {
      return editor.getParam('inline_toolbar_position_handler');
    };
    var getMenu = function (editor) {
      return editor.getParam('menu');
    };
    var getRemovedMenuItems = function (editor) {
      return editor.getParam('removed_menuitems', '');
    };
    var getMinWidth = function (editor) {
      return editor.getParam('min_width', 100, 'number');
    };
    var getMinHeight = function (editor) {
      return editor.getParam('min_height', 100, 'number');
    };
    var getMaxWidth = function (editor) {
      return editor.getParam('max_width', 65535, 'number');
    };
    var getMaxHeight = function (editor) {
      return editor.getParam('max_height', 65535, 'number');
    };
    var isSkinDisabled = function (editor) {
      return editor.settings.skin === false;
    };
    var isInline = function (editor) {
      return editor.getParam('inline', false, 'boolean');
    };
    var getResize = function (editor) {
      var resize = editor.getParam('resize', 'vertical');
      if (resize === false) {
        return 'none';
      } else if (resize === 'both') {
        return 'both';
      } else {
        return 'vertical';
      }
    };
    var getSkinUrl = function (editor) {
      var settings = editor.settings;
      var skin = settings.skin;
      var skinUrl = settings.skin_url;
      if (skin !== false) {
        var skinName = skin ? skin : 'lightgray';
        if (skinUrl) {
          skinUrl = editor.documentBaseURI.toAbsolute(skinUrl);
        } else {
          skinUrl = global$1.baseURL + '/skins/' + skinName;
        }
      }
      return skinUrl;
    };
    var getIndexedToolbars = function (settings, defaultToolbar) {
      var toolbars = [];
      for (var i = 1; i < 10; i++) {
        var toolbar = settings['toolbar' + i];
        if (!toolbar) {
          break;
        }
        toolbars.push(toolbar);
      }
      var mainToolbar = settings.toolbar ? [settings.toolbar] : [defaultToolbar];
      return toolbars.length > 0 ? toolbars : mainToolbar;
    };
    var getToolbars = function (editor) {
      var toolbar = editor.getParam('toolbar');
      var defaultToolbar = 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image';
      if (toolbar === false) {
        return [];
      } else if (global$2.isArray(toolbar)) {
        return global$2.grep(toolbar, function (toolbar) {
          return toolbar.length > 0;
        });
      } else {
        return getIndexedToolbars(editor.settings, defaultToolbar);
      }
    };

    var global$3 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

    var global$4 = tinymce.util.Tools.resolve('tinymce.ui.Factory');

    var global$5 = tinymce.util.Tools.resolve('tinymce.util.I18n');

    var fireSkinLoaded = function (editor) {
      return editor.fire('SkinLoaded');
    };
    var fireResizeEditor = function (editor) {
      return editor.fire('ResizeEditor');
    };
    var fireBeforeRenderUI = function (editor) {
      return editor.fire('BeforeRenderUI');
    };
    var Events = {
      fireSkinLoaded: fireSkinLoaded,
      fireResizeEditor: fireResizeEditor,
      fireBeforeRenderUI: fireBeforeRenderUI
    };

    var focus = function (panel, type) {
      return function () {
        var item = panel.find(type)[0];
        if (item) {
          item.focus(true);
        }
      };
    };
    var addKeys = function (editor, panel) {
      editor.shortcuts.add('Alt+F9', '', focus(panel, 'menubar'));
      editor.shortcuts.add('Alt+F10,F10', '', focus(panel, 'toolbar'));
      editor.shortcuts.add('Alt+F11', '', focus(panel, 'elementpath'));
      panel.on('cancel', function () {
        editor.focus();
      });
    };
    var A11y = { addKeys: addKeys };

    var global$6 = tinymce.util.Tools.resolve('tinymce.geom.Rect');

    var global$7 = tinymce.util.Tools.resolve('tinymce.util.Delay');

    var noop = function () {
    };
    var constant = function (value) {
      return function () {
        return value;
      };
    };
    var never = constant(false);
    var always = constant(true);

    var none = function () {
      return NONE;
    };
    var NONE = function () {
      var eq = function (o) {
        return o.isNone();
      };
      var call = function (thunk) {
        return thunk();
      };
      var id = function (n) {
        return n;
      };
      var me = {
        fold: function (n, s) {
          return n();
        },
        is: never,
        isSome: never,
        isNone: always,
        getOr: id,
        getOrThunk: call,
        getOrDie: function (msg) {
          throw new Error(msg || 'error: getOrDie called on none.');
        },
        getOrNull: constant(null),
        getOrUndefined: constant(undefined),
        or: id,
        orThunk: call,
        map: none,
        each: noop,
        bind: none,
        exists: never,
        forall: always,
        filter: none,
        equals: eq,
        equals_: eq,
        toArray: function () {
          return [];
        },
        toString: constant('none()')
      };
      if (Object.freeze) {
        Object.freeze(me);
      }
      return me;
    }();
    var some = function (a) {
      var constant_a = constant(a);
      var self = function () {
        return me;
      };
      var bind = function (f) {
        return f(a);
      };
      var me = {
        fold: function (n, s) {
          return s(a);
        },
        is: function (v) {
          return a === v;
        },
        isSome: always,
        isNone: never,
        getOr: constant_a,
        getOrThunk: constant_a,
        getOrDie: constant_a,
        getOrNull: constant_a,
        getOrUndefined: constant_a,
        or: self,
        orThunk: self,
        map: function (f) {
          return some(f(a));
        },
        each: function (f) {
          f(a);
        },
        bind: bind,
        exists: bind,
        forall: bind,
        filter: function (f) {
          return f(a) ? me : NONE;
        },
        toArray: function () {
          return [a];
        },
        toString: function () {
          return 'some(' + a + ')';
        },
        equals: function (o) {
          return o.is(a);
        },
        equals_: function (o, elementEq) {
          return o.fold(never, function (b) {
            return elementEq(a, b);
          });
        }
      };
      return me;
    };
    var from = function (value) {
      return value === null || value === undefined ? NONE : some(value);
    };
    var Option = {
      some: some,
      none: none,
      from: from
    };

    var getUiContainerDelta = function (ctrl) {
      var uiContainer = getUiContainer(ctrl);
      if (uiContainer && global$3.DOM.getStyle(uiContainer, 'position', true) !== 'static') {
        var containerPos = global$3.DOM.getPos(uiContainer);
        var dx = uiContainer.scrollLeft - containerPos.x;
        var dy = uiContainer.scrollTop - containerPos.y;
        return Option.some({
          x: dx,
          y: dy
        });
      } else {
        return Option.none();
      }
    };
    var setUiContainer = function (editor, ctrl) {
      var uiContainer = global$3.DOM.select(editor.settings.ui_container)[0];
      ctrl.getRoot().uiContainer = uiContainer;
    };
    var getUiContainer = function (ctrl) {
      return ctrl ? ctrl.getRoot().uiContainer : null;
    };
    var inheritUiContainer = function (fromCtrl, toCtrl) {
      return toCtrl.uiContainer = getUiContainer(fromCtrl);
    };
    var UiContainer = {
      getUiContainerDelta: getUiContainerDelta,
      setUiContainer: setUiContainer,
      getUiContainer: getUiContainer,
      inheritUiContainer: inheritUiContainer
    };

    var createToolbar = function (editor, items, size) {
      var toolbarItems = [];
      var buttonGroup;
      if (!items) {
        return;
      }
      global$2.each(items.split(/[ ,]/), function (item) {
        var itemName;
        var bindSelectorChanged = function () {
          var selection = editor.selection;
          if (item.settings.stateSelector) {
            selection.selectorChanged(item.settings.stateSelector, function (state) {
              item.active(state);
            }, true);
          }
          if (item.settings.disabledStateSelector) {
            selection.selectorChanged(item.settings.disabledStateSelector, function (state) {
              item.disabled(state);
            });
          }
        };
        if (item === '|') {
          buttonGroup = null;
        } else {
          if (!buttonGroup) {
            buttonGroup = {
              type: 'buttongroup',
              items: []
            };
            toolbarItems.push(buttonGroup);
          }
          if (editor.buttons[item]) {
            itemName = item;
            item = editor.buttons[itemName];
            if (typeof item === 'function') {
              item = item();
            }
            item.type = item.type || 'button';
            item.size = size;
            item = global$4.create(item);
            buttonGroup.items.push(item);
            if (editor.initialized) {
              bindSelectorChanged();
            } else {
              editor.on('init', bindSelectorChanged);
            }
          }
        }
      });
      return {
        type: 'toolbar',
        layout: 'flow',
        items: toolbarItems
      };
    };
    var createToolbars = function (editor, size) {
      var toolbars = [];
      var addToolbar = function (items) {
        if (items) {
          toolbars.push(createToolbar(editor, items, size));
        }
      };
      global$2.each(getToolbars(editor), function (toolbar) {
        addToolbar(toolbar);
      });
      if (toolbars.length) {
        return {
          type: 'panel',
          layout: 'stack',
          classes: 'toolbar-grp',
          ariaRoot: true,
          ariaRemember: true,
          items: toolbars
        };
      }
    };
    var Toolbar = {
      createToolbar: createToolbar,
      createToolbars: createToolbars
    };

    var DOM = global$3.DOM;
    var toClientRect = function (geomRect) {
      return {
        left: geomRect.x,
        top: geomRect.y,
        width: geomRect.w,
        height: geomRect.h,
        right: geomRect.x + geomRect.w,
        bottom: geomRect.y + geomRect.h
      };
    };
    var hideAllFloatingPanels = function (editor) {
      global$2.each(editor.contextToolbars, function (toolbar) {
        if (toolbar.panel) {
          toolbar.panel.hide();
        }
      });
    };
    var movePanelTo = function (panel, pos) {
      panel.moveTo(pos.left, pos.top);
    };
    var togglePositionClass = function (panel, relPos, predicate) {
      relPos = relPos ? relPos.substr(0, 2) : '';
      global$2.each({
        t: 'down',
        b: 'up'
      }, function (cls, pos) {
        panel.classes.toggle('arrow-' + cls, predicate(pos, relPos.substr(0, 1)));
      });
      global$2.each({
        l: 'left',
        r: 'right'
      }, function (cls, pos) {
        panel.classes.toggle('arrow-' + cls, predicate(pos, relPos.substr(1, 1)));
      });
    };
    var userConstrain = function (handler, x, y, elementRect, contentAreaRect, panelRect) {
      panelRect = toClientRect({
        x: x,
        y: y,
        w: panelRect.w,
        h: panelRect.h
      });
      if (handler) {
        panelRect = handler({
          elementRect: toClientRect(elementRect),
          contentAreaRect: toClientRect(contentAreaRect),
          panelRect: panelRect
        });
      }
      return panelRect;
    };
    var addContextualToolbars = function (editor) {
      var scrollContainer;
      var getContextToolbars = function () {
        return editor.contextToolbars || [];
      };
      var getElementRect = function (elm) {
        var pos, targetRect, root;
        pos = DOM.getPos(editor.getContentAreaContainer());
        targetRect = editor.dom.getRect(elm);
        root = editor.dom.getRoot();
        if (root.nodeName === 'BODY') {
          targetRect.x -= root.ownerDocument.documentElement.scrollLeft || root.scrollLeft;
          targetRect.y -= root.ownerDocument.documentElement.scrollTop || root.scrollTop;
        }
        targetRect.x += pos.x;
        targetRect.y += pos.y;
        return targetRect;
      };
      var reposition = function (match, shouldShow) {
        var relPos, panelRect, elementRect, contentAreaRect, panel, relRect, testPositions, smallElementWidthThreshold;
        var handler = getInlineToolbarPositionHandler(editor);
        if (editor.removed) {
          return;
        }
        if (!match || !match.toolbar.panel) {
          hideAllFloatingPanels(editor);
          return;
        }
        testPositions = [
          'bc-tc',
          'tc-bc',
          'tl-bl',
          'bl-tl',
          'tr-br',
          'br-tr'
        ];
        panel = match.toolbar.panel;
        if (shouldShow) {
          panel.show();
        }
        elementRect = getElementRect(match.element);
        panelRect = DOM.getRect(panel.getEl());
        contentAreaRect = DOM.getRect(editor.getContentAreaContainer() || editor.getBody());
        var delta = UiContainer.getUiContainerDelta(panel).getOr({
          x: 0,
          y: 0
        });
        elementRect.x += delta.x;
        elementRect.y += delta.y;
        panelRect.x += delta.x;
        panelRect.y += delta.y;
        contentAreaRect.x += delta.x;
        contentAreaRect.y += delta.y;
        smallElementWidthThreshold = 25;
        if (DOM.getStyle(match.element, 'display', true) !== 'inline') {
          var clientRect = match.element.getBoundingClientRect();
          elementRect.w = clientRect.width;
          elementRect.h = clientRect.height;
        }
        if (!editor.inline) {
          contentAreaRect.w = editor.getDoc().documentElement.offsetWidth;
        }
        if (editor.selection.controlSelection.isResizable(match.element) && elementRect.w < smallElementWidthThreshold) {
          elementRect = global$6.inflate(elementRect, 0, 8);
        }
        relPos = global$6.findBestRelativePosition(panelRect, elementRect, contentAreaRect, testPositions);
        elementRect = global$6.clamp(elementRect, contentAreaRect);
        if (relPos) {
          relRect = global$6.relativePosition(panelRect, elementRect, relPos);
          movePanelTo(panel, userConstrain(handler, relRect.x, relRect.y, elementRect, contentAreaRect, panelRect));
        } else {
          contentAreaRect.h += panelRect.h;
          elementRect = global$6.intersect(contentAreaRect, elementRect);
          if (elementRect) {
            relPos = global$6.findBestRelativePosition(panelRect, elementRect, contentAreaRect, [
              'bc-tc',
              'bl-tl',
              'br-tr'
            ]);
            if (relPos) {
              relRect = global$6.relativePosition(panelRect, elementRect, relPos);
              movePanelTo(panel, userConstrain(handler, relRect.x, relRect.y, elementRect, contentAreaRect, panelRect));
            } else {
              movePanelTo(panel, userConstrain(handler, elementRect.x, elementRect.y, elementRect, contentAreaRect, panelRect));
            }
          } else {
            panel.hide();
          }
        }
        togglePositionClass(panel, relPos, function (pos1, pos2) {
          return pos1 === pos2;
        });
      };
      var repositionHandler = function (show) {
        return function () {
          var execute = function () {
            if (editor.selection) {
              reposition(findFrontMostMatch(editor.selection.getNode()), show);
            }
          };
          global$7.requestAnimationFrame(execute);
        };
      };
      var bindScrollEvent = function (panel) {
        if (!scrollContainer) {
          var reposition_1 = repositionHandler(true);
          var uiContainer_1 = UiContainer.getUiContainer(panel);
          scrollContainer = editor.selection.getScrollContainer() || editor.getWin();
          DOM.bind(scrollContainer, 'scroll', reposition_1);
          DOM.bind(uiContainer_1, 'scroll', reposition_1);
          editor.on('remove', function () {
            DOM.unbind(scrollContainer, 'scroll', reposition_1);
            DOM.unbind(uiContainer_1, 'scroll', reposition_1);
          });
        }
      };
      var showContextToolbar = function (match) {
        var panel;
        if (match.toolbar.panel) {
          match.toolbar.panel.show();
          reposition(match);
          return;
        }
        panel = global$4.create({
          type: 'floatpanel',
          role: 'dialog',
          classes: 'tinymce tinymce-inline arrow',
          ariaLabel: 'Inline toolbar',
          layout: 'flex',
          direction: 'column',
          align: 'stretch',
          autohide: false,
          autofix: true,
          fixed: true,
          border: 1,
          items: Toolbar.createToolbar(editor, match.toolbar.items),
          oncancel: function () {
            editor.focus();
          }
        });
        UiContainer.setUiContainer(editor, panel);
        bindScrollEvent(panel);
        match.toolbar.panel = panel;
        panel.renderTo().reflow();
        reposition(match);
      };
      var hideAllContextToolbars = function () {
        global$2.each(getContextToolbars(), function (toolbar) {
          if (toolbar.panel) {
            toolbar.panel.hide();
          }
        });
      };
      var findFrontMostMatch = function (targetElm) {
        var i, y, parentsAndSelf;
        var toolbars = getContextToolbars();
        parentsAndSelf = editor.$(targetElm).parents().add(targetElm);
        for (i = parentsAndSelf.length - 1; i >= 0; i--) {
          for (y = toolbars.length - 1; y >= 0; y--) {
            if (toolbars[y].predicate(parentsAndSelf[i])) {
              return {
                toolbar: toolbars[y],
                element: parentsAndSelf[i]
              };
            }
          }
        }
        return null;
      };
      editor.on('click keyup setContent ObjectResized', function (e) {
        if (e.type === 'setcontent' && !e.selection) {
          return;
        }
        global$7.setEditorTimeout(editor, function () {
          var match;
          match = findFrontMostMatch(editor.selection.getNode());
          if (match) {
            hideAllContextToolbars();
            showContextToolbar(match);
          } else {
            hideAllContextToolbars();
          }
        });
      });
      editor.on('blur hide contextmenu', hideAllContextToolbars);
      editor.on('ObjectResizeStart', function () {
        var match = findFrontMostMatch(editor.selection.getNode());
        if (match && match.toolbar.panel) {
          match.toolbar.panel.hide();
        }
      });
      editor.on('ResizeEditor ResizeWindow', repositionHandler(true));
      editor.on('nodeChange', repositionHandler(false));
      editor.on('remove', function () {
        global$2.each(getContextToolbars(), function (toolbar) {
          if (toolbar.panel) {
            toolbar.panel.remove();
          }
        });
        editor.contextToolbars = {};
      });
      editor.shortcuts.add('ctrl+F9', '', function () {
        var match = findFrontMostMatch(editor.selection.getNode());
        if (match && match.toolbar.panel) {
          match.toolbar.panel.items()[0].focus();
        }
      });
    };
    var ContextToolbars = { addContextualToolbars: addContextualToolbars };

    var typeOf = function (x) {
      if (x === null) {
        return 'null';
      }
      var t = typeof x;
      if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
        return 'array';
      }
      if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
        return 'string';
      }
      return t;
    };
    var isType = function (type) {
      return function (value) {
        return typeOf(value) === type;
      };
    };
    var isArray = isType('array');
    var isFunction = isType('function');
    var isNumber = isType('number');

    var nativeSlice = Array.prototype.slice;
    var nativeIndexOf = Array.prototype.indexOf;
    var nativePush = Array.prototype.push;
    var rawIndexOf = function (ts, t) {
      return nativeIndexOf.call(ts, t);
    };
    var indexOf = function (xs, x) {
      var r = rawIndexOf(xs, x);
      return r === -1 ? Option.none() : Option.some(r);
    };
    var exists = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return true;
        }
      }
      return false;
    };
    var map = function (xs, f) {
      var len = xs.length;
      var r = new Array(len);
      for (var i = 0; i < len; i++) {
        var x = xs[i];
        r[i] = f(x, i);
      }
      return r;
    };
    var each = function (xs, f) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        f(x, i);
      }
    };
    var filter = function (xs, pred) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          r.push(x);
        }
      }
      return r;
    };
    var foldl = function (xs, f, acc) {
      each(xs, function (x) {
        acc = f(acc, x);
      });
      return acc;
    };
    var find = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return Option.some(x);
        }
      }
      return Option.none();
    };
    var findIndex = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return Option.some(i);
        }
      }
      return Option.none();
    };
    var flatten = function (xs) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; ++i) {
        if (!isArray(xs[i])) {
          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
        }
        nativePush.apply(r, xs[i]);
      }
      return r;
    };
    var from$1 = isFunction(Array.from) ? Array.from : function (x) {
      return nativeSlice.call(x);
    };

    var defaultMenus = {
      file: {
        title: 'File',
        items: 'newdocument restoredraft | preview | print'
      },
      edit: {
        title: 'Edit',
        items: 'undo redo | cut copy paste pastetext | selectall'
      },
      view: {
        title: 'View',
        items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen'
      },
      insert: {
        title: 'Insert',
        items: 'image link media template codesample inserttable | charmap hr | pagebreak nonbreaking anchor toc | insertdatetime'
      },
      format: {
        title: 'Format',
        items: 'bold italic underline strikethrough superscript subscript codeformat | blockformats align | removeformat'
      },
      tools: {
        title: 'Tools',
        items: 'spellchecker spellcheckerlanguage | a11ycheck code'
      },
      table: { title: 'Table' },
      help: { title: 'Help' }
    };
    var delimiterMenuNamePair = function () {
      return {
        name: '|',
        item: { text: '|' }
      };
    };
    var createMenuNameItemPair = function (name, item) {
      var menuItem = item ? {
        name: name,
        item: item
      } : null;
      return name === '|' ? delimiterMenuNamePair() : menuItem;
    };
    var hasItemName = function (namedMenuItems, name) {
      return findIndex(namedMenuItems, function (namedMenuItem) {
        return namedMenuItem.name === name;
      }).isSome();
    };
    var isSeparator = function (namedMenuItem) {
      return namedMenuItem && namedMenuItem.item.text === '|';
    };
    var cleanupMenu = function (namedMenuItems, removedMenuItems) {
      var menuItemsPass1 = filter(namedMenuItems, function (namedMenuItem) {
        return removedMenuItems.hasOwnProperty(namedMenuItem.name) === false;
      });
      var menuItemsPass2 = filter(menuItemsPass1, function (namedMenuItem, i) {
        return !isSeparator(namedMenuItem) || !isSeparator(menuItemsPass1[i - 1]);
      });
      return filter(menuItemsPass2, function (namedMenuItem, i) {
        return !isSeparator(namedMenuItem) || i > 0 && i < menuItemsPass2.length - 1;
      });
    };
    var createMenu = function (editorMenuItems, menus, removedMenuItems, context) {
      var menuButton, menu, namedMenuItems, isUserDefined;
      if (menus) {
        menu = menus[context];
        isUserDefined = true;
      } else {
        menu = defaultMenus[context];
      }
      if (menu) {
        menuButton = { text: menu.title };
        namedMenuItems = [];
        global$2.each((menu.items || '').split(/[ ,]/), function (name) {
          var namedMenuItem = createMenuNameItemPair(name, editorMenuItems[name]);
          if (namedMenuItem) {
            namedMenuItems.push(namedMenuItem);
          }
        });
        if (!isUserDefined) {
          global$2.each(editorMenuItems, function (item, name) {
            if (item.context === context && !hasItemName(namedMenuItems, name)) {
              if (item.separator === 'before') {
                namedMenuItems.push(delimiterMenuNamePair());
              }
              if (item.prependToContext) {
                namedMenuItems.unshift(createMenuNameItemPair(name, item));
              } else {
                namedMenuItems.push(createMenuNameItemPair(name, item));
              }
              if (item.separator === 'after') {
                namedMenuItems.push(delimiterMenuNamePair());
              }
            }
          });
        }
        menuButton.menu = map(cleanupMenu(namedMenuItems, removedMenuItems), function (menuItem) {
          return menuItem.item;
        });
        if (!menuButton.menu.length) {
          return null;
        }
      }
      return menuButton;
    };
    var getDefaultMenubar = function (editor) {
      var name;
      var defaultMenuBar = [];
      var menu = getMenu(editor);
      if (menu) {
        for (name in menu) {
          defaultMenuBar.push(name);
        }
      } else {
        for (name in defaultMenus) {
          defaultMenuBar.push(name);
        }
      }
      return defaultMenuBar;
    };
    var createMenuButtons = function (editor) {
      var menuButtons = [];
      var defaultMenuBar = getDefaultMenubar(editor);
      var removedMenuItems = global$2.makeMap(getRemovedMenuItems(editor).split(/[ ,]/));
      var menubar = getMenubar(editor);
      var enabledMenuNames = typeof menubar === 'string' ? menubar.split(/[ ,]/) : defaultMenuBar;
      for (var i = 0; i < enabledMenuNames.length; i++) {
        var menuItems = enabledMenuNames[i];
        var menu = createMenu(editor.menuItems, getMenu(editor), removedMenuItems, menuItems);
        if (menu) {
          menuButtons.push(menu);
        }
      }
      return menuButtons;
    };
    var Menubar = { createMenuButtons: createMenuButtons };

    var DOM$1 = global$3.DOM;
    var getSize = function (elm) {
      return {
        width: elm.clientWidth,
        height: elm.clientHeight
      };
    };
    var resizeTo = function (editor, width, height) {
      var containerElm, iframeElm, containerSize, iframeSize;
      containerElm = editor.getContainer();
      iframeElm = editor.getContentAreaContainer().firstChild;
      containerSize = getSize(containerElm);
      iframeSize = getSize(iframeElm);
      if (width !== null) {
        width = Math.max(getMinWidth(editor), width);
        width = Math.min(getMaxWidth(editor), width);
        DOM$1.setStyle(containerElm, 'width', width + (containerSize.width - iframeSize.width));
        DOM$1.setStyle(iframeElm, 'width', width);
      }
      height = Math.max(getMinHeight(editor), height);
      height = Math.min(getMaxHeight(editor), height);
      DOM$1.setStyle(iframeElm, 'height', height);
      Events.fireResizeEditor(editor);
    };
    var resizeBy = function (editor, dw, dh) {
      var elm = editor.getContentAreaContainer();
      resizeTo(editor, elm.clientWidth + dw, elm.clientHeight + dh);
    };
    var Resize = {
      resizeTo: resizeTo,
      resizeBy: resizeBy
    };

    var global$8 = tinymce.util.Tools.resolve('tinymce.Env');

    var api = function (elm) {
      return {
        element: function () {
          return elm;
        }
      };
    };
    var trigger = function (sidebar, panel, callbackName) {
      var callback = sidebar.settings[callbackName];
      if (callback) {
        callback(api(panel.getEl('body')));
      }
    };
    var hidePanels = function (name, container, sidebars) {
      global$2.each(sidebars, function (sidebar) {
        var panel = container.items().filter('#' + sidebar.name)[0];
        if (panel && panel.visible() && sidebar.name !== name) {
          trigger(sidebar, panel, 'onhide');
          panel.visible(false);
        }
      });
    };
    var deactivateButtons = function (toolbar) {
      toolbar.items().each(function (ctrl) {
        ctrl.active(false);
      });
    };
    var findSidebar = function (sidebars, name) {
      return global$2.grep(sidebars, function (sidebar) {
        return sidebar.name === name;
      })[0];
    };
    var showPanel = function (editor, name, sidebars) {
      return function (e) {
        var btnCtrl = e.control;
        var container = btnCtrl.parents().filter('panel')[0];
        var panel = container.find('#' + name)[0];
        var sidebar = findSidebar(sidebars, name);
        hidePanels(name, container, sidebars);
        deactivateButtons(btnCtrl.parent());
        if (panel && panel.visible()) {
          trigger(sidebar, panel, 'onhide');
          panel.hide();
          btnCtrl.active(false);
        } else {
          if (panel) {
            panel.show();
            trigger(sidebar, panel, 'onshow');
          } else {
            panel = global$4.create({
              type: 'container',
              name: name,
              layout: 'stack',
              classes: 'sidebar-panel',
              html: ''
            });
            container.prepend(panel);
            trigger(sidebar, panel, 'onrender');
            trigger(sidebar, panel, 'onshow');
          }
          btnCtrl.active(true);
        }
        Events.fireResizeEditor(editor);
      };
    };
    var isModernBrowser = function () {
      return !global$8.ie || global$8.ie >= 11;
    };
    var hasSidebar = function (editor) {
      return isModernBrowser() && editor.sidebars ? editor.sidebars.length > 0 : false;
    };
    var createSidebar = function (editor) {
      var buttons = global$2.map(editor.sidebars, function (sidebar) {
        var settings = sidebar.settings;
        return {
          type: 'button',
          icon: settings.icon,
          image: settings.image,
          tooltip: settings.tooltip,
          onclick: showPanel(editor, sidebar.name, editor.sidebars)
        };
      });
      return {
        type: 'panel',
        name: 'sidebar',
        layout: 'stack',
        classes: 'sidebar',
        items: [{
            type: 'toolbar',
            layout: 'stack',
            classes: 'sidebar-toolbar',
            items: buttons
          }]
      };
    };
    var Sidebar = {
      hasSidebar: hasSidebar,
      createSidebar: createSidebar
    };

    var fireSkinLoaded$1 = function (editor) {
      var done = function () {
        editor._skinLoaded = true;
        Events.fireSkinLoaded(editor);
      };
      return function () {
        if (editor.initialized) {
          done();
        } else {
          editor.on('init', done);
        }
      };
    };
    var SkinLoaded = { fireSkinLoaded: fireSkinLoaded$1 };

    var DOM$2 = global$3.DOM;
    var switchMode = function (panel) {
      return function (e) {
        panel.find('*').disabled(e.mode === 'readonly');
      };
    };
    var editArea = function (border) {
      return {
        type: 'panel',
        name: 'iframe',
        layout: 'stack',
        classes: 'edit-area',
        border: border,
        html: ''
      };
    };
    var editAreaContainer = function (editor) {
      return {
        type: 'panel',
        layout: 'stack',
        classes: 'edit-aria-container',
        border: '1 0 0 0',
        items: [
          editArea('0'),
          Sidebar.createSidebar(editor)
        ]
      };
    };
    var render = function (editor, theme, args) {
      var panel, resizeHandleCtrl, startSize;
      if (isSkinDisabled(editor) === false && args.skinUiCss) {
        DOM$2.styleSheetLoader.load(args.skinUiCss, SkinLoaded.fireSkinLoaded(editor));
      } else {
        SkinLoaded.fireSkinLoaded(editor)();
      }
      panel = theme.panel = global$4.create({
        type: 'panel',
        role: 'application',
        classes: 'tinymce',
        style: 'visibility: hidden',
        layout: 'stack',
        border: 1,
        items: [
          {
            type: 'container',
            classes: 'top-part',
            items: [
              hasMenubar(editor) === false ? null : {
                type: 'menubar',
                border: '0 0 1 0',
                items: Menubar.createMenuButtons(editor)
              },
              Toolbar.createToolbars(editor, getToolbarSize(editor))
            ]
          },
          Sidebar.hasSidebar(editor) ? editAreaContainer(editor) : editArea('1 0 0 0')
        ]
      });
      UiContainer.setUiContainer(editor, panel);
      if (getResize(editor) !== 'none') {
        resizeHandleCtrl = {
          type: 'resizehandle',
          direction: getResize(editor),
          onResizeStart: function () {
            var elm = editor.getContentAreaContainer().firstChild;
            startSize = {
              width: elm.clientWidth,
              height: elm.clientHeight
            };
          },
          onResize: function (e) {
            if (getResize(editor) === 'both') {
              Resize.resizeTo(editor, startSize.width + e.deltaX, startSize.height + e.deltaY);
            } else {
              Resize.resizeTo(editor, null, startSize.height + e.deltaY);
            }
          }
        };
      }
      if (hasStatusbar(editor)) {
        var linkHtml = '<a href="https://www.tiny.cloud/?utm_campaign=editor_referral&amp;utm_medium=poweredby&amp;utm_source=tinymce" rel="noopener" target="_blank" role="presentation" tabindex="-1">Tiny</a>';
        var html = global$5.translate([
          'Powered by {0}',
          linkHtml
        ]);
        var brandingLabel = isBrandingEnabled(editor) ? {
          type: 'label',
          classes: 'branding',
          html: ' ' + html
        } : null;
        panel.add({
          type: 'panel',
          name: 'statusbar',
          classes: 'statusbar',
          layout: 'flow',
          border: '1 0 0 0',
          ariaRoot: true,
          items: [
            {
              type: 'elementpath',
              editor: editor
            },
            resizeHandleCtrl,
            brandingLabel
          ]
        });
      }
      Events.fireBeforeRenderUI(editor);
      editor.on('SwitchMode', switchMode(panel));
      panel.renderBefore(args.targetNode).reflow();
      if (isReadOnly(editor)) {
        editor.setMode('readonly');
      }
      if (args.width) {
        DOM$2.setStyle(panel.getEl(), 'width', args.width);
      }
      editor.on('remove', function () {
        panel.remove();
        panel = null;
      });
      A11y.addKeys(editor, panel);
      ContextToolbars.addContextualToolbars(editor);
      return {
        iframeContainer: panel.find('#iframe')[0].getEl(),
        editorContainer: panel.getEl()
      };
    };
    var Iframe = { render: render };

    var global$9 = tinymce.util.Tools.resolve('tinymce.dom.DomQuery');

    var count = 0;
    var funcs = {
      id: function () {
        return 'mceu_' + count++;
      },
      create: function (name, attrs, children) {
        var elm = domGlobals.document.createElement(name);
        global$3.DOM.setAttribs(elm, attrs);
        if (typeof children === 'string') {
          elm.innerHTML = children;
        } else {
          global$2.each(children, function (child) {
            if (child.nodeType) {
              elm.appendChild(child);
            }
          });
        }
        return elm;
      },
      createFragment: function (html) {
        return global$3.DOM.createFragment(html);
      },
      getWindowSize: function () {
        return global$3.DOM.getViewPort();
      },
      getSize: function (elm) {
        var width, height;
        if (elm.getBoundingClientRect) {
          var rect = elm.getBoundingClientRect();
          width = Math.max(rect.width || rect.right - rect.left, elm.offsetWidth);
          height = Math.max(rect.height || rect.bottom - rect.bottom, elm.offsetHeight);
        } else {
          width = elm.offsetWidth;
          height = elm.offsetHeight;
        }
        return {
          width: width,
          height: height
        };
      },
      getPos: function (elm, root) {
        return global$3.DOM.getPos(elm, root || funcs.getContainer());
      },
      getContainer: function () {
        return global$8.container ? global$8.container : domGlobals.document.body;
      },
      getViewPort: function (win) {
        return global$3.DOM.getViewPort(win);
      },
      get: function (id) {
        return domGlobals.document.getElementById(id);
      },
      addClass: function (elm, cls) {
        return global$3.DOM.addClass(elm, cls);
      },
      removeClass: function (elm, cls) {
        return global$3.DOM.removeClass(elm, cls);
      },
      hasClass: function (elm, cls) {
        return global$3.DOM.hasClass(elm, cls);
      },
      toggleClass: function (elm, cls, state) {
        return global$3.DOM.toggleClass(elm, cls, state);
      },
      css: function (elm, name, value) {
        return global$3.DOM.setStyle(elm, name, value);
      },
      getRuntimeStyle: function (elm, name) {
        return global$3.DOM.getStyle(elm, name, true);
      },
      on: function (target, name, callback, scope) {
        return global$3.DOM.bind(target, name, callback, scope);
      },
      off: function (target, name, callback) {
        return global$3.DOM.unbind(target, name, callback);
      },
      fire: function (target, name, args) {
        return global$3.DOM.fire(target, name, args);
      },
      innerHtml: function (elm, html) {
        global$3.DOM.setHTML(elm, html);
      }
    };

    var isStatic = function (elm) {
      return funcs.getRuntimeStyle(elm, 'position') === 'static';
    };
    var isFixed = function (ctrl) {
      return ctrl.state.get('fixed');
    };
    function calculateRelativePosition(ctrl, targetElm, rel) {
      var ctrlElm, pos, x, y, selfW, selfH, targetW, targetH, viewport, size;
      viewport = getWindowViewPort();
      pos = funcs.getPos(targetElm, UiContainer.getUiContainer(ctrl));
      x = pos.x;
      y = pos.y;
      if (isFixed(ctrl) && isStatic(domGlobals.document.body)) {
        x -= viewport.x;
        y -= viewport.y;
      }
      ctrlElm = ctrl.getEl();
      size = funcs.getSize(ctrlElm);
      selfW = size.width;
      selfH = size.height;
      size = funcs.getSize(targetElm);
      targetW = size.width;
      targetH = size.height;
      rel = (rel || '').split('');
      if (rel[0] === 'b') {
        y += targetH;
      }
      if (rel[1] === 'r') {
        x += targetW;
      }
      if (rel[0] === 'c') {
        y += Math.round(targetH / 2);
      }
      if (rel[1] === 'c') {
        x += Math.round(targetW / 2);
      }
      if (rel[3] === 'b') {
        y -= selfH;
      }
      if (rel[4] === 'r') {
        x -= selfW;
      }
      if (rel[3] === 'c') {
        y -= Math.round(selfH / 2);
      }
      if (rel[4] === 'c') {
        x -= Math.round(selfW / 2);
      }
      return {
        x: x,
        y: y,
        w: selfW,
        h: selfH
      };
    }
    var getUiContainerViewPort = function (customUiContainer) {
      return {
        x: 0,
        y: 0,
        w: customUiContainer.scrollWidth - 1,
        h: customUiContainer.scrollHeight - 1
      };
    };
    var getWindowViewPort = function () {
      var win = domGlobals.window;
      var x = Math.max(win.pageXOffset, domGlobals.document.body.scrollLeft, domGlobals.document.documentElement.scrollLeft);
      var y = Math.max(win.pageYOffset, domGlobals.document.body.scrollTop, domGlobals.document.documentElement.scrollTop);
      var w = win.innerWidth || domGlobals.document.documentElement.clientWidth;
      var h = win.innerHeight || domGlobals.document.documentElement.clientHeight;
      return {
        x: x,
        y: y,
        w: w,
        h: h
      };
    };
    var getViewPortRect = function (ctrl) {
      var customUiContainer = UiContainer.getUiContainer(ctrl);
      return customUiContainer && !isFixed(ctrl) ? getUiContainerViewPort(customUiContainer) : getWindowViewPort();
    };
    var Movable = {
      testMoveRel: function (elm, rels) {
        var viewPortRect = getViewPortRect(this);
        for (var i = 0; i < rels.length; i++) {
          var pos = calculateRelativePosition(this, elm, rels[i]);
          if (isFixed(this)) {
            if (pos.x > 0 && pos.x + pos.w < viewPortRect.w && pos.y > 0 && pos.y + pos.h < viewPortRect.h) {
              return rels[i];
            }
          } else {
            if (pos.x > viewPortRect.x && pos.x + pos.w < viewPortRect.w + viewPortRect.x && pos.y > viewPortRect.y && pos.y + pos.h < viewPortRect.h + viewPortRect.y) {
              return rels[i];
            }
          }
        }
        return rels[0];
      },
      moveRel: function (elm, rel) {
        if (typeof rel !== 'string') {
          rel = this.testMoveRel(elm, rel);
        }
        var pos = calculateRelativePosition(this, elm, rel);
        return this.moveTo(pos.x, pos.y);
      },
      moveBy: function (dx, dy) {
        var self = this, rect = self.layoutRect();
        self.moveTo(rect.x + dx, rect.y + dy);
        return self;
      },
      moveTo: function (x, y) {
        var self = this;
        function constrain(value, max, size) {
          if (value < 0) {
            return 0;
          }
          if (value + size > max) {
            value = max - size;
            return value < 0 ? 0 : value;
          }
          return value;
        }
        if (self.settings.constrainToViewport) {
          var viewPortRect = getViewPortRect(this);
          var layoutRect = self.layoutRect();
          x = constrain(x, viewPortRect.w + viewPortRect.x, layoutRect.w);
          y = constrain(y, viewPortRect.h + viewPortRect.y, layoutRect.h);
        }
        var uiContainer = UiContainer.getUiContainer(self);
        if (uiContainer && isStatic(uiContainer) && !isFixed(self)) {
          x -= uiContainer.scrollLeft;
          y -= uiContainer.scrollTop;
        }
        if (uiContainer) {
          x += 1;
          y += 1;
        }
        if (self.state.get('rendered')) {
          self.layoutRect({
            x: x,
            y: y
          }).repaint();
        } else {
          self.settings.x = x;
          self.settings.y = y;
        }
        self.fire('move', {
          x: x,
          y: y
        });
        return self;
      }
    };

    var global$a = tinymce.util.Tools.resolve('tinymce.util.Class');

    var global$b = tinymce.util.Tools.resolve('tinymce.util.EventDispatcher');

    var BoxUtils = {
      parseBox: function (value) {
        var len;
        var radix = 10;
        if (!value) {
          return;
        }
        if (typeof value === 'number') {
          value = value || 0;
          return {
            top: value,
            left: value,
            bottom: value,
            right: value
          };
        }
        value = value.split(' ');
        len = value.length;
        if (len === 1) {
          value[1] = value[2] = value[3] = value[0];
        } else if (len === 2) {
          value[2] = value[0];
          value[3] = value[1];
        } else if (len === 3) {
          value[3] = value[1];
        }
        return {
          top: parseInt(value[0], radix) || 0,
          right: parseInt(value[1], radix) || 0,
          bottom: parseInt(value[2], radix) || 0,
          left: parseInt(value[3], radix) || 0
        };
      },
      measureBox: function (elm, prefix) {
        function getStyle(name) {
          var defaultView = elm.ownerDocument.defaultView;
          if (defaultView) {
            var computedStyle = defaultView.getComputedStyle(elm, null);
            if (computedStyle) {
              name = name.replace(/[A-Z]/g, function (a) {
                return '-' + a;
              });
              return computedStyle.getPropertyValue(name);
            } else {
              return null;
            }
          }
          return elm.currentStyle[name];
        }
        function getSide(name) {
          var val = parseFloat(getStyle(name));
          return isNaN(val) ? 0 : val;
        }
        return {
          top: getSide(prefix + 'TopWidth'),
          right: getSide(prefix + 'RightWidth'),
          bottom: getSide(prefix + 'BottomWidth'),
          left: getSide(prefix + 'LeftWidth')
        };
      }
    };

    function noop$1() {
    }
    function ClassList(onchange) {
      this.cls = [];
      this.cls._map = {};
      this.onchange = onchange || noop$1;
      this.prefix = '';
    }
    global$2.extend(ClassList.prototype, {
      add: function (cls) {
        if (cls && !this.contains(cls)) {
          this.cls._map[cls] = true;
          this.cls.push(cls);
          this._change();
        }
        return this;
      },
      remove: function (cls) {
        if (this.contains(cls)) {
          var i = void 0;
          for (i = 0; i < this.cls.length; i++) {
            if (this.cls[i] === cls) {
              break;
            }
          }
          this.cls.splice(i, 1);
          delete this.cls._map[cls];
          this._change();
        }
        return this;
      },
      toggle: function (cls, state) {
        var curState = this.contains(cls);
        if (curState !== state) {
          if (curState) {
            this.remove(cls);
          } else {
            this.add(cls);
          }
          this._change();
        }
        return this;
      },
      contains: function (cls) {
        return !!this.cls._map[cls];
      },
      _change: function () {
        delete this.clsValue;
        this.onchange.call(this);
      }
    });
    ClassList.prototype.toString = function () {
      var value;
      if (this.clsValue) {
        return this.clsValue;
      }
      value = '';
      for (var i = 0; i < this.cls.length; i++) {
        if (i > 0) {
          value += ' ';
        }
        value += this.prefix + this.cls[i];
      }
      return value;
    };

    function unique(array) {
      var uniqueItems = [];
      var i = array.length, item;
      while (i--) {
        item = array[i];
        if (!item.__checked) {
          uniqueItems.push(item);
          item.__checked = 1;
        }
      }
      i = uniqueItems.length;
      while (i--) {
        delete uniqueItems[i].__checked;
      }
      return uniqueItems;
    }
    var expression = /^([\w\\*]+)?(?:#([\w\-\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i;
    var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g;
    var whiteSpace = /^\s*|\s*$/g;
    var Collection;
    var Selector = global$a.extend({
      init: function (selector) {
        var match = this.match;
        function compileNameFilter(name) {
          if (name) {
            name = name.toLowerCase();
            return function (item) {
              return name === '*' || item.type === name;
            };
          }
        }
        function compileIdFilter(id) {
          if (id) {
            return function (item) {
              return item._name === id;
            };
          }
        }
        function compileClassesFilter(classes) {
          if (classes) {
            classes = classes.split('.');
            return function (item) {
              var i = classes.length;
              while (i--) {
                if (!item.classes.contains(classes[i])) {
                  return false;
                }
              }
              return true;
            };
          }
        }
        function compileAttrFilter(name, cmp, check) {
          if (name) {
            return function (item) {
              var value = item[name] ? item[name]() : '';
              return !cmp ? !!check : cmp === '=' ? value === check : cmp === '*=' ? value.indexOf(check) >= 0 : cmp === '~=' ? (' ' + value + ' ').indexOf(' ' + check + ' ') >= 0 : cmp === '!=' ? value !== check : cmp === '^=' ? value.indexOf(check) === 0 : cmp === '$=' ? value.substr(value.length - check.length) === check : false;
            };
          }
        }
        function compilePsuedoFilter(name) {
          var notSelectors;
          if (name) {
            name = /(?:not\((.+)\))|(.+)/i.exec(name);
            if (!name[1]) {
              name = name[2];
              return function (item, index, length) {
                return name === 'first' ? index === 0 : name === 'last' ? index === length - 1 : name === 'even' ? index % 2 === 0 : name === 'odd' ? index % 2 === 1 : item[name] ? item[name]() : false;
              };
            }
            notSelectors = parseChunks(name[1], []);
            return function (item) {
              return !match(item, notSelectors);
            };
          }
        }
        function compile(selector, filters, direct) {
          var parts;
          function add(filter) {
            if (filter) {
              filters.push(filter);
            }
          }
          parts = expression.exec(selector.replace(whiteSpace, ''));
          add(compileNameFilter(parts[1]));
          add(compileIdFilter(parts[2]));
          add(compileClassesFilter(parts[3]));
          add(compileAttrFilter(parts[4], parts[5], parts[6]));
          add(compilePsuedoFilter(parts[7]));
          filters.pseudo = !!parts[7];
          filters.direct = direct;
          return filters;
        }
        function parseChunks(selector, selectors) {
          var parts = [];
          var extra, matches, i;
          do {
            chunker.exec('');
            matches = chunker.exec(selector);
            if (matches) {
              selector = matches[3];
              parts.push(matches[1]);
              if (matches[2]) {
                extra = matches[3];
                break;
              }
            }
          } while (matches);
          if (extra) {
            parseChunks(extra, selectors);
          }
          selector = [];
          for (i = 0; i < parts.length; i++) {
            if (parts[i] !== '>') {
              selector.push(compile(parts[i], [], parts[i - 1] === '>'));
            }
          }
          selectors.push(selector);
          return selectors;
        }
        this._selectors = parseChunks(selector, []);
      },
      match: function (control, selectors) {
        var i, l, si, sl, selector, fi, fl, filters, index, length, siblings, count, item;
        selectors = selectors || this._selectors;
        for (i = 0, l = selectors.length; i < l; i++) {
          selector = selectors[i];
          sl = selector.length;
          item = control;
          count = 0;
          for (si = sl - 1; si >= 0; si--) {
            filters = selector[si];
            while (item) {
              if (filters.pseudo) {
                siblings = item.parent().items();
                index = length = siblings.length;
                while (index--) {
                  if (siblings[index] === item) {
                    break;
                  }
                }
              }
              for (fi = 0, fl = filters.length; fi < fl; fi++) {
                if (!filters[fi](item, index, length)) {
                  fi = fl + 1;
                  break;
                }
              }
              if (fi === fl) {
                count++;
                break;
              } else {
                if (si === sl - 1) {
                  break;
                }
              }
              item = item.parent();
            }
          }
          if (count === sl) {
            return true;
          }
        }
        return false;
      },
      find: function (container) {
        var matches = [], i, l;
        var selectors = this._selectors;
        function collect(items, selector, index) {
          var i, l, fi, fl, item;
          var filters = selector[index];
          for (i = 0, l = items.length; i < l; i++) {
            item = items[i];
            for (fi = 0, fl = filters.length; fi < fl; fi++) {
              if (!filters[fi](item, i, l)) {
                fi = fl + 1;
                break;
              }
            }
            if (fi === fl) {
              if (index === selector.length - 1) {
                matches.push(item);
              } else {
                if (item.items) {
                  collect(item.items(), selector, index + 1);
                }
              }
            } else if (filters.direct) {
              return;
            }
            if (item.items) {
              collect(item.items(), selector, index);
            }
          }
        }
        if (container.items) {
          for (i = 0, l = selectors.length; i < l; i++) {
            collect(container.items(), selectors[i], 0);
          }
          if (l > 1) {
            matches = unique(matches);
          }
        }
        if (!Collection) {
          Collection = Selector.Collection;
        }
        return new Collection(matches);
      }
    });

    var Collection$1, proto;
    var push = Array.prototype.push, slice = Array.prototype.slice;
    proto = {
      length: 0,
      init: function (items) {
        if (items) {
          this.add(items);
        }
      },
      add: function (items) {
        var self = this;
        if (!global$2.isArray(items)) {
          if (items instanceof Collection$1) {
            self.add(items.toArray());
          } else {
            push.call(self, items);
          }
        } else {
          push.apply(self, items);
        }
        return self;
      },
      set: function (items) {
        var self = this;
        var len = self.length;
        var i;
        self.length = 0;
        self.add(items);
        for (i = self.length; i < len; i++) {
          delete self[i];
        }
        return self;
      },
      filter: function (selector) {
        var self = this;
        var i, l;
        var matches = [];
        var item, match;
        if (typeof selector === 'string') {
          selector = new Selector(selector);
          match = function (item) {
            return selector.match(item);
          };
        } else {
          match = selector;
        }
        for (i = 0, l = self.length; i < l; i++) {
          item = self[i];
          if (match(item)) {
            matches.push(item);
          }
        }
        return new Collection$1(matches);
      },
      slice: function () {
        return new Collection$1(slice.apply(this, arguments));
      },
      eq: function (index) {
        return index === -1 ? this.slice(index) : this.slice(index, +index + 1);
      },
      each: function (callback) {
        global$2.each(this, callback);
        return this;
      },
      toArray: function () {
        return global$2.toArray(this);
      },
      indexOf: function (ctrl) {
        var self = this;
        var i = self.length;
        while (i--) {
          if (self[i] === ctrl) {
            break;
          }
        }
        return i;
      },
      reverse: function () {
        return new Collection$1(global$2.toArray(this).reverse());
      },
      hasClass: function (cls) {
        return this[0] ? this[0].classes.contains(cls) : false;
      },
      prop: function (name, value) {
        var self = this;
        var item;
        if (value !== undefined) {
          self.each(function (item) {
            if (item[name]) {
              item[name](value);
            }
          });
          return self;
        }
        item = self[0];
        if (item && item[name]) {
          return item[name]();
        }
      },
      exec: function (name) {
        var self = this, args = global$2.toArray(arguments).slice(1);
        self.each(function (item) {
          if (item[name]) {
            item[name].apply(item, args);
          }
        });
        return self;
      },
      remove: function () {
        var i = this.length;
        while (i--) {
          this[i].remove();
        }
        return this;
      },
      addClass: function (cls) {
        return this.each(function (item) {
          item.classes.add(cls);
        });
      },
      removeClass: function (cls) {
        return this.each(function (item) {
          item.classes.remove(cls);
        });
      }
    };
    global$2.each('fire on off show hide append prepend before after reflow'.split(' '), function (name) {
      proto[name] = function () {
        var args = global$2.toArray(arguments);
        this.each(function (ctrl) {
          if (name in ctrl) {
            ctrl[name].apply(ctrl, args);
          }
        });
        return this;
      };
    });
    global$2.each('text name disabled active selected checked visible parent value data'.split(' '), function (name) {
      proto[name] = function (value) {
        return this.prop(name, value);
      };
    });
    Collection$1 = global$a.extend(proto);
    Selector.Collection = Collection$1;
    var Collection$2 = Collection$1;

    var Binding = function (settings) {
      this.create = settings.create;
    };
    Binding.create = function (model, name) {
      return new Binding({
        create: function (otherModel, otherName) {
          var bindings;
          var fromSelfToOther = function (e) {
            otherModel.set(otherName, e.value);
          };
          var fromOtherToSelf = function (e) {
            model.set(name, e.value);
          };
          otherModel.on('change:' + otherName, fromOtherToSelf);
          model.on('change:' + name, fromSelfToOther);
          bindings = otherModel._bindings;
          if (!bindings) {
            bindings = otherModel._bindings = [];
            otherModel.on('destroy', function () {
              var i = bindings.length;
              while (i--) {
                bindings[i]();
              }
            });
          }
          bindings.push(function () {
            model.off('change:' + name, fromSelfToOther);
          });
          return model.get(name);
        }
      });
    };

    var global$c = tinymce.util.Tools.resolve('tinymce.util.Observable');

    function isNode(node) {
      return node.nodeType > 0;
    }
    function isEqual(a, b) {
      var k, checked;
      if (a === b) {
        return true;
      }
      if (a === null || b === null) {
        return a === b;
      }
      if (typeof a !== 'object' || typeof b !== 'object') {
        return a === b;
      }
      if (global$2.isArray(b)) {
        if (a.length !== b.length) {
          return false;
        }
        k = a.length;
        while (k--) {
          if (!isEqual(a[k], b[k])) {
            return false;
          }
        }
      }
      if (isNode(a) || isNode(b)) {
        return a === b;
      }
      checked = {};
      for (k in b) {
        if (!isEqual(a[k], b[k])) {
          return false;
        }
        checked[k] = true;
      }
      for (k in a) {
        if (!checked[k] && !isEqual(a[k], b[k])) {
          return false;
        }
      }
      return true;
    }
    var ObservableObject = global$a.extend({
      Mixins: [global$c],
      init: function (data) {
        var name, value;
        data = data || {};
        for (name in data) {
          value = data[name];
          if (value instanceof Binding) {
            data[name] = value.create(this, name);
          }
        }
        this.data = data;
      },
      set: function (name, value) {
        var key, args;
        var oldValue = this.data[name];
        if (value instanceof Binding) {
          value = value.create(this, name);
        }
        if (typeof name === 'object') {
          for (key in name) {
            this.set(key, name[key]);
          }
          return this;
        }
        if (!isEqual(oldValue, value)) {
          this.data[name] = value;
          args = {
            target: this,
            name: name,
            value: value,
            oldValue: oldValue
          };
          this.fire('change:' + name, args);
          this.fire('change', args);
        }
        return this;
      },
      get: function (name) {
        return this.data[name];
      },
      has: function (name) {
        return name in this.data;
      },
      bind: function (name) {
        return Binding.create(this, name);
      },
      destroy: function () {
        this.fire('destroy');
      }
    });

    var dirtyCtrls = {}, animationFrameRequested;
    var ReflowQueue = {
      add: function (ctrl) {
        var parent = ctrl.parent();
        if (parent) {
          if (!parent._layout || parent._layout.isNative()) {
            return;
          }
          if (!dirtyCtrls[parent._id]) {
            dirtyCtrls[parent._id] = parent;
          }
          if (!animationFrameRequested) {
            animationFrameRequested = true;
            global$7.requestAnimationFrame(function () {
              var id, ctrl;
              animationFrameRequested = false;
              for (id in dirtyCtrls) {
                ctrl = dirtyCtrls[id];
                if (ctrl.state.get('rendered')) {
                  ctrl.reflow();
                }
              }
              dirtyCtrls = {};
            }, domGlobals.document.body);
          }
        }
      },
      remove: function (ctrl) {
        if (dirtyCtrls[ctrl._id]) {
          delete dirtyCtrls[ctrl._id];
        }
      }
    };

    var hasMouseWheelEventSupport = 'onmousewheel' in domGlobals.document;
    var hasWheelEventSupport = false;
    var classPrefix = 'mce-';
    var Control, idCounter = 0;
    var proto$1 = {
      Statics: { classPrefix: classPrefix },
      isRtl: function () {
        return Control.rtl;
      },
      classPrefix: classPrefix,
      init: function (settings) {
        var self = this;
        var classes, defaultClasses;
        function applyClasses(classes) {
          var i;
          classes = classes.split(' ');
          for (i = 0; i < classes.length; i++) {
            self.classes.add(classes[i]);
          }
        }
        self.settings = settings = global$2.extend({}, self.Defaults, settings);
        self._id = settings.id || 'mceu_' + idCounter++;
        self._aria = { role: settings.role };
        self._elmCache = {};
        self.$ = global$9;
        self.state = new ObservableObject({
          visible: true,
          active: false,
          disabled: false,
          value: ''
        });
        self.data = new ObservableObject(settings.data);
        self.classes = new ClassList(function () {
          if (self.state.get('rendered')) {
            self.getEl().className = this.toString();
          }
        });
        self.classes.prefix = self.classPrefix;
        classes = settings.classes;
        if (classes) {
          if (self.Defaults) {
            defaultClasses = self.Defaults.classes;
            if (defaultClasses && classes !== defaultClasses) {
              applyClasses(defaultClasses);
            }
          }
          applyClasses(classes);
        }
        global$2.each('title text name visible disabled active value'.split(' '), function (name) {
          if (name in settings) {
            self[name](settings[name]);
          }
        });
        self.on('click', function () {
          if (self.disabled()) {
            return false;
          }
        });
        self.settings = settings;
        self.borderBox = BoxUtils.parseBox(settings.border);
        self.paddingBox = BoxUtils.parseBox(settings.padding);
        self.marginBox = BoxUtils.parseBox(settings.margin);
        if (settings.hidden) {
          self.hide();
        }
      },
      Properties: 'parent,name',
      getContainerElm: function () {
        var uiContainer = UiContainer.getUiContainer(this);
        return uiContainer ? uiContainer : funcs.getContainer();
      },
      getParentCtrl: function (elm) {
        var ctrl;
        var lookup = this.getRoot().controlIdLookup;
        while (elm && lookup) {
          ctrl = lookup[elm.id];
          if (ctrl) {
            break;
          }
          elm = elm.parentNode;
        }
        return ctrl;
      },
      initLayoutRect: function () {
        var self = this;
        var settings = self.settings;
        var borderBox, layoutRect;
        var elm = self.getEl();
        var width, height, minWidth, minHeight, autoResize;
        var startMinWidth, startMinHeight, initialSize;
        borderBox = self.borderBox = self.borderBox || BoxUtils.measureBox(elm, 'border');
        self.paddingBox = self.paddingBox || BoxUtils.measureBox(elm, 'padding');
        self.marginBox = self.marginBox || BoxUtils.measureBox(elm, 'margin');
        initialSize = funcs.getSize(elm);
        startMinWidth = settings.minWidth;
        startMinHeight = settings.minHeight;
        minWidth = startMinWidth || initialSize.width;
        minHeight = startMinHeight || initialSize.height;
        width = settings.width;
        height = settings.height;
        autoResize = settings.autoResize;
        autoResize = typeof autoResize !== 'undefined' ? autoResize : !width && !height;
        width = width || minWidth;
        height = height || minHeight;
        var deltaW = borderBox.left + borderBox.right;
        var deltaH = borderBox.top + borderBox.bottom;
        var maxW = settings.maxWidth || 65535;
        var maxH = settings.maxHeight || 65535;
        self._layoutRect = layoutRect = {
          x: settings.x || 0,
          y: settings.y || 0,
          w: width,
          h: height,
          deltaW: deltaW,
          deltaH: deltaH,
          contentW: width - deltaW,
          contentH: height - deltaH,
          innerW: width - deltaW,
          innerH: height - deltaH,
          startMinWidth: startMinWidth || 0,
          startMinHeight: startMinHeight || 0,
          minW: Math.min(minWidth, maxW),
          minH: Math.min(minHeight, maxH),
          maxW: maxW,
          maxH: maxH,
          autoResize: autoResize,
          scrollW: 0
        };
        self._lastLayoutRect = {};
        return layoutRect;
      },
      layoutRect: function (newRect) {
        var self = this;
        var curRect = self._layoutRect, lastLayoutRect, size, deltaWidth, deltaHeight, repaintControls;
        if (!curRect) {
          curRect = self.initLayoutRect();
        }
        if (newRect) {
          deltaWidth = curRect.deltaW;
          deltaHeight = curRect.deltaH;
          if (newRect.x !== undefined) {
            curRect.x = newRect.x;
          }
          if (newRect.y !== undefined) {
            curRect.y = newRect.y;
          }
          if (newRect.minW !== undefined) {
            curRect.minW = newRect.minW;
          }
          if (newRect.minH !== undefined) {
            curRect.minH = newRect.minH;
          }
          size = newRect.w;
          if (size !== undefined) {
            size = size < curRect.minW ? curRect.minW : size;
            size = size > curRect.maxW ? curRect.maxW : size;
            curRect.w = size;
            curRect.innerW = size - deltaWidth;
          }
          size = newRect.h;
          if (size !== undefined) {
            size = size < curRect.minH ? curRect.minH : size;
            size = size > curRect.maxH ? curRect.maxH : size;
            curRect.h = size;
            curRect.innerH = size - deltaHeight;
          }
          size = newRect.innerW;
          if (size !== undefined) {
            size = size < curRect.minW - deltaWidth ? curRect.minW - deltaWidth : size;
            size = size > curRect.maxW - deltaWidth ? curRect.maxW - deltaWidth : size;
            curRect.innerW = size;
            curRect.w = size + deltaWidth;
          }
          size = newRect.innerH;
          if (size !== undefined) {
            size = size < curRect.minH - deltaHeight ? curRect.minH - deltaHeight : size;
            size = size > curRect.maxH - deltaHeight ? curRect.maxH - deltaHeight : size;
            curRect.innerH = size;
            curRect.h = size + deltaHeight;
          }
          if (newRect.contentW !== undefined) {
            curRect.contentW = newRect.contentW;
          }
          if (newRect.contentH !== undefined) {
            curRect.contentH = newRect.contentH;
          }
          lastLayoutRect = self._lastLayoutRect;
          if (lastLayoutRect.x !== curRect.x || lastLayoutRect.y !== curRect.y || lastLayoutRect.w !== curRect.w || lastLayoutRect.h !== curRect.h) {
            repaintControls = Control.repaintControls;
            if (repaintControls) {
              if (repaintControls.map && !repaintControls.map[self._id]) {
                repaintControls.push(self);
                repaintControls.map[self._id] = true;
              }
            }
            lastLayoutRect.x = curRect.x;
            lastLayoutRect.y = curRect.y;
            lastLayoutRect.w = curRect.w;
            lastLayoutRect.h = curRect.h;
          }
          return self;
        }
        return curRect;
      },
      repaint: function () {
        var self = this;
        var style, bodyStyle, bodyElm, rect, borderBox;
        var borderW, borderH, lastRepaintRect, round, value;
        round = !domGlobals.document.createRange ? Math.round : function (value) {
          return value;
        };
        style = self.getEl().style;
        rect = self._layoutRect;
        lastRepaintRect = self._lastRepaintRect || {};
        borderBox = self.borderBox;
        borderW = borderBox.left + borderBox.right;
        borderH = borderBox.top + borderBox.bottom;
        if (rect.x !== lastRepaintRect.x) {
          style.left = round(rect.x) + 'px';
          lastRepaintRect.x = rect.x;
        }
        if (rect.y !== lastRepaintRect.y) {
          style.top = round(rect.y) + 'px';
          lastRepaintRect.y = rect.y;
        }
        if (rect.w !== lastRepaintRect.w) {
          value = round(rect.w - borderW);
          style.width = (value >= 0 ? value : 0) + 'px';
          lastRepaintRect.w = rect.w;
        }
        if (rect.h !== lastRepaintRect.h) {
          value = round(rect.h - borderH);
          style.height = (value >= 0 ? value : 0) + 'px';
          lastRepaintRect.h = rect.h;
        }
        if (self._hasBody && rect.innerW !== lastRepaintRect.innerW) {
          value = round(rect.innerW);
          bodyElm = self.getEl('body');
          if (bodyElm) {
            bodyStyle = bodyElm.style;
            bodyStyle.width = (value >= 0 ? value : 0) + 'px';
          }
          lastRepaintRect.innerW = rect.innerW;
        }
        if (self._hasBody && rect.innerH !== lastRepaintRect.innerH) {
          value = round(rect.innerH);
          bodyElm = bodyElm || self.getEl('body');
          if (bodyElm) {
            bodyStyle = bodyStyle || bodyElm.style;
            bodyStyle.height = (value >= 0 ? value : 0) + 'px';
          }
          lastRepaintRect.innerH = rect.innerH;
        }
        self._lastRepaintRect = lastRepaintRect;
        self.fire('repaint', {}, false);
      },
      updateLayoutRect: function () {
        var self = this;
        self.parent()._lastRect = null;
        funcs.css(self.getEl(), {
          width: '',
          height: ''
        });
        self._layoutRect = self._lastRepaintRect = self._lastLayoutRect = null;
        self.initLayoutRect();
      },
      on: function (name, callback) {
        var self = this;
        function resolveCallbackName(name) {
          var callback, scope;
          if (typeof name !== 'string') {
            return name;
          }
          return function (e) {
            if (!callback) {
              self.parentsAndSelf().each(function (ctrl) {
                var callbacks = ctrl.settings.callbacks;
                if (callbacks && (callback = callbacks[name])) {
                  scope = ctrl;
                  return false;
                }
              });
            }
            if (!callback) {
              e.action = name;
              this.fire('execute', e);
              return;
            }
            return callback.call(scope, e);
          };
        }
        getEventDispatcher(self).on(name, resolveCallbackName(callback));
        return self;
      },
      off: function (name, callback) {
        getEventDispatcher(this).off(name, callback);
        return this;
      },
      fire: function (name, args, bubble) {
        var self = this;
        args = args || {};
        if (!args.control) {
          args.control = self;
        }
        args = getEventDispatcher(self).fire(name, args);
        if (bubble !== false && self.parent) {
          var parent = self.parent();
          while (parent && !args.isPropagationStopped()) {
            parent.fire(name, args, false);
            parent = parent.parent();
          }
        }
        return args;
      },
      hasEventListeners: function (name) {
        return getEventDispatcher(this).has(name);
      },
      parents: function (selector) {
        var self = this;
        var ctrl, parents = new Collection$2();
        for (ctrl = self.parent(); ctrl; ctrl = ctrl.parent()) {
          parents.add(ctrl);
        }
        if (selector) {
          parents = parents.filter(selector);
        }
        return parents;
      },
      parentsAndSelf: function (selector) {
        return new Collection$2(this).add(this.parents(selector));
      },
      next: function () {
        var parentControls = this.parent().items();
        return parentControls[parentControls.indexOf(this) + 1];
      },
      prev: function () {
        var parentControls = this.parent().items();
        return parentControls[parentControls.indexOf(this) - 1];
      },
      innerHtml: function (html) {
        this.$el.html(html);
        return this;
      },
      getEl: function (suffix) {
        var id = suffix ? this._id + '-' + suffix : this._id;
        if (!this._elmCache[id]) {
          this._elmCache[id] = global$9('#' + id)[0];
        }
        return this._elmCache[id];
      },
      show: function () {
        return this.visible(true);
      },
      hide: function () {
        return this.visible(false);
      },
      focus: function () {
        try {
          this.getEl().focus();
        } catch (ex) {
        }
        return this;
      },
      blur: function () {
        this.getEl().blur();
        return this;
      },
      aria: function (name, value) {
        var self = this, elm = self.getEl(self.ariaTarget);
        if (typeof value === 'undefined') {
          return self._aria[name];
        }
        self._aria[name] = value;
        if (self.state.get('rendered')) {
          elm.setAttribute(name === 'role' ? name : 'aria-' + name, value);
        }
        return self;
      },
      encode: function (text, translate) {
        if (translate !== false) {
          text = this.translate(text);
        }
        return (text || '').replace(/[&<>"]/g, function (match) {
          return '&#' + match.charCodeAt(0) + ';';
        });
      },
      translate: function (text) {
        return Control.translate ? Control.translate(text) : text;
      },
      before: function (items) {
        var self = this, parent = self.parent();
        if (parent) {
          parent.insert(items, parent.items().indexOf(self), true);
        }
        return self;
      },
      after: function (items) {
        var self = this, parent = self.parent();
        if (parent) {
          parent.insert(items, parent.items().indexOf(self));
        }
        return self;
      },
      remove: function () {
        var self = this;
        var elm = self.getEl();
        var parent = self.parent();
        var newItems, i;
        if (self.items) {
          var controls = self.items().toArray();
          i = controls.length;
          while (i--) {
            controls[i].remove();
          }
        }
        if (parent && parent.items) {
          newItems = [];
          parent.items().each(function (item) {
            if (item !== self) {
              newItems.push(item);
            }
          });
          parent.items().set(newItems);
          parent._lastRect = null;
        }
        if (self._eventsRoot && self._eventsRoot === self) {
          global$9(elm).off();
        }
        var lookup = self.getRoot().controlIdLookup;
        if (lookup) {
          delete lookup[self._id];
        }
        if (elm && elm.parentNode) {
          elm.parentNode.removeChild(elm);
        }
        self.state.set('rendered', false);
        self.state.destroy();
        self.fire('remove');
        return self;
      },
      renderBefore: function (elm) {
        global$9(elm).before(this.renderHtml());
        this.postRender();
        return this;
      },
      renderTo: function (elm) {
        global$9(elm || this.getContainerElm()).append(this.renderHtml());
        this.postRender();
        return this;
      },
      preRender: function () {
      },
      render: function () {
      },
      renderHtml: function () {
        return '<div id="' + this._id + '" class="' + this.classes + '"></div>';
      },
      postRender: function () {
        var self = this;
        var settings = self.settings;
        var elm, box, parent, name, parentEventsRoot;
        self.$el = global$9(self.getEl());
        self.state.set('rendered', true);
        for (name in settings) {
          if (name.indexOf('on') === 0) {
            self.on(name.substr(2), settings[name]);
          }
        }
        if (self._eventsRoot) {
          for (parent = self.parent(); !parentEventsRoot && parent; parent = parent.parent()) {
            parentEventsRoot = parent._eventsRoot;
          }
          if (parentEventsRoot) {
            for (name in parentEventsRoot._nativeEvents) {
              self._nativeEvents[name] = true;
            }
          }
        }
        bindPendingEvents(self);
        if (settings.style) {
          elm = self.getEl();
          if (elm) {
            elm.setAttribute('style', settings.style);
            elm.style.cssText = settings.style;
          }
        }
        if (self.settings.border) {
          box = self.borderBox;
          self.$el.css({
            'border-top-width': box.top,
            'border-right-width': box.right,
            'border-bottom-width': box.bottom,
            'border-left-width': box.left
          });
        }
        var root = self.getRoot();
        if (!root.controlIdLookup) {
          root.controlIdLookup = {};
        }
        root.controlIdLookup[self._id] = self;
        for (var key in self._aria) {
          self.aria(key, self._aria[key]);
        }
        if (self.state.get('visible') === false) {
          self.getEl().style.display = 'none';
        }
        self.bindStates();
        self.state.on('change:visible', function (e) {
          var state = e.value;
          var parentCtrl;
          if (self.state.get('rendered')) {
            self.getEl().style.display = state === false ? 'none' : '';
            self.getEl().getBoundingClientRect();
          }
          parentCtrl = self.parent();
          if (parentCtrl) {
            parentCtrl._lastRect = null;
          }
          self.fire(state ? 'show' : 'hide');
          ReflowQueue.add(self);
        });
        self.fire('postrender', {}, false);
      },
      bindStates: function () {
      },
      scrollIntoView: function (align) {
        function getOffset(elm, rootElm) {
          var x, y, parent = elm;
          x = y = 0;
          while (parent && parent !== rootElm && parent.nodeType) {
            x += parent.offsetLeft || 0;
            y += parent.offsetTop || 0;
            parent = parent.offsetParent;
          }
          return {
            x: x,
            y: y
          };
        }
        var elm = this.getEl(), parentElm = elm.parentNode;
        var x, y, width, height, parentWidth, parentHeight;
        var pos = getOffset(elm, parentElm);
        x = pos.x;
        y = pos.y;
        width = elm.offsetWidth;
        height = elm.offsetHeight;
        parentWidth = parentElm.clientWidth;
        parentHeight = parentElm.clientHeight;
        if (align === 'end') {
          x -= parentWidth - width;
          y -= parentHeight - height;
        } else if (align === 'center') {
          x -= parentWidth / 2 - width / 2;
          y -= parentHeight / 2 - height / 2;
        }
        parentElm.scrollLeft = x;
        parentElm.scrollTop = y;
        return this;
      },
      getRoot: function () {
        var ctrl = this, rootControl;
        var parents = [];
        while (ctrl) {
          if (ctrl.rootControl) {
            rootControl = ctrl.rootControl;
            break;
          }
          parents.push(ctrl);
          rootControl = ctrl;
          ctrl = ctrl.parent();
        }
        if (!rootControl) {
          rootControl = this;
        }
        var i = parents.length;
        while (i--) {
          parents[i].rootControl = rootControl;
        }
        return rootControl;
      },
      reflow: function () {
        ReflowQueue.remove(this);
        var parent = this.parent();
        if (parent && parent._layout && !parent._layout.isNative()) {
          parent.reflow();
        }
        return this;
      }
    };
    global$2.each('text title visible disabled active value'.split(' '), function (name) {
      proto$1[name] = function (value) {
        if (arguments.length === 0) {
          return this.state.get(name);
        }
        if (typeof value !== 'undefined') {
          this.state.set(name, value);
        }
        return this;
      };
    });
    Control = global$a.extend(proto$1);
    function getEventDispatcher(obj) {
      if (!obj._eventDispatcher) {
        obj._eventDispatcher = new global$b({
          scope: obj,
          toggleEvent: function (name, state) {
            if (state && global$b.isNative(name)) {
              if (!obj._nativeEvents) {
                obj._nativeEvents = {};
              }
              obj._nativeEvents[name] = true;
              if (obj.state.get('rendered')) {
                bindPendingEvents(obj);
              }
            }
          }
        });
      }
      return obj._eventDispatcher;
    }
    function bindPendingEvents(eventCtrl) {
      var i, l, parents, eventRootCtrl, nativeEvents, name;
      function delegate(e) {
        var control = eventCtrl.getParentCtrl(e.target);
        if (control) {
          control.fire(e.type, e);
        }
      }
      function mouseLeaveHandler() {
        var ctrl = eventRootCtrl._lastHoverCtrl;
        if (ctrl) {
          ctrl.fire('mouseleave', { target: ctrl.getEl() });
          ctrl.parents().each(function (ctrl) {
            ctrl.fire('mouseleave', { target: ctrl.getEl() });
          });
          eventRootCtrl._lastHoverCtrl = null;
        }
      }
      function mouseEnterHandler(e) {
        var ctrl = eventCtrl.getParentCtrl(e.target), lastCtrl = eventRootCtrl._lastHoverCtrl, idx = 0, i, parents, lastParents;
        if (ctrl !== lastCtrl) {
          eventRootCtrl._lastHoverCtrl = ctrl;
          parents = ctrl.parents().toArray().reverse();
          parents.push(ctrl);
          if (lastCtrl) {
            lastParents = lastCtrl.parents().toArray().reverse();
            lastParents.push(lastCtrl);
            for (idx = 0; idx < lastParents.length; idx++) {
              if (parents[idx] !== lastParents[idx]) {
                break;
              }
            }
            for (i = lastParents.length - 1; i >= idx; i--) {
              lastCtrl = lastParents[i];
              lastCtrl.fire('mouseleave', { target: lastCtrl.getEl() });
            }
          }
          for (i = idx; i < parents.length; i++) {
            ctrl = parents[i];
            ctrl.fire('mouseenter', { target: ctrl.getEl() });
          }
        }
      }
      function fixWheelEvent(e) {
        e.preventDefault();
        if (e.type === 'mousewheel') {
          e.deltaY = -1 / 40 * e.wheelDelta;
          if (e.wheelDeltaX) {
            e.deltaX = -1 / 40 * e.wheelDeltaX;
          }
        } else {
          e.deltaX = 0;
          e.deltaY = e.detail;
        }
        e = eventCtrl.fire('wheel', e);
      }
      nativeEvents = eventCtrl._nativeEvents;
      if (nativeEvents) {
        parents = eventCtrl.parents().toArray();
        parents.unshift(eventCtrl);
        for (i = 0, l = parents.length; !eventRootCtrl && i < l; i++) {
          eventRootCtrl = parents[i]._eventsRoot;
        }
        if (!eventRootCtrl) {
          eventRootCtrl = parents[parents.length - 1] || eventCtrl;
        }
        eventCtrl._eventsRoot = eventRootCtrl;
        for (l = i, i = 0; i < l; i++) {
          parents[i]._eventsRoot = eventRootCtrl;
        }
        var eventRootDelegates = eventRootCtrl._delegates;
        if (!eventRootDelegates) {
          eventRootDelegates = eventRootCtrl._delegates = {};
        }
        for (name in nativeEvents) {
          if (!nativeEvents) {
            return false;
          }
          if (name === 'wheel' && !hasWheelEventSupport) {
            if (hasMouseWheelEventSupport) {
              global$9(eventCtrl.getEl()).on('mousewheel', fixWheelEvent);
            } else {
              global$9(eventCtrl.getEl()).on('DOMMouseScroll', fixWheelEvent);
            }
            continue;
          }
          if (name === 'mouseenter' || name === 'mouseleave') {
            if (!eventRootCtrl._hasMouseEnter) {
              global$9(eventRootCtrl.getEl()).on('mouseleave', mouseLeaveHandler).on('mouseover', mouseEnterHandler);
              eventRootCtrl._hasMouseEnter = 1;
            }
          } else if (!eventRootDelegates[name]) {
            global$9(eventRootCtrl.getEl()).on(name, delegate);
            eventRootDelegates[name] = true;
          }
          nativeEvents[name] = false;
        }
      }
    }
    var Control$1 = Control;

    var hasTabstopData = function (elm) {
      return elm.getAttribute('data-mce-tabstop') ? true : false;
    };
    function KeyboardNavigation (settings) {
      var root = settings.root;
      var focusedElement, focusedControl;
      function isElement(node) {
        return node && node.nodeType === 1;
      }
      try {
        focusedElement = domGlobals.document.activeElement;
      } catch (ex) {
        focusedElement = domGlobals.document.body;
      }
      focusedControl = root.getParentCtrl(focusedElement);
      function getRole(elm) {
        elm = elm || focusedElement;
        if (isElement(elm)) {
          return elm.getAttribute('role');
        }
        return null;
      }
      function getParentRole(elm) {
        var role, parent = elm || focusedElement;
        while (parent = parent.parentNode) {
          if (role = getRole(parent)) {
            return role;
          }
        }
      }
      function getAriaProp(name) {
        var elm = focusedElement;
        if (isElement(elm)) {
          return elm.getAttribute('aria-' + name);
        }
      }
      function isTextInputElement(elm) {
        var tagName = elm.tagName.toUpperCase();
        return tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT';
      }
      function canFocus(elm) {
        if (isTextInputElement(elm) && !elm.hidden) {
          return true;
        }
        if (hasTabstopData(elm)) {
          return true;
        }
        if (/^(button|menuitem|checkbox|tab|menuitemcheckbox|option|gridcell|slider)$/.test(getRole(elm))) {
          return true;
        }
        return false;
      }
      function getFocusElements(elm) {
        var elements = [];
        function collect(elm) {
          if (elm.nodeType !== 1 || elm.style.display === 'none' || elm.disabled) {
            return;
          }
          if (canFocus(elm)) {
            elements.push(elm);
          }
          for (var i = 0; i < elm.childNodes.length; i++) {
            collect(elm.childNodes[i]);
          }
        }
        collect(elm || root.getEl());
        return elements;
      }
      function getNavigationRoot(targetControl) {
        var navigationRoot, controls;
        targetControl = targetControl || focusedControl;
        controls = targetControl.parents().toArray();
        controls.unshift(targetControl);
        for (var i = 0; i < controls.length; i++) {
          navigationRoot = controls[i];
          if (navigationRoot.settings.ariaRoot) {
            break;
          }
        }
        return navigationRoot;
      }
      function focusFirst(targetControl) {
        var navigationRoot = getNavigationRoot(targetControl);
        var focusElements = getFocusElements(navigationRoot.getEl());
        if (navigationRoot.settings.ariaRemember && 'lastAriaIndex' in navigationRoot) {
          moveFocusToIndex(navigationRoot.lastAriaIndex, focusElements);
        } else {
          moveFocusToIndex(0, focusElements);
        }
      }
      function moveFocusToIndex(idx, elements) {
        if (idx < 0) {
          idx = elements.length - 1;
        } else if (idx >= elements.length) {
          idx = 0;
        }
        if (elements[idx]) {
          elements[idx].focus();
        }
        return idx;
      }
      function moveFocus(dir, elements) {
        var idx = -1;
        var navigationRoot = getNavigationRoot();
        elements = elements || getFocusElements(navigationRoot.getEl());
        for (var i = 0; i < elements.length; i++) {
          if (elements[i] === focusedElement) {
            idx = i;
          }
        }
        idx += dir;
        navigationRoot.lastAriaIndex = moveFocusToIndex(idx, elements);
      }
      function left() {
        var parentRole = getParentRole();
        if (parentRole === 'tablist') {
          moveFocus(-1, getFocusElements(focusedElement.parentNode));
        } else if (focusedControl.parent().submenu) {
          cancel();
        } else {
          moveFocus(-1);
        }
      }
      function right() {
        var role = getRole(), parentRole = getParentRole();
        if (parentRole === 'tablist') {
          moveFocus(1, getFocusElements(focusedElement.parentNode));
        } else if (role === 'menuitem' && parentRole === 'menu' && getAriaProp('haspopup')) {
          enter();
        } else {
          moveFocus(1);
        }
      }
      function up() {
        moveFocus(-1);
      }
      function down() {
        var role = getRole(), parentRole = getParentRole();
        if (role === 'menuitem' && parentRole === 'menubar') {
          enter();
        } else if (role === 'button' && getAriaProp('haspopup')) {
          enter({ key: 'down' });
        } else {
          moveFocus(1);
        }
      }
      function tab(e) {
        var parentRole = getParentRole();
        if (parentRole === 'tablist') {
          var elm = getFocusElements(focusedControl.getEl('body'))[0];
          if (elm) {
            elm.focus();
          }
        } else {
          moveFocus(e.shiftKey ? -1 : 1);
        }
      }
      function cancel() {
        focusedControl.fire('cancel');
      }
      function enter(aria) {
        aria = aria || {};
        focusedControl.fire('click', {
          target: focusedElement,
          aria: aria
        });
      }
      root.on('keydown', function (e) {
        function handleNonTabOrEscEvent(e, handler) {
          if (isTextInputElement(focusedElement) || hasTabstopData(focusedElement)) {
            return;
          }
          if (getRole(focusedElement) === 'slider') {
            return;
          }
          if (handler(e) !== false) {
            e.preventDefault();
          }
        }
        if (e.isDefaultPrevented()) {
          return;
        }
        switch (e.keyCode) {
        case 37:
          handleNonTabOrEscEvent(e, left);
          break;
        case 39:
          handleNonTabOrEscEvent(e, right);
          break;
        case 38:
          handleNonTabOrEscEvent(e, up);
          break;
        case 40:
          handleNonTabOrEscEvent(e, down);
          break;
        case 27:
          cancel();
          break;
        case 14:
        case 13:
        case 32:
          handleNonTabOrEscEvent(e, enter);
          break;
        case 9:
          tab(e);
          e.preventDefault();
          break;
        }
      });
      root.on('focusin', function (e) {
        focusedElement = e.target;
        focusedControl = e.control;
      });
      return { focusFirst: focusFirst };
    }

    var selectorCache = {};
    var Container = Control$1.extend({
      init: function (settings) {
        var self = this;
        self._super(settings);
        settings = self.settings;
        if (settings.fixed) {
          self.state.set('fixed', true);
        }
        self._items = new Collection$2();
        if (self.isRtl()) {
          self.classes.add('rtl');
        }
        self.bodyClasses = new ClassList(function () {
          if (self.state.get('rendered')) {
            self.getEl('body').className = this.toString();
          }
        });
        self.bodyClasses.prefix = self.classPrefix;
        self.classes.add('container');
        self.bodyClasses.add('container-body');
        if (settings.containerCls) {
          self.classes.add(settings.containerCls);
        }
        self._layout = global$4.create((settings.layout || '') + 'layout');
        if (self.settings.items) {
          self.add(self.settings.items);
        } else {
          self.add(self.render());
        }
        self._hasBody = true;
      },
      items: function () {
        return this._items;
      },
      find: function (selector) {
        selector = selectorCache[selector] = selectorCache[selector] || new Selector(selector);
        return selector.find(this);
      },
      add: function (items) {
        var self = this;
        self.items().add(self.create(items)).parent(self);
        return self;
      },
      focus: function (keyboard) {
        var self = this;
        var focusCtrl, keyboardNav, items;
        if (keyboard) {
          keyboardNav = self.keyboardNav || self.parents().eq(-1)[0].keyboardNav;
          if (keyboardNav) {
            keyboardNav.focusFirst(self);
            return;
          }
        }
        items = self.find('*');
        if (self.statusbar) {
          items.add(self.statusbar.items());
        }
        items.each(function (ctrl) {
          if (ctrl.settings.autofocus) {
            focusCtrl = null;
            return false;
          }
          if (ctrl.canFocus) {
            focusCtrl = focusCtrl || ctrl;
          }
        });
        if (focusCtrl) {
          focusCtrl.focus();
        }
        return self;
      },
      replace: function (oldItem, newItem) {
        var ctrlElm;
        var items = this.items();
        var i = items.length;
        while (i--) {
          if (items[i] === oldItem) {
            items[i] = newItem;
            break;
          }
        }
        if (i >= 0) {
          ctrlElm = newItem.getEl();
          if (ctrlElm) {
            ctrlElm.parentNode.removeChild(ctrlElm);
          }
          ctrlElm = oldItem.getEl();
          if (ctrlElm) {
            ctrlElm.parentNode.removeChild(ctrlElm);
          }
        }
        newItem.parent(this);
      },
      create: function (items) {
        var self = this;
        var settings;
        var ctrlItems = [];
        if (!global$2.isArray(items)) {
          items = [items];
        }
        global$2.each(items, function (item) {
          if (item) {
            if (!(item instanceof Control$1)) {
              if (typeof item === 'string') {
                item = { type: item };
              }
              settings = global$2.extend({}, self.settings.defaults, item);
              item.type = settings.type = settings.type || item.type || self.settings.defaultType || (settings.defaults ? settings.defaults.type : null);
              item = global$4.create(settings);
            }
            ctrlItems.push(item);
          }
        });
        return ctrlItems;
      },
      renderNew: function () {
        var self = this;
        self.items().each(function (ctrl, index) {
          var containerElm;
          ctrl.parent(self);
          if (!ctrl.state.get('rendered')) {
            containerElm = self.getEl('body');
            if (containerElm.hasChildNodes() && index <= containerElm.childNodes.length - 1) {
              global$9(containerElm.childNodes[index]).before(ctrl.renderHtml());
            } else {
              global$9(containerElm).append(ctrl.renderHtml());
            }
            ctrl.postRender();
            ReflowQueue.add(ctrl);
          }
        });
        self._layout.applyClasses(self.items().filter(':visible'));
        self._lastRect = null;
        return self;
      },
      append: function (items) {
        return this.add(items).renderNew();
      },
      prepend: function (items) {
        var self = this;
        self.items().set(self.create(items).concat(self.items().toArray()));
        return self.renderNew();
      },
      insert: function (items, index, before) {
        var self = this;
        var curItems, beforeItems, afterItems;
        items = self.create(items);
        curItems = self.items();
        if (!before && index < curItems.length - 1) {
          index += 1;
        }
        if (index >= 0 && index < curItems.length) {
          beforeItems = curItems.slice(0, index).toArray();
          afterItems = curItems.slice(index).toArray();
          curItems.set(beforeItems.concat(items, afterItems));
        }
        return self.renderNew();
      },
      fromJSON: function (data) {
        var self = this;
        for (var name in data) {
          self.find('#' + name).value(data[name]);
        }
        return self;
      },
      toJSON: function () {
        var self = this, data = {};
        self.find('*').each(function (ctrl) {
          var name = ctrl.name(), value = ctrl.value();
          if (name && typeof value !== 'undefined') {
            data[name] = value;
          }
        });
        return data;
      },
      renderHtml: function () {
        var self = this, layout = self._layout, role = this.settings.role;
        self.preRender();
        layout.preRender(self);
        return '<div id="' + self._id + '" class="' + self.classes + '"' + (role ? ' role="' + this.settings.role + '"' : '') + '>' + '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' + (self.settings.html || '') + layout.renderHtml(self) + '</div>' + '</div>';
      },
      postRender: function () {
        var self = this;
        var box;
        self.items().exec('postRender');
        self._super();
        self._layout.postRender(self);
        self.state.set('rendered', true);
        if (self.settings.style) {
          self.$el.css(self.settings.style);
        }
        if (self.settings.border) {
          box = self.borderBox;
          self.$el.css({
            'border-top-width': box.top,
            'border-right-width': box.right,
            'border-bottom-width': box.bottom,
            'border-left-width': box.left
          });
        }
        if (!self.parent()) {
          self.keyboardNav = KeyboardNavigation({ root: self });
        }
        return self;
      },
      initLayoutRect: function () {
        var self = this, layoutRect = self._super();
        self._layout.recalc(self);
        return layoutRect;
      },
      recalc: function () {
        var self = this;
        var rect = self._layoutRect;
        var lastRect = self._lastRect;
        if (!lastRect || lastRect.w !== rect.w || lastRect.h !== rect.h) {
          self._layout.recalc(self);
          rect = self.layoutRect();
          self._lastRect = {
            x: rect.x,
            y: rect.y,
            w: rect.w,
            h: rect.h
          };
          return true;
        }
      },
      reflow: function () {
        var i;
        ReflowQueue.remove(this);
        if (this.visible()) {
          Control$1.repaintControls = [];
          Control$1.repaintControls.map = {};
          this.recalc();
          i = Control$1.repaintControls.length;
          while (i--) {
            Control$1.repaintControls[i].repaint();
          }
          if (this.settings.layout !== 'flow' && this.settings.layout !== 'stack') {
            this.repaint();
          }
          Control$1.repaintControls = [];
        }
        return this;
      }
    });

    function getDocumentSize(doc) {
      var documentElement, body, scrollWidth, clientWidth;
      var offsetWidth, scrollHeight, clientHeight, offsetHeight;
      var max = Math.max;
      documentElement = doc.documentElement;
      body = doc.body;
      scrollWidth = max(documentElement.scrollWidth, body.scrollWidth);
      clientWidth = max(documentElement.clientWidth, body.clientWidth);
      offsetWidth = max(documentElement.offsetWidth, body.offsetWidth);
      scrollHeight = max(documentElement.scrollHeight, body.scrollHeight);
      clientHeight = max(documentElement.clientHeight, body.clientHeight);
      offsetHeight = max(documentElement.offsetHeight, body.offsetHeight);
      return {
        width: scrollWidth < offsetWidth ? clientWidth : scrollWidth,
        height: scrollHeight < offsetHeight ? clientHeight : scrollHeight
      };
    }
    function updateWithTouchData(e) {
      var keys, i;
      if (e.changedTouches) {
        keys = 'screenX screenY pageX pageY clientX clientY'.split(' ');
        for (i = 0; i < keys.length; i++) {
          e[keys[i]] = e.changedTouches[0][keys[i]];
        }
      }
    }
    function DragHelper (id, settings) {
      var $eventOverlay;
      var doc = settings.document || domGlobals.document;
      var downButton;
      var start, stop, drag, startX, startY;
      settings = settings || {};
      var handleElement = doc.getElementById(settings.handle || id);
      start = function (e) {
        var docSize = getDocumentSize(doc);
        var handleElm, cursor;
        updateWithTouchData(e);
        e.preventDefault();
        downButton = e.button;
        handleElm = handleElement;
        startX = e.screenX;
        startY = e.screenY;
        if (domGlobals.window.getComputedStyle) {
          cursor = domGlobals.window.getComputedStyle(handleElm, null).getPropertyValue('cursor');
        } else {
          cursor = handleElm.runtimeStyle.cursor;
        }
        $eventOverlay = global$9('<div></div>').css({
          position: 'absolute',
          top: 0,
          left: 0,
          width: docSize.width,
          height: docSize.height,
          zIndex: 2147483647,
          opacity: 0.0001,
          cursor: cursor
        }).appendTo(doc.body);
        global$9(doc).on('mousemove touchmove', drag).on('mouseup touchend', stop);
        settings.start(e);
      };
      drag = function (e) {
        updateWithTouchData(e);
        if (e.button !== downButton) {
          return stop(e);
        }
        e.deltaX = e.screenX - startX;
        e.deltaY = e.screenY - startY;
        e.preventDefault();
        settings.drag(e);
      };
      stop = function (e) {
        updateWithTouchData(e);
        global$9(doc).off('mousemove touchmove', drag).off('mouseup touchend', stop);
        $eventOverlay.remove();
        if (settings.stop) {
          settings.stop(e);
        }
      };
      this.destroy = function () {
        global$9(handleElement).off();
      };
      global$9(handleElement).on('mousedown touchstart', start);
    }

    var Scrollable = {
      init: function () {
        var self = this;
        self.on('repaint', self.renderScroll);
      },
      renderScroll: function () {
        var self = this, margin = 2;
        function repaintScroll() {
          var hasScrollH, hasScrollV, bodyElm;
          function repaintAxis(axisName, posName, sizeName, contentSizeName, hasScroll, ax) {
            var containerElm, scrollBarElm, scrollThumbElm;
            var containerSize, scrollSize, ratio, rect;
            var posNameLower, sizeNameLower;
            scrollBarElm = self.getEl('scroll' + axisName);
            if (scrollBarElm) {
              posNameLower = posName.toLowerCase();
              sizeNameLower = sizeName.toLowerCase();
              global$9(self.getEl('absend')).css(posNameLower, self.layoutRect()[contentSizeName] - 1);
              if (!hasScroll) {
                global$9(scrollBarElm).css('display', 'none');
                return;
              }
              global$9(scrollBarElm).css('display', 'block');
              containerElm = self.getEl('body');
              scrollThumbElm = self.getEl('scroll' + axisName + 't');
              containerSize = containerElm['client' + sizeName] - margin * 2;
              containerSize -= hasScrollH && hasScrollV ? scrollBarElm['client' + ax] : 0;
              scrollSize = containerElm['scroll' + sizeName];
              ratio = containerSize / scrollSize;
              rect = {};
              rect[posNameLower] = containerElm['offset' + posName] + margin;
              rect[sizeNameLower] = containerSize;
              global$9(scrollBarElm).css(rect);
              rect = {};
              rect[posNameLower] = containerElm['scroll' + posName] * ratio;
              rect[sizeNameLower] = containerSize * ratio;
              global$9(scrollThumbElm).css(rect);
            }
          }
          bodyElm = self.getEl('body');
          hasScrollH = bodyElm.scrollWidth > bodyElm.clientWidth;
          hasScrollV = bodyElm.scrollHeight > bodyElm.clientHeight;
          repaintAxis('h', 'Left', 'Width', 'contentW', hasScrollH, 'Height');
          repaintAxis('v', 'Top', 'Height', 'contentH', hasScrollV, 'Width');
        }
        function addScroll() {
          function addScrollAxis(axisName, posName, sizeName, deltaPosName, ax) {
            var scrollStart;
            var axisId = self._id + '-scroll' + axisName, prefix = self.classPrefix;
            global$9(self.getEl()).append('<div id="' + axisId + '" class="' + prefix + 'scrollbar ' + prefix + 'scrollbar-' + axisName + '">' + '<div id="' + axisId + 't" class="' + prefix + 'scrollbar-thumb"></div>' + '</div>');
            self.draghelper = new DragHelper(axisId + 't', {
              start: function () {
                scrollStart = self.getEl('body')['scroll' + posName];
                global$9('#' + axisId).addClass(prefix + 'active');
              },
              drag: function (e) {
                var ratio, hasScrollH, hasScrollV, containerSize;
                var layoutRect = self.layoutRect();
                hasScrollH = layoutRect.contentW > layoutRect.innerW;
                hasScrollV = layoutRect.contentH > layoutRect.innerH;
                containerSize = self.getEl('body')['client' + sizeName] - margin * 2;
                containerSize -= hasScrollH && hasScrollV ? self.getEl('scroll' + axisName)['client' + ax] : 0;
                ratio = containerSize / self.getEl('body')['scroll' + sizeName];
                self.getEl('body')['scroll' + posName] = scrollStart + e['delta' + deltaPosName] / ratio;
              },
              stop: function () {
                global$9('#' + axisId).removeClass(prefix + 'active');
              }
            });
          }
          self.classes.add('scroll');
          addScrollAxis('v', 'Top', 'Height', 'Y', 'Width');
          addScrollAxis('h', 'Left', 'Width', 'X', 'Height');
        }
        if (self.settings.autoScroll) {
          if (!self._hasScroll) {
            self._hasScroll = true;
            addScroll();
            self.on('wheel', function (e) {
              var bodyEl = self.getEl('body');
              bodyEl.scrollLeft += (e.deltaX || 0) * 10;
              bodyEl.scrollTop += e.deltaY * 10;
              repaintScroll();
            });
            global$9(self.getEl('body')).on('scroll', repaintScroll);
          }
          repaintScroll();
        }
      }
    };

    var Panel = Container.extend({
      Defaults: {
        layout: 'fit',
        containerCls: 'panel'
      },
      Mixins: [Scrollable],
      renderHtml: function () {
        var self = this;
        var layout = self._layout;
        var innerHtml = self.settings.html;
        self.preRender();
        layout.preRender(self);
        if (typeof innerHtml === 'undefined') {
          innerHtml = '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' + layout.renderHtml(self) + '</div>';
        } else {
          if (typeof innerHtml === 'function') {
            innerHtml = innerHtml.call(self);
          }
          self._hasBody = false;
        }
        return '<div id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1" role="group">' + (self._preBodyHtml || '') + innerHtml + '</div>';
      }
    });

    var Resizable = {
      resizeToContent: function () {
        this._layoutRect.autoResize = true;
        this._lastRect = null;
        this.reflow();
      },
      resizeTo: function (w, h) {
        if (w <= 1 || h <= 1) {
          var rect = funcs.getWindowSize();
          w = w <= 1 ? w * rect.w : w;
          h = h <= 1 ? h * rect.h : h;
        }
        this._layoutRect.autoResize = false;
        return this.layoutRect({
          minW: w,
          minH: h,
          w: w,
          h: h
        }).reflow();
      },
      resizeBy: function (dw, dh) {
        var self = this, rect = self.layoutRect();
        return self.resizeTo(rect.w + dw, rect.h + dh);
      }
    };

    var documentClickHandler, documentScrollHandler, windowResizeHandler;
    var visiblePanels = [];
    var zOrder = [];
    var hasModal;
    function isChildOf(ctrl, parent) {
      while (ctrl) {
        if (ctrl === parent) {
          return true;
        }
        ctrl = ctrl.parent();
      }
    }
    function skipOrHidePanels(e) {
      var i = visiblePanels.length;
      while (i--) {
        var panel = visiblePanels[i], clickCtrl = panel.getParentCtrl(e.target);
        if (panel.settings.autohide) {
          if (clickCtrl) {
            if (isChildOf(clickCtrl, panel) || panel.parent() === clickCtrl) {
              continue;
            }
          }
          e = panel.fire('autohide', { target: e.target });
          if (!e.isDefaultPrevented()) {
            panel.hide();
          }
        }
      }
    }
    function bindDocumentClickHandler() {
      if (!documentClickHandler) {
        documentClickHandler = function (e) {
          if (e.button === 2) {
            return;
          }
          skipOrHidePanels(e);
        };
        global$9(domGlobals.document).on('click touchstart', documentClickHandler);
      }
    }
    function bindDocumentScrollHandler() {
      if (!documentScrollHandler) {
        documentScrollHandler = function () {
          var i;
          i = visiblePanels.length;
          while (i--) {
            repositionPanel(visiblePanels[i]);
          }
        };
        global$9(domGlobals.window).on('scroll', documentScrollHandler);
      }
    }
    function bindWindowResizeHandler() {
      if (!windowResizeHandler) {
        var docElm_1 = domGlobals.document.documentElement;
        var clientWidth_1 = docElm_1.clientWidth, clientHeight_1 = docElm_1.clientHeight;
        windowResizeHandler = function () {
          if (!domGlobals.document.all || clientWidth_1 !== docElm_1.clientWidth || clientHeight_1 !== docElm_1.clientHeight) {
            clientWidth_1 = docElm_1.clientWidth;
            clientHeight_1 = docElm_1.clientHeight;
            FloatPanel.hideAll();
          }
        };
        global$9(domGlobals.window).on('resize', windowResizeHandler);
      }
    }
    function repositionPanel(panel) {
      var scrollY = funcs.getViewPort().y;
      function toggleFixedChildPanels(fixed, deltaY) {
        var parent;
        for (var i = 0; i < visiblePanels.length; i++) {
          if (visiblePanels[i] !== panel) {
            parent = visiblePanels[i].parent();
            while (parent && (parent = parent.parent())) {
              if (parent === panel) {
                visiblePanels[i].fixed(fixed).moveBy(0, deltaY).repaint();
              }
            }
          }
        }
      }
      if (panel.settings.autofix) {
        if (!panel.state.get('fixed')) {
          panel._autoFixY = panel.layoutRect().y;
          if (panel._autoFixY < scrollY) {
            panel.fixed(true).layoutRect({ y: 0 }).repaint();
            toggleFixedChildPanels(true, scrollY - panel._autoFixY);
          }
        } else {
          if (panel._autoFixY > scrollY) {
            panel.fixed(false).layoutRect({ y: panel._autoFixY }).repaint();
            toggleFixedChildPanels(false, panel._autoFixY - scrollY);
          }
        }
      }
    }
    function addRemove(add, ctrl) {
      var i, zIndex = FloatPanel.zIndex || 65535, topModal;
      if (add) {
        zOrder.push(ctrl);
      } else {
        i = zOrder.length;
        while (i--) {
          if (zOrder[i] === ctrl) {
            zOrder.splice(i, 1);
          }
        }
      }
      if (zOrder.length) {
        for (i = 0; i < zOrder.length; i++) {
          if (zOrder[i].modal) {
            zIndex++;
            topModal = zOrder[i];
          }
          zOrder[i].getEl().style.zIndex = zIndex;
          zOrder[i].zIndex = zIndex;
          zIndex++;
        }
      }
      var modalBlockEl = global$9('#' + ctrl.classPrefix + 'modal-block', ctrl.getContainerElm())[0];
      if (topModal) {
        global$9(modalBlockEl).css('z-index', topModal.zIndex - 1);
      } else if (modalBlockEl) {
        modalBlockEl.parentNode.removeChild(modalBlockEl);
        hasModal = false;
      }
      FloatPanel.currentZIndex = zIndex;
    }
    var FloatPanel = Panel.extend({
      Mixins: [
        Movable,
        Resizable
      ],
      init: function (settings) {
        var self = this;
        self._super(settings);
        self._eventsRoot = self;
        self.classes.add('floatpanel');
        if (settings.autohide) {
          bindDocumentClickHandler();
          bindWindowResizeHandler();
          visiblePanels.push(self);
        }
        if (settings.autofix) {
          bindDocumentScrollHandler();
          self.on('move', function () {
            repositionPanel(this);
          });
        }
        self.on('postrender show', function (e) {
          if (e.control === self) {
            var $modalBlockEl_1;
            var prefix_1 = self.classPrefix;
            if (self.modal && !hasModal) {
              $modalBlockEl_1 = global$9('#' + prefix_1 + 'modal-block', self.getContainerElm());
              if (!$modalBlockEl_1[0]) {
                $modalBlockEl_1 = global$9('<div id="' + prefix_1 + 'modal-block" class="' + prefix_1 + 'reset ' + prefix_1 + 'fade"></div>').appendTo(self.getContainerElm());
              }
              global$7.setTimeout(function () {
                $modalBlockEl_1.addClass(prefix_1 + 'in');
                global$9(self.getEl()).addClass(prefix_1 + 'in');
              });
              hasModal = true;
            }
            addRemove(true, self);
          }
        });
        self.on('show', function () {
          self.parents().each(function (ctrl) {
            if (ctrl.state.get('fixed')) {
              self.fixed(true);
              return false;
            }
          });
        });
        if (settings.popover) {
          self._preBodyHtml = '<div class="' + self.classPrefix + 'arrow"></div>';
          self.classes.add('popover').add('bottom').add(self.isRtl() ? 'end' : 'start');
        }
        self.aria('label', settings.ariaLabel);
        self.aria('labelledby', self._id);
        self.aria('describedby', self.describedBy || self._id + '-none');
      },
      fixed: function (state) {
        var self = this;
        if (self.state.get('fixed') !== state) {
          if (self.state.get('rendered')) {
            var viewport = funcs.getViewPort();
            if (state) {
              self.layoutRect().y -= viewport.y;
            } else {
              self.layoutRect().y += viewport.y;
            }
          }
          self.classes.toggle('fixed', state);
          self.state.set('fixed', state);
        }
        return self;
      },
      show: function () {
        var self = this;
        var i;
        var state = self._super();
        i = visiblePanels.length;
        while (i--) {
          if (visiblePanels[i] === self) {
            break;
          }
        }
        if (i === -1) {
          visiblePanels.push(self);
        }
        return state;
      },
      hide: function () {
        removeVisiblePanel(this);
        addRemove(false, this);
        return this._super();
      },
      hideAll: function () {
        FloatPanel.hideAll();
      },
      close: function () {
        var self = this;
        if (!self.fire('close').isDefaultPrevented()) {
          self.remove();
          addRemove(false, self);
        }
        return self;
      },
      remove: function () {
        removeVisiblePanel(this);
        this._super();
      },
      postRender: function () {
        var self = this;
        if (self.settings.bodyRole) {
          this.getEl('body').setAttribute('role', self.settings.bodyRole);
        }
        return self._super();
      }
    });
    FloatPanel.hideAll = function () {
      var i = visiblePanels.length;
      while (i--) {
        var panel = visiblePanels[i];
        if (panel && panel.settings.autohide) {
          panel.hide();
          visiblePanels.splice(i, 1);
        }
      }
    };
    function removeVisiblePanel(panel) {
      var i;
      i = visiblePanels.length;
      while (i--) {
        if (visiblePanels[i] === panel) {
          visiblePanels.splice(i, 1);
        }
      }
      i = zOrder.length;
      while (i--) {
        if (zOrder[i] === panel) {
          zOrder.splice(i, 1);
        }
      }
    }

    var isFixed$1 = function (inlineToolbarContainer, editor) {
      return !!(inlineToolbarContainer && !editor.settings.ui_container);
    };
    var render$1 = function (editor, theme, args) {
      var panel, inlineToolbarContainer;
      var DOM = global$3.DOM;
      var fixedToolbarContainer = getFixedToolbarContainer(editor);
      if (fixedToolbarContainer) {
        inlineToolbarContainer = DOM.select(fixedToolbarContainer)[0];
      }
      var reposition = function () {
        if (panel && panel.moveRel && panel.visible() && !panel._fixed) {
          var scrollContainer = editor.selection.getScrollContainer(), body = editor.getBody();
          var deltaX = 0, deltaY = 0;
          if (scrollContainer) {
            var bodyPos = DOM.getPos(body), scrollContainerPos = DOM.getPos(scrollContainer);
            deltaX = Math.max(0, scrollContainerPos.x - bodyPos.x);
            deltaY = Math.max(0, scrollContainerPos.y - bodyPos.y);
          }
          panel.fixed(false).moveRel(body, editor.rtl ? [
            'tr-br',
            'br-tr'
          ] : [
            'tl-bl',
            'bl-tl',
            'tr-br'
          ]).moveBy(deltaX, deltaY);
        }
      };
      var show = function () {
        if (panel) {
          panel.show();
          reposition();
          DOM.addClass(editor.getBody(), 'mce-edit-focus');
        }
      };
      var hide = function () {
        if (panel) {
          panel.hide();
          FloatPanel.hideAll();
          DOM.removeClass(editor.getBody(), 'mce-edit-focus');
        }
      };
      var render = function () {
        if (panel) {
          if (!panel.visible()) {
            show();
          }
          return;
        }
        panel = theme.panel = global$4.create({
          type: inlineToolbarContainer ? 'panel' : 'floatpanel',
          role: 'application',
          classes: 'tinymce tinymce-inline',
          layout: 'flex',
          direction: 'column',
          align: 'stretch',
          autohide: false,
          autofix: true,
          fixed: isFixed$1(inlineToolbarContainer, editor),
          border: 1,
          items: [
            hasMenubar(editor) === false ? null : {
              type: 'menubar',
              border: '0 0 1 0',
              items: Menubar.createMenuButtons(editor)
            },
            Toolbar.createToolbars(editor, getToolbarSize(editor))
          ]
        });
        UiContainer.setUiContainer(editor, panel);
        Events.fireBeforeRenderUI(editor);
        if (inlineToolbarContainer) {
          panel.renderTo(inlineToolbarContainer).reflow();
        } else {
          panel.renderTo().reflow();
        }
        A11y.addKeys(editor, panel);
        show();
        ContextToolbars.addContextualToolbars(editor);
        editor.on('nodeChange', reposition);
        editor.on('ResizeWindow', reposition);
        editor.on('activate', show);
        editor.on('deactivate', hide);
        editor.nodeChanged();
      };
      editor.settings.content_editable = true;
      editor.on('focus', function () {
        if (isSkinDisabled(editor) === false && args.skinUiCss) {
          DOM.styleSheetLoader.load(args.skinUiCss, render, render);
        } else {
          render();
        }
      });
      editor.on('blur hide', hide);
      editor.on('remove', function () {
        if (panel) {
          panel.remove();
          panel = null;
        }
      });
      if (isSkinDisabled(editor) === false && args.skinUiCss) {
        DOM.styleSheetLoader.load(args.skinUiCss, SkinLoaded.fireSkinLoaded(editor));
      } else {
        SkinLoaded.fireSkinLoaded(editor)();
      }
      return {};
    };
    var Inline = { render: render$1 };

    function Throbber (elm, inline) {
      var self = this;
      var state;
      var classPrefix = Control$1.classPrefix;
      var timer;
      self.show = function (time, callback) {
        function render() {
          if (state) {
            global$9(elm).append('<div class="' + classPrefix + 'throbber' + (inline ? ' ' + classPrefix + 'throbber-inline' : '') + '"></div>');
            if (callback) {
              callback();
            }
          }
        }
        self.hide();
        state = true;
        if (time) {
          timer = global$7.setTimeout(render, time);
        } else {
          render();
        }
        return self;
      };
      self.hide = function () {
        var child = elm.lastChild;
        global$7.clearTimeout(timer);
        if (child && child.className.indexOf('throbber') !== -1) {
          child.parentNode.removeChild(child);
        }
        state = false;
        return self;
      };
    }

    var setup = function (editor, theme) {
      var throbber;
      editor.on('ProgressState', function (e) {
        throbber = throbber || new Throbber(theme.panel.getEl('body'));
        if (e.state) {
          throbber.show(e.time);
        } else {
          throbber.hide();
        }
      });
    };
    var ProgressState = { setup: setup };

    var renderUI = function (editor, theme, args) {
      var skinUrl = getSkinUrl(editor);
      if (skinUrl) {
        args.skinUiCss = skinUrl + '/skin.min.css';
        editor.contentCSS.push(skinUrl + '/content' + (editor.inline ? '.inline' : '') + '.min.css');
      }
      ProgressState.setup(editor, theme);
      return isInline(editor) ? Inline.render(editor, theme, args) : Iframe.render(editor, theme, args);
    };
    var Render = { renderUI: renderUI };

    var Tooltip = Control$1.extend({
      Mixins: [Movable],
      Defaults: { classes: 'widget tooltip tooltip-n' },
      renderHtml: function () {
        var self = this, prefix = self.classPrefix;
        return '<div id="' + self._id + '" class="' + self.classes + '" role="presentation">' + '<div class="' + prefix + 'tooltip-arrow"></div>' + '<div class="' + prefix + 'tooltip-inner">' + self.encode(self.state.get('text')) + '</div>' + '</div>';
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:text', function (e) {
          self.getEl().lastChild.innerHTML = self.encode(e.value);
        });
        return self._super();
      },
      repaint: function () {
        var self = this;
        var style, rect;
        style = self.getEl().style;
        rect = self._layoutRect;
        style.left = rect.x + 'px';
        style.top = rect.y + 'px';
        style.zIndex = 65535 + 65535;
      }
    });

    var Widget = Control$1.extend({
      init: function (settings) {
        var self = this;
        self._super(settings);
        settings = self.settings;
        self.canFocus = true;
        if (settings.tooltip && Widget.tooltips !== false) {
          self.on('mouseenter', function (e) {
            var tooltip = self.tooltip().moveTo(-65535);
            if (e.control === self) {
              var rel = tooltip.text(settings.tooltip).show().testMoveRel(self.getEl(), [
                'bc-tc',
                'bc-tl',
                'bc-tr'
              ]);
              tooltip.classes.toggle('tooltip-n', rel === 'bc-tc');
              tooltip.classes.toggle('tooltip-nw', rel === 'bc-tl');
              tooltip.classes.toggle('tooltip-ne', rel === 'bc-tr');
              tooltip.moveRel(self.getEl(), rel);
            } else {
              tooltip.hide();
            }
          });
          self.on('mouseleave mousedown click', function () {
            self.tooltip().remove();
            self._tooltip = null;
          });
        }
        self.aria('label', settings.ariaLabel || settings.tooltip);
      },
      tooltip: function () {
        if (!this._tooltip) {
          this._tooltip = new Tooltip({ type: 'tooltip' });
          UiContainer.inheritUiContainer(this, this._tooltip);
          this._tooltip.renderTo();
        }
        return this._tooltip;
      },
      postRender: function () {
        var self = this, settings = self.settings;
        self._super();
        if (!self.parent() && (settings.width || settings.height)) {
          self.initLayoutRect();
          self.repaint();
        }
        if (settings.autofocus) {
          self.focus();
        }
      },
      bindStates: function () {
        var self = this;
        function disable(state) {
          self.aria('disabled', state);
          self.classes.toggle('disabled', state);
        }
        function active(state) {
          self.aria('pressed', state);
          self.classes.toggle('active', state);
        }
        self.state.on('change:disabled', function (e) {
          disable(e.value);
        });
        self.state.on('change:active', function (e) {
          active(e.value);
        });
        if (self.state.get('disabled')) {
          disable(true);
        }
        if (self.state.get('active')) {
          active(true);
        }
        return self._super();
      },
      remove: function () {
        this._super();
        if (this._tooltip) {
          this._tooltip.remove();
          this._tooltip = null;
        }
      }
    });

    var Progress = Widget.extend({
      Defaults: { value: 0 },
      init: function (settings) {
        var self = this;
        self._super(settings);
        self.classes.add('progress');
        if (!self.settings.filter) {
          self.settings.filter = function (value) {
            return Math.round(value);
          };
        }
      },
      renderHtml: function () {
        var self = this, id = self._id, prefix = this.classPrefix;
        return '<div id="' + id + '" class="' + self.classes + '">' + '<div class="' + prefix + 'bar-container">' + '<div class="' + prefix + 'bar"></div>' + '</div>' + '<div class="' + prefix + 'text">0%</div>' + '</div>';
      },
      postRender: function () {
        var self = this;
        self._super();
        self.value(self.settings.value);
        return self;
      },
      bindStates: function () {
        var self = this;
        function setValue(value) {
          value = self.settings.filter(value);
          self.getEl().lastChild.innerHTML = value + '%';
          self.getEl().firstChild.firstChild.style.width = value + '%';
        }
        self.state.on('change:value', function (e) {
          setValue(e.value);
        });
        setValue(self.state.get('value'));
        return self._super();
      }
    });

    var updateLiveRegion = function (ctx, text) {
      ctx.getEl().lastChild.textContent = text + (ctx.progressBar ? ' ' + ctx.progressBar.value() + '%' : '');
    };
    var Notification = Control$1.extend({
      Mixins: [Movable],
      Defaults: { classes: 'widget notification' },
      init: function (settings) {
        var self = this;
        self._super(settings);
        self.maxWidth = settings.maxWidth;
        if (settings.text) {
          self.text(settings.text);
        }
        if (settings.icon) {
          self.icon = settings.icon;
        }
        if (settings.color) {
          self.color = settings.color;
        }
        if (settings.type) {
          self.classes.add('notification-' + settings.type);
        }
        if (settings.timeout && (settings.timeout < 0 || settings.timeout > 0) && !settings.closeButton) {
          self.closeButton = false;
        } else {
          self.classes.add('has-close');
          self.closeButton = true;
        }
        if (settings.progressBar) {
          self.progressBar = new Progress();
        }
        self.on('click', function (e) {
          if (e.target.className.indexOf(self.classPrefix + 'close') !== -1) {
            self.close();
          }
        });
      },
      renderHtml: function () {
        var self = this;
        var prefix = self.classPrefix;
        var icon = '', closeButton = '', progressBar = '', notificationStyle = '';
        if (self.icon) {
          icon = '<i class="' + prefix + 'ico' + ' ' + prefix + 'i-' + self.icon + '"></i>';
        }
        notificationStyle = ' style="max-width: ' + self.maxWidth + 'px;' + (self.color ? 'background-color: ' + self.color + ';"' : '"');
        if (self.closeButton) {
          closeButton = '<button type="button" class="' + prefix + 'close" aria-hidden="true">\xD7</button>';
        }
        if (self.progressBar) {
          progressBar = self.progressBar.renderHtml();
        }
        return '<div id="' + self._id + '" class="' + self.classes + '"' + notificationStyle + ' role="presentation">' + icon + '<div class="' + prefix + 'notification-inner">' + self.state.get('text') + '</div>' + progressBar + closeButton + '<div style="clip: rect(1px, 1px, 1px, 1px);height: 1px;overflow: hidden;position: absolute;width: 1px;"' + ' aria-live="assertive" aria-relevant="additions" aria-atomic="true"></div>' + '</div>';
      },
      postRender: function () {
        var self = this;
        global$7.setTimeout(function () {
          self.$el.addClass(self.classPrefix + 'in');
          updateLiveRegion(self, self.state.get('text'));
        }, 100);
        return self._super();
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:text', function (e) {
          self.getEl().firstChild.innerHTML = e.value;
          updateLiveRegion(self, e.value);
        });
        if (self.progressBar) {
          self.progressBar.bindStates();
          self.progressBar.state.on('change:value', function (e) {
            updateLiveRegion(self, self.state.get('text'));
          });
        }
        return self._super();
      },
      close: function () {
        var self = this;
        if (!self.fire('close').isDefaultPrevented()) {
          self.remove();
        }
        return self;
      },
      repaint: function () {
        var self = this;
        var style, rect;
        style = self.getEl().style;
        rect = self._layoutRect;
        style.left = rect.x + 'px';
        style.top = rect.y + 'px';
        style.zIndex = 65535 - 1;
      }
    });

    function NotificationManagerImpl (editor) {
      var getEditorContainer = function (editor) {
        return editor.inline ? editor.getElement() : editor.getContentAreaContainer();
      };
      var getContainerWidth = function () {
        var container = getEditorContainer(editor);
        return funcs.getSize(container).width;
      };
      var prePositionNotifications = function (notifications) {
        each(notifications, function (notification) {
          notification.moveTo(0, 0);
        });
      };
      var positionNotifications = function (notifications) {
        if (notifications.length > 0) {
          var firstItem = notifications.slice(0, 1)[0];
          var container = getEditorContainer(editor);
          firstItem.moveRel(container, 'tc-tc');
          each(notifications, function (notification, index) {
            if (index > 0) {
              notification.moveRel(notifications[index - 1].getEl(), 'bc-tc');
            }
          });
        }
      };
      var reposition = function (notifications) {
        prePositionNotifications(notifications);
        positionNotifications(notifications);
      };
      var open = function (args, closeCallback) {
        var extendedArgs = global$2.extend(args, { maxWidth: getContainerWidth() });
        var notif = new Notification(extendedArgs);
        notif.args = extendedArgs;
        if (extendedArgs.timeout > 0) {
          notif.timer = setTimeout(function () {
            notif.close();
            closeCallback();
          }, extendedArgs.timeout);
        }
        notif.on('close', function () {
          closeCallback();
        });
        notif.renderTo();
        return notif;
      };
      var close = function (notification) {
        notification.close();
      };
      var getArgs = function (notification) {
        return notification.args;
      };
      return {
        open: open,
        close: close,
        reposition: reposition,
        getArgs: getArgs
      };
    }

    var windows = [];
    var oldMetaValue = '';
    function toggleFullScreenState(state) {
      var noScaleMetaValue = 'width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0';
      var viewport = global$9('meta[name=viewport]')[0], contentValue;
      if (global$8.overrideViewPort === false) {
        return;
      }
      if (!viewport) {
        viewport = domGlobals.document.createElement('meta');
        viewport.setAttribute('name', 'viewport');
        domGlobals.document.getElementsByTagName('head')[0].appendChild(viewport);
      }
      contentValue = viewport.getAttribute('content');
      if (contentValue && typeof oldMetaValue !== 'undefined') {
        oldMetaValue = contentValue;
      }
      viewport.setAttribute('content', state ? noScaleMetaValue : oldMetaValue);
    }
    function toggleBodyFullScreenClasses(classPrefix, state) {
      if (checkFullscreenWindows() && state === false) {
        global$9([
          domGlobals.document.documentElement,
          domGlobals.document.body
        ]).removeClass(classPrefix + 'fullscreen');
      }
    }
    function checkFullscreenWindows() {
      for (var i = 0; i < windows.length; i++) {
        if (windows[i]._fullscreen) {
          return true;
        }
      }
      return false;
    }
    function handleWindowResize() {
      if (!global$8.desktop) {
        var lastSize_1 = {
          w: domGlobals.window.innerWidth,
          h: domGlobals.window.innerHeight
        };
        global$7.setInterval(function () {
          var w = domGlobals.window.innerWidth, h = domGlobals.window.innerHeight;
          if (lastSize_1.w !== w || lastSize_1.h !== h) {
            lastSize_1 = {
              w: w,
              h: h
            };
            global$9(domGlobals.window).trigger('resize');
          }
        }, 100);
      }
      function reposition() {
        var i;
        var rect = funcs.getWindowSize();
        var layoutRect;
        for (i = 0; i < windows.length; i++) {
          layoutRect = windows[i].layoutRect();
          windows[i].moveTo(windows[i].settings.x || Math.max(0, rect.w / 2 - layoutRect.w / 2), windows[i].settings.y || Math.max(0, rect.h / 2 - layoutRect.h / 2));
        }
      }
      global$9(domGlobals.window).on('resize', reposition);
    }
    var Window = FloatPanel.extend({
      modal: true,
      Defaults: {
        border: 1,
        layout: 'flex',
        containerCls: 'panel',
        role: 'dialog',
        callbacks: {
          submit: function () {
            this.fire('submit', { data: this.toJSON() });
          },
          close: function () {
            this.close();
          }
        }
      },
      init: function (settings) {
        var self = this;
        self._super(settings);
        if (self.isRtl()) {
          self.classes.add('rtl');
        }
        self.classes.add('window');
        self.bodyClasses.add('window-body');
        self.state.set('fixed', true);
        if (settings.buttons) {
          self.statusbar = new Panel({
            layout: 'flex',
            border: '1 0 0 0',
            spacing: 3,
            padding: 10,
            align: 'center',
            pack: self.isRtl() ? 'start' : 'end',
            defaults: { type: 'button' },
            items: settings.buttons
          });
          self.statusbar.classes.add('foot');
          self.statusbar.parent(self);
        }
        self.on('click', function (e) {
          var closeClass = self.classPrefix + 'close';
          if (funcs.hasClass(e.target, closeClass) || funcs.hasClass(e.target.parentNode, closeClass)) {
            self.close();
          }
        });
        self.on('cancel', function () {
          self.close();
        });
        self.on('move', function (e) {
          if (e.control === self) {
            FloatPanel.hideAll();
          }
        });
        self.aria('describedby', self.describedBy || self._id + '-none');
        self.aria('label', settings.title);
        self._fullscreen = false;
      },
      recalc: function () {
        var self = this;
        var statusbar = self.statusbar;
        var layoutRect, width, x, needsRecalc;
        if (self._fullscreen) {
          self.layoutRect(funcs.getWindowSize());
          self.layoutRect().contentH = self.layoutRect().innerH;
        }
        self._super();
        layoutRect = self.layoutRect();
        if (self.settings.title && !self._fullscreen) {
          width = layoutRect.headerW;
          if (width > layoutRect.w) {
            x = layoutRect.x - Math.max(0, width / 2);
            self.layoutRect({
              w: width,
              x: x
            });
            needsRecalc = true;
          }
        }
        if (statusbar) {
          statusbar.layoutRect({ w: self.layoutRect().innerW }).recalc();
          width = statusbar.layoutRect().minW + layoutRect.deltaW;
          if (width > layoutRect.w) {
            x = layoutRect.x - Math.max(0, width - layoutRect.w);
            self.layoutRect({
              w: width,
              x: x
            });
            needsRecalc = true;
          }
        }
        if (needsRecalc) {
          self.recalc();
        }
      },
      initLayoutRect: function () {
        var self = this;
        var layoutRect = self._super();
        var deltaH = 0, headEl;
        if (self.settings.title && !self._fullscreen) {
          headEl = self.getEl('head');
          var size = funcs.getSize(headEl);
          layoutRect.headerW = size.width;
          layoutRect.headerH = size.height;
          deltaH += layoutRect.headerH;
        }
        if (self.statusbar) {
          deltaH += self.statusbar.layoutRect().h;
        }
        layoutRect.deltaH += deltaH;
        layoutRect.minH += deltaH;
        layoutRect.h += deltaH;
        var rect = funcs.getWindowSize();
        layoutRect.x = self.settings.x || Math.max(0, rect.w / 2 - layoutRect.w / 2);
        layoutRect.y = self.settings.y || Math.max(0, rect.h / 2 - layoutRect.h / 2);
        return layoutRect;
      },
      renderHtml: function () {
        var self = this, layout = self._layout, id = self._id, prefix = self.classPrefix;
        var settings = self.settings;
        var headerHtml = '', footerHtml = '', html = settings.html;
        self.preRender();
        layout.preRender(self);
        if (settings.title) {
          headerHtml = '<div id="' + id + '-head" class="' + prefix + 'window-head">' + '<div id="' + id + '-title" class="' + prefix + 'title">' + self.encode(settings.title) + '</div>' + '<div id="' + id + '-dragh" class="' + prefix + 'dragh"></div>' + '<button type="button" class="' + prefix + 'close" aria-hidden="true">' + '<i class="mce-ico mce-i-remove"></i>' + '</button>' + '</div>';
        }
        if (settings.url) {
          html = '<iframe src="' + settings.url + '" tabindex="-1"></iframe>';
        }
        if (typeof html === 'undefined') {
          html = layout.renderHtml(self);
        }
        if (self.statusbar) {
          footerHtml = self.statusbar.renderHtml();
        }
        return '<div id="' + id + '" class="' + self.classes + '" hidefocus="1">' + '<div class="' + self.classPrefix + 'reset" role="application">' + headerHtml + '<div id="' + id + '-body" class="' + self.bodyClasses + '">' + html + '</div>' + footerHtml + '</div>' + '</div>';
      },
      fullscreen: function (state) {
        var self = this;
        var documentElement = domGlobals.document.documentElement;
        var slowRendering;
        var prefix = self.classPrefix;
        var layoutRect;
        if (state !== self._fullscreen) {
          global$9(domGlobals.window).on('resize', function () {
            var time;
            if (self._fullscreen) {
              if (!slowRendering) {
                time = new Date().getTime();
                var rect = funcs.getWindowSize();
                self.moveTo(0, 0).resizeTo(rect.w, rect.h);
                if (new Date().getTime() - time > 50) {
                  slowRendering = true;
                }
              } else {
                if (!self._timer) {
                  self._timer = global$7.setTimeout(function () {
                    var rect = funcs.getWindowSize();
                    self.moveTo(0, 0).resizeTo(rect.w, rect.h);
                    self._timer = 0;
                  }, 50);
                }
              }
            }
          });
          layoutRect = self.layoutRect();
          self._fullscreen = state;
          if (!state) {
            self.borderBox = BoxUtils.parseBox(self.settings.border);
            self.getEl('head').style.display = '';
            layoutRect.deltaH += layoutRect.headerH;
            global$9([
              documentElement,
              domGlobals.document.body
            ]).removeClass(prefix + 'fullscreen');
            self.classes.remove('fullscreen');
            self.moveTo(self._initial.x, self._initial.y).resizeTo(self._initial.w, self._initial.h);
          } else {
            self._initial = {
              x: layoutRect.x,
              y: layoutRect.y,
              w: layoutRect.w,
              h: layoutRect.h
            };
            self.borderBox = BoxUtils.parseBox('0');
            self.getEl('head').style.display = 'none';
            layoutRect.deltaH -= layoutRect.headerH + 2;
            global$9([
              documentElement,
              domGlobals.document.body
            ]).addClass(prefix + 'fullscreen');
            self.classes.add('fullscreen');
            var rect = funcs.getWindowSize();
            self.moveTo(0, 0).resizeTo(rect.w, rect.h);
          }
        }
        return self.reflow();
      },
      postRender: function () {
        var self = this;
        var startPos;
        setTimeout(function () {
          self.classes.add('in');
          self.fire('open');
        }, 0);
        self._super();
        if (self.statusbar) {
          self.statusbar.postRender();
        }
        self.focus();
        this.dragHelper = new DragHelper(self._id + '-dragh', {
          start: function () {
            startPos = {
              x: self.layoutRect().x,
              y: self.layoutRect().y
            };
          },
          drag: function (e) {
            self.moveTo(startPos.x + e.deltaX, startPos.y + e.deltaY);
          }
        });
        self.on('submit', function (e) {
          if (!e.isDefaultPrevented()) {
            self.close();
          }
        });
        windows.push(self);
        toggleFullScreenState(true);
      },
      submit: function () {
        return this.fire('submit', { data: this.toJSON() });
      },
      remove: function () {
        var self = this;
        var i;
        self.dragHelper.destroy();
        self._super();
        if (self.statusbar) {
          this.statusbar.remove();
        }
        toggleBodyFullScreenClasses(self.classPrefix, false);
        i = windows.length;
        while (i--) {
          if (windows[i] === self) {
            windows.splice(i, 1);
          }
        }
        toggleFullScreenState(windows.length > 0);
      },
      getContentWindow: function () {
        var ifr = this.getEl().getElementsByTagName('iframe')[0];
        return ifr ? ifr.contentWindow : null;
      }
    });
    handleWindowResize();

    var MessageBox = Window.extend({
      init: function (settings) {
        settings = {
          border: 1,
          padding: 20,
          layout: 'flex',
          pack: 'center',
          align: 'center',
          containerCls: 'panel',
          autoScroll: true,
          buttons: {
            type: 'button',
            text: 'Ok',
            action: 'ok'
          },
          items: {
            type: 'label',
            multiline: true,
            maxWidth: 500,
            maxHeight: 200
          }
        };
        this._super(settings);
      },
      Statics: {
        OK: 1,
        OK_CANCEL: 2,
        YES_NO: 3,
        YES_NO_CANCEL: 4,
        msgBox: function (settings) {
          var buttons;
          var callback = settings.callback || function () {
          };
          function createButton(text, status, primary) {
            return {
              type: 'button',
              text: text,
              subtype: primary ? 'primary' : '',
              onClick: function (e) {
                e.control.parents()[1].close();
                callback(status);
              }
            };
          }
          switch (settings.buttons) {
          case MessageBox.OK_CANCEL:
            buttons = [
              createButton('Ok', true, true),
              createButton('Cancel', false)
            ];
            break;
          case MessageBox.YES_NO:
          case MessageBox.YES_NO_CANCEL:
            buttons = [
              createButton('Yes', 1, true),
              createButton('No', 0)
            ];
            if (settings.buttons === MessageBox.YES_NO_CANCEL) {
              buttons.push(createButton('Cancel', -1));
            }
            break;
          default:
            buttons = [createButton('Ok', true, true)];
            break;
          }
          return new Window({
            padding: 20,
            x: settings.x,
            y: settings.y,
            minWidth: 300,
            minHeight: 100,
            layout: 'flex',
            pack: 'center',
            align: 'center',
            buttons: buttons,
            title: settings.title,
            role: 'alertdialog',
            items: {
              type: 'label',
              multiline: true,
              maxWidth: 500,
              maxHeight: 200,
              text: settings.text
            },
            onPostRender: function () {
              this.aria('describedby', this.items()[0]._id);
            },
            onClose: settings.onClose,
            onCancel: function () {
              callback(false);
            }
          }).renderTo(domGlobals.document.body).reflow();
        },
        alert: function (settings, callback) {
          if (typeof settings === 'string') {
            settings = { text: settings };
          }
          settings.callback = callback;
          return MessageBox.msgBox(settings);
        },
        confirm: function (settings, callback) {
          if (typeof settings === 'string') {
            settings = { text: settings };
          }
          settings.callback = callback;
          settings.buttons = MessageBox.OK_CANCEL;
          return MessageBox.msgBox(settings);
        }
      }
    });

    function WindowManagerImpl (editor) {
      var open = function (args, params, closeCallback) {
        var win;
        args.title = args.title || ' ';
        args.url = args.url || args.file;
        if (args.url) {
          args.width = parseInt(args.width || 320, 10);
          args.height = parseInt(args.height || 240, 10);
        }
        if (args.body) {
          args.items = {
            defaults: args.defaults,
            type: args.bodyType || 'form',
            items: args.body,
            data: args.data,
            callbacks: args.commands
          };
        }
        if (!args.url && !args.buttons) {
          args.buttons = [
            {
              text: 'Ok',
              subtype: 'primary',
              onclick: function () {
                win.find('form')[0].submit();
              }
            },
            {
              text: 'Cancel',
              onclick: function () {
                win.close();
              }
            }
          ];
        }
        win = new Window(args);
        win.on('close', function () {
          closeCallback(win);
        });
        if (args.data) {
          win.on('postRender', function () {
            this.find('*').each(function (ctrl) {
              var name = ctrl.name();
              if (name in args.data) {
                ctrl.value(args.data[name]);
              }
            });
          });
        }
        win.features = args || {};
        win.params = params || {};
        win = win.renderTo(domGlobals.document.body).reflow();
        return win;
      };
      var alert = function (message, choiceCallback, closeCallback) {
        var win;
        win = MessageBox.alert(message, function () {
          choiceCallback();
        });
        win.on('close', function () {
          closeCallback(win);
        });
        return win;
      };
      var confirm = function (message, choiceCallback, closeCallback) {
        var win;
        win = MessageBox.confirm(message, function (state) {
          choiceCallback(state);
        });
        win.on('close', function () {
          closeCallback(win);
        });
        return win;
      };
      var close = function (window) {
        window.close();
      };
      var getParams = function (window) {
        return window.params;
      };
      var setParams = function (window, params) {
        window.params = params;
      };
      return {
        open: open,
        alert: alert,
        confirm: confirm,
        close: close,
        getParams: getParams,
        setParams: setParams
      };
    }

    var get = function (editor) {
      var renderUI = function (args) {
        return Render.renderUI(editor, this, args);
      };
      var resizeTo = function (w, h) {
        return Resize.resizeTo(editor, w, h);
      };
      var resizeBy = function (dw, dh) {
        return Resize.resizeBy(editor, dw, dh);
      };
      var getNotificationManagerImpl = function () {
        return NotificationManagerImpl(editor);
      };
      var getWindowManagerImpl = function () {
        return WindowManagerImpl();
      };
      return {
        renderUI: renderUI,
        resizeTo: resizeTo,
        resizeBy: resizeBy,
        getNotificationManagerImpl: getNotificationManagerImpl,
        getWindowManagerImpl: getWindowManagerImpl
      };
    };
    var ThemeApi = { get: get };

    var Layout = global$a.extend({
      Defaults: {
        firstControlClass: 'first',
        lastControlClass: 'last'
      },
      init: function (settings) {
        this.settings = global$2.extend({}, this.Defaults, settings);
      },
      preRender: function (container) {
        container.bodyClasses.add(this.settings.containerClass);
      },
      applyClasses: function (items) {
        var self = this;
        var settings = self.settings;
        var firstClass, lastClass, firstItem, lastItem;
        firstClass = settings.firstControlClass;
        lastClass = settings.lastControlClass;
        items.each(function (item) {
          item.classes.remove(firstClass).remove(lastClass).add(settings.controlClass);
          if (item.visible()) {
            if (!firstItem) {
              firstItem = item;
            }
            lastItem = item;
          }
        });
        if (firstItem) {
          firstItem.classes.add(firstClass);
        }
        if (lastItem) {
          lastItem.classes.add(lastClass);
        }
      },
      renderHtml: function (container) {
        var self = this;
        var html = '';
        self.applyClasses(container.items());
        container.items().each(function (item) {
          html += item.renderHtml();
        });
        return html;
      },
      recalc: function () {
      },
      postRender: function () {
      },
      isNative: function () {
        return false;
      }
    });

    var AbsoluteLayout = Layout.extend({
      Defaults: {
        containerClass: 'abs-layout',
        controlClass: 'abs-layout-item'
      },
      recalc: function (container) {
        container.items().filter(':visible').each(function (ctrl) {
          var settings = ctrl.settings;
          ctrl.layoutRect({
            x: settings.x,
            y: settings.y,
            w: settings.w,
            h: settings.h
          });
          if (ctrl.recalc) {
            ctrl.recalc();
          }
        });
      },
      renderHtml: function (container) {
        return '<div id="' + container._id + '-absend" class="' + container.classPrefix + 'abs-end"></div>' + this._super(container);
      }
    });

    var Button = Widget.extend({
      Defaults: {
        classes: 'widget btn',
        role: 'button'
      },
      init: function (settings) {
        var self = this;
        var size;
        self._super(settings);
        settings = self.settings;
        size = self.settings.size;
        self.on('click mousedown', function (e) {
          e.preventDefault();
        });
        self.on('touchstart', function (e) {
          self.fire('click', e);
          e.preventDefault();
        });
        if (settings.subtype) {
          self.classes.add(settings.subtype);
        }
        if (size) {
          self.classes.add('btn-' + size);
        }
        if (settings.icon) {
          self.icon(settings.icon);
        }
      },
      icon: function (icon) {
        if (!arguments.length) {
          return this.state.get('icon');
        }
        this.state.set('icon', icon);
        return this;
      },
      repaint: function () {
        var btnElm = this.getEl().firstChild;
        var btnStyle;
        if (btnElm) {
          btnStyle = btnElm.style;
          btnStyle.width = btnStyle.height = '100%';
        }
        this._super();
      },
      renderHtml: function () {
        var self = this, id = self._id, prefix = self.classPrefix;
        var icon = self.state.get('icon'), image;
        var text = self.state.get('text');
        var textHtml = '';
        var ariaPressed;
        var settings = self.settings;
        image = settings.image;
        if (image) {
          icon = 'none';
          if (typeof image !== 'string') {
            image = domGlobals.window.getSelection ? image[0] : image[1];
          }
          image = ' style="background-image: url(\'' + image + '\')"';
        } else {
          image = '';
        }
        if (text) {
          self.classes.add('btn-has-text');
          textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
        }
        icon = icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';
        ariaPressed = typeof settings.active === 'boolean' ? ' aria-pressed="' + settings.active + '"' : '';
        return '<div id="' + id + '" class="' + self.classes + '" tabindex="-1"' + ariaPressed + '>' + '<button id="' + id + '-button" role="presentation" type="button" tabindex="-1">' + (icon ? '<i class="' + icon + '"' + image + '></i>' : '') + textHtml + '</button>' + '</div>';
      },
      bindStates: function () {
        var self = this, $ = self.$, textCls = self.classPrefix + 'txt';
        function setButtonText(text) {
          var $span = $('span.' + textCls, self.getEl());
          if (text) {
            if (!$span[0]) {
              $('button:first', self.getEl()).append('<span class="' + textCls + '"></span>');
              $span = $('span.' + textCls, self.getEl());
            }
            $span.html(self.encode(text));
          } else {
            $span.remove();
          }
          self.classes.toggle('btn-has-text', !!text);
        }
        self.state.on('change:text', function (e) {
          setButtonText(e.value);
        });
        self.state.on('change:icon', function (e) {
          var icon = e.value;
          var prefix = self.classPrefix;
          self.settings.icon = icon;
          icon = icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
          var btnElm = self.getEl().firstChild;
          var iconElm = btnElm.getElementsByTagName('i')[0];
          if (icon) {
            if (!iconElm || iconElm !== btnElm.firstChild) {
              iconElm = domGlobals.document.createElement('i');
              btnElm.insertBefore(iconElm, btnElm.firstChild);
            }
            iconElm.className = icon;
          } else if (iconElm) {
            btnElm.removeChild(iconElm);
          }
          setButtonText(self.state.get('text'));
        });
        return self._super();
      }
    });

    var BrowseButton = Button.extend({
      init: function (settings) {
        var self = this;
        settings = global$2.extend({
          text: 'Browse...',
          multiple: false,
          accept: null
        }, settings);
        self._super(settings);
        self.classes.add('browsebutton');
        if (settings.multiple) {
          self.classes.add('multiple');
        }
      },
      postRender: function () {
        var self = this;
        var input = funcs.create('input', {
          type: 'file',
          id: self._id + '-browse',
          accept: self.settings.accept
        });
        self._super();
        global$9(input).on('change', function (e) {
          var files = e.target.files;
          self.value = function () {
            if (!files.length) {
              return null;
            } else if (self.settings.multiple) {
              return files;
            } else {
              return files[0];
            }
          };
          e.preventDefault();
          if (files.length) {
            self.fire('change', e);
          }
        });
        global$9(input).on('click', function (e) {
          e.stopPropagation();
        });
        global$9(self.getEl('button')).on('click touchstart', function (e) {
          e.stopPropagation();
          input.click();
          e.preventDefault();
        });
        self.getEl().appendChild(input);
      },
      remove: function () {
        global$9(this.getEl('button')).off();
        global$9(this.getEl('input')).off();
        this._super();
      }
    });

    var ButtonGroup = Container.extend({
      Defaults: {
        defaultType: 'button',
        role: 'group'
      },
      renderHtml: function () {
        var self = this, layout = self._layout;
        self.classes.add('btn-group');
        self.preRender();
        layout.preRender(self);
        return '<div id="' + self._id + '" class="' + self.classes + '">' + '<div id="' + self._id + '-body">' + (self.settings.html || '') + layout.renderHtml(self) + '</div>' + '</div>';
      }
    });

    var Checkbox = Widget.extend({
      Defaults: {
        classes: 'checkbox',
        role: 'checkbox',
        checked: false
      },
      init: function (settings) {
        var self = this;
        self._super(settings);
        self.on('click mousedown', function (e) {
          e.preventDefault();
        });
        self.on('click', function (e) {
          e.preventDefault();
          if (!self.disabled()) {
            self.checked(!self.checked());
          }
        });
        self.checked(self.settings.checked);
      },
      checked: function (state) {
        if (!arguments.length) {
          return this.state.get('checked');
        }
        this.state.set('checked', state);
        return this;
      },
      value: function (state) {
        if (!arguments.length) {
          return this.checked();
        }
        return this.checked(state);
      },
      renderHtml: function () {
        var self = this, id = self._id, prefix = self.classPrefix;
        return '<div id="' + id + '" class="' + self.classes + '" unselectable="on" aria-labelledby="' + id + '-al" tabindex="-1">' + '<i class="' + prefix + 'ico ' + prefix + 'i-checkbox"></i>' + '<span id="' + id + '-al" class="' + prefix + 'label">' + self.encode(self.state.get('text')) + '</span>' + '</div>';
      },
      bindStates: function () {
        var self = this;
        function checked(state) {
          self.classes.toggle('checked', state);
          self.aria('checked', state);
        }
        self.state.on('change:text', function (e) {
          self.getEl('al').firstChild.data = self.translate(e.value);
        });
        self.state.on('change:checked change:value', function (e) {
          self.fire('change');
          checked(e.value);
        });
        self.state.on('change:icon', function (e) {
          var icon = e.value;
          var prefix = self.classPrefix;
          if (typeof icon === 'undefined') {
            return self.settings.icon;
          }
          self.settings.icon = icon;
          icon = icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
          var btnElm = self.getEl().firstChild;
          var iconElm = btnElm.getElementsByTagName('i')[0];
          if (icon) {
            if (!iconElm || iconElm !== btnElm.firstChild) {
              iconElm = domGlobals.document.createElement('i');
              btnElm.insertBefore(iconElm, btnElm.firstChild);
            }
            iconElm.className = icon;
          } else if (iconElm) {
            btnElm.removeChild(iconElm);
          }
        });
        if (self.state.get('checked')) {
          checked(true);
        }
        return self._super();
      }
    });

    var global$d = tinymce.util.Tools.resolve('tinymce.util.VK');

    var ComboBox = Widget.extend({
      init: function (settings) {
        var self = this;
        self._super(settings);
        settings = self.settings;
        self.classes.add('combobox');
        self.subinput = true;
        self.ariaTarget = 'inp';
        settings.menu = settings.menu || settings.values;
        if (settings.menu) {
          settings.icon = 'caret';
        }
        self.on('click', function (e) {
          var elm = e.target;
          var root = self.getEl();
          if (!global$9.contains(root, elm) && elm !== root) {
            return;
          }
          while (elm && elm !== root) {
            if (elm.id && elm.id.indexOf('-open') !== -1) {
              self.fire('action');
              if (settings.menu) {
                self.showMenu();
                if (e.aria) {
                  self.menu.items()[0].focus();
                }
              }
            }
            elm = elm.parentNode;
          }
        });
        self.on('keydown', function (e) {
          var rootControl;
          if (e.keyCode === 13 && e.target.nodeName === 'INPUT') {
            e.preventDefault();
            self.parents().reverse().each(function (ctrl) {
              if (ctrl.toJSON) {
                rootControl = ctrl;
                return false;
              }
            });
            self.fire('submit', { data: rootControl.toJSON() });
          }
        });
        self.on('keyup', function (e) {
          if (e.target.nodeName === 'INPUT') {
            var oldValue = self.state.get('value');
            var newValue = e.target.value;
            if (newValue !== oldValue) {
              self.state.set('value', newValue);
              self.fire('autocomplete', e);
            }
          }
        });
        self.on('mouseover', function (e) {
          var tooltip = self.tooltip().moveTo(-65535);
          if (self.statusLevel() && e.target.className.indexOf(self.classPrefix + 'status') !== -1) {
            var statusMessage = self.statusMessage() || 'Ok';
            var rel = tooltip.text(statusMessage).show().testMoveRel(e.target, [
              'bc-tc',
              'bc-tl',
              'bc-tr'
            ]);
            tooltip.classes.toggle('tooltip-n', rel === 'bc-tc');
            tooltip.classes.toggle('tooltip-nw', rel === 'bc-tl');
            tooltip.classes.toggle('tooltip-ne', rel === 'bc-tr');
            tooltip.moveRel(e.target, rel);
          }
        });
      },
      statusLevel: function (value) {
        if (arguments.length > 0) {
          this.state.set('statusLevel', value);
        }
        return this.state.get('statusLevel');
      },
      statusMessage: function (value) {
        if (arguments.length > 0) {
          this.state.set('statusMessage', value);
        }
        return this.state.get('statusMessage');
      },
      showMenu: function () {
        var self = this;
        var settings = self.settings;
        var menu;
        if (!self.menu) {
          menu = settings.menu || [];
          if (menu.length) {
            menu = {
              type: 'menu',
              items: menu
            };
          } else {
            menu.type = menu.type || 'menu';
          }
          self.menu = global$4.create(menu).parent(self).renderTo(self.getContainerElm());
          self.fire('createmenu');
          self.menu.reflow();
          self.menu.on('cancel', function (e) {
            if (e.control === self.menu) {
              self.focus();
            }
          });
          self.menu.on('show hide', function (e) {
            e.control.items().each(function (ctrl) {
              ctrl.active(ctrl.value() === self.value());
            });
          }).fire('show');
          self.menu.on('select', function (e) {
            self.value(e.control.value());
          });
          self.on('focusin', function (e) {
            if (e.target.tagName.toUpperCase() === 'INPUT') {
              self.menu.hide();
            }
          });
          self.aria('expanded', true);
        }
        self.menu.show();
        self.menu.layoutRect({ w: self.layoutRect().w });
        self.menu.moveRel(self.getEl(), self.isRtl() ? [
          'br-tr',
          'tr-br'
        ] : [
          'bl-tl',
          'tl-bl'
        ]);
      },
      focus: function () {
        this.getEl('inp').focus();
      },
      repaint: function () {
        var self = this, elm = self.getEl(), openElm = self.getEl('open'), rect = self.layoutRect();
        var width, lineHeight, innerPadding = 0;
        var inputElm = elm.firstChild;
        if (self.statusLevel() && self.statusLevel() !== 'none') {
          innerPadding = parseInt(funcs.getRuntimeStyle(inputElm, 'padding-right'), 10) - parseInt(funcs.getRuntimeStyle(inputElm, 'padding-left'), 10);
        }
        if (openElm) {
          width = rect.w - funcs.getSize(openElm).width - 10;
        } else {
          width = rect.w - 10;
        }
        var doc = domGlobals.document;
        if (doc.all && (!doc.documentMode || doc.documentMode <= 8)) {
          lineHeight = self.layoutRect().h - 2 + 'px';
        }
        global$9(inputElm).css({
          width: width - innerPadding,
          lineHeight: lineHeight
        });
        self._super();
        return self;
      },
      postRender: function () {
        var self = this;
        global$9(this.getEl('inp')).on('change', function (e) {
          self.state.set('value', e.target.value);
          self.fire('change', e);
        });
        return self._super();
      },
      renderHtml: function () {
        var self = this, id = self._id, settings = self.settings, prefix = self.classPrefix;
        var value = self.state.get('value') || '';
        var icon, text, openBtnHtml = '', extraAttrs = '', statusHtml = '';
        if ('spellcheck' in settings) {
          extraAttrs += ' spellcheck="' + settings.spellcheck + '"';
        }
        if (settings.maxLength) {
          extraAttrs += ' maxlength="' + settings.maxLength + '"';
        }
        if (settings.size) {
          extraAttrs += ' size="' + settings.size + '"';
        }
        if (settings.subtype) {
          extraAttrs += ' type="' + settings.subtype + '"';
        }
        statusHtml = '<i id="' + id + '-status" class="mce-status mce-ico" style="display: none"></i>';
        if (self.disabled()) {
          extraAttrs += ' disabled="disabled"';
        }
        icon = settings.icon;
        if (icon && icon !== 'caret') {
          icon = prefix + 'ico ' + prefix + 'i-' + settings.icon;
        }
        text = self.state.get('text');
        if (icon || text) {
          openBtnHtml = '<div id="' + id + '-open" class="' + prefix + 'btn ' + prefix + 'open" tabIndex="-1" role="button">' + '<button id="' + id + '-action" type="button" hidefocus="1" tabindex="-1">' + (icon !== 'caret' ? '<i class="' + icon + '"></i>' : '<i class="' + prefix + 'caret"></i>') + (text ? (icon ? ' ' : '') + text : '') + '</button>' + '</div>';
          self.classes.add('has-open');
        }
        return '<div id="' + id + '" class="' + self.classes + '">' + '<input id="' + id + '-inp" class="' + prefix + 'textbox" value="' + self.encode(value, false) + '" hidefocus="1"' + extraAttrs + ' placeholder="' + self.encode(settings.placeholder) + '" />' + statusHtml + openBtnHtml + '</div>';
      },
      value: function (value) {
        if (arguments.length) {
          this.state.set('value', value);
          return this;
        }
        if (this.state.get('rendered')) {
          this.state.set('value', this.getEl('inp').value);
        }
        return this.state.get('value');
      },
      showAutoComplete: function (items, term) {
        var self = this;
        if (items.length === 0) {
          self.hideMenu();
          return;
        }
        var insert = function (value, title) {
          return function () {
            self.fire('selectitem', {
              title: title,
              value: value
            });
          };
        };
        if (self.menu) {
          self.menu.items().remove();
        } else {
          self.menu = global$4.create({
            type: 'menu',
            classes: 'combobox-menu',
            layout: 'flow'
          }).parent(self).renderTo();
        }
        global$2.each(items, function (item) {
          self.menu.add({
            text: item.title,
            url: item.previewUrl,
            match: term,
            classes: 'menu-item-ellipsis',
            onclick: insert(item.value, item.title)
          });
        });
        self.menu.renderNew();
        self.hideMenu();
        self.menu.on('cancel', function (e) {
          if (e.control.parent() === self.menu) {
            e.stopPropagation();
            self.focus();
            self.hideMenu();
          }
        });
        self.menu.on('select', function () {
          self.focus();
        });
        var maxW = self.layoutRect().w;
        self.menu.layoutRect({
          w: maxW,
          minW: 0,
          maxW: maxW
        });
        self.menu.repaint();
        self.menu.reflow();
        self.menu.show();
        self.menu.moveRel(self.getEl(), self.isRtl() ? [
          'br-tr',
          'tr-br'
        ] : [
          'bl-tl',
          'tl-bl'
        ]);
      },
      hideMenu: function () {
        if (this.menu) {
          this.menu.hide();
        }
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:value', function (e) {
          if (self.getEl('inp').value !== e.value) {
            self.getEl('inp').value = e.value;
          }
        });
        self.state.on('change:disabled', function (e) {
          self.getEl('inp').disabled = e.value;
        });
        self.state.on('change:statusLevel', function (e) {
          var statusIconElm = self.getEl('status');
          var prefix = self.classPrefix, value = e.value;
          funcs.css(statusIconElm, 'display', value === 'none' ? 'none' : '');
          funcs.toggleClass(statusIconElm, prefix + 'i-checkmark', value === 'ok');
          funcs.toggleClass(statusIconElm, prefix + 'i-warning', value === 'warn');
          funcs.toggleClass(statusIconElm, prefix + 'i-error', value === 'error');
          self.classes.toggle('has-status', value !== 'none');
          self.repaint();
        });
        funcs.on(self.getEl('status'), 'mouseleave', function () {
          self.tooltip().hide();
        });
        self.on('cancel', function (e) {
          if (self.menu && self.menu.visible()) {
            e.stopPropagation();
            self.hideMenu();
          }
        });
        var focusIdx = function (idx, menu) {
          if (menu && menu.items().length > 0) {
            menu.items().eq(idx)[0].focus();
          }
        };
        self.on('keydown', function (e) {
          var keyCode = e.keyCode;
          if (e.target.nodeName === 'INPUT') {
            if (keyCode === global$d.DOWN) {
              e.preventDefault();
              self.fire('autocomplete');
              focusIdx(0, self.menu);
            } else if (keyCode === global$d.UP) {
              e.preventDefault();
              focusIdx(-1, self.menu);
            }
          }
        });
        return self._super();
      },
      remove: function () {
        global$9(this.getEl('inp')).off();
        if (this.menu) {
          this.menu.remove();
        }
        this._super();
      }
    });

    var ColorBox = ComboBox.extend({
      init: function (settings) {
        var self = this;
        settings.spellcheck = false;
        if (settings.onaction) {
          settings.icon = 'none';
        }
        self._super(settings);
        self.classes.add('colorbox');
        self.on('change keyup postrender', function () {
          self.repaintColor(self.value());
        });
      },
      repaintColor: function (value) {
        var openElm = this.getEl('open');
        var elm = openElm ? openElm.getElementsByTagName('i')[0] : null;
        if (elm) {
          try {
            elm.style.background = value;
          } catch (ex) {
          }
        }
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:value', function (e) {
          if (self.state.get('rendered')) {
            self.repaintColor(e.value);
          }
        });
        return self._super();
      }
    });

    var PanelButton = Button.extend({
      showPanel: function () {
        var self = this, settings = self.settings;
        self.classes.add('opened');
        if (!self.panel) {
          var panelSettings = settings.panel;
          if (panelSettings.type) {
            panelSettings = {
              layout: 'grid',
              items: panelSettings
            };
          }
          panelSettings.role = panelSettings.role || 'dialog';
          panelSettings.popover = true;
          panelSettings.autohide = true;
          panelSettings.ariaRoot = true;
          self.panel = new FloatPanel(panelSettings).on('hide', function () {
            self.classes.remove('opened');
          }).on('cancel', function (e) {
            e.stopPropagation();
            self.focus();
            self.hidePanel();
          }).parent(self).renderTo(self.getContainerElm());
          self.panel.fire('show');
          self.panel.reflow();
        } else {
          self.panel.show();
        }
        var rtlRels = [
          'bc-tc',
          'bc-tl',
          'bc-tr'
        ];
        var ltrRels = [
          'bc-tc',
          'bc-tr',
          'bc-tl',
          'tc-bc',
          'tc-br',
          'tc-bl'
        ];
        var rel = self.panel.testMoveRel(self.getEl(), settings.popoverAlign || (self.isRtl() ? rtlRels : ltrRels));
        self.panel.classes.toggle('start', rel.substr(-1) === 'l');
        self.panel.classes.toggle('end', rel.substr(-1) === 'r');
        var isTop = rel.substr(0, 1) === 't';
        self.panel.classes.toggle('bottom', !isTop);
        self.panel.classes.toggle('top', isTop);
        self.panel.moveRel(self.getEl(), rel);
      },
      hidePanel: function () {
        var self = this;
        if (self.panel) {
          self.panel.hide();
        }
      },
      postRender: function () {
        var self = this;
        self.aria('haspopup', true);
        self.on('click', function (e) {
          if (e.control === self) {
            if (self.panel && self.panel.visible()) {
              self.hidePanel();
            } else {
              self.showPanel();
              self.panel.focus(!!e.aria);
            }
          }
        });
        return self._super();
      },
      remove: function () {
        if (this.panel) {
          this.panel.remove();
          this.panel = null;
        }
        return this._super();
      }
    });

    var DOM$3 = global$3.DOM;
    var ColorButton = PanelButton.extend({
      init: function (settings) {
        this._super(settings);
        this.classes.add('splitbtn');
        this.classes.add('colorbutton');
      },
      color: function (color) {
        if (color) {
          this._color = color;
          this.getEl('preview').style.backgroundColor = color;
          return this;
        }
        return this._color;
      },
      resetColor: function () {
        this._color = null;
        this.getEl('preview').style.backgroundColor = null;
        return this;
      },
      renderHtml: function () {
        var self = this, id = self._id, prefix = self.classPrefix, text = self.state.get('text');
        var icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
        var image = self.settings.image ? ' style="background-image: url(\'' + self.settings.image + '\')"' : '';
        var textHtml = '';
        if (text) {
          self.classes.add('btn-has-text');
          textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
        }
        return '<div id="' + id + '" class="' + self.classes + '" role="button" tabindex="-1" aria-haspopup="true">' + '<button role="presentation" hidefocus="1" type="button" tabindex="-1">' + (icon ? '<i class="' + icon + '"' + image + '></i>' : '') + '<span id="' + id + '-preview" class="' + prefix + 'preview"></span>' + textHtml + '</button>' + '<button type="button" class="' + prefix + 'open" hidefocus="1" tabindex="-1">' + ' <i class="' + prefix + 'caret"></i>' + '</button>' + '</div>';
      },
      postRender: function () {
        var self = this, onClickHandler = self.settings.onclick;
        self.on('click', function (e) {
          if (e.aria && e.aria.key === 'down') {
            return;
          }
          if (e.control === self && !DOM$3.getParent(e.target, '.' + self.classPrefix + 'open')) {
            e.stopImmediatePropagation();
            onClickHandler.call(self, e);
          }
        });
        delete self.settings.onclick;
        return self._super();
      }
    });

    var global$e = tinymce.util.Tools.resolve('tinymce.util.Color');

    var ColorPicker = Widget.extend({
      Defaults: { classes: 'widget colorpicker' },
      init: function (settings) {
        this._super(settings);
      },
      postRender: function () {
        var self = this;
        var color = self.color();
        var hsv, hueRootElm, huePointElm, svRootElm, svPointElm;
        hueRootElm = self.getEl('h');
        huePointElm = self.getEl('hp');
        svRootElm = self.getEl('sv');
        svPointElm = self.getEl('svp');
        function getPos(elm, event) {
          var pos = funcs.getPos(elm);
          var x, y;
          x = event.pageX - pos.x;
          y = event.pageY - pos.y;
          x = Math.max(0, Math.min(x / elm.clientWidth, 1));
          y = Math.max(0, Math.min(y / elm.clientHeight, 1));
          return {
            x: x,
            y: y
          };
        }
        function updateColor(hsv, hueUpdate) {
          var hue = (360 - hsv.h) / 360;
          funcs.css(huePointElm, { top: hue * 100 + '%' });
          if (!hueUpdate) {
            funcs.css(svPointElm, {
              left: hsv.s + '%',
              top: 100 - hsv.v + '%'
            });
          }
          svRootElm.style.background = global$e({
            s: 100,
            v: 100,
            h: hsv.h
          }).toHex();
          self.color().parse({
            s: hsv.s,
            v: hsv.v,
            h: hsv.h
          });
        }
        function updateSaturationAndValue(e) {
          var pos;
          pos = getPos(svRootElm, e);
          hsv.s = pos.x * 100;
          hsv.v = (1 - pos.y) * 100;
          updateColor(hsv);
          self.fire('change');
        }
        function updateHue(e) {
          var pos;
          pos = getPos(hueRootElm, e);
          hsv = color.toHsv();
          hsv.h = (1 - pos.y) * 360;
          updateColor(hsv, true);
          self.fire('change');
        }
        self._repaint = function () {
          hsv = color.toHsv();
          updateColor(hsv);
        };
        self._super();
        self._svdraghelper = new DragHelper(self._id + '-sv', {
          start: updateSaturationAndValue,
          drag: updateSaturationAndValue
        });
        self._hdraghelper = new DragHelper(self._id + '-h', {
          start: updateHue,
          drag: updateHue
        });
        self._repaint();
      },
      rgb: function () {
        return this.color().toRgb();
      },
      value: function (value) {
        var self = this;
        if (arguments.length) {
          self.color().parse(value);
          if (self._rendered) {
            self._repaint();
          }
        } else {
          return self.color().toHex();
        }
      },
      color: function () {
        if (!this._color) {
          this._color = global$e();
        }
        return this._color;
      },
      renderHtml: function () {
        var self = this;
        var id = self._id;
        var prefix = self.classPrefix;
        var hueHtml;
        var stops = '#ff0000,#ff0080,#ff00ff,#8000ff,#0000ff,#0080ff,#00ffff,#00ff80,#00ff00,#80ff00,#ffff00,#ff8000,#ff0000';
        function getOldIeFallbackHtml() {
          var i, l, html = '', gradientPrefix, stopsList;
          gradientPrefix = 'filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=';
          stopsList = stops.split(',');
          for (i = 0, l = stopsList.length - 1; i < l; i++) {
            html += '<div class="' + prefix + 'colorpicker-h-chunk" style="' + 'height:' + 100 / l + '%;' + gradientPrefix + stopsList[i] + ',endColorstr=' + stopsList[i + 1] + ');' + '-ms-' + gradientPrefix + stopsList[i] + ',endColorstr=' + stopsList[i + 1] + ')' + '"></div>';
          }
          return html;
        }
        var gradientCssText = 'background: -ms-linear-gradient(top,' + stops + ');' + 'background: linear-gradient(to bottom,' + stops + ');';
        hueHtml = '<div id="' + id + '-h" class="' + prefix + 'colorpicker-h" style="' + gradientCssText + '">' + getOldIeFallbackHtml() + '<div id="' + id + '-hp" class="' + prefix + 'colorpicker-h-marker"></div>' + '</div>';
        return '<div id="' + id + '" class="' + self.classes + '">' + '<div id="' + id + '-sv" class="' + prefix + 'colorpicker-sv">' + '<div class="' + prefix + 'colorpicker-overlay1">' + '<div class="' + prefix + 'colorpicker-overlay2">' + '<div id="' + id + '-svp" class="' + prefix + 'colorpicker-selector1">' + '<div class="' + prefix + 'colorpicker-selector2"></div>' + '</div>' + '</div>' + '</div>' + '</div>' + hueHtml + '</div>';
      }
    });

    var DropZone = Widget.extend({
      init: function (settings) {
        var self = this;
        settings = global$2.extend({
          height: 100,
          text: 'Drop an image here',
          multiple: false,
          accept: null
        }, settings);
        self._super(settings);
        self.classes.add('dropzone');
        if (settings.multiple) {
          self.classes.add('multiple');
        }
      },
      renderHtml: function () {
        var self = this;
        var attrs, elm;
        var cfg = self.settings;
        attrs = {
          id: self._id,
          hidefocus: '1'
        };
        elm = funcs.create('div', attrs, '<span>' + this.translate(cfg.text) + '</span>');
        if (cfg.height) {
          funcs.css(elm, 'height', cfg.height + 'px');
        }
        if (cfg.width) {
          funcs.css(elm, 'width', cfg.width + 'px');
        }
        elm.className = self.classes;
        return elm.outerHTML;
      },
      postRender: function () {
        var self = this;
        var toggleDragClass = function (e) {
          e.preventDefault();
          self.classes.toggle('dragenter');
          self.getEl().className = self.classes;
        };
        var filter = function (files) {
          var accept = self.settings.accept;
          if (typeof accept !== 'string') {
            return files;
          }
          var re = new RegExp('(' + accept.split(/\s*,\s*/).join('|') + ')$', 'i');
          return global$2.grep(files, function (file) {
            return re.test(file.name);
          });
        };
        self._super();
        self.$el.on('dragover', function (e) {
          e.preventDefault();
        });
        self.$el.on('dragenter', toggleDragClass);
        self.$el.on('dragleave', toggleDragClass);
        self.$el.on('drop', function (e) {
          e.preventDefault();
          if (self.state.get('disabled')) {
            return;
          }
          var files = filter(e.dataTransfer.files);
          self.value = function () {
            if (!files.length) {
              return null;
            } else if (self.settings.multiple) {
              return files;
            } else {
              return files[0];
            }
          };
          if (files.length) {
            self.fire('change', e);
          }
        });
      },
      remove: function () {
        this.$el.off();
        this._super();
      }
    });

    var Path = Widget.extend({
      init: function (settings) {
        var self = this;
        if (!settings.delimiter) {
          settings.delimiter = '\xBB';
        }
        self._super(settings);
        self.classes.add('path');
        self.canFocus = true;
        self.on('click', function (e) {
          var index;
          var target = e.target;
          if (index = target.getAttribute('data-index')) {
            self.fire('select', {
              value: self.row()[index],
              index: index
            });
          }
        });
        self.row(self.settings.row);
      },
      focus: function () {
        var self = this;
        self.getEl().firstChild.focus();
        return self;
      },
      row: function (row) {
        if (!arguments.length) {
          return this.state.get('row');
        }
        this.state.set('row', row);
        return this;
      },
      renderHtml: function () {
        var self = this;
        return '<div id="' + self._id + '" class="' + self.classes + '">' + self._getDataPathHtml(self.state.get('row')) + '</div>';
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:row', function (e) {
          self.innerHtml(self._getDataPathHtml(e.value));
        });
        return self._super();
      },
      _getDataPathHtml: function (data) {
        var self = this;
        var parts = data || [];
        var i, l, html = '';
        var prefix = self.classPrefix;
        for (i = 0, l = parts.length; i < l; i++) {
          html += (i > 0 ? '<div class="' + prefix + 'divider" aria-hidden="true"> ' + self.settings.delimiter + ' </div>' : '') + '<div role="button" class="' + prefix + 'path-item' + (i === l - 1 ? ' ' + prefix + 'last' : '') + '" data-index="' + i + '" tabindex="-1" id="' + self._id + '-' + i + '" aria-level="' + (i + 1) + '">' + parts[i].name + '</div>';
        }
        if (!html) {
          html = '<div class="' + prefix + 'path-item">\xA0</div>';
        }
        return html;
      }
    });

    var ElementPath = Path.extend({
      postRender: function () {
        var self = this, editor = self.settings.editor;
        function isHidden(elm) {
          if (elm.nodeType === 1) {
            if (elm.nodeName === 'BR' || !!elm.getAttribute('data-mce-bogus')) {
              return true;
            }
            if (elm.getAttribute('data-mce-type') === 'bookmark') {
              return true;
            }
          }
          return false;
        }
        if (editor.settings.elementpath !== false) {
          self.on('select', function (e) {
            editor.focus();
            editor.selection.select(this.row()[e.index].element);
            editor.nodeChanged();
          });
          editor.on('nodeChange', function (e) {
            var outParents = [];
            var parents = e.parents;
            var i = parents.length;
            while (i--) {
              if (parents[i].nodeType === 1 && !isHidden(parents[i])) {
                var args = editor.fire('ResolveName', {
                  name: parents[i].nodeName.toLowerCase(),
                  target: parents[i]
                });
                if (!args.isDefaultPrevented()) {
                  outParents.push({
                    name: args.name,
                    element: parents[i]
                  });
                }
                if (args.isPropagationStopped()) {
                  break;
                }
              }
            }
            self.row(outParents);
          });
        }
        return self._super();
      }
    });

    var FormItem = Container.extend({
      Defaults: {
        layout: 'flex',
        align: 'center',
        defaults: { flex: 1 }
      },
      renderHtml: function () {
        var self = this, layout = self._layout, prefix = self.classPrefix;
        self.classes.add('formitem');
        layout.preRender(self);
        return '<div id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1">' + (self.settings.title ? '<div id="' + self._id + '-title" class="' + prefix + 'title">' + self.settings.title + '</div>' : '') + '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' + (self.settings.html || '') + layout.renderHtml(self) + '</div>' + '</div>';
      }
    });

    var Form = Container.extend({
      Defaults: {
        containerCls: 'form',
        layout: 'flex',
        direction: 'column',
        align: 'stretch',
        flex: 1,
        padding: 15,
        labelGap: 30,
        spacing: 10,
        callbacks: {
          submit: function () {
            this.submit();
          }
        }
      },
      preRender: function () {
        var self = this, items = self.items();
        if (!self.settings.formItemDefaults) {
          self.settings.formItemDefaults = {
            layout: 'flex',
            autoResize: 'overflow',
            defaults: { flex: 1 }
          };
        }
        items.each(function (ctrl) {
          var formItem;
          var label = ctrl.settings.label;
          if (label) {
            formItem = new FormItem(global$2.extend({
              items: {
                type: 'label',
                id: ctrl._id + '-l',
                text: label,
                flex: 0,
                forId: ctrl._id,
                disabled: ctrl.disabled()
              }
            }, self.settings.formItemDefaults));
            formItem.type = 'formitem';
            ctrl.aria('labelledby', ctrl._id + '-l');
            if (typeof ctrl.settings.flex === 'undefined') {
              ctrl.settings.flex = 1;
            }
            self.replace(ctrl, formItem);
            formItem.add(ctrl);
          }
        });
      },
      submit: function () {
        return this.fire('submit', { data: this.toJSON() });
      },
      postRender: function () {
        var self = this;
        self._super();
        self.fromJSON(self.settings.data);
      },
      bindStates: function () {
        var self = this;
        self._super();
        function recalcLabels() {
          var maxLabelWidth = 0;
          var labels = [];
          var i, labelGap, items;
          if (self.settings.labelGapCalc === false) {
            return;
          }
          if (self.settings.labelGapCalc === 'children') {
            items = self.find('formitem');
          } else {
            items = self.items();
          }
          items.filter('formitem').each(function (item) {
            var labelCtrl = item.items()[0], labelWidth = labelCtrl.getEl().clientWidth;
            maxLabelWidth = labelWidth > maxLabelWidth ? labelWidth : maxLabelWidth;
            labels.push(labelCtrl);
          });
          labelGap = self.settings.labelGap || 0;
          i = labels.length;
          while (i--) {
            labels[i].settings.minWidth = maxLabelWidth + labelGap;
          }
        }
        self.on('show', recalcLabels);
        recalcLabels();
      }
    });

    var FieldSet = Form.extend({
      Defaults: {
        containerCls: 'fieldset',
        layout: 'flex',
        direction: 'column',
        align: 'stretch',
        flex: 1,
        padding: '25 15 5 15',
        labelGap: 30,
        spacing: 10,
        border: 1
      },
      renderHtml: function () {
        var self = this, layout = self._layout, prefix = self.classPrefix;
        self.preRender();
        layout.preRender(self);
        return '<fieldset id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1">' + (self.settings.title ? '<legend id="' + self._id + '-title" class="' + prefix + 'fieldset-title">' + self.settings.title + '</legend>' : '') + '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' + (self.settings.html || '') + layout.renderHtml(self) + '</div>' + '</fieldset>';
      }
    });

    var unique$1 = 0;
    var generate = function (prefix) {
      var date = new Date();
      var time = date.getTime();
      var random = Math.floor(Math.random() * 1000000000);
      unique$1++;
      return prefix + '_' + random + unique$1 + String(time);
    };

    var fromHtml = function (html, scope) {
      var doc = scope || domGlobals.document;
      var div = doc.createElement('div');
      div.innerHTML = html;
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
        domGlobals.console.error('HTML does not have a single root node', html);
        throw new Error('HTML must have a single root node');
      }
      return fromDom(div.childNodes[0]);
    };
    var fromTag = function (tag, scope) {
      var doc = scope || domGlobals.document;
      var node = doc.createElement(tag);
      return fromDom(node);
    };
    var fromText = function (text, scope) {
      var doc = scope || domGlobals.document;
      var node = doc.createTextNode(text);
      return fromDom(node);
    };
    var fromDom = function (node) {
      if (node === null || node === undefined) {
        throw new Error('Node cannot be null or undefined');
      }
      return { dom: constant(node) };
    };
    var fromPoint = function (docElm, x, y) {
      var doc = docElm.dom();
      return Option.from(doc.elementFromPoint(x, y)).map(fromDom);
    };
    var Element = {
      fromHtml: fromHtml,
      fromTag: fromTag,
      fromText: fromText,
      fromDom: fromDom,
      fromPoint: fromPoint
    };

    var cached = function (f) {
      var called = false;
      var r;
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        if (!called) {
          called = true;
          r = f.apply(null, args);
        }
        return r;
      };
    };

    var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE;
    var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE;
    var COMMENT = domGlobals.Node.COMMENT_NODE;
    var DOCUMENT = domGlobals.Node.DOCUMENT_NODE;
    var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE;
    var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE;
    var ELEMENT = domGlobals.Node.ELEMENT_NODE;
    var TEXT = domGlobals.Node.TEXT_NODE;
    var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE;
    var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE;
    var ENTITY = domGlobals.Node.ENTITY_NODE;
    var NOTATION = domGlobals.Node.NOTATION_NODE;

    var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();

    var path = function (parts, scope) {
      var o = scope !== undefined && scope !== null ? scope : Global;
      for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
        o = o[parts[i]];
      }
      return o;
    };
    var resolve = function (p, scope) {
      var parts = p.split('.');
      return path(parts, scope);
    };

    var unsafe = function (name, scope) {
      return resolve(name, scope);
    };
    var getOrDie = function (name, scope) {
      var actual = unsafe(name, scope);
      if (actual === undefined || actual === null) {
        throw new Error(name + ' not available on this browser');
      }
      return actual;
    };
    var Global$1 = { getOrDie: getOrDie };

    var Immutable = function () {
      var fields = [];
      for (var _i = 0; _i < arguments.length; _i++) {
        fields[_i] = arguments[_i];
      }
      return function () {
        var values = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          values[_i] = arguments[_i];
        }
        if (fields.length !== values.length) {
          throw new Error('Wrong number of arguments to struct. Expected "[' + fields.length + ']", got ' + values.length + ' arguments');
        }
        var struct = {};
        each(fields, function (name, i) {
          struct[name] = constant(values[i]);
        });
        return struct;
      };
    };

    var node = function () {
      var f = Global$1.getOrDie('Node');
      return f;
    };
    var compareDocumentPosition = function (a, b, match) {
      return (a.compareDocumentPosition(b) & match) !== 0;
    };
    var documentPositionPreceding = function (a, b) {
      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_PRECEDING);
    };
    var documentPositionContainedBy = function (a, b) {
      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_CONTAINED_BY);
    };
    var Node = {
      documentPositionPreceding: documentPositionPreceding,
      documentPositionContainedBy: documentPositionContainedBy
    };

    var firstMatch = function (regexes, s) {
      for (var i = 0; i < regexes.length; i++) {
        var x = regexes[i];
        if (x.test(s)) {
          return x;
        }
      }
      return undefined;
    };
    var find$1 = function (regexes, agent) {
      var r = firstMatch(regexes, agent);
      if (!r) {
        return {
          major: 0,
          minor: 0
        };
      }
      var group = function (i) {
        return Number(agent.replace(r, '$' + i));
      };
      return nu(group(1), group(2));
    };
    var detect = function (versionRegexes, agent) {
      var cleanedAgent = String(agent).toLowerCase();
      if (versionRegexes.length === 0) {
        return unknown();
      }
      return find$1(versionRegexes, cleanedAgent);
    };
    var unknown = function () {
      return nu(0, 0);
    };
    var nu = function (major, minor) {
      return {
        major: major,
        minor: minor
      };
    };
    var Version = {
      nu: nu,
      detect: detect,
      unknown: unknown
    };

    var edge = 'Edge';
    var chrome = 'Chrome';
    var ie = 'IE';
    var opera = 'Opera';
    var firefox = 'Firefox';
    var safari = 'Safari';
    var isBrowser = function (name, current) {
      return function () {
        return current === name;
      };
    };
    var unknown$1 = function () {
      return nu$1({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$1 = function (info) {
      var current = info.current;
      var version = info.version;
      return {
        current: current,
        version: version,
        isEdge: isBrowser(edge, current),
        isChrome: isBrowser(chrome, current),
        isIE: isBrowser(ie, current),
        isOpera: isBrowser(opera, current),
        isFirefox: isBrowser(firefox, current),
        isSafari: isBrowser(safari, current)
      };
    };
    var Browser = {
      unknown: unknown$1,
      nu: nu$1,
      edge: constant(edge),
      chrome: constant(chrome),
      ie: constant(ie),
      opera: constant(opera),
      firefox: constant(firefox),
      safari: constant(safari)
    };

    var windows$1 = 'Windows';
    var ios = 'iOS';
    var android = 'Android';
    var linux = 'Linux';
    var osx = 'OSX';
    var solaris = 'Solaris';
    var freebsd = 'FreeBSD';
    var isOS = function (name, current) {
      return function () {
        return current === name;
      };
    };
    var unknown$2 = function () {
      return nu$2({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$2 = function (info) {
      var current = info.current;
      var version = info.version;
      return {
        current: current,
        version: version,
        isWindows: isOS(windows$1, current),
        isiOS: isOS(ios, current),
        isAndroid: isOS(android, current),
        isOSX: isOS(osx, current),
        isLinux: isOS(linux, current),
        isSolaris: isOS(solaris, current),
        isFreeBSD: isOS(freebsd, current)
      };
    };
    var OperatingSystem = {
      unknown: unknown$2,
      nu: nu$2,
      windows: constant(windows$1),
      ios: constant(ios),
      android: constant(android),
      linux: constant(linux),
      osx: constant(osx),
      solaris: constant(solaris),
      freebsd: constant(freebsd)
    };

    var DeviceType = function (os, browser, userAgent) {
      var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
      var isiPhone = os.isiOS() && !isiPad;
      var isAndroid3 = os.isAndroid() && os.version.major === 3;
      var isAndroid4 = os.isAndroid() && os.version.major === 4;
      var isTablet = isiPad || isAndroid3 || isAndroid4 && /mobile/i.test(userAgent) === true;
      var isTouch = os.isiOS() || os.isAndroid();
      var isPhone = isTouch && !isTablet;
      var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
      return {
        isiPad: constant(isiPad),
        isiPhone: constant(isiPhone),
        isTablet: constant(isTablet),
        isPhone: constant(isPhone),
        isTouch: constant(isTouch),
        isAndroid: os.isAndroid,
        isiOS: os.isiOS,
        isWebView: constant(iOSwebview)
      };
    };

    var detect$1 = function (candidates, userAgent) {
      var agent = String(userAgent).toLowerCase();
      return find(candidates, function (candidate) {
        return candidate.search(agent);
      });
    };
    var detectBrowser = function (browsers, userAgent) {
      return detect$1(browsers, userAgent).map(function (browser) {
        var version = Version.detect(browser.versionRegexes, userAgent);
        return {
          current: browser.name,
          version: version
        };
      });
    };
    var detectOs = function (oses, userAgent) {
      return detect$1(oses, userAgent).map(function (os) {
        var version = Version.detect(os.versionRegexes, userAgent);
        return {
          current: os.name,
          version: version
        };
      });
    };
    var UaString = {
      detectBrowser: detectBrowser,
      detectOs: detectOs
    };

    var contains = function (str, substr) {
      return str.indexOf(substr) !== -1;
    };

    var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
    var checkContains = function (target) {
      return function (uastring) {
        return contains(uastring, target);
      };
    };
    var browsers = [
      {
        name: 'Edge',
        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
        search: function (uastring) {
          return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
        }
      },
      {
        name: 'Chrome',
        versionRegexes: [
          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
          normalVersionRegex
        ],
        search: function (uastring) {
          return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
        }
      },
      {
        name: 'IE',
        versionRegexes: [
          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
          /.*?rv:([0-9]+)\.([0-9]+).*/
        ],
        search: function (uastring) {
          return contains(uastring, 'msie') || contains(uastring, 'trident');
        }
      },
      {
        name: 'Opera',
        versionRegexes: [
          normalVersionRegex,
          /.*?opera\/([0-9]+)\.([0-9]+).*/
        ],
        search: checkContains('opera')
      },
      {
        name: 'Firefox',
        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
        search: checkContains('firefox')
      },
      {
        name: 'Safari',
        versionRegexes: [
          normalVersionRegex,
          /.*?cpu os ([0-9]+)_([0-9]+).*/
        ],
        search: function (uastring) {
          return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
        }
      }
    ];
    var oses = [
      {
        name: 'Windows',
        search: checkContains('win'),
        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'iOS',
        search: function (uastring) {
          return contains(uastring, 'iphone') || contains(uastring, 'ipad');
        },
        versionRegexes: [
          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
          /.*cpu os ([0-9]+)_([0-9]+).*/,
          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
        ]
      },
      {
        name: 'Android',
        search: checkContains('android'),
        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'OSX',
        search: checkContains('os x'),
        versionRegexes: [/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]
      },
      {
        name: 'Linux',
        search: checkContains('linux'),
        versionRegexes: []
      },
      {
        name: 'Solaris',
        search: checkContains('sunos'),
        versionRegexes: []
      },
      {
        name: 'FreeBSD',
        search: checkContains('freebsd'),
        versionRegexes: []
      }
    ];
    var PlatformInfo = {
      browsers: constant(browsers),
      oses: constant(oses)
    };

    var detect$2 = function (userAgent) {
      var browsers = PlatformInfo.browsers();
      var oses = PlatformInfo.oses();
      var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu);
      var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
      var deviceType = DeviceType(os, browser, userAgent);
      return {
        browser: browser,
        os: os,
        deviceType: deviceType
      };
    };
    var PlatformDetection = { detect: detect$2 };

    var detect$3 = cached(function () {
      var userAgent = domGlobals.navigator.userAgent;
      return PlatformDetection.detect(userAgent);
    });
    var PlatformDetection$1 = { detect: detect$3 };

    var ELEMENT$1 = ELEMENT;
    var DOCUMENT$1 = DOCUMENT;
    var bypassSelector = function (dom) {
      return dom.nodeType !== ELEMENT$1 && dom.nodeType !== DOCUMENT$1 || dom.childElementCount === 0;
    };
    var all = function (selector, scope) {
      var base = scope === undefined ? domGlobals.document : scope.dom();
      return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), Element.fromDom);
    };
    var one = function (selector, scope) {
      var base = scope === undefined ? domGlobals.document : scope.dom();
      return bypassSelector(base) ? Option.none() : Option.from(base.querySelector(selector)).map(Element.fromDom);
    };

    var regularContains = function (e1, e2) {
      var d1 = e1.dom();
      var d2 = e2.dom();
      return d1 === d2 ? false : d1.contains(d2);
    };
    var ieContains = function (e1, e2) {
      return Node.documentPositionContainedBy(e1.dom(), e2.dom());
    };
    var browser = PlatformDetection$1.detect().browser;
    var contains$1 = browser.isIE() ? ieContains : regularContains;

    var spot = Immutable('element', 'offset');

    var descendants = function (scope, selector) {
      return all(selector, scope);
    };

    var trim = global$2.trim;
    var hasContentEditableState = function (value) {
      return function (node) {
        if (node && node.nodeType === 1) {
          if (node.contentEditable === value) {
            return true;
          }
          if (node.getAttribute('data-mce-contenteditable') === value) {
            return true;
          }
        }
        return false;
      };
    };
    var isContentEditableTrue = hasContentEditableState('true');
    var isContentEditableFalse = hasContentEditableState('false');
    var create = function (type, title, url, level, attach) {
      return {
        type: type,
        title: title,
        url: url,
        level: level,
        attach: attach
      };
    };
    var isChildOfContentEditableTrue = function (node) {
      while (node = node.parentNode) {
        var value = node.contentEditable;
        if (value && value !== 'inherit') {
          return isContentEditableTrue(node);
        }
      }
      return false;
    };
    var select = function (selector, root) {
      return map(descendants(Element.fromDom(root), selector), function (element) {
        return element.dom();
      });
    };
    var getElementText = function (elm) {
      return elm.innerText || elm.textContent;
    };
    var getOrGenerateId = function (elm) {
      return elm.id ? elm.id : generate('h');
    };
    var isAnchor = function (elm) {
      return elm && elm.nodeName === 'A' && (elm.id || elm.name);
    };
    var isValidAnchor = function (elm) {
      return isAnchor(elm) && isEditable(elm);
    };
    var isHeader = function (elm) {
      return elm && /^(H[1-6])$/.test(elm.nodeName);
    };
    var isEditable = function (elm) {
      return isChildOfContentEditableTrue(elm) && !isContentEditableFalse(elm);
    };
    var isValidHeader = function (elm) {
      return isHeader(elm) && isEditable(elm);
    };
    var getLevel = function (elm) {
      return isHeader(elm) ? parseInt(elm.nodeName.substr(1), 10) : 0;
    };
    var headerTarget = function (elm) {
      var headerId = getOrGenerateId(elm);
      var attach = function () {
        elm.id = headerId;
      };
      return create('header', getElementText(elm), '#' + headerId, getLevel(elm), attach);
    };
    var anchorTarget = function (elm) {
      var anchorId = elm.id || elm.name;
      var anchorText = getElementText(elm);
      return create('anchor', anchorText ? anchorText : '#' + anchorId, '#' + anchorId, 0, noop);
    };
    var getHeaderTargets = function (elms) {
      return map(filter(elms, isValidHeader), headerTarget);
    };
    var getAnchorTargets = function (elms) {
      return map(filter(elms, isValidAnchor), anchorTarget);
    };
    var getTargetElements = function (elm) {
      var elms = select('h1,h2,h3,h4,h5,h6,a:not([href])', elm);
      return elms;
    };
    var hasTitle = function (target) {
      return trim(target.title).length > 0;
    };
    var find$2 = function (elm) {
      var elms = getTargetElements(elm);
      return filter(getHeaderTargets(elms).concat(getAnchorTargets(elms)), hasTitle);
    };
    var LinkTargets = { find: find$2 };

    var getActiveEditor = function () {
      return window.tinymce ? window.tinymce.activeEditor : global$1.activeEditor;
    };
    var history = {};
    var HISTORY_LENGTH = 5;
    var clearHistory = function () {
      history = {};
    };
    var toMenuItem = function (target) {
      return {
        title: target.title,
        value: {
          title: { raw: target.title },
          url: target.url,
          attach: target.attach
        }
      };
    };
    var toMenuItems = function (targets) {
      return global$2.map(targets, toMenuItem);
    };
    var staticMenuItem = function (title, url) {
      return {
        title: title,
        value: {
          title: title,
          url: url,
          attach: noop
        }
      };
    };
    var isUniqueUrl = function (url, targets) {
      var foundTarget = exists(targets, function (target) {
        return target.url === url;
      });
      return !foundTarget;
    };
    var getSetting = function (editorSettings, name, defaultValue) {
      var value = name in editorSettings ? editorSettings[name] : defaultValue;
      return value === false ? null : value;
    };
    var createMenuItems = function (term, targets, fileType, editorSettings) {
      var separator = { title: '-' };
      var fromHistoryMenuItems = function (history) {
        var historyItems = history.hasOwnProperty(fileType) ? history[fileType] : [];
        var uniqueHistory = filter(historyItems, function (url) {
          return isUniqueUrl(url, targets);
        });
        return global$2.map(uniqueHistory, function (url) {
          return {
            title: url,
            value: {
              title: url,
              url: url,
              attach: noop
            }
          };
        });
      };
      var fromMenuItems = function (type) {
        var filteredTargets = filter(targets, function (target) {
          return target.type === type;
        });
        return toMenuItems(filteredTargets);
      };
      var anchorMenuItems = function () {
        var anchorMenuItems = fromMenuItems('anchor');
        var topAnchor = getSetting(editorSettings, 'anchor_top', '#top');
        var bottomAchor = getSetting(editorSettings, 'anchor_bottom', '#bottom');
        if (topAnchor !== null) {
          anchorMenuItems.unshift(staticMenuItem('<top>', topAnchor));
        }
        if (bottomAchor !== null) {
          anchorMenuItems.push(staticMenuItem('<bottom>', bottomAchor));
        }
        return anchorMenuItems;
      };
      var join = function (items) {
        return foldl(items, function (a, b) {
          var bothEmpty = a.length === 0 || b.length === 0;
          return bothEmpty ? a.concat(b) : a.concat(separator, b);
        }, []);
      };
      if (editorSettings.typeahead_urls === false) {
        return [];
      }
      return fileType === 'file' ? join([
        filterByQuery(term, fromHistoryMenuItems(history)),
        filterByQuery(term, fromMenuItems('header')),
        filterByQuery(term, anchorMenuItems())
      ]) : filterByQuery(term, fromHistoryMenuItems(history));
    };
    var addToHistory = function (url, fileType) {
      var items = history[fileType];
      if (!/^https?/.test(url)) {
        return;
      }
      if (items) {
        if (indexOf(items, url).isNone()) {
          history[fileType] = items.slice(0, HISTORY_LENGTH).concat(url);
        }
      } else {
        history[fileType] = [url];
      }
    };
    var filterByQuery = function (term, menuItems) {
      var lowerCaseTerm = term.toLowerCase();
      var result = global$2.grep(menuItems, function (item) {
        return item.title.toLowerCase().indexOf(lowerCaseTerm) !== -1;
      });
      return result.length === 1 && result[0].title === term ? [] : result;
    };
    var getTitle = function (linkDetails) {
      var title = linkDetails.title;
      return title.raw ? title.raw : title;
    };
    var setupAutoCompleteHandler = function (ctrl, editorSettings, bodyElm, fileType) {
      var autocomplete = function (term) {
        var linkTargets = LinkTargets.find(bodyElm);
        var menuItems = createMenuItems(term, linkTargets, fileType, editorSettings);
        ctrl.showAutoComplete(menuItems, term);
      };
      ctrl.on('autocomplete', function () {
        autocomplete(ctrl.value());
      });
      ctrl.on('selectitem', function (e) {
        var linkDetails = e.value;
        ctrl.value(linkDetails.url);
        var title = getTitle(linkDetails);
        if (fileType === 'image') {
          ctrl.fire('change', {
            meta: {
              alt: title,
              attach: linkDetails.attach
            }
          });
        } else {
          ctrl.fire('change', {
            meta: {
              text: title,
              attach: linkDetails.attach
            }
          });
        }
        ctrl.focus();
      });
      ctrl.on('click', function (e) {
        if (ctrl.value().length === 0 && e.target.nodeName === 'INPUT') {
          autocomplete('');
        }
      });
      ctrl.on('PostRender', function () {
        ctrl.getRoot().on('submit', function (e) {
          if (!e.isDefaultPrevented()) {
            addToHistory(ctrl.value(), fileType);
          }
        });
      });
    };
    var statusToUiState = function (result) {
      var status = result.status, message = result.message;
      if (status === 'valid') {
        return {
          status: 'ok',
          message: message
        };
      } else if (status === 'unknown') {
        return {
          status: 'warn',
          message: message
        };
      } else if (status === 'invalid') {
        return {
          status: 'warn',
          message: message
        };
      } else {
        return {
          status: 'none',
          message: ''
        };
      }
    };
    var setupLinkValidatorHandler = function (ctrl, editorSettings, fileType) {
      var validatorHandler = editorSettings.filepicker_validator_handler;
      if (validatorHandler) {
        var validateUrl_1 = function (url) {
          if (url.length === 0) {
            ctrl.statusLevel('none');
            return;
          }
          validatorHandler({
            url: url,
            type: fileType
          }, function (result) {
            var uiState = statusToUiState(result);
            ctrl.statusMessage(uiState.message);
            ctrl.statusLevel(uiState.status);
          });
        };
        ctrl.state.on('change:value', function (e) {
          validateUrl_1(e.value);
        });
      }
    };
    var FilePicker = ComboBox.extend({
      Statics: { clearHistory: clearHistory },
      init: function (settings) {
        var self = this, editor = getActiveEditor(), editorSettings = editor.settings;
        var actionCallback, fileBrowserCallback, fileBrowserCallbackTypes;
        var fileType = settings.filetype;
        settings.spellcheck = false;
        fileBrowserCallbackTypes = editorSettings.file_picker_types || editorSettings.file_browser_callback_types;
        if (fileBrowserCallbackTypes) {
          fileBrowserCallbackTypes = global$2.makeMap(fileBrowserCallbackTypes, /[, ]/);
        }
        if (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[fileType]) {
          fileBrowserCallback = editorSettings.file_picker_callback;
          if (fileBrowserCallback && (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[fileType])) {
            actionCallback = function () {
              var meta = self.fire('beforecall').meta;
              meta = global$2.extend({ filetype: fileType }, meta);
              fileBrowserCallback.call(editor, function (value, meta) {
                self.value(value).fire('change', { meta: meta });
              }, self.value(), meta);
            };
          } else {
            fileBrowserCallback = editorSettings.file_browser_callback;
            if (fileBrowserCallback && (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[fileType])) {
              actionCallback = function () {
                fileBrowserCallback(self.getEl('inp').id, self.value(), fileType, window);
              };
            }
          }
        }
        if (actionCallback) {
          settings.icon = 'browse';
          settings.onaction = actionCallback;
        }
        self._super(settings);
        self.classes.add('filepicker');
        setupAutoCompleteHandler(self, editorSettings, editor.getBody(), fileType);
        setupLinkValidatorHandler(self, editorSettings, fileType);
      }
    });

    var FitLayout = AbsoluteLayout.extend({
      recalc: function (container) {
        var contLayoutRect = container.layoutRect(), paddingBox = container.paddingBox;
        container.items().filter(':visible').each(function (ctrl) {
          ctrl.layoutRect({
            x: paddingBox.left,
            y: paddingBox.top,
            w: contLayoutRect.innerW - paddingBox.right - paddingBox.left,
            h: contLayoutRect.innerH - paddingBox.top - paddingBox.bottom
          });
          if (ctrl.recalc) {
            ctrl.recalc();
          }
        });
      }
    });

    var FlexLayout = AbsoluteLayout.extend({
      recalc: function (container) {
        var i, l, items, contLayoutRect, contPaddingBox, contSettings, align, pack, spacing, totalFlex, availableSpace, direction;
        var ctrl, ctrlLayoutRect, ctrlSettings, flex;
        var maxSizeItems = [];
        var size, maxSize, ratio, rect, pos, maxAlignEndPos;
        var sizeName, minSizeName, posName, maxSizeName, beforeName, innerSizeName, deltaSizeName, contentSizeName;
        var alignAxisName, alignInnerSizeName, alignSizeName, alignMinSizeName, alignBeforeName, alignAfterName;
        var alignDeltaSizeName, alignContentSizeName;
        var max = Math.max, min = Math.min;
        items = container.items().filter(':visible');
        contLayoutRect = container.layoutRect();
        contPaddingBox = container.paddingBox;
        contSettings = container.settings;
        direction = container.isRtl() ? contSettings.direction || 'row-reversed' : contSettings.direction;
        align = contSettings.align;
        pack = container.isRtl() ? contSettings.pack || 'end' : contSettings.pack;
        spacing = contSettings.spacing || 0;
        if (direction === 'row-reversed' || direction === 'column-reverse') {
          items = items.set(items.toArray().reverse());
          direction = direction.split('-')[0];
        }
        if (direction === 'column') {
          posName = 'y';
          sizeName = 'h';
          minSizeName = 'minH';
          maxSizeName = 'maxH';
          innerSizeName = 'innerH';
          beforeName = 'top';
          deltaSizeName = 'deltaH';
          contentSizeName = 'contentH';
          alignBeforeName = 'left';
          alignSizeName = 'w';
          alignAxisName = 'x';
          alignInnerSizeName = 'innerW';
          alignMinSizeName = 'minW';
          alignAfterName = 'right';
          alignDeltaSizeName = 'deltaW';
          alignContentSizeName = 'contentW';
        } else {
          posName = 'x';
          sizeName = 'w';
          minSizeName = 'minW';
          maxSizeName = 'maxW';
          innerSizeName = 'innerW';
          beforeName = 'left';
          deltaSizeName = 'deltaW';
          contentSizeName = 'contentW';
          alignBeforeName = 'top';
          alignSizeName = 'h';
          alignAxisName = 'y';
          alignInnerSizeName = 'innerH';
          alignMinSizeName = 'minH';
          alignAfterName = 'bottom';
          alignDeltaSizeName = 'deltaH';
          alignContentSizeName = 'contentH';
        }
        availableSpace = contLayoutRect[innerSizeName] - contPaddingBox[beforeName] - contPaddingBox[beforeName];
        maxAlignEndPos = totalFlex = 0;
        for (i = 0, l = items.length; i < l; i++) {
          ctrl = items[i];
          ctrlLayoutRect = ctrl.layoutRect();
          ctrlSettings = ctrl.settings;
          flex = ctrlSettings.flex;
          availableSpace -= i < l - 1 ? spacing : 0;
          if (flex > 0) {
            totalFlex += flex;
            if (ctrlLayoutRect[maxSizeName]) {
              maxSizeItems.push(ctrl);
            }
            ctrlLayoutRect.flex = flex;
          }
          availableSpace -= ctrlLayoutRect[minSizeName];
          size = contPaddingBox[alignBeforeName] + ctrlLayoutRect[alignMinSizeName] + contPaddingBox[alignAfterName];
          if (size > maxAlignEndPos) {
            maxAlignEndPos = size;
          }
        }
        rect = {};
        if (availableSpace < 0) {
          rect[minSizeName] = contLayoutRect[minSizeName] - availableSpace + contLayoutRect[deltaSizeName];
        } else {
          rect[minSizeName] = contLayoutRect[innerSizeName] - availableSpace + contLayoutRect[deltaSizeName];
        }
        rect[alignMinSizeName] = maxAlignEndPos + contLayoutRect[alignDeltaSizeName];
        rect[contentSizeName] = contLayoutRect[innerSizeName] - availableSpace;
        rect[alignContentSizeName] = maxAlignEndPos;
        rect.minW = min(rect.minW, contLayoutRect.maxW);
        rect.minH = min(rect.minH, contLayoutRect.maxH);
        rect.minW = max(rect.minW, contLayoutRect.startMinWidth);
        rect.minH = max(rect.minH, contLayoutRect.startMinHeight);
        if (contLayoutRect.autoResize && (rect.minW !== contLayoutRect.minW || rect.minH !== contLayoutRect.minH)) {
          rect.w = rect.minW;
          rect.h = rect.minH;
          container.layoutRect(rect);
          this.recalc(container);
          if (container._lastRect === null) {
            var parentCtrl = container.parent();
            if (parentCtrl) {
              parentCtrl._lastRect = null;
              parentCtrl.recalc();
            }
          }
          return;
        }
        ratio = availableSpace / totalFlex;
        for (i = 0, l = maxSizeItems.length; i < l; i++) {
          ctrl = maxSizeItems[i];
          ctrlLayoutRect = ctrl.layoutRect();
          maxSize = ctrlLayoutRect[maxSizeName];
          size = ctrlLayoutRect[minSizeName] + ctrlLayoutRect.flex * ratio;
          if (size > maxSize) {
            availableSpace -= ctrlLayoutRect[maxSizeName] - ctrlLayoutRect[minSizeName];
            totalFlex -= ctrlLayoutRect.flex;
            ctrlLayoutRect.flex = 0;
            ctrlLayoutRect.maxFlexSize = maxSize;
          } else {
            ctrlLayoutRect.maxFlexSize = 0;
          }
        }
        ratio = availableSpace / totalFlex;
        pos = contPaddingBox[beforeName];
        rect = {};
        if (totalFlex === 0) {
          if (pack === 'end') {
            pos = availableSpace + contPaddingBox[beforeName];
          } else if (pack === 'center') {
            pos = Math.round(contLayoutRect[innerSizeName] / 2 - (contLayoutRect[innerSizeName] - availableSpace) / 2) + contPaddingBox[beforeName];
            if (pos < 0) {
              pos = contPaddingBox[beforeName];
            }
          } else if (pack === 'justify') {
            pos = contPaddingBox[beforeName];
            spacing = Math.floor(availableSpace / (items.length - 1));
          }
        }
        rect[alignAxisName] = contPaddingBox[alignBeforeName];
        for (i = 0, l = items.length; i < l; i++) {
          ctrl = items[i];
          ctrlLayoutRect = ctrl.layoutRect();
          size = ctrlLayoutRect.maxFlexSize || ctrlLayoutRect[minSizeName];
          if (align === 'center') {
            rect[alignAxisName] = Math.round(contLayoutRect[alignInnerSizeName] / 2 - ctrlLayoutRect[alignSizeName] / 2);
          } else if (align === 'stretch') {
            rect[alignSizeName] = max(ctrlLayoutRect[alignMinSizeName] || 0, contLayoutRect[alignInnerSizeName] - contPaddingBox[alignBeforeName] - contPaddingBox[alignAfterName]);
            rect[alignAxisName] = contPaddingBox[alignBeforeName];
          } else if (align === 'end') {
            rect[alignAxisName] = contLayoutRect[alignInnerSizeName] - ctrlLayoutRect[alignSizeName] - contPaddingBox.top;
          }
          if (ctrlLayoutRect.flex > 0) {
            size += ctrlLayoutRect.flex * ratio;
          }
          rect[sizeName] = size;
          rect[posName] = pos;
          ctrl.layoutRect(rect);
          if (ctrl.recalc) {
            ctrl.recalc();
          }
          pos += size + spacing;
        }
      }
    });

    var FlowLayout = Layout.extend({
      Defaults: {
        containerClass: 'flow-layout',
        controlClass: 'flow-layout-item',
        endClass: 'break'
      },
      recalc: function (container) {
        container.items().filter(':visible').each(function (ctrl) {
          if (ctrl.recalc) {
            ctrl.recalc();
          }
        });
      },
      isNative: function () {
        return true;
      }
    });

    var descendant = function (scope, selector) {
      return one(selector, scope);
    };

    var toggleFormat = function (editor, fmt) {
      return function () {
        editor.execCommand('mceToggleFormat', false, fmt);
      };
    };
    var addFormatChangedListener = function (editor, name, changed) {
      var handler = function (state) {
        changed(state, name);
      };
      if (editor.formatter) {
        editor.formatter.formatChanged(name, handler);
      } else {
        editor.on('init', function () {
          editor.formatter.formatChanged(name, handler);
        });
      }
    };
    var postRenderFormatToggle = function (editor, name) {
      return function (e) {
        addFormatChangedListener(editor, name, function (state) {
          e.control.active(state);
        });
      };
    };

    var register = function (editor) {
      var alignFormats = [
        'alignleft',
        'aligncenter',
        'alignright',
        'alignjustify'
      ];
      var defaultAlign = 'alignleft';
      var alignMenuItems = [
        {
          text: 'Left',
          icon: 'alignleft',
          onclick: toggleFormat(editor, 'alignleft')
        },
        {
          text: 'Center',
          icon: 'aligncenter',
          onclick: toggleFormat(editor, 'aligncenter')
        },
        {
          text: 'Right',
          icon: 'alignright',
          onclick: toggleFormat(editor, 'alignright')
        },
        {
          text: 'Justify',
          icon: 'alignjustify',
          onclick: toggleFormat(editor, 'alignjustify')
        }
      ];
      editor.addMenuItem('align', {
        text: 'Align',
        menu: alignMenuItems
      });
      editor.addButton('align', {
        type: 'menubutton',
        icon: defaultAlign,
        menu: alignMenuItems,
        onShowMenu: function (e) {
          var menu = e.control.menu;
          global$2.each(alignFormats, function (formatName, idx) {
            menu.items().eq(idx).each(function (item) {
              return item.active(editor.formatter.match(formatName));
            });
          });
        },
        onPostRender: function (e) {
          var ctrl = e.control;
          global$2.each(alignFormats, function (formatName, idx) {
            addFormatChangedListener(editor, formatName, function (state) {
              ctrl.icon(defaultAlign);
              if (state) {
                ctrl.icon(formatName);
              }
            });
          });
        }
      });
      global$2.each({
        alignleft: [
          'Align left',
          'JustifyLeft'
        ],
        aligncenter: [
          'Align center',
          'JustifyCenter'
        ],
        alignright: [
          'Align right',
          'JustifyRight'
        ],
        alignjustify: [
          'Justify',
          'JustifyFull'
        ],
        alignnone: [
          'No alignment',
          'JustifyNone'
        ]
      }, function (item, name) {
        editor.addButton(name, {
          active: false,
          tooltip: item[0],
          cmd: item[1],
          onPostRender: postRenderFormatToggle(editor, name)
        });
      });
    };
    var Align = { register: register };

    var getFirstFont = function (fontFamily) {
      return fontFamily ? fontFamily.split(',')[0] : '';
    };
    var findMatchingValue = function (items, fontFamily) {
      var font = fontFamily ? fontFamily.toLowerCase() : '';
      var value;
      global$2.each(items, function (item) {
        if (item.value.toLowerCase() === font) {
          value = item.value;
        }
      });
      global$2.each(items, function (item) {
        if (!value && getFirstFont(item.value).toLowerCase() === getFirstFont(font).toLowerCase()) {
          value = item.value;
        }
      });
      return value;
    };
    var createFontNameListBoxChangeHandler = function (editor, items) {
      return function () {
        var self = this;
        self.state.set('value', null);
        editor.on('init nodeChange', function (e) {
          var fontFamily = editor.queryCommandValue('FontName');
          var match = findMatchingValue(items, fontFamily);
          self.value(match ? match : null);
          if (!match && fontFamily) {
            self.text(getFirstFont(fontFamily));
          }
        });
      };
    };
    var createFormats = function (formats) {
      formats = formats.replace(/;$/, '').split(';');
      var i = formats.length;
      while (i--) {
        formats[i] = formats[i].split('=');
      }
      return formats;
    };
    var getFontItems = function (editor) {
      var defaultFontsFormats = 'Andale Mono=andale mono,monospace;' + 'Arial=arial,helvetica,sans-serif;' + 'Arial Black=arial black,sans-serif;' + 'Book Antiqua=book antiqua,palatino,serif;' + 'Comic Sans MS=comic sans ms,sans-serif;' + 'Courier New=courier new,courier,monospace;' + 'Georgia=georgia,palatino,serif;' + 'Helvetica=helvetica,arial,sans-serif;' + 'Impact=impact,sans-serif;' + 'Symbol=symbol;' + 'Tahoma=tahoma,arial,helvetica,sans-serif;' + 'Terminal=terminal,monaco,monospace;' + 'Times New Roman=times new roman,times,serif;' + 'Trebuchet MS=trebuchet ms,geneva,sans-serif;' + 'Verdana=verdana,geneva,sans-serif;' + 'Webdings=webdings;' + 'Wingdings=wingdings,zapf dingbats';
      var fonts = createFormats(editor.settings.font_formats || defaultFontsFormats);
      return global$2.map(fonts, function (font) {
        return {
          text: { raw: font[0] },
          value: font[1],
          textStyle: font[1].indexOf('dings') === -1 ? 'font-family:' + font[1] : ''
        };
      });
    };
    var registerButtons = function (editor) {
      editor.addButton('fontselect', function () {
        var items = getFontItems(editor);
        return {
          type: 'listbox',
          text: 'Font Family',
          tooltip: 'Font Family',
          values: items,
          fixedWidth: true,
          onPostRender: createFontNameListBoxChangeHandler(editor, items),
          onselect: function (e) {
            if (e.control.settings.value) {
              editor.execCommand('FontName', false, e.control.settings.value);
            }
          }
        };
      });
    };
    var register$1 = function (editor) {
      registerButtons(editor);
    };
    var FontSelect = { register: register$1 };

    var round = function (number, precision) {
      var factor = Math.pow(10, precision);
      return Math.round(number * factor) / factor;
    };
    var toPt = function (fontSize, precision) {
      if (/[0-9.]+px$/.test(fontSize)) {
        return round(parseInt(fontSize, 10) * 72 / 96, precision || 0) + 'pt';
      }
      return fontSize;
    };
    var findMatchingValue$1 = function (items, pt, px) {
      var value;
      global$2.each(items, function (item) {
        if (item.value === px) {
          value = px;
        } else if (item.value === pt) {
          value = pt;
        }
      });
      return value;
    };
    var createFontSizeListBoxChangeHandler = function (editor, items) {
      return function () {
        var self = this;
        editor.on('init nodeChange', function (e) {
          var px, pt, precision, match;
          px = editor.queryCommandValue('FontSize');
          if (px) {
            for (precision = 3; !match && precision >= 0; precision--) {
              pt = toPt(px, precision);
              match = findMatchingValue$1(items, pt, px);
            }
          }
          self.value(match ? match : null);
          if (!match) {
            self.text(pt);
          }
        });
      };
    };
    var getFontSizeItems = function (editor) {
      var defaultFontsizeFormats = '8pt 10pt 12pt 14pt 18pt 24pt 36pt';
      var fontsizeFormats = editor.settings.fontsize_formats || defaultFontsizeFormats;
      return global$2.map(fontsizeFormats.split(' '), function (item) {
        var text = item, value = item;
        var values = item.split('=');
        if (values.length > 1) {
          text = values[0];
          value = values[1];
        }
        return {
          text: text,
          value: value
        };
      });
    };
    var registerButtons$1 = function (editor) {
      editor.addButton('fontsizeselect', function () {
        var items = getFontSizeItems(editor);
        return {
          type: 'listbox',
          text: 'Font Sizes',
          tooltip: 'Font Sizes',
          values: items,
          fixedWidth: true,
          onPostRender: createFontSizeListBoxChangeHandler(editor, items),
          onclick: function (e) {
            if (e.control.settings.value) {
              editor.execCommand('FontSize', false, e.control.settings.value);
            }
          }
        };
      });
    };
    var register$2 = function (editor) {
      registerButtons$1(editor);
    };
    var FontSizeSelect = { register: register$2 };

    var hideMenuObjects = function (editor, menu) {
      var count = menu.length;
      global$2.each(menu, function (item) {
        if (item.menu) {
          item.hidden = hideMenuObjects(editor, item.menu) === 0;
        }
        var formatName = item.format;
        if (formatName) {
          item.hidden = !editor.formatter.canApply(formatName);
        }
        if (item.hidden) {
          count--;
        }
      });
      return count;
    };
    var hideFormatMenuItems = function (editor, menu) {
      var count = menu.items().length;
      menu.items().each(function (item) {
        if (item.menu) {
          item.visible(hideFormatMenuItems(editor, item.menu) > 0);
        }
        if (!item.menu && item.settings.menu) {
          item.visible(hideMenuObjects(editor, item.settings.menu) > 0);
        }
        var formatName = item.settings.format;
        if (formatName) {
          item.visible(editor.formatter.canApply(formatName));
        }
        if (!item.visible()) {
          count--;
        }
      });
      return count;
    };
    var createFormatMenu = function (editor) {
      var count = 0;
      var newFormats = [];
      var defaultStyleFormats = [
        {
          title: 'Headings',
          items: [
            {
              title: 'Heading 1',
              format: 'h1'
            },
            {
              title: 'Heading 2',
              format: 'h2'
            },
            {
              title: 'Heading 3',
              format: 'h3'
            },
            {
              title: 'Heading 4',
              format: 'h4'
            },
            {
              title: 'Heading 5',
              format: 'h5'
            },
            {
              title: 'Heading 6',
              format: 'h6'
            }
          ]
        },
        {
          title: 'Inline',
          items: [
            {
              title: 'Bold',
              icon: 'bold',
              format: 'bold'
            },
            {
              title: 'Italic',
              icon: 'italic',
              format: 'italic'
            },
            {
              title: 'Underline',
              icon: 'underline',
              format: 'underline'
            },
            {
              title: 'Strikethrough',
              icon: 'strikethrough',
              format: 'strikethrough'
            },
            {
              title: 'Superscript',
              icon: 'superscript',
              format: 'superscript'
            },
            {
              title: 'Subscript',
              icon: 'subscript',
              format: 'subscript'
            },
            {
              title: 'Code',
              icon: 'code',
              format: 'code'
            }
          ]
        },
        {
          title: 'Blocks',
          items: [
            {
              title: 'Paragraph',
              format: 'p'
            },
            {
              title: 'Blockquote',
              format: 'blockquote'
            },
            {
              title: 'Div',
              format: 'div'
            },
            {
              title: 'Pre',
              format: 'pre'
            }
          ]
        },
        {
          title: 'Alignment',
          items: [
            {
              title: 'Left',
              icon: 'alignleft',
              format: 'alignleft'
            },
            {
              title: 'Center',
              icon: 'aligncenter',
              format: 'aligncenter'
            },
            {
              title: 'Right',
              icon: 'alignright',
              format: 'alignright'
            },
            {
              title: 'Justify',
              icon: 'alignjustify',
              format: 'alignjustify'
            }
          ]
        }
      ];
      var createMenu = function (formats) {
        var menu = [];
        if (!formats) {
          return;
        }
        global$2.each(formats, function (format) {
          var menuItem = {
            text: format.title,
            icon: format.icon
          };
          if (format.items) {
            menuItem.menu = createMenu(format.items);
          } else {
            var formatName = format.format || 'custom' + count++;
            if (!format.format) {
              format.name = formatName;
              newFormats.push(format);
            }
            menuItem.format = formatName;
            menuItem.cmd = format.cmd;
          }
          menu.push(menuItem);
        });
        return menu;
      };
      var createStylesMenu = function () {
        var menu;
        if (editor.settings.style_formats_merge) {
          if (editor.settings.style_formats) {
            menu = createMenu(defaultStyleFormats.concat(editor.settings.style_formats));
          } else {
            menu = createMenu(defaultStyleFormats);
          }
        } else {
          menu = createMenu(editor.settings.style_formats || defaultStyleFormats);
        }
        return menu;
      };
      editor.on('init', function () {
        global$2.each(newFormats, function (format) {
          editor.formatter.register(format.name, format);
        });
      });
      return {
        type: 'menu',
        items: createStylesMenu(),
        onPostRender: function (e) {
          editor.fire('renderFormatsMenu', { control: e.control });
        },
        itemDefaults: {
          preview: true,
          textStyle: function () {
            if (this.settings.format) {
              return editor.formatter.getCssText(this.settings.format);
            }
          },
          onPostRender: function () {
            var self = this;
            self.parent().on('show', function () {
              var formatName, command;
              formatName = self.settings.format;
              if (formatName) {
                self.disabled(!editor.formatter.canApply(formatName));
                self.active(editor.formatter.match(formatName));
              }
              command = self.settings.cmd;
              if (command) {
                self.active(editor.queryCommandState(command));
              }
            });
          },
          onclick: function () {
            if (this.settings.format) {
              toggleFormat(editor, this.settings.format)();
            }
            if (this.settings.cmd) {
              editor.execCommand(this.settings.cmd);
            }
          }
        }
      };
    };
    var registerMenuItems = function (editor, formatMenu) {
      editor.addMenuItem('formats', {
        text: 'Formats',
        menu: formatMenu
      });
    };
    var registerButtons$2 = function (editor, formatMenu) {
      editor.addButton('styleselect', {
        type: 'menubutton',
        text: 'Formats',
        menu: formatMenu,
        onShowMenu: function () {
          if (editor.settings.style_formats_autohide) {
            hideFormatMenuItems(editor, this.menu);
          }
        }
      });
    };
    var register$3 = function (editor) {
      var formatMenu = createFormatMenu(editor);
      registerMenuItems(editor, formatMenu);
      registerButtons$2(editor, formatMenu);
    };
    var Formats = { register: register$3 };

    var defaultBlocks = 'Paragraph=p;' + 'Heading 1=h1;' + 'Heading 2=h2;' + 'Heading 3=h3;' + 'Heading 4=h4;' + 'Heading 5=h5;' + 'Heading 6=h6;' + 'Preformatted=pre';
    var createFormats$1 = function (formats) {
      formats = formats.replace(/;$/, '').split(';');
      var i = formats.length;
      while (i--) {
        formats[i] = formats[i].split('=');
      }
      return formats;
    };
    var createListBoxChangeHandler = function (editor, items, formatName) {
      return function () {
        var self = this;
        editor.on('nodeChange', function (e) {
          var formatter = editor.formatter;
          var value = null;
          global$2.each(e.parents, function (node) {
            global$2.each(items, function (item) {
              if (formatName) {
                if (formatter.matchNode(node, formatName, { value: item.value })) {
                  value = item.value;
                }
              } else {
                if (formatter.matchNode(node, item.value)) {
                  value = item.value;
                }
              }
              if (value) {
                return false;
              }
            });
            if (value) {
              return false;
            }
          });
          self.value(value);
        });
      };
    };
    var lazyFormatSelectBoxItems = function (editor, blocks) {
      return function () {
        var items = [];
        global$2.each(blocks, function (block) {
          items.push({
            text: block[0],
            value: block[1],
            textStyle: function () {
              return editor.formatter.getCssText(block[1]);
            }
          });
        });
        return {
          type: 'listbox',
          text: blocks[0][0],
          values: items,
          fixedWidth: true,
          onselect: function (e) {
            if (e.control) {
              var fmt = e.control.value();
              toggleFormat(editor, fmt)();
            }
          },
          onPostRender: createListBoxChangeHandler(editor, items)
        };
      };
    };
    var buildMenuItems = function (editor, blocks) {
      return global$2.map(blocks, function (block) {
        return {
          text: block[0],
          onclick: toggleFormat(editor, block[1]),
          textStyle: function () {
            return editor.formatter.getCssText(block[1]);
          }
        };
      });
    };
    var register$4 = function (editor) {
      var blocks = createFormats$1(editor.settings.block_formats || defaultBlocks);
      editor.addMenuItem('blockformats', {
        text: 'Blocks',
        menu: buildMenuItems(editor, blocks)
      });
      editor.addButton('formatselect', lazyFormatSelectBoxItems(editor, blocks));
    };
    var FormatSelect = { register: register$4 };

    var createCustomMenuItems = function (editor, names) {
      var items, nameList;
      if (typeof names === 'string') {
        nameList = names.split(' ');
      } else if (global$2.isArray(names)) {
        return flatten(global$2.map(names, function (names) {
          return createCustomMenuItems(editor, names);
        }));
      }
      items = global$2.grep(nameList, function (name) {
        return name === '|' || name in editor.menuItems;
      });
      return global$2.map(items, function (name) {
        return name === '|' ? { text: '-' } : editor.menuItems[name];
      });
    };
    var isSeparator$1 = function (menuItem) {
      return menuItem && menuItem.text === '-';
    };
    var trimMenuItems = function (menuItems) {
      var menuItems2 = filter(menuItems, function (menuItem, i) {
        return !isSeparator$1(menuItem) || !isSeparator$1(menuItems[i - 1]);
      });
      return filter(menuItems2, function (menuItem, i) {
        return !isSeparator$1(menuItem) || i > 0 && i < menuItems2.length - 1;
      });
    };
    var createContextMenuItems = function (editor, context) {
      var outputMenuItems = [{ text: '-' }];
      var menuItems = global$2.grep(editor.menuItems, function (menuItem) {
        return menuItem.context === context;
      });
      global$2.each(menuItems, function (menuItem) {
        if (menuItem.separator === 'before') {
          outputMenuItems.push({ text: '|' });
        }
        if (menuItem.prependToContext) {
          outputMenuItems.unshift(menuItem);
        } else {
          outputMenuItems.push(menuItem);
        }
        if (menuItem.separator === 'after') {
          outputMenuItems.push({ text: '|' });
        }
      });
      return outputMenuItems;
    };
    var createInsertMenu = function (editor) {
      var insertButtonItems = editor.settings.insert_button_items;
      if (insertButtonItems) {
        return trimMenuItems(createCustomMenuItems(editor, insertButtonItems));
      } else {
        return trimMenuItems(createContextMenuItems(editor, 'insert'));
      }
    };
    var registerButtons$3 = function (editor) {
      editor.addButton('insert', {
        type: 'menubutton',
        icon: 'insert',
        menu: [],
        oncreatemenu: function () {
          this.menu.add(createInsertMenu(editor));
          this.menu.renderNew();
        }
      });
    };
    var register$5 = function (editor) {
      registerButtons$3(editor);
    };
    var InsertButton = { register: register$5 };

    var registerFormatButtons = function (editor) {
      global$2.each({
        bold: 'Bold',
        italic: 'Italic',
        underline: 'Underline',
        strikethrough: 'Strikethrough',
        subscript: 'Subscript',
        superscript: 'Superscript'
      }, function (text, name) {
        editor.addButton(name, {
          active: false,
          tooltip: text,
          onPostRender: postRenderFormatToggle(editor, name),
          onclick: toggleFormat(editor, name)
        });
      });
    };
    var registerCommandButtons = function (editor) {
      global$2.each({
        outdent: [
          'Decrease indent',
          'Outdent'
        ],
        indent: [
          'Increase indent',
          'Indent'
        ],
        cut: [
          'Cut',
          'Cut'
        ],
        copy: [
          'Copy',
          'Copy'
        ],
        paste: [
          'Paste',
          'Paste'
        ],
        help: [
          'Help',
          'mceHelp'
        ],
        selectall: [
          'Select all',
          'SelectAll'
        ],
        visualaid: [
          'Visual aids',
          'mceToggleVisualAid'
        ],
        newdocument: [
          'New document',
          'mceNewDocument'
        ],
        removeformat: [
          'Clear formatting',
          'RemoveFormat'
        ],
        remove: [
          'Remove',
          'Delete'
        ]
      }, function (item, name) {
        editor.addButton(name, {
          tooltip: item[0],
          cmd: item[1]
        });
      });
    };
    var registerCommandToggleButtons = function (editor) {
      global$2.each({
        blockquote: [
          'Blockquote',
          'mceBlockQuote'
        ],
        subscript: [
          'Subscript',
          'Subscript'
        ],
        superscript: [
          'Superscript',
          'Superscript'
        ]
      }, function (item, name) {
        editor.addButton(name, {
          active: false,
          tooltip: item[0],
          cmd: item[1],
          onPostRender: postRenderFormatToggle(editor, name)
        });
      });
    };
    var registerButtons$4 = function (editor) {
      registerFormatButtons(editor);
      registerCommandButtons(editor);
      registerCommandToggleButtons(editor);
    };
    var registerMenuItems$1 = function (editor) {
      global$2.each({
        bold: [
          'Bold',
          'Bold',
          'Meta+B'
        ],
        italic: [
          'Italic',
          'Italic',
          'Meta+I'
        ],
        underline: [
          'Underline',
          'Underline',
          'Meta+U'
        ],
        strikethrough: [
          'Strikethrough',
          'Strikethrough'
        ],
        subscript: [
          'Subscript',
          'Subscript'
        ],
        superscript: [
          'Superscript',
          'Superscript'
        ],
        removeformat: [
          'Clear formatting',
          'RemoveFormat'
        ],
        newdocument: [
          'New document',
          'mceNewDocument'
        ],
        cut: [
          'Cut',
          'Cut',
          'Meta+X'
        ],
        copy: [
          'Copy',
          'Copy',
          'Meta+C'
        ],
        paste: [
          'Paste',
          'Paste',
          'Meta+V'
        ],
        selectall: [
          'Select all',
          'SelectAll',
          'Meta+A'
        ]
      }, function (item, name) {
        editor.addMenuItem(name, {
          text: item[0],
          icon: name,
          shortcut: item[2],
          cmd: item[1]
        });
      });
      editor.addMenuItem('codeformat', {
        text: 'Code',
        icon: 'code',
        onclick: toggleFormat(editor, 'code')
      });
    };
    var register$6 = function (editor) {
      registerButtons$4(editor);
      registerMenuItems$1(editor);
    };
    var SimpleControls = { register: register$6 };

    var toggleUndoRedoState = function (editor, type) {
      return function () {
        var self = this;
        var checkState = function () {
          var typeFn = type === 'redo' ? 'hasRedo' : 'hasUndo';
          return editor.undoManager ? editor.undoManager[typeFn]() : false;
        };
        self.disabled(!checkState());
        editor.on('Undo Redo AddUndo TypingUndo ClearUndos SwitchMode', function () {
          self.disabled(editor.readonly || !checkState());
        });
      };
    };
    var registerMenuItems$2 = function (editor) {
      editor.addMenuItem('undo', {
        text: 'Undo',
        icon: 'undo',
        shortcut: 'Meta+Z',
        onPostRender: toggleUndoRedoState(editor, 'undo'),
        cmd: 'undo'
      });
      editor.addMenuItem('redo', {
        text: 'Redo',
        icon: 'redo',
        shortcut: 'Meta+Y',
        onPostRender: toggleUndoRedoState(editor, 'redo'),
        cmd: 'redo'
      });
    };
    var registerButtons$5 = function (editor) {
      editor.addButton('undo', {
        tooltip: 'Undo',
        onPostRender: toggleUndoRedoState(editor, 'undo'),
        cmd: 'undo'
      });
      editor.addButton('redo', {
        tooltip: 'Redo',
        onPostRender: toggleUndoRedoState(editor, 'redo'),
        cmd: 'redo'
      });
    };
    var register$7 = function (editor) {
      registerMenuItems$2(editor);
      registerButtons$5(editor);
    };
    var UndoRedo = { register: register$7 };

    var toggleVisualAidState = function (editor) {
      return function () {
        var self = this;
        editor.on('VisualAid', function (e) {
          self.active(e.hasVisual);
        });
        self.active(editor.hasVisual);
      };
    };
    var registerMenuItems$3 = function (editor) {
      editor.addMenuItem('visualaid', {
        text: 'Visual aids',
        selectable: true,
        onPostRender: toggleVisualAidState(editor),
        cmd: 'mceToggleVisualAid'
      });
    };
    var register$8 = function (editor) {
      registerMenuItems$3(editor);
    };
    var VisualAid = { register: register$8 };

    var setupEnvironment = function () {
      Widget.tooltips = !global$8.iOS;
      Control$1.translate = function (text) {
        return global$1.translate(text);
      };
    };
    var setupUiContainer = function (editor) {
      if (editor.settings.ui_container) {
        global$8.container = descendant(Element.fromDom(domGlobals.document.body), editor.settings.ui_container).fold(constant(null), function (elm) {
          return elm.dom();
        });
      }
    };
    var setupRtlMode = function (editor) {
      if (editor.rtl) {
        Control$1.rtl = true;
      }
    };
    var setupHideFloatPanels = function (editor) {
      editor.on('mousedown progressstate', function () {
        FloatPanel.hideAll();
      });
    };
    var setup$1 = function (editor) {
      setupRtlMode(editor);
      setupHideFloatPanels(editor);
      setupUiContainer(editor);
      setupEnvironment();
      FormatSelect.register(editor);
      Align.register(editor);
      SimpleControls.register(editor);
      UndoRedo.register(editor);
      FontSizeSelect.register(editor);
      FontSelect.register(editor);
      Formats.register(editor);
      VisualAid.register(editor);
      InsertButton.register(editor);
    };
    var FormatControls = { setup: setup$1 };

    var GridLayout = AbsoluteLayout.extend({
      recalc: function (container) {
        var settings, rows, cols, items, contLayoutRect, width, height, rect, ctrlLayoutRect, ctrl, x, y, posX, posY, ctrlSettings, contPaddingBox, align, spacingH, spacingV, alignH, alignV, maxX, maxY;
        var colWidths = [];
        var rowHeights = [];
        var ctrlMinWidth, ctrlMinHeight, availableWidth, availableHeight, reverseRows, idx;
        settings = container.settings;
        items = container.items().filter(':visible');
        contLayoutRect = container.layoutRect();
        cols = settings.columns || Math.ceil(Math.sqrt(items.length));
        rows = Math.ceil(items.length / cols);
        spacingH = settings.spacingH || settings.spacing || 0;
        spacingV = settings.spacingV || settings.spacing || 0;
        alignH = settings.alignH || settings.align;
        alignV = settings.alignV || settings.align;
        contPaddingBox = container.paddingBox;
        reverseRows = 'reverseRows' in settings ? settings.reverseRows : container.isRtl();
        if (alignH && typeof alignH === 'string') {
          alignH = [alignH];
        }
        if (alignV && typeof alignV === 'string') {
          alignV = [alignV];
        }
        for (x = 0; x < cols; x++) {
          colWidths.push(0);
        }
        for (y = 0; y < rows; y++) {
          rowHeights.push(0);
        }
        for (y = 0; y < rows; y++) {
          for (x = 0; x < cols; x++) {
            ctrl = items[y * cols + x];
            if (!ctrl) {
              break;
            }
            ctrlLayoutRect = ctrl.layoutRect();
            ctrlMinWidth = ctrlLayoutRect.minW;
            ctrlMinHeight = ctrlLayoutRect.minH;
            colWidths[x] = ctrlMinWidth > colWidths[x] ? ctrlMinWidth : colWidths[x];
            rowHeights[y] = ctrlMinHeight > rowHeights[y] ? ctrlMinHeight : rowHeights[y];
          }
        }
        availableWidth = contLayoutRect.innerW - contPaddingBox.left - contPaddingBox.right;
        for (maxX = 0, x = 0; x < cols; x++) {
          maxX += colWidths[x] + (x > 0 ? spacingH : 0);
          availableWidth -= (x > 0 ? spacingH : 0) + colWidths[x];
        }
        availableHeight = contLayoutRect.innerH - contPaddingBox.top - contPaddingBox.bottom;
        for (maxY = 0, y = 0; y < rows; y++) {
          maxY += rowHeights[y] + (y > 0 ? spacingV : 0);
          availableHeight -= (y > 0 ? spacingV : 0) + rowHeights[y];
        }
        maxX += contPaddingBox.left + contPaddingBox.right;
        maxY += contPaddingBox.top + contPaddingBox.bottom;
        rect = {};
        rect.minW = maxX + (contLayoutRect.w - contLayoutRect.innerW);
        rect.minH = maxY + (contLayoutRect.h - contLayoutRect.innerH);
        rect.contentW = rect.minW - contLayoutRect.deltaW;
        rect.contentH = rect.minH - contLayoutRect.deltaH;
        rect.minW = Math.min(rect.minW, contLayoutRect.maxW);
        rect.minH = Math.min(rect.minH, contLayoutRect.maxH);
        rect.minW = Math.max(rect.minW, contLayoutRect.startMinWidth);
        rect.minH = Math.max(rect.minH, contLayoutRect.startMinHeight);
        if (contLayoutRect.autoResize && (rect.minW !== contLayoutRect.minW || rect.minH !== contLayoutRect.minH)) {
          rect.w = rect.minW;
          rect.h = rect.minH;
          container.layoutRect(rect);
          this.recalc(container);
          if (container._lastRect === null) {
            var parentCtrl = container.parent();
            if (parentCtrl) {
              parentCtrl._lastRect = null;
              parentCtrl.recalc();
            }
          }
          return;
        }
        if (contLayoutRect.autoResize) {
          rect = container.layoutRect(rect);
          rect.contentW = rect.minW - contLayoutRect.deltaW;
          rect.contentH = rect.minH - contLayoutRect.deltaH;
        }
        var flexV;
        if (settings.packV === 'start') {
          flexV = 0;
        } else {
          flexV = availableHeight > 0 ? Math.floor(availableHeight / rows) : 0;
        }
        var totalFlex = 0;
        var flexWidths = settings.flexWidths;
        if (flexWidths) {
          for (x = 0; x < flexWidths.length; x++) {
            totalFlex += flexWidths[x];
          }
        } else {
          totalFlex = cols;
        }
        var ratio = availableWidth / totalFlex;
        for (x = 0; x < cols; x++) {
          colWidths[x] += flexWidths ? flexWidths[x] * ratio : ratio;
        }
        posY = contPaddingBox.top;
        for (y = 0; y < rows; y++) {
          posX = contPaddingBox.left;
          height = rowHeights[y] + flexV;
          for (x = 0; x < cols; x++) {
            if (reverseRows) {
              idx = y * cols + cols - 1 - x;
            } else {
              idx = y * cols + x;
            }
            ctrl = items[idx];
            if (!ctrl) {
              break;
            }
            ctrlSettings = ctrl.settings;
            ctrlLayoutRect = ctrl.layoutRect();
            width = Math.max(colWidths[x], ctrlLayoutRect.startMinWidth);
            ctrlLayoutRect.x = posX;
            ctrlLayoutRect.y = posY;
            align = ctrlSettings.alignH || (alignH ? alignH[x] || alignH[0] : null);
            if (align === 'center') {
              ctrlLayoutRect.x = posX + width / 2 - ctrlLayoutRect.w / 2;
            } else if (align === 'right') {
              ctrlLayoutRect.x = posX + width - ctrlLayoutRect.w;
            } else if (align === 'stretch') {
              ctrlLayoutRect.w = width;
            }
            align = ctrlSettings.alignV || (alignV ? alignV[x] || alignV[0] : null);
            if (align === 'center') {
              ctrlLayoutRect.y = posY + height / 2 - ctrlLayoutRect.h / 2;
            } else if (align === 'bottom') {
              ctrlLayoutRect.y = posY + height - ctrlLayoutRect.h;
            } else if (align === 'stretch') {
              ctrlLayoutRect.h = height;
            }
            ctrl.layoutRect(ctrlLayoutRect);
            posX += width + spacingH;
            if (ctrl.recalc) {
              ctrl.recalc();
            }
          }
          posY += height + spacingV;
        }
      }
    });

    var Iframe$1 = Widget.extend({
      renderHtml: function () {
        var self = this;
        self.classes.add('iframe');
        self.canFocus = false;
        return '<iframe id="' + self._id + '" class="' + self.classes + '" tabindex="-1" src="' + (self.settings.url || 'javascript:\'\'') + '" frameborder="0"></iframe>';
      },
      src: function (src) {
        this.getEl().src = src;
      },
      html: function (html, callback) {
        var self = this, body = this.getEl().contentWindow.document.body;
        if (!body) {
          global$7.setTimeout(function () {
            self.html(html);
          });
        } else {
          body.innerHTML = html;
          if (callback) {
            callback();
          }
        }
        return this;
      }
    });

    var InfoBox = Widget.extend({
      init: function (settings) {
        var self = this;
        self._super(settings);
        self.classes.add('widget').add('infobox');
        self.canFocus = false;
      },
      severity: function (level) {
        this.classes.remove('error');
        this.classes.remove('warning');
        this.classes.remove('success');
        this.classes.add(level);
      },
      help: function (state) {
        this.state.set('help', state);
      },
      renderHtml: function () {
        var self = this, prefix = self.classPrefix;
        return '<div id="' + self._id + '" class="' + self.classes + '">' + '<div id="' + self._id + '-body">' + self.encode(self.state.get('text')) + '<button role="button" tabindex="-1">' + '<i class="' + prefix + 'ico ' + prefix + 'i-help"></i>' + '</button>' + '</div>' + '</div>';
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:text', function (e) {
          self.getEl('body').firstChild.data = self.encode(e.value);
          if (self.state.get('rendered')) {
            self.updateLayoutRect();
          }
        });
        self.state.on('change:help', function (e) {
          self.classes.toggle('has-help', e.value);
          if (self.state.get('rendered')) {
            self.updateLayoutRect();
          }
        });
        return self._super();
      }
    });

    var Label = Widget.extend({
      init: function (settings) {
        var self = this;
        self._super(settings);
        self.classes.add('widget').add('label');
        self.canFocus = false;
        if (settings.multiline) {
          self.classes.add('autoscroll');
        }
        if (settings.strong) {
          self.classes.add('strong');
        }
      },
      initLayoutRect: function () {
        var self = this, layoutRect = self._super();
        if (self.settings.multiline) {
          var size = funcs.getSize(self.getEl());
          if (size.width > layoutRect.maxW) {
            layoutRect.minW = layoutRect.maxW;
            self.classes.add('multiline');
          }
          self.getEl().style.width = layoutRect.minW + 'px';
          layoutRect.startMinH = layoutRect.h = layoutRect.minH = Math.min(layoutRect.maxH, funcs.getSize(self.getEl()).height);
        }
        return layoutRect;
      },
      repaint: function () {
        var self = this;
        if (!self.settings.multiline) {
          self.getEl().style.lineHeight = self.layoutRect().h + 'px';
        }
        return self._super();
      },
      severity: function (level) {
        this.classes.remove('error');
        this.classes.remove('warning');
        this.classes.remove('success');
        this.classes.add(level);
      },
      renderHtml: function () {
        var self = this;
        var targetCtrl, forName, forId = self.settings.forId;
        var text = self.settings.html ? self.settings.html : self.encode(self.state.get('text'));
        if (!forId && (forName = self.settings.forName)) {
          targetCtrl = self.getRoot().find('#' + forName)[0];
          if (targetCtrl) {
            forId = targetCtrl._id;
          }
        }
        if (forId) {
          return '<label id="' + self._id + '" class="' + self.classes + '"' + (forId ? ' for="' + forId + '"' : '') + '>' + text + '</label>';
        }
        return '<span id="' + self._id + '" class="' + self.classes + '">' + text + '</span>';
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:text', function (e) {
          self.innerHtml(self.encode(e.value));
          if (self.state.get('rendered')) {
            self.updateLayoutRect();
          }
        });
        return self._super();
      }
    });

    var Toolbar$1 = Container.extend({
      Defaults: {
        role: 'toolbar',
        layout: 'flow'
      },
      init: function (settings) {
        var self = this;
        self._super(settings);
        self.classes.add('toolbar');
      },
      postRender: function () {
        var self = this;
        self.items().each(function (ctrl) {
          ctrl.classes.add('toolbar-item');
        });
        return self._super();
      }
    });

    var MenuBar = Toolbar$1.extend({
      Defaults: {
        role: 'menubar',
        containerCls: 'menubar',
        ariaRoot: true,
        defaults: { type: 'menubutton' }
      }
    });

    function isChildOf$1(node, parent) {
      while (node) {
        if (parent === node) {
          return true;
        }
        node = node.parentNode;
      }
      return false;
    }
    var MenuButton = Button.extend({
      init: function (settings) {
        var self = this;
        self._renderOpen = true;
        self._super(settings);
        settings = self.settings;
        self.classes.add('menubtn');
        if (settings.fixedWidth) {
          self.classes.add('fixed-width');
        }
        self.aria('haspopup', true);
        self.state.set('menu', settings.menu || self.render());
      },
      showMenu: function (toggle) {
        var self = this;
        var menu;
        if (self.menu && self.menu.visible() && toggle !== false) {
          return self.hideMenu();
        }
        if (!self.menu) {
          menu = self.state.get('menu') || [];
          self.classes.add('opened');
          if (menu.length) {
            menu = {
              type: 'menu',
              animate: true,
              items: menu
            };
          } else {
            menu.type = menu.type || 'menu';
            menu.animate = true;
          }
          if (!menu.renderTo) {
            self.menu = global$4.create(menu).parent(self).renderTo();
          } else {
            self.menu = menu.parent(self).show().renderTo();
          }
          self.fire('createmenu');
          self.menu.reflow();
          self.menu.on('cancel', function (e) {
            if (e.control.parent() === self.menu) {
              e.stopPropagation();
              self.focus();
              self.hideMenu();
            }
          });
          self.menu.on('select', function () {
            self.focus();
          });
          self.menu.on('show hide', function (e) {
            if (e.type === 'hide' && e.control.parent() === self) {
              self.classes.remove('opened-under');
            }
            if (e.control === self.menu) {
              self.activeMenu(e.type === 'show');
              self.classes.toggle('opened', e.type === 'show');
            }
            self.aria('expanded', e.type === 'show');
          }).fire('show');
        }
        self.menu.show();
        self.menu.layoutRect({ w: self.layoutRect().w });
        self.menu.repaint();
        self.menu.moveRel(self.getEl(), self.isRtl() ? [
          'br-tr',
          'tr-br'
        ] : [
          'bl-tl',
          'tl-bl'
        ]);
        var menuLayoutRect = self.menu.layoutRect();
        var selfBottom = self.$el.offset().top + self.layoutRect().h;
        if (selfBottom > menuLayoutRect.y && selfBottom < menuLayoutRect.y + menuLayoutRect.h) {
          self.classes.add('opened-under');
        }
        self.fire('showmenu');
      },
      hideMenu: function () {
        var self = this;
        if (self.menu) {
          self.menu.items().each(function (item) {
            if (item.hideMenu) {
              item.hideMenu();
            }
          });
          self.menu.hide();
        }
      },
      activeMenu: function (state) {
        this.classes.toggle('active', state);
      },
      renderHtml: function () {
        var self = this, id = self._id, prefix = self.classPrefix;
        var icon = self.settings.icon, image;
        var text = self.state.get('text');
        var textHtml = '';
        image = self.settings.image;
        if (image) {
          icon = 'none';
          if (typeof image !== 'string') {
            image = domGlobals.window.getSelection ? image[0] : image[1];
          }
          image = ' style="background-image: url(\'' + image + '\')"';
        } else {
          image = '';
        }
        if (text) {
          self.classes.add('btn-has-text');
          textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
        }
        icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';
        self.aria('role', self.parent() instanceof MenuBar ? 'menuitem' : 'button');
        return '<div id="' + id + '" class="' + self.classes + '" tabindex="-1" aria-labelledby="' + id + '">' + '<button id="' + id + '-open" role="presentation" type="button" tabindex="-1">' + (icon ? '<i class="' + icon + '"' + image + '></i>' : '') + textHtml + ' <i class="' + prefix + 'caret"></i>' + '</button>' + '</div>';
      },
      postRender: function () {
        var self = this;
        self.on('click', function (e) {
          if (e.control === self && isChildOf$1(e.target, self.getEl())) {
            self.focus();
            self.showMenu(!e.aria);
            if (e.aria) {
              self.menu.items().filter(':visible')[0].focus();
            }
          }
        });
        self.on('mouseenter', function (e) {
          var overCtrl = e.control;
          var parent = self.parent();
          var hasVisibleSiblingMenu;
          if (overCtrl && parent && overCtrl instanceof MenuButton && overCtrl.parent() === parent) {
            parent.items().filter('MenuButton').each(function (ctrl) {
              if (ctrl.hideMenu && ctrl !== overCtrl) {
                if (ctrl.menu && ctrl.menu.visible()) {
                  hasVisibleSiblingMenu = true;
                }
                ctrl.hideMenu();
              }
            });
            if (hasVisibleSiblingMenu) {
              overCtrl.focus();
              overCtrl.showMenu();
            }
          }
        });
        return self._super();
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:menu', function () {
          if (self.menu) {
            self.menu.remove();
          }
          self.menu = null;
        });
        return self._super();
      },
      remove: function () {
        this._super();
        if (this.menu) {
          this.menu.remove();
        }
      }
    });

    var Menu = FloatPanel.extend({
      Defaults: {
        defaultType: 'menuitem',
        border: 1,
        layout: 'stack',
        role: 'application',
        bodyRole: 'menu',
        ariaRoot: true
      },
      init: function (settings) {
        var self = this;
        settings.autohide = true;
        settings.constrainToViewport = true;
        if (typeof settings.items === 'function') {
          settings.itemsFactory = settings.items;
          settings.items = [];
        }
        if (settings.itemDefaults) {
          var items = settings.items;
          var i = items.length;
          while (i--) {
            items[i] = global$2.extend({}, settings.itemDefaults, items[i]);
          }
        }
        self._super(settings);
        self.classes.add('menu');
        if (settings.animate && global$8.ie !== 11) {
          self.classes.add('animate');
        }
      },
      repaint: function () {
        this.classes.toggle('menu-align', true);
        this._super();
        this.getEl().style.height = '';
        this.getEl('body').style.height = '';
        return this;
      },
      cancel: function () {
        var self = this;
        self.hideAll();
        self.fire('select');
      },
      load: function () {
        var self = this;
        var time, factory;
        function hideThrobber() {
          if (self.throbber) {
            self.throbber.hide();
            self.throbber = null;
          }
        }
        factory = self.settings.itemsFactory;
        if (!factory) {
          return;
        }
        if (!self.throbber) {
          self.throbber = new Throbber(self.getEl('body'), true);
          if (self.items().length === 0) {
            self.throbber.show();
            self.fire('loading');
          } else {
            self.throbber.show(100, function () {
              self.items().remove();
              self.fire('loading');
            });
          }
          self.on('hide close', hideThrobber);
        }
        self.requestTime = time = new Date().getTime();
        self.settings.itemsFactory(function (items) {
          if (items.length === 0) {
            self.hide();
            return;
          }
          if (self.requestTime !== time) {
            return;
          }
          self.getEl().style.width = '';
          self.getEl('body').style.width = '';
          hideThrobber();
          self.items().remove();
          self.getEl('body').innerHTML = '';
          self.add(items);
          self.renderNew();
          self.fire('loaded');
        });
      },
      hideAll: function () {
        var self = this;
        this.find('menuitem').exec('hideMenu');
        return self._super();
      },
      preRender: function () {
        var self = this;
        self.items().each(function (ctrl) {
          var settings = ctrl.settings;
          if (settings.icon || settings.image || settings.selectable) {
            self._hasIcons = true;
            return false;
          }
        });
        if (self.settings.itemsFactory) {
          self.on('postrender', function () {
            if (self.settings.itemsFactory) {
              self.load();
            }
          });
        }
        self.on('show hide', function (e) {
          if (e.control === self) {
            if (e.type === 'show') {
              global$7.setTimeout(function () {
                self.classes.add('in');
              }, 0);
            } else {
              self.classes.remove('in');
            }
          }
        });
        return self._super();
      }
    });

    var ListBox = MenuButton.extend({
      init: function (settings) {
        var self = this;
        var values, selected, selectedText, lastItemCtrl;
        function setSelected(menuValues) {
          for (var i = 0; i < menuValues.length; i++) {
            selected = menuValues[i].selected || settings.value === menuValues[i].value;
            if (selected) {
              selectedText = selectedText || menuValues[i].text;
              self.state.set('value', menuValues[i].value);
              return true;
            }
            if (menuValues[i].menu) {
              if (setSelected(menuValues[i].menu)) {
                return true;
              }
            }
          }
        }
        self._super(settings);
        settings = self.settings;
        self._values = values = settings.values;
        if (values) {
          if (typeof settings.value !== 'undefined') {
            setSelected(values);
          }
          if (!selected && values.length > 0) {
            selectedText = values[0].text;
            self.state.set('value', values[0].value);
          }
          self.state.set('menu', values);
        }
        self.state.set('text', settings.text || selectedText);
        self.classes.add('listbox');
        self.on('select', function (e) {
          var ctrl = e.control;
          if (lastItemCtrl) {
            e.lastControl = lastItemCtrl;
          }
          if (settings.multiple) {
            ctrl.active(!ctrl.active());
          } else {
            self.value(e.control.value());
          }
          lastItemCtrl = ctrl;
        });
      },
      value: function (value) {
        if (arguments.length === 0) {
          return this.state.get('value');
        }
        if (typeof value === 'undefined') {
          return this;
        }
        function valueExists(values) {
          return exists(values, function (a) {
            return a.menu ? valueExists(a.menu) : a.value === value;
          });
        }
        if (this.settings.values) {
          if (valueExists(this.settings.values)) {
            this.state.set('value', value);
          } else if (value === null) {
            this.state.set('value', null);
          }
        } else {
          this.state.set('value', value);
        }
        return this;
      },
      bindStates: function () {
        var self = this;
        function activateMenuItemsByValue(menu, value) {
          if (menu instanceof Menu) {
            menu.items().each(function (ctrl) {
              if (!ctrl.hasMenus()) {
                ctrl.active(ctrl.value() === value);
              }
            });
          }
        }
        function getSelectedItem(menuValues, value) {
          var selectedItem;
          if (!menuValues) {
            return;
          }
          for (var i = 0; i < menuValues.length; i++) {
            if (menuValues[i].value === value) {
              return menuValues[i];
            }
            if (menuValues[i].menu) {
              selectedItem = getSelectedItem(menuValues[i].menu, value);
              if (selectedItem) {
                return selectedItem;
              }
            }
          }
        }
        self.on('show', function (e) {
          activateMenuItemsByValue(e.control, self.value());
        });
        self.state.on('change:value', function (e) {
          var selectedItem = getSelectedItem(self.state.get('menu'), e.value);
          if (selectedItem) {
            self.text(selectedItem.text);
          } else {
            self.text(self.settings.text);
          }
        });
        return self._super();
      }
    });

    var toggleTextStyle = function (ctrl, state) {
      var textStyle = ctrl._textStyle;
      if (textStyle) {
        var textElm = ctrl.getEl('text');
        textElm.setAttribute('style', textStyle);
        if (state) {
          textElm.style.color = '';
          textElm.style.backgroundColor = '';
        }
      }
    };
    var MenuItem = Widget.extend({
      Defaults: {
        border: 0,
        role: 'menuitem'
      },
      init: function (settings) {
        var self = this;
        var text;
        self._super(settings);
        settings = self.settings;
        self.classes.add('menu-item');
        if (settings.menu) {
          self.classes.add('menu-item-expand');
        }
        if (settings.preview) {
          self.classes.add('menu-item-preview');
        }
        text = self.state.get('text');
        if (text === '-' || text === '|') {
          self.classes.add('menu-item-sep');
          self.aria('role', 'separator');
          self.state.set('text', '-');
        }
        if (settings.selectable) {
          self.aria('role', 'menuitemcheckbox');
          self.classes.add('menu-item-checkbox');
          settings.icon = 'selected';
        }
        if (!settings.preview && !settings.selectable) {
          self.classes.add('menu-item-normal');
        }
        self.on('mousedown', function (e) {
          e.preventDefault();
        });
        if (settings.menu && !settings.ariaHideMenu) {
          self.aria('haspopup', true);
        }
      },
      hasMenus: function () {
        return !!this.settings.menu;
      },
      showMenu: function () {
        var self = this;
        var settings = self.settings;
        var menu;
        var parent = self.parent();
        parent.items().each(function (ctrl) {
          if (ctrl !== self) {
            ctrl.hideMenu();
          }
        });
        if (settings.menu) {
          menu = self.menu;
          if (!menu) {
            menu = settings.menu;
            if (menu.length) {
              menu = {
                type: 'menu',
                items: menu
              };
            } else {
              menu.type = menu.type || 'menu';
            }
            if (parent.settings.itemDefaults) {
              menu.itemDefaults = parent.settings.itemDefaults;
            }
            menu = self.menu = global$4.create(menu).parent(self).renderTo();
            menu.reflow();
            menu.on('cancel', function (e) {
              e.stopPropagation();
              self.focus();
              menu.hide();
            });
            menu.on('show hide', function (e) {
              if (e.control.items) {
                e.control.items().each(function (ctrl) {
                  ctrl.active(ctrl.settings.selected);
                });
              }
            }).fire('show');
            menu.on('hide', function (e) {
              if (e.control === menu) {
                self.classes.remove('selected');
              }
            });
            menu.submenu = true;
          } else {
            menu.show();
          }
          menu._parentMenu = parent;
          menu.classes.add('menu-sub');
          var rel = menu.testMoveRel(self.getEl(), self.isRtl() ? [
            'tl-tr',
            'bl-br',
            'tr-tl',
            'br-bl'
          ] : [
            'tr-tl',
            'br-bl',
            'tl-tr',
            'bl-br'
          ]);
          menu.moveRel(self.getEl(), rel);
          menu.rel = rel;
          rel = 'menu-sub-' + rel;
          menu.classes.remove(menu._lastRel).add(rel);
          menu._lastRel = rel;
          self.classes.add('selected');
          self.aria('expanded', true);
        }
      },
      hideMenu: function () {
        var self = this;
        if (self.menu) {
          self.menu.items().each(function (item) {
            if (item.hideMenu) {
              item.hideMenu();
            }
          });
          self.menu.hide();
          self.aria('expanded', false);
        }
        return self;
      },
      renderHtml: function () {
        var self = this;
        var id = self._id;
        var settings = self.settings;
        var prefix = self.classPrefix;
        var text = self.state.get('text');
        var icon = self.settings.icon, image = '', shortcut = settings.shortcut;
        var url = self.encode(settings.url), iconHtml = '';
        function convertShortcut(shortcut) {
          var i, value, replace = {};
          if (global$8.mac) {
            replace = {
              alt: '&#x2325;',
              ctrl: '&#x2318;',
              shift: '&#x21E7;',
              meta: '&#x2318;'
            };
          } else {
            replace = { meta: 'Ctrl' };
          }
          shortcut = shortcut.split('+');
          for (i = 0; i < shortcut.length; i++) {
            value = replace[shortcut[i].toLowerCase()];
            if (value) {
              shortcut[i] = value;
            }
          }
          return shortcut.join('+');
        }
        function escapeRegExp(str) {
          return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
        }
        function markMatches(text) {
          var match = settings.match || '';
          return match ? text.replace(new RegExp(escapeRegExp(match), 'gi'), function (match) {
            return '!mce~match[' + match + ']mce~match!';
          }) : text;
        }
        function boldMatches(text) {
          return text.replace(new RegExp(escapeRegExp('!mce~match['), 'g'), '<b>').replace(new RegExp(escapeRegExp(']mce~match!'), 'g'), '</b>');
        }
        if (icon) {
          self.parent().classes.add('menu-has-icons');
        }
        if (settings.image) {
          image = ' style="background-image: url(\'' + settings.image + '\')"';
        }
        if (shortcut) {
          shortcut = convertShortcut(shortcut);
        }
        icon = prefix + 'ico ' + prefix + 'i-' + (self.settings.icon || 'none');
        iconHtml = text !== '-' ? '<i class="' + icon + '"' + image + '></i>\xA0' : '';
        text = boldMatches(self.encode(markMatches(text)));
        url = boldMatches(self.encode(markMatches(url)));
        return '<div id="' + id + '" class="' + self.classes + '" tabindex="-1">' + iconHtml + (text !== '-' ? '<span id="' + id + '-text" class="' + prefix + 'text">' + text + '</span>' : '') + (shortcut ? '<div id="' + id + '-shortcut" class="' + prefix + 'menu-shortcut">' + shortcut + '</div>' : '') + (settings.menu ? '<div class="' + prefix + 'caret"></div>' : '') + (url ? '<div class="' + prefix + 'menu-item-link">' + url + '</div>' : '') + '</div>';
      },
      postRender: function () {
        var self = this, settings = self.settings;
        var textStyle = settings.textStyle;
        if (typeof textStyle === 'function') {
          textStyle = textStyle.call(this);
        }
        if (textStyle) {
          var textElm = self.getEl('text');
          if (textElm) {
            textElm.setAttribute('style', textStyle);
            self._textStyle = textStyle;
          }
        }
        self.on('mouseenter click', function (e) {
          if (e.control === self) {
            if (!settings.menu && e.type === 'click') {
              self.fire('select');
              global$7.requestAnimationFrame(function () {
                self.parent().hideAll();
              });
            } else {
              self.showMenu();
              if (e.aria) {
                self.menu.focus(true);
              }
            }
          }
        });
        self._super();
        return self;
      },
      hover: function () {
        var self = this;
        self.parent().items().each(function (ctrl) {
          ctrl.classes.remove('selected');
        });
        self.classes.toggle('selected', true);
        return self;
      },
      active: function (state) {
        toggleTextStyle(this, state);
        if (typeof state !== 'undefined') {
          this.aria('checked', state);
        }
        return this._super(state);
      },
      remove: function () {
        this._super();
        if (this.menu) {
          this.menu.remove();
        }
      }
    });

    var Radio = Checkbox.extend({
      Defaults: {
        classes: 'radio',
        role: 'radio'
      }
    });

    var ResizeHandle = Widget.extend({
      renderHtml: function () {
        var self = this, prefix = self.classPrefix;
        self.classes.add('resizehandle');
        if (self.settings.direction === 'both') {
          self.classes.add('resizehandle-both');
        }
        self.canFocus = false;
        return '<div id="' + self._id + '" class="' + self.classes + '">' + '<i class="' + prefix + 'ico ' + prefix + 'i-resize"></i>' + '</div>';
      },
      postRender: function () {
        var self = this;
        self._super();
        self.resizeDragHelper = new DragHelper(this._id, {
          start: function () {
            self.fire('ResizeStart');
          },
          drag: function (e) {
            if (self.settings.direction !== 'both') {
              e.deltaX = 0;
            }
            self.fire('Resize', e);
          },
          stop: function () {
            self.fire('ResizeEnd');
          }
        });
      },
      remove: function () {
        if (this.resizeDragHelper) {
          this.resizeDragHelper.destroy();
        }
        return this._super();
      }
    });

    function createOptions(options) {
      var strOptions = '';
      if (options) {
        for (var i = 0; i < options.length; i++) {
          strOptions += '<option value="' + options[i] + '">' + options[i] + '</option>';
        }
      }
      return strOptions;
    }
    var SelectBox = Widget.extend({
      Defaults: {
        classes: 'selectbox',
        role: 'selectbox',
        options: []
      },
      init: function (settings) {
        var self = this;
        self._super(settings);
        if (self.settings.size) {
          self.size = self.settings.size;
        }
        if (self.settings.options) {
          self._options = self.settings.options;
        }
        self.on('keydown', function (e) {
          var rootControl;
          if (e.keyCode === 13) {
            e.preventDefault();
            self.parents().reverse().each(function (ctrl) {
              if (ctrl.toJSON) {
                rootControl = ctrl;
                return false;
              }
            });
            self.fire('submit', { data: rootControl.toJSON() });
          }
        });
      },
      options: function (state) {
        if (!arguments.length) {
          return this.state.get('options');
        }
        this.state.set('options', state);
        return this;
      },
      renderHtml: function () {
        var self = this;
        var options, size = '';
        options = createOptions(self._options);
        if (self.size) {
          size = ' size = "' + self.size + '"';
        }
        return '<select id="' + self._id + '" class="' + self.classes + '"' + size + '>' + options + '</select>';
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:options', function (e) {
          self.getEl().innerHTML = createOptions(e.value);
        });
        return self._super();
      }
    });

    function constrain(value, minVal, maxVal) {
      if (value < minVal) {
        value = minVal;
      }
      if (value > maxVal) {
        value = maxVal;
      }
      return value;
    }
    function setAriaProp(el, name, value) {
      el.setAttribute('aria-' + name, value);
    }
    function updateSliderHandle(ctrl, value) {
      var maxHandlePos, shortSizeName, sizeName, stylePosName, styleValue, handleEl;
      if (ctrl.settings.orientation === 'v') {
        stylePosName = 'top';
        sizeName = 'height';
        shortSizeName = 'h';
      } else {
        stylePosName = 'left';
        sizeName = 'width';
        shortSizeName = 'w';
      }
      handleEl = ctrl.getEl('handle');
      maxHandlePos = (ctrl.layoutRect()[shortSizeName] || 100) - funcs.getSize(handleEl)[sizeName];
      styleValue = maxHandlePos * ((value - ctrl._minValue) / (ctrl._maxValue - ctrl._minValue)) + 'px';
      handleEl.style[stylePosName] = styleValue;
      handleEl.style.height = ctrl.layoutRect().h + 'px';
      setAriaProp(handleEl, 'valuenow', value);
      setAriaProp(handleEl, 'valuetext', '' + ctrl.settings.previewFilter(value));
      setAriaProp(handleEl, 'valuemin', ctrl._minValue);
      setAriaProp(handleEl, 'valuemax', ctrl._maxValue);
    }
    var Slider = Widget.extend({
      init: function (settings) {
        var self = this;
        if (!settings.previewFilter) {
          settings.previewFilter = function (value) {
            return Math.round(value * 100) / 100;
          };
        }
        self._super(settings);
        self.classes.add('slider');
        if (settings.orientation === 'v') {
          self.classes.add('vertical');
        }
        self._minValue = isNumber(settings.minValue) ? settings.minValue : 0;
        self._maxValue = isNumber(settings.maxValue) ? settings.maxValue : 100;
        self._initValue = self.state.get('value');
      },
      renderHtml: function () {
        var self = this, id = self._id, prefix = self.classPrefix;
        return '<div id="' + id + '" class="' + self.classes + '">' + '<div id="' + id + '-handle" class="' + prefix + 'slider-handle" role="slider" tabindex="-1"></div>' + '</div>';
      },
      reset: function () {
        this.value(this._initValue).repaint();
      },
      postRender: function () {
        var self = this;
        var minValue, maxValue, screenCordName, stylePosName, sizeName, shortSizeName;
        function toFraction(min, max, val) {
          return (val + min) / (max - min);
        }
        function fromFraction(min, max, val) {
          return val * (max - min) - min;
        }
        function handleKeyboard(minValue, maxValue) {
          function alter(delta) {
            var value;
            value = self.value();
            value = fromFraction(minValue, maxValue, toFraction(minValue, maxValue, value) + delta * 0.05);
            value = constrain(value, minValue, maxValue);
            self.value(value);
            self.fire('dragstart', { value: value });
            self.fire('drag', { value: value });
            self.fire('dragend', { value: value });
          }
          self.on('keydown', function (e) {
            switch (e.keyCode) {
            case 37:
            case 38:
              alter(-1);
              break;
            case 39:
            case 40:
              alter(1);
              break;
            }
          });
        }
        function handleDrag(minValue, maxValue, handleEl) {
          var startPos, startHandlePos, maxHandlePos, handlePos, value;
          self._dragHelper = new DragHelper(self._id, {
            handle: self._id + '-handle',
            start: function (e) {
              startPos = e[screenCordName];
              startHandlePos = parseInt(self.getEl('handle').style[stylePosName], 10);
              maxHandlePos = (self.layoutRect()[shortSizeName] || 100) - funcs.getSize(handleEl)[sizeName];
              self.fire('dragstart', { value: value });
            },
            drag: function (e) {
              var delta = e[screenCordName] - startPos;
              handlePos = constrain(startHandlePos + delta, 0, maxHandlePos);
              handleEl.style[stylePosName] = handlePos + 'px';
              value = minValue + handlePos / maxHandlePos * (maxValue - minValue);
              self.value(value);
              self.tooltip().text('' + self.settings.previewFilter(value)).show().moveRel(handleEl, 'bc tc');
              self.fire('drag', { value: value });
            },
            stop: function () {
              self.tooltip().hide();
              self.fire('dragend', { value: value });
            }
          });
        }
        minValue = self._minValue;
        maxValue = self._maxValue;
        if (self.settings.orientation === 'v') {
          screenCordName = 'screenY';
          stylePosName = 'top';
          sizeName = 'height';
          shortSizeName = 'h';
        } else {
          screenCordName = 'screenX';
          stylePosName = 'left';
          sizeName = 'width';
          shortSizeName = 'w';
        }
        self._super();
        handleKeyboard(minValue, maxValue);
        handleDrag(minValue, maxValue, self.getEl('handle'));
      },
      repaint: function () {
        this._super();
        updateSliderHandle(this, this.value());
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:value', function (e) {
          updateSliderHandle(self, e.value);
        });
        return self._super();
      }
    });

    var Spacer = Widget.extend({
      renderHtml: function () {
        var self = this;
        self.classes.add('spacer');
        self.canFocus = false;
        return '<div id="' + self._id + '" class="' + self.classes + '"></div>';
      }
    });

    var SplitButton = MenuButton.extend({
      Defaults: {
        classes: 'widget btn splitbtn',
        role: 'button'
      },
      repaint: function () {
        var self = this;
        var elm = self.getEl();
        var rect = self.layoutRect();
        var mainButtonElm, menuButtonElm;
        self._super();
        mainButtonElm = elm.firstChild;
        menuButtonElm = elm.lastChild;
        global$9(mainButtonElm).css({
          width: rect.w - funcs.getSize(menuButtonElm).width,
          height: rect.h - 2
        });
        global$9(menuButtonElm).css({ height: rect.h - 2 });
        return self;
      },
      activeMenu: function (state) {
        var self = this;
        global$9(self.getEl().lastChild).toggleClass(self.classPrefix + 'active', state);
      },
      renderHtml: function () {
        var self = this;
        var id = self._id;
        var prefix = self.classPrefix;
        var image;
        var icon = self.state.get('icon');
        var text = self.state.get('text');
        var settings = self.settings;
        var textHtml = '', ariaPressed;
        image = settings.image;
        if (image) {
          icon = 'none';
          if (typeof image !== 'string') {
            image = domGlobals.window.getSelection ? image[0] : image[1];
          }
          image = ' style="background-image: url(\'' + image + '\')"';
        } else {
          image = '';
        }
        icon = settings.icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';
        if (text) {
          self.classes.add('btn-has-text');
          textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
        }
        ariaPressed = typeof settings.active === 'boolean' ? ' aria-pressed="' + settings.active + '"' : '';
        return '<div id="' + id + '" class="' + self.classes + '" role="button"' + ariaPressed + ' tabindex="-1">' + '<button type="button" hidefocus="1" tabindex="-1">' + (icon ? '<i class="' + icon + '"' + image + '></i>' : '') + textHtml + '</button>' + '<button type="button" class="' + prefix + 'open" hidefocus="1" tabindex="-1">' + (self._menuBtnText ? (icon ? '\xA0' : '') + self._menuBtnText : '') + ' <i class="' + prefix + 'caret"></i>' + '</button>' + '</div>';
      },
      postRender: function () {
        var self = this, onClickHandler = self.settings.onclick;
        self.on('click', function (e) {
          var node = e.target;
          if (e.control === this) {
            while (node) {
              if (e.aria && e.aria.key !== 'down' || node.nodeName === 'BUTTON' && node.className.indexOf('open') === -1) {
                e.stopImmediatePropagation();
                if (onClickHandler) {
                  onClickHandler.call(this, e);
                }
                return;
              }
              node = node.parentNode;
            }
          }
        });
        delete self.settings.onclick;
        return self._super();
      }
    });

    var StackLayout = FlowLayout.extend({
      Defaults: {
        containerClass: 'stack-layout',
        controlClass: 'stack-layout-item',
        endClass: 'break'
      },
      isNative: function () {
        return true;
      }
    });

    var TabPanel = Panel.extend({
      Defaults: {
        layout: 'absolute',
        defaults: { type: 'panel' }
      },
      activateTab: function (idx) {
        var activeTabElm;
        if (this.activeTabId) {
          activeTabElm = this.getEl(this.activeTabId);
          global$9(activeTabElm).removeClass(this.classPrefix + 'active');
          activeTabElm.setAttribute('aria-selected', 'false');
        }
        this.activeTabId = 't' + idx;
        activeTabElm = this.getEl('t' + idx);
        activeTabElm.setAttribute('aria-selected', 'true');
        global$9(activeTabElm).addClass(this.classPrefix + 'active');
        this.items()[idx].show().fire('showtab');
        this.reflow();
        this.items().each(function (item, i) {
          if (idx !== i) {
            item.hide();
          }
        });
      },
      renderHtml: function () {
        var self = this;
        var layout = self._layout;
        var tabsHtml = '';
        var prefix = self.classPrefix;
        self.preRender();
        layout.preRender(self);
        self.items().each(function (ctrl, i) {
          var id = self._id + '-t' + i;
          ctrl.aria('role', 'tabpanel');
          ctrl.aria('labelledby', id);
          tabsHtml += '<div id="' + id + '" class="' + prefix + 'tab" ' + 'unselectable="on" role="tab" aria-controls="' + ctrl._id + '" aria-selected="false" tabIndex="-1">' + self.encode(ctrl.settings.title) + '</div>';
        });
        return '<div id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1">' + '<div id="' + self._id + '-head" class="' + prefix + 'tabs" role="tablist">' + tabsHtml + '</div>' + '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' + layout.renderHtml(self) + '</div>' + '</div>';
      },
      postRender: function () {
        var self = this;
        self._super();
        self.settings.activeTab = self.settings.activeTab || 0;
        self.activateTab(self.settings.activeTab);
        this.on('click', function (e) {
          var targetParent = e.target.parentNode;
          if (targetParent && targetParent.id === self._id + '-head') {
            var i = targetParent.childNodes.length;
            while (i--) {
              if (targetParent.childNodes[i] === e.target) {
                self.activateTab(i);
              }
            }
          }
        });
      },
      initLayoutRect: function () {
        var self = this;
        var rect, minW, minH;
        minW = funcs.getSize(self.getEl('head')).width;
        minW = minW < 0 ? 0 : minW;
        minH = 0;
        self.items().each(function (item) {
          minW = Math.max(minW, item.layoutRect().minW);
          minH = Math.max(minH, item.layoutRect().minH);
        });
        self.items().each(function (ctrl) {
          ctrl.settings.x = 0;
          ctrl.settings.y = 0;
          ctrl.settings.w = minW;
          ctrl.settings.h = minH;
          ctrl.layoutRect({
            x: 0,
            y: 0,
            w: minW,
            h: minH
          });
        });
        var headH = funcs.getSize(self.getEl('head')).height;
        self.settings.minWidth = minW;
        self.settings.minHeight = minH + headH;
        rect = self._super();
        rect.deltaH += headH;
        rect.innerH = rect.h - rect.deltaH;
        return rect;
      }
    });

    var TextBox = Widget.extend({
      init: function (settings) {
        var self = this;
        self._super(settings);
        self.classes.add('textbox');
        if (settings.multiline) {
          self.classes.add('multiline');
        } else {
          self.on('keydown', function (e) {
            var rootControl;
            if (e.keyCode === 13) {
              e.preventDefault();
              self.parents().reverse().each(function (ctrl) {
                if (ctrl.toJSON) {
                  rootControl = ctrl;
                  return false;
                }
              });
              self.fire('submit', { data: rootControl.toJSON() });
            }
          });
          self.on('keyup', function (e) {
            self.state.set('value', e.target.value);
          });
        }
      },
      repaint: function () {
        var self = this;
        var style, rect, borderBox, borderW, borderH = 0, lastRepaintRect;
        style = self.getEl().style;
        rect = self._layoutRect;
        lastRepaintRect = self._lastRepaintRect || {};
        var doc = domGlobals.document;
        if (!self.settings.multiline && doc.all && (!doc.documentMode || doc.documentMode <= 8)) {
          style.lineHeight = rect.h - borderH + 'px';
        }
        borderBox = self.borderBox;
        borderW = borderBox.left + borderBox.right + 8;
        borderH = borderBox.top + borderBox.bottom + (self.settings.multiline ? 8 : 0);
        if (rect.x !== lastRepaintRect.x) {
          style.left = rect.x + 'px';
          lastRepaintRect.x = rect.x;
        }
        if (rect.y !== lastRepaintRect.y) {
          style.top = rect.y + 'px';
          lastRepaintRect.y = rect.y;
        }
        if (rect.w !== lastRepaintRect.w) {
          style.width = rect.w - borderW + 'px';
          lastRepaintRect.w = rect.w;
        }
        if (rect.h !== lastRepaintRect.h) {
          style.height = rect.h - borderH + 'px';
          lastRepaintRect.h = rect.h;
        }
        self._lastRepaintRect = lastRepaintRect;
        self.fire('repaint', {}, false);
        return self;
      },
      renderHtml: function () {
        var self = this;
        var settings = self.settings;
        var attrs, elm;
        attrs = {
          id: self._id,
          hidefocus: '1'
        };
        global$2.each([
          'rows',
          'spellcheck',
          'maxLength',
          'size',
          'readonly',
          'min',
          'max',
          'step',
          'list',
          'pattern',
          'placeholder',
          'required',
          'multiple'
        ], function (name) {
          attrs[name] = settings[name];
        });
        if (self.disabled()) {
          attrs.disabled = 'disabled';
        }
        if (settings.subtype) {
          attrs.type = settings.subtype;
        }
        elm = funcs.create(settings.multiline ? 'textarea' : 'input', attrs);
        elm.value = self.state.get('value');
        elm.className = self.classes.toString();
        return elm.outerHTML;
      },
      value: function (value) {
        if (arguments.length) {
          this.state.set('value', value);
          return this;
        }
        if (this.state.get('rendered')) {
          this.state.set('value', this.getEl().value);
        }
        return this.state.get('value');
      },
      postRender: function () {
        var self = this;
        self.getEl().value = self.state.get('value');
        self._super();
        self.$el.on('change', function (e) {
          self.state.set('value', e.target.value);
          self.fire('change', e);
        });
      },
      bindStates: function () {
        var self = this;
        self.state.on('change:value', function (e) {
          if (self.getEl().value !== e.value) {
            self.getEl().value = e.value;
          }
        });
        self.state.on('change:disabled', function (e) {
          self.getEl().disabled = e.value;
        });
        return self._super();
      },
      remove: function () {
        this.$el.off();
        this._super();
      }
    });

    var getApi = function () {
      return {
        Selector: Selector,
        Collection: Collection$2,
        ReflowQueue: ReflowQueue,
        Control: Control$1,
        Factory: global$4,
        KeyboardNavigation: KeyboardNavigation,
        Container: Container,
        DragHelper: DragHelper,
        Scrollable: Scrollable,
        Panel: Panel,
        Movable: Movable,
        Resizable: Resizable,
        FloatPanel: FloatPanel,
        Window: Window,
        MessageBox: MessageBox,
        Tooltip: Tooltip,
        Widget: Widget,
        Progress: Progress,
        Notification: Notification,
        Layout: Layout,
        AbsoluteLayout: AbsoluteLayout,
        Button: Button,
        ButtonGroup: ButtonGroup,
        Checkbox: Checkbox,
        ComboBox: ComboBox,
        ColorBox: ColorBox,
        PanelButton: PanelButton,
        ColorButton: ColorButton,
        ColorPicker: ColorPicker,
        Path: Path,
        ElementPath: ElementPath,
        FormItem: FormItem,
        Form: Form,
        FieldSet: FieldSet,
        FilePicker: FilePicker,
        FitLayout: FitLayout,
        FlexLayout: FlexLayout,
        FlowLayout: FlowLayout,
        FormatControls: FormatControls,
        GridLayout: GridLayout,
        Iframe: Iframe$1,
        InfoBox: InfoBox,
        Label: Label,
        Toolbar: Toolbar$1,
        MenuBar: MenuBar,
        MenuButton: MenuButton,
        MenuItem: MenuItem,
        Throbber: Throbber,
        Menu: Menu,
        ListBox: ListBox,
        Radio: Radio,
        ResizeHandle: ResizeHandle,
        SelectBox: SelectBox,
        Slider: Slider,
        Spacer: Spacer,
        SplitButton: SplitButton,
        StackLayout: StackLayout,
        TabPanel: TabPanel,
        TextBox: TextBox,
        DropZone: DropZone,
        BrowseButton: BrowseButton
      };
    };
    var appendTo = function (target) {
      if (target.ui) {
        global$2.each(getApi(), function (ref, key) {
          target.ui[key] = ref;
        });
      } else {
        target.ui = getApi();
      }
    };
    var registerToFactory = function () {
      global$2.each(getApi(), function (ref, key) {
        global$4.add(key, ref);
      });
    };
    var Api = {
      appendTo: appendTo,
      registerToFactory: registerToFactory
    };

    Api.registerToFactory();
    Api.appendTo(window.tinymce ? window.tinymce : {});
    global.add('modern', function (editor) {
      FormatControls.setup(editor);
      return ThemeApi.get(editor);
    });
    function Theme () {
    }

    return Theme;

}(window));
})();


/***/ }),

/***/ 560:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "table" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/table')
//   ES2015:
//     import 'tinymce/plugins/table'
__webpack_require__(561);

/***/ }),

/***/ 561:
/***/ (function(module, exports) {

(function () {
var table = (function (domGlobals) {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var noop = function () {
    };
    var compose = function (fa, fb) {
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        return fa(fb.apply(null, args));
      };
    };
    var constant = function (value) {
      return function () {
        return value;
      };
    };
    var identity = function (x) {
      return x;
    };
    function curry(fn) {
      var initialArgs = [];
      for (var _i = 1; _i < arguments.length; _i++) {
        initialArgs[_i - 1] = arguments[_i];
      }
      return function () {
        var restArgs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          restArgs[_i] = arguments[_i];
        }
        var all = initialArgs.concat(restArgs);
        return fn.apply(null, all);
      };
    }
    var not = function (f) {
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        return !f.apply(null, args);
      };
    };
    var die = function (msg) {
      return function () {
        throw new Error(msg);
      };
    };
    var never = constant(false);
    var always = constant(true);

    var none = function () {
      return NONE;
    };
    var NONE = function () {
      var eq = function (o) {
        return o.isNone();
      };
      var call = function (thunk) {
        return thunk();
      };
      var id = function (n) {
        return n;
      };
      var me = {
        fold: function (n, s) {
          return n();
        },
        is: never,
        isSome: never,
        isNone: always,
        getOr: id,
        getOrThunk: call,
        getOrDie: function (msg) {
          throw new Error(msg || 'error: getOrDie called on none.');
        },
        getOrNull: constant(null),
        getOrUndefined: constant(undefined),
        or: id,
        orThunk: call,
        map: none,
        each: noop,
        bind: none,
        exists: never,
        forall: always,
        filter: none,
        equals: eq,
        equals_: eq,
        toArray: function () {
          return [];
        },
        toString: constant('none()')
      };
      if (Object.freeze) {
        Object.freeze(me);
      }
      return me;
    }();
    var some = function (a) {
      var constant_a = constant(a);
      var self = function () {
        return me;
      };
      var bind = function (f) {
        return f(a);
      };
      var me = {
        fold: function (n, s) {
          return s(a);
        },
        is: function (v) {
          return a === v;
        },
        isSome: always,
        isNone: never,
        getOr: constant_a,
        getOrThunk: constant_a,
        getOrDie: constant_a,
        getOrNull: constant_a,
        getOrUndefined: constant_a,
        or: self,
        orThunk: self,
        map: function (f) {
          return some(f(a));
        },
        each: function (f) {
          f(a);
        },
        bind: bind,
        exists: bind,
        forall: bind,
        filter: function (f) {
          return f(a) ? me : NONE;
        },
        toArray: function () {
          return [a];
        },
        toString: function () {
          return 'some(' + a + ')';
        },
        equals: function (o) {
          return o.is(a);
        },
        equals_: function (o, elementEq) {
          return o.fold(never, function (b) {
            return elementEq(a, b);
          });
        }
      };
      return me;
    };
    var from = function (value) {
      return value === null || value === undefined ? NONE : some(value);
    };
    var Option = {
      some: some,
      none: none,
      from: from
    };

    var typeOf = function (x) {
      if (x === null) {
        return 'null';
      }
      var t = typeof x;
      if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
        return 'array';
      }
      if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
        return 'string';
      }
      return t;
    };
    var isType = function (type) {
      return function (value) {
        return typeOf(value) === type;
      };
    };
    var isString = isType('string');
    var isArray = isType('array');
    var isBoolean = isType('boolean');
    var isFunction = isType('function');
    var isNumber = isType('number');

    var nativeSlice = Array.prototype.slice;
    var nativeIndexOf = Array.prototype.indexOf;
    var nativePush = Array.prototype.push;
    var rawIndexOf = function (ts, t) {
      return nativeIndexOf.call(ts, t);
    };
    var contains = function (xs, x) {
      return rawIndexOf(xs, x) > -1;
    };
    var exists = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return true;
        }
      }
      return false;
    };
    var map = function (xs, f) {
      var len = xs.length;
      var r = new Array(len);
      for (var i = 0; i < len; i++) {
        var x = xs[i];
        r[i] = f(x, i);
      }
      return r;
    };
    var each = function (xs, f) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        f(x, i);
      }
    };
    var eachr = function (xs, f) {
      for (var i = xs.length - 1; i >= 0; i--) {
        var x = xs[i];
        f(x, i);
      }
    };
    var filter = function (xs, pred) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          r.push(x);
        }
      }
      return r;
    };
    var foldr = function (xs, f, acc) {
      eachr(xs, function (x) {
        acc = f(acc, x);
      });
      return acc;
    };
    var foldl = function (xs, f, acc) {
      each(xs, function (x) {
        acc = f(acc, x);
      });
      return acc;
    };
    var find = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return Option.some(x);
        }
      }
      return Option.none();
    };
    var findIndex = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return Option.some(i);
        }
      }
      return Option.none();
    };
    var flatten = function (xs) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; ++i) {
        if (!isArray(xs[i])) {
          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
        }
        nativePush.apply(r, xs[i]);
      }
      return r;
    };
    var bind = function (xs, f) {
      var output = map(xs, f);
      return flatten(output);
    };
    var forall = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; ++i) {
        var x = xs[i];
        if (pred(x, i) !== true) {
          return false;
        }
      }
      return true;
    };
    var reverse = function (xs) {
      var r = nativeSlice.call(xs, 0);
      r.reverse();
      return r;
    };
    var last = function (xs) {
      return xs.length === 0 ? Option.none() : Option.some(xs[xs.length - 1]);
    };
    var from$1 = isFunction(Array.from) ? Array.from : function (x) {
      return nativeSlice.call(x);
    };

    var keys = Object.keys;
    var each$1 = function (obj, f) {
      var props = keys(obj);
      for (var k = 0, len = props.length; k < len; k++) {
        var i = props[k];
        var x = obj[i];
        f(x, i);
      }
    };
    var map$1 = function (obj, f) {
      return tupleMap(obj, function (x, i) {
        return {
          k: i,
          v: f(x, i)
        };
      });
    };
    var tupleMap = function (obj, f) {
      var r = {};
      each$1(obj, function (x, i) {
        var tuple = f(x, i);
        r[tuple.k] = tuple.v;
      });
      return r;
    };

    var Immutable = function () {
      var fields = [];
      for (var _i = 0; _i < arguments.length; _i++) {
        fields[_i] = arguments[_i];
      }
      return function () {
        var values = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          values[_i] = arguments[_i];
        }
        if (fields.length !== values.length) {
          throw new Error('Wrong number of arguments to struct. Expected "[' + fields.length + ']", got ' + values.length + ' arguments');
        }
        var struct = {};
        each(fields, function (name, i) {
          struct[name] = constant(values[i]);
        });
        return struct;
      };
    };

    var sort = function (arr) {
      return arr.slice(0).sort();
    };
    var reqMessage = function (required, keys) {
      throw new Error('All required keys (' + sort(required).join(', ') + ') were not specified. Specified keys were: ' + sort(keys).join(', ') + '.');
    };
    var unsuppMessage = function (unsupported) {
      throw new Error('Unsupported keys for object: ' + sort(unsupported).join(', '));
    };
    var validateStrArr = function (label, array) {
      if (!isArray(array)) {
        throw new Error('The ' + label + ' fields must be an array. Was: ' + array + '.');
      }
      each(array, function (a) {
        if (!isString(a)) {
          throw new Error('The value ' + a + ' in the ' + label + ' fields was not a string.');
        }
      });
    };
    var invalidTypeMessage = function (incorrect, type) {
      throw new Error('All values need to be of type: ' + type + '. Keys (' + sort(incorrect).join(', ') + ') were not.');
    };
    var checkDupes = function (everything) {
      var sorted = sort(everything);
      var dupe = find(sorted, function (s, i) {
        return i < sorted.length - 1 && s === sorted[i + 1];
      });
      dupe.each(function (d) {
        throw new Error('The field: ' + d + ' occurs more than once in the combined fields: [' + sorted.join(', ') + '].');
      });
    };

    var MixedBag = function (required, optional) {
      var everything = required.concat(optional);
      if (everything.length === 0) {
        throw new Error('You must specify at least one required or optional field.');
      }
      validateStrArr('required', required);
      validateStrArr('optional', optional);
      checkDupes(everything);
      return function (obj) {
        var keys$1 = keys(obj);
        var allReqd = forall(required, function (req) {
          return contains(keys$1, req);
        });
        if (!allReqd) {
          reqMessage(required, keys$1);
        }
        var unsupported = filter(keys$1, function (key) {
          return !contains(everything, key);
        });
        if (unsupported.length > 0) {
          unsuppMessage(unsupported);
        }
        var r = {};
        each(required, function (req) {
          r[req] = constant(obj[req]);
        });
        each(optional, function (opt) {
          r[opt] = constant(Object.prototype.hasOwnProperty.call(obj, opt) ? Option.some(obj[opt]) : Option.none());
        });
        return r;
      };
    };

    var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE;
    var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE;
    var COMMENT = domGlobals.Node.COMMENT_NODE;
    var DOCUMENT = domGlobals.Node.DOCUMENT_NODE;
    var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE;
    var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE;
    var ELEMENT = domGlobals.Node.ELEMENT_NODE;
    var TEXT = domGlobals.Node.TEXT_NODE;
    var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE;
    var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE;
    var ENTITY = domGlobals.Node.ENTITY_NODE;
    var NOTATION = domGlobals.Node.NOTATION_NODE;

    var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();

    var path = function (parts, scope) {
      var o = scope !== undefined && scope !== null ? scope : Global;
      for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
        o = o[parts[i]];
      }
      return o;
    };
    var resolve = function (p, scope) {
      var parts = p.split('.');
      return path(parts, scope);
    };

    var unsafe = function (name, scope) {
      return resolve(name, scope);
    };
    var getOrDie = function (name, scope) {
      var actual = unsafe(name, scope);
      if (actual === undefined || actual === null) {
        throw new Error(name + ' not available on this browser');
      }
      return actual;
    };
    var Global$1 = { getOrDie: getOrDie };

    var name = function (element) {
      var r = element.dom().nodeName;
      return r.toLowerCase();
    };
    var type = function (element) {
      return element.dom().nodeType;
    };
    var isType$1 = function (t) {
      return function (element) {
        return type(element) === t;
      };
    };
    var isComment = function (element) {
      return type(element) === COMMENT || name(element) === '#comment';
    };
    var isElement = isType$1(ELEMENT);
    var isText = isType$1(TEXT);

    var rawSet = function (dom, key, value) {
      if (isString(value) || isBoolean(value) || isNumber(value)) {
        dom.setAttribute(key, value + '');
      } else {
        domGlobals.console.error('Invalid call to Attr.set. Key ', key, ':: Value ', value, ':: Element ', dom);
        throw new Error('Attribute value was not simple');
      }
    };
    var set = function (element, key, value) {
      rawSet(element.dom(), key, value);
    };
    var setAll = function (element, attrs) {
      var dom = element.dom();
      each$1(attrs, function (v, k) {
        rawSet(dom, k, v);
      });
    };
    var get = function (element, key) {
      var v = element.dom().getAttribute(key);
      return v === null ? undefined : v;
    };
    var has = function (element, key) {
      var dom = element.dom();
      return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
    };
    var remove = function (element, key) {
      element.dom().removeAttribute(key);
    };
    var clone = function (element) {
      return foldl(element.dom().attributes, function (acc, attr) {
        acc[attr.name] = attr.value;
        return acc;
      }, {});
    };

    var checkRange = function (str, substr, start) {
      if (substr === '') {
        return true;
      }
      if (str.length < substr.length) {
        return false;
      }
      var x = str.substr(start, start + substr.length);
      return x === substr;
    };
    var contains$1 = function (str, substr) {
      return str.indexOf(substr) !== -1;
    };
    var endsWith = function (str, suffix) {
      return checkRange(str, suffix, str.length - suffix.length);
    };
    var trim = function (str) {
      return str.replace(/^\s+|\s+$/g, '');
    };

    var isSupported = function (dom) {
      return dom.style !== undefined && isFunction(dom.style.getPropertyValue);
    };

    var cached = function (f) {
      var called = false;
      var r;
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        if (!called) {
          called = true;
          r = f.apply(null, args);
        }
        return r;
      };
    };

    var fromHtml = function (html, scope) {
      var doc = scope || domGlobals.document;
      var div = doc.createElement('div');
      div.innerHTML = html;
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
        domGlobals.console.error('HTML does not have a single root node', html);
        throw new Error('HTML must have a single root node');
      }
      return fromDom(div.childNodes[0]);
    };
    var fromTag = function (tag, scope) {
      var doc = scope || domGlobals.document;
      var node = doc.createElement(tag);
      return fromDom(node);
    };
    var fromText = function (text, scope) {
      var doc = scope || domGlobals.document;
      var node = doc.createTextNode(text);
      return fromDom(node);
    };
    var fromDom = function (node) {
      if (node === null || node === undefined) {
        throw new Error('Node cannot be null or undefined');
      }
      return { dom: constant(node) };
    };
    var fromPoint = function (docElm, x, y) {
      var doc = docElm.dom();
      return Option.from(doc.elementFromPoint(x, y)).map(fromDom);
    };
    var Element = {
      fromHtml: fromHtml,
      fromTag: fromTag,
      fromText: fromText,
      fromDom: fromDom,
      fromPoint: fromPoint
    };

    var inBody = function (element) {
      var dom = isText(element) ? element.dom().parentNode : element.dom();
      return dom !== undefined && dom !== null && dom.ownerDocument.body.contains(dom);
    };
    var body = cached(function () {
      return getBody(Element.fromDom(domGlobals.document));
    });
    var getBody = function (doc) {
      var b = doc.dom().body;
      if (b === null || b === undefined) {
        throw new Error('Body is not available yet');
      }
      return Element.fromDom(b);
    };

    var internalSet = function (dom, property, value) {
      if (!isString(value)) {
        domGlobals.console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
        throw new Error('CSS value must be a string: ' + value);
      }
      if (isSupported(dom)) {
        dom.style.setProperty(property, value);
      }
    };
    var internalRemove = function (dom, property) {
      if (isSupported(dom)) {
        dom.style.removeProperty(property);
      }
    };
    var set$1 = function (element, property, value) {
      var dom = element.dom();
      internalSet(dom, property, value);
    };
    var setAll$1 = function (element, css) {
      var dom = element.dom();
      each$1(css, function (v, k) {
        internalSet(dom, k, v);
      });
    };
    var get$1 = function (element, property) {
      var dom = element.dom();
      var styles = domGlobals.window.getComputedStyle(dom);
      var r = styles.getPropertyValue(property);
      var v = r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
      return v === null ? undefined : v;
    };
    var getUnsafeProperty = function (dom, property) {
      return isSupported(dom) ? dom.style.getPropertyValue(property) : '';
    };
    var getRaw = function (element, property) {
      var dom = element.dom();
      var raw = getUnsafeProperty(dom, property);
      return Option.from(raw).filter(function (r) {
        return r.length > 0;
      });
    };
    var remove$1 = function (element, property) {
      var dom = element.dom();
      internalRemove(dom, property);
      if (has(element, 'style') && trim(get(element, 'style')) === '') {
        remove(element, 'style');
      }
    };
    var copy = function (source, target) {
      var sourceDom = source.dom();
      var targetDom = target.dom();
      if (isSupported(sourceDom) && isSupported(targetDom)) {
        targetDom.style.cssText = sourceDom.style.cssText;
      }
    };

    var node = function () {
      var f = Global$1.getOrDie('Node');
      return f;
    };
    var compareDocumentPosition = function (a, b, match) {
      return (a.compareDocumentPosition(b) & match) !== 0;
    };
    var documentPositionPreceding = function (a, b) {
      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_PRECEDING);
    };
    var documentPositionContainedBy = function (a, b) {
      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_CONTAINED_BY);
    };
    var Node = {
      documentPositionPreceding: documentPositionPreceding,
      documentPositionContainedBy: documentPositionContainedBy
    };

    var firstMatch = function (regexes, s) {
      for (var i = 0; i < regexes.length; i++) {
        var x = regexes[i];
        if (x.test(s)) {
          return x;
        }
      }
      return undefined;
    };
    var find$1 = function (regexes, agent) {
      var r = firstMatch(regexes, agent);
      if (!r) {
        return {
          major: 0,
          minor: 0
        };
      }
      var group = function (i) {
        return Number(agent.replace(r, '$' + i));
      };
      return nu(group(1), group(2));
    };
    var detect = function (versionRegexes, agent) {
      var cleanedAgent = String(agent).toLowerCase();
      if (versionRegexes.length === 0) {
        return unknown();
      }
      return find$1(versionRegexes, cleanedAgent);
    };
    var unknown = function () {
      return nu(0, 0);
    };
    var nu = function (major, minor) {
      return {
        major: major,
        minor: minor
      };
    };
    var Version = {
      nu: nu,
      detect: detect,
      unknown: unknown
    };

    var edge = 'Edge';
    var chrome = 'Chrome';
    var ie = 'IE';
    var opera = 'Opera';
    var firefox = 'Firefox';
    var safari = 'Safari';
    var isBrowser = function (name, current) {
      return function () {
        return current === name;
      };
    };
    var unknown$1 = function () {
      return nu$1({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$1 = function (info) {
      var current = info.current;
      var version = info.version;
      return {
        current: current,
        version: version,
        isEdge: isBrowser(edge, current),
        isChrome: isBrowser(chrome, current),
        isIE: isBrowser(ie, current),
        isOpera: isBrowser(opera, current),
        isFirefox: isBrowser(firefox, current),
        isSafari: isBrowser(safari, current)
      };
    };
    var Browser = {
      unknown: unknown$1,
      nu: nu$1,
      edge: constant(edge),
      chrome: constant(chrome),
      ie: constant(ie),
      opera: constant(opera),
      firefox: constant(firefox),
      safari: constant(safari)
    };

    var windows = 'Windows';
    var ios = 'iOS';
    var android = 'Android';
    var linux = 'Linux';
    var osx = 'OSX';
    var solaris = 'Solaris';
    var freebsd = 'FreeBSD';
    var isOS = function (name, current) {
      return function () {
        return current === name;
      };
    };
    var unknown$2 = function () {
      return nu$2({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$2 = function (info) {
      var current = info.current;
      var version = info.version;
      return {
        current: current,
        version: version,
        isWindows: isOS(windows, current),
        isiOS: isOS(ios, current),
        isAndroid: isOS(android, current),
        isOSX: isOS(osx, current),
        isLinux: isOS(linux, current),
        isSolaris: isOS(solaris, current),
        isFreeBSD: isOS(freebsd, current)
      };
    };
    var OperatingSystem = {
      unknown: unknown$2,
      nu: nu$2,
      windows: constant(windows),
      ios: constant(ios),
      android: constant(android),
      linux: constant(linux),
      osx: constant(osx),
      solaris: constant(solaris),
      freebsd: constant(freebsd)
    };

    var DeviceType = function (os, browser, userAgent) {
      var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
      var isiPhone = os.isiOS() && !isiPad;
      var isAndroid3 = os.isAndroid() && os.version.major === 3;
      var isAndroid4 = os.isAndroid() && os.version.major === 4;
      var isTablet = isiPad || isAndroid3 || isAndroid4 && /mobile/i.test(userAgent) === true;
      var isTouch = os.isiOS() || os.isAndroid();
      var isPhone = isTouch && !isTablet;
      var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
      return {
        isiPad: constant(isiPad),
        isiPhone: constant(isiPhone),
        isTablet: constant(isTablet),
        isPhone: constant(isPhone),
        isTouch: constant(isTouch),
        isAndroid: os.isAndroid,
        isiOS: os.isiOS,
        isWebView: constant(iOSwebview)
      };
    };

    var detect$1 = function (candidates, userAgent) {
      var agent = String(userAgent).toLowerCase();
      return find(candidates, function (candidate) {
        return candidate.search(agent);
      });
    };
    var detectBrowser = function (browsers, userAgent) {
      return detect$1(browsers, userAgent).map(function (browser) {
        var version = Version.detect(browser.versionRegexes, userAgent);
        return {
          current: browser.name,
          version: version
        };
      });
    };
    var detectOs = function (oses, userAgent) {
      return detect$1(oses, userAgent).map(function (os) {
        var version = Version.detect(os.versionRegexes, userAgent);
        return {
          current: os.name,
          version: version
        };
      });
    };
    var UaString = {
      detectBrowser: detectBrowser,
      detectOs: detectOs
    };

    var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
    var checkContains = function (target) {
      return function (uastring) {
        return contains$1(uastring, target);
      };
    };
    var browsers = [
      {
        name: 'Edge',
        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
        search: function (uastring) {
          return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit');
        }
      },
      {
        name: 'Chrome',
        versionRegexes: [
          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
          normalVersionRegex
        ],
        search: function (uastring) {
          return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe');
        }
      },
      {
        name: 'IE',
        versionRegexes: [
          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
          /.*?rv:([0-9]+)\.([0-9]+).*/
        ],
        search: function (uastring) {
          return contains$1(uastring, 'msie') || contains$1(uastring, 'trident');
        }
      },
      {
        name: 'Opera',
        versionRegexes: [
          normalVersionRegex,
          /.*?opera\/([0-9]+)\.([0-9]+).*/
        ],
        search: checkContains('opera')
      },
      {
        name: 'Firefox',
        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
        search: checkContains('firefox')
      },
      {
        name: 'Safari',
        versionRegexes: [
          normalVersionRegex,
          /.*?cpu os ([0-9]+)_([0-9]+).*/
        ],
        search: function (uastring) {
          return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit');
        }
      }
    ];
    var oses = [
      {
        name: 'Windows',
        search: checkContains('win'),
        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'iOS',
        search: function (uastring) {
          return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad');
        },
        versionRegexes: [
          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
          /.*cpu os ([0-9]+)_([0-9]+).*/,
          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
        ]
      },
      {
        name: 'Android',
        search: checkContains('android'),
        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'OSX',
        search: checkContains('os x'),
        versionRegexes: [/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]
      },
      {
        name: 'Linux',
        search: checkContains('linux'),
        versionRegexes: []
      },
      {
        name: 'Solaris',
        search: checkContains('sunos'),
        versionRegexes: []
      },
      {
        name: 'FreeBSD',
        search: checkContains('freebsd'),
        versionRegexes: []
      }
    ];
    var PlatformInfo = {
      browsers: constant(browsers),
      oses: constant(oses)
    };

    var detect$2 = function (userAgent) {
      var browsers = PlatformInfo.browsers();
      var oses = PlatformInfo.oses();
      var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu);
      var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
      var deviceType = DeviceType(os, browser, userAgent);
      return {
        browser: browser,
        os: os,
        deviceType: deviceType
      };
    };
    var PlatformDetection = { detect: detect$2 };

    var detect$3 = cached(function () {
      var userAgent = domGlobals.navigator.userAgent;
      return PlatformDetection.detect(userAgent);
    });
    var PlatformDetection$1 = { detect: detect$3 };

    var ELEMENT$1 = ELEMENT;
    var DOCUMENT$1 = DOCUMENT;
    var is = function (element, selector) {
      var dom = element.dom();
      if (dom.nodeType !== ELEMENT$1) {
        return false;
      } else {
        var elem = dom;
        if (elem.matches !== undefined) {
          return elem.matches(selector);
        } else if (elem.msMatchesSelector !== undefined) {
          return elem.msMatchesSelector(selector);
        } else if (elem.webkitMatchesSelector !== undefined) {
          return elem.webkitMatchesSelector(selector);
        } else if (elem.mozMatchesSelector !== undefined) {
          return elem.mozMatchesSelector(selector);
        } else {
          throw new Error('Browser lacks native selectors');
        }
      }
    };
    var bypassSelector = function (dom) {
      return dom.nodeType !== ELEMENT$1 && dom.nodeType !== DOCUMENT$1 || dom.childElementCount === 0;
    };
    var all = function (selector, scope) {
      var base = scope === undefined ? domGlobals.document : scope.dom();
      return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), Element.fromDom);
    };
    var one = function (selector, scope) {
      var base = scope === undefined ? domGlobals.document : scope.dom();
      return bypassSelector(base) ? Option.none() : Option.from(base.querySelector(selector)).map(Element.fromDom);
    };

    var eq = function (e1, e2) {
      return e1.dom() === e2.dom();
    };
    var regularContains = function (e1, e2) {
      var d1 = e1.dom();
      var d2 = e2.dom();
      return d1 === d2 ? false : d1.contains(d2);
    };
    var ieContains = function (e1, e2) {
      return Node.documentPositionContainedBy(e1.dom(), e2.dom());
    };
    var browser = PlatformDetection$1.detect().browser;
    var contains$2 = browser.isIE() ? ieContains : regularContains;
    var is$1 = is;

    var owner = function (element) {
      return Element.fromDom(element.dom().ownerDocument);
    };
    var defaultView = function (element) {
      return Element.fromDom(element.dom().ownerDocument.defaultView);
    };
    var parent = function (element) {
      return Option.from(element.dom().parentNode).map(Element.fromDom);
    };
    var parents = function (element, isRoot) {
      var stop = isFunction(isRoot) ? isRoot : never;
      var dom = element.dom();
      var ret = [];
      while (dom.parentNode !== null && dom.parentNode !== undefined) {
        var rawParent = dom.parentNode;
        var p = Element.fromDom(rawParent);
        ret.push(p);
        if (stop(p) === true) {
          break;
        } else {
          dom = rawParent;
        }
      }
      return ret;
    };
    var prevSibling = function (element) {
      return Option.from(element.dom().previousSibling).map(Element.fromDom);
    };
    var nextSibling = function (element) {
      return Option.from(element.dom().nextSibling).map(Element.fromDom);
    };
    var children = function (element) {
      return map(element.dom().childNodes, Element.fromDom);
    };
    var child = function (element, index) {
      var cs = element.dom().childNodes;
      return Option.from(cs[index]).map(Element.fromDom);
    };
    var firstChild = function (element) {
      return child(element, 0);
    };
    var spot = Immutable('element', 'offset');

    var before = function (marker, element) {
      var parent$1 = parent(marker);
      parent$1.each(function (v) {
        v.dom().insertBefore(element.dom(), marker.dom());
      });
    };
    var after = function (marker, element) {
      var sibling = nextSibling(marker);
      sibling.fold(function () {
        var parent$1 = parent(marker);
        parent$1.each(function (v) {
          append(v, element);
        });
      }, function (v) {
        before(v, element);
      });
    };
    var prepend = function (parent, element) {
      var firstChild$1 = firstChild(parent);
      firstChild$1.fold(function () {
        append(parent, element);
      }, function (v) {
        parent.dom().insertBefore(element.dom(), v.dom());
      });
    };
    var append = function (parent, element) {
      parent.dom().appendChild(element.dom());
    };
    var wrap = function (element, wrapper) {
      before(element, wrapper);
      append(wrapper, element);
    };

    var before$1 = function (marker, elements) {
      each(elements, function (x) {
        before(marker, x);
      });
    };
    var after$1 = function (marker, elements) {
      each(elements, function (x, i) {
        var e = i === 0 ? marker : elements[i - 1];
        after(e, x);
      });
    };
    var append$1 = function (parent, elements) {
      each(elements, function (x) {
        append(parent, x);
      });
    };

    var empty = function (element) {
      element.dom().textContent = '';
      each(children(element), function (rogue) {
        remove$2(rogue);
      });
    };
    var remove$2 = function (element) {
      var dom = element.dom();
      if (dom.parentNode !== null) {
        dom.parentNode.removeChild(dom);
      }
    };
    var unwrap = function (wrapper) {
      var children$1 = children(wrapper);
      if (children$1.length > 0) {
        before$1(wrapper, children$1);
      }
      remove$2(wrapper);
    };

    var dimension = Immutable('width', 'height');
    var dimensions = Immutable('width', 'height');
    var grid = Immutable('rows', 'columns');
    var address = Immutable('row', 'column');
    var coords = Immutable('x', 'y');
    var detail = Immutable('element', 'rowspan', 'colspan');
    var detailnew = Immutable('element', 'rowspan', 'colspan', 'isNew');
    var extended = Immutable('element', 'rowspan', 'colspan', 'row', 'column');
    var rowdata = Immutable('element', 'cells', 'section');
    var elementnew = Immutable('element', 'isNew');
    var rowdatanew = Immutable('element', 'cells', 'section', 'isNew');
    var rowcells = Immutable('cells', 'section');
    var rowdetails = Immutable('details', 'section');
    var bounds = Immutable('startRow', 'startCol', 'finishRow', 'finishCol');

    var ancestors = function (scope, predicate, isRoot) {
      return filter(parents(scope, isRoot), predicate);
    };
    var children$1 = function (scope, predicate) {
      return filter(children(scope), predicate);
    };
    var descendants = function (scope, predicate) {
      var result = [];
      each(children(scope), function (x) {
        if (predicate(x)) {
          result = result.concat([x]);
        }
        result = result.concat(descendants(x, predicate));
      });
      return result;
    };

    var ancestors$1 = function (scope, selector, isRoot) {
      return ancestors(scope, function (e) {
        return is(e, selector);
      }, isRoot);
    };
    var children$2 = function (scope, selector) {
      return children$1(scope, function (e) {
        return is(e, selector);
      });
    };
    var descendants$1 = function (scope, selector) {
      return all(selector, scope);
    };

    function ClosestOrAncestor (is, ancestor, scope, a, isRoot) {
      return is(scope, a) ? Option.some(scope) : isFunction(isRoot) && isRoot(scope) ? Option.none() : ancestor(scope, a, isRoot);
    }

    var ancestor = function (scope, predicate, isRoot) {
      var element = scope.dom();
      var stop = isFunction(isRoot) ? isRoot : constant(false);
      while (element.parentNode) {
        element = element.parentNode;
        var el = Element.fromDom(element);
        if (predicate(el)) {
          return Option.some(el);
        } else if (stop(el)) {
          break;
        }
      }
      return Option.none();
    };
    var closest = function (scope, predicate, isRoot) {
      var is = function (s, test) {
        return test(s);
      };
      return ClosestOrAncestor(is, ancestor, scope, predicate, isRoot);
    };
    var child$1 = function (scope, predicate) {
      var pred = function (node) {
        return predicate(Element.fromDom(node));
      };
      var result = find(scope.dom().childNodes, pred);
      return result.map(Element.fromDom);
    };
    var descendant = function (scope, predicate) {
      var descend = function (node) {
        for (var i = 0; i < node.childNodes.length; i++) {
          var child_1 = Element.fromDom(node.childNodes[i]);
          if (predicate(child_1)) {
            return Option.some(child_1);
          }
          var res = descend(node.childNodes[i]);
          if (res.isSome()) {
            return res;
          }
        }
        return Option.none();
      };
      return descend(scope.dom());
    };

    var ancestor$1 = function (scope, selector, isRoot) {
      return ancestor(scope, function (e) {
        return is(e, selector);
      }, isRoot);
    };
    var child$2 = function (scope, selector) {
      return child$1(scope, function (e) {
        return is(e, selector);
      });
    };
    var descendant$1 = function (scope, selector) {
      return one(selector, scope);
    };
    var closest$1 = function (scope, selector, isRoot) {
      return ClosestOrAncestor(is, ancestor$1, scope, selector, isRoot);
    };

    var firstLayer = function (scope, selector) {
      return filterFirstLayer(scope, selector, constant(true));
    };
    var filterFirstLayer = function (scope, selector, predicate) {
      return bind(children(scope), function (x) {
        return is(x, selector) ? predicate(x) ? [x] : [] : filterFirstLayer(x, selector, predicate);
      });
    };
    var LayerSelector = {
      firstLayer: firstLayer,
      filterFirstLayer: filterFirstLayer
    };

    var lookup = function (tags, element, isRoot) {
      if (isRoot === void 0) {
        isRoot = never;
      }
      if (isRoot(element)) {
        return Option.none();
      }
      if (contains(tags, name(element))) {
        return Option.some(element);
      }
      var isRootOrUpperTable = function (elm) {
        return is(elm, 'table') || isRoot(elm);
      };
      return ancestor$1(element, tags.join(','), isRootOrUpperTable);
    };
    var cell = function (element, isRoot) {
      return lookup([
        'td',
        'th'
      ], element, isRoot);
    };
    var cells = function (ancestor) {
      return LayerSelector.firstLayer(ancestor, 'th,td');
    };
    var notCell = function (element, isRoot) {
      return lookup([
        'caption',
        'tr',
        'tbody',
        'tfoot',
        'thead'
      ], element, isRoot);
    };
    var neighbours = function (selector, element) {
      return parent(element).map(function (parent) {
        return children$2(parent, selector);
      });
    };
    var neighbourCells = curry(neighbours, 'th,td');
    var neighbourRows = curry(neighbours, 'tr');
    var firstCell = function (ancestor) {
      return descendant$1(ancestor, 'th,td');
    };
    var table = function (element, isRoot) {
      return closest$1(element, 'table', isRoot);
    };
    var row = function (element, isRoot) {
      return lookup(['tr'], element, isRoot);
    };
    var rows = function (ancestor) {
      return LayerSelector.firstLayer(ancestor, 'tr');
    };
    var attr = function (element, property) {
      return parseInt(get(element, property), 10);
    };
    var grid$1 = function (element, rowProp, colProp) {
      var rowsCount = attr(element, rowProp);
      var cols = attr(element, colProp);
      return grid(rowsCount, cols);
    };
    var TableLookup = {
      cell: cell,
      firstCell: firstCell,
      cells: cells,
      neighbourCells: neighbourCells,
      table: table,
      row: row,
      rows: rows,
      notCell: notCell,
      neighbourRows: neighbourRows,
      attr: attr,
      grid: grid$1
    };

    var fromTable = function (table) {
      var rows = TableLookup.rows(table);
      return map(rows, function (row) {
        var element = row;
        var parent$1 = parent(element);
        var parentSection = parent$1.map(function (p) {
          var parentName = name(p);
          return parentName === 'tfoot' || parentName === 'thead' || parentName === 'tbody' ? parentName : 'tbody';
        }).getOr('tbody');
        var cells = map(TableLookup.cells(row), function (cell) {
          var rowspan = has(cell, 'rowspan') ? parseInt(get(cell, 'rowspan'), 10) : 1;
          var colspan = has(cell, 'colspan') ? parseInt(get(cell, 'colspan'), 10) : 1;
          return detail(cell, rowspan, colspan);
        });
        return rowdata(element, cells, parentSection);
      });
    };
    var fromPastedRows = function (rows, example) {
      return map(rows, function (row) {
        var cells = map(TableLookup.cells(row), function (cell) {
          var rowspan = has(cell, 'rowspan') ? parseInt(get(cell, 'rowspan'), 10) : 1;
          var colspan = has(cell, 'colspan') ? parseInt(get(cell, 'colspan'), 10) : 1;
          return detail(cell, rowspan, colspan);
        });
        return rowdata(row, cells, example.section());
      });
    };
    var DetailsList = {
      fromTable: fromTable,
      fromPastedRows: fromPastedRows
    };

    var key = function (row, column) {
      return row + ',' + column;
    };
    var getAt = function (warehouse, row, column) {
      var raw = warehouse.access()[key(row, column)];
      return raw !== undefined ? Option.some(raw) : Option.none();
    };
    var findItem = function (warehouse, item, comparator) {
      var filtered = filterItems(warehouse, function (detail) {
        return comparator(item, detail.element());
      });
      return filtered.length > 0 ? Option.some(filtered[0]) : Option.none();
    };
    var filterItems = function (warehouse, predicate) {
      var all = bind(warehouse.all(), function (r) {
        return r.cells();
      });
      return filter(all, predicate);
    };
    var generate = function (list) {
      var access = {};
      var cells = [];
      var maxRows = list.length;
      var maxColumns = 0;
      each(list, function (details, r) {
        var currentRow = [];
        each(details.cells(), function (detail) {
          var start = 0;
          while (access[key(r, start)] !== undefined) {
            start++;
          }
          var current = extended(detail.element(), detail.rowspan(), detail.colspan(), r, start);
          for (var i = 0; i < detail.colspan(); i++) {
            for (var j = 0; j < detail.rowspan(); j++) {
              var cr = r + j;
              var cc = start + i;
              var newpos = key(cr, cc);
              access[newpos] = current;
              maxColumns = Math.max(maxColumns, cc + 1);
            }
          }
          currentRow.push(current);
        });
        cells.push(rowdata(details.element(), currentRow, details.section()));
      });
      var grid$1 = grid(maxRows, maxColumns);
      return {
        grid: constant(grid$1),
        access: constant(access),
        all: constant(cells)
      };
    };
    var justCells = function (warehouse) {
      var rows = map(warehouse.all(), function (w) {
        return w.cells();
      });
      return flatten(rows);
    };
    var Warehouse = {
      generate: generate,
      getAt: getAt,
      findItem: findItem,
      filterItems: filterItems,
      justCells: justCells
    };

    var statsStruct = Immutable('minRow', 'minCol', 'maxRow', 'maxCol');
    var findSelectedStats = function (house, isSelected) {
      var totalColumns = house.grid().columns();
      var totalRows = house.grid().rows();
      var minRow = totalRows;
      var minCol = totalColumns;
      var maxRow = 0;
      var maxCol = 0;
      each$1(house.access(), function (detail) {
        if (isSelected(detail)) {
          var startRow = detail.row();
          var endRow = startRow + detail.rowspan() - 1;
          var startCol = detail.column();
          var endCol = startCol + detail.colspan() - 1;
          if (startRow < minRow) {
            minRow = startRow;
          } else if (endRow > maxRow) {
            maxRow = endRow;
          }
          if (startCol < minCol) {
            minCol = startCol;
          } else if (endCol > maxCol) {
            maxCol = endCol;
          }
        }
      });
      return statsStruct(minRow, minCol, maxRow, maxCol);
    };
    var makeCell = function (list, seenSelected, rowIndex) {
      var row = list[rowIndex].element();
      var td = Element.fromTag('td');
      append(td, Element.fromTag('br'));
      var f = seenSelected ? append : prepend;
      f(row, td);
    };
    var fillInGaps = function (list, house, stats, isSelected) {
      var totalColumns = house.grid().columns();
      var totalRows = house.grid().rows();
      for (var i = 0; i < totalRows; i++) {
        var seenSelected = false;
        for (var j = 0; j < totalColumns; j++) {
          if (!(i < stats.minRow() || i > stats.maxRow() || j < stats.minCol() || j > stats.maxCol())) {
            var needCell = Warehouse.getAt(house, i, j).filter(isSelected).isNone();
            if (needCell) {
              makeCell(list, seenSelected, i);
            } else {
              seenSelected = true;
            }
          }
        }
      }
    };
    var clean = function (table, stats) {
      var emptyRows = filter(LayerSelector.firstLayer(table, 'tr'), function (row) {
        return row.dom().childElementCount === 0;
      });
      each(emptyRows, remove$2);
      if (stats.minCol() === stats.maxCol() || stats.minRow() === stats.maxRow()) {
        each(LayerSelector.firstLayer(table, 'th,td'), function (cell) {
          remove(cell, 'rowspan');
          remove(cell, 'colspan');
        });
      }
      remove(table, 'width');
      remove(table, 'height');
      remove$1(table, 'width');
      remove$1(table, 'height');
    };
    var extract = function (table, selectedSelector) {
      var isSelected = function (detail) {
        return is(detail.element(), selectedSelector);
      };
      var list = DetailsList.fromTable(table);
      var house = Warehouse.generate(list);
      var stats = findSelectedStats(house, isSelected);
      var selector = 'th:not(' + selectedSelector + ')' + ',td:not(' + selectedSelector + ')';
      var unselectedCells = LayerSelector.filterFirstLayer(table, 'th,td', function (cell) {
        return is(cell, selector);
      });
      each(unselectedCells, remove$2);
      fillInGaps(list, house, stats, isSelected);
      clean(table, stats);
      return table;
    };
    var CopySelected = { extract: extract };

    function NodeValue (is, name) {
      var get = function (element) {
        if (!is(element)) {
          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
        }
        return getOption(element).getOr('');
      };
      var getOption = function (element) {
        return is(element) ? Option.from(element.dom().nodeValue) : Option.none();
      };
      var set = function (element, value) {
        if (!is(element)) {
          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
        }
        element.dom().nodeValue = value;
      };
      return {
        get: get,
        getOption: getOption,
        set: set
      };
    }

    var api = NodeValue(isText, 'text');
    var get$2 = function (element) {
      return api.get(element);
    };
    var getOption = function (element) {
      return api.getOption(element);
    };
    var set$2 = function (element, value) {
      api.set(element, value);
    };

    var getEnd = function (element) {
      return name(element) === 'img' ? 1 : getOption(element).fold(function () {
        return children(element).length;
      }, function (v) {
        return v.length;
      });
    };
    var NBSP = '\xA0';
    var isTextNodeWithCursorPosition = function (el) {
      return getOption(el).filter(function (text) {
        return text.trim().length !== 0 || text.indexOf(NBSP) > -1;
      }).isSome();
    };
    var elementsWithCursorPosition = [
      'img',
      'br'
    ];
    var isCursorPosition = function (elem) {
      var hasCursorPosition = isTextNodeWithCursorPosition(elem);
      return hasCursorPosition || contains(elementsWithCursorPosition, name(elem));
    };

    var first = function (element) {
      return descendant(element, isCursorPosition);
    };
    var last$1 = function (element) {
      return descendantRtl(element, isCursorPosition);
    };
    var descendantRtl = function (scope, predicate) {
      var descend = function (element) {
        var children$1 = children(element);
        for (var i = children$1.length - 1; i >= 0; i--) {
          var child = children$1[i];
          if (predicate(child)) {
            return Option.some(child);
          }
          var res = descend(child);
          if (res.isSome()) {
            return res;
          }
        }
        return Option.none();
      };
      return descend(scope);
    };

    var clone$1 = function (original, isDeep) {
      return Element.fromDom(original.dom().cloneNode(isDeep));
    };
    var shallow = function (original) {
      return clone$1(original, false);
    };
    var deep = function (original) {
      return clone$1(original, true);
    };
    var shallowAs = function (original, tag) {
      var nu = Element.fromTag(tag);
      var attributes = clone(original);
      setAll(nu, attributes);
      return nu;
    };
    var copy$1 = function (original, tag) {
      var nu = shallowAs(original, tag);
      var cloneChildren = children(deep(original));
      append$1(nu, cloneChildren);
      return nu;
    };

    var createCell = function () {
      var td = Element.fromTag('td');
      append(td, Element.fromTag('br'));
      return td;
    };
    var replace = function (cell, tag, attrs) {
      var replica = copy$1(cell, tag);
      each$1(attrs, function (v, k) {
        if (v === null) {
          remove(replica, k);
        } else {
          set(replica, k, v);
        }
      });
      return replica;
    };
    var pasteReplace = function (cell) {
      return cell;
    };
    var newRow = function (doc) {
      return function () {
        return Element.fromTag('tr', doc.dom());
      };
    };
    var cloneFormats = function (oldCell, newCell, formats) {
      var first$1 = first(oldCell);
      return first$1.map(function (firstText) {
        var formatSelector = formats.join(',');
        var parents = ancestors$1(firstText, formatSelector, function (element) {
          return eq(element, oldCell);
        });
        return foldr(parents, function (last, parent) {
          var clonedFormat = shallow(parent);
          remove(clonedFormat, 'contenteditable');
          append(last, clonedFormat);
          return clonedFormat;
        }, newCell);
      }).getOr(newCell);
    };
    var cellOperations = function (mutate, doc, formatsToClone) {
      var newCell = function (prev) {
        var docu = owner(prev.element());
        var td = Element.fromTag(name(prev.element()), docu.dom());
        var formats = formatsToClone.getOr([
          'strong',
          'em',
          'b',
          'i',
          'span',
          'font',
          'h1',
          'h2',
          'h3',
          'h4',
          'h5',
          'h6',
          'p',
          'div'
        ]);
        var lastNode = formats.length > 0 ? cloneFormats(prev.element(), td, formats) : td;
        append(lastNode, Element.fromTag('br'));
        copy(prev.element(), td);
        remove$1(td, 'height');
        if (prev.colspan() !== 1) {
          remove$1(prev.element(), 'width');
        }
        mutate(prev.element(), td);
        return td;
      };
      return {
        row: newRow(doc),
        cell: newCell,
        replace: replace,
        gap: createCell
      };
    };
    var paste = function (doc) {
      return {
        row: newRow(doc),
        cell: createCell,
        replace: pasteReplace,
        gap: createCell
      };
    };
    var TableFill = {
      cellOperations: cellOperations,
      paste: paste
    };

    var fromHtml$1 = function (html, scope) {
      var doc = scope || domGlobals.document;
      var div = doc.createElement('div');
      div.innerHTML = html;
      return children(Element.fromDom(div));
    };

    var inSelection = function (bounds, detail) {
      var leftEdge = detail.column();
      var rightEdge = detail.column() + detail.colspan() - 1;
      var topEdge = detail.row();
      var bottomEdge = detail.row() + detail.rowspan() - 1;
      return leftEdge <= bounds.finishCol() && rightEdge >= bounds.startCol() && (topEdge <= bounds.finishRow() && bottomEdge >= bounds.startRow());
    };
    var isWithin = function (bounds, detail) {
      return detail.column() >= bounds.startCol() && detail.column() + detail.colspan() - 1 <= bounds.finishCol() && detail.row() >= bounds.startRow() && detail.row() + detail.rowspan() - 1 <= bounds.finishRow();
    };
    var isRectangular = function (warehouse, bounds) {
      var isRect = true;
      var detailIsWithin = curry(isWithin, bounds);
      for (var i = bounds.startRow(); i <= bounds.finishRow(); i++) {
        for (var j = bounds.startCol(); j <= bounds.finishCol(); j++) {
          isRect = isRect && Warehouse.getAt(warehouse, i, j).exists(detailIsWithin);
        }
      }
      return isRect ? Option.some(bounds) : Option.none();
    };
    var CellBounds = {
      inSelection: inSelection,
      isWithin: isWithin,
      isRectangular: isRectangular
    };

    var getBounds = function (detailA, detailB) {
      return bounds(Math.min(detailA.row(), detailB.row()), Math.min(detailA.column(), detailB.column()), Math.max(detailA.row() + detailA.rowspan() - 1, detailB.row() + detailB.rowspan() - 1), Math.max(detailA.column() + detailA.colspan() - 1, detailB.column() + detailB.colspan() - 1));
    };
    var getAnyBox = function (warehouse, startCell, finishCell) {
      var startCoords = Warehouse.findItem(warehouse, startCell, eq);
      var finishCoords = Warehouse.findItem(warehouse, finishCell, eq);
      return startCoords.bind(function (sc) {
        return finishCoords.map(function (fc) {
          return getBounds(sc, fc);
        });
      });
    };
    var getBox = function (warehouse, startCell, finishCell) {
      return getAnyBox(warehouse, startCell, finishCell).bind(function (bounds) {
        return CellBounds.isRectangular(warehouse, bounds);
      });
    };
    var CellGroup = {
      getAnyBox: getAnyBox,
      getBox: getBox
    };

    var moveBy = function (warehouse, cell, row, column) {
      return Warehouse.findItem(warehouse, cell, eq).bind(function (detail) {
        var startRow = row > 0 ? detail.row() + detail.rowspan() - 1 : detail.row();
        var startCol = column > 0 ? detail.column() + detail.colspan() - 1 : detail.column();
        var dest = Warehouse.getAt(warehouse, startRow + row, startCol + column);
        return dest.map(function (d) {
          return d.element();
        });
      });
    };
    var intercepts = function (warehouse, start, finish) {
      return CellGroup.getAnyBox(warehouse, start, finish).map(function (bounds) {
        var inside = Warehouse.filterItems(warehouse, curry(CellBounds.inSelection, bounds));
        return map(inside, function (detail) {
          return detail.element();
        });
      });
    };
    var parentCell = function (warehouse, innerCell) {
      var isContainedBy = function (c1, c2) {
        return contains$2(c2, c1);
      };
      return Warehouse.findItem(warehouse, innerCell, isContainedBy).map(function (detail) {
        return detail.element();
      });
    };
    var CellFinder = {
      moveBy: moveBy,
      intercepts: intercepts,
      parentCell: parentCell
    };

    var moveBy$1 = function (cell, deltaRow, deltaColumn) {
      return TableLookup.table(cell).bind(function (table) {
        var warehouse = getWarehouse(table);
        return CellFinder.moveBy(warehouse, cell, deltaRow, deltaColumn);
      });
    };
    var intercepts$1 = function (table, first, last) {
      var warehouse = getWarehouse(table);
      return CellFinder.intercepts(warehouse, first, last);
    };
    var nestedIntercepts = function (table, first, firstTable, last, lastTable) {
      var warehouse = getWarehouse(table);
      var optStartCell = eq(table, firstTable) ? Option.some(first) : CellFinder.parentCell(warehouse, first);
      var optLastCell = eq(table, lastTable) ? Option.some(last) : CellFinder.parentCell(warehouse, last);
      return optStartCell.bind(function (startCell) {
        return optLastCell.bind(function (lastCell) {
          return CellFinder.intercepts(warehouse, startCell, lastCell);
        });
      });
    };
    var getBox$1 = function (table, first, last) {
      var warehouse = getWarehouse(table);
      return CellGroup.getBox(warehouse, first, last);
    };
    var getWarehouse = function (table) {
      var list = DetailsList.fromTable(table);
      return Warehouse.generate(list);
    };
    var TablePositions = {
      moveBy: moveBy$1,
      intercepts: intercepts$1,
      nestedIntercepts: nestedIntercepts,
      getBox: getBox$1
    };

    var TagBoundaries = [
      'body',
      'p',
      'div',
      'article',
      'aside',
      'figcaption',
      'figure',
      'footer',
      'header',
      'nav',
      'section',
      'ol',
      'ul',
      'li',
      'table',
      'thead',
      'tbody',
      'tfoot',
      'caption',
      'tr',
      'td',
      'th',
      'h1',
      'h2',
      'h3',
      'h4',
      'h5',
      'h6',
      'blockquote',
      'pre',
      'address'
    ];

    function DomUniverse () {
      var clone$1 = function (element) {
        return Element.fromDom(element.dom().cloneNode(false));
      };
      var document = function (element) {
        return element.dom().ownerDocument;
      };
      var isBoundary = function (element) {
        if (!isElement(element)) {
          return false;
        }
        if (name(element) === 'body') {
          return true;
        }
        return contains(TagBoundaries, name(element));
      };
      var isEmptyTag = function (element) {
        if (!isElement(element)) {
          return false;
        }
        return contains([
          'br',
          'img',
          'hr',
          'input'
        ], name(element));
      };
      var comparePosition = function (element, other) {
        return element.dom().compareDocumentPosition(other.dom());
      };
      var copyAttributesTo = function (source, destination) {
        var as = clone(source);
        setAll(destination, as);
      };
      return {
        up: constant({
          selector: ancestor$1,
          closest: closest$1,
          predicate: ancestor,
          all: parents
        }),
        down: constant({
          selector: descendants$1,
          predicate: descendants
        }),
        styles: constant({
          get: get$1,
          getRaw: getRaw,
          set: set$1,
          remove: remove$1
        }),
        attrs: constant({
          get: get,
          set: set,
          remove: remove,
          copyTo: copyAttributesTo
        }),
        insert: constant({
          before: before,
          after: after,
          afterAll: after$1,
          append: append,
          appendAll: append$1,
          prepend: prepend,
          wrap: wrap
        }),
        remove: constant({
          unwrap: unwrap,
          remove: remove$2
        }),
        create: constant({
          nu: Element.fromTag,
          clone: clone$1,
          text: Element.fromText
        }),
        query: constant({
          comparePosition: comparePosition,
          prevSibling: prevSibling,
          nextSibling: nextSibling
        }),
        property: constant({
          children: children,
          name: name,
          parent: parent,
          document: document,
          isText: isText,
          isComment: isComment,
          isElement: isElement,
          getText: get$2,
          setText: set$2,
          isBoundary: isBoundary,
          isEmptyTag: isEmptyTag
        }),
        eq: eq,
        is: is$1
      };
    }

    var leftRight = Immutable('left', 'right');
    var brokenPath = Immutable('first', 'second', 'splits');
    var bisect = function (universe, parent, child) {
      var children = universe.property().children(parent);
      var index = findIndex(children, curry(universe.eq, child));
      return index.map(function (ind) {
        return {
          before: constant(children.slice(0, ind)),
          after: constant(children.slice(ind + 1))
        };
      });
    };
    var breakToRight = function (universe, parent, child) {
      return bisect(universe, parent, child).map(function (parts) {
        var second = universe.create().clone(parent);
        universe.insert().appendAll(second, parts.after());
        universe.insert().after(parent, second);
        return leftRight(parent, second);
      });
    };
    var breakToLeft = function (universe, parent, child) {
      return bisect(universe, parent, child).map(function (parts) {
        var prior = universe.create().clone(parent);
        universe.insert().appendAll(prior, parts.before().concat([child]));
        universe.insert().appendAll(parent, parts.after());
        universe.insert().before(parent, prior);
        return leftRight(prior, parent);
      });
    };
    var breakPath = function (universe, item, isTop, breaker) {
      var next = function (child, group, splits) {
        var fallback = brokenPath(child, Option.none(), splits);
        if (isTop(child)) {
          return brokenPath(child, group, splits);
        } else {
          return universe.property().parent(child).bind(function (parent) {
            return breaker(universe, parent, child).map(function (breakage) {
              var extra = [{
                  first: breakage.left,
                  second: breakage.right
                }];
              var nextChild = isTop(parent) ? parent : breakage.left();
              return next(nextChild, Option.some(breakage.right()), splits.concat(extra));
            });
          }).getOr(fallback);
        }
      };
      return next(item, Option.none(), []);
    };

    var all$1 = function (universe, look, elements, f) {
      var head = elements[0];
      var tail = elements.slice(1);
      return f(universe, look, head, tail);
    };
    var oneAll = function (universe, look, elements) {
      return elements.length > 0 ? all$1(universe, look, elements, unsafeOne) : Option.none();
    };
    var unsafeOne = function (universe, look, head, tail) {
      var start = look(universe, head);
      return foldr(tail, function (b, a) {
        var current = look(universe, a);
        return commonElement(universe, b, current);
      }, start);
    };
    var commonElement = function (universe, start, end) {
      return start.bind(function (s) {
        return end.filter(curry(universe.eq, s));
      });
    };

    var eq$1 = function (universe, item) {
      return curry(universe.eq, item);
    };
    var unsafeSubset = function (universe, common, ps1, ps2) {
      var children = universe.property().children(common);
      if (universe.eq(common, ps1[0])) {
        return Option.some([ps1[0]]);
      }
      if (universe.eq(common, ps2[0])) {
        return Option.some([ps2[0]]);
      }
      var finder = function (ps) {
        var topDown = reverse(ps);
        var index = findIndex(topDown, eq$1(universe, common)).getOr(-1);
        var item = index < topDown.length - 1 ? topDown[index + 1] : topDown[index];
        return findIndex(children, eq$1(universe, item));
      };
      var startIndex = finder(ps1);
      var endIndex = finder(ps2);
      return startIndex.bind(function (sIndex) {
        return endIndex.map(function (eIndex) {
          var first = Math.min(sIndex, eIndex);
          var last = Math.max(sIndex, eIndex);
          return children.slice(first, last + 1);
        });
      });
    };
    var ancestors$2 = function (universe, start, end, isRoot) {
      if (isRoot === void 0) {
        isRoot = never;
      }
      var ps1 = [start].concat(universe.up().all(start));
      var ps2 = [end].concat(universe.up().all(end));
      var prune = function (path) {
        var index = findIndex(path, isRoot);
        return index.fold(function () {
          return path;
        }, function (ind) {
          return path.slice(0, ind + 1);
        });
      };
      var pruned1 = prune(ps1);
      var pruned2 = prune(ps2);
      var shared = find(pruned1, function (x) {
        return exists(pruned2, eq$1(universe, x));
      });
      return {
        firstpath: constant(pruned1),
        secondpath: constant(pruned2),
        shared: constant(shared)
      };
    };
    var subset = function (universe, start, end) {
      var ancs = ancestors$2(universe, start, end);
      return ancs.shared().bind(function (shared) {
        return unsafeSubset(universe, shared, ancs.firstpath(), ancs.secondpath());
      });
    };
    var SubsetFn = {
      subset: subset,
      ancestors: ancestors$2
    };

    var sharedOne = oneAll;
    var subset$1 = SubsetFn.subset;
    var ancestors$3 = SubsetFn.ancestors;
    var breakToLeft$1 = breakToLeft;
    var breakToRight$1 = breakToRight;
    var breakPath$1 = breakPath;
    var Parent = {
      sharedOne: sharedOne,
      subset: subset$1,
      ancestors: ancestors$3,
      breakToLeft: breakToLeft$1,
      breakToRight: breakToRight$1,
      breakPath: breakPath$1
    };

    var universe = DomUniverse();
    var sharedOne$1 = function (look, elements) {
      return Parent.sharedOne(universe, function (_universe, element) {
        return look(element);
      }, elements);
    };
    var subset$2 = function (start, finish) {
      return Parent.subset(universe, start, finish);
    };
    var ancestors$4 = function (start, finish, isRoot) {
      return Parent.ancestors(universe, start, finish, isRoot);
    };
    var breakToLeft$2 = function (parent, child) {
      return Parent.breakToLeft(universe, parent, child);
    };
    var breakToRight$2 = function (parent, child) {
      return Parent.breakToRight(universe, parent, child);
    };
    var breakPath$2 = function (child, isTop, breaker) {
      return Parent.breakPath(universe, child, isTop, function (u, p, c) {
        return breaker(p, c);
      });
    };
    var DomParent = {
      sharedOne: sharedOne$1,
      subset: subset$2,
      ancestors: ancestors$4,
      breakToLeft: breakToLeft$2,
      breakToRight: breakToRight$2,
      breakPath: breakPath$2
    };

    var create = MixedBag([
      'boxes',
      'start',
      'finish'
    ], []);
    var Identified = { create: create };

    var lookupTable = function (container) {
      return ancestor$1(container, 'table');
    };
    var identify = function (start, finish, isRoot) {
      var getIsRoot = function (rootTable) {
        return function (element) {
          return isRoot !== undefined && isRoot(element) || eq(element, rootTable);
        };
      };
      if (eq(start, finish)) {
        return Option.some(Identified.create({
          boxes: Option.some([start]),
          start: start,
          finish: finish
        }));
      } else {
        return lookupTable(start).bind(function (startTable) {
          return lookupTable(finish).bind(function (finishTable) {
            if (eq(startTable, finishTable)) {
              return Option.some(Identified.create({
                boxes: TablePositions.intercepts(startTable, start, finish),
                start: start,
                finish: finish
              }));
            } else if (contains$2(startTable, finishTable)) {
              var ancestorCells = ancestors$1(finish, 'td,th', getIsRoot(startTable));
              var finishCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : finish;
              return Option.some(Identified.create({
                boxes: TablePositions.nestedIntercepts(startTable, start, startTable, finish, finishTable),
                start: start,
                finish: finishCell
              }));
            } else if (contains$2(finishTable, startTable)) {
              var ancestorCells = ancestors$1(start, 'td,th', getIsRoot(finishTable));
              var startCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : start;
              return Option.some(Identified.create({
                boxes: TablePositions.nestedIntercepts(finishTable, start, startTable, finish, finishTable),
                start: start,
                finish: startCell
              }));
            } else {
              return DomParent.ancestors(start, finish).shared().bind(function (lca) {
                return closest$1(lca, 'table', isRoot).bind(function (lcaTable) {
                  var finishAncestorCells = ancestors$1(finish, 'td,th', getIsRoot(lcaTable));
                  var finishCell = finishAncestorCells.length > 0 ? finishAncestorCells[finishAncestorCells.length - 1] : finish;
                  var startAncestorCells = ancestors$1(start, 'td,th', getIsRoot(lcaTable));
                  var startCell = startAncestorCells.length > 0 ? startAncestorCells[startAncestorCells.length - 1] : start;
                  return Option.some(Identified.create({
                    boxes: TablePositions.nestedIntercepts(lcaTable, start, startTable, finish, finishTable),
                    start: startCell,
                    finish: finishCell
                  }));
                });
              });
            }
          });
        });
      }
    };
    var retrieve = function (container, selector) {
      var sels = descendants$1(container, selector);
      return sels.length > 0 ? Option.some(sels) : Option.none();
    };
    var getLast = function (boxes, lastSelectedSelector) {
      return find(boxes, function (box) {
        return is(box, lastSelectedSelector);
      });
    };
    var getEdges = function (container, firstSelectedSelector, lastSelectedSelector) {
      return descendant$1(container, firstSelectedSelector).bind(function (first) {
        return descendant$1(container, lastSelectedSelector).bind(function (last) {
          return DomParent.sharedOne(lookupTable, [
            first,
            last
          ]).map(function (tbl) {
            return {
              first: constant(first),
              last: constant(last),
              table: constant(tbl)
            };
          });
        });
      });
    };
    var expandTo = function (finish, firstSelectedSelector) {
      return ancestor$1(finish, 'table').bind(function (table) {
        return descendant$1(table, firstSelectedSelector).bind(function (start) {
          return identify(start, finish).bind(function (identified) {
            return identified.boxes().map(function (boxes) {
              return {
                boxes: constant(boxes),
                start: constant(identified.start()),
                finish: constant(identified.finish())
              };
            });
          });
        });
      });
    };
    var shiftSelection = function (boxes, deltaRow, deltaColumn, firstSelectedSelector, lastSelectedSelector) {
      return getLast(boxes, lastSelectedSelector).bind(function (last) {
        return TablePositions.moveBy(last, deltaRow, deltaColumn).bind(function (finish) {
          return expandTo(finish, firstSelectedSelector);
        });
      });
    };
    var CellSelection = {
      identify: identify,
      retrieve: retrieve,
      shiftSelection: shiftSelection,
      getEdges: getEdges
    };

    var retrieve$1 = function (container, selector) {
      return CellSelection.retrieve(container, selector);
    };
    var retrieveBox = function (container, firstSelectedSelector, lastSelectedSelector) {
      return CellSelection.getEdges(container, firstSelectedSelector, lastSelectedSelector).bind(function (edges) {
        var isRoot = function (ancestor) {
          return eq(container, ancestor);
        };
        var firstAncestor = ancestor$1(edges.first(), 'thead,tfoot,tbody,table', isRoot);
        var lastAncestor = ancestor$1(edges.last(), 'thead,tfoot,tbody,table', isRoot);
        return firstAncestor.bind(function (fA) {
          return lastAncestor.bind(function (lA) {
            return eq(fA, lA) ? TablePositions.getBox(edges.table(), edges.first(), edges.last()) : Option.none();
          });
        });
      });
    };
    var TableSelection = {
      retrieve: retrieve$1,
      retrieveBox: retrieveBox
    };

    var selected = 'data-mce-selected';
    var selectedSelector = 'td[' + selected + '],th[' + selected + ']';
    var attributeSelector = '[' + selected + ']';
    var firstSelected = 'data-mce-first-selected';
    var firstSelectedSelector = 'td[' + firstSelected + '],th[' + firstSelected + ']';
    var lastSelected = 'data-mce-last-selected';
    var lastSelectedSelector = 'td[' + lastSelected + '],th[' + lastSelected + ']';
    var Ephemera = {
      selected: constant(selected),
      selectedSelector: constant(selectedSelector),
      attributeSelector: constant(attributeSelector),
      firstSelected: constant(firstSelected),
      firstSelectedSelector: constant(firstSelectedSelector),
      lastSelected: constant(lastSelected),
      lastSelectedSelector: constant(lastSelectedSelector)
    };

    var generate$1 = function (cases) {
      if (!isArray(cases)) {
        throw new Error('cases must be an array');
      }
      if (cases.length === 0) {
        throw new Error('there must be at least one case');
      }
      var constructors = [];
      var adt = {};
      each(cases, function (acase, count) {
        var keys$1 = keys(acase);
        if (keys$1.length !== 1) {
          throw new Error('one and only one name per case');
        }
        var key = keys$1[0];
        var value = acase[key];
        if (adt[key] !== undefined) {
          throw new Error('duplicate key detected:' + key);
        } else if (key === 'cata') {
          throw new Error('cannot have a case named cata (sorry)');
        } else if (!isArray(value)) {
          throw new Error('case arguments must be an array');
        }
        constructors.push(key);
        adt[key] = function () {
          var argLength = arguments.length;
          if (argLength !== value.length) {
            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
          }
          var args = new Array(argLength);
          for (var i = 0; i < args.length; i++) {
            args[i] = arguments[i];
          }
          var match = function (branches) {
            var branchKeys = keys(branches);
            if (constructors.length !== branchKeys.length) {
              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
            }
            var allReqd = forall(constructors, function (reqKey) {
              return contains(branchKeys, reqKey);
            });
            if (!allReqd) {
              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
            }
            return branches[key].apply(null, args);
          };
          return {
            fold: function () {
              if (arguments.length !== cases.length) {
                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + arguments.length);
              }
              var target = arguments[count];
              return target.apply(null, args);
            },
            match: match,
            log: function (label) {
              domGlobals.console.log(label, {
                constructors: constructors,
                constructor: key,
                params: args
              });
            }
          };
        };
      });
      return adt;
    };
    var Adt = { generate: generate$1 };

    var type$1 = Adt.generate([
      { none: [] },
      { multiple: ['elements'] },
      { single: ['selection'] }
    ]);
    var cata = function (subject, onNone, onMultiple, onSingle) {
      return subject.fold(onNone, onMultiple, onSingle);
    };
    var SelectionTypes = {
      cata: cata,
      none: type$1.none,
      multiple: type$1.multiple,
      single: type$1.single
    };

    var selection = function (cell, selections) {
      return SelectionTypes.cata(selections.get(), constant([]), identity, constant([cell]));
    };
    var unmergable = function (cell, selections) {
      var hasSpan = function (elem) {
        return has(elem, 'rowspan') && parseInt(get(elem, 'rowspan'), 10) > 1 || has(elem, 'colspan') && parseInt(get(elem, 'colspan'), 10) > 1;
      };
      var candidates = selection(cell, selections);
      return candidates.length > 0 && forall(candidates, hasSpan) ? Option.some(candidates) : Option.none();
    };
    var mergable = function (table, selections) {
      return SelectionTypes.cata(selections.get(), Option.none, function (cells, _env) {
        if (cells.length === 0) {
          return Option.none();
        }
        return TableSelection.retrieveBox(table, Ephemera.firstSelectedSelector(), Ephemera.lastSelectedSelector()).bind(function (bounds) {
          return cells.length > 1 ? Option.some({
            bounds: constant(bounds),
            cells: constant(cells)
          }) : Option.none();
        });
      }, Option.none);
    };
    var CellOperations = {
      mergable: mergable,
      unmergable: unmergable,
      selection: selection
    };

    var noMenu = function (cell) {
      return {
        element: constant(cell),
        mergable: Option.none,
        unmergable: Option.none,
        selection: constant([cell])
      };
    };
    var forMenu = function (selections, table, cell) {
      return {
        element: constant(cell),
        mergable: constant(CellOperations.mergable(table, selections)),
        unmergable: constant(CellOperations.unmergable(cell, selections)),
        selection: constant(CellOperations.selection(cell, selections))
      };
    };
    var notCell$1 = function (element) {
      return noMenu(element);
    };
    var paste$1 = Immutable('element', 'clipboard', 'generators');
    var pasteRows = function (selections, table, cell, clipboard, generators) {
      return {
        element: constant(cell),
        mergable: Option.none,
        unmergable: Option.none,
        selection: constant(CellOperations.selection(cell, selections)),
        clipboard: constant(clipboard),
        generators: constant(generators)
      };
    };
    var TableTargets = {
      noMenu: noMenu,
      forMenu: forMenu,
      notCell: notCell$1,
      paste: paste$1,
      pasteRows: pasteRows
    };

    var extractSelected = function (cells) {
      return TableLookup.table(cells[0]).map(deep).map(function (replica) {
        return [CopySelected.extract(replica, Ephemera.attributeSelector())];
      });
    };
    var serializeElements = function (editor, elements) {
      return map(elements, function (elm) {
        return editor.selection.serializer.serialize(elm.dom(), {});
      }).join('');
    };
    var getTextContent = function (elements) {
      return map(elements, function (element) {
        return element.dom().innerText;
      }).join('');
    };
    var registerEvents = function (editor, selections, actions, cellSelection) {
      editor.on('BeforeGetContent', function (e) {
        var multiCellContext = function (cells) {
          e.preventDefault();
          extractSelected(cells).each(function (elements) {
            e.content = e.format === 'text' ? getTextContent(elements) : serializeElements(editor, elements);
          });
        };
        if (e.selection === true) {
          SelectionTypes.cata(selections.get(), noop, multiCellContext, noop);
        }
      });
      editor.on('BeforeSetContent', function (e) {
        if (e.selection === true && e.paste === true) {
          var cellOpt = Option.from(editor.dom.getParent(editor.selection.getStart(), 'th,td'));
          cellOpt.each(function (domCell) {
            var cell = Element.fromDom(domCell);
            TableLookup.table(cell).each(function (table) {
              var elements = filter(fromHtml$1(e.content), function (content) {
                return name(content) !== 'meta';
              });
              if (elements.length === 1 && name(elements[0]) === 'table') {
                e.preventDefault();
                var doc = Element.fromDom(editor.getDoc());
                var generators = TableFill.paste(doc);
                var targets = TableTargets.paste(cell, elements[0], generators);
                actions.pasteCells(table, targets).each(function (rng) {
                  editor.selection.setRng(rng);
                  editor.focus();
                  cellSelection.clear(table);
                });
              }
            });
          });
        }
      });
    };
    var Clipboard = { registerEvents: registerEvents };

    function Dimension (name, getOffset) {
      var set = function (element, h) {
        if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
          throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
        }
        var dom = element.dom();
        if (isSupported(dom)) {
          dom.style[name] = h + 'px';
        }
      };
      var get = function (element) {
        var r = getOffset(element);
        if (r <= 0 || r === null) {
          var css = get$1(element, name);
          return parseFloat(css) || 0;
        }
        return r;
      };
      var getOuter = get;
      var aggregate = function (element, properties) {
        return foldl(properties, function (acc, property) {
          var val = get$1(element, property);
          var value = val === undefined ? 0 : parseInt(val, 10);
          return isNaN(value) ? acc : acc + value;
        }, 0);
      };
      var max = function (element, value, properties) {
        var cumulativeInclusions = aggregate(element, properties);
        var absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
        return absoluteMax;
      };
      return {
        set: set,
        get: get,
        getOuter: getOuter,
        aggregate: aggregate,
        max: max
      };
    }

    var api$1 = Dimension('height', function (element) {
      var dom = element.dom();
      return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
    });
    var get$3 = function (element) {
      return api$1.get(element);
    };
    var getOuter = function (element) {
      return api$1.getOuter(element);
    };

    var api$2 = Dimension('width', function (element) {
      return element.dom().offsetWidth;
    });
    var get$4 = function (element) {
      return api$2.get(element);
    };
    var getOuter$1 = function (element) {
      return api$2.getOuter(element);
    };

    var platform = PlatformDetection$1.detect();
    var needManualCalc = function () {
      return platform.browser.isIE() || platform.browser.isEdge();
    };
    var toNumber = function (px, fallback) {
      var num = parseFloat(px);
      return isNaN(num) ? fallback : num;
    };
    var getProp = function (elm, name, fallback) {
      return toNumber(get$1(elm, name), fallback);
    };
    var getCalculatedHeight = function (cell) {
      var paddingTop = getProp(cell, 'padding-top', 0);
      var paddingBottom = getProp(cell, 'padding-bottom', 0);
      var borderTop = getProp(cell, 'border-top-width', 0);
      var borderBottom = getProp(cell, 'border-bottom-width', 0);
      var height = cell.dom().getBoundingClientRect().height;
      var boxSizing = get$1(cell, 'box-sizing');
      var borders = borderTop + borderBottom;
      return boxSizing === 'border-box' ? height : height - paddingTop - paddingBottom - borders;
    };
    var getWidth = function (cell) {
      return getProp(cell, 'width', get$4(cell));
    };
    var getHeight = function (cell) {
      return needManualCalc() ? getCalculatedHeight(cell) : getProp(cell, 'height', get$3(cell));
    };
    var RuntimeSize = {
      getWidth: getWidth,
      getHeight: getHeight
    };

    var genericSizeRegex = /(\d+(\.\d+)?)(\w|%)*/;
    var percentageBasedSizeRegex = /(\d+(\.\d+)?)%/;
    var pixelBasedSizeRegex = /(\d+(\.\d+)?)px|em/;
    var setPixelWidth = function (cell, amount) {
      set$1(cell, 'width', amount + 'px');
    };
    var setPercentageWidth = function (cell, amount) {
      set$1(cell, 'width', amount + '%');
    };
    var setHeight = function (cell, amount) {
      set$1(cell, 'height', amount + 'px');
    };
    var getHeightValue = function (cell) {
      return getRaw(cell, 'height').getOrThunk(function () {
        return RuntimeSize.getHeight(cell) + 'px';
      });
    };
    var convert = function (cell, number, getter, setter) {
      var newSize = TableLookup.table(cell).map(function (table) {
        var total = getter(table);
        return Math.floor(number / 100 * total);
      }).getOr(number);
      setter(cell, newSize);
      return newSize;
    };
    var normalizePixelSize = function (value, cell, getter, setter) {
      var number = parseInt(value, 10);
      return endsWith(value, '%') && name(cell) !== 'table' ? convert(cell, number, getter, setter) : number;
    };
    var getTotalHeight = function (cell) {
      var value = getHeightValue(cell);
      if (!value) {
        return get$3(cell);
      }
      return normalizePixelSize(value, cell, get$3, setHeight);
    };
    var get$5 = function (cell, type, f) {
      var v = f(cell);
      var span = getSpan(cell, type);
      return v / span;
    };
    var getSpan = function (cell, type) {
      return has(cell, type) ? parseInt(get(cell, type), 10) : 1;
    };
    var getRawWidth = function (element) {
      var cssWidth = getRaw(element, 'width');
      return cssWidth.fold(function () {
        return Option.from(get(element, 'width'));
      }, function (width) {
        return Option.some(width);
      });
    };
    var normalizePercentageWidth = function (cellWidth, tableSize) {
      return cellWidth / tableSize.pixelWidth() * 100;
    };
    var choosePercentageSize = function (element, width, tableSize) {
      var percentMatch = percentageBasedSizeRegex.exec(width);
      if (percentMatch !== null) {
        return parseFloat(percentMatch[1]);
      } else {
        var intWidth = get$4(element);
        return normalizePercentageWidth(intWidth, tableSize);
      }
    };
    var getPercentageWidth = function (cell, tableSize) {
      var width = getRawWidth(cell);
      return width.fold(function () {
        var intWidth = get$4(cell);
        return normalizePercentageWidth(intWidth, tableSize);
      }, function (w) {
        return choosePercentageSize(cell, w, tableSize);
      });
    };
    var normalizePixelWidth = function (cellWidth, tableSize) {
      return cellWidth / 100 * tableSize.pixelWidth();
    };
    var choosePixelSize = function (element, width, tableSize) {
      var pixelMatch = pixelBasedSizeRegex.exec(width);
      if (pixelMatch !== null) {
        return parseInt(pixelMatch[1], 10);
      }
      var percentMatch = percentageBasedSizeRegex.exec(width);
      if (percentMatch !== null) {
        var floatWidth = parseFloat(percentMatch[1]);
        return normalizePixelWidth(floatWidth, tableSize);
      }
      return get$4(element);
    };
    var getPixelWidth = function (cell, tableSize) {
      var width = getRawWidth(cell);
      return width.fold(function () {
        return get$4(cell);
      }, function (w) {
        return choosePixelSize(cell, w, tableSize);
      });
    };
    var getHeight$1 = function (cell) {
      return get$5(cell, 'rowspan', getTotalHeight);
    };
    var getGenericWidth = function (cell) {
      var width = getRawWidth(cell);
      return width.bind(function (w) {
        var match = genericSizeRegex.exec(w);
        if (match !== null) {
          return Option.some({
            width: constant(parseFloat(match[1])),
            unit: constant(match[3])
          });
        } else {
          return Option.none();
        }
      });
    };
    var setGenericWidth = function (cell, amount, unit) {
      set$1(cell, 'width', amount + unit);
    };
    var Sizes = {
      percentageBasedSizeRegex: constant(percentageBasedSizeRegex),
      pixelBasedSizeRegex: constant(pixelBasedSizeRegex),
      setPixelWidth: setPixelWidth,
      setPercentageWidth: setPercentageWidth,
      setHeight: setHeight,
      getPixelWidth: getPixelWidth,
      getPercentageWidth: getPercentageWidth,
      getGenericWidth: getGenericWidth,
      setGenericWidth: setGenericWidth,
      getHeight: getHeight$1,
      getRawWidth: getRawWidth
    };

    var halve = function (main, other) {
      var width = Sizes.getGenericWidth(main);
      width.each(function (w) {
        var newWidth = w.width() / 2;
        Sizes.setGenericWidth(main, newWidth, w.unit());
        Sizes.setGenericWidth(other, newWidth, w.unit());
      });
    };
    var CellMutations = { halve: halve };

    var r = function (left, top) {
      var translate = function (x, y) {
        return r(left + x, top + y);
      };
      return {
        left: constant(left),
        top: constant(top),
        translate: translate
      };
    };
    var Position = r;

    var boxPosition = function (dom) {
      var box = dom.getBoundingClientRect();
      return Position(box.left, box.top);
    };
    var firstDefinedOrZero = function (a, b) {
      return a !== undefined ? a : b !== undefined ? b : 0;
    };
    var absolute = function (element) {
      var doc = element.dom().ownerDocument;
      var body = doc.body;
      var win = doc.defaultView;
      var html = doc.documentElement;
      var scrollTop = firstDefinedOrZero(win.pageYOffset, html.scrollTop);
      var scrollLeft = firstDefinedOrZero(win.pageXOffset, html.scrollLeft);
      var clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
      var clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
      return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
    };
    var viewport = function (element) {
      var dom = element.dom();
      var doc = dom.ownerDocument;
      var body = doc.body;
      if (body === dom) {
        return Position(body.offsetLeft, body.offsetTop);
      }
      if (!inBody(element)) {
        return Position(0, 0);
      }
      return boxPosition(dom);
    };

    var rowInfo = Immutable('row', 'y');
    var colInfo = Immutable('col', 'x');
    var rtlEdge = function (cell) {
      var pos = absolute(cell);
      return pos.left() + getOuter$1(cell);
    };
    var ltrEdge = function (cell) {
      return absolute(cell).left();
    };
    var getLeftEdge = function (index, cell) {
      return colInfo(index, ltrEdge(cell));
    };
    var getRightEdge = function (index, cell) {
      return colInfo(index, rtlEdge(cell));
    };
    var getTop = function (cell) {
      return absolute(cell).top();
    };
    var getTopEdge = function (index, cell) {
      return rowInfo(index, getTop(cell));
    };
    var getBottomEdge = function (index, cell) {
      return rowInfo(index, getTop(cell) + getOuter(cell));
    };
    var findPositions = function (getInnerEdge, getOuterEdge, array) {
      if (array.length === 0) {
        return [];
      }
      var lines = map(array.slice(1), function (cellOption, index) {
        return cellOption.map(function (cell) {
          return getInnerEdge(index, cell);
        });
      });
      var lastLine = array[array.length - 1].map(function (cell) {
        return getOuterEdge(array.length - 1, cell);
      });
      return lines.concat([lastLine]);
    };
    var negate = function (step) {
      return -step;
    };
    var height = {
      delta: identity,
      positions: function (optElements) {
        return findPositions(getTopEdge, getBottomEdge, optElements);
      },
      edge: getTop
    };
    var ltr = {
      delta: identity,
      edge: ltrEdge,
      positions: function (optElements) {
        return findPositions(getLeftEdge, getRightEdge, optElements);
      }
    };
    var rtl = {
      delta: negate,
      edge: rtlEdge,
      positions: function (optElements) {
        return findPositions(getRightEdge, getLeftEdge, optElements);
      }
    };
    var BarPositions = {
      height: height,
      rtl: rtl,
      ltr: ltr
    };

    var ResizeDirection = {
      ltr: BarPositions.ltr,
      rtl: BarPositions.rtl
    };

    function TableDirection (directionAt) {
      var auto = function (table) {
        return directionAt(table).isRtl() ? ResizeDirection.rtl : ResizeDirection.ltr;
      };
      var delta = function (amount, table) {
        return auto(table).delta(amount, table);
      };
      var positions = function (cols, table) {
        return auto(table).positions(cols, table);
      };
      var edge = function (cell) {
        return auto(cell).edge(cell);
      };
      return {
        delta: delta,
        edge: edge,
        positions: positions
      };
    }

    var getGridSize = function (table) {
      var input = DetailsList.fromTable(table);
      var warehouse = Warehouse.generate(input);
      return warehouse.grid();
    };
    var TableGridSize = { getGridSize: getGridSize };

    var __assign = function () {
      __assign = Object.assign || function __assign(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
          s = arguments[i];
          for (var p in s)
            if (Object.prototype.hasOwnProperty.call(s, p))
              t[p] = s[p];
        }
        return t;
      };
      return __assign.apply(this, arguments);
    };

    var cat = function (arr) {
      var r = [];
      var push = function (x) {
        r.push(x);
      };
      for (var i = 0; i < arr.length; i++) {
        arr[i].each(push);
      }
      return r;
    };
    var findMap = function (arr, f) {
      for (var i = 0; i < arr.length; i++) {
        var r = f(arr[i], i);
        if (r.isSome()) {
          return r;
        }
      }
      return Option.none();
    };

    var setIfNot = function (element, property, value, ignore) {
      if (value === ignore) {
        remove(element, property);
      } else {
        set(element, property, value);
      }
    };
    var render = function (table, grid) {
      var newRows = [];
      var newCells = [];
      var renderSection = function (gridSection, sectionName) {
        var section = child$2(table, sectionName).getOrThunk(function () {
          var tb = Element.fromTag(sectionName, owner(table).dom());
          append(table, tb);
          return tb;
        });
        empty(section);
        var rows = map(gridSection, function (row) {
          if (row.isNew()) {
            newRows.push(row.element());
          }
          var tr = row.element();
          empty(tr);
          each(row.cells(), function (cell) {
            if (cell.isNew()) {
              newCells.push(cell.element());
            }
            setIfNot(cell.element(), 'colspan', cell.colspan(), 1);
            setIfNot(cell.element(), 'rowspan', cell.rowspan(), 1);
            append(tr, cell.element());
          });
          return tr;
        });
        append$1(section, rows);
      };
      var removeSection = function (sectionName) {
        child$2(table, sectionName).each(remove$2);
      };
      var renderOrRemoveSection = function (gridSection, sectionName) {
        if (gridSection.length > 0) {
          renderSection(gridSection, sectionName);
        } else {
          removeSection(sectionName);
        }
      };
      var headSection = [];
      var bodySection = [];
      var footSection = [];
      each(grid, function (row) {
        switch (row.section()) {
        case 'thead':
          headSection.push(row);
          break;
        case 'tbody':
          bodySection.push(row);
          break;
        case 'tfoot':
          footSection.push(row);
          break;
        }
      });
      renderOrRemoveSection(headSection, 'thead');
      renderOrRemoveSection(bodySection, 'tbody');
      renderOrRemoveSection(footSection, 'tfoot');
      return {
        newRows: constant(newRows),
        newCells: constant(newCells)
      };
    };
    var copy$2 = function (grid) {
      var rows = map(grid, function (row) {
        var tr = shallow(row.element());
        each(row.cells(), function (cell) {
          var clonedCell = deep(cell.element());
          setIfNot(clonedCell, 'colspan', cell.colspan(), 1);
          setIfNot(clonedCell, 'rowspan', cell.rowspan(), 1);
          append(tr, clonedCell);
        });
        return tr;
      });
      return rows;
    };
    var Redraw = {
      render: render,
      copy: copy$2
    };

    var read = function (element, attr) {
      var value = get(element, attr);
      return value === undefined || value === '' ? [] : value.split(' ');
    };
    var add = function (element, attr, id) {
      var old = read(element, attr);
      var nu = old.concat([id]);
      set(element, attr, nu.join(' '));
      return true;
    };
    var remove$3 = function (element, attr, id) {
      var nu = filter(read(element, attr), function (v) {
        return v !== id;
      });
      if (nu.length > 0) {
        set(element, attr, nu.join(' '));
      } else {
        remove(element, attr);
      }
      return false;
    };

    var supports = function (element) {
      return element.dom().classList !== undefined;
    };
    var get$6 = function (element) {
      return read(element, 'class');
    };
    var add$1 = function (element, clazz) {
      return add(element, 'class', clazz);
    };
    var remove$4 = function (element, clazz) {
      return remove$3(element, 'class', clazz);
    };

    var add$2 = function (element, clazz) {
      if (supports(element)) {
        element.dom().classList.add(clazz);
      } else {
        add$1(element, clazz);
      }
    };
    var cleanClass = function (element) {
      var classList = supports(element) ? element.dom().classList : get$6(element);
      if (classList.length === 0) {
        remove(element, 'class');
      }
    };
    var remove$5 = function (element, clazz) {
      if (supports(element)) {
        var classList = element.dom().classList;
        classList.remove(clazz);
      } else {
        remove$4(element, clazz);
      }
      cleanClass(element);
    };
    var has$1 = function (element, clazz) {
      return supports(element) && element.dom().classList.contains(clazz);
    };

    var repeat = function (repititions, f) {
      var r = [];
      for (var i = 0; i < repititions; i++) {
        r.push(f(i));
      }
      return r;
    };
    var range = function (start, end) {
      var r = [];
      for (var i = start; i < end; i++) {
        r.push(i);
      }
      return r;
    };
    var deduce = function (xs, index) {
      if (index < 0 || index >= xs.length - 1) {
        return Option.none();
      }
      var current = xs[index].fold(function () {
        var rest = reverse(xs.slice(0, index));
        return findMap(rest, function (a, i) {
          return a.map(function (aa) {
            return {
              value: aa,
              delta: i + 1
            };
          });
        });
      }, function (c) {
        return Option.some({
          value: c,
          delta: 0
        });
      });
      var next = xs[index + 1].fold(function () {
        var rest = xs.slice(index + 1);
        return findMap(rest, function (a, i) {
          return a.map(function (aa) {
            return {
              value: aa,
              delta: i + 1
            };
          });
        });
      }, function (n) {
        return Option.some({
          value: n,
          delta: 1
        });
      });
      return current.bind(function (c) {
        return next.map(function (n) {
          var extras = n.delta + c.delta;
          return Math.abs(n.value - c.value) / extras;
        });
      });
    };

    var columns = function (warehouse) {
      var grid = warehouse.grid();
      var cols = range(0, grid.columns());
      var rowsArr = range(0, grid.rows());
      return map(cols, function (col) {
        var getBlock = function () {
          return bind(rowsArr, function (r) {
            return Warehouse.getAt(warehouse, r, col).filter(function (detail) {
              return detail.column() === col;
            }).fold(constant([]), function (detail) {
              return [detail];
            });
          });
        };
        var isSingle = function (detail) {
          return detail.colspan() === 1;
        };
        var getFallback = function () {
          return Warehouse.getAt(warehouse, 0, col);
        };
        return decide(getBlock, isSingle, getFallback);
      });
    };
    var decide = function (getBlock, isSingle, getFallback) {
      var inBlock = getBlock();
      var singleInBlock = find(inBlock, isSingle);
      var detailOption = singleInBlock.orThunk(function () {
        return Option.from(inBlock[0]).orThunk(getFallback);
      });
      return detailOption.map(function (detail) {
        return detail.element();
      });
    };
    var rows$1 = function (warehouse) {
      var grid = warehouse.grid();
      var rowsArr = range(0, grid.rows());
      var cols = range(0, grid.columns());
      return map(rowsArr, function (row) {
        var getBlock = function () {
          return bind(cols, function (c) {
            return Warehouse.getAt(warehouse, row, c).filter(function (detail) {
              return detail.row() === row;
            }).fold(constant([]), function (detail) {
              return [detail];
            });
          });
        };
        var isSingle = function (detail) {
          return detail.rowspan() === 1;
        };
        var getFallback = function () {
          return Warehouse.getAt(warehouse, row, 0);
        };
        return decide(getBlock, isSingle, getFallback);
      });
    };
    var Blocks = {
      columns: columns,
      rows: rows$1
    };

    var css = function (namespace) {
      var dashNamespace = namespace.replace(/\./g, '-');
      var resolve = function (str) {
        return dashNamespace + '-' + str;
      };
      return { resolve: resolve };
    };

    var styles = css('ephox-snooker');
    var Styles = { resolve: styles.resolve };

    var col = function (column, x, y, w, h) {
      var blocker = Element.fromTag('div');
      setAll$1(blocker, {
        position: 'absolute',
        left: x - w / 2 + 'px',
        top: y + 'px',
        height: h + 'px',
        width: w + 'px'
      });
      setAll(blocker, {
        'data-column': column,
        'role': 'presentation'
      });
      return blocker;
    };
    var row$1 = function (r, x, y, w, h) {
      var blocker = Element.fromTag('div');
      setAll$1(blocker, {
        position: 'absolute',
        left: x + 'px',
        top: y - h / 2 + 'px',
        height: h + 'px',
        width: w + 'px'
      });
      setAll(blocker, {
        'data-row': r,
        'role': 'presentation'
      });
      return blocker;
    };
    var Bar = {
      col: col,
      row: row$1
    };

    var resizeBar = Styles.resolve('resizer-bar');
    var resizeRowBar = Styles.resolve('resizer-rows');
    var resizeColBar = Styles.resolve('resizer-cols');
    var BAR_THICKNESS = 7;
    var destroy = function (wire) {
      var previous = descendants$1(wire.parent(), '.' + resizeBar);
      each(previous, remove$2);
    };
    var drawBar = function (wire, positions, create) {
      var origin = wire.origin();
      each(positions, function (cpOption, i) {
        cpOption.each(function (cp) {
          var bar = create(origin, cp);
          add$2(bar, resizeBar);
          append(wire.parent(), bar);
        });
      });
    };
    var refreshCol = function (wire, colPositions, position, tableHeight) {
      drawBar(wire, colPositions, function (origin, cp) {
        var colBar = Bar.col(cp.col(), cp.x() - origin.left(), position.top() - origin.top(), BAR_THICKNESS, tableHeight);
        add$2(colBar, resizeColBar);
        return colBar;
      });
    };
    var refreshRow = function (wire, rowPositions, position, tableWidth) {
      drawBar(wire, rowPositions, function (origin, cp) {
        var rowBar = Bar.row(cp.row(), position.left() - origin.left(), cp.y() - origin.top(), tableWidth, BAR_THICKNESS);
        add$2(rowBar, resizeRowBar);
        return rowBar;
      });
    };
    var refreshGrid = function (wire, table, rows, cols, hdirection, vdirection) {
      var position = absolute(table);
      var rowPositions = rows.length > 0 ? hdirection.positions(rows, table) : [];
      refreshRow(wire, rowPositions, position, getOuter$1(table));
      var colPositions = cols.length > 0 ? vdirection.positions(cols, table) : [];
      refreshCol(wire, colPositions, position, getOuter(table));
    };
    var refresh = function (wire, table, hdirection, vdirection) {
      destroy(wire);
      var list = DetailsList.fromTable(table);
      var warehouse = Warehouse.generate(list);
      var rows = Blocks.rows(warehouse);
      var cols = Blocks.columns(warehouse);
      refreshGrid(wire, table, rows, cols, hdirection, vdirection);
    };
    var each$2 = function (wire, f) {
      var bars = descendants$1(wire.parent(), '.' + resizeBar);
      each(bars, f);
    };
    var hide = function (wire) {
      each$2(wire, function (bar) {
        set$1(bar, 'display', 'none');
      });
    };
    var show = function (wire) {
      each$2(wire, function (bar) {
        set$1(bar, 'display', 'block');
      });
    };
    var isRowBar = function (element) {
      return has$1(element, resizeRowBar);
    };
    var isColBar = function (element) {
      return has$1(element, resizeColBar);
    };
    var Bars = {
      refresh: refresh,
      hide: hide,
      show: show,
      destroy: destroy,
      isRowBar: isRowBar,
      isColBar: isColBar
    };

    var addCell = function (gridRow, index, cell) {
      var cells = gridRow.cells();
      var before = cells.slice(0, index);
      var after = cells.slice(index);
      var newCells = before.concat([cell]).concat(after);
      return setCells(gridRow, newCells);
    };
    var mutateCell = function (gridRow, index, cell) {
      var cells = gridRow.cells();
      cells[index] = cell;
    };
    var setCells = function (gridRow, cells) {
      return rowcells(cells, gridRow.section());
    };
    var mapCells = function (gridRow, f) {
      var cells = gridRow.cells();
      var r = map(cells, f);
      return rowcells(r, gridRow.section());
    };
    var getCell = function (gridRow, index) {
      return gridRow.cells()[index];
    };
    var getCellElement = function (gridRow, index) {
      return getCell(gridRow, index).element();
    };
    var cellLength = function (gridRow) {
      return gridRow.cells().length;
    };
    var GridRow = {
      addCell: addCell,
      setCells: setCells,
      mutateCell: mutateCell,
      getCell: getCell,
      getCellElement: getCellElement,
      mapCells: mapCells,
      cellLength: cellLength
    };

    var getColumn = function (grid, index) {
      return map(grid, function (row) {
        return GridRow.getCell(row, index);
      });
    };
    var getRow = function (grid, index) {
      return grid[index];
    };
    var findDiff = function (xs, comp) {
      if (xs.length === 0) {
        return 0;
      }
      var first = xs[0];
      var index = findIndex(xs, function (x) {
        return !comp(first.element(), x.element());
      });
      return index.fold(function () {
        return xs.length;
      }, function (ind) {
        return ind;
      });
    };
    var subgrid = function (grid, row, column, comparator) {
      var restOfRow = getRow(grid, row).cells().slice(column);
      var endColIndex = findDiff(restOfRow, comparator);
      var restOfColumn = getColumn(grid, column).slice(row);
      var endRowIndex = findDiff(restOfColumn, comparator);
      return {
        colspan: constant(endColIndex),
        rowspan: constant(endRowIndex)
      };
    };
    var TableGrid = { subgrid: subgrid };

    var toDetails = function (grid, comparator) {
      var seen = map(grid, function (row, ri) {
        return map(row.cells(), function (col, ci) {
          return false;
        });
      });
      var updateSeen = function (ri, ci, rowspan, colspan) {
        for (var r = ri; r < ri + rowspan; r++) {
          for (var c = ci; c < ci + colspan; c++) {
            seen[r][c] = true;
          }
        }
      };
      return map(grid, function (row, ri) {
        var details = bind(row.cells(), function (cell, ci) {
          if (seen[ri][ci] === false) {
            var result = TableGrid.subgrid(grid, ri, ci, comparator);
            updateSeen(ri, ci, result.rowspan(), result.colspan());
            return [detailnew(cell.element(), result.rowspan(), result.colspan(), cell.isNew())];
          } else {
            return [];
          }
        });
        return rowdetails(details, row.section());
      });
    };
    var toGrid = function (warehouse, generators, isNew) {
      var grid = [];
      for (var i = 0; i < warehouse.grid().rows(); i++) {
        var rowCells = [];
        for (var j = 0; j < warehouse.grid().columns(); j++) {
          var element = Warehouse.getAt(warehouse, i, j).map(function (item) {
            return elementnew(item.element(), isNew);
          }).getOrThunk(function () {
            return elementnew(generators.gap(), true);
          });
          rowCells.push(element);
        }
        var row = rowcells(rowCells, warehouse.all()[i].section());
        grid.push(row);
      }
      return grid;
    };
    var Transitions = {
      toDetails: toDetails,
      toGrid: toGrid
    };

    var fromWarehouse = function (warehouse, generators) {
      return Transitions.toGrid(warehouse, generators, false);
    };
    var deriveRows = function (rendered, generators) {
      var findRow = function (details) {
        var rowOfCells = findMap(details, function (detail) {
          return parent(detail.element()).map(function (row) {
            var isNew = parent(row).isNone();
            return elementnew(row, isNew);
          });
        });
        return rowOfCells.getOrThunk(function () {
          return elementnew(generators.row(), true);
        });
      };
      return map(rendered, function (details) {
        var row = findRow(details.details());
        return rowdatanew(row.element(), details.details(), details.section(), row.isNew());
      });
    };
    var toDetailList = function (grid, generators) {
      var rendered = Transitions.toDetails(grid, eq);
      return deriveRows(rendered, generators);
    };
    var findInWarehouse = function (warehouse, element) {
      var all = flatten(map(warehouse.all(), function (r) {
        return r.cells();
      }));
      return find(all, function (e) {
        return eq(element, e.element());
      });
    };
    var run = function (operation, extract, adjustment, postAction, genWrappers) {
      return function (wire, table, target, generators, direction) {
        var input = DetailsList.fromTable(table);
        var warehouse = Warehouse.generate(input);
        var output = extract(warehouse, target).map(function (info) {
          var model = fromWarehouse(warehouse, generators);
          var result = operation(model, info, eq, genWrappers(generators));
          var grid = toDetailList(result.grid(), generators);
          return {
            grid: constant(grid),
            cursor: result.cursor
          };
        });
        return output.fold(function () {
          return Option.none();
        }, function (out) {
          var newElements = Redraw.render(table, out.grid());
          adjustment(table, out.grid(), direction);
          postAction(table);
          Bars.refresh(wire, table, BarPositions.height, direction);
          return Option.some({
            cursor: out.cursor,
            newRows: newElements.newRows,
            newCells: newElements.newCells
          });
        });
      };
    };
    var onCell = function (warehouse, target) {
      return TableLookup.cell(target.element()).bind(function (cell) {
        return findInWarehouse(warehouse, cell);
      });
    };
    var onPaste = function (warehouse, target) {
      return TableLookup.cell(target.element()).bind(function (cell) {
        return findInWarehouse(warehouse, cell).map(function (details) {
          var value = __assign(__assign({}, details), {
            generators: target.generators,
            clipboard: target.clipboard
          });
          return value;
        });
      });
    };
    var onPasteRows = function (warehouse, target) {
      var details = map(target.selection(), function (cell) {
        return TableLookup.cell(cell).bind(function (lc) {
          return findInWarehouse(warehouse, lc);
        });
      });
      var cells = cat(details);
      return cells.length > 0 ? Option.some({
        cells: cells,
        generators: target.generators,
        clipboard: target.clipboard
      }) : Option.none();
    };
    var onMergable = function (_warehouse, target) {
      return target.mergable();
    };
    var onUnmergable = function (_warehouse, target) {
      return target.unmergable();
    };
    var onCells = function (warehouse, target) {
      var details = map(target.selection(), function (cell) {
        return TableLookup.cell(cell).bind(function (lc) {
          return findInWarehouse(warehouse, lc);
        });
      });
      var cells = cat(details);
      return cells.length > 0 ? Option.some(cells) : Option.none();
    };

    var value = function (o) {
      var is = function (v) {
        return o === v;
      };
      var or = function (opt) {
        return value(o);
      };
      var orThunk = function (f) {
        return value(o);
      };
      var map = function (f) {
        return value(f(o));
      };
      var mapError = function (f) {
        return value(o);
      };
      var each = function (f) {
        f(o);
      };
      var bind = function (f) {
        return f(o);
      };
      var fold = function (_, onValue) {
        return onValue(o);
      };
      var exists = function (f) {
        return f(o);
      };
      var forall = function (f) {
        return f(o);
      };
      var toOption = function () {
        return Option.some(o);
      };
      return {
        is: is,
        isValue: always,
        isError: never,
        getOr: constant(o),
        getOrThunk: constant(o),
        getOrDie: constant(o),
        or: or,
        orThunk: orThunk,
        fold: fold,
        map: map,
        mapError: mapError,
        each: each,
        bind: bind,
        exists: exists,
        forall: forall,
        toOption: toOption
      };
    };
    var error = function (message) {
      var getOrThunk = function (f) {
        return f();
      };
      var getOrDie = function () {
        return die(String(message))();
      };
      var or = function (opt) {
        return opt;
      };
      var orThunk = function (f) {
        return f();
      };
      var map = function (f) {
        return error(message);
      };
      var mapError = function (f) {
        return error(f(message));
      };
      var bind = function (f) {
        return error(message);
      };
      var fold = function (onError, _) {
        return onError(message);
      };
      return {
        is: never,
        isValue: never,
        isError: always,
        getOr: identity,
        getOrThunk: getOrThunk,
        getOrDie: getOrDie,
        or: or,
        orThunk: orThunk,
        fold: fold,
        map: map,
        mapError: mapError,
        each: noop,
        bind: bind,
        exists: never,
        forall: always,
        toOption: Option.none
      };
    };
    var fromOption = function (opt, err) {
      return opt.fold(function () {
        return error(err);
      }, value);
    };
    var Result = {
      value: value,
      error: error,
      fromOption: fromOption
    };

    var measure = function (startAddress, gridA, gridB) {
      if (startAddress.row() >= gridA.length || startAddress.column() > GridRow.cellLength(gridA[0])) {
        return Result.error('invalid start address out of table bounds, row: ' + startAddress.row() + ', column: ' + startAddress.column());
      }
      var rowRemainder = gridA.slice(startAddress.row());
      var colRemainder = rowRemainder[0].cells().slice(startAddress.column());
      var colRequired = GridRow.cellLength(gridB[0]);
      var rowRequired = gridB.length;
      return Result.value({
        rowDelta: constant(rowRemainder.length - rowRequired),
        colDelta: constant(colRemainder.length - colRequired)
      });
    };
    var measureWidth = function (gridA, gridB) {
      var colLengthA = GridRow.cellLength(gridA[0]);
      var colLengthB = GridRow.cellLength(gridB[0]);
      return {
        rowDelta: constant(0),
        colDelta: constant(colLengthA - colLengthB)
      };
    };
    var fill = function (cells, generator) {
      return map(cells, function () {
        return elementnew(generator.cell(), true);
      });
    };
    var rowFill = function (grid, amount, generator) {
      return grid.concat(repeat(amount, function (_row) {
        return GridRow.setCells(grid[grid.length - 1], fill(grid[grid.length - 1].cells(), generator));
      }));
    };
    var colFill = function (grid, amount, generator) {
      return map(grid, function (row) {
        return GridRow.setCells(row, row.cells().concat(fill(range(0, amount), generator)));
      });
    };
    var tailor = function (gridA, delta, generator) {
      var fillCols = delta.colDelta() < 0 ? colFill : identity;
      var fillRows = delta.rowDelta() < 0 ? rowFill : identity;
      var modifiedCols = fillCols(gridA, Math.abs(delta.colDelta()), generator);
      var tailoredGrid = fillRows(modifiedCols, Math.abs(delta.rowDelta()), generator);
      return tailoredGrid;
    };
    var Fitment = {
      measure: measure,
      measureWidth: measureWidth,
      tailor: tailor
    };

    var merge = function (grid, bounds, comparator, substitution) {
      if (grid.length === 0) {
        return grid;
      }
      for (var i = bounds.startRow(); i <= bounds.finishRow(); i++) {
        for (var j = bounds.startCol(); j <= bounds.finishCol(); j++) {
          GridRow.mutateCell(grid[i], j, elementnew(substitution(), false));
        }
      }
      return grid;
    };
    var unmerge = function (grid, target, comparator, substitution) {
      var first = true;
      for (var i = 0; i < grid.length; i++) {
        for (var j = 0; j < GridRow.cellLength(grid[0]); j++) {
          var current = GridRow.getCellElement(grid[i], j);
          var isToReplace = comparator(current, target);
          if (isToReplace === true && first === false) {
            GridRow.mutateCell(grid[i], j, elementnew(substitution(), true));
          } else if (isToReplace === true) {
            first = false;
          }
        }
      }
      return grid;
    };
    var uniqueCells = function (row, comparator) {
      return foldl(row, function (rest, cell) {
        return exists(rest, function (currentCell) {
          return comparator(currentCell.element(), cell.element());
        }) ? rest : rest.concat([cell]);
      }, []);
    };
    var splitRows = function (grid, index, comparator, substitution) {
      if (index > 0 && index < grid.length) {
        var rowPrevCells = grid[index - 1].cells();
        var cells = uniqueCells(rowPrevCells, comparator);
        each(cells, function (cell) {
          var replacement = Option.none();
          var _loop_1 = function (i) {
            var _loop_2 = function (j) {
              var current = grid[i].cells()[j];
              var isToReplace = comparator(current.element(), cell.element());
              if (isToReplace) {
                if (replacement.isNone()) {
                  replacement = Option.some(substitution());
                }
                replacement.each(function (sub) {
                  GridRow.mutateCell(grid[i], j, elementnew(sub, true));
                });
              }
            };
            for (var j = 0; j < GridRow.cellLength(grid[0]); j++) {
              _loop_2(j);
            }
          };
          for (var i = index; i < grid.length; i++) {
            _loop_1(i);
          }
        });
      }
      return grid;
    };
    var MergingOperations = {
      merge: merge,
      unmerge: unmerge,
      splitRows: splitRows
    };

    var isSpanning = function (grid, row, col, comparator) {
      var candidate = GridRow.getCell(grid[row], col);
      var matching = curry(comparator, candidate.element());
      var currentRow = grid[row];
      return grid.length > 1 && GridRow.cellLength(currentRow) > 1 && (col > 0 && matching(GridRow.getCellElement(currentRow, col - 1)) || col < currentRow.cells().length - 1 && matching(GridRow.getCellElement(currentRow, col + 1)) || row > 0 && matching(GridRow.getCellElement(grid[row - 1], col)) || row < grid.length - 1 && matching(GridRow.getCellElement(grid[row + 1], col)));
    };
    var mergeTables = function (startAddress, gridA, gridB, generator, comparator) {
      var startRow = startAddress.row();
      var startCol = startAddress.column();
      var mergeHeight = gridB.length;
      var mergeWidth = GridRow.cellLength(gridB[0]);
      var endRow = startRow + mergeHeight;
      var endCol = startCol + mergeWidth;
      for (var r = startRow; r < endRow; r++) {
        for (var c = startCol; c < endCol; c++) {
          if (isSpanning(gridA, r, c, comparator)) {
            MergingOperations.unmerge(gridA, GridRow.getCellElement(gridA[r], c), comparator, generator.cell);
          }
          var newCell = GridRow.getCellElement(gridB[r - startRow], c - startCol);
          var replacement = generator.replace(newCell);
          GridRow.mutateCell(gridA[r], c, elementnew(replacement, true));
        }
      }
      return gridA;
    };
    var merge$1 = function (startAddress, gridA, gridB, generator, comparator) {
      var result = Fitment.measure(startAddress, gridA, gridB);
      return result.map(function (delta) {
        var fittedGrid = Fitment.tailor(gridA, delta, generator);
        return mergeTables(startAddress, fittedGrid, gridB, generator, comparator);
      });
    };
    var insert = function (index, gridA, gridB, generator, comparator) {
      MergingOperations.splitRows(gridA, index, comparator, generator.cell);
      var delta = Fitment.measureWidth(gridB, gridA);
      var fittedNewGrid = Fitment.tailor(gridB, delta, generator);
      var secondDelta = Fitment.measureWidth(gridA, fittedNewGrid);
      var fittedOldGrid = Fitment.tailor(gridA, secondDelta, generator);
      return fittedOldGrid.slice(0, index).concat(fittedNewGrid).concat(fittedOldGrid.slice(index, fittedOldGrid.length));
    };
    var TableMerge = {
      merge: merge$1,
      insert: insert
    };

    var insertRowAt = function (grid, index, example, comparator, substitution) {
      var before = grid.slice(0, index);
      var after = grid.slice(index);
      var between = GridRow.mapCells(grid[example], function (ex, c) {
        var withinSpan = index > 0 && index < grid.length && comparator(GridRow.getCellElement(grid[index - 1], c), GridRow.getCellElement(grid[index], c));
        var ret = withinSpan ? GridRow.getCell(grid[index], c) : elementnew(substitution(ex.element(), comparator), true);
        return ret;
      });
      return before.concat([between]).concat(after);
    };
    var insertColumnAt = function (grid, index, example, comparator, substitution) {
      return map(grid, function (row) {
        var withinSpan = index > 0 && index < GridRow.cellLength(row) && comparator(GridRow.getCellElement(row, index - 1), GridRow.getCellElement(row, index));
        var sub = withinSpan ? GridRow.getCell(row, index) : elementnew(substitution(GridRow.getCellElement(row, example), comparator), true);
        return GridRow.addCell(row, index, sub);
      });
    };
    var splitCellIntoColumns = function (grid, exampleRow, exampleCol, comparator, substitution) {
      var index = exampleCol + 1;
      return map(grid, function (row, i) {
        var isTargetCell = i === exampleRow;
        var sub = isTargetCell ? elementnew(substitution(GridRow.getCellElement(row, exampleCol), comparator), true) : GridRow.getCell(row, exampleCol);
        return GridRow.addCell(row, index, sub);
      });
    };
    var splitCellIntoRows = function (grid, exampleRow, exampleCol, comparator, substitution) {
      var index = exampleRow + 1;
      var before = grid.slice(0, index);
      var after = grid.slice(index);
      var between = GridRow.mapCells(grid[exampleRow], function (ex, i) {
        var isTargetCell = i === exampleCol;
        return isTargetCell ? elementnew(substitution(ex.element(), comparator), true) : ex;
      });
      return before.concat([between]).concat(after);
    };
    var deleteColumnsAt = function (grid, start, finish) {
      var rows = map(grid, function (row) {
        var cells = row.cells().slice(0, start).concat(row.cells().slice(finish + 1));
        return rowcells(cells, row.section());
      });
      return filter(rows, function (row) {
        return row.cells().length > 0;
      });
    };
    var deleteRowsAt = function (grid, start, finish) {
      return grid.slice(0, start).concat(grid.slice(finish + 1));
    };
    var ModificationOperations = {
      insertRowAt: insertRowAt,
      insertColumnAt: insertColumnAt,
      splitCellIntoColumns: splitCellIntoColumns,
      splitCellIntoRows: splitCellIntoRows,
      deleteRowsAt: deleteRowsAt,
      deleteColumnsAt: deleteColumnsAt
    };

    var replaceIn = function (grid, targets, comparator, substitution) {
      var isTarget = function (cell) {
        return exists(targets, function (target) {
          return comparator(cell.element(), target.element());
        });
      };
      return map(grid, function (row) {
        return GridRow.mapCells(row, function (cell) {
          return isTarget(cell) ? elementnew(substitution(cell.element(), comparator), true) : cell;
        });
      });
    };
    var notStartRow = function (grid, rowIndex, colIndex, comparator) {
      return GridRow.getCellElement(grid[rowIndex], colIndex) !== undefined && (rowIndex > 0 && comparator(GridRow.getCellElement(grid[rowIndex - 1], colIndex), GridRow.getCellElement(grid[rowIndex], colIndex)));
    };
    var notStartColumn = function (row, index, comparator) {
      return index > 0 && comparator(GridRow.getCellElement(row, index - 1), GridRow.getCellElement(row, index));
    };
    var replaceColumn = function (grid, index, comparator, substitution) {
      var targets = bind(grid, function (row, i) {
        var alreadyAdded = notStartRow(grid, i, index, comparator) || notStartColumn(row, index, comparator);
        return alreadyAdded ? [] : [GridRow.getCell(row, index)];
      });
      return replaceIn(grid, targets, comparator, substitution);
    };
    var replaceRow = function (grid, index, comparator, substitution) {
      var targetRow = grid[index];
      var targets = bind(targetRow.cells(), function (item, i) {
        var alreadyAdded = notStartRow(grid, index, i, comparator) || notStartColumn(targetRow, i, comparator);
        return alreadyAdded ? [] : [item];
      });
      return replaceIn(grid, targets, comparator, substitution);
    };
    var TransformOperations = {
      replaceColumn: replaceColumn,
      replaceRow: replaceRow
    };

    var adt = Adt.generate([
      { none: [] },
      { only: ['index'] },
      {
        left: [
          'index',
          'next'
        ]
      },
      {
        middle: [
          'prev',
          'index',
          'next'
        ]
      },
      {
        right: [
          'prev',
          'index'
        ]
      }
    ]);
    var ColumnContext = __assign({}, adt);

    var neighbours$1 = function (input, index) {
      if (input.length === 0) {
        return ColumnContext.none();
      }
      if (input.length === 1) {
        return ColumnContext.only(0);
      }
      if (index === 0) {
        return ColumnContext.left(0, 1);
      }
      if (index === input.length - 1) {
        return ColumnContext.right(index - 1, index);
      }
      if (index > 0 && index < input.length - 1) {
        return ColumnContext.middle(index - 1, index, index + 1);
      }
      return ColumnContext.none();
    };
    var determine = function (input, column, step, tableSize) {
      var result = input.slice(0);
      var context = neighbours$1(input, column);
      var zero = function (array) {
        return map(array, constant(0));
      };
      var onNone = constant(zero(result));
      var onOnly = function (index) {
        return tableSize.singleColumnWidth(result[index], step);
      };
      var onChange = function (index, next) {
        if (step >= 0) {
          var newNext = Math.max(tableSize.minCellWidth(), result[next] - step);
          return zero(result.slice(0, index)).concat([
            step,
            newNext - result[next]
          ]).concat(zero(result.slice(next + 1)));
        } else {
          var newThis = Math.max(tableSize.minCellWidth(), result[index] + step);
          var diffx = result[index] - newThis;
          return zero(result.slice(0, index)).concat([
            newThis - result[index],
            diffx
          ]).concat(zero(result.slice(next + 1)));
        }
      };
      var onLeft = onChange;
      var onMiddle = function (_prev, index, next) {
        return onChange(index, next);
      };
      var onRight = function (_prev, index) {
        if (step >= 0) {
          return zero(result.slice(0, index)).concat([step]);
        } else {
          var size = Math.max(tableSize.minCellWidth(), result[index] + step);
          return zero(result.slice(0, index)).concat([size - result[index]]);
        }
      };
      return context.fold(onNone, onOnly, onLeft, onMiddle, onRight);
    };
    var Deltas = { determine: determine };

    var getSpan$1 = function (cell, type) {
      return has(cell, type) && parseInt(get(cell, type), 10) > 1;
    };
    var hasColspan = function (cell) {
      return getSpan$1(cell, 'colspan');
    };
    var hasRowspan = function (cell) {
      return getSpan$1(cell, 'rowspan');
    };
    var getInt = function (element, property) {
      return parseInt(get$1(element, property), 10);
    };
    var CellUtils = {
      hasColspan: hasColspan,
      hasRowspan: hasRowspan,
      minWidth: constant(10),
      minHeight: constant(10),
      getInt: getInt
    };

    var getRaw$1 = function (cell, property, getter) {
      return getRaw(cell, property).fold(function () {
        return getter(cell) + 'px';
      }, function (raw) {
        return raw;
      });
    };
    var getRawW = function (cell, tableSize) {
      return getRaw$1(cell, 'width', function (e) {
        return Sizes.getPixelWidth(e, tableSize);
      });
    };
    var getRawH = function (cell) {
      return getRaw$1(cell, 'height', Sizes.getHeight);
    };
    var getWidthFrom = function (warehouse, direction, getWidth, fallback, tableSize) {
      var columns = Blocks.columns(warehouse);
      var backups = map(columns, function (cellOption) {
        return cellOption.map(direction.edge);
      });
      return map(columns, function (cellOption, c) {
        var columnCell = cellOption.filter(not(CellUtils.hasColspan));
        return columnCell.fold(function () {
          var deduced = deduce(backups, c);
          return fallback(deduced);
        }, function (cell) {
          return getWidth(cell, tableSize);
        });
      });
    };
    var getDeduced = function (deduced) {
      return deduced.map(function (d) {
        return d + 'px';
      }).getOr('');
    };
    var getRawWidths = function (warehouse, direction, tableSize) {
      return getWidthFrom(warehouse, direction, getRawW, getDeduced, tableSize);
    };
    var getPercentageWidths = function (warehouse, direction, tableSize) {
      return getWidthFrom(warehouse, direction, Sizes.getPercentageWidth, function (deduced) {
        return deduced.fold(function () {
          return tableSize.minCellWidth();
        }, function (cellWidth) {
          return cellWidth / tableSize.pixelWidth() * 100;
        });
      }, tableSize);
    };
    var getPixelWidths = function (warehouse, direction, tableSize) {
      return getWidthFrom(warehouse, direction, Sizes.getPixelWidth, function (deduced) {
        return deduced.getOrThunk(tableSize.minCellWidth);
      }, tableSize);
    };
    var getHeightFrom = function (warehouse, direction, getHeight, fallback) {
      var rows = Blocks.rows(warehouse);
      var backups = map(rows, function (cellOption) {
        return cellOption.map(direction.edge);
      });
      return map(rows, function (cellOption, c) {
        var rowCell = cellOption.filter(not(CellUtils.hasRowspan));
        return rowCell.fold(function () {
          var deduced = deduce(backups, c);
          return fallback(deduced);
        }, function (cell) {
          return getHeight(cell);
        });
      });
    };
    var getPixelHeights = function (warehouse, direction) {
      return getHeightFrom(warehouse, direction, Sizes.getHeight, function (deduced) {
        return deduced.getOrThunk(CellUtils.minHeight);
      });
    };
    var getRawHeights = function (warehouse, direction) {
      return getHeightFrom(warehouse, direction, getRawH, getDeduced);
    };
    var ColumnSizes = {
      getRawWidths: getRawWidths,
      getPixelWidths: getPixelWidths,
      getPercentageWidths: getPercentageWidths,
      getPixelHeights: getPixelHeights,
      getRawHeights: getRawHeights
    };

    var total = function (start, end, measures) {
      var r = 0;
      for (var i = start; i < end; i++) {
        r += measures[i] !== undefined ? measures[i] : 0;
      }
      return r;
    };
    var recalculateWidth = function (warehouse, widths) {
      var all = Warehouse.justCells(warehouse);
      return map(all, function (cell) {
        var width = total(cell.column(), cell.column() + cell.colspan(), widths);
        return {
          element: cell.element,
          width: constant(width),
          colspan: cell.colspan
        };
      });
    };
    var recalculateHeight = function (warehouse, heights) {
      var all = Warehouse.justCells(warehouse);
      return map(all, function (cell) {
        var height = total(cell.row(), cell.row() + cell.rowspan(), heights);
        return {
          element: cell.element,
          height: constant(height),
          rowspan: cell.rowspan
        };
      });
    };
    var matchRowHeight = function (warehouse, heights) {
      return map(warehouse.all(), function (row, i) {
        return {
          element: row.element,
          height: constant(heights[i])
        };
      });
    };
    var Recalculations = {
      recalculateWidth: recalculateWidth,
      recalculateHeight: recalculateHeight,
      matchRowHeight: matchRowHeight
    };

    var percentageSize = function (width, element) {
      var floatWidth = parseFloat(width);
      var pixelWidth = get$4(element);
      var getCellDelta = function (delta) {
        return delta / pixelWidth * 100;
      };
      var singleColumnWidth = function (w, _delta) {
        return [100 - w];
      };
      var minCellWidth = function () {
        return CellUtils.minWidth() / pixelWidth * 100;
      };
      var setTableWidth = function (table, _newWidths, delta) {
        var ratio = delta / 100;
        var change = ratio * floatWidth;
        Sizes.setPercentageWidth(table, floatWidth + change);
      };
      return {
        width: constant(floatWidth),
        pixelWidth: constant(pixelWidth),
        getWidths: ColumnSizes.getPercentageWidths,
        getCellDelta: getCellDelta,
        singleColumnWidth: singleColumnWidth,
        minCellWidth: minCellWidth,
        setElementWidth: Sizes.setPercentageWidth,
        setTableWidth: setTableWidth
      };
    };
    var pixelSize = function (width) {
      var getCellDelta = identity;
      var singleColumnWidth = function (w, delta) {
        var newNext = Math.max(CellUtils.minWidth(), w + delta);
        return [newNext - w];
      };
      var setTableWidth = function (table, newWidths, _delta) {
        var total = foldr(newWidths, function (b, a) {
          return b + a;
        }, 0);
        Sizes.setPixelWidth(table, total);
      };
      return {
        width: constant(width),
        pixelWidth: constant(width),
        getWidths: ColumnSizes.getPixelWidths,
        getCellDelta: getCellDelta,
        singleColumnWidth: singleColumnWidth,
        minCellWidth: CellUtils.minWidth,
        setElementWidth: Sizes.setPixelWidth,
        setTableWidth: setTableWidth
      };
    };
    var chooseSize = function (element, width) {
      var percentMatch = Sizes.percentageBasedSizeRegex().exec(width);
      if (percentMatch !== null) {
        return percentageSize(percentMatch[1], element);
      }
      var pixelMatch = Sizes.pixelBasedSizeRegex().exec(width);
      if (pixelMatch !== null) {
        var intWidth = parseInt(pixelMatch[1], 10);
        return pixelSize(intWidth);
      }
      var fallbackWidth = get$4(element);
      return pixelSize(fallbackWidth);
    };
    var getTableSize = function (element) {
      var width = Sizes.getRawWidth(element);
      return width.fold(function () {
        var fallbackWidth = get$4(element);
        return pixelSize(fallbackWidth);
      }, function (w) {
        return chooseSize(element, w);
      });
    };
    var TableSize = { getTableSize: getTableSize };

    var getWarehouse$1 = function (list) {
      return Warehouse.generate(list);
    };
    var sumUp = function (newSize) {
      return foldr(newSize, function (b, a) {
        return b + a;
      }, 0);
    };
    var getTableWarehouse = function (table) {
      var list = DetailsList.fromTable(table);
      return getWarehouse$1(list);
    };
    var adjustWidth = function (table, delta, index, direction) {
      var tableSize = TableSize.getTableSize(table);
      var step = tableSize.getCellDelta(delta);
      var warehouse = getTableWarehouse(table);
      var widths = tableSize.getWidths(warehouse, direction, tableSize);
      var deltas = Deltas.determine(widths, index, step, tableSize);
      var newWidths = map(deltas, function (dx, i) {
        return dx + widths[i];
      });
      var newSizes = Recalculations.recalculateWidth(warehouse, newWidths);
      each(newSizes, function (cell) {
        tableSize.setElementWidth(cell.element(), cell.width());
      });
      if (index === warehouse.grid().columns() - 1) {
        tableSize.setTableWidth(table, newWidths, step);
      }
    };
    var adjustHeight = function (table, delta, index, direction) {
      var warehouse = getTableWarehouse(table);
      var heights = ColumnSizes.getPixelHeights(warehouse, direction);
      var newHeights = map(heights, function (dy, i) {
        return index === i ? Math.max(delta + dy, CellUtils.minHeight()) : dy;
      });
      var newCellSizes = Recalculations.recalculateHeight(warehouse, newHeights);
      var newRowSizes = Recalculations.matchRowHeight(warehouse, newHeights);
      each(newRowSizes, function (row) {
        Sizes.setHeight(row.element(), row.height());
      });
      each(newCellSizes, function (cell) {
        Sizes.setHeight(cell.element(), cell.height());
      });
      var total = sumUp(newHeights);
      Sizes.setHeight(table, total);
    };
    var adjustWidthTo = function (table, list, direction) {
      var tableSize = TableSize.getTableSize(table);
      var warehouse = getWarehouse$1(list);
      var widths = tableSize.getWidths(warehouse, direction, tableSize);
      var newSizes = Recalculations.recalculateWidth(warehouse, widths);
      each(newSizes, function (cell) {
        tableSize.setElementWidth(cell.element(), cell.width());
      });
      if (newSizes.length > 0) {
        tableSize.setTableWidth(table, widths, tableSize.getCellDelta(0));
      }
    };
    var Adjustments = {
      adjustWidth: adjustWidth,
      adjustHeight: adjustHeight,
      adjustWidthTo: adjustWidthTo
    };

    var Cell = function (initial) {
      var value = initial;
      var get = function () {
        return value;
      };
      var set = function (v) {
        value = v;
      };
      var clone = function () {
        return Cell(get());
      };
      return {
        get: get,
        set: set,
        clone: clone
      };
    };

    var base = function (handleUnsupported, required) {
      return baseWith(handleUnsupported, required, {
        validate: isFunction,
        label: 'function'
      });
    };
    var baseWith = function (handleUnsupported, required, pred) {
      if (required.length === 0) {
        throw new Error('You must specify at least one required field.');
      }
      validateStrArr('required', required);
      checkDupes(required);
      return function (obj) {
        var keys$1 = keys(obj);
        var allReqd = forall(required, function (req) {
          return contains(keys$1, req);
        });
        if (!allReqd) {
          reqMessage(required, keys$1);
        }
        handleUnsupported(required, keys$1);
        var invalidKeys = filter(required, function (key) {
          return !pred.validate(obj[key], key);
        });
        if (invalidKeys.length > 0) {
          invalidTypeMessage(invalidKeys, pred.label);
        }
        return obj;
      };
    };
    var handleExact = function (required, keys) {
      var unsupported = filter(keys, function (key) {
        return !contains(required, key);
      });
      if (unsupported.length > 0) {
        unsuppMessage(unsupported);
      }
    };
    var exactly = function (required) {
      return base(handleExact, required);
    };

    var verifyGenerators = exactly([
      'cell',
      'row',
      'replace',
      'gap'
    ]);
    var elementToData = function (element) {
      var colspan = has(element, 'colspan') ? parseInt(get(element, 'colspan'), 10) : 1;
      var rowspan = has(element, 'rowspan') ? parseInt(get(element, 'rowspan'), 10) : 1;
      return {
        element: constant(element),
        colspan: constant(colspan),
        rowspan: constant(rowspan)
      };
    };
    var modification = function (generators, toData) {
      if (toData === void 0) {
        toData = elementToData;
      }
      verifyGenerators(generators);
      var position = Cell(Option.none());
      var nu = function (data) {
        return generators.cell(data);
      };
      var nuFrom = function (element) {
        var data = toData(element);
        return nu(data);
      };
      var add = function (element) {
        var replacement = nuFrom(element);
        if (position.get().isNone()) {
          position.set(Option.some(replacement));
        }
        recent = Option.some({
          item: element,
          replacement: replacement
        });
        return replacement;
      };
      var recent = Option.none();
      var getOrInit = function (element, comparator) {
        return recent.fold(function () {
          return add(element);
        }, function (p) {
          return comparator(element, p.item) ? p.replacement : add(element);
        });
      };
      return {
        getOrInit: getOrInit,
        cursor: position.get
      };
    };
    var transform = function (scope, tag) {
      return function (generators) {
        var position = Cell(Option.none());
        verifyGenerators(generators);
        var list = [];
        var find$1 = function (element, comparator) {
          return find(list, function (x) {
            return comparator(x.item, element);
          });
        };
        var makeNew = function (element) {
          var attrs = { scope: scope };
          var cell = generators.replace(element, tag, attrs);
          list.push({
            item: element,
            sub: cell
          });
          if (position.get().isNone()) {
            position.set(Option.some(cell));
          }
          return cell;
        };
        var replaceOrInit = function (element, comparator) {
          return find$1(element, comparator).fold(function () {
            return makeNew(element);
          }, function (p) {
            return comparator(element, p.item) ? p.sub : makeNew(element);
          });
        };
        return {
          replaceOrInit: replaceOrInit,
          cursor: position.get
        };
      };
    };
    var merging = function (generators) {
      verifyGenerators(generators);
      var position = Cell(Option.none());
      var combine = function (cell) {
        if (position.get().isNone()) {
          position.set(Option.some(cell));
        }
        return function () {
          var raw = generators.cell({
            element: constant(cell),
            colspan: constant(1),
            rowspan: constant(1)
          });
          remove$1(raw, 'width');
          remove$1(cell, 'width');
          return raw;
        };
      };
      return {
        combine: combine,
        cursor: position.get
      };
    };
    var Generators = {
      modification: modification,
      transform: transform,
      merging: merging
    };

    var blockList = [
      'body',
      'p',
      'div',
      'article',
      'aside',
      'figcaption',
      'figure',
      'footer',
      'header',
      'nav',
      'section',
      'ol',
      'ul',
      'table',
      'thead',
      'tfoot',
      'tbody',
      'caption',
      'tr',
      'td',
      'th',
      'h1',
      'h2',
      'h3',
      'h4',
      'h5',
      'h6',
      'blockquote',
      'pre',
      'address'
    ];
    var isList = function (universe, item) {
      var tagName = universe.property().name(item);
      return contains([
        'ol',
        'ul'
      ], tagName);
    };
    var isBlock = function (universe, item) {
      var tagName = universe.property().name(item);
      return contains(blockList, tagName);
    };
    var isFormatting = function (universe, item) {
      var tagName = universe.property().name(item);
      return contains([
        'address',
        'pre',
        'p',
        'h1',
        'h2',
        'h3',
        'h4',
        'h5',
        'h6'
      ], tagName);
    };
    var isHeading = function (universe, item) {
      var tagName = universe.property().name(item);
      return contains([
        'h1',
        'h2',
        'h3',
        'h4',
        'h5',
        'h6'
      ], tagName);
    };
    var isContainer = function (universe, item) {
      return contains([
        'div',
        'li',
        'td',
        'th',
        'blockquote',
        'body',
        'caption'
      ], universe.property().name(item));
    };
    var isEmptyTag = function (universe, item) {
      return contains([
        'br',
        'img',
        'hr',
        'input'
      ], universe.property().name(item));
    };
    var isFrame = function (universe, item) {
      return universe.property().name(item) === 'iframe';
    };
    var isInline = function (universe, item) {
      return !(isBlock(universe, item) || isEmptyTag(universe, item)) && universe.property().name(item) !== 'li';
    };
    var Structure = {
      isBlock: isBlock,
      isList: isList,
      isFormatting: isFormatting,
      isHeading: isHeading,
      isContainer: isContainer,
      isEmptyTag: isEmptyTag,
      isFrame: isFrame,
      isInline: isInline
    };

    var universe$1 = DomUniverse();
    var isBlock$1 = function (element) {
      return Structure.isBlock(universe$1, element);
    };
    var isList$1 = function (element) {
      return Structure.isList(universe$1, element);
    };
    var isFormatting$1 = function (element) {
      return Structure.isFormatting(universe$1, element);
    };
    var isHeading$1 = function (element) {
      return Structure.isHeading(universe$1, element);
    };
    var isContainer$1 = function (element) {
      return Structure.isContainer(universe$1, element);
    };
    var isEmptyTag$1 = function (element) {
      return Structure.isEmptyTag(universe$1, element);
    };
    var isFrame$1 = function (element) {
      return Structure.isFrame(universe$1, element);
    };
    var isInline$1 = function (element) {
      return Structure.isInline(universe$1, element);
    };
    var DomStructure = {
      isBlock: isBlock$1,
      isList: isList$1,
      isFormatting: isFormatting$1,
      isHeading: isHeading$1,
      isContainer: isContainer$1,
      isEmptyTag: isEmptyTag$1,
      isFrame: isFrame$1,
      isInline: isInline$1
    };

    var merge$2 = function (cells) {
      var isBr = function (el) {
        return name(el) === 'br';
      };
      var advancedBr = function (children) {
        return forall(children, function (c) {
          return isBr(c) || isText(c) && get$2(c).trim().length === 0;
        });
      };
      var isListItem = function (el) {
        return name(el) === 'li' || ancestor(el, DomStructure.isList).isSome();
      };
      var siblingIsBlock = function (el) {
        return nextSibling(el).map(function (rightSibling) {
          if (DomStructure.isBlock(rightSibling)) {
            return true;
          }
          if (DomStructure.isEmptyTag(rightSibling)) {
            return name(rightSibling) === 'img' ? false : true;
          }
          return false;
        }).getOr(false);
      };
      var markCell = function (cell) {
        return last$1(cell).bind(function (rightEdge) {
          var rightSiblingIsBlock = siblingIsBlock(rightEdge);
          return parent(rightEdge).map(function (parent) {
            return rightSiblingIsBlock === true || isListItem(parent) || isBr(rightEdge) || DomStructure.isBlock(parent) && !eq(cell, parent) ? [] : [Element.fromTag('br')];
          });
        }).getOr([]);
      };
      var markContent = function () {
        var content = bind(cells, function (cell) {
          var children$1 = children(cell);
          return advancedBr(children$1) ? [] : children$1.concat(markCell(cell));
        });
        return content.length === 0 ? [Element.fromTag('br')] : content;
      };
      var contents = markContent();
      empty(cells[0]);
      append$1(cells[0], contents);
    };
    var TableContent = { merge: merge$2 };

    var prune = function (table) {
      var cells = TableLookup.cells(table);
      if (cells.length === 0) {
        remove$2(table);
      }
    };
    var outcome = Immutable('grid', 'cursor');
    var elementFromGrid = function (grid, row, column) {
      return findIn(grid, row, column).orThunk(function () {
        return findIn(grid, 0, 0);
      });
    };
    var findIn = function (grid, row, column) {
      return Option.from(grid[row]).bind(function (r) {
        return Option.from(r.cells()[column]).bind(function (c) {
          return Option.from(c.element());
        });
      });
    };
    var bundle = function (grid, row, column) {
      return outcome(grid, findIn(grid, row, column));
    };
    var uniqueRows = function (details) {
      return foldl(details, function (rest, detail) {
        return exists(rest, function (currentDetail) {
          return currentDetail.row() === detail.row();
        }) ? rest : rest.concat([detail]);
      }, []).sort(function (detailA, detailB) {
        return detailA.row() - detailB.row();
      });
    };
    var uniqueColumns = function (details) {
      return foldl(details, function (rest, detail) {
        return exists(rest, function (currentDetail) {
          return currentDetail.column() === detail.column();
        }) ? rest : rest.concat([detail]);
      }, []).sort(function (detailA, detailB) {
        return detailA.column() - detailB.column();
      });
    };
    var insertRowBefore = function (grid, detail, comparator, genWrappers) {
      var example = detail.row();
      var targetIndex = detail.row();
      var newGrid = ModificationOperations.insertRowAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, targetIndex, detail.column());
    };
    var insertRowsBefore = function (grid, details, comparator, genWrappers) {
      var example = details[0].row();
      var targetIndex = details[0].row();
      var rows = uniqueRows(details);
      var newGrid = foldl(rows, function (newG, _row) {
        return ModificationOperations.insertRowAt(newG, targetIndex, example, comparator, genWrappers.getOrInit);
      }, grid);
      return bundle(newGrid, targetIndex, details[0].column());
    };
    var insertRowAfter = function (grid, detail, comparator, genWrappers) {
      var example = detail.row();
      var targetIndex = detail.row() + detail.rowspan();
      var newGrid = ModificationOperations.insertRowAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, targetIndex, detail.column());
    };
    var insertRowsAfter = function (grid, details, comparator, genWrappers) {
      var rows = uniqueRows(details);
      var example = rows[rows.length - 1].row();
      var targetIndex = rows[rows.length - 1].row() + rows[rows.length - 1].rowspan();
      var newGrid = foldl(rows, function (newG, _row) {
        return ModificationOperations.insertRowAt(newG, targetIndex, example, comparator, genWrappers.getOrInit);
      }, grid);
      return bundle(newGrid, targetIndex, details[0].column());
    };
    var insertColumnBefore = function (grid, detail, comparator, genWrappers) {
      var example = detail.column();
      var targetIndex = detail.column();
      var newGrid = ModificationOperations.insertColumnAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, detail.row(), targetIndex);
    };
    var insertColumnsBefore = function (grid, details, comparator, genWrappers) {
      var columns = uniqueColumns(details);
      var example = columns[0].column();
      var targetIndex = columns[0].column();
      var newGrid = foldl(columns, function (newG, _row) {
        return ModificationOperations.insertColumnAt(newG, targetIndex, example, comparator, genWrappers.getOrInit);
      }, grid);
      return bundle(newGrid, details[0].row(), targetIndex);
    };
    var insertColumnAfter = function (grid, detail, comparator, genWrappers) {
      var example = detail.column();
      var targetIndex = detail.column() + detail.colspan();
      var newGrid = ModificationOperations.insertColumnAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, detail.row(), targetIndex);
    };
    var insertColumnsAfter = function (grid, details, comparator, genWrappers) {
      var example = details[details.length - 1].column();
      var targetIndex = details[details.length - 1].column() + details[details.length - 1].colspan();
      var columns = uniqueColumns(details);
      var newGrid = foldl(columns, function (newG, _row) {
        return ModificationOperations.insertColumnAt(newG, targetIndex, example, comparator, genWrappers.getOrInit);
      }, grid);
      return bundle(newGrid, details[0].row(), targetIndex);
    };
    var makeRowHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceRow(grid, detail.row(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };
    var makeColumnHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceColumn(grid, detail.column(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };
    var unmakeRowHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceRow(grid, detail.row(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };
    var unmakeColumnHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceColumn(grid, detail.column(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };
    var splitCellIntoColumns$1 = function (grid, detail, comparator, genWrappers) {
      var newGrid = ModificationOperations.splitCellIntoColumns(grid, detail.row(), detail.column(), comparator, genWrappers.getOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };
    var splitCellIntoRows$1 = function (grid, detail, comparator, genWrappers) {
      var newGrid = ModificationOperations.splitCellIntoRows(grid, detail.row(), detail.column(), comparator, genWrappers.getOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };
    var eraseColumns = function (grid, details, _comparator, _genWrappers) {
      var columns = uniqueColumns(details);
      var newGrid = ModificationOperations.deleteColumnsAt(grid, columns[0].column(), columns[columns.length - 1].column());
      var cursor = elementFromGrid(newGrid, details[0].row(), details[0].column());
      return outcome(newGrid, cursor);
    };
    var eraseRows = function (grid, details, _comparator, _genWrappers) {
      var rows = uniqueRows(details);
      var newGrid = ModificationOperations.deleteRowsAt(grid, rows[0].row(), rows[rows.length - 1].row());
      var cursor = elementFromGrid(newGrid, details[0].row(), details[0].column());
      return outcome(newGrid, cursor);
    };
    var mergeCells = function (grid, mergable, comparator, _genWrappers) {
      var cells = mergable.cells();
      TableContent.merge(cells);
      var newGrid = MergingOperations.merge(grid, mergable.bounds(), comparator, constant(cells[0]));
      return outcome(newGrid, Option.from(cells[0]));
    };
    var unmergeCells = function (grid, unmergable, comparator, genWrappers) {
      var newGrid = foldr(unmergable, function (b, cell) {
        return MergingOperations.unmerge(b, cell, comparator, genWrappers.combine(cell));
      }, grid);
      return outcome(newGrid, Option.from(unmergable[0]));
    };
    var pasteCells = function (grid, pasteDetails, comparator, _genWrappers) {
      var gridify = function (table, generators) {
        var list = DetailsList.fromTable(table);
        var wh = Warehouse.generate(list);
        return Transitions.toGrid(wh, generators, true);
      };
      var gridB = gridify(pasteDetails.clipboard(), pasteDetails.generators());
      var startAddress = address(pasteDetails.row(), pasteDetails.column());
      var mergedGrid = TableMerge.merge(startAddress, grid, gridB, pasteDetails.generators(), comparator);
      return mergedGrid.fold(function () {
        return outcome(grid, Option.some(pasteDetails.element()));
      }, function (nuGrid) {
        var cursor = elementFromGrid(nuGrid, pasteDetails.row(), pasteDetails.column());
        return outcome(nuGrid, cursor);
      });
    };
    var gridifyRows = function (rows, generators, example) {
      var pasteDetails = DetailsList.fromPastedRows(rows, example);
      var wh = Warehouse.generate(pasteDetails);
      return Transitions.toGrid(wh, generators, true);
    };
    var pasteRowsBefore = function (grid, pasteDetails, comparator, _genWrappers) {
      var example = grid[pasteDetails.cells[0].row()];
      var index = pasteDetails.cells[0].row();
      var gridB = gridifyRows(pasteDetails.clipboard(), pasteDetails.generators(), example);
      var mergedGrid = TableMerge.insert(index, grid, gridB, pasteDetails.generators(), comparator);
      var cursor = elementFromGrid(mergedGrid, pasteDetails.cells[0].row(), pasteDetails.cells[0].column());
      return outcome(mergedGrid, cursor);
    };
    var pasteRowsAfter = function (grid, pasteDetails, comparator, _genWrappers) {
      var example = grid[pasteDetails.cells[0].row()];
      var index = pasteDetails.cells[pasteDetails.cells.length - 1].row() + pasteDetails.cells[pasteDetails.cells.length - 1].rowspan();
      var gridB = gridifyRows(pasteDetails.clipboard(), pasteDetails.generators(), example);
      var mergedGrid = TableMerge.insert(index, grid, gridB, pasteDetails.generators(), comparator);
      var cursor = elementFromGrid(mergedGrid, pasteDetails.cells[0].row(), pasteDetails.cells[0].column());
      return outcome(mergedGrid, cursor);
    };
    var resize = Adjustments.adjustWidthTo;
    var TableOperations = {
      insertRowBefore: run(insertRowBefore, onCell, noop, noop, Generators.modification),
      insertRowsBefore: run(insertRowsBefore, onCells, noop, noop, Generators.modification),
      insertRowAfter: run(insertRowAfter, onCell, noop, noop, Generators.modification),
      insertRowsAfter: run(insertRowsAfter, onCells, noop, noop, Generators.modification),
      insertColumnBefore: run(insertColumnBefore, onCell, resize, noop, Generators.modification),
      insertColumnsBefore: run(insertColumnsBefore, onCells, resize, noop, Generators.modification),
      insertColumnAfter: run(insertColumnAfter, onCell, resize, noop, Generators.modification),
      insertColumnsAfter: run(insertColumnsAfter, onCells, resize, noop, Generators.modification),
      splitCellIntoColumns: run(splitCellIntoColumns$1, onCell, resize, noop, Generators.modification),
      splitCellIntoRows: run(splitCellIntoRows$1, onCell, noop, noop, Generators.modification),
      eraseColumns: run(eraseColumns, onCells, resize, prune, Generators.modification),
      eraseRows: run(eraseRows, onCells, noop, prune, Generators.modification),
      makeColumnHeader: run(makeColumnHeader, onCell, noop, noop, Generators.transform('row', 'th')),
      unmakeColumnHeader: run(unmakeColumnHeader, onCell, noop, noop, Generators.transform(null, 'td')),
      makeRowHeader: run(makeRowHeader, onCell, noop, noop, Generators.transform('col', 'th')),
      unmakeRowHeader: run(unmakeRowHeader, onCell, noop, noop, Generators.transform(null, 'td')),
      mergeCells: run(mergeCells, onMergable, noop, noop, Generators.merging),
      unmergeCells: run(unmergeCells, onUnmergable, resize, noop, Generators.merging),
      pasteCells: run(pasteCells, onPaste, resize, noop, Generators.modification),
      pasteRowsBefore: run(pasteRowsBefore, onPasteRows, noop, noop, Generators.modification),
      pasteRowsAfter: run(pasteRowsAfter, onPasteRows, noop, noop, Generators.modification)
    };

    var getBody$1 = function (editor) {
      return Element.fromDom(editor.getBody());
    };
    var getPixelWidth$1 = function (elm) {
      return elm.getBoundingClientRect().width;
    };
    var getPixelHeight = function (elm) {
      return elm.getBoundingClientRect().height;
    };
    var getIsRoot = function (editor) {
      return function (element) {
        return eq(element, getBody$1(editor));
      };
    };
    var removePxSuffix = function (size) {
      return size ? size.replace(/px$/, '') : '';
    };
    var addSizeSuffix = function (size) {
      if (/^[0-9]+$/.test(size)) {
        size += 'px';
      }
      return size;
    };
    var removeDataStyle = function (table) {
      var dataStyleCells = descendants$1(table, 'td[data-mce-style],th[data-mce-style]');
      remove(table, 'data-mce-style');
      each(dataStyleCells, function (cell) {
        remove(cell, 'data-mce-style');
      });
    };

    var getDirection = function (element) {
      return get$1(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
    };

    var ltr$1 = { isRtl: constant(false) };
    var rtl$1 = { isRtl: constant(true) };
    var directionAt = function (element) {
      var dir = getDirection(element);
      return dir === 'rtl' ? rtl$1 : ltr$1;
    };
    var Direction = { directionAt: directionAt };

    var defaultTableToolbar = [
      'tableprops',
      'tabledelete',
      '|',
      'tableinsertrowbefore',
      'tableinsertrowafter',
      'tabledeleterow',
      '|',
      'tableinsertcolbefore',
      'tableinsertcolafter',
      'tabledeletecol'
    ];
    var defaultStyles = {
      'border-collapse': 'collapse',
      'width': '100%'
    };
    var defaultAttributes = { border: '1' };
    var getDefaultAttributes = function (editor) {
      return editor.getParam('table_default_attributes', defaultAttributes, 'object');
    };
    var getDefaultStyles = function (editor) {
      return editor.getParam('table_default_styles', defaultStyles, 'object');
    };
    var hasTableResizeBars = function (editor) {
      return editor.getParam('table_resize_bars', true, 'boolean');
    };
    var hasTabNavigation = function (editor) {
      return editor.getParam('table_tab_navigation', true, 'boolean');
    };
    var hasAdvancedCellTab = function (editor) {
      return editor.getParam('table_cell_advtab', true, 'boolean');
    };
    var hasAdvancedRowTab = function (editor) {
      return editor.getParam('table_row_advtab', true, 'boolean');
    };
    var hasAdvancedTableTab = function (editor) {
      return editor.getParam('table_advtab', true, 'boolean');
    };
    var hasAppearanceOptions = function (editor) {
      return editor.getParam('table_appearance_options', true, 'boolean');
    };
    var hasTableGrid = function (editor) {
      return editor.getParam('table_grid', true, 'boolean');
    };
    var shouldStyleWithCss = function (editor) {
      return editor.getParam('table_style_by_css', false, 'boolean');
    };
    var getCellClassList = function (editor) {
      return editor.getParam('table_cell_class_list', [], 'array');
    };
    var getRowClassList = function (editor) {
      return editor.getParam('table_row_class_list', [], 'array');
    };
    var getTableClassList = function (editor) {
      return editor.getParam('table_class_list', [], 'array');
    };
    var getColorPickerCallback = function (editor) {
      return editor.getParam('color_picker_callback');
    };
    var isPixelsForced = function (editor) {
      return editor.getParam('table_responsive_width') === false;
    };
    var getCloneElements = function (editor) {
      var cloneElements = editor.getParam('table_clone_elements');
      if (isString(cloneElements)) {
        return Option.some(cloneElements.split(/[ ,]/));
      } else if (Array.isArray(cloneElements)) {
        return Option.some(cloneElements);
      } else {
        return Option.none();
      }
    };
    var hasObjectResizing = function (editor) {
      var objectResizing = editor.getParam('object_resizing', true);
      return objectResizing === 'table' || objectResizing;
    };
    var getToolbar = function (editor) {
      var toolbar = editor.getParam('table_toolbar', defaultTableToolbar);
      if (toolbar === '' || toolbar === false) {
        return [];
      } else if (isString(toolbar)) {
        return toolbar.split(/[ ,]/);
      } else if (isArray(toolbar)) {
        return toolbar;
      } else {
        return [];
      }
    };

    var fireNewRow = function (editor, row) {
      return editor.fire('newrow', { node: row });
    };
    var fireNewCell = function (editor, cell) {
      return editor.fire('newcell', { node: cell });
    };
    var fireObjectResizeStart = function (editor, target, width, height) {
      editor.fire('ObjectResizeStart', {
        target: target,
        width: width,
        height: height
      });
    };
    var fireObjectResized = function (editor, target, width, height) {
      editor.fire('ObjectResized', {
        target: target,
        width: width,
        height: height
      });
    };

    var TableActions = function (editor, lazyWire) {
      var isTableBody = function (editor) {
        return name(getBody$1(editor)) === 'table';
      };
      var lastRowGuard = function (table) {
        var size = TableGridSize.getGridSize(table);
        return isTableBody(editor) === false || size.rows() > 1;
      };
      var lastColumnGuard = function (table) {
        var size = TableGridSize.getGridSize(table);
        return isTableBody(editor) === false || size.columns() > 1;
      };
      var cloneFormats = getCloneElements(editor);
      var execute = function (operation, guard, mutate, lazyWire) {
        return function (table, target) {
          removeDataStyle(table);
          var wire = lazyWire();
          var doc = Element.fromDom(editor.getDoc());
          var direction = TableDirection(Direction.directionAt);
          var generators = TableFill.cellOperations(mutate, doc, cloneFormats);
          return guard(table) ? operation(wire, table, target, generators, direction).bind(function (result) {
            each(result.newRows(), function (row) {
              fireNewRow(editor, row.dom());
            });
            each(result.newCells(), function (cell) {
              fireNewCell(editor, cell.dom());
            });
            return result.cursor().map(function (cell) {
              var rng = editor.dom.createRng();
              rng.setStart(cell.dom(), 0);
              rng.setEnd(cell.dom(), 0);
              return rng;
            });
          }) : Option.none();
        };
      };
      var deleteRow = execute(TableOperations.eraseRows, lastRowGuard, noop, lazyWire);
      var deleteColumn = execute(TableOperations.eraseColumns, lastColumnGuard, noop, lazyWire);
      var insertRowsBefore = execute(TableOperations.insertRowsBefore, always, noop, lazyWire);
      var insertRowsAfter = execute(TableOperations.insertRowsAfter, always, noop, lazyWire);
      var insertColumnsBefore = execute(TableOperations.insertColumnsBefore, always, CellMutations.halve, lazyWire);
      var insertColumnsAfter = execute(TableOperations.insertColumnsAfter, always, CellMutations.halve, lazyWire);
      var mergeCells = execute(TableOperations.mergeCells, always, noop, lazyWire);
      var unmergeCells = execute(TableOperations.unmergeCells, always, noop, lazyWire);
      var pasteRowsBefore = execute(TableOperations.pasteRowsBefore, always, noop, lazyWire);
      var pasteRowsAfter = execute(TableOperations.pasteRowsAfter, always, noop, lazyWire);
      var pasteCells = execute(TableOperations.pasteCells, always, noop, lazyWire);
      return {
        deleteRow: deleteRow,
        deleteColumn: deleteColumn,
        insertRowsBefore: insertRowsBefore,
        insertRowsAfter: insertRowsAfter,
        insertColumnsBefore: insertColumnsBefore,
        insertColumnsAfter: insertColumnsAfter,
        mergeCells: mergeCells,
        unmergeCells: unmergeCells,
        pasteRowsBefore: pasteRowsBefore,
        pasteRowsAfter: pasteRowsAfter,
        pasteCells: pasteCells
      };
    };

    var copyRows = function (table, target, generators) {
      var list = DetailsList.fromTable(table);
      var house = Warehouse.generate(list);
      var details = onCells(house, target);
      return details.map(function (selectedCells) {
        var grid = Transitions.toGrid(house, generators, false);
        var slicedGrid = grid.slice(selectedCells[0].row(), selectedCells[selectedCells.length - 1].row() + selectedCells[selectedCells.length - 1].rowspan());
        var slicedDetails = toDetailList(slicedGrid, generators);
        return Redraw.copy(slicedDetails);
      });
    };
    var CopyRows = { copyRows: copyRows };

    var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    var getTDTHOverallStyle = function (dom, elm, name) {
      var cells = dom.select('td,th', elm);
      var firstChildStyle;
      var checkChildren = function (firstChildStyle, elms) {
        for (var i = 0; i < elms.length; i++) {
          var currentStyle = dom.getStyle(elms[i], name);
          if (typeof firstChildStyle === 'undefined') {
            firstChildStyle = currentStyle;
          }
          if (firstChildStyle !== currentStyle) {
            return '';
          }
        }
        return firstChildStyle;
      };
      firstChildStyle = checkChildren(firstChildStyle, cells);
      return firstChildStyle;
    };
    var applyAlign = function (editor, elm, name) {
      if (name) {
        editor.formatter.apply('align' + name, {}, elm);
      }
    };
    var applyVAlign = function (editor, elm, name) {
      if (name) {
        editor.formatter.apply('valign' + name, {}, elm);
      }
    };
    var unApplyAlign = function (editor, elm) {
      global$1.each('left center right'.split(' '), function (name) {
        editor.formatter.remove('align' + name, {}, elm);
      });
    };
    var unApplyVAlign = function (editor, elm) {
      global$1.each('top middle bottom'.split(' '), function (name) {
        editor.formatter.remove('valign' + name, {}, elm);
      });
    };
    var Styles$1 = {
      applyAlign: applyAlign,
      applyVAlign: applyVAlign,
      unApplyAlign: unApplyAlign,
      unApplyVAlign: unApplyVAlign,
      getTDTHOverallStyle: getTDTHOverallStyle
    };

    var buildListItems = function (inputList, itemCallback, startItems) {
      var appendItems = function (values, output) {
        output = output || [];
        global$1.each(values, function (item) {
          var menuItem = { text: item.text || item.title };
          if (item.menu) {
            menuItem.menu = appendItems(item.menu);
          } else {
            menuItem.value = item.value;
            if (itemCallback) {
              itemCallback(menuItem);
            }
          }
          output.push(menuItem);
        });
        return output;
      };
      return appendItems(inputList, startItems || []);
    };
    function styleFieldHasFocus(e) {
      return e.control.rootControl.find('#style')[0].getEl().isEqualNode(domGlobals.document.activeElement);
    }
    var syncAdvancedStyleFields = function (editor, evt) {
      if (styleFieldHasFocus(evt)) {
        updateAdvancedFields(editor, evt);
      } else {
        updateStyleField(editor, evt);
      }
    };
    var updateStyleField = function (editor, evt) {
      var dom = editor.dom;
      var rootControl = evt.control.rootControl;
      var data = rootControl.toJSON();
      var css = dom.parseStyle(data.style);
      css['border-style'] = data.borderStyle;
      css['border-color'] = data.borderColor;
      css['background-color'] = data.backgroundColor;
      css.width = data.width ? addSizeSuffix(data.width) : '';
      css.height = data.height ? addSizeSuffix(data.height) : '';
      rootControl.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
    };
    var updateAdvancedFields = function (editor, evt) {
      var dom = editor.dom;
      var rootControl = evt.control.rootControl;
      var data = rootControl.toJSON();
      var css = dom.parseStyle(data.style);
      rootControl.find('#borderStyle').value(css['border-style'] || '');
      rootControl.find('#borderColor').value(css['border-color'] || '');
      rootControl.find('#backgroundColor').value(css['background-color'] || '');
      rootControl.find('#width').value(css.width || '');
      rootControl.find('#height').value(css.height || '');
    };
    var extractAdvancedStyles = function (dom, elm) {
      var css = dom.parseStyle(dom.getAttrib(elm, 'style'));
      var data = {};
      if (css['border-style']) {
        data.borderStyle = css['border-style'];
      }
      if (css['border-color']) {
        data.borderColor = css['border-color'];
      }
      if (css['background-color']) {
        data.backgroundColor = css['background-color'];
      }
      data.style = dom.serializeStyle(css);
      return data;
    };
    var createStyleForm = function (editor) {
      var createColorPickAction = function () {
        var colorPickerCallback = getColorPickerCallback(editor);
        if (colorPickerCallback) {
          return function (evt) {
            return colorPickerCallback.call(editor, function (value) {
              evt.control.value(value).fire('change');
            }, evt.control.value());
          };
        }
      };
      return {
        title: 'Advanced',
        type: 'form',
        defaults: { onchange: curry(updateStyleField, editor) },
        items: [
          {
            label: 'Style',
            name: 'style',
            type: 'textbox',
            onchange: curry(updateAdvancedFields, editor)
          },
          {
            type: 'form',
            padding: 0,
            formItemDefaults: {
              layout: 'grid',
              alignH: [
                'start',
                'right'
              ]
            },
            defaults: { size: 7 },
            items: [
              {
                label: 'Border style',
                type: 'listbox',
                name: 'borderStyle',
                width: 90,
                onselect: curry(updateStyleField, editor),
                values: [
                  {
                    text: 'Select...',
                    value: ''
                  },
                  {
                    text: 'Solid',
                    value: 'solid'
                  },
                  {
                    text: 'Dotted',
                    value: 'dotted'
                  },
                  {
                    text: 'Dashed',
                    value: 'dashed'
                  },
                  {
                    text: 'Double',
                    value: 'double'
                  },
                  {
                    text: 'Groove',
                    value: 'groove'
                  },
                  {
                    text: 'Ridge',
                    value: 'ridge'
                  },
                  {
                    text: 'Inset',
                    value: 'inset'
                  },
                  {
                    text: 'Outset',
                    value: 'outset'
                  },
                  {
                    text: 'None',
                    value: 'none'
                  },
                  {
                    text: 'Hidden',
                    value: 'hidden'
                  }
                ]
              },
              {
                label: 'Border color',
                type: 'colorbox',
                name: 'borderColor',
                onaction: createColorPickAction()
              },
              {
                label: 'Background color',
                type: 'colorbox',
                name: 'backgroundColor',
                onaction: createColorPickAction()
              }
            ]
          }
        ]
      };
    };
    var Helpers = {
      createStyleForm: createStyleForm,
      buildListItems: buildListItems,
      updateStyleField: updateStyleField,
      extractAdvancedStyles: extractAdvancedStyles,
      updateAdvancedFields: updateAdvancedFields,
      syncAdvancedStyleFields: syncAdvancedStyleFields
    };

    var updateStyles = function (elm, cssText) {
      delete elm.dataset.mceStyle;
      elm.style.cssText += ';' + cssText;
    };
    var extractDataFromElement = function (editor, elm) {
      var dom = editor.dom;
      var data = {
        width: dom.getStyle(elm, 'width') || dom.getAttrib(elm, 'width'),
        height: dom.getStyle(elm, 'height') || dom.getAttrib(elm, 'height'),
        scope: dom.getAttrib(elm, 'scope'),
        class: dom.getAttrib(elm, 'class'),
        type: elm.nodeName.toLowerCase(),
        style: '',
        align: '',
        valign: ''
      };
      global$1.each('left center right'.split(' '), function (name) {
        if (editor.formatter.matchNode(elm, 'align' + name)) {
          data.align = name;
        }
      });
      global$1.each('top middle bottom'.split(' '), function (name) {
        if (editor.formatter.matchNode(elm, 'valign' + name)) {
          data.valign = name;
        }
      });
      if (hasAdvancedCellTab(editor)) {
        global$1.extend(data, Helpers.extractAdvancedStyles(dom, elm));
      }
      return data;
    };
    var onSubmitCellForm = function (editor, cells, evt) {
      var dom = editor.dom;
      var data;
      function setAttrib(elm, name, value) {
        if (cells.length === 1 || value) {
          dom.setAttrib(elm, name, value);
        }
      }
      function setStyle(elm, name, value) {
        if (cells.length === 1 || value) {
          dom.setStyle(elm, name, value);
        }
      }
      if (hasAdvancedCellTab(editor)) {
        Helpers.syncAdvancedStyleFields(editor, evt);
      }
      data = evt.control.rootControl.toJSON();
      editor.undoManager.transact(function () {
        global$1.each(cells, function (cellElm) {
          setAttrib(cellElm, 'scope', data.scope);
          if (cells.length === 1) {
            setAttrib(cellElm, 'style', data.style);
          } else {
            updateStyles(cellElm, data.style);
          }
          setAttrib(cellElm, 'class', data.class);
          setStyle(cellElm, 'width', addSizeSuffix(data.width));
          setStyle(cellElm, 'height', addSizeSuffix(data.height));
          if (data.type && cellElm.nodeName.toLowerCase() !== data.type) {
            cellElm = dom.rename(cellElm, data.type);
          }
          if (cells.length === 1) {
            Styles$1.unApplyAlign(editor, cellElm);
            Styles$1.unApplyVAlign(editor, cellElm);
          }
          if (data.align) {
            Styles$1.applyAlign(editor, cellElm, data.align);
          }
          if (data.valign) {
            Styles$1.applyVAlign(editor, cellElm, data.valign);
          }
        });
        editor.focus();
      });
    };
    var open = function (editor) {
      var cellElm, data, classListCtrl, cells = [];
      cells = editor.dom.select('td[data-mce-selected],th[data-mce-selected]');
      cellElm = editor.dom.getParent(editor.selection.getStart(), 'td,th');
      if (!cells.length && cellElm) {
        cells.push(cellElm);
      }
      cellElm = cellElm || cells[0];
      if (!cellElm) {
        return;
      }
      if (cells.length > 1) {
        data = {
          width: '',
          height: '',
          scope: '',
          class: '',
          align: '',
          valign: '',
          style: '',
          type: cellElm.nodeName.toLowerCase()
        };
      } else {
        data = extractDataFromElement(editor, cellElm);
      }
      if (getCellClassList(editor).length > 0) {
        classListCtrl = {
          name: 'class',
          type: 'listbox',
          label: 'Class',
          values: Helpers.buildListItems(getCellClassList(editor), function (item) {
            if (item.value) {
              item.textStyle = function () {
                return editor.formatter.getCssText({
                  block: 'td',
                  classes: [item.value]
                });
              };
            }
          })
        };
      }
      var generalCellForm = {
        type: 'form',
        layout: 'flex',
        direction: 'column',
        labelGapCalc: 'children',
        padding: 0,
        items: [
          {
            type: 'form',
            layout: 'grid',
            columns: 2,
            labelGapCalc: false,
            padding: 0,
            defaults: {
              type: 'textbox',
              maxWidth: 50
            },
            items: [
              {
                label: 'Width',
                name: 'width',
                onchange: curry(Helpers.updateStyleField, editor)
              },
              {
                label: 'Height',
                name: 'height',
                onchange: curry(Helpers.updateStyleField, editor)
              },
              {
                label: 'Cell type',
                name: 'type',
                type: 'listbox',
                text: 'None',
                minWidth: 90,
                maxWidth: null,
                values: [
                  {
                    text: 'Cell',
                    value: 'td'
                  },
                  {
                    text: 'Header cell',
                    value: 'th'
                  }
                ]
              },
              {
                label: 'Scope',
                name: 'scope',
                type: 'listbox',
                text: 'None',
                minWidth: 90,
                maxWidth: null,
                values: [
                  {
                    text: 'None',
                    value: ''
                  },
                  {
                    text: 'Row',
                    value: 'row'
                  },
                  {
                    text: 'Column',
                    value: 'col'
                  },
                  {
                    text: 'Row group',
                    value: 'rowgroup'
                  },
                  {
                    text: 'Column group',
                    value: 'colgroup'
                  }
                ]
              },
              {
                label: 'H Align',
                name: 'align',
                type: 'listbox',
                text: 'None',
                minWidth: 90,
                maxWidth: null,
                values: [
                  {
                    text: 'None',
                    value: ''
                  },
                  {
                    text: 'Left',
                    value: 'left'
                  },
                  {
                    text: 'Center',
                    value: 'center'
                  },
                  {
                    text: 'Right',
                    value: 'right'
                  }
                ]
              },
              {
                label: 'V Align',
                name: 'valign',
                type: 'listbox',
                text: 'None',
                minWidth: 90,
                maxWidth: null,
                values: [
                  {
                    text: 'None',
                    value: ''
                  },
                  {
                    text: 'Top',
                    value: 'top'
                  },
                  {
                    text: 'Middle',
                    value: 'middle'
                  },
                  {
                    text: 'Bottom',
                    value: 'bottom'
                  }
                ]
              }
            ]
          },
          classListCtrl
        ]
      };
      if (hasAdvancedCellTab(editor)) {
        editor.windowManager.open({
          title: 'Cell properties',
          bodyType: 'tabpanel',
          data: data,
          body: [
            {
              title: 'General',
              type: 'form',
              items: generalCellForm
            },
            Helpers.createStyleForm(editor)
          ],
          onsubmit: curry(onSubmitCellForm, editor, cells)
        });
      } else {
        editor.windowManager.open({
          title: 'Cell properties',
          data: data,
          body: generalCellForm,
          onsubmit: curry(onSubmitCellForm, editor, cells)
        });
      }
    };
    var CellDialog = { open: open };

    var extractDataFromElement$1 = function (editor, elm) {
      var dom = editor.dom;
      var data = {
        height: dom.getStyle(elm, 'height') || dom.getAttrib(elm, 'height'),
        scope: dom.getAttrib(elm, 'scope'),
        class: dom.getAttrib(elm, 'class'),
        align: '',
        style: '',
        type: elm.parentNode.nodeName.toLowerCase()
      };
      global$1.each('left center right'.split(' '), function (name) {
        if (editor.formatter.matchNode(elm, 'align' + name)) {
          data.align = name;
        }
      });
      if (hasAdvancedRowTab(editor)) {
        global$1.extend(data, Helpers.extractAdvancedStyles(dom, elm));
      }
      return data;
    };
    var switchRowType = function (dom, rowElm, toType) {
      var tableElm = dom.getParent(rowElm, 'table');
      var oldParentElm = rowElm.parentNode;
      var parentElm = dom.select(toType, tableElm)[0];
      if (!parentElm) {
        parentElm = dom.create(toType);
        if (tableElm.firstChild) {
          if (tableElm.firstChild.nodeName === 'CAPTION') {
            dom.insertAfter(parentElm, tableElm.firstChild);
          } else {
            tableElm.insertBefore(parentElm, tableElm.firstChild);
          }
        } else {
          tableElm.appendChild(parentElm);
        }
      }
      parentElm.appendChild(rowElm);
      if (!oldParentElm.hasChildNodes()) {
        dom.remove(oldParentElm);
      }
    };
    function onSubmitRowForm(editor, rows, oldData, evt) {
      var dom = editor.dom;
      function setAttrib(elm, name, value) {
        if (rows.length === 1 || value) {
          dom.setAttrib(elm, name, value);
        }
      }
      function setStyle(elm, name, value) {
        if (rows.length === 1 || value) {
          dom.setStyle(elm, name, value);
        }
      }
      if (hasAdvancedRowTab(editor)) {
        Helpers.syncAdvancedStyleFields(editor, evt);
      }
      var data = evt.control.rootControl.toJSON();
      editor.undoManager.transact(function () {
        global$1.each(rows, function (rowElm) {
          setAttrib(rowElm, 'scope', data.scope);
          setAttrib(rowElm, 'style', data.style);
          setAttrib(rowElm, 'class', data.class);
          setStyle(rowElm, 'height', addSizeSuffix(data.height));
          if (data.type !== rowElm.parentNode.nodeName.toLowerCase()) {
            switchRowType(editor.dom, rowElm, data.type);
          }
          if (data.align !== oldData.align) {
            Styles$1.unApplyAlign(editor, rowElm);
            Styles$1.applyAlign(editor, rowElm, data.align);
          }
        });
        editor.focus();
      });
    }
    var open$1 = function (editor) {
      var dom = editor.dom;
      var tableElm, cellElm, rowElm, classListCtrl, data;
      var rows = [];
      var generalRowForm;
      tableElm = dom.getParent(editor.selection.getStart(), 'table');
      cellElm = dom.getParent(editor.selection.getStart(), 'td,th');
      global$1.each(tableElm.rows, function (row) {
        global$1.each(row.cells, function (cell) {
          if (dom.getAttrib(cell, 'data-mce-selected') || cell === cellElm) {
            rows.push(row);
            return false;
          }
        });
      });
      rowElm = rows[0];
      if (!rowElm) {
        return;
      }
      if (rows.length > 1) {
        data = {
          height: '',
          scope: '',
          style: '',
          class: '',
          align: '',
          type: rowElm.parentNode.nodeName.toLowerCase()
        };
      } else {
        data = extractDataFromElement$1(editor, rowElm);
      }
      if (getRowClassList(editor).length > 0) {
        classListCtrl = {
          name: 'class',
          type: 'listbox',
          label: 'Class',
          values: Helpers.buildListItems(getRowClassList(editor), function (item) {
            if (item.value) {
              item.textStyle = function () {
                return editor.formatter.getCssText({
                  block: 'tr',
                  classes: [item.value]
                });
              };
            }
          })
        };
      }
      generalRowForm = {
        type: 'form',
        columns: 2,
        padding: 0,
        defaults: { type: 'textbox' },
        items: [
          {
            type: 'listbox',
            name: 'type',
            label: 'Row type',
            text: 'Header',
            maxWidth: null,
            values: [
              {
                text: 'Header',
                value: 'thead'
              },
              {
                text: 'Body',
                value: 'tbody'
              },
              {
                text: 'Footer',
                value: 'tfoot'
              }
            ]
          },
          {
            type: 'listbox',
            name: 'align',
            label: 'Alignment',
            text: 'None',
            maxWidth: null,
            values: [
              {
                text: 'None',
                value: ''
              },
              {
                text: 'Left',
                value: 'left'
              },
              {
                text: 'Center',
                value: 'center'
              },
              {
                text: 'Right',
                value: 'right'
              }
            ]
          },
          {
            label: 'Height',
            name: 'height'
          },
          classListCtrl
        ]
      };
      if (hasAdvancedRowTab(editor)) {
        editor.windowManager.open({
          title: 'Row properties',
          data: data,
          bodyType: 'tabpanel',
          body: [
            {
              title: 'General',
              type: 'form',
              items: generalRowForm
            },
            Helpers.createStyleForm(editor)
          ],
          onsubmit: curry(onSubmitRowForm, editor, rows, data)
        });
      } else {
        editor.windowManager.open({
          title: 'Row properties',
          data: data,
          body: generalRowForm,
          onsubmit: curry(onSubmitRowForm, editor, rows, data)
        });
      }
    };
    var RowDialog = { open: open$1 };

    var global$2 = tinymce.util.Tools.resolve('tinymce.Env');

    var DefaultRenderOptions = {
      styles: {
        'border-collapse': 'collapse',
        'width': '100%'
      },
      attributes: { border: '1' },
      percentages: true
    };
    var makeTable = function () {
      return Element.fromTag('table');
    };
    var tableBody = function () {
      return Element.fromTag('tbody');
    };
    var tableRow = function () {
      return Element.fromTag('tr');
    };
    var tableHeaderCell = function () {
      return Element.fromTag('th');
    };
    var tableCell = function () {
      return Element.fromTag('td');
    };
    var render$1 = function (rows, columns, rowHeaders, columnHeaders, renderOpts) {
      if (renderOpts === void 0) {
        renderOpts = DefaultRenderOptions;
      }
      var table = makeTable();
      setAll$1(table, renderOpts.styles);
      setAll(table, renderOpts.attributes);
      var tbody = tableBody();
      append(table, tbody);
      var trs = [];
      for (var i = 0; i < rows; i++) {
        var tr = tableRow();
        for (var j = 0; j < columns; j++) {
          var td = i < rowHeaders || j < columnHeaders ? tableHeaderCell() : tableCell();
          if (j < columnHeaders) {
            set(td, 'scope', 'row');
          }
          if (i < rowHeaders) {
            set(td, 'scope', 'col');
          }
          append(td, Element.fromTag('br'));
          if (renderOpts.percentages) {
            set$1(td, 'width', 100 / columns + '%');
          }
          append(tr, td);
        }
        trs.push(tr);
      }
      append$1(tbody, trs);
      return table;
    };

    var get$7 = function (element) {
      return element.dom().innerHTML;
    };
    var getOuter$2 = function (element) {
      var container = Element.fromTag('div');
      var clone = Element.fromDom(element.dom().cloneNode(true));
      append(container, clone);
      return get$7(container);
    };

    var placeCaretInCell = function (editor, cell) {
      editor.selection.select(cell.dom(), true);
      editor.selection.collapse(true);
    };
    var selectFirstCellInTable = function (editor, tableElm) {
      descendant$1(tableElm, 'td,th').each(curry(placeCaretInCell, editor));
    };
    var fireEvents = function (editor, table) {
      each(descendants$1(table, 'tr'), function (row) {
        fireNewRow(editor, row.dom());
        each(descendants$1(row, 'th,td'), function (cell) {
          fireNewCell(editor, cell.dom());
        });
      });
    };
    var isPercentage = function (width) {
      return isString(width) && width.indexOf('%') !== -1;
    };
    var insert$1 = function (editor, columns, rows) {
      var defaultStyles = getDefaultStyles(editor);
      var options = {
        styles: defaultStyles,
        attributes: getDefaultAttributes(editor),
        percentages: isPercentage(defaultStyles.width) && !isPixelsForced(editor)
      };
      var table = render$1(rows, columns, 0, 0, options);
      set(table, 'data-mce-id', '__mce');
      var html = getOuter$2(table);
      editor.insertContent(html);
      return descendant$1(getBody$1(editor), 'table[data-mce-id="__mce"]').map(function (table) {
        if (isPixelsForced(editor)) {
          set$1(table, 'width', get$1(table, 'width'));
        }
        remove(table, 'data-mce-id');
        fireEvents(editor, table);
        selectFirstCellInTable(editor, table);
        return table.dom();
      }).getOr(null);
    };
    var InsertTable = { insert: insert$1 };

    function styleTDTH(dom, elm, name, value) {
      if (elm.tagName === 'TD' || elm.tagName === 'TH') {
        dom.setStyle(elm, name, value);
      } else {
        if (elm.children) {
          for (var i = 0; i < elm.children.length; i++) {
            styleTDTH(dom, elm.children[i], name, value);
          }
        }
      }
    }
    var extractDataFromElement$2 = function (editor, tableElm) {
      var dom = editor.dom;
      var data = {
        width: dom.getStyle(tableElm, 'width') || dom.getAttrib(tableElm, 'width'),
        height: dom.getStyle(tableElm, 'height') || dom.getAttrib(tableElm, 'height'),
        cellspacing: dom.getStyle(tableElm, 'border-spacing') || dom.getAttrib(tableElm, 'cellspacing'),
        cellpadding: dom.getAttrib(tableElm, 'data-mce-cell-padding') || dom.getAttrib(tableElm, 'cellpadding') || Styles$1.getTDTHOverallStyle(editor.dom, tableElm, 'padding'),
        border: dom.getAttrib(tableElm, 'data-mce-border') || dom.getAttrib(tableElm, 'border') || Styles$1.getTDTHOverallStyle(editor.dom, tableElm, 'border'),
        borderColor: dom.getAttrib(tableElm, 'data-mce-border-color'),
        caption: !!dom.select('caption', tableElm)[0],
        class: dom.getAttrib(tableElm, 'class')
      };
      global$1.each('left center right'.split(' '), function (name) {
        if (editor.formatter.matchNode(tableElm, 'align' + name)) {
          data.align = name;
        }
      });
      if (hasAdvancedTableTab(editor)) {
        global$1.extend(data, Helpers.extractAdvancedStyles(dom, tableElm));
      }
      return data;
    };
    var applyDataToElement = function (editor, tableElm, data) {
      var dom = editor.dom;
      var attrs = {};
      var styles = {};
      attrs.class = data.class;
      styles.height = addSizeSuffix(data.height);
      if (dom.getAttrib(tableElm, 'width') && !shouldStyleWithCss(editor)) {
        attrs.width = removePxSuffix(data.width);
      } else {
        styles.width = addSizeSuffix(data.width);
      }
      if (shouldStyleWithCss(editor)) {
        styles['border-width'] = addSizeSuffix(data.border);
        styles['border-spacing'] = addSizeSuffix(data.cellspacing);
        global$1.extend(attrs, {
          'data-mce-border-color': data.borderColor,
          'data-mce-cell-padding': data.cellpadding,
          'data-mce-border': data.border
        });
      } else {
        global$1.extend(attrs, {
          border: data.border,
          cellpadding: data.cellpadding,
          cellspacing: data.cellspacing
        });
      }
      if (shouldStyleWithCss(editor)) {
        if (tableElm.children) {
          for (var i = 0; i < tableElm.children.length; i++) {
            styleTDTH(dom, tableElm.children[i], {
              'border-width': addSizeSuffix(data.border),
              'border-color': data.borderColor,
              'padding': addSizeSuffix(data.cellpadding)
            });
          }
        }
      }
      if (data.style) {
        global$1.extend(styles, dom.parseStyle(data.style));
      } else {
        styles = global$1.extend({}, dom.parseStyle(dom.getAttrib(tableElm, 'style')), styles);
      }
      attrs.style = dom.serializeStyle(styles);
      dom.setAttribs(tableElm, attrs);
    };
    var onSubmitTableForm = function (editor, tableElm, evt) {
      var dom = editor.dom;
      var captionElm;
      var data;
      if (hasAdvancedTableTab(editor)) {
        Helpers.syncAdvancedStyleFields(editor, evt);
      }
      data = evt.control.rootControl.toJSON();
      if (data.class === false) {
        delete data.class;
      }
      editor.undoManager.transact(function () {
        if (!tableElm) {
          tableElm = InsertTable.insert(editor, data.cols || 1, data.rows || 1);
        }
        applyDataToElement(editor, tableElm, data);
        captionElm = dom.select('caption', tableElm)[0];
        if (captionElm && !data.caption) {
          dom.remove(captionElm);
        }
        if (!captionElm && data.caption) {
          captionElm = dom.create('caption');
          captionElm.innerHTML = !global$2.ie ? '<br data-mce-bogus="1"/>' : '\xA0';
          tableElm.insertBefore(captionElm, tableElm.firstChild);
        }
        Styles$1.unApplyAlign(editor, tableElm);
        if (data.align) {
          Styles$1.applyAlign(editor, tableElm, data.align);
        }
        editor.focus();
        editor.addVisual();
      });
    };
    var open$2 = function (editor, isProps) {
      var dom = editor.dom;
      var tableElm, colsCtrl, rowsCtrl, classListCtrl, data = {}, generalTableForm;
      if (isProps === true) {
        tableElm = dom.getParent(editor.selection.getStart(), 'table');
        if (tableElm) {
          data = extractDataFromElement$2(editor, tableElm);
        }
      } else {
        colsCtrl = {
          label: 'Cols',
          name: 'cols'
        };
        rowsCtrl = {
          label: 'Rows',
          name: 'rows'
        };
      }
      if (getTableClassList(editor).length > 0) {
        if (data.class) {
          data.class = data.class.replace(/\s*mce\-item\-table\s*/g, '');
        }
        classListCtrl = {
          name: 'class',
          type: 'listbox',
          label: 'Class',
          values: Helpers.buildListItems(getTableClassList(editor), function (item) {
            if (item.value) {
              item.textStyle = function () {
                return editor.formatter.getCssText({
                  block: 'table',
                  classes: [item.value]
                });
              };
            }
          })
        };
      }
      generalTableForm = {
        type: 'form',
        layout: 'flex',
        direction: 'column',
        labelGapCalc: 'children',
        padding: 0,
        items: [
          {
            type: 'form',
            labelGapCalc: false,
            padding: 0,
            layout: 'grid',
            columns: 2,
            defaults: {
              type: 'textbox',
              maxWidth: 50
            },
            items: hasAppearanceOptions(editor) ? [
              colsCtrl,
              rowsCtrl,
              {
                label: 'Width',
                name: 'width',
                onchange: curry(Helpers.updateStyleField, editor)
              },
              {
                label: 'Height',
                name: 'height',
                onchange: curry(Helpers.updateStyleField, editor)
              },
              {
                label: 'Cell spacing',
                name: 'cellspacing'
              },
              {
                label: 'Cell padding',
                name: 'cellpadding'
              },
              {
                label: 'Border',
                name: 'border'
              },
              {
                label: 'Caption',
                name: 'caption',
                type: 'checkbox'
              }
            ] : [
              colsCtrl,
              rowsCtrl,
              {
                label: 'Width',
                name: 'width',
                onchange: curry(Helpers.updateStyleField, editor)
              },
              {
                label: 'Height',
                name: 'height',
                onchange: curry(Helpers.updateStyleField, editor)
              }
            ]
          },
          {
            label: 'Alignment',
            name: 'align',
            type: 'listbox',
            text: 'None',
            values: [
              {
                text: 'None',
                value: ''
              },
              {
                text: 'Left',
                value: 'left'
              },
              {
                text: 'Center',
                value: 'center'
              },
              {
                text: 'Right',
                value: 'right'
              }
            ]
          },
          classListCtrl
        ]
      };
      if (hasAdvancedTableTab(editor)) {
        editor.windowManager.open({
          title: 'Table properties',
          data: data,
          bodyType: 'tabpanel',
          body: [
            {
              title: 'General',
              type: 'form',
              items: generalTableForm
            },
            Helpers.createStyleForm(editor)
          ],
          onsubmit: curry(onSubmitTableForm, editor, tableElm)
        });
      } else {
        editor.windowManager.open({
          title: 'Table properties',
          data: data,
          body: generalTableForm,
          onsubmit: curry(onSubmitTableForm, editor, tableElm)
        });
      }
    };
    var TableDialog = { open: open$2 };

    var each$3 = global$1.each;
    var registerCommands = function (editor, actions, cellSelection, selections, clipboardRows) {
      var isRoot = getIsRoot(editor);
      var eraseTable = function () {
        getSelectionStartCell().orThunk(getSelectionStartCaption).each(function (cellOrCaption) {
          var table = TableLookup.table(cellOrCaption, isRoot);
          table.filter(not(isRoot)).each(function (table) {
            var cursor = Element.fromText('');
            after(table, cursor);
            remove$2(table);
            var rng = editor.dom.createRng();
            rng.setStart(cursor.dom(), 0);
            rng.setEnd(cursor.dom(), 0);
            editor.selection.setRng(rng);
          });
        });
      };
      var getSelectionStartFromSelector = function (selector) {
        return function () {
          return Option.from(editor.dom.getParent(editor.selection.getStart(), selector)).map(Element.fromDom);
        };
      };
      var getSelectionStartCaption = getSelectionStartFromSelector('caption');
      var getSelectionStartCell = getSelectionStartFromSelector('th,td');
      var getTableFromCell = function (cell) {
        return TableLookup.table(cell, isRoot);
      };
      var getSize = function (table) {
        return {
          width: getPixelWidth$1(table.dom()),
          height: getPixelWidth$1(table.dom())
        };
      };
      var resizeChange = function (editor, oldSize, table) {
        var newSize = getSize(table);
        if (oldSize.width !== newSize.width || oldSize.height !== newSize.height) {
          fireObjectResizeStart(editor, table.dom(), oldSize.width, oldSize.height);
          fireObjectResized(editor, table.dom(), newSize.width, newSize.height);
        }
      };
      var actOnSelection = function (execute) {
        getSelectionStartCell().each(function (cell) {
          getTableFromCell(cell).each(function (table) {
            var targets = TableTargets.forMenu(selections, table, cell);
            var beforeSize = getSize(table);
            execute(table, targets).each(function (rng) {
              resizeChange(editor, beforeSize, table);
              editor.selection.setRng(rng);
              editor.focus();
              cellSelection.clear(table);
              removeDataStyle(table);
            });
          });
        });
      };
      var copyRowSelection = function (execute) {
        return getSelectionStartCell().bind(function (cell) {
          return getTableFromCell(cell).bind(function (table) {
            var doc = Element.fromDom(editor.getDoc());
            var targets = TableTargets.forMenu(selections, table, cell);
            var generators = TableFill.cellOperations(noop, doc, Option.none());
            return CopyRows.copyRows(table, targets, generators);
          });
        });
      };
      var pasteOnSelection = function (execute) {
        clipboardRows.get().each(function (rows) {
          var clonedRows = map(rows, function (row) {
            return deep(row);
          });
          getSelectionStartCell().each(function (cell) {
            getTableFromCell(cell).each(function (table) {
              var doc = Element.fromDom(editor.getDoc());
              var generators = TableFill.paste(doc);
              var targets = TableTargets.pasteRows(selections, table, cell, clonedRows, generators);
              execute(table, targets).each(function (rng) {
                editor.selection.setRng(rng);
                editor.focus();
                cellSelection.clear(table);
              });
            });
          });
        });
      };
      each$3({
        mceTableSplitCells: function () {
          actOnSelection(actions.unmergeCells);
        },
        mceTableMergeCells: function () {
          actOnSelection(actions.mergeCells);
        },
        mceTableInsertRowBefore: function () {
          actOnSelection(actions.insertRowsBefore);
        },
        mceTableInsertRowAfter: function () {
          actOnSelection(actions.insertRowsAfter);
        },
        mceTableInsertColBefore: function () {
          actOnSelection(actions.insertColumnsBefore);
        },
        mceTableInsertColAfter: function () {
          actOnSelection(actions.insertColumnsAfter);
        },
        mceTableDeleteCol: function () {
          actOnSelection(actions.deleteColumn);
        },
        mceTableDeleteRow: function () {
          actOnSelection(actions.deleteRow);
        },
        mceTableCutRow: function (grid) {
          clipboardRows.set(copyRowSelection());
          actOnSelection(actions.deleteRow);
        },
        mceTableCopyRow: function (grid) {
          clipboardRows.set(copyRowSelection());
        },
        mceTablePasteRowBefore: function (grid) {
          pasteOnSelection(actions.pasteRowsBefore);
        },
        mceTablePasteRowAfter: function (grid) {
          pasteOnSelection(actions.pasteRowsAfter);
        },
        mceTableDelete: eraseTable
      }, function (func, name) {
        editor.addCommand(name, func);
      });
      each$3({
        mceInsertTable: curry(TableDialog.open, editor),
        mceTableProps: curry(TableDialog.open, editor, true),
        mceTableRowProps: curry(RowDialog.open, editor),
        mceTableCellProps: curry(CellDialog.open, editor)
      }, function (func, name) {
        editor.addCommand(name, function (ui, val) {
          func(val);
        });
      });
    };
    var Commands = { registerCommands: registerCommands };

    var only = function (element) {
      var parent = Option.from(element.dom().documentElement).map(Element.fromDom).getOr(element);
      return {
        parent: constant(parent),
        view: constant(element),
        origin: constant(Position(0, 0))
      };
    };
    var detached = function (editable, chrome) {
      var origin = function () {
        return absolute(chrome);
      };
      return {
        parent: constant(chrome),
        view: constant(editable),
        origin: origin
      };
    };
    var body$1 = function (editable, chrome) {
      return {
        parent: constant(chrome),
        view: constant(editable),
        origin: constant(Position(0, 0))
      };
    };
    var ResizeWire = {
      only: only,
      detached: detached,
      body: body$1
    };

    var Event = function (fields) {
      var struct = Immutable.apply(null, fields);
      var handlers = [];
      var bind = function (handler) {
        if (handler === undefined) {
          throw new Error('Event bind error: undefined handler');
        }
        handlers.push(handler);
      };
      var unbind = function (handler) {
        handlers = filter(handlers, function (h) {
          return h !== handler;
        });
      };
      var trigger = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        var event = struct.apply(null, args);
        each(handlers, function (handler) {
          handler(event);
        });
      };
      return {
        bind: bind,
        unbind: unbind,
        trigger: trigger
      };
    };

    var create$1 = function (typeDefs) {
      var registry = map$1(typeDefs, function (event) {
        return {
          bind: event.bind,
          unbind: event.unbind
        };
      });
      var trigger = map$1(typeDefs, function (event) {
        return event.trigger;
      });
      return {
        registry: registry,
        trigger: trigger
      };
    };
    var Events = { create: create$1 };

    var mkEvent = function (target, x, y, stop, prevent, kill, raw) {
      return {
        target: constant(target),
        x: constant(x),
        y: constant(y),
        stop: stop,
        prevent: prevent,
        kill: kill,
        raw: constant(raw)
      };
    };
    var handle = function (filter, handler) {
      return function (rawEvent) {
        if (!filter(rawEvent)) {
          return;
        }
        var target = Element.fromDom(rawEvent.target);
        var stop = function () {
          rawEvent.stopPropagation();
        };
        var prevent = function () {
          rawEvent.preventDefault();
        };
        var kill = compose(prevent, stop);
        var evt = mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
        handler(evt);
      };
    };
    var binder = function (element, event, filter, handler, useCapture) {
      var wrapped = handle(filter, handler);
      element.dom().addEventListener(event, wrapped, useCapture);
      return { unbind: curry(unbind, element, event, wrapped, useCapture) };
    };
    var bind$1 = function (element, event, filter, handler) {
      return binder(element, event, filter, handler, false);
    };
    var unbind = function (element, event, handler, useCapture) {
      element.dom().removeEventListener(event, handler, useCapture);
    };

    var filter$1 = constant(true);
    var bind$2 = function (element, event, handler) {
      return bind$1(element, event, filter$1, handler);
    };

    var hasOwnProperty = Object.prototype.hasOwnProperty;
    var shallow$1 = function (old, nu) {
      return nu;
    };
    var baseMerge = function (merger) {
      return function () {
        var objects = new Array(arguments.length);
        for (var i = 0; i < objects.length; i++) {
          objects[i] = arguments[i];
        }
        if (objects.length === 0) {
          throw new Error('Can\'t merge zero objects');
        }
        var ret = {};
        for (var j = 0; j < objects.length; j++) {
          var curObject = objects[j];
          for (var key in curObject) {
            if (hasOwnProperty.call(curObject, key)) {
              ret[key] = merger(ret[key], curObject[key]);
            }
          }
        }
        return ret;
      };
    };
    var merge$3 = baseMerge(shallow$1);

    var styles$1 = css('ephox-dragster');
    var Styles$2 = { resolve: styles$1.resolve };

    var Blocker = function (options) {
      var settings = merge$3({ layerClass: Styles$2.resolve('blocker') }, options);
      var div = Element.fromTag('div');
      set(div, 'role', 'presentation');
      setAll$1(div, {
        position: 'fixed',
        left: '0px',
        top: '0px',
        width: '100%',
        height: '100%'
      });
      add$2(div, Styles$2.resolve('blocker'));
      add$2(div, settings.layerClass);
      var element = function () {
        return div;
      };
      var destroy = function () {
        remove$2(div);
      };
      return {
        element: element,
        destroy: destroy
      };
    };

    var DragMode = exactly([
      'compare',
      'extract',
      'mutate',
      'sink'
    ]);
    var DragSink = exactly([
      'element',
      'start',
      'stop',
      'destroy'
    ]);
    var DragApi = exactly([
      'forceDrop',
      'drop',
      'move',
      'delayDrop'
    ]);

    var compare = function (old, nu) {
      return Position(nu.left() - old.left(), nu.top() - old.top());
    };
    var extract$1 = function (event) {
      return Option.some(Position(event.x(), event.y()));
    };
    var mutate = function (mutation, info) {
      mutation.mutate(info.left(), info.top());
    };
    var sink = function (dragApi, settings) {
      var blocker = Blocker(settings);
      var mdown = bind$2(blocker.element(), 'mousedown', dragApi.forceDrop);
      var mup = bind$2(blocker.element(), 'mouseup', dragApi.drop);
      var mmove = bind$2(blocker.element(), 'mousemove', dragApi.move);
      var mout = bind$2(blocker.element(), 'mouseout', dragApi.delayDrop);
      var destroy = function () {
        blocker.destroy();
        mup.unbind();
        mmove.unbind();
        mout.unbind();
        mdown.unbind();
      };
      var start = function (parent) {
        append(parent, blocker.element());
      };
      var stop = function () {
        remove$2(blocker.element());
      };
      return DragSink({
        element: blocker.element,
        start: start,
        stop: stop,
        destroy: destroy
      });
    };
    var MouseDrag = DragMode({
      compare: compare,
      extract: extract$1,
      sink: sink,
      mutate: mutate
    });

    var last$2 = function (fn, rate) {
      var timer = null;
      var cancel = function () {
        if (timer !== null) {
          domGlobals.clearTimeout(timer);
          timer = null;
        }
      };
      var throttle = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        if (timer !== null) {
          domGlobals.clearTimeout(timer);
        }
        timer = domGlobals.setTimeout(function () {
          fn.apply(null, args);
          timer = null;
        }, rate);
      };
      return {
        cancel: cancel,
        throttle: throttle
      };
    };

    function InDrag () {
      var previous = Option.none();
      var reset = function () {
        previous = Option.none();
      };
      var update = function (mode, nu) {
        var result = previous.map(function (old) {
          return mode.compare(old, nu);
        });
        previous = Option.some(nu);
        return result;
      };
      var onEvent = function (event, mode) {
        var dataOption = mode.extract(event);
        dataOption.each(function (data) {
          var offset = update(mode, data);
          offset.each(function (d) {
            events.trigger.move(d);
          });
        });
      };
      var events = Events.create({ move: Event(['info']) });
      return {
        onEvent: onEvent,
        reset: reset,
        events: events.registry
      };
    }

    function NoDrag () {
      return {
        onEvent: noop,
        reset: noop
      };
    }

    function Movement () {
      var noDragState = NoDrag();
      var inDragState = InDrag();
      var dragState = noDragState;
      var on = function () {
        dragState.reset();
        dragState = inDragState;
      };
      var off = function () {
        dragState.reset();
        dragState = noDragState;
      };
      var onEvent = function (event, mode) {
        dragState.onEvent(event, mode);
      };
      var isOn = function () {
        return dragState === inDragState;
      };
      return {
        on: on,
        off: off,
        isOn: isOn,
        onEvent: onEvent,
        events: inDragState.events
      };
    }

    var setup = function (mutation, mode, settings) {
      var active = false;
      var events = Events.create({
        start: Event([]),
        stop: Event([])
      });
      var movement = Movement();
      var drop = function () {
        sink.stop();
        if (movement.isOn()) {
          movement.off();
          events.trigger.stop();
        }
      };
      var throttledDrop = last$2(drop, 200);
      var go = function (parent) {
        sink.start(parent);
        movement.on();
        events.trigger.start();
      };
      var mousemove = function (event) {
        throttledDrop.cancel();
        movement.onEvent(event, mode);
      };
      movement.events.move.bind(function (event) {
        mode.mutate(mutation, event.info());
      });
      var on = function () {
        active = true;
      };
      var off = function () {
        active = false;
      };
      var runIfActive = function (f) {
        return function () {
          var args = [];
          for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
          }
          if (active) {
            f.apply(null, args);
          }
        };
      };
      var sink = mode.sink(DragApi({
        forceDrop: drop,
        drop: runIfActive(drop),
        move: runIfActive(mousemove),
        delayDrop: runIfActive(throttledDrop.throttle)
      }), settings);
      var destroy = function () {
        sink.destroy();
      };
      return {
        element: sink.element,
        go: go,
        on: on,
        off: off,
        destroy: destroy,
        events: events.registry
      };
    };
    var Dragging = { setup: setup };

    var transform$1 = function (mutation, settings) {
      if (settings === void 0) {
        settings = {};
      }
      var mode = settings.mode !== undefined ? settings.mode : MouseDrag;
      return Dragging.setup(mutation, mode, settings);
    };
    var Dragger = { transform: transform$1 };

    var Mutation = function () {
      var events = Events.create({
        drag: Event([
          'xDelta',
          'yDelta'
        ])
      });
      var mutate = function (x, y) {
        events.trigger.drag(x, y);
      };
      return {
        mutate: mutate,
        events: events.registry
      };
    };

    var BarMutation = function () {
      var events = Events.create({
        drag: Event([
          'xDelta',
          'yDelta',
          'target'
        ])
      });
      var target = Option.none();
      var delegate = Mutation();
      delegate.events.drag.bind(function (event) {
        target.each(function (t) {
          events.trigger.drag(event.xDelta(), event.yDelta(), t);
        });
      });
      var assign = function (t) {
        target = Option.some(t);
      };
      var get = function () {
        return target;
      };
      return {
        assign: assign,
        get: get,
        mutate: delegate.mutate,
        events: events.registry
      };
    };

    var isContentEditableTrue = function (elm) {
      return get(elm, 'contenteditable') === 'true';
    };
    var findClosestContentEditable = function (target, isRoot) {
      return closest$1(target, '[contenteditable]', isRoot);
    };

    var resizeBarDragging = Styles.resolve('resizer-bar-dragging');
    var BarManager = function (wire, direction, hdirection) {
      var mutation = BarMutation();
      var resizing = Dragger.transform(mutation, {});
      var hoverTable = Option.none();
      var getResizer = function (element, type) {
        return Option.from(get(element, type));
      };
      mutation.events.drag.bind(function (event) {
        getResizer(event.target(), 'data-row').each(function (_dataRow) {
          var currentRow = CellUtils.getInt(event.target(), 'top');
          set$1(event.target(), 'top', currentRow + event.yDelta() + 'px');
        });
        getResizer(event.target(), 'data-column').each(function (_dataCol) {
          var currentCol = CellUtils.getInt(event.target(), 'left');
          set$1(event.target(), 'left', currentCol + event.xDelta() + 'px');
        });
      });
      var getDelta = function (target, dir) {
        var newX = CellUtils.getInt(target, dir);
        var oldX = parseInt(get(target, 'data-initial-' + dir), 10);
        return newX - oldX;
      };
      resizing.events.stop.bind(function () {
        mutation.get().each(function (target) {
          hoverTable.each(function (table) {
            getResizer(target, 'data-row').each(function (row) {
              var delta = getDelta(target, 'top');
              remove(target, 'data-initial-top');
              events.trigger.adjustHeight(table, delta, parseInt(row, 10));
            });
            getResizer(target, 'data-column').each(function (column) {
              var delta = getDelta(target, 'left');
              remove(target, 'data-initial-left');
              events.trigger.adjustWidth(table, delta, parseInt(column, 10));
            });
            Bars.refresh(wire, table, hdirection, direction);
          });
        });
      });
      var handler = function (target, dir) {
        events.trigger.startAdjust();
        mutation.assign(target);
        set(target, 'data-initial-' + dir, parseInt(get$1(target, dir), 10));
        add$2(target, resizeBarDragging);
        set$1(target, 'opacity', '0.2');
        resizing.go(wire.parent());
      };
      var mousedown = bind$2(wire.parent(), 'mousedown', function (event) {
        if (Bars.isRowBar(event.target())) {
          handler(event.target(), 'top');
        }
        if (Bars.isColBar(event.target())) {
          handler(event.target(), 'left');
        }
      });
      var isRoot = function (e) {
        return eq(e, wire.view());
      };
      var findClosestEditableTable = function (target) {
        return closest$1(target, 'table', isRoot).filter(function (table) {
          return findClosestContentEditable(table, isRoot).exists(isContentEditableTrue);
        });
      };
      var mouseover = bind$2(wire.view(), 'mouseover', function (event) {
        findClosestEditableTable(event.target()).fold(function () {
          if (inBody(event.target())) {
            Bars.destroy(wire);
          }
        }, function (table) {
          hoverTable = Option.some(table);
          Bars.refresh(wire, table, hdirection, direction);
        });
      });
      var destroy = function () {
        mousedown.unbind();
        mouseover.unbind();
        resizing.destroy();
        Bars.destroy(wire);
      };
      var refresh = function (tbl) {
        Bars.refresh(wire, tbl, hdirection, direction);
      };
      var events = Events.create({
        adjustHeight: Event([
          'table',
          'delta',
          'row'
        ]),
        adjustWidth: Event([
          'table',
          'delta',
          'column'
        ]),
        startAdjust: Event([])
      });
      return {
        destroy: destroy,
        refresh: refresh,
        on: resizing.on,
        off: resizing.off,
        hideBars: curry(Bars.hide, wire),
        showBars: curry(Bars.show, wire),
        events: events.registry
      };
    };

    var create$2 = function (wire, vdirection) {
      var hdirection = BarPositions.height;
      var manager = BarManager(wire, vdirection, hdirection);
      var events = Events.create({
        beforeResize: Event(['table']),
        afterResize: Event(['table']),
        startDrag: Event([])
      });
      manager.events.adjustHeight.bind(function (event) {
        events.trigger.beforeResize(event.table());
        var delta = hdirection.delta(event.delta(), event.table());
        Adjustments.adjustHeight(event.table(), delta, event.row(), hdirection);
        events.trigger.afterResize(event.table());
      });
      manager.events.startAdjust.bind(function (event) {
        events.trigger.startDrag();
      });
      manager.events.adjustWidth.bind(function (event) {
        events.trigger.beforeResize(event.table());
        var delta = vdirection.delta(event.delta(), event.table());
        Adjustments.adjustWidth(event.table(), delta, event.column(), vdirection);
        events.trigger.afterResize(event.table());
      });
      return {
        on: manager.on,
        off: manager.off,
        hideBars: manager.hideBars,
        showBars: manager.showBars,
        destroy: manager.destroy,
        events: events.registry
      };
    };
    var TableResize = { create: create$2 };

    var createContainer = function () {
      var container = Element.fromTag('div');
      setAll$1(container, {
        position: 'static',
        height: '0',
        width: '0',
        padding: '0',
        margin: '0',
        border: '0'
      });
      append(body(), container);
      return container;
    };
    var get$8 = function (editor, container) {
      return editor.inline ? ResizeWire.body(getBody$1(editor), createContainer()) : ResizeWire.only(Element.fromDom(editor.getDoc()));
    };
    var remove$6 = function (editor, wire) {
      if (editor.inline) {
        remove$2(wire.parent());
      }
    };
    var TableWire = {
      get: get$8,
      remove: remove$6
    };

    var ResizeHandler = function (editor) {
      var selectionRng = Option.none();
      var resize = Option.none();
      var wire = Option.none();
      var percentageBasedSizeRegex = /(\d+(\.\d+)?)%/;
      var startW, startRawW;
      var isTable = function (elm) {
        return elm.nodeName === 'TABLE';
      };
      var getRawWidth = function (elm) {
        return editor.dom.getStyle(elm, 'width') || editor.dom.getAttrib(elm, 'width');
      };
      var lazyResize = function () {
        return resize;
      };
      var lazyWire = function () {
        return wire.getOr(ResizeWire.only(Element.fromDom(editor.getBody())));
      };
      var destroy = function () {
        resize.each(function (sz) {
          sz.destroy();
        });
        wire.each(function (w) {
          TableWire.remove(editor, w);
        });
      };
      editor.on('init', function () {
        var direction = TableDirection(Direction.directionAt);
        var rawWire = TableWire.get(editor);
        wire = Option.some(rawWire);
        if (hasObjectResizing(editor) && hasTableResizeBars(editor)) {
          var sz = TableResize.create(rawWire, direction);
          sz.on();
          sz.events.startDrag.bind(function (event) {
            selectionRng = Option.some(editor.selection.getRng());
          });
          sz.events.beforeResize.bind(function (event) {
            var rawTable = event.table().dom();
            fireObjectResizeStart(editor, rawTable, getPixelWidth$1(rawTable), getPixelHeight(rawTable));
          });
          sz.events.afterResize.bind(function (event) {
            var table = event.table();
            var rawTable = table.dom();
            removeDataStyle(table);
            selectionRng.each(function (rng) {
              editor.selection.setRng(rng);
              editor.focus();
            });
            fireObjectResized(editor, rawTable, getPixelWidth$1(rawTable), getPixelHeight(rawTable));
            editor.undoManager.add();
          });
          resize = Option.some(sz);
        }
      });
      editor.on('ObjectResizeStart', function (e) {
        var targetElm = e.target;
        if (isTable(targetElm)) {
          startW = e.width;
          startRawW = getRawWidth(targetElm);
        }
      });
      editor.on('ObjectResized', function (e) {
        var targetElm = e.target;
        if (isTable(targetElm)) {
          var table = targetElm;
          if (percentageBasedSizeRegex.test(startRawW)) {
            var percentW = parseFloat(percentageBasedSizeRegex.exec(startRawW)[1]);
            var targetPercentW = e.width * percentW / startW;
            editor.dom.setStyle(table, 'width', targetPercentW + '%');
          } else {
            var newCellSizes_1 = [];
            global$1.each(table.rows, function (row) {
              global$1.each(row.cells, function (cell) {
                var width = editor.dom.getStyle(cell, 'width', true);
                newCellSizes_1.push({
                  cell: cell,
                  width: width
                });
              });
            });
            global$1.each(newCellSizes_1, function (newCellSize) {
              editor.dom.setStyle(newCellSize.cell, 'width', newCellSize.width);
              editor.dom.setAttrib(newCellSize.cell, 'width', null);
            });
          }
        }
      });
      return {
        lazyResize: lazyResize,
        lazyWire: lazyWire,
        destroy: destroy
      };
    };

    var adt$1 = Adt.generate([
      { none: ['current'] },
      { first: ['current'] },
      {
        middle: [
          'current',
          'target'
        ]
      },
      { last: ['current'] }
    ]);
    var none$1 = function (current) {
      if (current === void 0) {
        current = undefined;
      }
      return adt$1.none(current);
    };
    var CellLocation = __assign(__assign({}, adt$1), { none: none$1 });

    var detect$4 = function (current, isRoot) {
      return TableLookup.table(current, isRoot).bind(function (table) {
        var all = TableLookup.cells(table);
        var index = findIndex(all, function (x) {
          return eq(current, x);
        });
        return index.map(function (ind) {
          return {
            index: constant(ind),
            all: constant(all)
          };
        });
      });
    };
    var next = function (current, isRoot) {
      var detection = detect$4(current, isRoot);
      return detection.fold(function () {
        return CellLocation.none(current);
      }, function (info) {
        return info.index() + 1 < info.all().length ? CellLocation.middle(current, info.all()[info.index() + 1]) : CellLocation.last(current);
      });
    };
    var prev = function (current, isRoot) {
      var detection = detect$4(current, isRoot);
      return detection.fold(function () {
        return CellLocation.none();
      }, function (info) {
        return info.index() - 1 >= 0 ? CellLocation.middle(current, info.all()[info.index() - 1]) : CellLocation.first(current);
      });
    };
    var CellNavigation = {
      next: next,
      prev: prev
    };

    var create$3 = Immutable('start', 'soffset', 'finish', 'foffset');
    var SimRange = { create: create$3 };

    var adt$2 = Adt.generate([
      { before: ['element'] },
      {
        on: [
          'element',
          'offset'
        ]
      },
      { after: ['element'] }
    ]);
    var cata$1 = function (subject, onBefore, onOn, onAfter) {
      return subject.fold(onBefore, onOn, onAfter);
    };
    var getStart = function (situ) {
      return situ.fold(identity, identity, identity);
    };
    var before$2 = adt$2.before;
    var on = adt$2.on;
    var after$2 = adt$2.after;
    var Situ = {
      before: before$2,
      on: on,
      after: after$2,
      cata: cata$1,
      getStart: getStart
    };

    var adt$3 = Adt.generate([
      { domRange: ['rng'] },
      {
        relative: [
          'startSitu',
          'finishSitu'
        ]
      },
      {
        exact: [
          'start',
          'soffset',
          'finish',
          'foffset'
        ]
      }
    ]);
    var exactFromRange = function (simRange) {
      return adt$3.exact(simRange.start(), simRange.soffset(), simRange.finish(), simRange.foffset());
    };
    var getStart$1 = function (selection) {
      return selection.match({
        domRange: function (rng) {
          return Element.fromDom(rng.startContainer);
        },
        relative: function (startSitu, finishSitu) {
          return Situ.getStart(startSitu);
        },
        exact: function (start, soffset, finish, foffset) {
          return start;
        }
      });
    };
    var domRange = adt$3.domRange;
    var relative = adt$3.relative;
    var exact = adt$3.exact;
    var getWin = function (selection) {
      var start = getStart$1(selection);
      return defaultView(start);
    };
    var range$1 = SimRange.create;
    var Selection = {
      domRange: domRange,
      relative: relative,
      exact: exact,
      exactFromRange: exactFromRange,
      getWin: getWin,
      range: range$1
    };

    var selectNodeContents = function (win, element) {
      var rng = win.document.createRange();
      selectNodeContentsUsing(rng, element);
      return rng;
    };
    var selectNodeContentsUsing = function (rng, element) {
      rng.selectNodeContents(element.dom());
    };
    var setStart = function (rng, situ) {
      situ.fold(function (e) {
        rng.setStartBefore(e.dom());
      }, function (e, o) {
        rng.setStart(e.dom(), o);
      }, function (e) {
        rng.setStartAfter(e.dom());
      });
    };
    var setFinish = function (rng, situ) {
      situ.fold(function (e) {
        rng.setEndBefore(e.dom());
      }, function (e, o) {
        rng.setEnd(e.dom(), o);
      }, function (e) {
        rng.setEndAfter(e.dom());
      });
    };
    var relativeToNative = function (win, startSitu, finishSitu) {
      var range = win.document.createRange();
      setStart(range, startSitu);
      setFinish(range, finishSitu);
      return range;
    };
    var exactToNative = function (win, start, soffset, finish, foffset) {
      var rng = win.document.createRange();
      rng.setStart(start.dom(), soffset);
      rng.setEnd(finish.dom(), foffset);
      return rng;
    };
    var toRect = function (rect) {
      return {
        left: constant(rect.left),
        top: constant(rect.top),
        right: constant(rect.right),
        bottom: constant(rect.bottom),
        width: constant(rect.width),
        height: constant(rect.height)
      };
    };
    var getFirstRect = function (rng) {
      var rects = rng.getClientRects();
      var rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
      return rect.width > 0 || rect.height > 0 ? Option.some(rect).map(toRect) : Option.none();
    };

    var adt$4 = Adt.generate([
      {
        ltr: [
          'start',
          'soffset',
          'finish',
          'foffset'
        ]
      },
      {
        rtl: [
          'start',
          'soffset',
          'finish',
          'foffset'
        ]
      }
    ]);
    var fromRange = function (win, type, range) {
      return type(Element.fromDom(range.startContainer), range.startOffset, Element.fromDom(range.endContainer), range.endOffset);
    };
    var getRanges = function (win, selection) {
      return selection.match({
        domRange: function (rng) {
          return {
            ltr: constant(rng),
            rtl: Option.none
          };
        },
        relative: function (startSitu, finishSitu) {
          return {
            ltr: cached(function () {
              return relativeToNative(win, startSitu, finishSitu);
            }),
            rtl: cached(function () {
              return Option.some(relativeToNative(win, finishSitu, startSitu));
            })
          };
        },
        exact: function (start, soffset, finish, foffset) {
          return {
            ltr: cached(function () {
              return exactToNative(win, start, soffset, finish, foffset);
            }),
            rtl: cached(function () {
              return Option.some(exactToNative(win, finish, foffset, start, soffset));
            })
          };
        }
      });
    };
    var doDiagnose = function (win, ranges) {
      var rng = ranges.ltr();
      if (rng.collapsed) {
        var reversed = ranges.rtl().filter(function (rev) {
          return rev.collapsed === false;
        });
        return reversed.map(function (rev) {
          return adt$4.rtl(Element.fromDom(rev.endContainer), rev.endOffset, Element.fromDom(rev.startContainer), rev.startOffset);
        }).getOrThunk(function () {
          return fromRange(win, adt$4.ltr, rng);
        });
      } else {
        return fromRange(win, adt$4.ltr, rng);
      }
    };
    var diagnose = function (win, selection) {
      var ranges = getRanges(win, selection);
      return doDiagnose(win, ranges);
    };
    var asLtrRange = function (win, selection) {
      var diagnosis = diagnose(win, selection);
      return diagnosis.match({
        ltr: function (start, soffset, finish, foffset) {
          var rng = win.document.createRange();
          rng.setStart(start.dom(), soffset);
          rng.setEnd(finish.dom(), foffset);
          return rng;
        },
        rtl: function (start, soffset, finish, foffset) {
          var rng = win.document.createRange();
          rng.setStart(finish.dom(), foffset);
          rng.setEnd(start.dom(), soffset);
          return rng;
        }
      });
    };

    var searchForPoint = function (rectForOffset, x, y, maxX, length) {
      if (length === 0) {
        return 0;
      } else if (x === maxX) {
        return length - 1;
      }
      var xDelta = maxX;
      for (var i = 1; i < length; i++) {
        var rect = rectForOffset(i);
        var curDeltaX = Math.abs(x - rect.left);
        if (y <= rect.bottom) {
          if (y < rect.top || curDeltaX > xDelta) {
            return i - 1;
          } else {
            xDelta = curDeltaX;
          }
        }
      }
      return 0;
    };
    var inRect = function (rect, x, y) {
      return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
    };

    var locateOffset = function (doc, textnode, x, y, rect) {
      var rangeForOffset = function (o) {
        var r = doc.dom().createRange();
        r.setStart(textnode.dom(), o);
        r.collapse(true);
        return r;
      };
      var rectForOffset = function (o) {
        var r = rangeForOffset(o);
        return r.getBoundingClientRect();
      };
      var length = get$2(textnode).length;
      var offset = searchForPoint(rectForOffset, x, y, rect.right, length);
      return rangeForOffset(offset);
    };
    var locate = function (doc, node, x, y) {
      var r = doc.dom().createRange();
      r.selectNode(node.dom());
      var rects = r.getClientRects();
      var foundRect = findMap(rects, function (rect) {
        return inRect(rect, x, y) ? Option.some(rect) : Option.none();
      });
      return foundRect.map(function (rect) {
        return locateOffset(doc, node, x, y, rect);
      });
    };

    var searchInChildren = function (doc, node, x, y) {
      var r = doc.dom().createRange();
      var nodes = children(node);
      return findMap(nodes, function (n) {
        r.selectNode(n.dom());
        return inRect(r.getBoundingClientRect(), x, y) ? locateNode(doc, n, x, y) : Option.none();
      });
    };
    var locateNode = function (doc, node, x, y) {
      return isText(node) ? locate(doc, node, x, y) : searchInChildren(doc, node, x, y);
    };
    var locate$1 = function (doc, node, x, y) {
      var r = doc.dom().createRange();
      r.selectNode(node.dom());
      var rect = r.getBoundingClientRect();
      var boundedX = Math.max(rect.left, Math.min(rect.right, x));
      var boundedY = Math.max(rect.top, Math.min(rect.bottom, y));
      return locateNode(doc, node, boundedX, boundedY);
    };

    var COLLAPSE_TO_LEFT = true;
    var COLLAPSE_TO_RIGHT = false;
    var getCollapseDirection = function (rect, x) {
      return x - rect.left < rect.right - x ? COLLAPSE_TO_LEFT : COLLAPSE_TO_RIGHT;
    };
    var createCollapsedNode = function (doc, target, collapseDirection) {
      var r = doc.dom().createRange();
      r.selectNode(target.dom());
      r.collapse(collapseDirection);
      return r;
    };
    var locateInElement = function (doc, node, x) {
      var cursorRange = doc.dom().createRange();
      cursorRange.selectNode(node.dom());
      var rect = cursorRange.getBoundingClientRect();
      var collapseDirection = getCollapseDirection(rect, x);
      var f = collapseDirection === COLLAPSE_TO_LEFT ? first : last$1;
      return f(node).map(function (target) {
        return createCollapsedNode(doc, target, collapseDirection);
      });
    };
    var locateInEmpty = function (doc, node, x) {
      var rect = node.dom().getBoundingClientRect();
      var collapseDirection = getCollapseDirection(rect, x);
      return Option.some(createCollapsedNode(doc, node, collapseDirection));
    };
    var search = function (doc, node, x) {
      var f = children(node).length === 0 ? locateInEmpty : locateInElement;
      return f(doc, node, x);
    };

    var caretPositionFromPoint = function (doc, x, y) {
      return Option.from(doc.dom().caretPositionFromPoint(x, y)).bind(function (pos) {
        if (pos.offsetNode === null) {
          return Option.none();
        }
        var r = doc.dom().createRange();
        r.setStart(pos.offsetNode, pos.offset);
        r.collapse();
        return Option.some(r);
      });
    };
    var caretRangeFromPoint = function (doc, x, y) {
      return Option.from(doc.dom().caretRangeFromPoint(x, y));
    };
    var searchTextNodes = function (doc, node, x, y) {
      var r = doc.dom().createRange();
      r.selectNode(node.dom());
      var rect = r.getBoundingClientRect();
      var boundedX = Math.max(rect.left, Math.min(rect.right, x));
      var boundedY = Math.max(rect.top, Math.min(rect.bottom, y));
      return locate$1(doc, node, boundedX, boundedY);
    };
    var searchFromPoint = function (doc, x, y) {
      return Element.fromPoint(doc, x, y).bind(function (elem) {
        var fallback = function () {
          return search(doc, elem, x);
        };
        return children(elem).length === 0 ? fallback() : searchTextNodes(doc, elem, x, y).orThunk(fallback);
      });
    };
    var availableSearch = document.caretPositionFromPoint ? caretPositionFromPoint : document.caretRangeFromPoint ? caretRangeFromPoint : searchFromPoint;
    var fromPoint$1 = function (win, x, y) {
      var doc = Element.fromDom(win.document);
      return availableSearch(doc, x, y).map(function (rng) {
        return SimRange.create(Element.fromDom(rng.startContainer), rng.startOffset, Element.fromDom(rng.endContainer), rng.endOffset);
      });
    };

    var beforeSpecial = function (element, offset) {
      var name$1 = name(element);
      if ('input' === name$1) {
        return Situ.after(element);
      } else if (!contains([
          'br',
          'img'
        ], name$1)) {
        return Situ.on(element, offset);
      } else {
        return offset === 0 ? Situ.before(element) : Situ.after(element);
      }
    };
    var preprocessRelative = function (startSitu, finishSitu) {
      var start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
      var finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
      return Selection.relative(start, finish);
    };
    var preprocessExact = function (start, soffset, finish, foffset) {
      var startSitu = beforeSpecial(start, soffset);
      var finishSitu = beforeSpecial(finish, foffset);
      return Selection.relative(startSitu, finishSitu);
    };
    var preprocess = function (selection) {
      return selection.match({
        domRange: function (rng) {
          var start = Element.fromDom(rng.startContainer);
          var finish = Element.fromDom(rng.endContainer);
          return preprocessExact(start, rng.startOffset, finish, rng.endOffset);
        },
        relative: preprocessRelative,
        exact: preprocessExact
      });
    };

    var makeRange = function (start, soffset, finish, foffset) {
      var doc = owner(start);
      var rng = doc.dom().createRange();
      rng.setStart(start.dom(), soffset);
      rng.setEnd(finish.dom(), foffset);
      return rng;
    };
    var after$3 = function (start, soffset, finish, foffset) {
      var r = makeRange(start, soffset, finish, foffset);
      var same = eq(start, finish) && soffset === foffset;
      return r.collapsed && !same;
    };

    var doSetNativeRange = function (win, rng) {
      Option.from(win.getSelection()).each(function (selection) {
        selection.removeAllRanges();
        selection.addRange(rng);
      });
    };
    var doSetRange = function (win, start, soffset, finish, foffset) {
      var rng = exactToNative(win, start, soffset, finish, foffset);
      doSetNativeRange(win, rng);
    };
    var setLegacyRtlRange = function (win, selection, start, soffset, finish, foffset) {
      selection.collapse(start.dom(), soffset);
      selection.extend(finish.dom(), foffset);
    };
    var setRangeFromRelative = function (win, relative) {
      return diagnose(win, relative).match({
        ltr: function (start, soffset, finish, foffset) {
          doSetRange(win, start, soffset, finish, foffset);
        },
        rtl: function (start, soffset, finish, foffset) {
          var selection = win.getSelection();
          if (selection.setBaseAndExtent) {
            selection.setBaseAndExtent(start.dom(), soffset, finish.dom(), foffset);
          } else if (selection.extend) {
            try {
              setLegacyRtlRange(win, selection, start, soffset, finish, foffset);
            } catch (e) {
              doSetRange(win, finish, foffset, start, soffset);
            }
          } else {
            doSetRange(win, finish, foffset, start, soffset);
          }
        }
      });
    };
    var setExact = function (win, start, soffset, finish, foffset) {
      var relative = preprocessExact(start, soffset, finish, foffset);
      setRangeFromRelative(win, relative);
    };
    var setRelative = function (win, startSitu, finishSitu) {
      var relative = preprocessRelative(startSitu, finishSitu);
      setRangeFromRelative(win, relative);
    };
    var toNative = function (selection) {
      var win = Selection.getWin(selection).dom();
      var getDomRange = function (start, soffset, finish, foffset) {
        return exactToNative(win, start, soffset, finish, foffset);
      };
      var filtered = preprocess(selection);
      return diagnose(win, filtered).match({
        ltr: getDomRange,
        rtl: getDomRange
      });
    };
    var readRange = function (selection) {
      if (selection.rangeCount > 0) {
        var firstRng = selection.getRangeAt(0);
        var lastRng = selection.getRangeAt(selection.rangeCount - 1);
        return Option.some(SimRange.create(Element.fromDom(firstRng.startContainer), firstRng.startOffset, Element.fromDom(lastRng.endContainer), lastRng.endOffset));
      } else {
        return Option.none();
      }
    };
    var doGetExact = function (selection) {
      var anchor = Element.fromDom(selection.anchorNode);
      var focus = Element.fromDom(selection.focusNode);
      return after$3(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Option.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
    };
    var setToElement = function (win, element) {
      var rng = selectNodeContents(win, element);
      doSetNativeRange(win, rng);
    };
    var getExact = function (win) {
      return Option.from(win.getSelection()).filter(function (sel) {
        return sel.rangeCount > 0;
      }).bind(doGetExact);
    };
    var get$9 = function (win) {
      return getExact(win).map(function (range) {
        return Selection.exact(range.start(), range.soffset(), range.finish(), range.foffset());
      });
    };
    var getFirstRect$1 = function (win, selection) {
      var rng = asLtrRange(win, selection);
      return getFirstRect(rng);
    };
    var getAtPoint = function (win, x, y) {
      return fromPoint$1(win, x, y);
    };
    var clear = function (win) {
      var selection = win.getSelection();
      selection.removeAllRanges();
    };

    var global$3 = tinymce.util.Tools.resolve('tinymce.util.VK');

    var forward = function (editor, isRoot, cell, lazyWire) {
      return go(editor, isRoot, CellNavigation.next(cell), lazyWire);
    };
    var backward = function (editor, isRoot, cell, lazyWire) {
      return go(editor, isRoot, CellNavigation.prev(cell), lazyWire);
    };
    var getCellFirstCursorPosition = function (editor, cell) {
      var selection = Selection.exact(cell, 0, cell, 0);
      return toNative(selection);
    };
    var getNewRowCursorPosition = function (editor, table) {
      var rows = descendants$1(table, 'tr');
      return last(rows).bind(function (last) {
        return descendant$1(last, 'td,th').map(function (first) {
          return getCellFirstCursorPosition(editor, first);
        });
      });
    };
    var go = function (editor, isRoot, cell, actions, lazyWire) {
      return cell.fold(Option.none, Option.none, function (current, next) {
        return first(next).map(function (cell) {
          return getCellFirstCursorPosition(editor, cell);
        });
      }, function (current) {
        return TableLookup.table(current, isRoot).bind(function (table) {
          var targets = TableTargets.noMenu(current);
          editor.undoManager.transact(function () {
            actions.insertRowsAfter(table, targets);
          });
          return getNewRowCursorPosition(editor, table);
        });
      });
    };
    var rootElements = [
      'table',
      'li',
      'dl'
    ];
    var handle$1 = function (event, editor, actions, lazyWire) {
      if (event.keyCode === global$3.TAB) {
        var body_1 = getBody$1(editor);
        var isRoot_1 = function (element) {
          var name$1 = name(element);
          return eq(element, body_1) || contains(rootElements, name$1);
        };
        var rng = editor.selection.getRng();
        if (rng.collapsed) {
          var start = Element.fromDom(rng.startContainer);
          TableLookup.cell(start, isRoot_1).each(function (cell) {
            event.preventDefault();
            var navigation = event.shiftKey ? backward : forward;
            var rng = navigation(editor, isRoot_1, cell, actions, lazyWire);
            rng.each(function (range) {
              editor.selection.setRng(range);
            });
          });
        }
      }
    };
    var TabContext = { handle: handle$1 };

    var create$4 = Immutable('selection', 'kill');
    var Response = { create: create$4 };

    var create$5 = function (start, soffset, finish, foffset) {
      return {
        start: constant(Situ.on(start, soffset)),
        finish: constant(Situ.on(finish, foffset))
      };
    };
    var Situs = { create: create$5 };

    var convertToRange = function (win, selection) {
      var rng = asLtrRange(win, selection);
      return SimRange.create(Element.fromDom(rng.startContainer), rng.startOffset, Element.fromDom(rng.endContainer), rng.endOffset);
    };
    var makeSitus = Situs.create;
    var Util = {
      convertToRange: convertToRange,
      makeSitus: makeSitus
    };

    var sync = function (container, isRoot, start, soffset, finish, foffset, selectRange) {
      if (!(eq(start, finish) && soffset === foffset)) {
        return closest$1(start, 'td,th', isRoot).bind(function (s) {
          return closest$1(finish, 'td,th', isRoot).bind(function (f) {
            return detect$5(container, isRoot, s, f, selectRange);
          });
        });
      } else {
        return Option.none();
      }
    };
    var detect$5 = function (container, isRoot, start, finish, selectRange) {
      if (!eq(start, finish)) {
        return CellSelection.identify(start, finish, isRoot).bind(function (cellSel) {
          var boxes = cellSel.boxes().getOr([]);
          if (boxes.length > 0) {
            selectRange(container, boxes, cellSel.start(), cellSel.finish());
            return Option.some(Response.create(Option.some(Util.makeSitus(start, 0, start, getEnd(start))), true));
          } else {
            return Option.none();
          }
        });
      } else {
        return Option.none();
      }
    };
    var update = function (rows, columns, container, selected, annotations) {
      var updateSelection = function (newSels) {
        annotations.clear(container);
        annotations.selectRange(container, newSels.boxes(), newSels.start(), newSels.finish());
        return newSels.boxes();
      };
      return CellSelection.shiftSelection(selected, rows, columns, annotations.firstSelectedSelector(), annotations.lastSelectedSelector()).map(updateSelection);
    };
    var KeySelection = {
      sync: sync,
      detect: detect$5,
      update: update
    };

    var traverse = Immutable('item', 'mode');
    var backtrack = function (universe, item, _direction, transition) {
      if (transition === void 0) {
        transition = sidestep;
      }
      return universe.property().parent(item).map(function (p) {
        return traverse(p, transition);
      });
    };
    var sidestep = function (universe, item, direction, transition) {
      if (transition === void 0) {
        transition = advance;
      }
      return direction.sibling(universe, item).map(function (p) {
        return traverse(p, transition);
      });
    };
    var advance = function (universe, item, direction, transition) {
      if (transition === void 0) {
        transition = advance;
      }
      var children = universe.property().children(item);
      var result = direction.first(children);
      return result.map(function (r) {
        return traverse(r, transition);
      });
    };
    var successors = [
      {
        current: backtrack,
        next: sidestep,
        fallback: Option.none()
      },
      {
        current: sidestep,
        next: advance,
        fallback: Option.some(backtrack)
      },
      {
        current: advance,
        next: advance,
        fallback: Option.some(sidestep)
      }
    ];
    var go$1 = function (universe, item, mode, direction, rules) {
      if (rules === void 0) {
        rules = successors;
      }
      var ruleOpt = find(rules, function (succ) {
        return succ.current === mode;
      });
      return ruleOpt.bind(function (rule) {
        return rule.current(universe, item, direction, rule.next).orThunk(function () {
          return rule.fallback.bind(function (fb) {
            return go$1(universe, item, fb, direction);
          });
        });
      });
    };

    var left = function () {
      var sibling = function (universe, item) {
        return universe.query().prevSibling(item);
      };
      var first = function (children) {
        return children.length > 0 ? Option.some(children[children.length - 1]) : Option.none();
      };
      return {
        sibling: sibling,
        first: first
      };
    };
    var right = function () {
      var sibling = function (universe, item) {
        return universe.query().nextSibling(item);
      };
      var first = function (children) {
        return children.length > 0 ? Option.some(children[0]) : Option.none();
      };
      return {
        sibling: sibling,
        first: first
      };
    };
    var Walkers = {
      left: left,
      right: right
    };

    var hone = function (universe, item, predicate, mode, direction, isRoot) {
      var next = go$1(universe, item, mode, direction);
      return next.bind(function (n) {
        if (isRoot(n.item())) {
          return Option.none();
        } else {
          return predicate(n.item()) ? Option.some(n.item()) : hone(universe, n.item(), predicate, n.mode(), direction, isRoot);
        }
      });
    };
    var left$1 = function (universe, item, predicate, isRoot) {
      return hone(universe, item, predicate, sidestep, Walkers.left(), isRoot);
    };
    var right$1 = function (universe, item, predicate, isRoot) {
      return hone(universe, item, predicate, sidestep, Walkers.right(), isRoot);
    };

    var isLeaf = function (universe) {
      return function (element) {
        return universe.property().children(element).length === 0;
      };
    };
    var before$3 = function (universe, item, isRoot) {
      return seekLeft(universe, item, isLeaf(universe), isRoot);
    };
    var after$4 = function (universe, item, isRoot) {
      return seekRight(universe, item, isLeaf(universe), isRoot);
    };
    var seekLeft = left$1;
    var seekRight = right$1;

    var universe$2 = DomUniverse();
    var before$4 = function (element, isRoot) {
      return before$3(universe$2, element, isRoot);
    };
    var after$5 = function (element, isRoot) {
      return after$4(universe$2, element, isRoot);
    };
    var seekLeft$1 = function (element, predicate, isRoot) {
      return seekLeft(universe$2, element, predicate, isRoot);
    };
    var seekRight$1 = function (element, predicate, isRoot) {
      return seekRight(universe$2, element, predicate, isRoot);
    };

    var ancestor$2 = function (scope, predicate, isRoot) {
      return ancestor(scope, predicate, isRoot).isSome();
    };

    var point = Immutable('element', 'offset');
    var delta = Immutable('element', 'deltaOffset');
    var range$2 = Immutable('element', 'start', 'finish');
    var points = Immutable('begin', 'end');
    var text = Immutable('element', 'text');

    var adt$5 = Adt.generate([
      { none: ['message'] },
      { success: [] },
      { failedUp: ['cell'] },
      { failedDown: ['cell'] }
    ]);
    var isOverlapping = function (bridge, before, after) {
      var beforeBounds = bridge.getRect(before);
      var afterBounds = bridge.getRect(after);
      return afterBounds.right > beforeBounds.left && afterBounds.left < beforeBounds.right;
    };
    var isRow = function (elem) {
      return closest$1(elem, 'tr');
    };
    var verify = function (bridge, before, beforeOffset, after, afterOffset, failure, isRoot) {
      return closest$1(after, 'td,th', isRoot).bind(function (afterCell) {
        return closest$1(before, 'td,th', isRoot).map(function (beforeCell) {
          if (!eq(afterCell, beforeCell)) {
            return DomParent.sharedOne(isRow, [
              afterCell,
              beforeCell
            ]).fold(function () {
              return isOverlapping(bridge, beforeCell, afterCell) ? adt$5.success() : failure(beforeCell);
            }, function (_sharedRow) {
              return failure(beforeCell);
            });
          } else {
            return eq(after, afterCell) && getEnd(afterCell) === afterOffset ? failure(beforeCell) : adt$5.none('in same cell');
          }
        });
      }).getOr(adt$5.none('default'));
    };
    var cata$2 = function (subject, onNone, onSuccess, onFailedUp, onFailedDown) {
      return subject.fold(onNone, onSuccess, onFailedUp, onFailedDown);
    };
    var BeforeAfter = __assign(__assign({}, adt$5), {
      verify: verify,
      cata: cata$2
    });

    var inAncestor = Immutable('ancestor', 'descendants', 'element', 'index');
    var inParent = Immutable('parent', 'children', 'element', 'index');
    var indexInParent = function (element) {
      return parent(element).bind(function (parent) {
        var children$1 = children(parent);
        return indexOf(children$1, element).map(function (index) {
          return inParent(parent, children$1, element, index);
        });
      });
    };
    var indexOf = function (elements, element) {
      return findIndex(elements, curry(eq, element));
    };

    var isBr = function (elem) {
      return name(elem) === 'br';
    };
    var gatherer = function (cand, gather, isRoot) {
      return gather(cand, isRoot).bind(function (target) {
        return isText(target) && get$2(target).trim().length === 0 ? gatherer(target, gather, isRoot) : Option.some(target);
      });
    };
    var handleBr = function (isRoot, element, direction) {
      return direction.traverse(element).orThunk(function () {
        return gatherer(element, direction.gather, isRoot);
      }).map(direction.relative);
    };
    var findBr = function (element, offset) {
      return child(element, offset).filter(isBr).orThunk(function () {
        return child(element, offset - 1).filter(isBr);
      });
    };
    var handleParent = function (isRoot, element, offset, direction) {
      return findBr(element, offset).bind(function (br) {
        return direction.traverse(br).fold(function () {
          return gatherer(br, direction.gather, isRoot).map(direction.relative);
        }, function (adjacent) {
          return indexInParent(adjacent).map(function (info) {
            return Situ.on(info.parent(), info.index());
          });
        });
      });
    };
    var tryBr = function (isRoot, element, offset, direction) {
      var target = isBr(element) ? handleBr(isRoot, element, direction) : handleParent(isRoot, element, offset, direction);
      return target.map(function (tgt) {
        return {
          start: constant(tgt),
          finish: constant(tgt)
        };
      });
    };
    var process = function (analysis) {
      return BeforeAfter.cata(analysis, function (message) {
        return Option.none();
      }, function () {
        return Option.none();
      }, function (cell) {
        return Option.some(point(cell, 0));
      }, function (cell) {
        return Option.some(point(cell, getEnd(cell)));
      });
    };
    var BrTags = {
      tryBr: tryBr,
      process: process
    };

    var nu$3 = MixedBag([
      'left',
      'top',
      'right',
      'bottom'
    ], []);
    var moveDown = function (caret, amount) {
      return nu$3({
        left: caret.left(),
        top: caret.top() + amount,
        right: caret.right(),
        bottom: caret.bottom() + amount
      });
    };
    var moveUp = function (caret, amount) {
      return nu$3({
        left: caret.left(),
        top: caret.top() - amount,
        right: caret.right(),
        bottom: caret.bottom() - amount
      });
    };
    var moveBottomTo = function (caret, bottom) {
      var height = caret.bottom() - caret.top();
      return nu$3({
        left: caret.left(),
        top: bottom - height,
        right: caret.right(),
        bottom: bottom
      });
    };
    var moveTopTo = function (caret, top) {
      var height = caret.bottom() - caret.top();
      return nu$3({
        left: caret.left(),
        top: top,
        right: caret.right(),
        bottom: top + height
      });
    };
    var translate = function (caret, xDelta, yDelta) {
      return nu$3({
        left: caret.left() + xDelta,
        top: caret.top() + yDelta,
        right: caret.right() + xDelta,
        bottom: caret.bottom() + yDelta
      });
    };
    var getTop$1 = function (caret) {
      return caret.top();
    };
    var getBottom = function (caret) {
      return caret.bottom();
    };
    var toString = function (caret) {
      return '(' + caret.left() + ', ' + caret.top() + ') -> (' + caret.right() + ', ' + caret.bottom() + ')';
    };
    var Carets = {
      nu: nu$3,
      moveUp: moveUp,
      moveDown: moveDown,
      moveBottomTo: moveBottomTo,
      moveTopTo: moveTopTo,
      getTop: getTop$1,
      getBottom: getBottom,
      translate: translate,
      toString: toString
    };

    var getPartialBox = function (bridge, element, offset) {
      if (offset >= 0 && offset < getEnd(element)) {
        return bridge.getRangedRect(element, offset, element, offset + 1);
      } else if (offset > 0) {
        return bridge.getRangedRect(element, offset - 1, element, offset);
      }
      return Option.none();
    };
    var toCaret = function (rect) {
      return Carets.nu({
        left: rect.left,
        top: rect.top,
        right: rect.right,
        bottom: rect.bottom
      });
    };
    var getElemBox = function (bridge, element) {
      return Option.some(bridge.getRect(element));
    };
    var getBoxAt = function (bridge, element, offset) {
      if (isElement(element)) {
        return getElemBox(bridge, element).map(toCaret);
      } else if (isText(element)) {
        return getPartialBox(bridge, element, offset).map(toCaret);
      } else {
        return Option.none();
      }
    };
    var getEntireBox = function (bridge, element) {
      if (isElement(element)) {
        return getElemBox(bridge, element).map(toCaret);
      } else if (isText(element)) {
        return bridge.getRangedRect(element, 0, element, getEnd(element)).map(toCaret);
      } else {
        return Option.none();
      }
    };
    var Rectangles = {
      getBoxAt: getBoxAt,
      getEntireBox: getEntireBox
    };

    var JUMP_SIZE = 5;
    var NUM_RETRIES = 100;
    var adt$6 = Adt.generate([
      { none: [] },
      { retry: ['caret'] }
    ]);
    var isOutside = function (caret, box) {
      return caret.left() < box.left() || Math.abs(box.right() - caret.left()) < 1 || caret.left() > box.right();
    };
    var inOutsideBlock = function (bridge, element, caret) {
      return closest(element, DomStructure.isBlock).fold(constant(false), function (cell) {
        return Rectangles.getEntireBox(bridge, cell).exists(function (box) {
          return isOutside(caret, box);
        });
      });
    };
    var adjustDown = function (bridge, element, guessBox, original, caret) {
      var lowerCaret = Carets.moveDown(caret, JUMP_SIZE);
      if (Math.abs(guessBox.bottom() - original.bottom()) < 1) {
        return adt$6.retry(lowerCaret);
      } else if (guessBox.top() > caret.bottom()) {
        return adt$6.retry(lowerCaret);
      } else if (guessBox.top() === caret.bottom()) {
        return adt$6.retry(Carets.moveDown(caret, 1));
      } else {
        return inOutsideBlock(bridge, element, caret) ? adt$6.retry(Carets.translate(lowerCaret, JUMP_SIZE, 0)) : adt$6.none();
      }
    };
    var adjustUp = function (bridge, element, guessBox, original, caret) {
      var higherCaret = Carets.moveUp(caret, JUMP_SIZE);
      if (Math.abs(guessBox.top() - original.top()) < 1) {
        return adt$6.retry(higherCaret);
      } else if (guessBox.bottom() < caret.top()) {
        return adt$6.retry(higherCaret);
      } else if (guessBox.bottom() === caret.top()) {
        return adt$6.retry(Carets.moveUp(caret, 1));
      } else {
        return inOutsideBlock(bridge, element, caret) ? adt$6.retry(Carets.translate(higherCaret, JUMP_SIZE, 0)) : adt$6.none();
      }
    };
    var upMovement = {
      point: Carets.getTop,
      adjuster: adjustUp,
      move: Carets.moveUp,
      gather: before$4
    };
    var downMovement = {
      point: Carets.getBottom,
      adjuster: adjustDown,
      move: Carets.moveDown,
      gather: after$5
    };
    var isAtTable = function (bridge, x, y) {
      return bridge.elementFromPoint(x, y).filter(function (elm) {
        return name(elm) === 'table';
      }).isSome();
    };
    var adjustForTable = function (bridge, movement, original, caret, numRetries) {
      return adjustTil(bridge, movement, original, movement.move(caret, JUMP_SIZE), numRetries);
    };
    var adjustTil = function (bridge, movement, original, caret, numRetries) {
      if (numRetries === 0) {
        return Option.some(caret);
      }
      if (isAtTable(bridge, caret.left(), movement.point(caret))) {
        return adjustForTable(bridge, movement, original, caret, numRetries - 1);
      }
      return bridge.situsFromPoint(caret.left(), movement.point(caret)).bind(function (guess) {
        return guess.start().fold(Option.none, function (element) {
          return Rectangles.getEntireBox(bridge, element).bind(function (guessBox) {
            return movement.adjuster(bridge, element, guessBox, original, caret).fold(Option.none, function (newCaret) {
              return adjustTil(bridge, movement, original, newCaret, numRetries - 1);
            });
          }).orThunk(function () {
            return Option.some(caret);
          });
        }, Option.none);
      });
    };
    var ieTryDown = function (bridge, caret) {
      return bridge.situsFromPoint(caret.left(), caret.bottom() + JUMP_SIZE);
    };
    var ieTryUp = function (bridge, caret) {
      return bridge.situsFromPoint(caret.left(), caret.top() - JUMP_SIZE);
    };
    var checkScroll = function (movement, adjusted, bridge) {
      if (movement.point(adjusted) > bridge.getInnerHeight()) {
        return Option.some(movement.point(adjusted) - bridge.getInnerHeight());
      } else if (movement.point(adjusted) < 0) {
        return Option.some(-movement.point(adjusted));
      } else {
        return Option.none();
      }
    };
    var retry = function (movement, bridge, caret) {
      var moved = movement.move(caret, JUMP_SIZE);
      var adjusted = adjustTil(bridge, movement, caret, moved, NUM_RETRIES).getOr(moved);
      return checkScroll(movement, adjusted, bridge).fold(function () {
        return bridge.situsFromPoint(adjusted.left(), movement.point(adjusted));
      }, function (delta) {
        bridge.scrollBy(0, delta);
        return bridge.situsFromPoint(adjusted.left(), movement.point(adjusted) - delta);
      });
    };
    var Retries = {
      tryUp: curry(retry, upMovement),
      tryDown: curry(retry, downMovement),
      ieTryUp: ieTryUp,
      ieTryDown: ieTryDown,
      getJumpSize: constant(JUMP_SIZE)
    };

    var MAX_RETRIES = 20;
    var platform$1 = PlatformDetection$1.detect();
    var findSpot = function (bridge, isRoot, direction) {
      return bridge.getSelection().bind(function (sel) {
        return BrTags.tryBr(isRoot, sel.finish(), sel.foffset(), direction).fold(function () {
          return Option.some(point(sel.finish(), sel.foffset()));
        }, function (brNeighbour) {
          var range = bridge.fromSitus(brNeighbour);
          var analysis = BeforeAfter.verify(bridge, sel.finish(), sel.foffset(), range.finish(), range.foffset(), direction.failure, isRoot);
          return BrTags.process(analysis);
        });
      });
    };
    var scan = function (bridge, isRoot, element, offset, direction, numRetries) {
      if (numRetries === 0) {
        return Option.none();
      }
      return tryCursor(bridge, isRoot, element, offset, direction).bind(function (situs) {
        var range = bridge.fromSitus(situs);
        var analysis = BeforeAfter.verify(bridge, element, offset, range.finish(), range.foffset(), direction.failure, isRoot);
        return BeforeAfter.cata(analysis, function () {
          return Option.none();
        }, function () {
          return Option.some(situs);
        }, function (cell) {
          if (eq(element, cell) && offset === 0) {
            return tryAgain(bridge, element, offset, Carets.moveUp, direction);
          } else {
            return scan(bridge, isRoot, cell, 0, direction, numRetries - 1);
          }
        }, function (cell) {
          if (eq(element, cell) && offset === getEnd(cell)) {
            return tryAgain(bridge, element, offset, Carets.moveDown, direction);
          } else {
            return scan(bridge, isRoot, cell, getEnd(cell), direction, numRetries - 1);
          }
        });
      });
    };
    var tryAgain = function (bridge, element, offset, move, direction) {
      return Rectangles.getBoxAt(bridge, element, offset).bind(function (box) {
        return tryAt(bridge, direction, move(box, Retries.getJumpSize()));
      });
    };
    var tryAt = function (bridge, direction, box) {
      if (platform$1.browser.isChrome() || platform$1.browser.isSafari() || platform$1.browser.isFirefox() || platform$1.browser.isEdge()) {
        return direction.otherRetry(bridge, box);
      } else if (platform$1.browser.isIE()) {
        return direction.ieRetry(bridge, box);
      } else {
        return Option.none();
      }
    };
    var tryCursor = function (bridge, isRoot, element, offset, direction) {
      return Rectangles.getBoxAt(bridge, element, offset).bind(function (box) {
        return tryAt(bridge, direction, box);
      });
    };
    var handle$2 = function (bridge, isRoot, direction) {
      return findSpot(bridge, isRoot, direction).bind(function (spot) {
        return scan(bridge, isRoot, spot.element(), spot.offset(), direction, MAX_RETRIES).map(bridge.fromSitus);
      });
    };
    var TableKeys = { handle: handle$2 };

    var detection = PlatformDetection$1.detect();
    var inSameTable = function (elem, table) {
      return ancestor$2(elem, function (e) {
        return parent(e).exists(function (p) {
          return eq(p, table);
        });
      });
    };
    var simulate = function (bridge, isRoot, direction, initial, anchor) {
      return closest$1(initial, 'td,th', isRoot).bind(function (start) {
        return closest$1(start, 'table', isRoot).bind(function (table) {
          if (!inSameTable(anchor, table)) {
            return Option.none();
          }
          return TableKeys.handle(bridge, isRoot, direction).bind(function (range) {
            return closest$1(range.finish(), 'td,th', isRoot).map(function (finish) {
              return {
                start: constant(start),
                finish: constant(finish),
                range: constant(range)
              };
            });
          });
        });
      });
    };
    var navigate = function (bridge, isRoot, direction, initial, anchor, precheck) {
      if (detection.browser.isIE()) {
        return Option.none();
      } else {
        return precheck(initial, isRoot).orThunk(function () {
          return simulate(bridge, isRoot, direction, initial, anchor).map(function (info) {
            var range = info.range();
            return Response.create(Option.some(Util.makeSitus(range.start(), range.soffset(), range.finish(), range.foffset())), true);
          });
        });
      }
    };
    var firstUpCheck = function (initial, isRoot) {
      return closest$1(initial, 'tr', isRoot).bind(function (startRow) {
        return closest$1(startRow, 'table', isRoot).bind(function (table) {
          var rows = descendants$1(table, 'tr');
          if (eq(startRow, rows[0])) {
            return seekLeft$1(table, function (element) {
              return last$1(element).isSome();
            }, isRoot).map(function (last) {
              var lastOffset = getEnd(last);
              return Response.create(Option.some(Util.makeSitus(last, lastOffset, last, lastOffset)), true);
            });
          } else {
            return Option.none();
          }
        });
      });
    };
    var lastDownCheck = function (initial, isRoot) {
      return closest$1(initial, 'tr', isRoot).bind(function (startRow) {
        return closest$1(startRow, 'table', isRoot).bind(function (table) {
          var rows = descendants$1(table, 'tr');
          if (eq(startRow, rows[rows.length - 1])) {
            return seekRight$1(table, function (element) {
              return first(element).isSome();
            }, isRoot).map(function (first) {
              return Response.create(Option.some(Util.makeSitus(first, 0, first, 0)), true);
            });
          } else {
            return Option.none();
          }
        });
      });
    };
    var select = function (bridge, container, isRoot, direction, initial, anchor, selectRange) {
      return simulate(bridge, isRoot, direction, initial, anchor).bind(function (info) {
        return KeySelection.detect(container, isRoot, info.start(), info.finish(), selectRange);
      });
    };
    var VerticalMovement = {
      navigate: navigate,
      select: select,
      firstUpCheck: firstUpCheck,
      lastDownCheck: lastDownCheck
    };

    var findCell = function (target, isRoot) {
      return closest$1(target, 'td,th', isRoot);
    };
    function MouseSelection (bridge, container, isRoot, annotations) {
      var cursor = Option.none();
      var clearState = function () {
        cursor = Option.none();
      };
      var mousedown = function (event) {
        annotations.clear(container);
        cursor = findCell(event.target(), isRoot);
      };
      var mouseover = function (event) {
        cursor.each(function (start) {
          annotations.clear(container);
          findCell(event.target(), isRoot).each(function (finish) {
            CellSelection.identify(start, finish, isRoot).each(function (cellSel) {
              var boxes = cellSel.boxes().getOr([]);
              if (boxes.length > 1 || boxes.length === 1 && !eq(start, finish)) {
                annotations.selectRange(container, boxes, cellSel.start(), cellSel.finish());
                bridge.selectContents(finish);
              }
            });
          });
        });
      };
      var mouseup = function (_event) {
        cursor.each(clearState);
      };
      return {
        mousedown: mousedown,
        mouseover: mouseover,
        mouseup: mouseup
      };
    }

    var down = {
      traverse: nextSibling,
      gather: after$5,
      relative: Situ.before,
      otherRetry: Retries.tryDown,
      ieRetry: Retries.ieTryDown,
      failure: BeforeAfter.failedDown
    };
    var up = {
      traverse: prevSibling,
      gather: before$4,
      relative: Situ.before,
      otherRetry: Retries.tryUp,
      ieRetry: Retries.ieTryUp,
      failure: BeforeAfter.failedUp
    };
    var KeyDirection = {
      down: down,
      up: up
    };

    var isKey = function (key) {
      return function (keycode) {
        return keycode === key;
      };
    };
    var isUp = isKey(38);
    var isDown = isKey(40);
    var isNavigation = function (keycode) {
      return keycode >= 37 && keycode <= 40;
    };
    var SelectionKeys = {
      ltr: {
        isBackward: isKey(37),
        isForward: isKey(39)
      },
      rtl: {
        isBackward: isKey(39),
        isForward: isKey(37)
      },
      isUp: isUp,
      isDown: isDown,
      isNavigation: isNavigation
    };

    var toRaw = function (sr) {
      return {
        left: sr.left(),
        top: sr.top(),
        right: sr.right(),
        bottom: sr.bottom(),
        width: sr.width(),
        height: sr.height()
      };
    };
    var Rect = { toRaw: toRaw };

    var isSafari = PlatformDetection$1.detect().browser.isSafari();
    var get$a = function (_DOC) {
      var doc = _DOC !== undefined ? _DOC.dom() : domGlobals.document;
      var x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
      var y = doc.body.scrollTop || doc.documentElement.scrollTop;
      return Position(x, y);
    };
    var by = function (x, y, _DOC) {
      var doc = _DOC !== undefined ? _DOC.dom() : domGlobals.document;
      var win = doc.defaultView;
      win.scrollBy(x, y);
    };

    var WindowBridge = function (win) {
      var elementFromPoint = function (x, y) {
        return Element.fromPoint(Element.fromDom(win.document), x, y);
      };
      var getRect = function (element) {
        return element.dom().getBoundingClientRect();
      };
      var getRangedRect = function (start, soffset, finish, foffset) {
        var sel = Selection.exact(start, soffset, finish, foffset);
        return getFirstRect$1(win, sel).map(Rect.toRaw);
      };
      var getSelection = function () {
        return get$9(win).map(function (exactAdt) {
          return Util.convertToRange(win, exactAdt);
        });
      };
      var fromSitus = function (situs) {
        var relative = Selection.relative(situs.start(), situs.finish());
        return Util.convertToRange(win, relative);
      };
      var situsFromPoint = function (x, y) {
        return getAtPoint(win, x, y).map(function (exact) {
          return Situs.create(exact.start(), exact.soffset(), exact.finish(), exact.foffset());
        });
      };
      var clearSelection = function () {
        clear(win);
      };
      var selectContents = function (element) {
        setToElement(win, element);
      };
      var setSelection = function (sel) {
        setExact(win, sel.start(), sel.soffset(), sel.finish(), sel.foffset());
      };
      var setRelativeSelection = function (start, finish) {
        setRelative(win, start, finish);
      };
      var getInnerHeight = function () {
        return win.innerHeight;
      };
      var getScrollY = function () {
        var pos = get$a(Element.fromDom(win.document));
        return pos.top();
      };
      var scrollBy = function (x, y) {
        by(x, y, Element.fromDom(win.document));
      };
      return {
        elementFromPoint: elementFromPoint,
        getRect: getRect,
        getRangedRect: getRangedRect,
        getSelection: getSelection,
        fromSitus: fromSitus,
        situsFromPoint: situsFromPoint,
        clearSelection: clearSelection,
        setSelection: setSelection,
        setRelativeSelection: setRelativeSelection,
        selectContents: selectContents,
        getInnerHeight: getInnerHeight,
        getScrollY: getScrollY,
        scrollBy: scrollBy
      };
    };

    var rc = Immutable('rows', 'cols');
    var mouse = function (win, container, isRoot, annotations) {
      var bridge = WindowBridge(win);
      var handlers = MouseSelection(bridge, container, isRoot, annotations);
      return {
        mousedown: handlers.mousedown,
        mouseover: handlers.mouseover,
        mouseup: handlers.mouseup
      };
    };
    var keyboard = function (win, container, isRoot, annotations) {
      var bridge = WindowBridge(win);
      var clearToNavigate = function () {
        annotations.clear(container);
        return Option.none();
      };
      var keydown = function (event, start, soffset, finish, foffset, direction) {
        var realEvent = event.raw();
        var keycode = realEvent.which;
        var shiftKey = realEvent.shiftKey === true;
        var handler = CellSelection.retrieve(container, annotations.selectedSelector()).fold(function () {
          if (SelectionKeys.isDown(keycode) && shiftKey) {
            return curry(VerticalMovement.select, bridge, container, isRoot, KeyDirection.down, finish, start, annotations.selectRange);
          } else if (SelectionKeys.isUp(keycode) && shiftKey) {
            return curry(VerticalMovement.select, bridge, container, isRoot, KeyDirection.up, finish, start, annotations.selectRange);
          } else if (SelectionKeys.isDown(keycode)) {
            return curry(VerticalMovement.navigate, bridge, isRoot, KeyDirection.down, finish, start, VerticalMovement.lastDownCheck);
          } else if (SelectionKeys.isUp(keycode)) {
            return curry(VerticalMovement.navigate, bridge, isRoot, KeyDirection.up, finish, start, VerticalMovement.firstUpCheck);
          } else {
            return Option.none;
          }
        }, function (selected) {
          var update = function (attempts) {
            return function () {
              var navigation = findMap(attempts, function (delta) {
                return KeySelection.update(delta.rows(), delta.cols(), container, selected, annotations);
              });
              return navigation.fold(function () {
                return CellSelection.getEdges(container, annotations.firstSelectedSelector(), annotations.lastSelectedSelector()).map(function (edges) {
                  var relative = SelectionKeys.isDown(keycode) || direction.isForward(keycode) ? Situ.after : Situ.before;
                  bridge.setRelativeSelection(Situ.on(edges.first(), 0), relative(edges.table()));
                  annotations.clear(container);
                  return Response.create(Option.none(), true);
                });
              }, function (_) {
                return Option.some(Response.create(Option.none(), true));
              });
            };
          };
          if (SelectionKeys.isDown(keycode) && shiftKey) {
            return update([rc(+1, 0)]);
          } else if (SelectionKeys.isUp(keycode) && shiftKey) {
            return update([rc(-1, 0)]);
          } else if (direction.isBackward(keycode) && shiftKey) {
            return update([
              rc(0, -1),
              rc(-1, 0)
            ]);
          } else if (direction.isForward(keycode) && shiftKey) {
            return update([
              rc(0, +1),
              rc(+1, 0)
            ]);
          } else if (SelectionKeys.isNavigation(keycode) && shiftKey === false) {
            return clearToNavigate;
          } else {
            return Option.none;
          }
        });
        return handler();
      };
      var keyup = function (event, start, soffset, finish, foffset) {
        return CellSelection.retrieve(container, annotations.selectedSelector()).fold(function () {
          var realEvent = event.raw();
          var keycode = realEvent.which;
          var shiftKey = realEvent.shiftKey === true;
          if (shiftKey === false) {
            return Option.none();
          }
          if (SelectionKeys.isNavigation(keycode)) {
            return KeySelection.sync(container, isRoot, start, soffset, finish, foffset, annotations.selectRange);
          } else {
            return Option.none();
          }
        }, Option.none);
      };
      return {
        keydown: keydown,
        keyup: keyup
      };
    };
    var InputHandlers = {
      mouse: mouse,
      keyboard: keyboard
    };

    var remove$7 = function (element, classes) {
      each(classes, function (x) {
        remove$5(element, x);
      });
    };

    var addClass = function (clazz) {
      return function (element) {
        add$2(element, clazz);
      };
    };
    var removeClasses = function (classes) {
      return function (element) {
        remove$7(element, classes);
      };
    };

    var byClass = function (ephemera) {
      var addSelectionClass = addClass(ephemera.selected());
      var removeSelectionClasses = removeClasses([
        ephemera.selected(),
        ephemera.lastSelected(),
        ephemera.firstSelected()
      ]);
      var clear = function (container) {
        var sels = descendants$1(container, ephemera.selectedSelector());
        each(sels, removeSelectionClasses);
      };
      var selectRange = function (container, cells, start, finish) {
        clear(container);
        each(cells, addSelectionClass);
        add$2(start, ephemera.firstSelected());
        add$2(finish, ephemera.lastSelected());
      };
      return {
        clear: clear,
        selectRange: selectRange,
        selectedSelector: ephemera.selectedSelector,
        firstSelectedSelector: ephemera.firstSelectedSelector,
        lastSelectedSelector: ephemera.lastSelectedSelector
      };
    };
    var byAttr = function (ephemera) {
      var removeSelectionAttributes = function (element) {
        remove(element, ephemera.selected());
        remove(element, ephemera.firstSelected());
        remove(element, ephemera.lastSelected());
      };
      var addSelectionAttribute = function (element) {
        set(element, ephemera.selected(), '1');
      };
      var clear = function (container) {
        var sels = descendants$1(container, ephemera.selectedSelector());
        each(sels, removeSelectionAttributes);
      };
      var selectRange = function (container, cells, start, finish) {
        clear(container);
        each(cells, addSelectionAttribute);
        set(start, ephemera.firstSelected(), '1');
        set(finish, ephemera.lastSelected(), '1');
      };
      return {
        clear: clear,
        selectRange: selectRange,
        selectedSelector: ephemera.selectedSelector,
        firstSelectedSelector: ephemera.firstSelectedSelector,
        lastSelectedSelector: ephemera.lastSelectedSelector
      };
    };
    var SelectionAnnotation = {
      byClass: byClass,
      byAttr: byAttr
    };

    var hasInternalTarget = function (e) {
      return has$1(Element.fromDom(e.target), 'ephox-snooker-resizer-bar') === false;
    };
    function CellSelection$1 (editor, lazyResize) {
      var handlerStruct = MixedBag([
        'mousedown',
        'mouseover',
        'mouseup',
        'keyup',
        'keydown'
      ], []);
      var handlers = Option.none();
      var annotations = SelectionAnnotation.byAttr(Ephemera);
      editor.on('init', function (e) {
        var win = editor.getWin();
        var body = getBody$1(editor);
        var isRoot = getIsRoot(editor);
        var syncSelection = function () {
          var sel = editor.selection;
          var start = Element.fromDom(sel.getStart());
          var end = Element.fromDom(sel.getEnd());
          var shared = DomParent.sharedOne(TableLookup.table, [
            start,
            end
          ]);
          shared.fold(function () {
            annotations.clear(body);
          }, noop);
        };
        var mouseHandlers = InputHandlers.mouse(win, body, isRoot, annotations);
        var keyHandlers = InputHandlers.keyboard(win, body, isRoot, annotations);
        var hasShiftKey = function (event) {
          return event.raw().shiftKey === true;
        };
        var handleResponse = function (event, response) {
          if (!hasShiftKey(event)) {
            return;
          }
          if (response.kill()) {
            event.kill();
          }
          response.selection().each(function (ns) {
            var relative = Selection.relative(ns.start(), ns.finish());
            var rng = asLtrRange(win, relative);
            editor.selection.setRng(rng);
          });
        };
        var keyup = function (event) {
          var wrappedEvent = wrapEvent(event);
          if (wrappedEvent.raw().shiftKey && SelectionKeys.isNavigation(wrappedEvent.raw().which)) {
            var rng = editor.selection.getRng();
            var start = Element.fromDom(rng.startContainer);
            var end = Element.fromDom(rng.endContainer);
            keyHandlers.keyup(wrappedEvent, start, rng.startOffset, end, rng.endOffset).each(function (response) {
              handleResponse(wrappedEvent, response);
            });
          }
        };
        var keydown = function (event) {
          var wrappedEvent = wrapEvent(event);
          lazyResize().each(function (resize) {
            resize.hideBars();
          });
          var rng = editor.selection.getRng();
          var startContainer = Element.fromDom(editor.selection.getStart());
          var start = Element.fromDom(rng.startContainer);
          var end = Element.fromDom(rng.endContainer);
          var direction = Direction.directionAt(startContainer).isRtl() ? SelectionKeys.rtl : SelectionKeys.ltr;
          keyHandlers.keydown(wrappedEvent, start, rng.startOffset, end, rng.endOffset, direction).each(function (response) {
            handleResponse(wrappedEvent, response);
          });
          lazyResize().each(function (resize) {
            resize.showBars();
          });
        };
        var isMouseEvent = function (event) {
          return event.hasOwnProperty('x') && event.hasOwnProperty('y');
        };
        var wrapEvent = function (event) {
          var target = Element.fromDom(event.target);
          var stop = function () {
            event.stopPropagation();
          };
          var prevent = function () {
            event.preventDefault();
          };
          var kill = compose(prevent, stop);
          return {
            target: constant(target),
            x: constant(isMouseEvent(event) ? event.x : null),
            y: constant(isMouseEvent(event) ? event.y : null),
            stop: stop,
            prevent: prevent,
            kill: kill,
            raw: constant(event)
          };
        };
        var isLeftMouse = function (raw) {
          return raw.button === 0;
        };
        var isLeftButtonPressed = function (raw) {
          if (raw.buttons === undefined) {
            return true;
          }
          if (global$2.ie && global$2.ie >= 12 && raw.buttons === 0) {
            return true;
          }
          return (raw.buttons & 1) !== 0;
        };
        var mouseDown = function (e) {
          if (isLeftMouse(e) && hasInternalTarget(e)) {
            mouseHandlers.mousedown(wrapEvent(e));
          }
        };
        var mouseOver = function (e) {
          if (isLeftButtonPressed(e) && hasInternalTarget(e)) {
            mouseHandlers.mouseover(wrapEvent(e));
          }
        };
        var mouseUp = function (e) {
          if (isLeftMouse(e) && hasInternalTarget(e)) {
            mouseHandlers.mouseup(wrapEvent(e));
          }
        };
        editor.on('mousedown', mouseDown);
        editor.on('mouseover', mouseOver);
        editor.on('mouseup', mouseUp);
        editor.on('keyup', keyup);
        editor.on('keydown', keydown);
        editor.on('nodechange', syncSelection);
        handlers = Option.some(handlerStruct({
          mousedown: mouseDown,
          mouseover: mouseOver,
          mouseup: mouseUp,
          keyup: keyup,
          keydown: keydown
        }));
      });
      var destroy = function () {
        handlers.each(function (handlers) {
        });
      };
      return {
        clear: annotations.clear,
        destroy: destroy
      };
    }

    var Selections = function (editor) {
      var get = function () {
        var body = getBody$1(editor);
        return TableSelection.retrieve(body, Ephemera.selectedSelector()).fold(function () {
          if (editor.selection.getStart() === undefined) {
            return SelectionTypes.none();
          } else {
            return SelectionTypes.single(editor.selection);
          }
        }, function (cells) {
          return SelectionTypes.multiple(cells);
        });
      };
      return { get: get };
    };

    var each$4 = global$1.each;
    var addButtons = function (editor) {
      var menuItems = [];
      each$4('inserttable tableprops deletetable | cell row column'.split(' '), function (name) {
        if (name === '|') {
          menuItems.push({ text: '-' });
        } else {
          menuItems.push(editor.menuItems[name]);
        }
      });
      editor.addButton('table', {
        type: 'menubutton',
        title: 'Table',
        menu: menuItems
      });
      function cmd(command) {
        return function () {
          editor.execCommand(command);
        };
      }
      editor.addButton('tableprops', {
        title: 'Table properties',
        onclick: cmd('mceTableProps'),
        icon: 'table'
      });
      editor.addButton('tabledelete', {
        title: 'Delete table',
        onclick: cmd('mceTableDelete')
      });
      editor.addButton('tablecellprops', {
        title: 'Cell properties',
        onclick: cmd('mceTableCellProps')
      });
      editor.addButton('tablemergecells', {
        title: 'Merge cells',
        onclick: cmd('mceTableMergeCells')
      });
      editor.addButton('tablesplitcells', {
        title: 'Split cell',
        onclick: cmd('mceTableSplitCells')
      });
      editor.addButton('tableinsertrowbefore', {
        title: 'Insert row before',
        onclick: cmd('mceTableInsertRowBefore')
      });
      editor.addButton('tableinsertrowafter', {
        title: 'Insert row after',
        onclick: cmd('mceTableInsertRowAfter')
      });
      editor.addButton('tabledeleterow', {
        title: 'Delete row',
        onclick: cmd('mceTableDeleteRow')
      });
      editor.addButton('tablerowprops', {
        title: 'Row properties',
        onclick: cmd('mceTableRowProps')
      });
      editor.addButton('tablecutrow', {
        title: 'Cut row',
        onclick: cmd('mceTableCutRow')
      });
      editor.addButton('tablecopyrow', {
        title: 'Copy row',
        onclick: cmd('mceTableCopyRow')
      });
      editor.addButton('tablepasterowbefore', {
        title: 'Paste row before',
        onclick: cmd('mceTablePasteRowBefore')
      });
      editor.addButton('tablepasterowafter', {
        title: 'Paste row after',
        onclick: cmd('mceTablePasteRowAfter')
      });
      editor.addButton('tableinsertcolbefore', {
        title: 'Insert column before',
        onclick: cmd('mceTableInsertColBefore')
      });
      editor.addButton('tableinsertcolafter', {
        title: 'Insert column after',
        onclick: cmd('mceTableInsertColAfter')
      });
      editor.addButton('tabledeletecol', {
        title: 'Delete column',
        onclick: cmd('mceTableDeleteCol')
      });
    };
    var addToolbars = function (editor) {
      var isTable = function (table) {
        var selectorMatched = editor.dom.is(table, 'table') && editor.getBody().contains(table);
        return selectorMatched;
      };
      var toolbar = getToolbar(editor);
      if (toolbar.length > 0) {
        editor.addContextToolbar(isTable, toolbar.join(' '));
      }
    };
    var Buttons = {
      addButtons: addButtons,
      addToolbars: addToolbars
    };

    var addMenuItems = function (editor, selections) {
      var targets = Option.none();
      var tableCtrls = [];
      var cellCtrls = [];
      var mergeCtrls = [];
      var unmergeCtrls = [];
      var noTargetDisable = function (ctrl) {
        ctrl.disabled(true);
      };
      var ctrlEnable = function (ctrl) {
        ctrl.disabled(false);
      };
      var pushTable = function () {
        var self = this;
        tableCtrls.push(self);
        targets.fold(function () {
          noTargetDisable(self);
        }, function (targets) {
          ctrlEnable(self);
        });
      };
      var pushCell = function () {
        var self = this;
        cellCtrls.push(self);
        targets.fold(function () {
          noTargetDisable(self);
        }, function (targets) {
          ctrlEnable(self);
        });
      };
      var pushMerge = function () {
        var self = this;
        mergeCtrls.push(self);
        targets.fold(function () {
          noTargetDisable(self);
        }, function (targets) {
          self.disabled(targets.mergable().isNone());
        });
      };
      var pushUnmerge = function () {
        var self = this;
        unmergeCtrls.push(self);
        targets.fold(function () {
          noTargetDisable(self);
        }, function (targets) {
          self.disabled(targets.unmergable().isNone());
        });
      };
      var setDisabledCtrls = function () {
        targets.fold(function () {
          each(tableCtrls, noTargetDisable);
          each(cellCtrls, noTargetDisable);
          each(mergeCtrls, noTargetDisable);
          each(unmergeCtrls, noTargetDisable);
        }, function (targets) {
          each(tableCtrls, ctrlEnable);
          each(cellCtrls, ctrlEnable);
          each(mergeCtrls, function (mergeCtrl) {
            mergeCtrl.disabled(targets.mergable().isNone());
          });
          each(unmergeCtrls, function (unmergeCtrl) {
            unmergeCtrl.disabled(targets.unmergable().isNone());
          });
        });
      };
      editor.on('init', function () {
        editor.on('nodechange', function (e) {
          var cellOpt = Option.from(editor.dom.getParent(editor.selection.getStart(), 'th,td'));
          targets = cellOpt.bind(function (cellDom) {
            var cell = Element.fromDom(cellDom);
            var table = TableLookup.table(cell);
            return table.map(function (table) {
              return TableTargets.forMenu(selections, table, cell);
            });
          });
          setDisabledCtrls();
        });
      });
      var generateTableGrid = function () {
        var html = '';
        html = '<table role="grid" class="mce-grid mce-grid-border" aria-readonly="true">';
        for (var y = 0; y < 10; y++) {
          html += '<tr>';
          for (var x = 0; x < 10; x++) {
            html += '<td role="gridcell" tabindex="-1"><a id="mcegrid' + (y * 10 + x) + '" href="#" ' + 'data-mce-x="' + x + '" data-mce-y="' + y + '"></a></td>';
          }
          html += '</tr>';
        }
        html += '</table>';
        html += '<div class="mce-text-center" role="presentation">1 x 1</div>';
        return html;
      };
      var selectGrid = function (editor, tx, ty, control) {
        var table = control.getEl().getElementsByTagName('table')[0];
        var x, y, focusCell, cell, active;
        var rtl = control.isRtl() || control.parent().rel === 'tl-tr';
        table.nextSibling.innerHTML = tx + 1 + ' x ' + (ty + 1);
        if (rtl) {
          tx = 9 - tx;
        }
        for (y = 0; y < 10; y++) {
          for (x = 0; x < 10; x++) {
            cell = table.rows[y].childNodes[x].firstChild;
            active = (rtl ? x >= tx : x <= tx) && y <= ty;
            editor.dom.toggleClass(cell, 'mce-active', active);
            if (active) {
              focusCell = cell;
            }
          }
        }
        return focusCell.parentNode;
      };
      var insertTable = hasTableGrid(editor) === false ? {
        text: 'Table',
        icon: 'table',
        context: 'table',
        onclick: cmd('mceInsertTable')
      } : {
        text: 'Table',
        icon: 'table',
        context: 'table',
        ariaHideMenu: true,
        onclick: function (e) {
          if (e.aria) {
            this.parent().hideAll();
            e.stopImmediatePropagation();
            editor.execCommand('mceInsertTable');
          }
        },
        onshow: function () {
          selectGrid(editor, 0, 0, this.menu.items()[0]);
        },
        onhide: function () {
          var elements = this.menu.items()[0].getEl().getElementsByTagName('a');
          editor.dom.removeClass(elements, 'mce-active');
          editor.dom.addClass(elements[0], 'mce-active');
        },
        menu: [{
            type: 'container',
            html: generateTableGrid(),
            onPostRender: function () {
              this.lastX = this.lastY = 0;
            },
            onmousemove: function (e) {
              var target = e.target;
              var x, y;
              if (target.tagName.toUpperCase() === 'A') {
                x = parseInt(target.getAttribute('data-mce-x'), 10);
                y = parseInt(target.getAttribute('data-mce-y'), 10);
                if (this.isRtl() || this.parent().rel === 'tl-tr') {
                  x = 9 - x;
                }
                if (x !== this.lastX || y !== this.lastY) {
                  selectGrid(editor, x, y, e.control);
                  this.lastX = x;
                  this.lastY = y;
                }
              }
            },
            onclick: function (e) {
              var self = this;
              if (e.target.tagName.toUpperCase() === 'A') {
                e.preventDefault();
                e.stopPropagation();
                self.parent().cancel();
                editor.undoManager.transact(function () {
                  InsertTable.insert(editor, self.lastX + 1, self.lastY + 1);
                });
                editor.addVisual();
              }
            }
          }]
      };
      function cmd(command) {
        return function () {
          editor.execCommand(command);
        };
      }
      var tableProperties = {
        text: 'Table properties',
        context: 'table',
        onPostRender: pushTable,
        onclick: cmd('mceTableProps')
      };
      var deleteTable = {
        text: 'Delete table',
        context: 'table',
        onPostRender: pushTable,
        cmd: 'mceTableDelete'
      };
      var row = {
        text: 'Row',
        context: 'table',
        menu: [
          {
            text: 'Insert row before',
            onclick: cmd('mceTableInsertRowBefore'),
            onPostRender: pushCell
          },
          {
            text: 'Insert row after',
            onclick: cmd('mceTableInsertRowAfter'),
            onPostRender: pushCell
          },
          {
            text: 'Delete row',
            onclick: cmd('mceTableDeleteRow'),
            onPostRender: pushCell
          },
          {
            text: 'Row properties',
            onclick: cmd('mceTableRowProps'),
            onPostRender: pushCell
          },
          { text: '-' },
          {
            text: 'Cut row',
            onclick: cmd('mceTableCutRow'),
            onPostRender: pushCell
          },
          {
            text: 'Copy row',
            onclick: cmd('mceTableCopyRow'),
            onPostRender: pushCell
          },
          {
            text: 'Paste row before',
            onclick: cmd('mceTablePasteRowBefore'),
            onPostRender: pushCell
          },
          {
            text: 'Paste row after',
            onclick: cmd('mceTablePasteRowAfter'),
            onPostRender: pushCell
          }
        ]
      };
      var column = {
        text: 'Column',
        context: 'table',
        menu: [
          {
            text: 'Insert column before',
            onclick: cmd('mceTableInsertColBefore'),
            onPostRender: pushCell
          },
          {
            text: 'Insert column after',
            onclick: cmd('mceTableInsertColAfter'),
            onPostRender: pushCell
          },
          {
            text: 'Delete column',
            onclick: cmd('mceTableDeleteCol'),
            onPostRender: pushCell
          }
        ]
      };
      var cell = {
        separator: 'before',
        text: 'Cell',
        context: 'table',
        menu: [
          {
            text: 'Cell properties',
            onclick: cmd('mceTableCellProps'),
            onPostRender: pushCell
          },
          {
            text: 'Merge cells',
            onclick: cmd('mceTableMergeCells'),
            onPostRender: pushMerge
          },
          {
            text: 'Split cell',
            onclick: cmd('mceTableSplitCells'),
            onPostRender: pushUnmerge
          }
        ]
      };
      editor.addMenuItem('inserttable', insertTable);
      editor.addMenuItem('tableprops', tableProperties);
      editor.addMenuItem('deletetable', deleteTable);
      editor.addMenuItem('row', row);
      editor.addMenuItem('column', column);
      editor.addMenuItem('cell', cell);
    };
    var MenuItems = { addMenuItems: addMenuItems };

    var getClipboardRows = function (clipboardRows) {
      return clipboardRows.get().fold(function () {
        return;
      }, function (rows) {
        return map(rows, function (row) {
          return row.dom();
        });
      });
    };
    var setClipboardRows = function (rows, clipboardRows) {
      var sugarRows = map(rows, Element.fromDom);
      clipboardRows.set(Option.from(sugarRows));
    };
    var getApi = function (editor, clipboardRows) {
      return {
        insertTable: function (columns, rows) {
          return InsertTable.insert(editor, columns, rows);
        },
        setClipboardRows: function (rows) {
          return setClipboardRows(rows, clipboardRows);
        },
        getClipboardRows: function () {
          return getClipboardRows(clipboardRows);
        }
      };
    };

    function Plugin(editor) {
      var resizeHandler = ResizeHandler(editor);
      var cellSelection = CellSelection$1(editor, resizeHandler.lazyResize);
      var actions = TableActions(editor, resizeHandler.lazyWire);
      var selections = Selections(editor);
      var clipboardRows = Cell(Option.none());
      Commands.registerCommands(editor, actions, cellSelection, selections, clipboardRows);
      Clipboard.registerEvents(editor, selections, actions, cellSelection);
      MenuItems.addMenuItems(editor, selections);
      Buttons.addButtons(editor);
      Buttons.addToolbars(editor);
      editor.on('PreInit', function () {
        editor.serializer.addTempAttr(Ephemera.firstSelected());
        editor.serializer.addTempAttr(Ephemera.lastSelected());
      });
      if (hasTabNavigation(editor)) {
        editor.on('keydown', function (e) {
          TabContext.handle(e, editor, actions, resizeHandler.lazyWire);
        });
      }
      editor.on('remove', function () {
        resizeHandler.destroy();
        cellSelection.destroy();
      });
      return getApi(editor, clipboardRows);
    }
    global.add('table', Plugin);
    function Plugin$1 () {
    }

    return Plugin$1;

}(window));
})();


/***/ }),

/***/ 562:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "directionality" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/directionality')
//   ES2015:
//     import 'tinymce/plugins/directionality'
__webpack_require__(563);

/***/ }),

/***/ 563:
/***/ (function(module, exports) {

(function () {
var directionality = (function () {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    var setDir = function (editor, dir) {
      var dom = editor.dom;
      var curDir;
      var blocks = editor.selection.getSelectedBlocks();
      if (blocks.length) {
        curDir = dom.getAttrib(blocks[0], 'dir');
        global$1.each(blocks, function (block) {
          if (!dom.getParent(block.parentNode, '*[dir="' + dir + '"]', dom.getRoot())) {
            dom.setAttrib(block, 'dir', curDir !== dir ? dir : null);
          }
        });
        editor.nodeChanged();
      }
    };
    var Direction = { setDir: setDir };

    var register = function (editor) {
      editor.addCommand('mceDirectionLTR', function () {
        Direction.setDir(editor, 'ltr');
      });
      editor.addCommand('mceDirectionRTL', function () {
        Direction.setDir(editor, 'rtl');
      });
    };
    var Commands = { register: register };

    var generateSelector = function (dir) {
      var selector = [];
      global$1.each('h1 h2 h3 h4 h5 h6 div p'.split(' '), function (name) {
        selector.push(name + '[dir=' + dir + ']');
      });
      return selector.join(',');
    };
    var register$1 = function (editor) {
      editor.addButton('ltr', {
        title: 'Left to right',
        cmd: 'mceDirectionLTR',
        stateSelector: generateSelector('ltr')
      });
      editor.addButton('rtl', {
        title: 'Right to left',
        cmd: 'mceDirectionRTL',
        stateSelector: generateSelector('rtl')
      });
    };
    var Buttons = { register: register$1 };

    global.add('directionality', function (editor) {
      Commands.register(editor);
      Buttons.register(editor);
    });
    function Plugin () {
    }

    return Plugin;

}());
})();


/***/ }),

/***/ 564:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "searchreplace" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/searchreplace')
//   ES2015:
//     import 'tinymce/plugins/searchreplace'
__webpack_require__(565);

/***/ }),

/***/ 565:
/***/ (function(module, exports) {

(function () {
var searchreplace = (function () {
    'use strict';

    var Cell = function (initial) {
      var value = initial;
      var get = function () {
        return value;
      };
      var set = function (v) {
        value = v;
      };
      var clone = function () {
        return Cell(get());
      };
      return {
        get: get,
        set: set,
        clone: clone
      };
    };

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    function isContentEditableFalse(node) {
      return node && node.nodeType === 1 && node.contentEditable === 'false';
    }
    function findAndReplaceDOMText(regex, node, replacementNode, captureGroup, schema) {
      var m;
      var matches = [];
      var text, count = 0, doc;
      var blockElementsMap, hiddenTextElementsMap, shortEndedElementsMap;
      doc = node.ownerDocument;
      blockElementsMap = schema.getBlockElements();
      hiddenTextElementsMap = schema.getWhiteSpaceElements();
      shortEndedElementsMap = schema.getShortEndedElements();
      function getMatchIndexes(m, captureGroup) {
        captureGroup = captureGroup || 0;
        if (!m[0]) {
          throw new Error('findAndReplaceDOMText cannot handle zero-length matches');
        }
        var index = m.index;
        if (captureGroup > 0) {
          var cg = m[captureGroup];
          if (!cg) {
            throw new Error('Invalid capture group');
          }
          index += m[0].indexOf(cg);
          m[0] = cg;
        }
        return [
          index,
          index + m[0].length,
          [m[0]]
        ];
      }
      function getText(node) {
        var txt;
        if (node.nodeType === 3) {
          return node.data;
        }
        if (hiddenTextElementsMap[node.nodeName] && !blockElementsMap[node.nodeName]) {
          return '';
        }
        txt = '';
        if (isContentEditableFalse(node)) {
          return '\n';
        }
        if (blockElementsMap[node.nodeName] || shortEndedElementsMap[node.nodeName]) {
          txt += '\n';
        }
        if (node = node.firstChild) {
          do {
            txt += getText(node);
          } while (node = node.nextSibling);
        }
        return txt;
      }
      function stepThroughMatches(node, matches, replaceFn) {
        var startNode, endNode, startNodeIndex, endNodeIndex, innerNodes = [], atIndex = 0, curNode = node, matchLocation = matches.shift(), matchIndex = 0;
        out:
          while (true) {
            if (blockElementsMap[curNode.nodeName] || shortEndedElementsMap[curNode.nodeName] || isContentEditableFalse(curNode)) {
              atIndex++;
            }
            if (curNode.nodeType === 3) {
              if (!endNode && curNode.length + atIndex >= matchLocation[1]) {
                endNode = curNode;
                endNodeIndex = matchLocation[1] - atIndex;
              } else if (startNode) {
                innerNodes.push(curNode);
              }
              if (!startNode && curNode.length + atIndex > matchLocation[0]) {
                startNode = curNode;
                startNodeIndex = matchLocation[0] - atIndex;
              }
              atIndex += curNode.length;
            }
            if (startNode && endNode) {
              curNode = replaceFn({
                startNode: startNode,
                startNodeIndex: startNodeIndex,
                endNode: endNode,
                endNodeIndex: endNodeIndex,
                innerNodes: innerNodes,
                match: matchLocation[2],
                matchIndex: matchIndex
              });
              atIndex -= endNode.length - endNodeIndex;
              startNode = null;
              endNode = null;
              innerNodes = [];
              matchLocation = matches.shift();
              matchIndex++;
              if (!matchLocation) {
                break;
              }
            } else if ((!hiddenTextElementsMap[curNode.nodeName] || blockElementsMap[curNode.nodeName]) && curNode.firstChild) {
              if (!isContentEditableFalse(curNode)) {
                curNode = curNode.firstChild;
                continue;
              }
            } else if (curNode.nextSibling) {
              curNode = curNode.nextSibling;
              continue;
            }
            while (true) {
              if (curNode.nextSibling) {
                curNode = curNode.nextSibling;
                break;
              } else if (curNode.parentNode !== node) {
                curNode = curNode.parentNode;
              } else {
                break out;
              }
            }
          }
      }
      function genReplacer(nodeName) {
        var makeReplacementNode;
        if (typeof nodeName !== 'function') {
          var stencilNode_1 = nodeName.nodeType ? nodeName : doc.createElement(nodeName);
          makeReplacementNode = function (fill, matchIndex) {
            var clone = stencilNode_1.cloneNode(false);
            clone.setAttribute('data-mce-index', matchIndex);
            if (fill) {
              clone.appendChild(doc.createTextNode(fill));
            }
            return clone;
          };
        } else {
          makeReplacementNode = nodeName;
        }
        return function (range) {
          var before;
          var after;
          var parentNode;
          var startNode = range.startNode;
          var endNode = range.endNode;
          var matchIndex = range.matchIndex;
          if (startNode === endNode) {
            var node_1 = startNode;
            parentNode = node_1.parentNode;
            if (range.startNodeIndex > 0) {
              before = doc.createTextNode(node_1.data.substring(0, range.startNodeIndex));
              parentNode.insertBefore(before, node_1);
            }
            var el = makeReplacementNode(range.match[0], matchIndex);
            parentNode.insertBefore(el, node_1);
            if (range.endNodeIndex < node_1.length) {
              after = doc.createTextNode(node_1.data.substring(range.endNodeIndex));
              parentNode.insertBefore(after, node_1);
            }
            node_1.parentNode.removeChild(node_1);
            return el;
          }
          before = doc.createTextNode(startNode.data.substring(0, range.startNodeIndex));
          after = doc.createTextNode(endNode.data.substring(range.endNodeIndex));
          var elA = makeReplacementNode(startNode.data.substring(range.startNodeIndex), matchIndex);
          for (var i = 0, l = range.innerNodes.length; i < l; ++i) {
            var innerNode = range.innerNodes[i];
            var innerEl = makeReplacementNode(innerNode.data, matchIndex);
            innerNode.parentNode.replaceChild(innerEl, innerNode);
          }
          var elB = makeReplacementNode(endNode.data.substring(0, range.endNodeIndex), matchIndex);
          parentNode = startNode.parentNode;
          parentNode.insertBefore(before, startNode);
          parentNode.insertBefore(elA, startNode);
          parentNode.removeChild(startNode);
          parentNode = endNode.parentNode;
          parentNode.insertBefore(elB, endNode);
          parentNode.insertBefore(after, endNode);
          parentNode.removeChild(endNode);
          return elB;
        };
      }
      text = getText(node);
      if (!text) {
        return;
      }
      if (regex.global) {
        while (m = regex.exec(text)) {
          matches.push(getMatchIndexes(m, captureGroup));
        }
      } else {
        m = text.match(regex);
        matches.push(getMatchIndexes(m, captureGroup));
      }
      if (matches.length) {
        count = matches.length;
        stepThroughMatches(node, matches, genReplacer(replacementNode));
      }
      return count;
    }
    var FindReplaceText = { findAndReplaceDOMText: findAndReplaceDOMText };

    var getElmIndex = function (elm) {
      var value = elm.getAttribute('data-mce-index');
      if (typeof value === 'number') {
        return '' + value;
      }
      return value;
    };
    var markAllMatches = function (editor, currentIndexState, regex) {
      var node, marker;
      marker = editor.dom.create('span', { 'data-mce-bogus': 1 });
      marker.className = 'mce-match-marker';
      node = editor.getBody();
      done(editor, currentIndexState, false);
      return FindReplaceText.findAndReplaceDOMText(regex, node, marker, false, editor.schema);
    };
    var unwrap = function (node) {
      var parentNode = node.parentNode;
      if (node.firstChild) {
        parentNode.insertBefore(node.firstChild, node);
      }
      node.parentNode.removeChild(node);
    };
    var findSpansByIndex = function (editor, index) {
      var nodes;
      var spans = [];
      nodes = global$1.toArray(editor.getBody().getElementsByTagName('span'));
      if (nodes.length) {
        for (var i = 0; i < nodes.length; i++) {
          var nodeIndex = getElmIndex(nodes[i]);
          if (nodeIndex === null || !nodeIndex.length) {
            continue;
          }
          if (nodeIndex === index.toString()) {
            spans.push(nodes[i]);
          }
        }
      }
      return spans;
    };
    var moveSelection = function (editor, currentIndexState, forward) {
      var testIndex = currentIndexState.get();
      var dom = editor.dom;
      forward = forward !== false;
      if (forward) {
        testIndex++;
      } else {
        testIndex--;
      }
      dom.removeClass(findSpansByIndex(editor, currentIndexState.get()), 'mce-match-marker-selected');
      var spans = findSpansByIndex(editor, testIndex);
      if (spans.length) {
        dom.addClass(findSpansByIndex(editor, testIndex), 'mce-match-marker-selected');
        editor.selection.scrollIntoView(spans[0]);
        return testIndex;
      }
      return -1;
    };
    var removeNode = function (dom, node) {
      var parent = node.parentNode;
      dom.remove(node);
      if (dom.isEmpty(parent)) {
        dom.remove(parent);
      }
    };
    var find = function (editor, currentIndexState, text, matchCase, wholeWord) {
      text = text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
      text = text.replace(/\s/g, '[^\\S\\r\\n]');
      text = wholeWord ? '\\b' + text + '\\b' : text;
      var count = markAllMatches(editor, currentIndexState, new RegExp(text, matchCase ? 'g' : 'gi'));
      if (count) {
        currentIndexState.set(-1);
        currentIndexState.set(moveSelection(editor, currentIndexState, true));
      }
      return count;
    };
    var next = function (editor, currentIndexState) {
      var index = moveSelection(editor, currentIndexState, true);
      if (index !== -1) {
        currentIndexState.set(index);
      }
    };
    var prev = function (editor, currentIndexState) {
      var index = moveSelection(editor, currentIndexState, false);
      if (index !== -1) {
        currentIndexState.set(index);
      }
    };
    var isMatchSpan = function (node) {
      var matchIndex = getElmIndex(node);
      return matchIndex !== null && matchIndex.length > 0;
    };
    var replace = function (editor, currentIndexState, text, forward, all) {
      var i, nodes, node, matchIndex, currentMatchIndex, nextIndex = currentIndexState.get(), hasMore;
      forward = forward !== false;
      node = editor.getBody();
      nodes = global$1.grep(global$1.toArray(node.getElementsByTagName('span')), isMatchSpan);
      for (i = 0; i < nodes.length; i++) {
        var nodeIndex = getElmIndex(nodes[i]);
        matchIndex = currentMatchIndex = parseInt(nodeIndex, 10);
        if (all || matchIndex === currentIndexState.get()) {
          if (text.length) {
            nodes[i].firstChild.nodeValue = text;
            unwrap(nodes[i]);
          } else {
            removeNode(editor.dom, nodes[i]);
          }
          while (nodes[++i]) {
            matchIndex = parseInt(getElmIndex(nodes[i]), 10);
            if (matchIndex === currentMatchIndex) {
              removeNode(editor.dom, nodes[i]);
            } else {
              i--;
              break;
            }
          }
          if (forward) {
            nextIndex--;
          }
        } else if (currentMatchIndex > currentIndexState.get()) {
          nodes[i].setAttribute('data-mce-index', currentMatchIndex - 1);
        }
      }
      currentIndexState.set(nextIndex);
      if (forward) {
        hasMore = hasNext(editor, currentIndexState);
        next(editor, currentIndexState);
      } else {
        hasMore = hasPrev(editor, currentIndexState);
        prev(editor, currentIndexState);
      }
      return !all && hasMore;
    };
    var done = function (editor, currentIndexState, keepEditorSelection) {
      var i, nodes, startContainer, endContainer;
      nodes = global$1.toArray(editor.getBody().getElementsByTagName('span'));
      for (i = 0; i < nodes.length; i++) {
        var nodeIndex = getElmIndex(nodes[i]);
        if (nodeIndex !== null && nodeIndex.length) {
          if (nodeIndex === currentIndexState.get().toString()) {
            if (!startContainer) {
              startContainer = nodes[i].firstChild;
            }
            endContainer = nodes[i].firstChild;
          }
          unwrap(nodes[i]);
        }
      }
      if (startContainer && endContainer) {
        var rng = editor.dom.createRng();
        rng.setStart(startContainer, 0);
        rng.setEnd(endContainer, endContainer.data.length);
        if (keepEditorSelection !== false) {
          editor.selection.setRng(rng);
        }
        return rng;
      }
    };
    var hasNext = function (editor, currentIndexState) {
      return findSpansByIndex(editor, currentIndexState.get() + 1).length > 0;
    };
    var hasPrev = function (editor, currentIndexState) {
      return findSpansByIndex(editor, currentIndexState.get() - 1).length > 0;
    };
    var Actions = {
      done: done,
      find: find,
      next: next,
      prev: prev,
      replace: replace,
      hasNext: hasNext,
      hasPrev: hasPrev
    };

    var get = function (editor, currentIndexState) {
      var done = function (keepEditorSelection) {
        return Actions.done(editor, currentIndexState, keepEditorSelection);
      };
      var find = function (text, matchCase, wholeWord) {
        return Actions.find(editor, currentIndexState, text, matchCase, wholeWord);
      };
      var next = function () {
        return Actions.next(editor, currentIndexState);
      };
      var prev = function () {
        return Actions.prev(editor, currentIndexState);
      };
      var replace = function (text, forward, all) {
        return Actions.replace(editor, currentIndexState, text, forward, all);
      };
      return {
        done: done,
        find: find,
        next: next,
        prev: prev,
        replace: replace
      };
    };
    var Api = { get: get };

    var open = function (editor, currentIndexState) {
      var last = {}, selectedText;
      editor.undoManager.add();
      selectedText = global$1.trim(editor.selection.getContent({ format: 'text' }));
      function updateButtonStates() {
        win.statusbar.find('#next').disabled(Actions.hasNext(editor, currentIndexState) === false);
        win.statusbar.find('#prev').disabled(Actions.hasPrev(editor, currentIndexState) === false);
      }
      function notFoundAlert() {
        editor.windowManager.alert('Could not find the specified string.', function () {
          win.find('#find')[0].focus();
        });
      }
      var win = editor.windowManager.open({
        layout: 'flex',
        pack: 'center',
        align: 'center',
        onClose: function () {
          editor.focus();
          Actions.done(editor, currentIndexState);
          editor.undoManager.add();
        },
        onSubmit: function (e) {
          var count, caseState, text, wholeWord;
          e.preventDefault();
          caseState = win.find('#case').checked();
          wholeWord = win.find('#words').checked();
          text = win.find('#find').value();
          if (!text.length) {
            Actions.done(editor, currentIndexState, false);
            win.statusbar.items().slice(1).disabled(true);
            return;
          }
          if (last.text === text && last.caseState === caseState && last.wholeWord === wholeWord) {
            if (!Actions.hasNext(editor, currentIndexState)) {
              notFoundAlert();
              return;
            }
            Actions.next(editor, currentIndexState);
            updateButtonStates();
            return;
          }
          count = Actions.find(editor, currentIndexState, text, caseState, wholeWord);
          if (!count) {
            notFoundAlert();
          }
          win.statusbar.items().slice(1).disabled(count === 0);
          updateButtonStates();
          last = {
            text: text,
            caseState: caseState,
            wholeWord: wholeWord
          };
        },
        buttons: [
          {
            text: 'Find',
            subtype: 'primary',
            onclick: function () {
              win.submit();
            }
          },
          {
            text: 'Replace',
            disabled: true,
            onclick: function () {
              if (!Actions.replace(editor, currentIndexState, win.find('#replace').value())) {
                win.statusbar.items().slice(1).disabled(true);
                currentIndexState.set(-1);
                last = {};
              }
            }
          },
          {
            text: 'Replace all',
            disabled: true,
            onclick: function () {
              Actions.replace(editor, currentIndexState, win.find('#replace').value(), true, true);
              win.statusbar.items().slice(1).disabled(true);
              last = {};
            }
          },
          {
            type: 'spacer',
            flex: 1
          },
          {
            text: 'Prev',
            name: 'prev',
            disabled: true,
            onclick: function () {
              Actions.prev(editor, currentIndexState);
              updateButtonStates();
            }
          },
          {
            text: 'Next',
            name: 'next',
            disabled: true,
            onclick: function () {
              Actions.next(editor, currentIndexState);
              updateButtonStates();
            }
          }
        ],
        title: 'Find and replace',
        items: {
          type: 'form',
          padding: 20,
          labelGap: 30,
          spacing: 10,
          items: [
            {
              type: 'textbox',
              name: 'find',
              size: 40,
              label: 'Find',
              value: selectedText
            },
            {
              type: 'textbox',
              name: 'replace',
              size: 40,
              label: 'Replace with'
            },
            {
              type: 'checkbox',
              name: 'case',
              text: 'Match case',
              label: ' '
            },
            {
              type: 'checkbox',
              name: 'words',
              text: 'Whole words',
              label: ' '
            }
          ]
        }
      });
    };
    var Dialog = { open: open };

    var register = function (editor, currentIndexState) {
      editor.addCommand('SearchReplace', function () {
        Dialog.open(editor, currentIndexState);
      });
    };
    var Commands = { register: register };

    var showDialog = function (editor, currentIndexState) {
      return function () {
        Dialog.open(editor, currentIndexState);
      };
    };
    var register$1 = function (editor, currentIndexState) {
      editor.addMenuItem('searchreplace', {
        text: 'Find and replace',
        shortcut: 'Meta+F',
        onclick: showDialog(editor, currentIndexState),
        separator: 'before',
        context: 'edit'
      });
      editor.addButton('searchreplace', {
        tooltip: 'Find and replace',
        onclick: showDialog(editor, currentIndexState)
      });
      editor.shortcuts.add('Meta+F', '', showDialog(editor, currentIndexState));
    };
    var Buttons = { register: register$1 };

    global.add('searchreplace', function (editor) {
      var currentIndexState = Cell(-1);
      Commands.register(editor, currentIndexState);
      Buttons.register(editor, currentIndexState);
      return Api.get(editor, currentIndexState);
    });
    function Plugin () {
    }

    return Plugin;

}());
})();


/***/ }),

/***/ 566:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "tabfocus" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/tabfocus')
//   ES2015:
//     import 'tinymce/plugins/tabfocus'
__webpack_require__(567);

/***/ }),

/***/ 567:
/***/ (function(module, exports) {

(function () {
var tabfocus = (function (domGlobals) {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

    var global$2 = tinymce.util.Tools.resolve('tinymce.EditorManager');

    var global$3 = tinymce.util.Tools.resolve('tinymce.Env');

    var global$4 = tinymce.util.Tools.resolve('tinymce.util.Delay');

    var global$5 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    var global$6 = tinymce.util.Tools.resolve('tinymce.util.VK');

    var getTabFocusElements = function (editor) {
      return editor.getParam('tabfocus_elements', ':prev,:next');
    };
    var getTabFocus = function (editor) {
      return editor.getParam('tab_focus', getTabFocusElements(editor));
    };
    var Settings = { getTabFocus: getTabFocus };

    var DOM = global$1.DOM;
    var tabCancel = function (e) {
      if (e.keyCode === global$6.TAB && !e.ctrlKey && !e.altKey && !e.metaKey) {
        e.preventDefault();
      }
    };
    var setup = function (editor) {
      function tabHandler(e) {
        var x, el, v, i;
        if (e.keyCode !== global$6.TAB || e.ctrlKey || e.altKey || e.metaKey || e.isDefaultPrevented()) {
          return;
        }
        function find(direction) {
          el = DOM.select(':input:enabled,*[tabindex]:not(iframe)');
          function canSelectRecursive(e) {
            return e.nodeName === 'BODY' || e.type !== 'hidden' && e.style.display !== 'none' && e.style.visibility !== 'hidden' && canSelectRecursive(e.parentNode);
          }
          function canSelect(el) {
            return /INPUT|TEXTAREA|BUTTON/.test(el.tagName) && global$2.get(e.id) && el.tabIndex !== -1 && canSelectRecursive(el);
          }
          global$5.each(el, function (e, i) {
            if (e.id === editor.id) {
              x = i;
              return false;
            }
          });
          if (direction > 0) {
            for (i = x + 1; i < el.length; i++) {
              if (canSelect(el[i])) {
                return el[i];
              }
            }
          } else {
            for (i = x - 1; i >= 0; i--) {
              if (canSelect(el[i])) {
                return el[i];
              }
            }
          }
          return null;
        }
        v = global$5.explode(Settings.getTabFocus(editor));
        if (v.length === 1) {
          v[1] = v[0];
          v[0] = ':prev';
        }
        if (e.shiftKey) {
          if (v[0] === ':prev') {
            el = find(-1);
          } else {
            el = DOM.get(v[0]);
          }
        } else {
          if (v[1] === ':next') {
            el = find(1);
          } else {
            el = DOM.get(v[1]);
          }
        }
        if (el) {
          var focusEditor = global$2.get(el.id || el.name);
          if (el.id && focusEditor) {
            focusEditor.focus();
          } else {
            global$4.setTimeout(function () {
              if (!global$3.webkit) {
                domGlobals.window.focus();
              }
              el.focus();
            }, 10);
          }
          e.preventDefault();
        }
      }
      editor.on('init', function () {
        if (editor.inline) {
          DOM.setAttrib(editor.getBody(), 'tabIndex', null);
        }
        editor.on('keyup', tabCancel);
        if (global$3.gecko) {
          editor.on('keypress keydown', tabHandler);
        } else {
          editor.on('keydown', tabHandler);
        }
      });
    };
    var Keyboard = { setup: setup };

    global.add('tabfocus', function (editor) {
      Keyboard.setup(editor);
    });
    function Plugin () {
    }

    return Plugin;

}(window));
})();


/***/ }),

/***/ 568:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "autoresize" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/autoresize')
//   ES2015:
//     import 'tinymce/plugins/autoresize'
__webpack_require__(569);

/***/ }),

/***/ 569:
/***/ (function(module, exports) {

(function () {
var autoresize = (function () {
    'use strict';

    var Cell = function (initial) {
      var value = initial;
      var get = function () {
        return value;
      };
      var set = function (v) {
        value = v;
      };
      var clone = function () {
        return Cell(get());
      };
      return {
        get: get,
        set: set,
        clone: clone
      };
    };

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var global$1 = tinymce.util.Tools.resolve('tinymce.Env');

    var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay');

    var getAutoResizeMinHeight = function (editor) {
      return parseInt(editor.getParam('autoresize_min_height', editor.getElement().offsetHeight), 10);
    };
    var getAutoResizeMaxHeight = function (editor) {
      return parseInt(editor.getParam('autoresize_max_height', 0), 10);
    };
    var getAutoResizeOverflowPadding = function (editor) {
      return editor.getParam('autoresize_overflow_padding', 1);
    };
    var getAutoResizeBottomMargin = function (editor) {
      return editor.getParam('autoresize_bottom_margin', 50);
    };
    var shouldAutoResizeOnInit = function (editor) {
      return editor.getParam('autoresize_on_init', true);
    };
    var Settings = {
      getAutoResizeMinHeight: getAutoResizeMinHeight,
      getAutoResizeMaxHeight: getAutoResizeMaxHeight,
      getAutoResizeOverflowPadding: getAutoResizeOverflowPadding,
      getAutoResizeBottomMargin: getAutoResizeBottomMargin,
      shouldAutoResizeOnInit: shouldAutoResizeOnInit
    };

    var isFullscreen = function (editor) {
      return editor.plugins.fullscreen && editor.plugins.fullscreen.isFullscreen();
    };
    var wait = function (editor, oldSize, times, interval, callback) {
      global$2.setEditorTimeout(editor, function () {
        resize(editor, oldSize);
        if (times--) {
          wait(editor, oldSize, times, interval, callback);
        } else if (callback) {
          callback();
        }
      }, interval);
    };
    var toggleScrolling = function (editor, state) {
      var body = editor.getBody();
      if (body) {
        body.style.overflowY = state ? '' : 'hidden';
        if (!state) {
          body.scrollTop = 0;
        }
      }
    };
    var resize = function (editor, oldSize) {
      var deltaSize, doc, body, resizeHeight, myHeight;
      var marginTop, marginBottom, paddingTop, paddingBottom, borderTop, borderBottom;
      var dom = editor.dom;
      doc = editor.getDoc();
      if (!doc) {
        return;
      }
      if (isFullscreen(editor)) {
        toggleScrolling(editor, true);
        return;
      }
      body = doc.body;
      resizeHeight = Settings.getAutoResizeMinHeight(editor);
      marginTop = dom.getStyle(body, 'margin-top', true);
      marginBottom = dom.getStyle(body, 'margin-bottom', true);
      paddingTop = dom.getStyle(body, 'padding-top', true);
      paddingBottom = dom.getStyle(body, 'padding-bottom', true);
      borderTop = dom.getStyle(body, 'border-top-width', true);
      borderBottom = dom.getStyle(body, 'border-bottom-width', true);
      myHeight = body.offsetHeight + parseInt(marginTop, 10) + parseInt(marginBottom, 10) + parseInt(paddingTop, 10) + parseInt(paddingBottom, 10) + parseInt(borderTop, 10) + parseInt(borderBottom, 10);
      if (isNaN(myHeight) || myHeight <= 0) {
        myHeight = global$1.ie ? body.scrollHeight : global$1.webkit && body.clientHeight === 0 ? 0 : body.offsetHeight;
      }
      if (myHeight > Settings.getAutoResizeMinHeight(editor)) {
        resizeHeight = myHeight;
      }
      var maxHeight = Settings.getAutoResizeMaxHeight(editor);
      if (maxHeight && myHeight > maxHeight) {
        resizeHeight = maxHeight;
        toggleScrolling(editor, true);
      } else {
        toggleScrolling(editor, false);
      }
      if (resizeHeight !== oldSize.get()) {
        deltaSize = resizeHeight - oldSize.get();
        dom.setStyle(editor.iframeElement, 'height', resizeHeight + 'px');
        oldSize.set(resizeHeight);
        if (global$1.webkit && deltaSize < 0) {
          resize(editor, oldSize);
        }
      }
    };
    var setup = function (editor, oldSize) {
      editor.on('init', function () {
        var overflowPadding, bottomMargin;
        var dom = editor.dom;
        overflowPadding = Settings.getAutoResizeOverflowPadding(editor);
        bottomMargin = Settings.getAutoResizeBottomMargin(editor);
        if (overflowPadding !== false) {
          dom.setStyles(editor.getBody(), {
            paddingLeft: overflowPadding,
            paddingRight: overflowPadding
          });
        }
        if (bottomMargin !== false) {
          dom.setStyles(editor.getBody(), { paddingBottom: bottomMargin });
        }
      });
      editor.on('nodechange setcontent keyup FullscreenStateChanged', function (e) {
        resize(editor, oldSize);
      });
      if (Settings.shouldAutoResizeOnInit(editor)) {
        editor.on('init', function () {
          wait(editor, oldSize, 20, 100, function () {
            wait(editor, oldSize, 5, 1000);
          });
        });
      }
    };
    var Resize = {
      setup: setup,
      resize: resize
    };

    var register = function (editor, oldSize) {
      editor.addCommand('mceAutoResize', function () {
        Resize.resize(editor, oldSize);
      });
    };
    var Commands = { register: register };

    global.add('autoresize', function (editor) {
      if (!editor.inline) {
        var oldSize = Cell(0);
        Commands.register(editor, oldSize);
        Resize.setup(editor, oldSize);
      }
    });
    function Plugin () {
    }

    return Plugin;

}());
})();


/***/ }),

/***/ 570:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "link" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/link')
//   ES2015:
//     import 'tinymce/plugins/link'
__webpack_require__(571);

/***/ }),

/***/ 571:
/***/ (function(module, exports) {

(function () {
var link = (function (domGlobals) {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var global$1 = tinymce.util.Tools.resolve('tinymce.util.VK');

    var assumeExternalTargets = function (editorSettings) {
      return typeof editorSettings.link_assume_external_targets === 'boolean' ? editorSettings.link_assume_external_targets : false;
    };
    var hasContextToolbar = function (editorSettings) {
      return typeof editorSettings.link_context_toolbar === 'boolean' ? editorSettings.link_context_toolbar : false;
    };
    var getLinkList = function (editorSettings) {
      return editorSettings.link_list;
    };
    var hasDefaultLinkTarget = function (editorSettings) {
      return typeof editorSettings.default_link_target === 'string';
    };
    var getDefaultLinkTarget = function (editorSettings) {
      return editorSettings.default_link_target;
    };
    var getTargetList = function (editorSettings) {
      return editorSettings.target_list;
    };
    var setTargetList = function (editor, list) {
      editor.settings.target_list = list;
    };
    var shouldShowTargetList = function (editorSettings) {
      return getTargetList(editorSettings) !== false;
    };
    var getRelList = function (editorSettings) {
      return editorSettings.rel_list;
    };
    var hasRelList = function (editorSettings) {
      return getRelList(editorSettings) !== undefined;
    };
    var getLinkClassList = function (editorSettings) {
      return editorSettings.link_class_list;
    };
    var hasLinkClassList = function (editorSettings) {
      return getLinkClassList(editorSettings) !== undefined;
    };
    var shouldShowLinkTitle = function (editorSettings) {
      return editorSettings.link_title !== false;
    };
    var allowUnsafeLinkTarget = function (editorSettings) {
      return typeof editorSettings.allow_unsafe_link_target === 'boolean' ? editorSettings.allow_unsafe_link_target : false;
    };
    var Settings = {
      assumeExternalTargets: assumeExternalTargets,
      hasContextToolbar: hasContextToolbar,
      getLinkList: getLinkList,
      hasDefaultLinkTarget: hasDefaultLinkTarget,
      getDefaultLinkTarget: getDefaultLinkTarget,
      getTargetList: getTargetList,
      setTargetList: setTargetList,
      shouldShowTargetList: shouldShowTargetList,
      getRelList: getRelList,
      hasRelList: hasRelList,
      getLinkClassList: getLinkClassList,
      hasLinkClassList: hasLinkClassList,
      shouldShowLinkTitle: shouldShowLinkTitle,
      allowUnsafeLinkTarget: allowUnsafeLinkTarget
    };

    var global$2 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

    var global$3 = tinymce.util.Tools.resolve('tinymce.Env');

    var appendClickRemove = function (link, evt) {
      domGlobals.document.body.appendChild(link);
      link.dispatchEvent(evt);
      domGlobals.document.body.removeChild(link);
    };
    var open = function (url) {
      if (!global$3.ie || global$3.ie > 10) {
        var link = domGlobals.document.createElement('a');
        link.target = '_blank';
        link.href = url;
        link.rel = 'noreferrer noopener';
        var evt = domGlobals.document.createEvent('MouseEvents');
        evt.initMouseEvent('click', true, true, domGlobals.window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        appendClickRemove(link, evt);
      } else {
        var win = domGlobals.window.open('', '_blank');
        if (win) {
          win.opener = null;
          var doc = win.document;
          doc.open();
          doc.write('<meta http-equiv="refresh" content="0; url=' + global$2.DOM.encode(url) + '">');
          doc.close();
        }
      }
    };
    var OpenUrl = { open: open };

    var global$4 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    var toggleTargetRules = function (rel, isUnsafe) {
      var rules = ['noopener'];
      var newRel = rel ? rel.split(/\s+/) : [];
      var toString = function (rel) {
        return global$4.trim(rel.sort().join(' '));
      };
      var addTargetRules = function (rel) {
        rel = removeTargetRules(rel);
        return rel.length ? rel.concat(rules) : rules;
      };
      var removeTargetRules = function (rel) {
        return rel.filter(function (val) {
          return global$4.inArray(rules, val) === -1;
        });
      };
      newRel = isUnsafe ? addTargetRules(newRel) : removeTargetRules(newRel);
      return newRel.length ? toString(newRel) : null;
    };
    var trimCaretContainers = function (text) {
      return text.replace(/\uFEFF/g, '');
    };
    var getAnchorElement = function (editor, selectedElm) {
      selectedElm = selectedElm || editor.selection.getNode();
      if (isImageFigure(selectedElm)) {
        return editor.dom.select('a[href]', selectedElm)[0];
      } else {
        return editor.dom.getParent(selectedElm, 'a[href]');
      }
    };
    var getAnchorText = function (selection, anchorElm) {
      var text = anchorElm ? anchorElm.innerText || anchorElm.textContent : selection.getContent({ format: 'text' });
      return trimCaretContainers(text);
    };
    var isLink = function (elm) {
      return elm && elm.nodeName === 'A' && elm.href;
    };
    var hasLinks = function (elements) {
      return global$4.grep(elements, isLink).length > 0;
    };
    var isOnlyTextSelected = function (html) {
      if (/</.test(html) && (!/^<a [^>]+>[^<]+<\/a>$/.test(html) || html.indexOf('href=') === -1)) {
        return false;
      }
      return true;
    };
    var isImageFigure = function (node) {
      return node && node.nodeName === 'FIGURE' && /\bimage\b/i.test(node.className);
    };
    var link = function (editor, attachState) {
      return function (data) {
        editor.undoManager.transact(function () {
          var selectedElm = editor.selection.getNode();
          var anchorElm = getAnchorElement(editor, selectedElm);
          var linkAttrs = {
            href: data.href,
            target: data.target ? data.target : null,
            rel: data.rel ? data.rel : null,
            class: data.class ? data.class : null,
            title: data.title ? data.title : null
          };
          if (!Settings.hasRelList(editor.settings) && Settings.allowUnsafeLinkTarget(editor.settings) === false) {
            linkAttrs.rel = toggleTargetRules(linkAttrs.rel, linkAttrs.target === '_blank');
          }
          if (data.href === attachState.href) {
            attachState.attach();
            attachState = {};
          }
          if (anchorElm) {
            editor.focus();
            if (data.hasOwnProperty('text')) {
              if ('innerText' in anchorElm) {
                anchorElm.innerText = data.text;
              } else {
                anchorElm.textContent = data.text;
              }
            }
            editor.dom.setAttribs(anchorElm, linkAttrs);
            editor.selection.select(anchorElm);
            editor.undoManager.add();
          } else {
            if (isImageFigure(selectedElm)) {
              linkImageFigure(editor, selectedElm, linkAttrs);
            } else if (data.hasOwnProperty('text')) {
              editor.insertContent(editor.dom.createHTML('a', linkAttrs, editor.dom.encode(data.text)));
            } else {
              editor.execCommand('mceInsertLink', false, linkAttrs);
            }
          }
        });
      };
    };
    var unlink = function (editor) {
      return function () {
        editor.undoManager.transact(function () {
          var node = editor.selection.getNode();
          if (isImageFigure(node)) {
            unlinkImageFigure(editor, node);
          } else {
            editor.execCommand('unlink');
          }
        });
      };
    };
    var unlinkImageFigure = function (editor, fig) {
      var a, img;
      img = editor.dom.select('img', fig)[0];
      if (img) {
        a = editor.dom.getParents(img, 'a[href]', fig)[0];
        if (a) {
          a.parentNode.insertBefore(img, a);
          editor.dom.remove(a);
        }
      }
    };
    var linkImageFigure = function (editor, fig, attrs) {
      var a, img;
      img = editor.dom.select('img', fig)[0];
      if (img) {
        a = editor.dom.create('a', attrs);
        img.parentNode.insertBefore(a, img);
        a.appendChild(img);
      }
    };
    var Utils = {
      link: link,
      unlink: unlink,
      isLink: isLink,
      hasLinks: hasLinks,
      isOnlyTextSelected: isOnlyTextSelected,
      getAnchorElement: getAnchorElement,
      getAnchorText: getAnchorText,
      toggleTargetRules: toggleTargetRules
    };

    var global$5 = tinymce.util.Tools.resolve('tinymce.util.Delay');

    var global$6 = tinymce.util.Tools.resolve('tinymce.util.XHR');

    var attachState = {};
    var createLinkList = function (editor, callback) {
      var linkList = Settings.getLinkList(editor.settings);
      if (typeof linkList === 'string') {
        global$6.send({
          url: linkList,
          success: function (text) {
            callback(editor, JSON.parse(text));
          }
        });
      } else if (typeof linkList === 'function') {
        linkList(function (list) {
          callback(editor, list);
        });
      } else {
        callback(editor, linkList);
      }
    };
    var buildListItems = function (inputList, itemCallback, startItems) {
      var appendItems = function (values, output) {
        output = output || [];
        global$4.each(values, function (item) {
          var menuItem = { text: item.text || item.title };
          if (item.menu) {
            menuItem.menu = appendItems(item.menu);
          } else {
            menuItem.value = item.value;
            if (itemCallback) {
              itemCallback(menuItem);
            }
          }
          output.push(menuItem);
        });
        return output;
      };
      return appendItems(inputList, startItems || []);
    };
    var delayedConfirm = function (editor, message, callback) {
      var rng = editor.selection.getRng();
      global$5.setEditorTimeout(editor, function () {
        editor.windowManager.confirm(message, function (state) {
          editor.selection.setRng(rng);
          callback(state);
        });
      });
    };
    var showDialog = function (editor, linkList) {
      var data = {};
      var selection = editor.selection;
      var dom = editor.dom;
      var anchorElm, initialText;
      var win, onlyText, textListCtrl, linkListCtrl, relListCtrl, targetListCtrl, classListCtrl, linkTitleCtrl, value;
      var linkListChangeHandler = function (e) {
        var textCtrl = win.find('#text');
        if (!textCtrl.value() || e.lastControl && textCtrl.value() === e.lastControl.text()) {
          textCtrl.value(e.control.text());
        }
        win.find('#href').value(e.control.value());
      };
      var buildAnchorListControl = function (url) {
        var anchorList = [];
        global$4.each(editor.dom.select('a:not([href])'), function (anchor) {
          var id = anchor.name || anchor.id;
          if (id) {
            anchorList.push({
              text: id,
              value: '#' + id,
              selected: url.indexOf('#' + id) !== -1
            });
          }
        });
        if (anchorList.length) {
          anchorList.unshift({
            text: 'None',
            value: ''
          });
          return {
            name: 'anchor',
            type: 'listbox',
            label: 'Anchors',
            values: anchorList,
            onselect: linkListChangeHandler
          };
        }
      };
      var updateText = function () {
        if (!initialText && onlyText && !data.text) {
          this.parent().parent().find('#text')[0].value(this.value());
        }
      };
      var urlChange = function (e) {
        var meta = e.meta || {};
        if (linkListCtrl) {
          linkListCtrl.value(editor.convertURL(this.value(), 'href'));
        }
        global$4.each(e.meta, function (value, key) {
          var inp = win.find('#' + key);
          if (key === 'text') {
            if (initialText.length === 0) {
              inp.value(value);
              data.text = value;
            }
          } else {
            inp.value(value);
          }
        });
        if (meta.attach) {
          attachState = {
            href: this.value(),
            attach: meta.attach
          };
        }
        if (!meta.text) {
          updateText.call(this);
        }
      };
      var onBeforeCall = function (e) {
        e.meta = win.toJSON();
      };
      onlyText = Utils.isOnlyTextSelected(selection.getContent());
      anchorElm = Utils.getAnchorElement(editor);
      data.text = initialText = Utils.getAnchorText(editor.selection, anchorElm);
      data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : '';
      if (anchorElm) {
        data.target = dom.getAttrib(anchorElm, 'target');
      } else if (Settings.hasDefaultLinkTarget(editor.settings)) {
        data.target = Settings.getDefaultLinkTarget(editor.settings);
      }
      if (value = dom.getAttrib(anchorElm, 'rel')) {
        data.rel = value;
      }
      if (value = dom.getAttrib(anchorElm, 'class')) {
        data.class = value;
      }
      if (value = dom.getAttrib(anchorElm, 'title')) {
        data.title = value;
      }
      if (onlyText) {
        textListCtrl = {
          name: 'text',
          type: 'textbox',
          size: 40,
          label: 'Text to display',
          onchange: function () {
            data.text = this.value();
          }
        };
      }
      if (linkList) {
        linkListCtrl = {
          type: 'listbox',
          label: 'Link list',
          values: buildListItems(linkList, function (item) {
            item.value = editor.convertURL(item.value || item.url, 'href');
          }, [{
              text: 'None',
              value: ''
            }]),
          onselect: linkListChangeHandler,
          value: editor.convertURL(data.href, 'href'),
          onPostRender: function () {
            linkListCtrl = this;
          }
        };
      }
      if (Settings.shouldShowTargetList(editor.settings)) {
        if (Settings.getTargetList(editor.settings) === undefined) {
          Settings.setTargetList(editor, [
            {
              text: 'None',
              value: ''
            },
            {
              text: 'New window',
              value: '_blank'
            }
          ]);
        }
        targetListCtrl = {
          name: 'target',
          type: 'listbox',
          label: 'Target',
          values: buildListItems(Settings.getTargetList(editor.settings))
        };
      }
      if (Settings.hasRelList(editor.settings)) {
        relListCtrl = {
          name: 'rel',
          type: 'listbox',
          label: 'Rel',
          values: buildListItems(Settings.getRelList(editor.settings), function (item) {
            if (Settings.allowUnsafeLinkTarget(editor.settings) === false) {
              item.value = Utils.toggleTargetRules(item.value, data.target === '_blank');
            }
          })
        };
      }
      if (Settings.hasLinkClassList(editor.settings)) {
        classListCtrl = {
          name: 'class',
          type: 'listbox',
          label: 'Class',
          values: buildListItems(Settings.getLinkClassList(editor.settings), function (item) {
            if (item.value) {
              item.textStyle = function () {
                return editor.formatter.getCssText({
                  inline: 'a',
                  classes: [item.value]
                });
              };
            }
          })
        };
      }
      if (Settings.shouldShowLinkTitle(editor.settings)) {
        linkTitleCtrl = {
          name: 'title',
          type: 'textbox',
          label: 'Title',
          value: data.title
        };
      }
      win = editor.windowManager.open({
        title: 'Insert link',
        data: data,
        body: [
          {
            name: 'href',
            type: 'filepicker',
            filetype: 'file',
            size: 40,
            autofocus: true,
            label: 'Url',
            onchange: urlChange,
            onkeyup: updateText,
            onpaste: updateText,
            onbeforecall: onBeforeCall
          },
          textListCtrl,
          linkTitleCtrl,
          buildAnchorListControl(data.href),
          linkListCtrl,
          relListCtrl,
          targetListCtrl,
          classListCtrl
        ],
        onSubmit: function (e) {
          var assumeExternalTargets = Settings.assumeExternalTargets(editor.settings);
          var insertLink = Utils.link(editor, attachState);
          var removeLink = Utils.unlink(editor);
          var resultData = global$4.extend({}, data, e.data);
          var href = resultData.href;
          if (!href) {
            removeLink();
            return;
          }
          if (!onlyText || resultData.text === initialText) {
            delete resultData.text;
          }
          if (href.indexOf('@') > 0 && href.indexOf('//') === -1 && href.indexOf('mailto:') === -1) {
            delayedConfirm(editor, 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?', function (state) {
              if (state) {
                resultData.href = 'mailto:' + href;
              }
              insertLink(resultData);
            });
            return;
          }
          if (assumeExternalTargets === true && !/^\w+:/i.test(href) || assumeExternalTargets === false && /^\s*www[\.|\d\.]/i.test(href)) {
            delayedConfirm(editor, 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?', function (state) {
              if (state) {
                resultData.href = 'http://' + href;
              }
              insertLink(resultData);
            });
            return;
          }
          insertLink(resultData);
        }
      });
    };
    var open$1 = function (editor) {
      createLinkList(editor, showDialog);
    };
    var Dialog = { open: open$1 };

    var getLink = function (editor, elm) {
      return editor.dom.getParent(elm, 'a[href]');
    };
    var getSelectedLink = function (editor) {
      return getLink(editor, editor.selection.getStart());
    };
    var getHref = function (elm) {
      var href = elm.getAttribute('data-mce-href');
      return href ? href : elm.getAttribute('href');
    };
    var isContextMenuVisible = function (editor) {
      var contextmenu = editor.plugins.contextmenu;
      return contextmenu ? contextmenu.isContextMenuVisible() : false;
    };
    var hasOnlyAltModifier = function (e) {
      return e.altKey === true && e.shiftKey === false && e.ctrlKey === false && e.metaKey === false;
    };
    var gotoLink = function (editor, a) {
      if (a) {
        var href = getHref(a);
        if (/^#/.test(href)) {
          var targetEl = editor.$(href);
          if (targetEl.length) {
            editor.selection.scrollIntoView(targetEl[0], true);
          }
        } else {
          OpenUrl.open(a.href);
        }
      }
    };
    var openDialog = function (editor) {
      return function () {
        Dialog.open(editor);
      };
    };
    var gotoSelectedLink = function (editor) {
      return function () {
        gotoLink(editor, getSelectedLink(editor));
      };
    };
    var leftClickedOnAHref = function (editor) {
      return function (elm) {
        var sel, rng, node;
        if (Settings.hasContextToolbar(editor.settings) && !isContextMenuVisible(editor) && Utils.isLink(elm)) {
          sel = editor.selection;
          rng = sel.getRng();
          node = rng.startContainer;
          if (node.nodeType === 3 && sel.isCollapsed() && rng.startOffset > 0 && rng.startOffset < node.data.length) {
            return true;
          }
        }
        return false;
      };
    };
    var setupGotoLinks = function (editor) {
      editor.on('click', function (e) {
        var link = getLink(editor, e.target);
        if (link && global$1.metaKeyPressed(e)) {
          e.preventDefault();
          gotoLink(editor, link);
        }
      });
      editor.on('keydown', function (e) {
        var link = getSelectedLink(editor);
        if (link && e.keyCode === 13 && hasOnlyAltModifier(e)) {
          e.preventDefault();
          gotoLink(editor, link);
        }
      });
    };
    var toggleActiveState = function (editor) {
      return function () {
        var self = this;
        editor.on('nodechange', function (e) {
          self.active(!editor.readonly && !!Utils.getAnchorElement(editor, e.element));
        });
      };
    };
    var toggleViewLinkState = function (editor) {
      return function () {
        var self = this;
        var toggleVisibility = function (e) {
          if (Utils.hasLinks(e.parents)) {
            self.show();
          } else {
            self.hide();
          }
        };
        if (!Utils.hasLinks(editor.dom.getParents(editor.selection.getStart()))) {
          self.hide();
        }
        editor.on('nodechange', toggleVisibility);
        self.on('remove', function () {
          editor.off('nodechange', toggleVisibility);
        });
      };
    };
    var Actions = {
      openDialog: openDialog,
      gotoSelectedLink: gotoSelectedLink,
      leftClickedOnAHref: leftClickedOnAHref,
      setupGotoLinks: setupGotoLinks,
      toggleActiveState: toggleActiveState,
      toggleViewLinkState: toggleViewLinkState
    };

    var register = function (editor) {
      editor.addCommand('mceLink', Actions.openDialog(editor));
    };
    var Commands = { register: register };

    var setup = function (editor) {
      editor.addShortcut('Meta+K', '', Actions.openDialog(editor));
    };
    var Keyboard = { setup: setup };

    var setupButtons = function (editor) {
      editor.addButton('link', {
        active: false,
        icon: 'link',
        tooltip: 'Insert/edit link',
        onclick: Actions.openDialog(editor),
        onpostrender: Actions.toggleActiveState(editor)
      });
      editor.addButton('unlink', {
        active: false,
        icon: 'unlink',
        tooltip: 'Remove link',
        onclick: Utils.unlink(editor),
        onpostrender: Actions.toggleActiveState(editor)
      });
      if (editor.addContextToolbar) {
        editor.addButton('openlink', {
          icon: 'newtab',
          tooltip: 'Open link',
          onclick: Actions.gotoSelectedLink(editor)
        });
      }
    };
    var setupMenuItems = function (editor) {
      editor.addMenuItem('openlink', {
        text: 'Open link',
        icon: 'newtab',
        onclick: Actions.gotoSelectedLink(editor),
        onPostRender: Actions.toggleViewLinkState(editor),
        prependToContext: true
      });
      editor.addMenuItem('link', {
        icon: 'link',
        text: 'Link',
        shortcut: 'Meta+K',
        onclick: Actions.openDialog(editor),
        stateSelector: 'a[href]',
        context: 'insert',
        prependToContext: true
      });
      editor.addMenuItem('unlink', {
        icon: 'unlink',
        text: 'Remove link',
        onclick: Utils.unlink(editor),
        stateSelector: 'a[href]'
      });
    };
    var setupContextToolbars = function (editor) {
      if (editor.addContextToolbar) {
        editor.addContextToolbar(Actions.leftClickedOnAHref(editor), 'openlink | link unlink');
      }
    };
    var Controls = {
      setupButtons: setupButtons,
      setupMenuItems: setupMenuItems,
      setupContextToolbars: setupContextToolbars
    };

    global.add('link', function (editor) {
      Controls.setupButtons(editor);
      Controls.setupMenuItems(editor);
      Controls.setupContextToolbars(editor);
      Actions.setupGotoLinks(editor);
      Commands.register(editor);
      Keyboard.setup(editor);
    });
    function Plugin () {
    }

    return Plugin;

}(window));
})();


/***/ }),

/***/ 572:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "image" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/image')
//   ES2015:
//     import 'tinymce/plugins/image'
__webpack_require__(573);

/***/ }),

/***/ 573:
/***/ (function(module, exports) {

(function () {
var image = (function (domGlobals) {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var hasDimensions = function (editor) {
      return editor.settings.image_dimensions === false ? false : true;
    };
    var hasAdvTab = function (editor) {
      return editor.settings.image_advtab === true ? true : false;
    };
    var getPrependUrl = function (editor) {
      return editor.getParam('image_prepend_url', '');
    };
    var getClassList = function (editor) {
      return editor.getParam('image_class_list');
    };
    var hasDescription = function (editor) {
      return editor.settings.image_description === false ? false : true;
    };
    var hasImageTitle = function (editor) {
      return editor.settings.image_title === true ? true : false;
    };
    var hasImageCaption = function (editor) {
      return editor.settings.image_caption === true ? true : false;
    };
    var getImageList = function (editor) {
      return editor.getParam('image_list', false);
    };
    var hasUploadUrl = function (editor) {
      return editor.getParam('images_upload_url', false);
    };
    var hasUploadHandler = function (editor) {
      return editor.getParam('images_upload_handler', false);
    };
    var getUploadUrl = function (editor) {
      return editor.getParam('images_upload_url');
    };
    var getUploadHandler = function (editor) {
      return editor.getParam('images_upload_handler');
    };
    var getUploadBasePath = function (editor) {
      return editor.getParam('images_upload_base_path');
    };
    var getUploadCredentials = function (editor) {
      return editor.getParam('images_upload_credentials');
    };
    var Settings = {
      hasDimensions: hasDimensions,
      hasAdvTab: hasAdvTab,
      getPrependUrl: getPrependUrl,
      getClassList: getClassList,
      hasDescription: hasDescription,
      hasImageTitle: hasImageTitle,
      hasImageCaption: hasImageCaption,
      getImageList: getImageList,
      hasUploadUrl: hasUploadUrl,
      hasUploadHandler: hasUploadHandler,
      getUploadUrl: getUploadUrl,
      getUploadHandler: getUploadHandler,
      getUploadBasePath: getUploadBasePath,
      getUploadCredentials: getUploadCredentials
    };

    var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();

    var path = function (parts, scope) {
      var o = scope !== undefined && scope !== null ? scope : Global;
      for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
        o = o[parts[i]];
      }
      return o;
    };
    var resolve = function (p, scope) {
      var parts = p.split('.');
      return path(parts, scope);
    };

    var unsafe = function (name, scope) {
      return resolve(name, scope);
    };
    var getOrDie = function (name, scope) {
      var actual = unsafe(name, scope);
      if (actual === undefined || actual === null) {
        throw new Error(name + ' not available on this browser');
      }
      return actual;
    };
    var Global$1 = { getOrDie: getOrDie };

    function FileReader () {
      var f = Global$1.getOrDie('FileReader');
      return new f();
    }

    var global$1 = tinymce.util.Tools.resolve('tinymce.util.Promise');

    var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    var global$3 = tinymce.util.Tools.resolve('tinymce.util.XHR');

    var parseIntAndGetMax = function (val1, val2) {
      return Math.max(parseInt(val1, 10), parseInt(val2, 10));
    };
    var getImageSize = function (url, callback) {
      var img = domGlobals.document.createElement('img');
      function done(width, height) {
        if (img.parentNode) {
          img.parentNode.removeChild(img);
        }
        callback({
          width: width,
          height: height
        });
      }
      img.onload = function () {
        var width = parseIntAndGetMax(img.width, img.clientWidth);
        var height = parseIntAndGetMax(img.height, img.clientHeight);
        done(width, height);
      };
      img.onerror = function () {
        done(0, 0);
      };
      var style = img.style;
      style.visibility = 'hidden';
      style.position = 'fixed';
      style.bottom = style.left = '0px';
      style.width = style.height = 'auto';
      domGlobals.document.body.appendChild(img);
      img.src = url;
    };
    var buildListItems = function (inputList, itemCallback, startItems) {
      function appendItems(values, output) {
        output = output || [];
        global$2.each(values, function (item) {
          var menuItem = { text: item.text || item.title };
          if (item.menu) {
            menuItem.menu = appendItems(item.menu);
          } else {
            menuItem.value = item.value;
            itemCallback(menuItem);
          }
          output.push(menuItem);
        });
        return output;
      }
      return appendItems(inputList, startItems || []);
    };
    var removePixelSuffix = function (value) {
      if (value) {
        value = value.replace(/px$/, '');
      }
      return value;
    };
    var addPixelSuffix = function (value) {
      if (value.length > 0 && /^[0-9]+$/.test(value)) {
        value += 'px';
      }
      return value;
    };
    var mergeMargins = function (css) {
      if (css.margin) {
        var splitMargin = css.margin.split(' ');
        switch (splitMargin.length) {
        case 1:
          css['margin-top'] = css['margin-top'] || splitMargin[0];
          css['margin-right'] = css['margin-right'] || splitMargin[0];
          css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
          css['margin-left'] = css['margin-left'] || splitMargin[0];
          break;
        case 2:
          css['margin-top'] = css['margin-top'] || splitMargin[0];
          css['margin-right'] = css['margin-right'] || splitMargin[1];
          css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
          css['margin-left'] = css['margin-left'] || splitMargin[1];
          break;
        case 3:
          css['margin-top'] = css['margin-top'] || splitMargin[0];
          css['margin-right'] = css['margin-right'] || splitMargin[1];
          css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
          css['margin-left'] = css['margin-left'] || splitMargin[1];
          break;
        case 4:
          css['margin-top'] = css['margin-top'] || splitMargin[0];
          css['margin-right'] = css['margin-right'] || splitMargin[1];
          css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
          css['margin-left'] = css['margin-left'] || splitMargin[3];
        }
        delete css.margin;
      }
      return css;
    };
    var createImageList = function (editor, callback) {
      var imageList = Settings.getImageList(editor);
      if (typeof imageList === 'string') {
        global$3.send({
          url: imageList,
          success: function (text) {
            callback(JSON.parse(text));
          }
        });
      } else if (typeof imageList === 'function') {
        imageList(callback);
      } else {
        callback(imageList);
      }
    };
    var waitLoadImage = function (editor, data, imgElm) {
      function selectImage() {
        imgElm.onload = imgElm.onerror = null;
        if (editor.selection) {
          editor.selection.select(imgElm);
          editor.nodeChanged();
        }
      }
      imgElm.onload = function () {
        if (!data.width && !data.height && Settings.hasDimensions(editor)) {
          editor.dom.setAttribs(imgElm, {
            width: imgElm.clientWidth,
            height: imgElm.clientHeight
          });
        }
        selectImage();
      };
      imgElm.onerror = selectImage;
    };
    var blobToDataUri = function (blob) {
      return new global$1(function (resolve, reject) {
        var reader = FileReader();
        reader.onload = function () {
          resolve(reader.result);
        };
        reader.onerror = function () {
          reject(reader.error.message);
        };
        reader.readAsDataURL(blob);
      });
    };
    var Utils = {
      getImageSize: getImageSize,
      buildListItems: buildListItems,
      removePixelSuffix: removePixelSuffix,
      addPixelSuffix: addPixelSuffix,
      mergeMargins: mergeMargins,
      createImageList: createImageList,
      waitLoadImage: waitLoadImage,
      blobToDataUri: blobToDataUri
    };

    var global$4 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

    var hasOwnProperty = Object.prototype.hasOwnProperty;
    var shallow = function (old, nu) {
      return nu;
    };
    var baseMerge = function (merger) {
      return function () {
        var objects = new Array(arguments.length);
        for (var i = 0; i < objects.length; i++) {
          objects[i] = arguments[i];
        }
        if (objects.length === 0) {
          throw new Error('Can\'t merge zero objects');
        }
        var ret = {};
        for (var j = 0; j < objects.length; j++) {
          var curObject = objects[j];
          for (var key in curObject) {
            if (hasOwnProperty.call(curObject, key)) {
              ret[key] = merger(ret[key], curObject[key]);
            }
          }
        }
        return ret;
      };
    };
    var merge = baseMerge(shallow);

    var DOM = global$4.DOM;
    var getHspace = function (image) {
      if (image.style.marginLeft && image.style.marginRight && image.style.marginLeft === image.style.marginRight) {
        return Utils.removePixelSuffix(image.style.marginLeft);
      } else {
        return '';
      }
    };
    var getVspace = function (image) {
      if (image.style.marginTop && image.style.marginBottom && image.style.marginTop === image.style.marginBottom) {
        return Utils.removePixelSuffix(image.style.marginTop);
      } else {
        return '';
      }
    };
    var getBorder = function (image) {
      if (image.style.borderWidth) {
        return Utils.removePixelSuffix(image.style.borderWidth);
      } else {
        return '';
      }
    };
    var getAttrib = function (image, name) {
      if (image.hasAttribute(name)) {
        return image.getAttribute(name);
      } else {
        return '';
      }
    };
    var getStyle = function (image, name) {
      return image.style[name] ? image.style[name] : '';
    };
    var hasCaption = function (image) {
      return image.parentNode !== null && image.parentNode.nodeName === 'FIGURE';
    };
    var setAttrib = function (image, name, value) {
      image.setAttribute(name, value);
    };
    var wrapInFigure = function (image) {
      var figureElm = DOM.create('figure', { class: 'image' });
      DOM.insertAfter(figureElm, image);
      figureElm.appendChild(image);
      figureElm.appendChild(DOM.create('figcaption', { contentEditable: true }, 'Caption'));
      figureElm.contentEditable = 'false';
    };
    var removeFigure = function (image) {
      var figureElm = image.parentNode;
      DOM.insertAfter(image, figureElm);
      DOM.remove(figureElm);
    };
    var toggleCaption = function (image) {
      if (hasCaption(image)) {
        removeFigure(image);
      } else {
        wrapInFigure(image);
      }
    };
    var normalizeStyle = function (image, normalizeCss) {
      var attrValue = image.getAttribute('style');
      var value = normalizeCss(attrValue !== null ? attrValue : '');
      if (value.length > 0) {
        image.setAttribute('style', value);
        image.setAttribute('data-mce-style', value);
      } else {
        image.removeAttribute('style');
      }
    };
    var setSize = function (name, normalizeCss) {
      return function (image, name, value) {
        if (image.style[name]) {
          image.style[name] = Utils.addPixelSuffix(value);
          normalizeStyle(image, normalizeCss);
        } else {
          setAttrib(image, name, value);
        }
      };
    };
    var getSize = function (image, name) {
      if (image.style[name]) {
        return Utils.removePixelSuffix(image.style[name]);
      } else {
        return getAttrib(image, name);
      }
    };
    var setHspace = function (image, value) {
      var pxValue = Utils.addPixelSuffix(value);
      image.style.marginLeft = pxValue;
      image.style.marginRight = pxValue;
    };
    var setVspace = function (image, value) {
      var pxValue = Utils.addPixelSuffix(value);
      image.style.marginTop = pxValue;
      image.style.marginBottom = pxValue;
    };
    var setBorder = function (image, value) {
      var pxValue = Utils.addPixelSuffix(value);
      image.style.borderWidth = pxValue;
    };
    var setBorderStyle = function (image, value) {
      image.style.borderStyle = value;
    };
    var getBorderStyle = function (image) {
      return getStyle(image, 'borderStyle');
    };
    var isFigure = function (elm) {
      return elm.nodeName === 'FIGURE';
    };
    var defaultData = function () {
      return {
        src: '',
        alt: '',
        title: '',
        width: '',
        height: '',
        class: '',
        style: '',
        caption: false,
        hspace: '',
        vspace: '',
        border: '',
        borderStyle: ''
      };
    };
    var getStyleValue = function (normalizeCss, data) {
      var image = domGlobals.document.createElement('img');
      setAttrib(image, 'style', data.style);
      if (getHspace(image) || data.hspace !== '') {
        setHspace(image, data.hspace);
      }
      if (getVspace(image) || data.vspace !== '') {
        setVspace(image, data.vspace);
      }
      if (getBorder(image) || data.border !== '') {
        setBorder(image, data.border);
      }
      if (getBorderStyle(image) || data.borderStyle !== '') {
        setBorderStyle(image, data.borderStyle);
      }
      return normalizeCss(image.getAttribute('style'));
    };
    var create = function (normalizeCss, data) {
      var image = domGlobals.document.createElement('img');
      write(normalizeCss, merge(data, { caption: false }), image);
      setAttrib(image, 'alt', data.alt);
      if (data.caption) {
        var figure = DOM.create('figure', { class: 'image' });
        figure.appendChild(image);
        figure.appendChild(DOM.create('figcaption', { contentEditable: true }, 'Caption'));
        figure.contentEditable = 'false';
        return figure;
      } else {
        return image;
      }
    };
    var read = function (normalizeCss, image) {
      return {
        src: getAttrib(image, 'src'),
        alt: getAttrib(image, 'alt'),
        title: getAttrib(image, 'title'),
        width: getSize(image, 'width'),
        height: getSize(image, 'height'),
        class: getAttrib(image, 'class'),
        style: normalizeCss(getAttrib(image, 'style')),
        caption: hasCaption(image),
        hspace: getHspace(image),
        vspace: getVspace(image),
        border: getBorder(image),
        borderStyle: getStyle(image, 'borderStyle')
      };
    };
    var updateProp = function (image, oldData, newData, name, set) {
      if (newData[name] !== oldData[name]) {
        set(image, name, newData[name]);
      }
    };
    var normalized = function (set, normalizeCss) {
      return function (image, name, value) {
        set(image, value);
        normalizeStyle(image, normalizeCss);
      };
    };
    var write = function (normalizeCss, newData, image) {
      var oldData = read(normalizeCss, image);
      updateProp(image, oldData, newData, 'caption', function (image, _name, _value) {
        return toggleCaption(image);
      });
      updateProp(image, oldData, newData, 'src', setAttrib);
      updateProp(image, oldData, newData, 'alt', setAttrib);
      updateProp(image, oldData, newData, 'title', setAttrib);
      updateProp(image, oldData, newData, 'width', setSize('width', normalizeCss));
      updateProp(image, oldData, newData, 'height', setSize('height', normalizeCss));
      updateProp(image, oldData, newData, 'class', setAttrib);
      updateProp(image, oldData, newData, 'style', normalized(function (image, value) {
        return setAttrib(image, 'style', value);
      }, normalizeCss));
      updateProp(image, oldData, newData, 'hspace', normalized(setHspace, normalizeCss));
      updateProp(image, oldData, newData, 'vspace', normalized(setVspace, normalizeCss));
      updateProp(image, oldData, newData, 'border', normalized(setBorder, normalizeCss));
      updateProp(image, oldData, newData, 'borderStyle', normalized(setBorderStyle, normalizeCss));
    };

    var normalizeCss = function (editor, cssText) {
      var css = editor.dom.styles.parse(cssText);
      var mergedCss = Utils.mergeMargins(css);
      var compressed = editor.dom.styles.parse(editor.dom.styles.serialize(mergedCss));
      return editor.dom.styles.serialize(compressed);
    };
    var getSelectedImage = function (editor) {
      var imgElm = editor.selection.getNode();
      var figureElm = editor.dom.getParent(imgElm, 'figure.image');
      if (figureElm) {
        return editor.dom.select('img', figureElm)[0];
      }
      if (imgElm && (imgElm.nodeName !== 'IMG' || imgElm.getAttribute('data-mce-object') || imgElm.getAttribute('data-mce-placeholder'))) {
        return null;
      }
      return imgElm;
    };
    var splitTextBlock = function (editor, figure) {
      var dom = editor.dom;
      var textBlock = dom.getParent(figure.parentNode, function (node) {
        return editor.schema.getTextBlockElements()[node.nodeName];
      }, editor.getBody());
      if (textBlock) {
        return dom.split(textBlock, figure);
      } else {
        return figure;
      }
    };
    var readImageDataFromSelection = function (editor) {
      var image = getSelectedImage(editor);
      return image ? read(function (css) {
        return normalizeCss(editor, css);
      }, image) : defaultData();
    };
    var insertImageAtCaret = function (editor, data) {
      var elm = create(function (css) {
        return normalizeCss(editor, css);
      }, data);
      editor.dom.setAttrib(elm, 'data-mce-id', '__mcenew');
      editor.focus();
      editor.selection.setContent(elm.outerHTML);
      var insertedElm = editor.dom.select('*[data-mce-id="__mcenew"]')[0];
      editor.dom.setAttrib(insertedElm, 'data-mce-id', null);
      if (isFigure(insertedElm)) {
        var figure = splitTextBlock(editor, insertedElm);
        editor.selection.select(figure);
      } else {
        editor.selection.select(insertedElm);
      }
    };
    var syncSrcAttr = function (editor, image) {
      editor.dom.setAttrib(image, 'src', image.getAttribute('src'));
    };
    var deleteImage = function (editor, image) {
      if (image) {
        var elm = editor.dom.is(image.parentNode, 'figure.image') ? image.parentNode : image;
        editor.dom.remove(elm);
        editor.focus();
        editor.nodeChanged();
        if (editor.dom.isEmpty(editor.getBody())) {
          editor.setContent('');
          editor.selection.setCursorLocation();
        }
      }
    };
    var writeImageDataToSelection = function (editor, data) {
      var image = getSelectedImage(editor);
      write(function (css) {
        return normalizeCss(editor, css);
      }, data, image);
      syncSrcAttr(editor, image);
      if (isFigure(image.parentNode)) {
        var figure = image.parentNode;
        splitTextBlock(editor, figure);
        editor.selection.select(image.parentNode);
      } else {
        editor.selection.select(image);
        Utils.waitLoadImage(editor, data, image);
      }
    };
    var insertOrUpdateImage = function (editor, data) {
      var image = getSelectedImage(editor);
      if (image) {
        if (data.src) {
          writeImageDataToSelection(editor, data);
        } else {
          deleteImage(editor, image);
        }
      } else if (data.src) {
        insertImageAtCaret(editor, data);
      }
    };

    var updateVSpaceHSpaceBorder = function (editor) {
      return function (evt) {
        var dom = editor.dom;
        var rootControl = evt.control.rootControl;
        if (!Settings.hasAdvTab(editor)) {
          return;
        }
        var data = rootControl.toJSON();
        var css = dom.parseStyle(data.style);
        rootControl.find('#vspace').value('');
        rootControl.find('#hspace').value('');
        css = Utils.mergeMargins(css);
        if (css['margin-top'] && css['margin-bottom'] || css['margin-right'] && css['margin-left']) {
          if (css['margin-top'] === css['margin-bottom']) {
            rootControl.find('#vspace').value(Utils.removePixelSuffix(css['margin-top']));
          } else {
            rootControl.find('#vspace').value('');
          }
          if (css['margin-right'] === css['margin-left']) {
            rootControl.find('#hspace').value(Utils.removePixelSuffix(css['margin-right']));
          } else {
            rootControl.find('#hspace').value('');
          }
        }
        if (css['border-width']) {
          rootControl.find('#border').value(Utils.removePixelSuffix(css['border-width']));
        } else {
          rootControl.find('#border').value('');
        }
        if (css['border-style']) {
          rootControl.find('#borderStyle').value(css['border-style']);
        } else {
          rootControl.find('#borderStyle').value('');
        }
        rootControl.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
      };
    };
    var updateStyle = function (editor, win) {
      win.find('#style').each(function (ctrl) {
        var value = getStyleValue(function (css) {
          return normalizeCss(editor, css);
        }, merge(defaultData(), win.toJSON()));
        ctrl.value(value);
      });
    };
    var makeTab = function (editor) {
      return {
        title: 'Advanced',
        type: 'form',
        pack: 'start',
        items: [
          {
            label: 'Style',
            name: 'style',
            type: 'textbox',
            onchange: updateVSpaceHSpaceBorder(editor)
          },
          {
            type: 'form',
            layout: 'grid',
            packV: 'start',
            columns: 2,
            padding: 0,
            defaults: {
              type: 'textbox',
              maxWidth: 50,
              onchange: function (evt) {
                updateStyle(editor, evt.control.rootControl);
              }
            },
            items: [
              {
                label: 'Vertical space',
                name: 'vspace'
              },
              {
                label: 'Border width',
                name: 'border'
              },
              {
                label: 'Horizontal space',
                name: 'hspace'
              },
              {
                label: 'Border style',
                type: 'listbox',
                name: 'borderStyle',
                width: 90,
                maxWidth: 90,
                onselect: function (evt) {
                  updateStyle(editor, evt.control.rootControl);
                },
                values: [
                  {
                    text: 'Select...',
                    value: ''
                  },
                  {
                    text: 'Solid',
                    value: 'solid'
                  },
                  {
                    text: 'Dotted',
                    value: 'dotted'
                  },
                  {
                    text: 'Dashed',
                    value: 'dashed'
                  },
                  {
                    text: 'Double',
                    value: 'double'
                  },
                  {
                    text: 'Groove',
                    value: 'groove'
                  },
                  {
                    text: 'Ridge',
                    value: 'ridge'
                  },
                  {
                    text: 'Inset',
                    value: 'inset'
                  },
                  {
                    text: 'Outset',
                    value: 'outset'
                  },
                  {
                    text: 'None',
                    value: 'none'
                  },
                  {
                    text: 'Hidden',
                    value: 'hidden'
                  }
                ]
              }
            ]
          }
        ]
      };
    };
    var AdvTab = { makeTab: makeTab };

    var doSyncSize = function (widthCtrl, heightCtrl) {
      widthCtrl.state.set('oldVal', widthCtrl.value());
      heightCtrl.state.set('oldVal', heightCtrl.value());
    };
    var doSizeControls = function (win, f) {
      var widthCtrl = win.find('#width')[0];
      var heightCtrl = win.find('#height')[0];
      var constrained = win.find('#constrain')[0];
      if (widthCtrl && heightCtrl && constrained) {
        f(widthCtrl, heightCtrl, constrained.checked());
      }
    };
    var doUpdateSize = function (widthCtrl, heightCtrl, isContrained) {
      var oldWidth = widthCtrl.state.get('oldVal');
      var oldHeight = heightCtrl.state.get('oldVal');
      var newWidth = widthCtrl.value();
      var newHeight = heightCtrl.value();
      if (isContrained && oldWidth && oldHeight && newWidth && newHeight) {
        if (newWidth !== oldWidth) {
          newHeight = Math.round(newWidth / oldWidth * newHeight);
          if (!isNaN(newHeight)) {
            heightCtrl.value(newHeight);
          }
        } else {
          newWidth = Math.round(newHeight / oldHeight * newWidth);
          if (!isNaN(newWidth)) {
            widthCtrl.value(newWidth);
          }
        }
      }
      doSyncSize(widthCtrl, heightCtrl);
    };
    var syncSize = function (win) {
      doSizeControls(win, doSyncSize);
    };
    var updateSize = function (win) {
      doSizeControls(win, doUpdateSize);
    };
    var createUi = function () {
      var recalcSize = function (evt) {
        updateSize(evt.control.rootControl);
      };
      return {
        type: 'container',
        label: 'Dimensions',
        layout: 'flex',
        align: 'center',
        spacing: 5,
        items: [
          {
            name: 'width',
            type: 'textbox',
            maxLength: 5,
            size: 5,
            onchange: recalcSize,
            ariaLabel: 'Width'
          },
          {
            type: 'label',
            text: 'x'
          },
          {
            name: 'height',
            type: 'textbox',
            maxLength: 5,
            size: 5,
            onchange: recalcSize,
            ariaLabel: 'Height'
          },
          {
            name: 'constrain',
            type: 'checkbox',
            checked: true,
            text: 'Constrain proportions'
          }
        ]
      };
    };
    var SizeManager = {
      createUi: createUi,
      syncSize: syncSize,
      updateSize: updateSize
    };

    var onSrcChange = function (evt, editor) {
      var srcURL, prependURL, absoluteURLPattern;
      var meta = evt.meta || {};
      var control = evt.control;
      var rootControl = control.rootControl;
      var imageListCtrl = rootControl.find('#image-list')[0];
      if (imageListCtrl) {
        imageListCtrl.value(editor.convertURL(control.value(), 'src'));
      }
      global$2.each(meta, function (value, key) {
        rootControl.find('#' + key).value(value);
      });
      if (!meta.width && !meta.height) {
        srcURL = editor.convertURL(control.value(), 'src');
        prependURL = Settings.getPrependUrl(editor);
        absoluteURLPattern = new RegExp('^(?:[a-z]+:)?//', 'i');
        if (prependURL && !absoluteURLPattern.test(srcURL) && srcURL.substring(0, prependURL.length) !== prependURL) {
          srcURL = prependURL + srcURL;
        }
        control.value(srcURL);
        Utils.getImageSize(editor.documentBaseURI.toAbsolute(control.value()), function (data) {
          if (data.width && data.height && Settings.hasDimensions(editor)) {
            rootControl.find('#width').value(data.width);
            rootControl.find('#height').value(data.height);
            SizeManager.syncSize(rootControl);
          }
        });
      }
    };
    var onBeforeCall = function (evt) {
      evt.meta = evt.control.rootControl.toJSON();
    };
    var getGeneralItems = function (editor, imageListCtrl) {
      var generalFormItems = [
        {
          name: 'src',
          type: 'filepicker',
          filetype: 'image',
          label: 'Source',
          autofocus: true,
          onchange: function (evt) {
            onSrcChange(evt, editor);
          },
          onbeforecall: onBeforeCall
        },
        imageListCtrl
      ];
      if (Settings.hasDescription(editor)) {
        generalFormItems.push({
          name: 'alt',
          type: 'textbox',
          label: 'Image description'
        });
      }
      if (Settings.hasImageTitle(editor)) {
        generalFormItems.push({
          name: 'title',
          type: 'textbox',
          label: 'Image Title'
        });
      }
      if (Settings.hasDimensions(editor)) {
        generalFormItems.push(SizeManager.createUi());
      }
      if (Settings.getClassList(editor)) {
        generalFormItems.push({
          name: 'class',
          type: 'listbox',
          label: 'Class',
          values: Utils.buildListItems(Settings.getClassList(editor), function (item) {
            if (item.value) {
              item.textStyle = function () {
                return editor.formatter.getCssText({
                  inline: 'img',
                  classes: [item.value]
                });
              };
            }
          })
        });
      }
      if (Settings.hasImageCaption(editor)) {
        generalFormItems.push({
          name: 'caption',
          type: 'checkbox',
          label: 'Caption'
        });
      }
      return generalFormItems;
    };
    var makeTab$1 = function (editor, imageListCtrl) {
      return {
        title: 'General',
        type: 'form',
        items: getGeneralItems(editor, imageListCtrl)
      };
    };
    var MainTab = {
      makeTab: makeTab$1,
      getGeneralItems: getGeneralItems
    };

    var url = function () {
      return Global$1.getOrDie('URL');
    };
    var createObjectURL = function (blob) {
      return url().createObjectURL(blob);
    };
    var revokeObjectURL = function (u) {
      url().revokeObjectURL(u);
    };
    var URL = {
      createObjectURL: createObjectURL,
      revokeObjectURL: revokeObjectURL
    };

    var global$5 = tinymce.util.Tools.resolve('tinymce.ui.Factory');

    function XMLHttpRequest () {
      var f = Global$1.getOrDie('XMLHttpRequest');
      return new f();
    }

    var noop = function () {
    };
    var pathJoin = function (path1, path2) {
      if (path1) {
        return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '');
      }
      return path2;
    };
    function Uploader (settings) {
      var defaultHandler = function (blobInfo, success, failure, progress) {
        var xhr, formData;
        xhr = XMLHttpRequest();
        xhr.open('POST', settings.url);
        xhr.withCredentials = settings.credentials;
        xhr.upload.onprogress = function (e) {
          progress(e.loaded / e.total * 100);
        };
        xhr.onerror = function () {
          failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
        };
        xhr.onload = function () {
          var json;
          if (xhr.status < 200 || xhr.status >= 300) {
            failure('HTTP Error: ' + xhr.status);
            return;
          }
          json = JSON.parse(xhr.responseText);
          if (!json || typeof json.location !== 'string') {
            failure('Invalid JSON: ' + xhr.responseText);
            return;
          }
          success(pathJoin(settings.basePath, json.location));
        };
        formData = new domGlobals.FormData();
        formData.append('file', blobInfo.blob(), blobInfo.filename());
        xhr.send(formData);
      };
      var uploadBlob = function (blobInfo, handler) {
        return new global$1(function (resolve, reject) {
          try {
            handler(blobInfo, resolve, reject, noop);
          } catch (ex) {
            reject(ex.message);
          }
        });
      };
      var isDefaultHandler = function (handler) {
        return handler === defaultHandler;
      };
      var upload = function (blobInfo) {
        return !settings.url && isDefaultHandler(settings.handler) ? global$1.reject('Upload url missing from the settings.') : uploadBlob(blobInfo, settings.handler);
      };
      settings = global$2.extend({
        credentials: false,
        handler: defaultHandler
      }, settings);
      return { upload: upload };
    }

    var onFileInput = function (editor) {
      return function (evt) {
        var Throbber = global$5.get('Throbber');
        var rootControl = evt.control.rootControl;
        var throbber = new Throbber(rootControl.getEl());
        var file = evt.control.value();
        var blobUri = URL.createObjectURL(file);
        var uploader = Uploader({
          url: Settings.getUploadUrl(editor),
          basePath: Settings.getUploadBasePath(editor),
          credentials: Settings.getUploadCredentials(editor),
          handler: Settings.getUploadHandler(editor)
        });
        var finalize = function () {
          throbber.hide();
          URL.revokeObjectURL(blobUri);
        };
        throbber.show();
        return Utils.blobToDataUri(file).then(function (dataUrl) {
          var blobInfo = editor.editorUpload.blobCache.create({
            blob: file,
            blobUri: blobUri,
            name: file.name ? file.name.replace(/\.[^\.]+$/, '') : null,
            base64: dataUrl.split(',')[1]
          });
          return uploader.upload(blobInfo).then(function (url) {
            var src = rootControl.find('#src');
            src.value(url);
            rootControl.find('tabpanel')[0].activateTab(0);
            src.fire('change');
            finalize();
            return url;
          });
        }).catch(function (err) {
          editor.windowManager.alert(err);
          finalize();
        });
      };
    };
    var acceptExts = '.jpg,.jpeg,.png,.gif';
    var makeTab$2 = function (editor) {
      return {
        title: 'Upload',
        type: 'form',
        layout: 'flex',
        direction: 'column',
        align: 'stretch',
        padding: '20 20 20 20',
        items: [
          {
            type: 'container',
            layout: 'flex',
            direction: 'column',
            align: 'center',
            spacing: 10,
            items: [
              {
                text: 'Browse for an image',
                type: 'browsebutton',
                accept: acceptExts,
                onchange: onFileInput(editor)
              },
              {
                text: 'OR',
                type: 'label'
              }
            ]
          },
          {
            text: 'Drop an image here',
            type: 'dropzone',
            accept: acceptExts,
            height: 100,
            onchange: onFileInput(editor)
          }
        ]
      };
    };
    var UploadTab = { makeTab: makeTab$2 };

    function curry(fn) {
      var initialArgs = [];
      for (var _i = 1; _i < arguments.length; _i++) {
        initialArgs[_i - 1] = arguments[_i];
      }
      return function () {
        var restArgs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          restArgs[_i] = arguments[_i];
        }
        var all = initialArgs.concat(restArgs);
        return fn.apply(null, all);
      };
    }

    var submitForm = function (editor, evt) {
      var win = evt.control.getRoot();
      SizeManager.updateSize(win);
      editor.undoManager.transact(function () {
        var data = merge(readImageDataFromSelection(editor), win.toJSON());
        insertOrUpdateImage(editor, data);
      });
      editor.editorUpload.uploadImagesAuto();
    };
    function Dialog (editor) {
      function showDialog(imageList) {
        var data = readImageDataFromSelection(editor);
        var win, imageListCtrl;
        if (imageList) {
          imageListCtrl = {
            type: 'listbox',
            label: 'Image list',
            name: 'image-list',
            values: Utils.buildListItems(imageList, function (item) {
              item.value = editor.convertURL(item.value || item.url, 'src');
            }, [{
                text: 'None',
                value: ''
              }]),
            value: data.src && editor.convertURL(data.src, 'src'),
            onselect: function (e) {
              var altCtrl = win.find('#alt');
              if (!altCtrl.value() || e.lastControl && altCtrl.value() === e.lastControl.text()) {
                altCtrl.value(e.control.text());
              }
              win.find('#src').value(e.control.value()).fire('change');
            },
            onPostRender: function () {
              imageListCtrl = this;
            }
          };
        }
        if (Settings.hasAdvTab(editor) || Settings.hasUploadUrl(editor) || Settings.hasUploadHandler(editor)) {
          var body = [MainTab.makeTab(editor, imageListCtrl)];
          if (Settings.hasAdvTab(editor)) {
            body.push(AdvTab.makeTab(editor));
          }
          if (Settings.hasUploadUrl(editor) || Settings.hasUploadHandler(editor)) {
            body.push(UploadTab.makeTab(editor));
          }
          win = editor.windowManager.open({
            title: 'Insert/edit image',
            data: data,
            bodyType: 'tabpanel',
            body: body,
            onSubmit: curry(submitForm, editor)
          });
        } else {
          win = editor.windowManager.open({
            title: 'Insert/edit image',
            data: data,
            body: MainTab.getGeneralItems(editor, imageListCtrl),
            onSubmit: curry(submitForm, editor)
          });
        }
        SizeManager.syncSize(win);
      }
      function open() {
        Utils.createImageList(editor, showDialog);
      }
      return { open: open };
    }

    var register = function (editor) {
      editor.addCommand('mceImage', Dialog(editor).open);
    };
    var Commands = { register: register };

    var hasImageClass = function (node) {
      var className = node.attr('class');
      return className && /\bimage\b/.test(className);
    };
    var toggleContentEditableState = function (state) {
      return function (nodes) {
        var i = nodes.length, node;
        var toggleContentEditable = function (node) {
          node.attr('contenteditable', state ? 'true' : null);
        };
        while (i--) {
          node = nodes[i];
          if (hasImageClass(node)) {
            node.attr('contenteditable', state ? 'false' : null);
            global$2.each(node.getAll('figcaption'), toggleContentEditable);
          }
        }
      };
    };
    var setup = function (editor) {
      editor.on('preInit', function () {
        editor.parser.addNodeFilter('figure', toggleContentEditableState(true));
        editor.serializer.addNodeFilter('figure', toggleContentEditableState(false));
      });
    };
    var FilterContent = { setup: setup };

    var register$1 = function (editor) {
      editor.addButton('image', {
        icon: 'image',
        tooltip: 'Insert/edit image',
        onclick: Dialog(editor).open,
        stateSelector: 'img:not([data-mce-object],[data-mce-placeholder]),figure.image'
      });
      editor.addMenuItem('image', {
        icon: 'image',
        text: 'Image',
        onclick: Dialog(editor).open,
        context: 'insert',
        prependToContext: true
      });
    };
    var Buttons = { register: register$1 };

    global.add('image', function (editor) {
      FilterContent.setup(editor);
      Buttons.register(editor);
      Commands.register(editor);
    });
    function Plugin () {
    }

    return Plugin;

}(window));
})();


/***/ }),

/***/ 574:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "paste" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/paste')
//   ES2015:
//     import 'tinymce/plugins/paste'
__webpack_require__(575);

/***/ }),

/***/ 575:
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(console, global) {(function () {
var paste = (function (domGlobals) {
    'use strict';

    var Cell = function (initial) {
      var value = initial;
      var get = function () {
        return value;
      };
      var set = function (v) {
        value = v;
      };
      var clone = function () {
        return Cell(get());
      };
      return {
        get: get,
        set: set,
        clone: clone
      };
    };

    var global$1 = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var hasProPlugin = function (editor) {
      if (/(^|[ ,])powerpaste([, ]|$)/.test(editor.settings.plugins) && global$1.get('powerpaste')) {
        if (typeof domGlobals.window.console !== 'undefined' && domGlobals.window.console.log) {
          domGlobals.window.console.log('PowerPaste is incompatible with Paste plugin! Remove \'paste\' from the \'plugins\' option.');
        }
        return true;
      } else {
        return false;
      }
    };
    var DetectProPlugin = { hasProPlugin: hasProPlugin };

    var get = function (clipboard, quirks) {
      return {
        clipboard: clipboard,
        quirks: quirks
      };
    };
    var Api = { get: get };

    var firePastePreProcess = function (editor, html, internal, isWordHtml) {
      return editor.fire('PastePreProcess', {
        content: html,
        internal: internal,
        wordContent: isWordHtml
      });
    };
    var firePastePostProcess = function (editor, node, internal, isWordHtml) {
      return editor.fire('PastePostProcess', {
        node: node,
        internal: internal,
        wordContent: isWordHtml
      });
    };
    var firePastePlainTextToggle = function (editor, state) {
      return editor.fire('PastePlainTextToggle', { state: state });
    };
    var firePaste = function (editor, ieFake) {
      return editor.fire('paste', { ieFake: ieFake });
    };
    var Events = {
      firePastePreProcess: firePastePreProcess,
      firePastePostProcess: firePastePostProcess,
      firePastePlainTextToggle: firePastePlainTextToggle,
      firePaste: firePaste
    };

    var shouldPlainTextInform = function (editor) {
      return editor.getParam('paste_plaintext_inform', true);
    };
    var shouldBlockDrop = function (editor) {
      return editor.getParam('paste_block_drop', false);
    };
    var shouldPasteDataImages = function (editor) {
      return editor.getParam('paste_data_images', false);
    };
    var shouldFilterDrop = function (editor) {
      return editor.getParam('paste_filter_drop', true);
    };
    var getPreProcess = function (editor) {
      return editor.getParam('paste_preprocess');
    };
    var getPostProcess = function (editor) {
      return editor.getParam('paste_postprocess');
    };
    var getWebkitStyles = function (editor) {
      return editor.getParam('paste_webkit_styles');
    };
    var shouldRemoveWebKitStyles = function (editor) {
      return editor.getParam('paste_remove_styles_if_webkit', true);
    };
    var shouldMergeFormats = function (editor) {
      return editor.getParam('paste_merge_formats', true);
    };
    var isSmartPasteEnabled = function (editor) {
      return editor.getParam('smart_paste', true);
    };
    var isPasteAsTextEnabled = function (editor) {
      return editor.getParam('paste_as_text', false);
    };
    var getRetainStyleProps = function (editor) {
      return editor.getParam('paste_retain_style_properties');
    };
    var getWordValidElements = function (editor) {
      var defaultValidElements = '-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' + '-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,' + 'td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody';
      return editor.getParam('paste_word_valid_elements', defaultValidElements);
    };
    var shouldConvertWordFakeLists = function (editor) {
      return editor.getParam('paste_convert_word_fake_lists', true);
    };
    var shouldUseDefaultFilters = function (editor) {
      return editor.getParam('paste_enable_default_filters', true);
    };
    var Settings = {
      shouldPlainTextInform: shouldPlainTextInform,
      shouldBlockDrop: shouldBlockDrop,
      shouldPasteDataImages: shouldPasteDataImages,
      shouldFilterDrop: shouldFilterDrop,
      getPreProcess: getPreProcess,
      getPostProcess: getPostProcess,
      getWebkitStyles: getWebkitStyles,
      shouldRemoveWebKitStyles: shouldRemoveWebKitStyles,
      shouldMergeFormats: shouldMergeFormats,
      isSmartPasteEnabled: isSmartPasteEnabled,
      isPasteAsTextEnabled: isPasteAsTextEnabled,
      getRetainStyleProps: getRetainStyleProps,
      getWordValidElements: getWordValidElements,
      shouldConvertWordFakeLists: shouldConvertWordFakeLists,
      shouldUseDefaultFilters: shouldUseDefaultFilters
    };

    var shouldInformUserAboutPlainText = function (editor, userIsInformedState) {
      return userIsInformedState.get() === false && Settings.shouldPlainTextInform(editor);
    };
    var displayNotification = function (editor, message) {
      editor.notificationManager.open({
        text: editor.translate(message),
        type: 'info'
      });
    };
    var togglePlainTextPaste = function (editor, clipboard, userIsInformedState) {
      if (clipboard.pasteFormat.get() === 'text') {
        clipboard.pasteFormat.set('html');
        Events.firePastePlainTextToggle(editor, false);
      } else {
        clipboard.pasteFormat.set('text');
        Events.firePastePlainTextToggle(editor, true);
        if (shouldInformUserAboutPlainText(editor, userIsInformedState)) {
          displayNotification(editor, 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.');
          userIsInformedState.set(true);
        }
      }
      editor.focus();
    };
    var Actions = { togglePlainTextPaste: togglePlainTextPaste };

    var register = function (editor, clipboard, userIsInformedState) {
      editor.addCommand('mceTogglePlainTextPaste', function () {
        Actions.togglePlainTextPaste(editor, clipboard, userIsInformedState);
      });
      editor.addCommand('mceInsertClipboardContent', function (ui, value) {
        if (value.content) {
          clipboard.pasteHtml(value.content, value.internal);
        }
        if (value.text) {
          clipboard.pasteText(value.text);
        }
      });
    };
    var Commands = { register: register };

    var global$2 = tinymce.util.Tools.resolve('tinymce.Env');

    var global$3 = tinymce.util.Tools.resolve('tinymce.util.Delay');

    var global$4 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    var global$5 = tinymce.util.Tools.resolve('tinymce.util.VK');

    var internalMimeType = 'x-tinymce/html';
    var internalMark = '<!-- ' + internalMimeType + ' -->';
    var mark = function (html) {
      return internalMark + html;
    };
    var unmark = function (html) {
      return html.replace(internalMark, '');
    };
    var isMarked = function (html) {
      return html.indexOf(internalMark) !== -1;
    };
    var InternalHtml = {
      mark: mark,
      unmark: unmark,
      isMarked: isMarked,
      internalHtmlMime: function () {
        return internalMimeType;
      }
    };

    var global$6 = tinymce.util.Tools.resolve('tinymce.html.Entities');

    var isPlainText = function (text) {
      return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text);
    };
    var toBRs = function (text) {
      return text.replace(/\r?\n/g, '<br>');
    };
    var openContainer = function (rootTag, rootAttrs) {
      var key;
      var attrs = [];
      var tag = '<' + rootTag;
      if (typeof rootAttrs === 'object') {
        for (key in rootAttrs) {
          if (rootAttrs.hasOwnProperty(key)) {
            attrs.push(key + '="' + global$6.encodeAllRaw(rootAttrs[key]) + '"');
          }
        }
        if (attrs.length) {
          tag += ' ' + attrs.join(' ');
        }
      }
      return tag + '>';
    };
    var toBlockElements = function (text, rootTag, rootAttrs) {
      var blocks = text.split(/\n\n/);
      var tagOpen = openContainer(rootTag, rootAttrs);
      var tagClose = '</' + rootTag + '>';
      var paragraphs = global$4.map(blocks, function (p) {
        return p.split(/\n/).join('<br />');
      });
      var stitch = function (p) {
        return tagOpen + p + tagClose;
      };
      return paragraphs.length === 1 ? paragraphs[0] : global$4.map(paragraphs, stitch).join('');
    };
    var convert = function (text, rootTag, rootAttrs) {
      return rootTag ? toBlockElements(text, rootTag, rootAttrs) : toBRs(text);
    };
    var Newlines = {
      isPlainText: isPlainText,
      convert: convert,
      toBRs: toBRs,
      toBlockElements: toBlockElements
    };

    var global$7 = tinymce.util.Tools.resolve('tinymce.html.DomParser');

    var global$8 = tinymce.util.Tools.resolve('tinymce.html.Serializer');

    var global$9 = tinymce.util.Tools.resolve('tinymce.html.Node');

    var global$a = tinymce.util.Tools.resolve('tinymce.html.Schema');

    function filter(content, items) {
      global$4.each(items, function (v) {
        if (v.constructor === RegExp) {
          content = content.replace(v, '');
        } else {
          content = content.replace(v[0], v[1]);
        }
      });
      return content;
    }
    function innerText(html) {
      var schema = global$a();
      var domParser = global$7({}, schema);
      var text = '';
      var shortEndedElements = schema.getShortEndedElements();
      var ignoreElements = global$4.makeMap('script noscript style textarea video audio iframe object', ' ');
      var blockElements = schema.getBlockElements();
      function walk(node) {
        var name = node.name, currentNode = node;
        if (name === 'br') {
          text += '\n';
          return;
        }
        if (name === 'wbr') {
          return;
        }
        if (shortEndedElements[name]) {
          text += ' ';
        }
        if (ignoreElements[name]) {
          text += ' ';
          return;
        }
        if (node.type === 3) {
          text += node.value;
        }
        if (!node.shortEnded) {
          if (node = node.firstChild) {
            do {
              walk(node);
            } while (node = node.next);
          }
        }
        if (blockElements[name] && currentNode.next) {
          text += '\n';
          if (name === 'p') {
            text += '\n';
          }
        }
      }
      html = filter(html, [/<!\[[^\]]+\]>/g]);
      walk(domParser.parse(html));
      return text;
    }
    function trimHtml(html) {
      function trimSpaces(all, s1, s2) {
        if (!s1 && !s2) {
          return ' ';
        }
        return '\xA0';
      }
      html = filter(html, [
        /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig,
        /<!--StartFragment-->|<!--EndFragment-->/g,
        [
          /( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g,
          trimSpaces
        ],
        /<br class="Apple-interchange-newline">/g,
        /<br>$/i
      ]);
      return html;
    }
    function createIdGenerator(prefix) {
      var count = 0;
      return function () {
        return prefix + count++;
      };
    }
    var isMsEdge = function () {
      return domGlobals.navigator.userAgent.indexOf(' Edge/') !== -1;
    };
    var Utils = {
      filter: filter,
      innerText: innerText,
      trimHtml: trimHtml,
      createIdGenerator: createIdGenerator,
      isMsEdge: isMsEdge
    };

    function isWordContent(content) {
      return /<font face="Times New Roman"|class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i.test(content) || /class="OutlineElement/.test(content) || /id="?docs\-internal\-guid\-/.test(content);
    }
    function isNumericList(text) {
      var found, patterns;
      patterns = [
        /^[IVXLMCD]{1,2}\.[ \u00a0]/,
        /^[ivxlmcd]{1,2}\.[ \u00a0]/,
        /^[a-z]{1,2}[\.\)][ \u00a0]/,
        /^[A-Z]{1,2}[\.\)][ \u00a0]/,
        /^[0-9]+\.[ \u00a0]/,
        /^[\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\.[ \u00a0]/,
        /^[\u58f1\u5f10\u53c2\u56db\u4f0d\u516d\u4e03\u516b\u4e5d\u62fe]+\.[ \u00a0]/
      ];
      text = text.replace(/^[\u00a0 ]+/, '');
      global$4.each(patterns, function (pattern) {
        if (pattern.test(text)) {
          found = true;
          return false;
        }
      });
      return found;
    }
    function isBulletList(text) {
      return /^[\s\u00a0]*[\u2022\u00b7\u00a7\u25CF]\s*/.test(text);
    }
    function convertFakeListsToProperLists(node) {
      var currentListNode, prevListNode, lastLevel = 1;
      function getText(node) {
        var txt = '';
        if (node.type === 3) {
          return node.value;
        }
        if (node = node.firstChild) {
          do {
            txt += getText(node);
          } while (node = node.next);
        }
        return txt;
      }
      function trimListStart(node, regExp) {
        if (node.type === 3) {
          if (regExp.test(node.value)) {
            node.value = node.value.replace(regExp, '');
            return false;
          }
        }
        if (node = node.firstChild) {
          do {
            if (!trimListStart(node, regExp)) {
              return false;
            }
          } while (node = node.next);
        }
        return true;
      }
      function removeIgnoredNodes(node) {
        if (node._listIgnore) {
          node.remove();
          return;
        }
        if (node = node.firstChild) {
          do {
            removeIgnoredNodes(node);
          } while (node = node.next);
        }
      }
      function convertParagraphToLi(paragraphNode, listName, start) {
        var level = paragraphNode._listLevel || lastLevel;
        if (level !== lastLevel) {
          if (level < lastLevel) {
            if (currentListNode) {
              currentListNode = currentListNode.parent.parent;
            }
          } else {
            prevListNode = currentListNode;
            currentListNode = null;
          }
        }
        if (!currentListNode || currentListNode.name !== listName) {
          prevListNode = prevListNode || currentListNode;
          currentListNode = new global$9(listName, 1);
          if (start > 1) {
            currentListNode.attr('start', '' + start);
          }
          paragraphNode.wrap(currentListNode);
        } else {
          currentListNode.append(paragraphNode);
        }
        paragraphNode.name = 'li';
        if (level > lastLevel && prevListNode) {
          prevListNode.lastChild.append(currentListNode);
        }
        lastLevel = level;
        removeIgnoredNodes(paragraphNode);
        trimListStart(paragraphNode, /^\u00a0+/);
        trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/);
        trimListStart(paragraphNode, /^\u00a0+/);
      }
      var elements = [];
      var child = node.firstChild;
      while (typeof child !== 'undefined' && child !== null) {
        elements.push(child);
        child = child.walk();
        if (child !== null) {
          while (typeof child !== 'undefined' && child.parent !== node) {
            child = child.walk();
          }
        }
      }
      for (var i = 0; i < elements.length; i++) {
        node = elements[i];
        if (node.name === 'p' && node.firstChild) {
          var nodeText = getText(node);
          if (isBulletList(nodeText)) {
            convertParagraphToLi(node, 'ul');
            continue;
          }
          if (isNumericList(nodeText)) {
            var matches = /([0-9]+)\./.exec(nodeText);
            var start = 1;
            if (matches) {
              start = parseInt(matches[1], 10);
            }
            convertParagraphToLi(node, 'ol', start);
            continue;
          }
          if (node._listLevel) {
            convertParagraphToLi(node, 'ul', 1);
            continue;
          }
          currentListNode = null;
        } else {
          prevListNode = currentListNode;
          currentListNode = null;
        }
      }
    }
    function filterStyles(editor, validStyles, node, styleValue) {
      var outputStyles = {}, matches;
      var styles = editor.dom.parseStyle(styleValue);
      global$4.each(styles, function (value, name) {
        switch (name) {
        case 'mso-list':
          matches = /\w+ \w+([0-9]+)/i.exec(styleValue);
          if (matches) {
            node._listLevel = parseInt(matches[1], 10);
          }
          if (/Ignore/i.test(value) && node.firstChild) {
            node._listIgnore = true;
            node.firstChild._listIgnore = true;
          }
          break;
        case 'horiz-align':
          name = 'text-align';
          break;
        case 'vert-align':
          name = 'vertical-align';
          break;
        case 'font-color':
        case 'mso-foreground':
          name = 'color';
          break;
        case 'mso-background':
        case 'mso-highlight':
          name = 'background';
          break;
        case 'font-weight':
        case 'font-style':
          if (value !== 'normal') {
            outputStyles[name] = value;
          }
          return;
        case 'mso-element':
          if (/^(comment|comment-list)$/i.test(value)) {
            node.remove();
            return;
          }
          break;
        }
        if (name.indexOf('mso-comment') === 0) {
          node.remove();
          return;
        }
        if (name.indexOf('mso-') === 0) {
          return;
        }
        if (Settings.getRetainStyleProps(editor) === 'all' || validStyles && validStyles[name]) {
          outputStyles[name] = value;
        }
      });
      if (/(bold)/i.test(outputStyles['font-weight'])) {
        delete outputStyles['font-weight'];
        node.wrap(new global$9('b', 1));
      }
      if (/(italic)/i.test(outputStyles['font-style'])) {
        delete outputStyles['font-style'];
        node.wrap(new global$9('i', 1));
      }
      outputStyles = editor.dom.serializeStyle(outputStyles, node.name);
      if (outputStyles) {
        return outputStyles;
      }
      return null;
    }
    var filterWordContent = function (editor, content) {
      var retainStyleProperties, validStyles;
      retainStyleProperties = Settings.getRetainStyleProps(editor);
      if (retainStyleProperties) {
        validStyles = global$4.makeMap(retainStyleProperties.split(/[, ]/));
      }
      content = Utils.filter(content, [
        /<br class="?Apple-interchange-newline"?>/gi,
        /<b[^>]+id="?docs-internal-[^>]*>/gi,
        /<!--[\s\S]+?-->/gi,
        /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,
        [
          /<(\/?)s>/gi,
          '<$1strike>'
        ],
        [
          /&nbsp;/gi,
          '\xA0'
        ],
        [
          /<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,
          function (str, spaces) {
            return spaces.length > 0 ? spaces.replace(/./, ' ').slice(Math.floor(spaces.length / 2)).split('').join('\xA0') : '';
          }
        ]
      ]);
      var validElements = Settings.getWordValidElements(editor);
      var schema = global$a({
        valid_elements: validElements,
        valid_children: '-li[p]'
      });
      global$4.each(schema.elements, function (rule) {
        if (!rule.attributes.class) {
          rule.attributes.class = {};
          rule.attributesOrder.push('class');
        }
        if (!rule.attributes.style) {
          rule.attributes.style = {};
          rule.attributesOrder.push('style');
        }
      });
      var domParser = global$7({}, schema);
      domParser.addAttributeFilter('style', function (nodes) {
        var i = nodes.length, node;
        while (i--) {
          node = nodes[i];
          node.attr('style', filterStyles(editor, validStyles, node, node.attr('style')));
          if (node.name === 'span' && node.parent && !node.attributes.length) {
            node.unwrap();
          }
        }
      });
      domParser.addAttributeFilter('class', function (nodes) {
        var i = nodes.length, node, className;
        while (i--) {
          node = nodes[i];
          className = node.attr('class');
          if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) {
            node.remove();
          }
          node.attr('class', null);
        }
      });
      domParser.addNodeFilter('del', function (nodes) {
        var i = nodes.length;
        while (i--) {
          nodes[i].remove();
        }
      });
      domParser.addNodeFilter('a', function (nodes) {
        var i = nodes.length, node, href, name;
        while (i--) {
          node = nodes[i];
          href = node.attr('href');
          name = node.attr('name');
          if (href && href.indexOf('#_msocom_') !== -1) {
            node.remove();
            continue;
          }
          if (href && href.indexOf('file://') === 0) {
            href = href.split('#')[1];
            if (href) {
              href = '#' + href;
            }
          }
          if (!href && !name) {
            node.unwrap();
          } else {
            if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) {
              node.unwrap();
              continue;
            }
            node.attr({
              href: href,
              name: name
            });
          }
        }
      });
      var rootNode = domParser.parse(content);
      if (Settings.shouldConvertWordFakeLists(editor)) {
        convertFakeListsToProperLists(rootNode);
      }
      content = global$8({ validate: editor.settings.validate }, schema).serialize(rootNode);
      return content;
    };
    var preProcess = function (editor, content) {
      return Settings.shouldUseDefaultFilters(editor) ? filterWordContent(editor, content) : content;
    };
    var WordFilter = {
      preProcess: preProcess,
      isWordContent: isWordContent
    };

    var preProcess$1 = function (editor, html) {
      var parser = global$7({}, editor.schema);
      parser.addNodeFilter('meta', function (nodes) {
        global$4.each(nodes, function (node) {
          return node.remove();
        });
      });
      var fragment = parser.parse(html, {
        forced_root_block: false,
        isRootContent: true
      });
      return global$8({ validate: editor.settings.validate }, editor.schema).serialize(fragment);
    };
    var processResult = function (content, cancelled) {
      return {
        content: content,
        cancelled: cancelled
      };
    };
    var postProcessFilter = function (editor, html, internal, isWordHtml) {
      var tempBody = editor.dom.create('div', { style: 'display:none' }, html);
      var postProcessArgs = Events.firePastePostProcess(editor, tempBody, internal, isWordHtml);
      return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented());
    };
    var filterContent = function (editor, content, internal, isWordHtml) {
      var preProcessArgs = Events.firePastePreProcess(editor, content, internal, isWordHtml);
      var filteredContent = preProcess$1(editor, preProcessArgs.content);
      if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) {
        return postProcessFilter(editor, filteredContent, internal, isWordHtml);
      } else {
        return processResult(filteredContent, preProcessArgs.isDefaultPrevented());
      }
    };
    var process = function (editor, html, internal) {
      var isWordHtml = WordFilter.isWordContent(html);
      var content = isWordHtml ? WordFilter.preProcess(editor, html) : html;
      return filterContent(editor, content, internal, isWordHtml);
    };
    var ProcessFilters = { process: process };

    var pasteHtml = function (editor, html) {
      editor.insertContent(html, {
        merge: Settings.shouldMergeFormats(editor),
        paste: true
      });
      return true;
    };
    var isAbsoluteUrl = function (url) {
      return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url);
    };
    var isImageUrl = function (url) {
      return isAbsoluteUrl(url) && /.(gif|jpe?g|png)$/.test(url);
    };
    var createImage = function (editor, url, pasteHtmlFn) {
      editor.undoManager.extra(function () {
        pasteHtmlFn(editor, url);
      }, function () {
        editor.insertContent('<img src="' + url + '">');
      });
      return true;
    };
    var createLink = function (editor, url, pasteHtmlFn) {
      editor.undoManager.extra(function () {
        pasteHtmlFn(editor, url);
      }, function () {
        editor.execCommand('mceInsertLink', false, url);
      });
      return true;
    };
    var linkSelection = function (editor, html, pasteHtmlFn) {
      return editor.selection.isCollapsed() === false && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false;
    };
    var insertImage = function (editor, html, pasteHtmlFn) {
      return isImageUrl(html) ? createImage(editor, html, pasteHtmlFn) : false;
    };
    var smartInsertContent = function (editor, html) {
      global$4.each([
        linkSelection,
        insertImage,
        pasteHtml
      ], function (action) {
        return action(editor, html, pasteHtml) !== true;
      });
    };
    var insertContent = function (editor, html) {
      if (Settings.isSmartPasteEnabled(editor) === false) {
        pasteHtml(editor, html);
      } else {
        smartInsertContent(editor, html);
      }
    };
    var SmartPaste = {
      isImageUrl: isImageUrl,
      isAbsoluteUrl: isAbsoluteUrl,
      insertContent: insertContent
    };

    var noop = function () {
    };
    var constant = function (value) {
      return function () {
        return value;
      };
    };
    function curry(fn) {
      var initialArgs = [];
      for (var _i = 1; _i < arguments.length; _i++) {
        initialArgs[_i - 1] = arguments[_i];
      }
      return function () {
        var restArgs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          restArgs[_i] = arguments[_i];
        }
        var all = initialArgs.concat(restArgs);
        return fn.apply(null, all);
      };
    }
    var never = constant(false);
    var always = constant(true);

    var none = function () {
      return NONE;
    };
    var NONE = function () {
      var eq = function (o) {
        return o.isNone();
      };
      var call = function (thunk) {
        return thunk();
      };
      var id = function (n) {
        return n;
      };
      var me = {
        fold: function (n, s) {
          return n();
        },
        is: never,
        isSome: never,
        isNone: always,
        getOr: id,
        getOrThunk: call,
        getOrDie: function (msg) {
          throw new Error(msg || 'error: getOrDie called on none.');
        },
        getOrNull: constant(null),
        getOrUndefined: constant(undefined),
        or: id,
        orThunk: call,
        map: none,
        each: noop,
        bind: none,
        exists: never,
        forall: always,
        filter: none,
        equals: eq,
        equals_: eq,
        toArray: function () {
          return [];
        },
        toString: constant('none()')
      };
      if (Object.freeze) {
        Object.freeze(me);
      }
      return me;
    }();
    var some = function (a) {
      var constant_a = constant(a);
      var self = function () {
        return me;
      };
      var bind = function (f) {
        return f(a);
      };
      var me = {
        fold: function (n, s) {
          return s(a);
        },
        is: function (v) {
          return a === v;
        },
        isSome: always,
        isNone: never,
        getOr: constant_a,
        getOrThunk: constant_a,
        getOrDie: constant_a,
        getOrNull: constant_a,
        getOrUndefined: constant_a,
        or: self,
        orThunk: self,
        map: function (f) {
          return some(f(a));
        },
        each: function (f) {
          f(a);
        },
        bind: bind,
        exists: bind,
        forall: bind,
        filter: function (f) {
          return f(a) ? me : NONE;
        },
        toArray: function () {
          return [a];
        },
        toString: function () {
          return 'some(' + a + ')';
        },
        equals: function (o) {
          return o.is(a);
        },
        equals_: function (o, elementEq) {
          return o.fold(never, function (b) {
            return elementEq(a, b);
          });
        }
      };
      return me;
    };
    var from = function (value) {
      return value === null || value === undefined ? NONE : some(value);
    };
    var Option = {
      some: some,
      none: none,
      from: from
    };

    var typeOf = function (x) {
      if (x === null) {
        return 'null';
      }
      var t = typeof x;
      if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
        return 'array';
      }
      if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
        return 'string';
      }
      return t;
    };
    var isType = function (type) {
      return function (value) {
        return typeOf(value) === type;
      };
    };
    var isFunction = isType('function');

    var nativeSlice = Array.prototype.slice;
    var map = function (xs, f) {
      var len = xs.length;
      var r = new Array(len);
      for (var i = 0; i < len; i++) {
        var x = xs[i];
        r[i] = f(x, i);
      }
      return r;
    };
    var each = function (xs, f) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        f(x, i);
      }
    };
    var filter$1 = function (xs, pred) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          r.push(x);
        }
      }
      return r;
    };
    var from$1 = isFunction(Array.from) ? Array.from : function (x) {
      return nativeSlice.call(x);
    };

    var exports$1 = {}, module = { exports: exports$1 };
    (function (define, exports, module, 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.EphoxContactWrapper = f();
        }
      }(function () {
        return function () {
          function r(e, n, t) {
            function o(i, f) {
              if (!n[i]) {
                if (!e[i]) {
                  var c = 'function' == typeof require && require;
                  if (!f && c)
                    return c(i, !0);
                  if (u)
                    return u(i, !0);
                  var a = new Error('Cannot find module \'' + i + '\'');
                  throw a.code = 'MODULE_NOT_FOUND', a;
                }
                var p = n[i] = { exports: {} };
                e[i][0].call(p.exports, function (r) {
                  var n = e[i][1][r];
                  return o(n || r);
                }, p, p.exports, r, e, n, t);
              }
              return n[i].exports;
            }
            for (var u = 'function' == typeof require && require, i = 0; i < t.length; i++)
              o(t[i]);
            return o;
          }
          return r;
        }()({
          1: [
            function (require, module, exports) {
              var process = module.exports = {};
              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) {
                  return setTimeout(fun, 0);
                }
                if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
                  cachedSetTimeout = setTimeout;
                  return setTimeout(fun, 0);
                }
                try {
                  return cachedSetTimeout(fun, 0);
                } catch (e) {
                  try {
                    return cachedSetTimeout.call(null, fun, 0);
                  } catch (e) {
                    return cachedSetTimeout.call(this, fun, 0);
                  }
                }
              }
              function runClearTimeout(marker) {
                if (cachedClearTimeout === clearTimeout) {
                  return clearTimeout(marker);
                }
                if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
                  cachedClearTimeout = clearTimeout;
                  return clearTimeout(marker);
                }
                try {
                  return cachedClearTimeout(marker);
                } catch (e) {
                  try {
                    return cachedClearTimeout.call(null, marker);
                  } catch (e) {
                    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);
                }
              };
              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 = '';
              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.prependListener = noop;
              process.prependOnceListener = noop;
              process.listeners = function (name) {
                return [];
              };
              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;
              };
            },
            {}
          ],
          2: [
            function (require, module, exports) {
              (function (setImmediate) {
                (function (root) {
                  var setTimeoutFunc = setTimeout;
                  function noop() {
                  }
                  function bind(fn, thisArg) {
                    return function () {
                      fn.apply(thisArg, arguments);
                    };
                  }
                  function Promise(fn) {
                    if (typeof this !== 'object')
                      throw new TypeError('Promises must be constructed via new');
                    if (typeof fn !== 'function')
                      throw new TypeError('not a function');
                    this._state = 0;
                    this._handled = false;
                    this._value = undefined;
                    this._deferreds = [];
                    doResolve(fn, this);
                  }
                  function handle(self, deferred) {
                    while (self._state === 3) {
                      self = self._value;
                    }
                    if (self._state === 0) {
                      self._deferreds.push(deferred);
                      return;
                    }
                    self._handled = true;
                    Promise._immediateFn(function () {
                      var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
                      if (cb === null) {
                        (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
                        return;
                      }
                      var ret;
                      try {
                        ret = cb(self._value);
                      } catch (e) {
                        reject(deferred.promise, e);
                        return;
                      }
                      resolve(deferred.promise, ret);
                    });
                  }
                  function resolve(self, newValue) {
                    try {
                      if (newValue === self)
                        throw new TypeError('A promise cannot be resolved with itself.');
                      if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
                        var then = newValue.then;
                        if (newValue instanceof Promise) {
                          self._state = 3;
                          self._value = newValue;
                          finale(self);
                          return;
                        } else if (typeof then === 'function') {
                          doResolve(bind(then, newValue), self);
                          return;
                        }
                      }
                      self._state = 1;
                      self._value = newValue;
                      finale(self);
                    } catch (e) {
                      reject(self, e);
                    }
                  }
                  function reject(self, newValue) {
                    self._state = 2;
                    self._value = newValue;
                    finale(self);
                  }
                  function finale(self) {
                    if (self._state === 2 && self._deferreds.length === 0) {
                      Promise._immediateFn(function () {
                        if (!self._handled) {
                          Promise._unhandledRejectionFn(self._value);
                        }
                      });
                    }
                    for (var i = 0, len = self._deferreds.length; i < len; i++) {
                      handle(self, self._deferreds[i]);
                    }
                    self._deferreds = null;
                  }
                  function Handler(onFulfilled, onRejected, promise) {
                    this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
                    this.onRejected = typeof onRejected === 'function' ? onRejected : null;
                    this.promise = promise;
                  }
                  function doResolve(fn, self) {
                    var done = false;
                    try {
                      fn(function (value) {
                        if (done)
                          return;
                        done = true;
                        resolve(self, value);
                      }, function (reason) {
                        if (done)
                          return;
                        done = true;
                        reject(self, reason);
                      });
                    } catch (ex) {
                      if (done)
                        return;
                      done = true;
                      reject(self, ex);
                    }
                  }
                  Promise.prototype['catch'] = function (onRejected) {
                    return this.then(null, onRejected);
                  };
                  Promise.prototype.then = function (onFulfilled, onRejected) {
                    var prom = new this.constructor(noop);
                    handle(this, new Handler(onFulfilled, onRejected, prom));
                    return prom;
                  };
                  Promise.all = function (arr) {
                    var args = Array.prototype.slice.call(arr);
                    return new Promise(function (resolve, reject) {
                      if (args.length === 0)
                        return resolve([]);
                      var remaining = args.length;
                      function res(i, val) {
                        try {
                          if (val && (typeof val === 'object' || typeof val === 'function')) {
                            var then = val.then;
                            if (typeof then === 'function') {
                              then.call(val, function (val) {
                                res(i, val);
                              }, reject);
                              return;
                            }
                          }
                          args[i] = val;
                          if (--remaining === 0) {
                            resolve(args);
                          }
                        } catch (ex) {
                          reject(ex);
                        }
                      }
                      for (var i = 0; i < args.length; i++) {
                        res(i, args[i]);
                      }
                    });
                  };
                  Promise.resolve = function (value) {
                    if (value && typeof value === 'object' && value.constructor === Promise) {
                      return value;
                    }
                    return new Promise(function (resolve) {
                      resolve(value);
                    });
                  };
                  Promise.reject = function (value) {
                    return new Promise(function (resolve, reject) {
                      reject(value);
                    });
                  };
                  Promise.race = function (values) {
                    return new Promise(function (resolve, reject) {
                      for (var i = 0, len = values.length; i < len; i++) {
                        values[i].then(resolve, reject);
                      }
                    });
                  };
                  Promise._immediateFn = typeof setImmediate === 'function' ? function (fn) {
                    setImmediate(fn);
                  } : function (fn) {
                    setTimeoutFunc(fn, 0);
                  };
                  Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
                    if (typeof console !== 'undefined' && console) {
                      console.warn('Possible Unhandled Promise Rejection:', err);
                    }
                  };
                  Promise._setImmediateFn = function _setImmediateFn(fn) {
                    Promise._immediateFn = fn;
                  };
                  Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
                    Promise._unhandledRejectionFn = fn;
                  };
                  if (typeof module !== 'undefined' && module.exports) {
                    module.exports = Promise;
                  } else if (!root.Promise) {
                    root.Promise = Promise;
                  }
                }(this));
              }.call(this, require('timers').setImmediate));
            },
            { 'timers': 3 }
          ],
          3: [
            function (require, module, exports) {
              (function (setImmediate, clearImmediate) {
                var nextTick = require('process/browser.js').nextTick;
                var apply = Function.prototype.apply;
                var slice = Array.prototype.slice;
                var immediateIds = {};
                var nextImmediateId = 0;
                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) {
                  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);
                };
                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);
                  }
                };
                exports.setImmediate = typeof setImmediate === 'function' ? setImmediate : function (fn) {
                  var id = nextImmediateId++;
                  var args = arguments.length < 2 ? false : slice.call(arguments, 1);
                  immediateIds[id] = true;
                  nextTick(function onNextTick() {
                    if (immediateIds[id]) {
                      if (args) {
                        fn.apply(null, args);
                      } else {
                        fn.call(null);
                      }
                      exports.clearImmediate(id);
                    }
                  });
                  return id;
                };
                exports.clearImmediate = typeof clearImmediate === 'function' ? clearImmediate : function (id) {
                  delete immediateIds[id];
                };
              }.call(this, require('timers').setImmediate, require('timers').clearImmediate));
            },
            {
              'process/browser.js': 1,
              'timers': 3
            }
          ],
          4: [
            function (require, module, exports) {
              var promisePolyfill = require('promise-polyfill');
              var Global = function () {
                if (typeof window !== 'undefined') {
                  return window;
                } else {
                  return Function('return this;')();
                }
              }();
              module.exports = { boltExport: Global.Promise || promisePolyfill };
            },
            { 'promise-polyfill': 2 }
          ]
        }, {}, [4])(4);
      }));
    }(undefined, exports$1, module, undefined));
    var Promise = module.exports.boltExport;

    var nu = function (baseFn) {
      var data = Option.none();
      var callbacks = [];
      var map = function (f) {
        return nu(function (nCallback) {
          get(function (data) {
            nCallback(f(data));
          });
        });
      };
      var get = function (nCallback) {
        if (isReady()) {
          call(nCallback);
        } else {
          callbacks.push(nCallback);
        }
      };
      var set = function (x) {
        data = Option.some(x);
        run(callbacks);
        callbacks = [];
      };
      var isReady = function () {
        return data.isSome();
      };
      var run = function (cbs) {
        each(cbs, call);
      };
      var call = function (cb) {
        data.each(function (x) {
          domGlobals.setTimeout(function () {
            cb(x);
          }, 0);
        });
      };
      baseFn(set);
      return {
        get: get,
        map: map,
        isReady: isReady
      };
    };
    var pure = function (a) {
      return nu(function (callback) {
        callback(a);
      });
    };
    var LazyValue = {
      nu: nu,
      pure: pure
    };

    var errorReporter = function (err) {
      domGlobals.setTimeout(function () {
        throw err;
      }, 0);
    };
    var make = function (run) {
      var get = function (callback) {
        run().then(callback, errorReporter);
      };
      var map = function (fab) {
        return make(function () {
          return run().then(fab);
        });
      };
      var bind = function (aFutureB) {
        return make(function () {
          return run().then(function (v) {
            return aFutureB(v).toPromise();
          });
        });
      };
      var anonBind = function (futureB) {
        return make(function () {
          return run().then(function () {
            return futureB.toPromise();
          });
        });
      };
      var toLazy = function () {
        return LazyValue.nu(get);
      };
      var toCached = function () {
        var cache = null;
        return make(function () {
          if (cache === null) {
            cache = run();
          }
          return cache;
        });
      };
      var toPromise = run;
      return {
        map: map,
        bind: bind,
        anonBind: anonBind,
        toLazy: toLazy,
        toCached: toCached,
        toPromise: toPromise,
        get: get
      };
    };
    var nu$1 = function (baseFn) {
      return make(function () {
        return new Promise(baseFn);
      });
    };
    var pure$1 = function (a) {
      return make(function () {
        return Promise.resolve(a);
      });
    };
    var Future = {
      nu: nu$1,
      pure: pure$1
    };

    var par = function (asyncValues, nu) {
      return nu(function (callback) {
        var r = [];
        var count = 0;
        var cb = function (i) {
          return function (value) {
            r[i] = value;
            count++;
            if (count >= asyncValues.length) {
              callback(r);
            }
          };
        };
        if (asyncValues.length === 0) {
          callback([]);
        } else {
          each(asyncValues, function (asyncValue, i) {
            asyncValue.get(cb(i));
          });
        }
      });
    };

    var par$1 = function (futures) {
      return par(futures, Future.nu);
    };
    var traverse = function (array, fn) {
      return par$1(map(array, fn));
    };
    var mapM = traverse;

    var value = function () {
      var subject = Cell(Option.none());
      var clear = function () {
        subject.set(Option.none());
      };
      var set = function (s) {
        subject.set(Option.some(s));
      };
      var on = function (f) {
        subject.get().each(f);
      };
      var isSet = function () {
        return subject.get().isSome();
      };
      return {
        clear: clear,
        set: set,
        isSet: isSet,
        on: on
      };
    };

    var pasteHtml$1 = function (editor, html, internalFlag) {
      var internal = internalFlag ? internalFlag : InternalHtml.isMarked(html);
      var args = ProcessFilters.process(editor, InternalHtml.unmark(html), internal);
      if (args.cancelled === false) {
        SmartPaste.insertContent(editor, args.content);
      }
    };
    var pasteText = function (editor, text) {
      text = editor.dom.encode(text).replace(/\r\n/g, '\n');
      text = Newlines.convert(text, editor.settings.forced_root_block, editor.settings.forced_root_block_attrs);
      pasteHtml$1(editor, text, false);
    };
    var getDataTransferItems = function (dataTransfer) {
      var items = {};
      var mceInternalUrlPrefix = 'data:text/mce-internal,';
      if (dataTransfer) {
        if (dataTransfer.getData) {
          var legacyText = dataTransfer.getData('Text');
          if (legacyText && legacyText.length > 0) {
            if (legacyText.indexOf(mceInternalUrlPrefix) === -1) {
              items['text/plain'] = legacyText;
            }
          }
        }
        if (dataTransfer.types) {
          for (var i = 0; i < dataTransfer.types.length; i++) {
            var contentType = dataTransfer.types[i];
            try {
              items[contentType] = dataTransfer.getData(contentType);
            } catch (ex) {
              items[contentType] = '';
            }
          }
        }
      }
      return items;
    };
    var getClipboardContent = function (editor, clipboardEvent) {
      var content = getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer);
      return Utils.isMsEdge() ? global$4.extend(content, { 'text/html': '' }) : content;
    };
    var hasContentType = function (clipboardContent, mimeType) {
      return mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
    };
    var hasHtmlOrText = function (content) {
      return hasContentType(content, 'text/html') || hasContentType(content, 'text/plain');
    };
    var getBase64FromUri = function (uri) {
      var idx;
      idx = uri.indexOf(',');
      if (idx !== -1) {
        return uri.substr(idx + 1);
      }
      return null;
    };
    var isValidDataUriImage = function (settings, imgElm) {
      return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true;
    };
    var extractFilename = function (editor, str) {
      var m = str.match(/([\s\S]+?)\.(?:jpeg|jpg|png|gif)$/i);
      return m ? editor.dom.encode(m[1]) : null;
    };
    var uniqueId = Utils.createIdGenerator('mceclip');
    var pasteImage = function (editor, imageItem) {
      var base64 = getBase64FromUri(imageItem.uri);
      var id = uniqueId();
      var name = editor.settings.images_reuse_filename && imageItem.blob.name ? extractFilename(editor, imageItem.blob.name) : id;
      var img = new domGlobals.Image();
      img.src = imageItem.uri;
      if (isValidDataUriImage(editor.settings, img)) {
        var blobCache = editor.editorUpload.blobCache;
        var blobInfo = void 0, existingBlobInfo = void 0;
        existingBlobInfo = blobCache.findFirst(function (cachedBlobInfo) {
          return cachedBlobInfo.base64() === base64;
        });
        if (!existingBlobInfo) {
          blobInfo = blobCache.create(id, imageItem.blob, base64, name);
          blobCache.add(blobInfo);
        } else {
          blobInfo = existingBlobInfo;
        }
        pasteHtml$1(editor, '<img src="' + blobInfo.blobUri() + '">', false);
      } else {
        pasteHtml$1(editor, '<img src="' + imageItem.uri + '">', false);
      }
    };
    var isClipboardEvent = function (event) {
      return event.type === 'paste';
    };
    var readBlobsAsDataUris = function (items) {
      return mapM(items, function (item) {
        return Future.nu(function (resolve) {
          var blob = item.getAsFile ? item.getAsFile() : item;
          var reader = new window.FileReader();
          reader.onload = function () {
            resolve({
              blob: blob,
              uri: reader.result
            });
          };
          reader.readAsDataURL(blob);
        });
      });
    };
    var getImagesFromDataTransfer = function (dataTransfer) {
      var items = dataTransfer.items ? map(from$1(dataTransfer.items), function (item) {
        return item.getAsFile();
      }) : [];
      var files = dataTransfer.files ? from$1(dataTransfer.files) : [];
      var images = filter$1(items.length > 0 ? items : files, function (file) {
        return /^image\/(jpeg|png|gif|bmp)$/.test(file.type);
      });
      return images;
    };
    var pasteImageData = function (editor, e, rng) {
      var dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer;
      if (editor.settings.paste_data_images && dataTransfer) {
        var images = getImagesFromDataTransfer(dataTransfer);
        if (images.length > 0) {
          e.preventDefault();
          readBlobsAsDataUris(images).get(function (blobResults) {
            if (rng) {
              editor.selection.setRng(rng);
            }
            each(blobResults, function (result) {
              pasteImage(editor, result);
            });
          });
          return true;
        }
      }
      return false;
    };
    var isBrokenAndroidClipboardEvent = function (e) {
      var clipboardData = e.clipboardData;
      return domGlobals.navigator.userAgent.indexOf('Android') !== -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0;
    };
    var isKeyboardPasteEvent = function (e) {
      return global$5.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45;
    };
    var registerEventHandlers = function (editor, pasteBin, pasteFormat) {
      var keyboardPasteEvent = value();
      var keyboardPastePlainTextState;
      editor.on('keydown', function (e) {
        function removePasteBinOnKeyUp(e) {
          if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
            pasteBin.remove();
          }
        }
        if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
          keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86;
          if (keyboardPastePlainTextState && global$2.webkit && domGlobals.navigator.userAgent.indexOf('Version/') !== -1) {
            return;
          }
          e.stopImmediatePropagation();
          keyboardPasteEvent.set(e);
          window.setTimeout(function () {
            keyboardPasteEvent.clear();
          }, 100);
          if (global$2.ie && keyboardPastePlainTextState) {
            e.preventDefault();
            Events.firePaste(editor, true);
            return;
          }
          pasteBin.remove();
          pasteBin.create();
          editor.once('keyup', removePasteBinOnKeyUp);
          editor.once('paste', function () {
            editor.off('keyup', removePasteBinOnKeyUp);
          });
        }
      });
      function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal) {
        var content, isPlainTextHtml;
        if (hasContentType(clipboardContent, 'text/html')) {
          content = clipboardContent['text/html'];
        } else {
          content = pasteBin.getHtml();
          internal = internal ? internal : InternalHtml.isMarked(content);
          if (pasteBin.isDefaultContent(content)) {
            plainTextMode = true;
          }
        }
        content = Utils.trimHtml(content);
        pasteBin.remove();
        isPlainTextHtml = internal === false && Newlines.isPlainText(content);
        if (!content.length || isPlainTextHtml) {
          plainTextMode = true;
        }
        if (plainTextMode) {
          if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) {
            content = clipboardContent['text/plain'];
          } else {
            content = Utils.innerText(content);
          }
        }
        if (pasteBin.isDefaultContent(content)) {
          if (!isKeyBoardPaste) {
            editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.');
          }
          return;
        }
        if (plainTextMode) {
          pasteText(editor, content);
        } else {
          pasteHtml$1(editor, content, internal);
        }
      }
      var getLastRng = function () {
        return pasteBin.getLastRng() || editor.selection.getRng();
      };
      editor.on('paste', function (e) {
        var isKeyBoardPaste = keyboardPasteEvent.isSet();
        var clipboardContent = getClipboardContent(editor, e);
        var plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState;
        var internal = hasContentType(clipboardContent, InternalHtml.internalHtmlMime());
        keyboardPastePlainTextState = false;
        if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
          pasteBin.remove();
          return;
        }
        if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) {
          pasteBin.remove();
          return;
        }
        if (!isKeyBoardPaste) {
          e.preventDefault();
        }
        if (global$2.ie && (!isKeyBoardPaste || e.ieFake) && !hasContentType(clipboardContent, 'text/html')) {
          pasteBin.create();
          editor.dom.bind(pasteBin.getEl(), 'paste', function (e) {
            e.stopPropagation();
          });
          editor.getDoc().execCommand('Paste', false, null);
          clipboardContent['text/html'] = pasteBin.getHtml();
        }
        if (hasContentType(clipboardContent, 'text/html')) {
          e.preventDefault();
          if (!internal) {
            internal = InternalHtml.isMarked(clipboardContent['text/html']);
          }
          insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal);
        } else {
          global$3.setEditorTimeout(editor, function () {
            insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal);
          }, 0);
        }
      });
    };
    var registerEventsAndFilters = function (editor, pasteBin, pasteFormat) {
      registerEventHandlers(editor, pasteBin, pasteFormat);
      var src;
      editor.parser.addNodeFilter('img', function (nodes, name, args) {
        var isPasteInsert = function (args) {
          return args.data && args.data.paste === true;
        };
        var remove = function (node) {
          if (!node.attr('data-mce-object') && src !== global$2.transparentSrc) {
            node.remove();
          }
        };
        var isWebKitFakeUrl = function (src) {
          return src.indexOf('webkit-fake-url') === 0;
        };
        var isDataUri = function (src) {
          return src.indexOf('data:') === 0;
        };
        if (!editor.settings.paste_data_images && isPasteInsert(args)) {
          var i = nodes.length;
          while (i--) {
            src = nodes[i].attributes.map.src;
            if (!src) {
              continue;
            }
            if (isWebKitFakeUrl(src)) {
              remove(nodes[i]);
            } else if (!editor.settings.allow_html_data_urls && isDataUri(src)) {
              remove(nodes[i]);
            }
          }
        }
      });
    };

    var getPasteBinParent = function (editor) {
      return global$2.ie && editor.inline ? domGlobals.document.body : editor.getBody();
    };
    var isExternalPasteBin = function (editor) {
      return getPasteBinParent(editor) !== editor.getBody();
    };
    var delegatePasteEvents = function (editor, pasteBinElm, pasteBinDefaultContent) {
      if (isExternalPasteBin(editor)) {
        editor.dom.bind(pasteBinElm, 'paste keyup', function (e) {
          if (!isDefault(editor, pasteBinDefaultContent)) {
            editor.fire('paste');
          }
        });
      }
    };
    var create = function (editor, lastRngCell, pasteBinDefaultContent) {
      var dom = editor.dom, body = editor.getBody();
      var pasteBinElm;
      lastRngCell.set(editor.selection.getRng());
      pasteBinElm = editor.dom.add(getPasteBinParent(editor), 'div', {
        'id': 'mcepastebin',
        'class': 'mce-pastebin',
        'contentEditable': true,
        'data-mce-bogus': 'all',
        'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0'
      }, pasteBinDefaultContent);
      if (global$2.ie || global$2.gecko) {
        dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535);
      }
      dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function (e) {
        e.stopPropagation();
      });
      delegatePasteEvents(editor, pasteBinElm, pasteBinDefaultContent);
      pasteBinElm.focus();
      editor.selection.select(pasteBinElm, true);
    };
    var remove = function (editor, lastRngCell) {
      if (getEl(editor)) {
        var pasteBinClone = void 0;
        var lastRng = lastRngCell.get();
        while (pasteBinClone = editor.dom.get('mcepastebin')) {
          editor.dom.remove(pasteBinClone);
          editor.dom.unbind(pasteBinClone);
        }
        if (lastRng) {
          editor.selection.setRng(lastRng);
        }
      }
      lastRngCell.set(null);
    };
    var getEl = function (editor) {
      return editor.dom.get('mcepastebin');
    };
    var getHtml = function (editor) {
      var pasteBinElm, pasteBinClones, i, dirtyWrappers, cleanWrapper;
      var copyAndRemove = function (toElm, fromElm) {
        toElm.appendChild(fromElm);
        editor.dom.remove(fromElm, true);
      };
      pasteBinClones = global$4.grep(getPasteBinParent(editor).childNodes, function (elm) {
        return elm.id === 'mcepastebin';
      });
      pasteBinElm = pasteBinClones.shift();
      global$4.each(pasteBinClones, function (pasteBinClone) {
        copyAndRemove(pasteBinElm, pasteBinClone);
      });
      dirtyWrappers = editor.dom.select('div[id=mcepastebin]', pasteBinElm);
      for (i = dirtyWrappers.length - 1; i >= 0; i--) {
        cleanWrapper = editor.dom.create('div');
        pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]);
        copyAndRemove(cleanWrapper, dirtyWrappers[i]);
      }
      return pasteBinElm ? pasteBinElm.innerHTML : '';
    };
    var getLastRng = function (lastRng) {
      return lastRng.get();
    };
    var isDefaultContent = function (pasteBinDefaultContent, content) {
      return content === pasteBinDefaultContent;
    };
    var isPasteBin = function (elm) {
      return elm && elm.id === 'mcepastebin';
    };
    var isDefault = function (editor, pasteBinDefaultContent) {
      var pasteBinElm = getEl(editor);
      return isPasteBin(pasteBinElm) && isDefaultContent(pasteBinDefaultContent, pasteBinElm.innerHTML);
    };
    var PasteBin = function (editor) {
      var lastRng = Cell(null);
      var pasteBinDefaultContent = '%MCEPASTEBIN%';
      return {
        create: function () {
          return create(editor, lastRng, pasteBinDefaultContent);
        },
        remove: function () {
          return remove(editor, lastRng);
        },
        getEl: function () {
          return getEl(editor);
        },
        getHtml: function () {
          return getHtml(editor);
        },
        getLastRng: function () {
          return getLastRng(lastRng);
        },
        isDefault: function () {
          return isDefault(editor, pasteBinDefaultContent);
        },
        isDefaultContent: function (content) {
          return isDefaultContent(pasteBinDefaultContent, content);
        }
      };
    };

    var Clipboard = function (editor, pasteFormat) {
      var pasteBin = PasteBin(editor);
      editor.on('preInit', function () {
        return registerEventsAndFilters(editor, pasteBin, pasteFormat);
      });
      return {
        pasteFormat: pasteFormat,
        pasteHtml: function (html, internalFlag) {
          return pasteHtml$1(editor, html, internalFlag);
        },
        pasteText: function (text) {
          return pasteText(editor, text);
        },
        pasteImageData: function (e, rng) {
          return pasteImageData(editor, e, rng);
        },
        getDataTransferItems: getDataTransferItems,
        hasHtmlOrText: hasHtmlOrText,
        hasContentType: hasContentType
      };
    };

    var noop$1 = function () {
    };
    var hasWorkingClipboardApi = function (clipboardData) {
      return global$2.iOS === false && clipboardData !== undefined && typeof clipboardData.setData === 'function' && Utils.isMsEdge() !== true;
    };
    var setHtml5Clipboard = function (clipboardData, html, text) {
      if (hasWorkingClipboardApi(clipboardData)) {
        try {
          clipboardData.clearData();
          clipboardData.setData('text/html', html);
          clipboardData.setData('text/plain', text);
          clipboardData.setData(InternalHtml.internalHtmlMime(), html);
          return true;
        } catch (e) {
          return false;
        }
      } else {
        return false;
      }
    };
    var setClipboardData = function (evt, data, fallback, done) {
      if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) {
        evt.preventDefault();
        done();
      } else {
        fallback(data.html, done);
      }
    };
    var fallback = function (editor) {
      return function (html, done) {
        var markedHtml = InternalHtml.mark(html);
        var outer = editor.dom.create('div', {
          'contenteditable': 'false',
          'data-mce-bogus': 'all'
        });
        var inner = editor.dom.create('div', { contenteditable: 'true' }, markedHtml);
        editor.dom.setStyles(outer, {
          position: 'fixed',
          top: '0',
          left: '-3000px',
          width: '1000px',
          overflow: 'hidden'
        });
        outer.appendChild(inner);
        editor.dom.add(editor.getBody(), outer);
        var range = editor.selection.getRng();
        inner.focus();
        var offscreenRange = editor.dom.createRng();
        offscreenRange.selectNodeContents(inner);
        editor.selection.setRng(offscreenRange);
        setTimeout(function () {
          editor.selection.setRng(range);
          outer.parentNode.removeChild(outer);
          done();
        }, 0);
      };
    };
    var getData = function (editor) {
      return {
        html: editor.selection.getContent({ contextual: true }),
        text: editor.selection.getContent({ format: 'text' })
      };
    };
    var isTableSelection = function (editor) {
      return !!editor.dom.getParent(editor.selection.getStart(), 'td[data-mce-selected],th[data-mce-selected]', editor.getBody());
    };
    var hasSelectedContent = function (editor) {
      return !editor.selection.isCollapsed() || isTableSelection(editor);
    };
    var cut = function (editor) {
      return function (evt) {
        if (hasSelectedContent(editor)) {
          setClipboardData(evt, getData(editor), fallback(editor), function () {
            setTimeout(function () {
              editor.execCommand('Delete');
            }, 0);
          });
        }
      };
    };
    var copy = function (editor) {
      return function (evt) {
        if (hasSelectedContent(editor)) {
          setClipboardData(evt, getData(editor), fallback(editor), noop$1);
        }
      };
    };
    var register$1 = function (editor) {
      editor.on('cut', cut(editor));
      editor.on('copy', copy(editor));
    };
    var CutCopy = { register: register$1 };

    var global$b = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils');

    var getCaretRangeFromEvent = function (editor, e) {
      return global$b.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc());
    };
    var isPlainTextFileUrl = function (content) {
      var plainTextContent = content['text/plain'];
      return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false;
    };
    var setFocusedRange = function (editor, rng) {
      editor.focus();
      editor.selection.setRng(rng);
    };
    var setup = function (editor, clipboard, draggingInternallyState) {
      if (Settings.shouldBlockDrop(editor)) {
        editor.on('dragend dragover draggesture dragdrop drop drag', function (e) {
          e.preventDefault();
          e.stopPropagation();
        });
      }
      if (!Settings.shouldPasteDataImages(editor)) {
        editor.on('drop', function (e) {
          var dataTransfer = e.dataTransfer;
          if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
            e.preventDefault();
          }
        });
      }
      editor.on('drop', function (e) {
        var dropContent, rng;
        rng = getCaretRangeFromEvent(editor, e);
        if (e.isDefaultPrevented() || draggingInternallyState.get()) {
          return;
        }
        dropContent = clipboard.getDataTransferItems(e.dataTransfer);
        var internal = clipboard.hasContentType(dropContent, InternalHtml.internalHtmlMime());
        if ((!clipboard.hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && clipboard.pasteImageData(e, rng)) {
          return;
        }
        if (rng && Settings.shouldFilterDrop(editor)) {
          var content_1 = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain'];
          if (content_1) {
            e.preventDefault();
            global$3.setEditorTimeout(editor, function () {
              editor.undoManager.transact(function () {
                if (dropContent['mce-internal']) {
                  editor.execCommand('Delete');
                }
                setFocusedRange(editor, rng);
                content_1 = Utils.trimHtml(content_1);
                if (!dropContent['text/html']) {
                  clipboard.pasteText(content_1);
                } else {
                  clipboard.pasteHtml(content_1, internal);
                }
              });
            });
          }
        }
      });
      editor.on('dragstart', function (e) {
        draggingInternallyState.set(true);
      });
      editor.on('dragover dragend', function (e) {
        if (Settings.shouldPasteDataImages(editor) && draggingInternallyState.get() === false) {
          e.preventDefault();
          setFocusedRange(editor, getCaretRangeFromEvent(editor, e));
        }
        if (e.type === 'dragend') {
          draggingInternallyState.set(false);
        }
      });
    };
    var DragDrop = { setup: setup };

    var setup$1 = function (editor) {
      var plugin = editor.plugins.paste;
      var preProcess = Settings.getPreProcess(editor);
      if (preProcess) {
        editor.on('PastePreProcess', function (e) {
          preProcess.call(plugin, plugin, e);
        });
      }
      var postProcess = Settings.getPostProcess(editor);
      if (postProcess) {
        editor.on('PastePostProcess', function (e) {
          postProcess.call(plugin, plugin, e);
        });
      }
    };
    var PrePostProcess = { setup: setup$1 };

    function addPreProcessFilter(editor, filterFunc) {
      editor.on('PastePreProcess', function (e) {
        e.content = filterFunc(editor, e.content, e.internal, e.wordContent);
      });
    }
    function addPostProcessFilter(editor, filterFunc) {
      editor.on('PastePostProcess', function (e) {
        filterFunc(editor, e.node);
      });
    }
    function removeExplorerBrElementsAfterBlocks(editor, html) {
      if (!WordFilter.isWordContent(html)) {
        return html;
      }
      var blockElements = [];
      global$4.each(editor.schema.getBlockElements(), function (block, blockName) {
        blockElements.push(blockName);
      });
      var explorerBlocksRegExp = new RegExp('(?:<br>&nbsp;[\\s\\r\\n]+|<br>)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:<br>&nbsp;[\\s\\r\\n]+|<br>)*', 'g');
      html = Utils.filter(html, [[
          explorerBlocksRegExp,
          '$1'
        ]]);
      html = Utils.filter(html, [
        [
          /<br><br>/g,
          '<BR><BR>'
        ],
        [
          /<br>/g,
          ' '
        ],
        [
          /<BR><BR>/g,
          '<br>'
        ]
      ]);
      return html;
    }
    function removeWebKitStyles(editor, content, internal, isWordHtml) {
      if (isWordHtml || internal) {
        return content;
      }
      var webKitStylesSetting = Settings.getWebkitStyles(editor);
      var webKitStyles;
      if (Settings.shouldRemoveWebKitStyles(editor) === false || webKitStylesSetting === 'all') {
        return content;
      }
      if (webKitStylesSetting) {
        webKitStyles = webKitStylesSetting.split(/[, ]/);
      }
      if (webKitStyles) {
        var dom_1 = editor.dom, node_1 = editor.selection.getNode();
        content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function (all, before, value, after) {
          var inputStyles = dom_1.parseStyle(dom_1.decode(value));
          var outputStyles = {};
          if (webKitStyles === 'none') {
            return before + after;
          }
          for (var i = 0; i < webKitStyles.length; i++) {
            var inputValue = inputStyles[webKitStyles[i]], currentValue = dom_1.getStyle(node_1, webKitStyles[i], true);
            if (/color/.test(webKitStyles[i])) {
              inputValue = dom_1.toHex(inputValue);
              currentValue = dom_1.toHex(currentValue);
            }
            if (currentValue !== inputValue) {
              outputStyles[webKitStyles[i]] = inputValue;
            }
          }
          outputStyles = dom_1.serializeStyle(outputStyles, 'span');
          if (outputStyles) {
            return before + ' style="' + outputStyles + '"' + after;
          }
          return before + after;
        });
      } else {
        content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3');
      }
      content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function (all, before, value, after) {
        return before + ' style="' + value + '"' + after;
      });
      return content;
    }
    function removeUnderlineAndFontInAnchor(editor, root) {
      editor.$('a', root).find('font,u').each(function (i, node) {
        editor.dom.remove(node, true);
      });
    }
    var setup$2 = function (editor) {
      if (global$2.webkit) {
        addPreProcessFilter(editor, removeWebKitStyles);
      }
      if (global$2.ie) {
        addPreProcessFilter(editor, removeExplorerBrElementsAfterBlocks);
        addPostProcessFilter(editor, removeUnderlineAndFontInAnchor);
      }
    };
    var Quirks = { setup: setup$2 };

    var stateChange = function (editor, clipboard, e) {
      var ctrl = e.control;
      ctrl.active(clipboard.pasteFormat.get() === 'text');
      editor.on('PastePlainTextToggle', function (e) {
        ctrl.active(e.state);
      });
    };
    var register$2 = function (editor, clipboard) {
      var postRender = curry(stateChange, editor, clipboard);
      editor.addButton('pastetext', {
        active: false,
        icon: 'pastetext',
        tooltip: 'Paste as text',
        cmd: 'mceTogglePlainTextPaste',
        onPostRender: postRender
      });
      editor.addMenuItem('pastetext', {
        text: 'Paste as text',
        selectable: true,
        active: clipboard.pasteFormat,
        cmd: 'mceTogglePlainTextPaste',
        onPostRender: postRender
      });
    };
    var Buttons = { register: register$2 };

    global$1.add('paste', function (editor) {
      if (DetectProPlugin.hasProPlugin(editor) === false) {
        var userIsInformedState = Cell(false);
        var draggingInternallyState = Cell(false);
        var pasteFormat = Cell(Settings.isPasteAsTextEnabled(editor) ? 'text' : 'html');
        var clipboard = Clipboard(editor, pasteFormat);
        var quirks = Quirks.setup(editor);
        Buttons.register(editor, clipboard);
        Commands.register(editor, clipboard, userIsInformedState);
        PrePostProcess.setup(editor);
        CutCopy.register(editor);
        DragDrop.setup(editor, clipboard, draggingInternallyState);
        return Api.get(clipboard, quirks);
      }
    });
    function Plugin () {
    }

    return Plugin;

}(window));
})();

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5), __webpack_require__(6)))

/***/ }),

/***/ 576:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "code" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/code')
//   ES2015:
//     import 'tinymce/plugins/code'
__webpack_require__(577);

/***/ }),

/***/ 577:
/***/ (function(module, exports) {

(function () {
var code = (function () {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

    var getMinWidth = function (editor) {
      return editor.getParam('code_dialog_width', 600);
    };
    var getMinHeight = function (editor) {
      return editor.getParam('code_dialog_height', Math.min(global$1.DOM.getViewPort().h - 200, 500));
    };
    var Settings = {
      getMinWidth: getMinWidth,
      getMinHeight: getMinHeight
    };

    var setContent = function (editor, html) {
      editor.focus();
      editor.undoManager.transact(function () {
        editor.setContent(html);
      });
      editor.selection.setCursorLocation();
      editor.nodeChanged();
    };
    var getContent = function (editor) {
      return editor.getContent({ source_view: true });
    };
    var Content = {
      setContent: setContent,
      getContent: getContent
    };

    var open = function (editor) {
      var minWidth = Settings.getMinWidth(editor);
      var minHeight = Settings.getMinHeight(editor);
      var win = editor.windowManager.open({
        title: 'Source code',
        body: {
          type: 'textbox',
          name: 'code',
          multiline: true,
          minWidth: minWidth,
          minHeight: minHeight,
          spellcheck: false,
          style: 'direction: ltr; text-align: left'
        },
        onSubmit: function (e) {
          Content.setContent(editor, e.data.code);
        }
      });
      win.find('#code').value(Content.getContent(editor));
    };
    var Dialog = { open: open };

    var register = function (editor) {
      editor.addCommand('mceCodeEditor', function () {
        Dialog.open(editor);
      });
    };
    var Commands = { register: register };

    var register$1 = function (editor) {
      editor.addButton('code', {
        icon: 'code',
        tooltip: 'Source code',
        onclick: function () {
          Dialog.open(editor);
        }
      });
      editor.addMenuItem('code', {
        icon: 'code',
        text: 'Source code',
        onclick: function () {
          Dialog.open(editor);
        }
      });
    };
    var Buttons = { register: register$1 };

    global.add('code', function (editor) {
      Commands.register(editor);
      Buttons.register(editor);
      return {};
    });
    function Plugin () {
    }

    return Plugin;

}());
})();


/***/ }),

/***/ 578:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "fullscreen" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/fullscreen')
//   ES2015:
//     import 'tinymce/plugins/fullscreen'
__webpack_require__(579);

/***/ }),

/***/ 579:
/***/ (function(module, exports) {

(function () {
var fullscreen = (function (domGlobals) {
    'use strict';

    var Cell = function (initial) {
      var value = initial;
      var get = function () {
        return value;
      };
      var set = function (v) {
        value = v;
      };
      var clone = function () {
        return Cell(get());
      };
      return {
        get: get,
        set: set,
        clone: clone
      };
    };

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var get = function (fullscreenState) {
      return {
        isFullscreen: function () {
          return fullscreenState.get() !== null;
        }
      };
    };
    var Api = { get: get };

    var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

    var fireFullscreenStateChanged = function (editor, state) {
      editor.fire('FullscreenStateChanged', { state: state });
    };
    var Events = { fireFullscreenStateChanged: fireFullscreenStateChanged };

    var DOM = global$1.DOM;
    var getWindowSize = function () {
      var w;
      var h;
      var win = domGlobals.window;
      var doc = domGlobals.document;
      var body = doc.body;
      if (body.offsetWidth) {
        w = body.offsetWidth;
        h = body.offsetHeight;
      }
      if (win.innerWidth && win.innerHeight) {
        w = win.innerWidth;
        h = win.innerHeight;
      }
      return {
        w: w,
        h: h
      };
    };
    var getScrollPos = function () {
      var vp = DOM.getViewPort();
      return {
        x: vp.x,
        y: vp.y
      };
    };
    var setScrollPos = function (pos) {
      domGlobals.window.scrollTo(pos.x, pos.y);
    };
    var toggleFullscreen = function (editor, fullscreenState) {
      var body = domGlobals.document.body;
      var documentElement = domGlobals.document.documentElement;
      var editorContainerStyle;
      var editorContainer, iframe, iframeStyle;
      var fullscreenInfo = fullscreenState.get();
      var resize = function () {
        DOM.setStyle(iframe, 'height', getWindowSize().h - (editorContainer.clientHeight - iframe.clientHeight));
      };
      var removeResize = function () {
        DOM.unbind(domGlobals.window, 'resize', resize);
      };
      editorContainer = editor.getContainer();
      editorContainerStyle = editorContainer.style;
      iframe = editor.getContentAreaContainer().firstChild;
      iframeStyle = iframe.style;
      if (!fullscreenInfo) {
        var newFullScreenInfo = {
          scrollPos: getScrollPos(),
          containerWidth: editorContainerStyle.width,
          containerHeight: editorContainerStyle.height,
          iframeWidth: iframeStyle.width,
          iframeHeight: iframeStyle.height,
          resizeHandler: resize,
          removeHandler: removeResize
        };
        iframeStyle.width = iframeStyle.height = '100%';
        editorContainerStyle.width = editorContainerStyle.height = '';
        DOM.addClass(body, 'mce-fullscreen');
        DOM.addClass(documentElement, 'mce-fullscreen');
        DOM.addClass(editorContainer, 'mce-fullscreen');
        DOM.bind(domGlobals.window, 'resize', resize);
        editor.on('remove', removeResize);
        resize();
        fullscreenState.set(newFullScreenInfo);
        Events.fireFullscreenStateChanged(editor, true);
      } else {
        iframeStyle.width = fullscreenInfo.iframeWidth;
        iframeStyle.height = fullscreenInfo.iframeHeight;
        if (fullscreenInfo.containerWidth) {
          editorContainerStyle.width = fullscreenInfo.containerWidth;
        }
        if (fullscreenInfo.containerHeight) {
          editorContainerStyle.height = fullscreenInfo.containerHeight;
        }
        DOM.removeClass(body, 'mce-fullscreen');
        DOM.removeClass(documentElement, 'mce-fullscreen');
        DOM.removeClass(editorContainer, 'mce-fullscreen');
        setScrollPos(fullscreenInfo.scrollPos);
        DOM.unbind(domGlobals.window, 'resize', fullscreenInfo.resizeHandler);
        editor.off('remove', fullscreenInfo.removeHandler);
        fullscreenState.set(null);
        Events.fireFullscreenStateChanged(editor, false);
      }
    };
    var Actions = { toggleFullscreen: toggleFullscreen };

    var register = function (editor, fullscreenState) {
      editor.addCommand('mceFullScreen', function () {
        Actions.toggleFullscreen(editor, fullscreenState);
      });
    };
    var Commands = { register: register };

    var postRender = function (editor) {
      return function (e) {
        var ctrl = e.control;
        editor.on('FullscreenStateChanged', function (e) {
          ctrl.active(e.state);
        });
      };
    };
    var register$1 = function (editor) {
      editor.addMenuItem('fullscreen', {
        text: 'Fullscreen',
        shortcut: 'Ctrl+Shift+F',
        selectable: true,
        cmd: 'mceFullScreen',
        onPostRender: postRender(editor),
        context: 'view'
      });
      editor.addButton('fullscreen', {
        active: false,
        tooltip: 'Fullscreen',
        cmd: 'mceFullScreen',
        onPostRender: postRender(editor)
      });
    };
    var Buttons = { register: register$1 };

    global.add('fullscreen', function (editor) {
      var fullscreenState = Cell(null);
      if (editor.settings.inline) {
        return Api.get(fullscreenState);
      }
      Commands.register(editor, fullscreenState);
      Buttons.register(editor);
      editor.addShortcut('Ctrl+Shift+F', '', 'mceFullScreen');
      return Api.get(fullscreenState);
    });
    function Plugin () {
    }

    return Plugin;

}(window));
})();


/***/ }),

/***/ 580:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "textcolor" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/textcolor')
//   ES2015:
//     import 'tinymce/plugins/textcolor'
__webpack_require__(581);

/***/ }),

/***/ 581:
/***/ (function(module, exports) {

(function () {
var textcolor = (function () {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var getCurrentColor = function (editor, format) {
      var color;
      editor.dom.getParents(editor.selection.getStart(), function (elm) {
        var value;
        if (value = elm.style[format === 'forecolor' ? 'color' : 'background-color']) {
          color = color ? color : value;
        }
      });
      return color;
    };
    var mapColors = function (colorMap) {
      var i;
      var colors = [];
      for (i = 0; i < colorMap.length; i += 2) {
        colors.push({
          text: colorMap[i + 1],
          color: '#' + colorMap[i]
        });
      }
      return colors;
    };
    var applyFormat = function (editor, format, value) {
      editor.undoManager.transact(function () {
        editor.focus();
        editor.formatter.apply(format, { value: value });
        editor.nodeChanged();
      });
    };
    var removeFormat = function (editor, format) {
      editor.undoManager.transact(function () {
        editor.focus();
        editor.formatter.remove(format, { value: null }, null, true);
        editor.nodeChanged();
      });
    };
    var TextColor = {
      getCurrentColor: getCurrentColor,
      mapColors: mapColors,
      applyFormat: applyFormat,
      removeFormat: removeFormat
    };

    var register = function (editor) {
      editor.addCommand('mceApplyTextcolor', function (format, value) {
        TextColor.applyFormat(editor, format, value);
      });
      editor.addCommand('mceRemoveTextcolor', function (format) {
        TextColor.removeFormat(editor, format);
      });
    };
    var Commands = { register: register };

    var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

    var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    var defaultColorMap = [
      '000000',
      'Black',
      '993300',
      'Burnt orange',
      '333300',
      'Dark olive',
      '003300',
      'Dark green',
      '003366',
      'Dark azure',
      '000080',
      'Navy Blue',
      '333399',
      'Indigo',
      '333333',
      'Very dark gray',
      '800000',
      'Maroon',
      'FF6600',
      'Orange',
      '808000',
      'Olive',
      '008000',
      'Green',
      '008080',
      'Teal',
      '0000FF',
      'Blue',
      '666699',
      'Grayish blue',
      '808080',
      'Gray',
      'FF0000',
      'Red',
      'FF9900',
      'Amber',
      '99CC00',
      'Yellow green',
      '339966',
      'Sea green',
      '33CCCC',
      'Turquoise',
      '3366FF',
      'Royal blue',
      '800080',
      'Purple',
      '999999',
      'Medium gray',
      'FF00FF',
      'Magenta',
      'FFCC00',
      'Gold',
      'FFFF00',
      'Yellow',
      '00FF00',
      'Lime',
      '00FFFF',
      'Aqua',
      '00CCFF',
      'Sky blue',
      '993366',
      'Red violet',
      'FFFFFF',
      'White',
      'FF99CC',
      'Pink',
      'FFCC99',
      'Peach',
      'FFFF99',
      'Light yellow',
      'CCFFCC',
      'Pale green',
      'CCFFFF',
      'Pale cyan',
      '99CCFF',
      'Light sky blue',
      'CC99FF',
      'Plum'
    ];
    var getTextColorMap = function (editor) {
      return editor.getParam('textcolor_map', defaultColorMap);
    };
    var getForeColorMap = function (editor) {
      return editor.getParam('forecolor_map', getTextColorMap(editor));
    };
    var getBackColorMap = function (editor) {
      return editor.getParam('backcolor_map', getTextColorMap(editor));
    };
    var getTextColorRows = function (editor) {
      return editor.getParam('textcolor_rows', 5);
    };
    var getTextColorCols = function (editor) {
      return editor.getParam('textcolor_cols', 8);
    };
    var getForeColorRows = function (editor) {
      return editor.getParam('forecolor_rows', getTextColorRows(editor));
    };
    var getBackColorRows = function (editor) {
      return editor.getParam('backcolor_rows', getTextColorRows(editor));
    };
    var getForeColorCols = function (editor) {
      return editor.getParam('forecolor_cols', getTextColorCols(editor));
    };
    var getBackColorCols = function (editor) {
      return editor.getParam('backcolor_cols', getTextColorCols(editor));
    };
    var getColorPickerCallback = function (editor) {
      return editor.getParam('color_picker_callback', null);
    };
    var hasColorPicker = function (editor) {
      return typeof getColorPickerCallback(editor) === 'function';
    };
    var Settings = {
      getForeColorMap: getForeColorMap,
      getBackColorMap: getBackColorMap,
      getForeColorRows: getForeColorRows,
      getBackColorRows: getBackColorRows,
      getForeColorCols: getForeColorCols,
      getBackColorCols: getBackColorCols,
      getColorPickerCallback: getColorPickerCallback,
      hasColorPicker: hasColorPicker
    };

    var global$3 = tinymce.util.Tools.resolve('tinymce.util.I18n');

    var getHtml = function (cols, rows, colorMap, hasColorPicker) {
      var colors, color, html, last, x, y, i, count = 0;
      var id = global$1.DOM.uniqueId('mcearia');
      var getColorCellHtml = function (color, title) {
        var isNoColor = color === 'transparent';
        return '<td class="mce-grid-cell' + (isNoColor ? ' mce-colorbtn-trans' : '') + '">' + '<div id="' + id + '-' + count++ + '"' + ' data-mce-color="' + (color ? color : '') + '"' + ' role="option"' + ' tabIndex="-1"' + ' style="' + (color ? 'background-color: ' + color : '') + '"' + ' title="' + global$3.translate(title) + '">' + (isNoColor ? '&#215;' : '') + '</div>' + '</td>';
      };
      colors = TextColor.mapColors(colorMap);
      colors.push({
        text: global$3.translate('No color'),
        color: 'transparent'
      });
      html = '<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>';
      last = colors.length - 1;
      for (y = 0; y < rows; y++) {
        html += '<tr>';
        for (x = 0; x < cols; x++) {
          i = y * cols + x;
          if (i > last) {
            html += '<td></td>';
          } else {
            color = colors[i];
            html += getColorCellHtml(color.color, color.text);
          }
        }
        html += '</tr>';
      }
      if (hasColorPicker) {
        html += '<tr>' + '<td colspan="' + cols + '" class="mce-custom-color-btn">' + '<div id="' + id + '-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" ' + 'role="button" tabindex="-1" aria-labelledby="' + id + '-c" style="width: 100%">' + '<button type="button" role="presentation" tabindex="-1">' + global$3.translate('Custom...') + '</button>' + '</div>' + '</td>' + '</tr>';
        html += '<tr>';
        for (x = 0; x < cols; x++) {
          html += getColorCellHtml('', 'Custom color');
        }
        html += '</tr>';
      }
      html += '</tbody></table>';
      return html;
    };
    var ColorPickerHtml = { getHtml: getHtml };

    var setDivColor = function setDivColor(div, value) {
      div.style.background = value;
      div.setAttribute('data-mce-color', value);
    };
    var onButtonClick = function (editor) {
      return function (e) {
        var ctrl = e.control;
        if (ctrl._color) {
          editor.execCommand('mceApplyTextcolor', ctrl.settings.format, ctrl._color);
        } else {
          editor.execCommand('mceRemoveTextcolor', ctrl.settings.format);
        }
      };
    };
    var onPanelClick = function (editor, cols) {
      return function (e) {
        var buttonCtrl = this.parent();
        var value;
        var currentColor = TextColor.getCurrentColor(editor, buttonCtrl.settings.format);
        var selectColor = function (value) {
          editor.execCommand('mceApplyTextcolor', buttonCtrl.settings.format, value);
          buttonCtrl.hidePanel();
          buttonCtrl.color(value);
        };
        var resetColor = function () {
          editor.execCommand('mceRemoveTextcolor', buttonCtrl.settings.format);
          buttonCtrl.hidePanel();
          buttonCtrl.resetColor();
        };
        if (global$1.DOM.getParent(e.target, '.mce-custom-color-btn')) {
          buttonCtrl.hidePanel();
          var colorPickerCallback = Settings.getColorPickerCallback(editor);
          colorPickerCallback.call(editor, function (value) {
            var tableElm = buttonCtrl.panel.getEl().getElementsByTagName('table')[0];
            var customColorCells, div, i;
            customColorCells = global$2.map(tableElm.rows[tableElm.rows.length - 1].childNodes, function (elm) {
              return elm.firstChild;
            });
            for (i = 0; i < customColorCells.length; i++) {
              div = customColorCells[i];
              if (!div.getAttribute('data-mce-color')) {
                break;
              }
            }
            if (i === cols) {
              for (i = 0; i < cols - 1; i++) {
                setDivColor(customColorCells[i], customColorCells[i + 1].getAttribute('data-mce-color'));
              }
            }
            setDivColor(div, value);
            selectColor(value);
          }, currentColor);
        }
        value = e.target.getAttribute('data-mce-color');
        if (value) {
          if (this.lastId) {
            global$1.DOM.get(this.lastId).setAttribute('aria-selected', 'false');
          }
          e.target.setAttribute('aria-selected', true);
          this.lastId = e.target.id;
          if (value === 'transparent') {
            resetColor();
          } else {
            selectColor(value);
          }
        } else if (value !== null) {
          buttonCtrl.hidePanel();
        }
      };
    };
    var renderColorPicker = function (editor, foreColor) {
      return function () {
        var cols = foreColor ? Settings.getForeColorCols(editor) : Settings.getBackColorCols(editor);
        var rows = foreColor ? Settings.getForeColorRows(editor) : Settings.getBackColorRows(editor);
        var colorMap = foreColor ? Settings.getForeColorMap(editor) : Settings.getBackColorMap(editor);
        var hasColorPicker = Settings.hasColorPicker(editor);
        return ColorPickerHtml.getHtml(cols, rows, colorMap, hasColorPicker);
      };
    };
    var register$1 = function (editor) {
      editor.addButton('forecolor', {
        type: 'colorbutton',
        tooltip: 'Text color',
        format: 'forecolor',
        panel: {
          role: 'application',
          ariaRemember: true,
          html: renderColorPicker(editor, true),
          onclick: onPanelClick(editor, Settings.getForeColorCols(editor))
        },
        onclick: onButtonClick(editor)
      });
      editor.addButton('backcolor', {
        type: 'colorbutton',
        tooltip: 'Background color',
        format: 'hilitecolor',
        panel: {
          role: 'application',
          ariaRemember: true,
          html: renderColorPicker(editor, false),
          onclick: onPanelClick(editor, Settings.getBackColorCols(editor))
        },
        onclick: onButtonClick(editor)
      });
    };
    var Buttons = { register: register$1 };

    global.add('textcolor', function (editor) {
      Commands.register(editor);
      Buttons.register(editor);
    });
    function Plugin () {
    }

    return Plugin;

}());
})();


/***/ }),

/***/ 582:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "colorpicker" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/colorpicker')
//   ES2015:
//     import 'tinymce/plugins/colorpicker'
__webpack_require__(583);

/***/ }),

/***/ 583:
/***/ (function(module, exports) {

(function () {
var colorpicker = (function () {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var global$1 = tinymce.util.Tools.resolve('tinymce.util.Color');

    var showPreview = function (win, hexColor) {
      win.find('#preview')[0].getEl().style.background = hexColor;
    };
    var setColor = function (win, value) {
      var color = global$1(value), rgb = color.toRgb();
      win.fromJSON({
        r: rgb.r,
        g: rgb.g,
        b: rgb.b,
        hex: color.toHex().substr(1)
      });
      showPreview(win, color.toHex());
    };
    var open = function (editor, callback, value) {
      var win = editor.windowManager.open({
        title: 'Color',
        items: {
          type: 'container',
          layout: 'flex',
          direction: 'row',
          align: 'stretch',
          padding: 5,
          spacing: 10,
          items: [
            {
              type: 'colorpicker',
              value: value,
              onchange: function () {
                var rgb = this.rgb();
                if (win) {
                  win.find('#r').value(rgb.r);
                  win.find('#g').value(rgb.g);
                  win.find('#b').value(rgb.b);
                  win.find('#hex').value(this.value().substr(1));
                  showPreview(win, this.value());
                }
              }
            },
            {
              type: 'form',
              padding: 0,
              labelGap: 5,
              defaults: {
                type: 'textbox',
                size: 7,
                value: '0',
                flex: 1,
                spellcheck: false,
                onchange: function () {
                  var colorPickerCtrl = win.find('colorpicker')[0];
                  var name, value;
                  name = this.name();
                  value = this.value();
                  if (name === 'hex') {
                    value = '#' + value;
                    setColor(win, value);
                    colorPickerCtrl.value(value);
                    return;
                  }
                  value = {
                    r: win.find('#r').value(),
                    g: win.find('#g').value(),
                    b: win.find('#b').value()
                  };
                  colorPickerCtrl.value(value);
                  setColor(win, value);
                }
              },
              items: [
                {
                  name: 'r',
                  label: 'R',
                  autofocus: 1
                },
                {
                  name: 'g',
                  label: 'G'
                },
                {
                  name: 'b',
                  label: 'B'
                },
                {
                  name: 'hex',
                  label: '#',
                  value: '000000'
                },
                {
                  name: 'preview',
                  type: 'container',
                  border: 1
                }
              ]
            }
          ]
        },
        onSubmit: function () {
          callback('#' + win.toJSON().hex);
        }
      });
      setColor(win, value);
    };
    var Dialog = { open: open };

    global.add('colorpicker', function (editor) {
      if (!editor.settings.color_picker_callback) {
        editor.settings.color_picker_callback = function (callback, value) {
          Dialog.open(editor, callback, value);
        };
      }
    });
    function Plugin () {
    }

    return Plugin;

}());
})();


/***/ }),

/***/ 584:
/***/ (function(module, exports, __webpack_require__) {

// Exports the "lists" plugin for usage with module loaders
// Usage:
//   CommonJS:
//     require('tinymce/plugins/lists')
//   ES2015:
//     import 'tinymce/plugins/lists'
__webpack_require__(585);

/***/ }),

/***/ 585:
/***/ (function(module, exports) {

(function () {
var lists = (function (domGlobals) {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    var global$1 = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils');

    var global$2 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker');

    var global$3 = tinymce.util.Tools.resolve('tinymce.util.VK');

    var global$4 = tinymce.util.Tools.resolve('tinymce.dom.BookmarkManager');

    var global$5 = tinymce.util.Tools.resolve('tinymce.util.Tools');

    var global$6 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

    var isTextNode = function (node) {
      return node && node.nodeType === 3;
    };
    var isListNode = function (node) {
      return node && /^(OL|UL|DL)$/.test(node.nodeName);
    };
    var isOlUlNode = function (node) {
      return node && /^(OL|UL)$/.test(node.nodeName);
    };
    var isListItemNode = function (node) {
      return node && /^(LI|DT|DD)$/.test(node.nodeName);
    };
    var isDlItemNode = function (node) {
      return node && /^(DT|DD)$/.test(node.nodeName);
    };
    var isTableCellNode = function (node) {
      return node && /^(TH|TD)$/.test(node.nodeName);
    };
    var isBr = function (node) {
      return node && node.nodeName === 'BR';
    };
    var isFirstChild = function (node) {
      return node.parentNode.firstChild === node;
    };
    var isLastChild = function (node) {
      return node.parentNode.lastChild === node;
    };
    var isTextBlock = function (editor, node) {
      return node && !!editor.schema.getTextBlockElements()[node.nodeName];
    };
    var isBlock = function (node, blockElements) {
      return node && node.nodeName in blockElements;
    };
    var isBogusBr = function (dom, node) {
      if (!isBr(node)) {
        return false;
      }
      if (dom.isBlock(node.nextSibling) && !isBr(node.previousSibling)) {
        return true;
      }
      return false;
    };
    var isEmpty = function (dom, elm, keepBookmarks) {
      var empty = dom.isEmpty(elm);
      if (keepBookmarks && dom.select('span[data-mce-type=bookmark]', elm).length > 0) {
        return false;
      }
      return empty;
    };
    var isChildOfBody = function (dom, elm) {
      return dom.isChildOf(elm, dom.getRoot());
    };
    var NodeType = {
      isTextNode: isTextNode,
      isListNode: isListNode,
      isOlUlNode: isOlUlNode,
      isDlItemNode: isDlItemNode,
      isListItemNode: isListItemNode,
      isTableCellNode: isTableCellNode,
      isBr: isBr,
      isFirstChild: isFirstChild,
      isLastChild: isLastChild,
      isTextBlock: isTextBlock,
      isBlock: isBlock,
      isBogusBr: isBogusBr,
      isEmpty: isEmpty,
      isChildOfBody: isChildOfBody
    };

    var getNormalizedPoint = function (container, offset) {
      if (NodeType.isTextNode(container)) {
        return {
          container: container,
          offset: offset
        };
      }
      var node = global$1.getNode(container, offset);
      if (NodeType.isTextNode(node)) {
        return {
          container: node,
          offset: offset >= container.childNodes.length ? node.data.length : 0
        };
      } else if (node.previousSibling && NodeType.isTextNode(node.previousSibling)) {
        return {
          container: node.previousSibling,
          offset: node.previousSibling.data.length
        };
      } else if (node.nextSibling && NodeType.isTextNode(node.nextSibling)) {
        return {
          container: node.nextSibling,
          offset: 0
        };
      }
      return {
        container: container,
        offset: offset
      };
    };
    var normalizeRange = function (rng) {
      var outRng = rng.cloneRange();
      var rangeStart = getNormalizedPoint(rng.startContainer, rng.startOffset);
      outRng.setStart(rangeStart.container, rangeStart.offset);
      var rangeEnd = getNormalizedPoint(rng.endContainer, rng.endOffset);
      outRng.setEnd(rangeEnd.container, rangeEnd.offset);
      return outRng;
    };
    var Range = {
      getNormalizedPoint: getNormalizedPoint,
      normalizeRange: normalizeRange
    };

    var DOM = global$6.DOM;
    var createBookmark = function (rng) {
      var bookmark = {};
      var setupEndPoint = function (start) {
        var offsetNode, container, offset;
        container = rng[start ? 'startContainer' : 'endContainer'];
        offset = rng[start ? 'startOffset' : 'endOffset'];
        if (container.nodeType === 1) {
          offsetNode = DOM.create('span', { 'data-mce-type': 'bookmark' });
          if (container.hasChildNodes()) {
            offset = Math.min(offset, container.childNodes.length - 1);
            if (start) {
              container.insertBefore(offsetNode, container.childNodes[offset]);
            } else {
              DOM.insertAfter(offsetNode, container.childNodes[offset]);
            }
          } else {
            container.appendChild(offsetNode);
          }
          container = offsetNode;
          offset = 0;
        }
        bookmark[start ? 'startContainer' : 'endContainer'] = container;
        bookmark[start ? 'startOffset' : 'endOffset'] = offset;
      };
      setupEndPoint(true);
      if (!rng.collapsed) {
        setupEndPoint();
      }
      return bookmark;
    };
    var resolveBookmark = function (bookmark) {
      function restoreEndPoint(start) {
        var container, offset, node;
        var nodeIndex = function (container) {
          var node = container.parentNode.firstChild, idx = 0;
          while (node) {
            if (node === container) {
              return idx;
            }
            if (node.nodeType !== 1 || node.getAttribute('data-mce-type') !== 'bookmark') {
              idx++;
            }
            node = node.nextSibling;
          }
          return -1;
        };
        container = node = bookmark[start ? 'startContainer' : 'endContainer'];
        offset = bookmark[start ? 'startOffset' : 'endOffset'];
        if (!container) {
          return;
        }
        if (container.nodeType === 1) {
          offset = nodeIndex(container);
          container = container.parentNode;
          DOM.remove(node);
          if (!container.hasChildNodes() && DOM.isBlock(container)) {
            container.appendChild(DOM.create('br'));
          }
        }
        bookmark[start ? 'startContainer' : 'endContainer'] = container;
        bookmark[start ? 'startOffset' : 'endOffset'] = offset;
      }
      restoreEndPoint(true);
      restoreEndPoint();
      var rng = DOM.createRng();
      rng.setStart(bookmark.startContainer, bookmark.startOffset);
      if (bookmark.endContainer) {
        rng.setEnd(bookmark.endContainer, bookmark.endOffset);
      }
      return Range.normalizeRange(rng);
    };
    var Bookmark = {
      createBookmark: createBookmark,
      resolveBookmark: resolveBookmark
    };

    var noop = function () {
    };
    var constant = function (value) {
      return function () {
        return value;
      };
    };
    var not = function (f) {
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        return !f.apply(null, args);
      };
    };
    var never = constant(false);
    var always = constant(true);

    var none = function () {
      return NONE;
    };
    var NONE = function () {
      var eq = function (o) {
        return o.isNone();
      };
      var call = function (thunk) {
        return thunk();
      };
      var id = function (n) {
        return n;
      };
      var me = {
        fold: function (n, s) {
          return n();
        },
        is: never,
        isSome: never,
        isNone: always,
        getOr: id,
        getOrThunk: call,
        getOrDie: function (msg) {
          throw new Error(msg || 'error: getOrDie called on none.');
        },
        getOrNull: constant(null),
        getOrUndefined: constant(undefined),
        or: id,
        orThunk: call,
        map: none,
        each: noop,
        bind: none,
        exists: never,
        forall: always,
        filter: none,
        equals: eq,
        equals_: eq,
        toArray: function () {
          return [];
        },
        toString: constant('none()')
      };
      if (Object.freeze) {
        Object.freeze(me);
      }
      return me;
    }();
    var some = function (a) {
      var constant_a = constant(a);
      var self = function () {
        return me;
      };
      var bind = function (f) {
        return f(a);
      };
      var me = {
        fold: function (n, s) {
          return s(a);
        },
        is: function (v) {
          return a === v;
        },
        isSome: always,
        isNone: never,
        getOr: constant_a,
        getOrThunk: constant_a,
        getOrDie: constant_a,
        getOrNull: constant_a,
        getOrUndefined: constant_a,
        or: self,
        orThunk: self,
        map: function (f) {
          return some(f(a));
        },
        each: function (f) {
          f(a);
        },
        bind: bind,
        exists: bind,
        forall: bind,
        filter: function (f) {
          return f(a) ? me : NONE;
        },
        toArray: function () {
          return [a];
        },
        toString: function () {
          return 'some(' + a + ')';
        },
        equals: function (o) {
          return o.is(a);
        },
        equals_: function (o, elementEq) {
          return o.fold(never, function (b) {
            return elementEq(a, b);
          });
        }
      };
      return me;
    };
    var from = function (value) {
      return value === null || value === undefined ? NONE : some(value);
    };
    var Option = {
      some: some,
      none: none,
      from: from
    };

    var typeOf = function (x) {
      if (x === null) {
        return 'null';
      }
      var t = typeof x;
      if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
        return 'array';
      }
      if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
        return 'string';
      }
      return t;
    };
    var isType = function (type) {
      return function (value) {
        return typeOf(value) === type;
      };
    };
    var isString = isType('string');
    var isArray = isType('array');
    var isBoolean = isType('boolean');
    var isFunction = isType('function');
    var isNumber = isType('number');

    var nativeSlice = Array.prototype.slice;
    var nativePush = Array.prototype.push;
    var map = function (xs, f) {
      var len = xs.length;
      var r = new Array(len);
      for (var i = 0; i < len; i++) {
        var x = xs[i];
        r[i] = f(x, i);
      }
      return r;
    };
    var each = function (xs, f) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        f(x, i);
      }
    };
    var filter = function (xs, pred) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          r.push(x);
        }
      }
      return r;
    };
    var groupBy = function (xs, f) {
      if (xs.length === 0) {
        return [];
      } else {
        var wasType = f(xs[0]);
        var r = [];
        var group = [];
        for (var i = 0, len = xs.length; i < len; i++) {
          var x = xs[i];
          var type = f(x);
          if (type !== wasType) {
            r.push(group);
            group = [];
          }
          wasType = type;
          group.push(x);
        }
        if (group.length !== 0) {
          r.push(group);
        }
        return r;
      }
    };
    var foldl = function (xs, f, acc) {
      each(xs, function (x) {
        acc = f(acc, x);
      });
      return acc;
    };
    var find = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return Option.some(x);
        }
      }
      return Option.none();
    };
    var flatten = function (xs) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; ++i) {
        if (!isArray(xs[i])) {
          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
        }
        nativePush.apply(r, xs[i]);
      }
      return r;
    };
    var bind = function (xs, f) {
      var output = map(xs, f);
      return flatten(output);
    };
    var reverse = function (xs) {
      var r = nativeSlice.call(xs, 0);
      r.reverse();
      return r;
    };
    var head = function (xs) {
      return xs.length === 0 ? Option.none() : Option.some(xs[0]);
    };
    var last = function (xs) {
      return xs.length === 0 ? Option.none() : Option.some(xs[xs.length - 1]);
    };
    var from$1 = isFunction(Array.from) ? Array.from : function (x) {
      return nativeSlice.call(x);
    };

    var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();

    var path = function (parts, scope) {
      var o = scope !== undefined && scope !== null ? scope : Global;
      for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
        o = o[parts[i]];
      }
      return o;
    };
    var resolve = function (p, scope) {
      var parts = p.split('.');
      return path(parts, scope);
    };

    var unsafe = function (name, scope) {
      return resolve(name, scope);
    };
    var getOrDie = function (name, scope) {
      var actual = unsafe(name, scope);
      if (actual === undefined || actual === null) {
        throw new Error(name + ' not available on this browser');
      }
      return actual;
    };
    var Global$1 = { getOrDie: getOrDie };

    var htmlElement = function (scope) {
      return Global$1.getOrDie('HTMLElement', scope);
    };
    var isPrototypeOf = function (x) {
      var scope = resolve('ownerDocument.defaultView', x);
      return htmlElement(scope).prototype.isPrototypeOf(x);
    };
    var HTMLElement = { isPrototypeOf: isPrototypeOf };

    var global$7 = tinymce.util.Tools.resolve('tinymce.dom.DomQuery');

    var getParentList = function (editor) {
      var selectionStart = editor.selection.getStart(true);
      return editor.dom.getParent(selectionStart, 'OL,UL,DL', getClosestListRootElm(editor, selectionStart));
    };
    var isParentListSelected = function (parentList, selectedBlocks) {
      return parentList && selectedBlocks.length === 1 && selectedBlocks[0] === parentList;
    };
    var findSubLists = function (parentList) {
      return global$5.grep(parentList.querySelectorAll('ol,ul,dl'), function (elm) {
        return NodeType.isListNode(elm);
      });
    };
    var getSelectedSubLists = function (editor) {
      var parentList = getParentList(editor);
      var selectedBlocks = editor.selection.getSelectedBlocks();
      if (isParentListSelected(parentList, selectedBlocks)) {
        return findSubLists(parentList);
      } else {
        return global$5.grep(selectedBlocks, function (elm) {
          return NodeType.isListNode(elm) && parentList !== elm;
        });
      }
    };
    var findParentListItemsNodes = function (editor, elms) {
      var listItemsElms = global$5.map(elms, function (elm) {
        var parentLi = editor.dom.getParent(elm, 'li,dd,dt', getClosestListRootElm(editor, elm));
        return parentLi ? parentLi : elm;
      });
      return global$7.unique(listItemsElms);
    };
    var getSelectedListItems = function (editor) {
      var selectedBlocks = editor.selection.getSelectedBlocks();
      return global$5.grep(findParentListItemsNodes(editor, selectedBlocks), function (block) {
        return NodeType.isListItemNode(block);
      });
    };
    var getSelectedDlItems = function (editor) {
      return filter(getSelectedListItems(editor), NodeType.isDlItemNode);
    };
    var getClosestListRootElm = function (editor, elm) {
      var parentTableCell = editor.dom.getParents(elm, 'TD,TH');
      var root = parentTableCell.length > 0 ? parentTableCell[0] : editor.getBody();
      return root;
    };
    var findLastParentListNode = function (editor, elm) {
      var parentLists = editor.dom.getParents(elm, 'ol,ul', getClosestListRootElm(editor, elm));
      return last(parentLists);
    };
    var getSelectedLists = function (editor) {
      var firstList = findLastParentListNode(editor, editor.selection.getStart());
      var subsequentLists = filter(editor.selection.getSelectedBlocks(), NodeType.isOlUlNode);
      return firstList.toArray().concat(subsequentLists);
    };
    var getSelectedListRoots = function (editor) {
      var selectedLists = getSelectedLists(editor);
      return getUniqueListRoots(editor, selectedLists);
    };
    var getUniqueListRoots = function (editor, lists) {
      var listRoots = map(lists, function (list) {
        return findLastParentListNode(editor, list).getOr(list);
      });
      return global$7.unique(listRoots);
    };
    var isList = function (editor) {
      var list = getParentList(editor);
      return HTMLElement.isPrototypeOf(list);
    };
    var Selection = {
      isList: isList,
      getParentList: getParentList,
      getSelectedSubLists: getSelectedSubLists,
      getSelectedListItems: getSelectedListItems,
      getClosestListRootElm: getClosestListRootElm,
      getSelectedDlItems: getSelectedDlItems,
      getSelectedListRoots: getSelectedListRoots
    };

    var fromHtml = function (html, scope) {
      var doc = scope || domGlobals.document;
      var div = doc.createElement('div');
      div.innerHTML = html;
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
        domGlobals.console.error('HTML does not have a single root node', html);
        throw new Error('HTML must have a single root node');
      }
      return fromDom(div.childNodes[0]);
    };
    var fromTag = function (tag, scope) {
      var doc = scope || domGlobals.document;
      var node = doc.createElement(tag);
      return fromDom(node);
    };
    var fromText = function (text, scope) {
      var doc = scope || domGlobals.document;
      var node = doc.createTextNode(text);
      return fromDom(node);
    };
    var fromDom = function (node) {
      if (node === null || node === undefined) {
        throw new Error('Node cannot be null or undefined');
      }
      return { dom: constant(node) };
    };
    var fromPoint = function (docElm, x, y) {
      var doc = docElm.dom();
      return Option.from(doc.elementFromPoint(x, y)).map(fromDom);
    };
    var Element = {
      fromHtml: fromHtml,
      fromTag: fromTag,
      fromText: fromText,
      fromDom: fromDom,
      fromPoint: fromPoint
    };

    var lift2 = function (oa, ob, f) {
      return oa.isSome() && ob.isSome() ? Option.some(f(oa.getOrDie(), ob.getOrDie())) : Option.none();
    };

    var fromElements = function (elements, scope) {
      var doc = scope || domGlobals.document;
      var fragment = doc.createDocumentFragment();
      each(elements, function (element) {
        fragment.appendChild(element.dom());
      });
      return Element.fromDom(fragment);
    };

    var Immutable = function () {
      var fields = [];
      for (var _i = 0; _i < arguments.length; _i++) {
        fields[_i] = arguments[_i];
      }
      return function () {
        var values = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          values[_i] = arguments[_i];
        }
        if (fields.length !== values.length) {
          throw new Error('Wrong number of arguments to struct. Expected "[' + fields.length + ']", got ' + values.length + ' arguments');
        }
        var struct = {};
        each(fields, function (name, i) {
          struct[name] = constant(values[i]);
        });
        return struct;
      };
    };

    var keys = Object.keys;
    var each$1 = function (obj, f) {
      var props = keys(obj);
      for (var k = 0, len = props.length; k < len; k++) {
        var i = props[k];
        var x = obj[i];
        f(x, i);
      }
    };

    var node = function () {
      var f = Global$1.getOrDie('Node');
      return f;
    };
    var compareDocumentPosition = function (a, b, match) {
      return (a.compareDocumentPosition(b) & match) !== 0;
    };
    var documentPositionPreceding = function (a, b) {
      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_PRECEDING);
    };
    var documentPositionContainedBy = function (a, b) {
      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_CONTAINED_BY);
    };
    var Node = {
      documentPositionPreceding: documentPositionPreceding,
      documentPositionContainedBy: documentPositionContainedBy
    };

    var cached = function (f) {
      var called = false;
      var r;
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        if (!called) {
          called = true;
          r = f.apply(null, args);
        }
        return r;
      };
    };

    var firstMatch = function (regexes, s) {
      for (var i = 0; i < regexes.length; i++) {
        var x = regexes[i];
        if (x.test(s)) {
          return x;
        }
      }
      return undefined;
    };
    var find$1 = function (regexes, agent) {
      var r = firstMatch(regexes, agent);
      if (!r) {
        return {
          major: 0,
          minor: 0
        };
      }
      var group = function (i) {
        return Number(agent.replace(r, '$' + i));
      };
      return nu(group(1), group(2));
    };
    var detect = function (versionRegexes, agent) {
      var cleanedAgent = String(agent).toLowerCase();
      if (versionRegexes.length === 0) {
        return unknown();
      }
      return find$1(versionRegexes, cleanedAgent);
    };
    var unknown = function () {
      return nu(0, 0);
    };
    var nu = function (major, minor) {
      return {
        major: major,
        minor: minor
      };
    };
    var Version = {
      nu: nu,
      detect: detect,
      unknown: unknown
    };

    var edge = 'Edge';
    var chrome = 'Chrome';
    var ie = 'IE';
    var opera = 'Opera';
    var firefox = 'Firefox';
    var safari = 'Safari';
    var isBrowser = function (name, current) {
      return function () {
        return current === name;
      };
    };
    var unknown$1 = function () {
      return nu$1({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$1 = function (info) {
      var current = info.current;
      var version = info.version;
      return {
        current: current,
        version: version,
        isEdge: isBrowser(edge, current),
        isChrome: isBrowser(chrome, current),
        isIE: isBrowser(ie, current),
        isOpera: isBrowser(opera, current),
        isFirefox: isBrowser(firefox, current),
        isSafari: isBrowser(safari, current)
      };
    };
    var Browser = {
      unknown: unknown$1,
      nu: nu$1,
      edge: constant(edge),
      chrome: constant(chrome),
      ie: constant(ie),
      opera: constant(opera),
      firefox: constant(firefox),
      safari: constant(safari)
    };

    var windows = 'Windows';
    var ios = 'iOS';
    var android = 'Android';
    var linux = 'Linux';
    var osx = 'OSX';
    var solaris = 'Solaris';
    var freebsd = 'FreeBSD';
    var isOS = function (name, current) {
      return function () {
        return current === name;
      };
    };
    var unknown$2 = function () {
      return nu$2({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$2 = function (info) {
      var current = info.current;
      var version = info.version;
      return {
        current: current,
        version: version,
        isWindows: isOS(windows, current),
        isiOS: isOS(ios, current),
        isAndroid: isOS(android, current),
        isOSX: isOS(osx, current),
        isLinux: isOS(linux, current),
        isSolaris: isOS(solaris, current),
        isFreeBSD: isOS(freebsd, current)
      };
    };
    var OperatingSystem = {
      unknown: unknown$2,
      nu: nu$2,
      windows: constant(windows),
      ios: constant(ios),
      android: constant(android),
      linux: constant(linux),
      osx: constant(osx),
      solaris: constant(solaris),
      freebsd: constant(freebsd)
    };

    var DeviceType = function (os, browser, userAgent) {
      var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
      var isiPhone = os.isiOS() && !isiPad;
      var isAndroid3 = os.isAndroid() && os.version.major === 3;
      var isAndroid4 = os.isAndroid() && os.version.major === 4;
      var isTablet = isiPad || isAndroid3 || isAndroid4 && /mobile/i.test(userAgent) === true;
      var isTouch = os.isiOS() || os.isAndroid();
      var isPhone = isTouch && !isTablet;
      var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
      return {
        isiPad: constant(isiPad),
        isiPhone: constant(isiPhone),
        isTablet: constant(isTablet),
        isPhone: constant(isPhone),
        isTouch: constant(isTouch),
        isAndroid: os.isAndroid,
        isiOS: os.isiOS,
        isWebView: constant(iOSwebview)
      };
    };

    var detect$1 = function (candidates, userAgent) {
      var agent = String(userAgent).toLowerCase();
      return find(candidates, function (candidate) {
        return candidate.search(agent);
      });
    };
    var detectBrowser = function (browsers, userAgent) {
      return detect$1(browsers, userAgent).map(function (browser) {
        var version = Version.detect(browser.versionRegexes, userAgent);
        return {
          current: browser.name,
          version: version
        };
      });
    };
    var detectOs = function (oses, userAgent) {
      return detect$1(oses, userAgent).map(function (os) {
        var version = Version.detect(os.versionRegexes, userAgent);
        return {
          current: os.name,
          version: version
        };
      });
    };
    var UaString = {
      detectBrowser: detectBrowser,
      detectOs: detectOs
    };

    var contains = function (str, substr) {
      return str.indexOf(substr) !== -1;
    };

    var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
    var checkContains = function (target) {
      return function (uastring) {
        return contains(uastring, target);
      };
    };
    var browsers = [
      {
        name: 'Edge',
        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
        search: function (uastring) {
          return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
        }
      },
      {
        name: 'Chrome',
        versionRegexes: [
          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
          normalVersionRegex
        ],
        search: function (uastring) {
          return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
        }
      },
      {
        name: 'IE',
        versionRegexes: [
          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
          /.*?rv:([0-9]+)\.([0-9]+).*/
        ],
        search: function (uastring) {
          return contains(uastring, 'msie') || contains(uastring, 'trident');
        }
      },
      {
        name: 'Opera',
        versionRegexes: [
          normalVersionRegex,
          /.*?opera\/([0-9]+)\.([0-9]+).*/
        ],
        search: checkContains('opera')
      },
      {
        name: 'Firefox',
        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
        search: checkContains('firefox')
      },
      {
        name: 'Safari',
        versionRegexes: [
          normalVersionRegex,
          /.*?cpu os ([0-9]+)_([0-9]+).*/
        ],
        search: function (uastring) {
          return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
        }
      }
    ];
    var oses = [
      {
        name: 'Windows',
        search: checkContains('win'),
        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'iOS',
        search: function (uastring) {
          return contains(uastring, 'iphone') || contains(uastring, 'ipad');
        },
        versionRegexes: [
          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
          /.*cpu os ([0-9]+)_([0-9]+).*/,
          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
        ]
      },
      {
        name: 'Android',
        search: checkContains('android'),
        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'OSX',
        search: checkContains('os x'),
        versionRegexes: [/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]
      },
      {
        name: 'Linux',
        search: checkContains('linux'),
        versionRegexes: []
      },
      {
        name: 'Solaris',
        search: checkContains('sunos'),
        versionRegexes: []
      },
      {
        name: 'FreeBSD',
        search: checkContains('freebsd'),
        versionRegexes: []
      }
    ];
    var PlatformInfo = {
      browsers: constant(browsers),
      oses: constant(oses)
    };

    var detect$2 = function (userAgent) {
      var browsers = PlatformInfo.browsers();
      var oses = PlatformInfo.oses();
      var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu);
      var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
      var deviceType = DeviceType(os, browser, userAgent);
      return {
        browser: browser,
        os: os,
        deviceType: deviceType
      };
    };
    var PlatformDetection = { detect: detect$2 };

    var detect$3 = cached(function () {
      var userAgent = domGlobals.navigator.userAgent;
      return PlatformDetection.detect(userAgent);
    });
    var PlatformDetection$1 = { detect: detect$3 };

    var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE;
    var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE;
    var COMMENT = domGlobals.Node.COMMENT_NODE;
    var DOCUMENT = domGlobals.Node.DOCUMENT_NODE;
    var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE;
    var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE;
    var ELEMENT = domGlobals.Node.ELEMENT_NODE;
    var TEXT = domGlobals.Node.TEXT_NODE;
    var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE;
    var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE;
    var ENTITY = domGlobals.Node.ENTITY_NODE;
    var NOTATION = domGlobals.Node.NOTATION_NODE;

    var ELEMENT$1 = ELEMENT;
    var is = function (element, selector) {
      var dom = element.dom();
      if (dom.nodeType !== ELEMENT$1) {
        return false;
      } else {
        var elem = dom;
        if (elem.matches !== undefined) {
          return elem.matches(selector);
        } else if (elem.msMatchesSelector !== undefined) {
          return elem.msMatchesSelector(selector);
        } else if (elem.webkitMatchesSelector !== undefined) {
          return elem.webkitMatchesSelector(selector);
        } else if (elem.mozMatchesSelector !== undefined) {
          return elem.mozMatchesSelector(selector);
        } else {
          throw new Error('Browser lacks native selectors');
        }
      }
    };

    var eq = function (e1, e2) {
      return e1.dom() === e2.dom();
    };
    var regularContains = function (e1, e2) {
      var d1 = e1.dom();
      var d2 = e2.dom();
      return d1 === d2 ? false : d1.contains(d2);
    };
    var ieContains = function (e1, e2) {
      return Node.documentPositionContainedBy(e1.dom(), e2.dom());
    };
    var browser = PlatformDetection$1.detect().browser;
    var contains$1 = browser.isIE() ? ieContains : regularContains;
    var is$1 = is;

    var parent = function (element) {
      return Option.from(element.dom().parentNode).map(Element.fromDom);
    };
    var children = function (element) {
      return map(element.dom().childNodes, Element.fromDom);
    };
    var child = function (element, index) {
      var cs = element.dom().childNodes;
      return Option.from(cs[index]).map(Element.fromDom);
    };
    var firstChild = function (element) {
      return child(element, 0);
    };
    var lastChild = function (element) {
      return child(element, element.dom().childNodes.length - 1);
    };
    var spot = Immutable('element', 'offset');

    var before = function (marker, element) {
      var parent$1 = parent(marker);
      parent$1.each(function (v) {
        v.dom().insertBefore(element.dom(), marker.dom());
      });
    };
    var append = function (parent, element) {
      parent.dom().appendChild(element.dom());
    };

    var before$1 = function (marker, elements) {
      each(elements, function (x) {
        before(marker, x);
      });
    };
    var append$1 = function (parent, elements) {
      each(elements, function (x) {
        append(parent, x);
      });
    };

    var remove = function (element) {
      var dom = element.dom();
      if (dom.parentNode !== null) {
        dom.parentNode.removeChild(dom);
      }
    };

    var name = function (element) {
      var r = element.dom().nodeName;
      return r.toLowerCase();
    };
    var type = function (element) {
      return element.dom().nodeType;
    };
    var isType$1 = function (t) {
      return function (element) {
        return type(element) === t;
      };
    };
    var isElement = isType$1(ELEMENT);

    var rawSet = function (dom, key, value) {
      if (isString(value) || isBoolean(value) || isNumber(value)) {
        dom.setAttribute(key, value + '');
      } else {
        domGlobals.console.error('Invalid call to Attr.set. Key ', key, ':: Value ', value, ':: Element ', dom);
        throw new Error('Attribute value was not simple');
      }
    };
    var setAll = function (element, attrs) {
      var dom = element.dom();
      each$1(attrs, function (v, k) {
        rawSet(dom, k, v);
      });
    };
    var clone = function (element) {
      return foldl(element.dom().attributes, function (acc, attr) {
        acc[attr.name] = attr.value;
        return acc;
      }, {});
    };

    var isSupported = function (dom) {
      return dom.style !== undefined && isFunction(dom.style.getPropertyValue);
    };

    var internalSet = function (dom, property, value) {
      if (!isString(value)) {
        domGlobals.console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
        throw new Error('CSS value must be a string: ' + value);
      }
      if (isSupported(dom)) {
        dom.style.setProperty(property, value);
      }
    };
    var set = function (element, property, value) {
      var dom = element.dom();
      internalSet(dom, property, value);
    };

    var clone$1 = function (original, isDeep) {
      return Element.fromDom(original.dom().cloneNode(isDeep));
    };
    var deep = function (original) {
      return clone$1(original, true);
    };
    var shallowAs = function (original, tag) {
      var nu = Element.fromTag(tag);
      var attributes = clone(original);
      setAll(nu, attributes);
      return nu;
    };
    var mutate = function (original, tag) {
      var nu = shallowAs(original, tag);
      before(original, nu);
      var children$1 = children(original);
      append$1(nu, children$1);
      remove(original);
      return nu;
    };

    var joinSegment = function (parent, child) {
      append(parent.item, child.list);
    };
    var joinSegments = function (segments) {
      for (var i = 1; i < segments.length; i++) {
        joinSegment(segments[i - 1], segments[i]);
      }
    };
    var appendSegments = function (head$1, tail) {
      lift2(last(head$1), head(tail), joinSegment);
    };
    var createSegment = function (scope, listType) {
      var segment = {
        list: Element.fromTag(listType, scope),
        item: Element.fromTag('li', scope)
      };
      append(segment.list, segment.item);
      return segment;
    };
    var createSegments = function (scope, entry, size) {
      var segments = [];
      for (var i = 0; i < size; i++) {
        segments.push(createSegment(scope, entry.listType));
      }
      return segments;
    };
    var populateSegments = function (segments, entry) {
      for (var i = 0; i < segments.length - 1; i++) {
        set(segments[i].item, 'list-style-type', 'none');
      }
      last(segments).each(function (segment) {
        setAll(segment.list, entry.listAttributes);
        setAll(segment.item, entry.itemAttributes);
        append$1(segment.item, entry.content);
      });
    };
    var normalizeSegment = function (segment, entry) {
      if (name(segment.list) !== entry.listType) {
        segment.list = mutate(segment.list, entry.listType);
      }
      setAll(segment.list, entry.listAttributes);
    };
    var createItem = function (scope, attr, content) {
      var item = Element.fromTag('li', scope);
      setAll(item, attr);
      append$1(item, content);
      return item;
    };
    var appendItem = function (segment, item) {
      append(segment.list, item);
      segment.item = item;
    };
    var writeShallow = function (scope, cast, entry) {
      var newCast = cast.slice(0, entry.depth);
      last(newCast).each(function (segment) {
        var item = createItem(scope, entry.itemAttributes, entry.content);
        appendItem(segment, item);
        normalizeSegment(segment, entry);
      });
      return newCast;
    };
    var writeDeep = function (scope, cast, entry) {
      var segments = createSegments(scope, entry, entry.depth - cast.length);
      joinSegments(segments);
      populateSegments(segments, entry);
      appendSegments(cast, segments);
      return cast.concat(segments);
    };
    var composeList = function (scope, entries) {
      var cast = foldl(entries, function (cast, entry) {
        return entry.depth > cast.length ? writeDeep(scope, cast, entry) : writeShallow(scope, cast, entry);
      }, []);
      return head(cast).map(function (segment) {
        return segment.list;
      });
    };

    var isList$1 = function (el) {
      return is$1(el, 'OL,UL');
    };
    var hasFirstChildList = function (el) {
      return firstChild(el).map(isList$1).getOr(false);
    };
    var hasLastChildList = function (el) {
      return lastChild(el).map(isList$1).getOr(false);
    };

    var isIndented = function (entry) {
      return entry.depth > 0;
    };
    var isSelected = function (entry) {
      return entry.isSelected;
    };
    var cloneItemContent = function (li) {
      var children$1 = children(li);
      var content = hasLastChildList(li) ? children$1.slice(0, -1) : children$1;
      return map(content, deep);
    };
    var createEntry = function (li, depth, isSelected) {
      return parent(li).filter(isElement).map(function (list) {
        return {
          depth: depth,
          isSelected: isSelected,
          content: cloneItemContent(li),
          itemAttributes: clone(li),
          listAttributes: clone(list),
          listType: name(list)
        };
      });
    };

    var indentEntry = function (indentation, entry) {
      switch (indentation) {
      case 'Indent':
        entry.depth++;
        break;
      case 'Outdent':
        entry.depth--;
        break;
      case 'Flatten':
        entry.depth = 0;
      }
    };

    var hasOwnProperty = Object.prototype.hasOwnProperty;
    var shallow = function (old, nu) {
      return nu;
    };
    var baseMerge = function (merger) {
      return function () {
        var objects = new Array(arguments.length);
        for (var i = 0; i < objects.length; i++) {
          objects[i] = arguments[i];
        }
        if (objects.length === 0) {
          throw new Error('Can\'t merge zero objects');
        }
        var ret = {};
        for (var j = 0; j < objects.length; j++) {
          var curObject = objects[j];
          for (var key in curObject) {
            if (hasOwnProperty.call(curObject, key)) {
              ret[key] = merger(ret[key], curObject[key]);
            }
          }
        }
        return ret;
      };
    };
    var merge = baseMerge(shallow);

    var cloneListProperties = function (target, source) {
      target.listType = source.listType;
      target.listAttributes = merge({}, source.listAttributes);
    };
    var previousSiblingEntry = function (entries, start) {
      var depth = entries[start].depth;
      for (var i = start - 1; i >= 0; i--) {
        if (entries[i].depth === depth) {
          return Option.some(entries[i]);
        }
        if (entries[i].depth < depth) {
          break;
        }
      }
      return Option.none();
    };
    var normalizeEntries = function (entries) {
      each(entries, function (entry, i) {
        previousSiblingEntry(entries, i).each(function (matchingEntry) {
          cloneListProperties(entry, matchingEntry);
        });
      });
    };

    var Cell = function (initial) {
      var value = initial;
      var get = function () {
        return value;
      };
      var set = function (v) {
        value = v;
      };
      var clone = function () {
        return Cell(get());
      };
      return {
        get: get,
        set: set,
        clone: clone
      };
    };

    var parseItem = function (depth, itemSelection, selectionState, item) {
      return firstChild(item).filter(isList$1).fold(function () {
        itemSelection.each(function (selection) {
          if (eq(selection.start, item)) {
            selectionState.set(true);
          }
        });
        var currentItemEntry = createEntry(item, depth, selectionState.get());
        itemSelection.each(function (selection) {
          if (eq(selection.end, item)) {
            selectionState.set(false);
          }
        });
        var childListEntries = lastChild(item).filter(isList$1).map(function (list) {
          return parseList(depth, itemSelection, selectionState, list);
        }).getOr([]);
        return currentItemEntry.toArray().concat(childListEntries);
      }, function (list) {
        return parseList(depth, itemSelection, selectionState, list);
      });
    };
    var parseList = function (depth, itemSelection, selectionState, list) {
      return bind(children(list), function (element) {
        var parser = isList$1(element) ? parseList : parseItem;
        var newDepth = depth + 1;
        return parser(newDepth, itemSelection, selectionState, element);
      });
    };
    var parseLists = function (lists, itemSelection) {
      var selectionState = Cell(false);
      var initialDepth = 0;
      return map(lists, function (list) {
        return {
          sourceList: list,
          entries: parseList(initialDepth, itemSelection, selectionState, list)
        };
      });
    };

    var global$8 = tinymce.util.Tools.resolve('tinymce.Env');

    var createTextBlock = function (editor, contentNode) {
      var dom = editor.dom;
      var blockElements = editor.schema.getBlockElements();
      var fragment = dom.createFragment();
      var node, textBlock, blockName, hasContentNode;
      if (editor.settings.forced_root_block) {
        blockName = editor.settings.forced_root_block;
      }
      if (blockName) {
        textBlock = dom.create(blockName);
        if (textBlock.tagName === editor.settings.forced_root_block) {
          dom.setAttribs(textBlock, editor.settings.forced_root_block_attrs);
        }
        if (!NodeType.isBlock(contentNode.firstChild, blockElements)) {
          fragment.appendChild(textBlock);
        }
      }
      if (contentNode) {
        while (node = contentNode.firstChild) {
          var nodeName = node.nodeName;
          if (!hasContentNode && (nodeName !== 'SPAN' || node.getAttribute('data-mce-type') !== 'bookmark')) {
            hasContentNode = true;
          }
          if (NodeType.isBlock(node, blockElements)) {
            fragment.appendChild(node);
            textBlock = null;
          } else {
            if (blockName) {
              if (!textBlock) {
                textBlock = dom.create(blockName);
                fragment.appendChild(textBlock);
              }
              textBlock.appendChild(node);
            } else {
              fragment.appendChild(node);
            }
          }
        }
      }
      if (!editor.settings.forced_root_block) {
        fragment.appendChild(dom.create('br'));
      } else {
        if (!hasContentNode && (!global$8.ie || global$8.ie > 10)) {
          textBlock.appendChild(dom.create('br', { 'data-mce-bogus': '1' }));
        }
      }
      return fragment;
    };

    var outdentedComposer = function (editor, entries) {
      return map(entries, function (entry) {
        var content = fromElements(entry.content);
        return Element.fromDom(createTextBlock(editor, content.dom()));
      });
    };
    var indentedComposer = function (editor, entries) {
      normalizeEntries(entries);
      return composeList(editor.contentDocument, entries).toArray();
    };
    var composeEntries = function (editor, entries) {
      return bind(groupBy(entries, isIndented), function (entries) {
        var groupIsIndented = head(entries).map(isIndented).getOr(false);
        return groupIsIndented ? indentedComposer(editor, entries) : outdentedComposer(editor, entries);
      });
    };
    var indentSelectedEntries = function (entries, indentation) {
      each(filter(entries, isSelected), function (entry) {
        return indentEntry(indentation, entry);
      });
    };
    var getItemSelection = function (editor) {
      var selectedListItems = map(Selection.getSelectedListItems(editor), Element.fromDom);
      return lift2(find(selectedListItems, not(hasFirstChildList)), find(reverse(selectedListItems), not(hasFirstChildList)), function (start, end) {
        return {
          start: start,
          end: end
        };
      });
    };
    var listsIndentation = function (editor, lists, indentation) {
      var entrySets = parseLists(lists, getItemSelection(editor));
      each(entrySets, function (entrySet) {
        indentSelectedEntries(entrySet.entries, indentation);
        before$1(entrySet.sourceList, composeEntries(editor, entrySet.entries));
        remove(entrySet.sourceList);
      });
    };

    var DOM$1 = global$6.DOM;
    var splitList = function (editor, ul, li) {
      var tmpRng, fragment, bookmarks, node, newBlock;
      var removeAndKeepBookmarks = function (targetNode) {
        global$5.each(bookmarks, function (node) {
          targetNode.parentNode.insertBefore(node, li.parentNode);
        });
        DOM$1.remove(targetNode);
      };
      bookmarks = DOM$1.select('span[data-mce-type="bookmark"]', ul);
      newBlock = createTextBlock(editor, li);
      tmpRng = DOM$1.createRng();
      tmpRng.setStartAfter(li);
      tmpRng.setEndAfter(ul);
      fragment = tmpRng.extractContents();
      for (node = fragment.firstChild; node; node = node.firstChild) {
        if (node.nodeName === 'LI' && editor.dom.isEmpty(node)) {
          DOM$1.remove(node);
          break;
        }
      }
      if (!editor.dom.isEmpty(fragment)) {
        DOM$1.insertAfter(fragment, ul);
      }
      DOM$1.insertAfter(newBlock, ul);
      if (NodeType.isEmpty(editor.dom, li.parentNode)) {
        removeAndKeepBookmarks(li.parentNode);
      }
      DOM$1.remove(li);
      if (NodeType.isEmpty(editor.dom, ul)) {
        DOM$1.remove(ul);
      }
    };
    var SplitList = { splitList: splitList };

    var outdentDlItem = function (editor, item) {
      if (is$1(item, 'dd')) {
        mutate(item, 'dt');
      } else if (is$1(item, 'dt')) {
        parent(item).each(function (dl) {
          return SplitList.splitList(editor, dl.dom(), item.dom());
        });
      }
    };
    var indentDlItem = function (item) {
      if (is$1(item, 'dt')) {
        mutate(item, 'dd');
      }
    };
    var dlIndentation = function (editor, indentation, dlItems) {
      if (indentation === 'Indent') {
        each(dlItems, indentDlItem);
      } else {
        each(dlItems, function (item) {
          return outdentDlItem(editor, item);
        });
      }
    };

    var selectionIndentation = function (editor, indentation) {
      var lists = map(Selection.getSelectedListRoots(editor), Element.fromDom);
      var dlItems = map(Selection.getSelectedDlItems(editor), Element.fromDom);
      var isHandled = false;
      if (lists.length || dlItems.length) {
        var bookmark = editor.selection.getBookmark();
        listsIndentation(editor, lists, indentation);
        dlIndentation(editor, indentation, dlItems);
        editor.selection.moveToBookmark(bookmark);
        editor.selection.setRng(Range.normalizeRange(editor.selection.getRng()));
        editor.nodeChanged();
        isHandled = true;
      }
      return isHandled;
    };
    var indentListSelection = function (editor) {
      return selectionIndentation(editor, 'Indent');
    };
    var outdentListSelection = function (editor) {
      return selectionIndentation(editor, 'Outdent');
    };
    var flattenListSelection = function (editor) {
      return selectionIndentation(editor, 'Flatten');
    };

    var updateListStyle = function (dom, el, detail) {
      var type = detail['list-style-type'] ? detail['list-style-type'] : null;
      dom.setStyle(el, 'list-style-type', type);
    };
    var setAttribs = function (elm, attrs) {
      global$5.each(attrs, function (value, key) {
        elm.setAttribute(key, value);
      });
    };
    var updateListAttrs = function (dom, el, detail) {
      setAttribs(el, detail['list-attributes']);
      global$5.each(dom.select('li', el), function (li) {
        setAttribs(li, detail['list-item-attributes']);
      });
    };
    var updateListWithDetails = function (dom, el, detail) {
      updateListStyle(dom, el, detail);
      updateListAttrs(dom, el, detail);
    };
    var removeStyles = function (dom, element, styles) {
      global$5.each(styles, function (style) {
        var _a;
        return dom.setStyle(element, (_a = {}, _a[style] = '', _a));
      });
    };
    var getEndPointNode = function (editor, rng, start, root) {
      var container, offset;
      container = rng[start ? 'startContainer' : 'endContainer'];
      offset = rng[start ? 'startOffset' : 'endOffset'];
      if (container.nodeType === 1) {
        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
      }
      if (!start && NodeType.isBr(container.nextSibling)) {
        container = container.nextSibling;
      }
      while (container.parentNode !== root) {
        if (NodeType.isTextBlock(editor, container)) {
          return container;
        }
        if (/^(TD|TH)$/.test(container.parentNode.nodeName)) {
          return container;
        }
        container = container.parentNode;
      }
      return container;
    };
    var getSelectedTextBlocks = function (editor, rng, root) {
      var textBlocks = [], dom = editor.dom;
      var startNode = getEndPointNode(editor, rng, true, root);
      var endNode = getEndPointNode(editor, rng, false, root);
      var block;
      var siblings = [];
      for (var node = startNode; node; node = node.nextSibling) {
        siblings.push(node);
        if (node === endNode) {
          break;
        }
      }
      global$5.each(siblings, function (node) {
        if (NodeType.isTextBlock(editor, node)) {
          textBlocks.push(node);
          block = null;
          return;
        }
        if (dom.isBlock(node) || NodeType.isBr(node)) {
          if (NodeType.isBr(node)) {
            dom.remove(node);
          }
          block = null;
          return;
        }
        var nextSibling = node.nextSibling;
        if (global$4.isBookmarkNode(node)) {
          if (NodeType.isTextBlock(editor, nextSibling) || !nextSibling && node.parentNode === root) {
            block = null;
            return;
          }
        }
        if (!block) {
          block = dom.create('p');
          node.parentNode.insertBefore(block, node);
          textBlocks.push(block);
        }
        block.appendChild(node);
      });
      return textBlocks;
    };
    var hasCompatibleStyle = function (dom, sib, detail) {
      var sibStyle = dom.getStyle(sib, 'list-style-type');
      var detailStyle = detail ? detail['list-style-type'] : '';
      detailStyle = detailStyle === null ? '' : detailStyle;
      return sibStyle === detailStyle;
    };
    var applyList = function (editor, listName, detail) {
      if (detail === void 0) {
        detail = {};
      }
      var rng = editor.selection.getRng(true);
      var bookmark;
      var listItemName = 'LI';
      var root = Selection.getClosestListRootElm(editor, editor.selection.getStart(true));
      var dom = editor.dom;
      if (dom.getContentEditable(editor.selection.getNode()) === 'false') {
        return;
      }
      listName = listName.toUpperCase();
      if (listName === 'DL') {
        listItemName = 'DT';
      }
      bookmark = Bookmark.createBookmark(rng);
      global$5.each(getSelectedTextBlocks(editor, rng, root), function (block) {
        var listBlock, sibling;
        sibling = block.previousSibling;
        if (sibling && NodeType.isListNode(sibling) && sibling.nodeName === listName && hasCompatibleStyle(dom, sibling, detail)) {
          listBlock = sibling;
          block = dom.rename(block, listItemName);
          sibling.appendChild(block);
        } else {
          listBlock = dom.create(listName);
          block.parentNode.insertBefore(listBlock, block);
          listBlock.appendChild(block);
          block = dom.rename(block, listItemName);
        }
        removeStyles(dom, block, [
          'margin',
          'margin-right',
          'margin-bottom',
          'margin-left',
          'margin-top',
          'padding',
          'padding-right',
          'padding-bottom',
          'padding-left',
          'padding-top'
        ]);
        updateListWithDetails(dom, listBlock, detail);
        mergeWithAdjacentLists(editor.dom, listBlock);
      });
      editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
    };
    var isValidLists = function (list1, list2) {
      return list1 && list2 && NodeType.isListNode(list1) && list1.nodeName === list2.nodeName;
    };
    var hasSameListStyle = function (dom, list1, list2) {
      var targetStyle = dom.getStyle(list1, 'list-style-type', true);
      var style = dom.getStyle(list2, 'list-style-type', true);
      return targetStyle === style;
    };
    var hasSameClasses = function (elm1, elm2) {
      return elm1.className === elm2.className;
    };
    var shouldMerge = function (dom, list1, list2) {
      return isValidLists(list1, list2) && hasSameListStyle(dom, list1, list2) && hasSameClasses(list1, list2);
    };
    var mergeWithAdjacentLists = function (dom, listBlock) {
      var sibling, node;
      sibling = listBlock.nextSibling;
      if (shouldMerge(dom, listBlock, sibling)) {
        while (node = sibling.firstChild) {
          listBlock.appendChild(node);
        }
        dom.remove(sibling);
      }
      sibling = listBlock.previousSibling;
      if (shouldMerge(dom, listBlock, sibling)) {
        while (node = sibling.lastChild) {
          listBlock.insertBefore(node, listBlock.firstChild);
        }
        dom.remove(sibling);
      }
    };
    var updateList = function (dom, list, listName, detail) {
      if (list.nodeName !== listName) {
        var newList = dom.rename(list, listName);
        updateListWithDetails(dom, newList, detail);
      } else {
        updateListWithDetails(dom, list, detail);
      }
    };
    var toggleMultipleLists = function (editor, parentList, lists, listName, detail) {
      if (parentList.nodeName === listName && !hasListStyleDetail(detail)) {
        flattenListSelection(editor);
      } else {
        var bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
        global$5.each([parentList].concat(lists), function (elm) {
          updateList(editor.dom, elm, listName, detail);
        });
        editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
      }
    };
    var hasListStyleDetail = function (detail) {
      return 'list-style-type' in detail;
    };
    var toggleSingleList = function (editor, parentList, listName, detail) {
      if (parentList === editor.getBody()) {
        return;
      }
      if (parentList) {
        if (parentList.nodeName === listName && !hasListStyleDetail(detail)) {
          flattenListSelection(editor);
        } else {
          var bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
          updateListWithDetails(editor.dom, parentList, detail);
          mergeWithAdjacentLists(editor.dom, editor.dom.rename(parentList, listName));
          editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
        }
      } else {
        applyList(editor, listName, detail);
      }
    };
    var toggleList = function (editor, listName, detail) {
      var parentList = Selection.getParentList(editor);
      var selectedSubLists = Selection.getSelectedSubLists(editor);
      detail = detail ? detail : {};
      if (parentList && selectedSubLists.length > 0) {
        toggleMultipleLists(editor, parentList, selectedSubLists, listName, detail);
      } else {
        toggleSingleList(editor, parentList, listName, detail);
      }
    };
    var ToggleList = {
      toggleList: toggleList,
      mergeWithAdjacentLists: mergeWithAdjacentLists
    };

    var DOM$2 = global$6.DOM;
    var normalizeList = function (dom, ul) {
      var sibling;
      var parentNode = ul.parentNode;
      if (parentNode.nodeName === 'LI' && parentNode.firstChild === ul) {
        sibling = parentNode.previousSibling;
        if (sibling && sibling.nodeName === 'LI') {
          sibling.appendChild(ul);
          if (NodeType.isEmpty(dom, parentNode)) {
            DOM$2.remove(parentNode);
          }
        } else {
          DOM$2.setStyle(parentNode, 'listStyleType', 'none');
        }
      }
      if (NodeType.isListNode(parentNode)) {
        sibling = parentNode.previousSibling;
        if (sibling && sibling.nodeName === 'LI') {
          sibling.appendChild(ul);
        }
      }
    };
    var normalizeLists = function (dom, element) {
      global$5.each(global$5.grep(dom.select('ol,ul', element)), function (ul) {
        normalizeList(dom, ul);
      });
    };
    var NormalizeLists = {
      normalizeList: normalizeList,
      normalizeLists: normalizeLists
    };

    var findNextCaretContainer = function (editor, rng, isForward, root) {
      var node = rng.startContainer;
      var offset = rng.startOffset;
      var nonEmptyBlocks, walker;
      if (node.nodeType === 3 && (isForward ? offset < node.data.length : offset > 0)) {
        return node;
      }
      nonEmptyBlocks = editor.schema.getNonEmptyElements();
      if (node.nodeType === 1) {
        node = global$1.getNode(node, offset);
      }
      walker = new global$2(node, root);
      if (isForward) {
        if (NodeType.isBogusBr(editor.dom, node)) {
          walker.next();
        }
      }
      while (node = walker[isForward ? 'next' : 'prev2']()) {
        if (node.nodeName === 'LI' && !node.hasChildNodes()) {
          return node;
        }
        if (nonEmptyBlocks[node.nodeName]) {
          return node;
        }
        if (node.nodeType === 3 && node.data.length > 0) {
          return node;
        }
      }
    };
    var hasOnlyOneBlockChild = function (dom, elm) {
      var childNodes = elm.childNodes;
      return childNodes.length === 1 && !NodeType.isListNode(childNodes[0]) && dom.isBlock(childNodes[0]);
    };
    var unwrapSingleBlockChild = function (dom, elm) {
      if (hasOnlyOneBlockChild(dom, elm)) {
        dom.remove(elm.firstChild, true);
      }
    };
    var moveChildren = function (dom, fromElm, toElm) {
      var node, targetElm;
      targetElm = hasOnlyOneBlockChild(dom, toElm) ? toElm.firstChild : toElm;
      unwrapSingleBlockChild(dom, fromElm);
      if (!NodeType.isEmpty(dom, fromElm, true)) {
        while (node = fromElm.firstChild) {
          targetElm.appendChild(node);
        }
      }
    };
    var mergeLiElements = function (dom, fromElm, toElm) {
      var node, listNode;
      var ul = fromElm.parentNode;
      if (!NodeType.isChildOfBody(dom, fromElm) || !NodeType.isChildOfBody(dom, toElm)) {
        return;
      }
      if (NodeType.isListNode(toElm.lastChild)) {
        listNode = toElm.lastChild;
      }
      if (ul === toElm.lastChild) {
        if (NodeType.isBr(ul.previousSibling)) {
          dom.remove(ul.previousSibling);
        }
      }
      node = toElm.lastChild;
      if (node && NodeType.isBr(node) && fromElm.hasChildNodes()) {
        dom.remove(node);
      }
      if (NodeType.isEmpty(dom, toElm, true)) {
        dom.$(toElm).empty();
      }
      moveChildren(dom, fromElm, toElm);
      if (listNode) {
        toElm.appendChild(listNode);
      }
      var contains = contains$1(Element.fromDom(toElm), Element.fromDom(fromElm));
      var nestedLists = contains ? dom.getParents(fromElm, NodeType.isListNode, toElm) : [];
      dom.remove(fromElm);
      each(nestedLists, function (list) {
        if (NodeType.isEmpty(dom, list) && list !== dom.getRoot()) {
          dom.remove(list);
        }
      });
    };
    var mergeIntoEmptyLi = function (editor, fromLi, toLi) {
      editor.dom.$(toLi).empty();
      mergeLiElements(editor.dom, fromLi, toLi);
      editor.selection.setCursorLocation(toLi);
    };
    var mergeForward = function (editor, rng, fromLi, toLi) {
      var dom = editor.dom;
      if (dom.isEmpty(toLi)) {
        mergeIntoEmptyLi(editor, fromLi, toLi);
      } else {
        var bookmark = Bookmark.createBookmark(rng);
        mergeLiElements(dom, fromLi, toLi);
        editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
      }
    };
    var mergeBackward = function (editor, rng, fromLi, toLi) {
      var bookmark = Bookmark.createBookmark(rng);
      mergeLiElements(editor.dom, fromLi, toLi);
      var resolvedBookmark = Bookmark.resolveBookmark(bookmark);
      editor.selection.setRng(resolvedBookmark);
    };
    var backspaceDeleteFromListToListCaret = function (editor, isForward) {
      var dom = editor.dom, selection = editor.selection;
      var selectionStartElm = selection.getStart();
      var root = Selection.getClosestListRootElm(editor, selectionStartElm);
      var li = dom.getParent(selection.getStart(), 'LI', root);
      var ul, rng, otherLi;
      if (li) {
        ul = li.parentNode;
        if (ul === editor.getBody() && NodeType.isEmpty(dom, ul)) {
          return true;
        }
        rng = Range.normalizeRange(selection.getRng(true));
        otherLi = dom.getParent(findNextCaretContainer(editor, rng, isForward, root), 'LI', root);
        if (otherLi && otherLi !== li) {
          if (isForward) {
            mergeForward(editor, rng, otherLi, li);
          } else {
            mergeBackward(editor, rng, li, otherLi);
          }
          return true;
        } else if (!otherLi) {
          if (!isForward) {
            flattenListSelection(editor);
            return true;
          }
        }
      }
      return false;
    };
    var removeBlock = function (dom, block, root) {
      var parentBlock = dom.getParent(block.parentNode, dom.isBlock, root);
      dom.remove(block);
      if (parentBlock && dom.isEmpty(parentBlock)) {
        dom.remove(parentBlock);
      }
    };
    var backspaceDeleteIntoListCaret = function (editor, isForward) {
      var dom = editor.dom;
      var selectionStartElm = editor.selection.getStart();
      var root = Selection.getClosestListRootElm(editor, selectionStartElm);
      var block = dom.getParent(selectionStartElm, dom.isBlock, root);
      if (block && dom.isEmpty(block)) {
        var rng = Range.normalizeRange(editor.selection.getRng(true));
        var otherLi_1 = dom.getParent(findNextCaretContainer(editor, rng, isForward, root), 'LI', root);
        if (otherLi_1) {
          editor.undoManager.transact(function () {
            removeBlock(dom, block, root);
            ToggleList.mergeWithAdjacentLists(dom, otherLi_1.parentNode);
            editor.selection.select(otherLi_1, true);
            editor.selection.collapse(isForward);
          });
          return true;
        }
      }
      return false;
    };
    var backspaceDeleteCaret = function (editor, isForward) {
      return backspaceDeleteFromListToListCaret(editor, isForward) || backspaceDeleteIntoListCaret(editor, isForward);
    };
    var backspaceDeleteRange = function (editor) {
      var selectionStartElm = editor.selection.getStart();
      var root = Selection.getClosestListRootElm(editor, selectionStartElm);
      var startListParent = editor.dom.getParent(selectionStartElm, 'LI,DT,DD', root);
      if (startListParent || Selection.getSelectedListItems(editor).length > 0) {
        editor.undoManager.transact(function () {
          editor.execCommand('Delete');
          NormalizeLists.normalizeLists(editor.dom, editor.getBody());
        });
        return true;
      }
      return false;
    };
    var backspaceDelete = function (editor, isForward) {
      return editor.selection.isCollapsed() ? backspaceDeleteCaret(editor, isForward) : backspaceDeleteRange(editor);
    };
    var setup = function (editor) {
      editor.on('keydown', function (e) {
        if (e.keyCode === global$3.BACKSPACE) {
          if (backspaceDelete(editor, false)) {
            e.preventDefault();
          }
        } else if (e.keyCode === global$3.DELETE) {
          if (backspaceDelete(editor, true)) {
            e.preventDefault();
          }
        }
      });
    };
    var Delete = {
      setup: setup,
      backspaceDelete: backspaceDelete
    };

    var get = function (editor) {
      return {
        backspaceDelete: function (isForward) {
          Delete.backspaceDelete(editor, isForward);
        }
      };
    };
    var Api = { get: get };

    var queryListCommandState = function (editor, listName) {
      return function () {
        var parentList = editor.dom.getParent(editor.selection.getStart(), 'UL,OL,DL');
        return parentList && parentList.nodeName === listName;
      };
    };
    var register = function (editor) {
      editor.on('BeforeExecCommand', function (e) {
        var cmd = e.command.toLowerCase();
        if (cmd === 'indent') {
          indentListSelection(editor);
        } else if (cmd === 'outdent') {
          outdentListSelection(editor);
        }
      });
      editor.addCommand('InsertUnorderedList', function (ui, detail) {
        ToggleList.toggleList(editor, 'UL', detail);
      });
      editor.addCommand('InsertOrderedList', function (ui, detail) {
        ToggleList.toggleList(editor, 'OL', detail);
      });
      editor.addCommand('InsertDefinitionList', function (ui, detail) {
        ToggleList.toggleList(editor, 'DL', detail);
      });
      editor.addCommand('RemoveList', function () {
        flattenListSelection(editor);
      });
      editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState(editor, 'UL'));
      editor.addQueryStateHandler('InsertOrderedList', queryListCommandState(editor, 'OL'));
      editor.addQueryStateHandler('InsertDefinitionList', queryListCommandState(editor, 'DL'));
    };
    var Commands = { register: register };

    var shouldIndentOnTab = function (editor) {
      return editor.getParam('lists_indent_on_tab', true);
    };
    var Settings = { shouldIndentOnTab: shouldIndentOnTab };

    var setupTabKey = function (editor) {
      editor.on('keydown', function (e) {
        if (e.keyCode !== global$3.TAB || global$3.metaKeyPressed(e)) {
          return;
        }
        editor.undoManager.transact(function () {
          if (e.shiftKey ? outdentListSelection(editor) : indentListSelection(editor)) {
            e.preventDefault();
          }
        });
      });
    };
    var setup$1 = function (editor) {
      if (Settings.shouldIndentOnTab(editor)) {
        setupTabKey(editor);
      }
      Delete.setup(editor);
    };
    var Keyboard = { setup: setup$1 };

    var findIndex = function (list, predicate) {
      for (var index = 0; index < list.length; index++) {
        var element = list[index];
        if (predicate(element)) {
          return index;
        }
      }
      return -1;
    };
    var listState = function (editor, listName) {
      return function (e) {
        var ctrl = e.control;
        editor.on('NodeChange', function (e) {
          var tableCellIndex = findIndex(e.parents, NodeType.isTableCellNode);
          var parents = tableCellIndex !== -1 ? e.parents.slice(0, tableCellIndex) : e.parents;
          var lists = global$5.grep(parents, NodeType.isListNode);
          ctrl.active(lists.length > 0 && lists[0].nodeName === listName);
        });
      };
    };
    var register$1 = function (editor) {
      var hasPlugin = function (editor, plugin) {
        var plugins = editor.settings.plugins ? editor.settings.plugins : '';
        return global$5.inArray(plugins.split(/[ ,]/), plugin) !== -1;
      };
      if (!hasPlugin(editor, 'advlist')) {
        editor.addButton('numlist', {
          active: false,
          title: 'Numbered list',
          cmd: 'InsertOrderedList',
          onPostRender: listState(editor, 'OL')
        });
        editor.addButton('bullist', {
          active: false,
          title: 'Bullet list',
          cmd: 'InsertUnorderedList',
          onPostRender: listState(editor, 'UL')
        });
      }
      editor.addButton('indent', {
        icon: 'indent',
        title: 'Increase indent',
        cmd: 'Indent'
      });
    };
    var Buttons = { register: register$1 };

    global.add('lists', function (editor) {
      Keyboard.setup(editor);
      Buttons.register(editor);
      Commands.register(editor);
      return Api.get(editor);
    });
    function Plugin () {
    }

    return Plugin;

}(window));
})();


/***/ }),

/***/ 586:
/***/ (function(module, exports) {

/**
 * Adapted from https://github.com/kurtnovack/stickytoolbar
 */
tinymce.PluginManager.add('stickytoolbar', function(editor, url) {
   var offset = editor.settings.sticky_offset ? editor.settings.sticky_offset : 0;

   editor.on('init', function() {
      editor.setSticky();
   });

   $(window).on('scroll', function() {
      editor.setSticky();
   });

   editor.setSticky = function () {
      offset = editor.settings.sticky_offset ? editor.settings.sticky_offset : 0;
      var container = editor.editorContainer;
      var toolbars = $(container).find('.mce-toolbar-grp');
      var statusbar = $(container).find('.mce-statusbar');

      if (editor.isSticky()) {
         $(container).css({
            paddingTop: toolbars.outerHeight()
         });

         if (editor.isAtBottom()) {
            toolbars.css({
               top: 'auto',
               bottom: statusbar.outerHeight(),
               position: 'absolute',
               width: '100%',
               borderBottom: 'none'
            });
         } else {
            toolbars.css({
               top: offset,
               bottom: 'auto',
               position: 'fixed',
               width: $(container).width(),
               borderBottom: '1px solid rgba(0,0,0,0.2)'
            });
         }
      } else {
         $(container).css({
            paddingTop: 0
         });

         toolbars.css({
            top: 0,
            position: 'relative',
            width: 'auto',
            borderBottom: 'none'
         });
      }
   };

   editor.isSticky = function () {
      var container = editor.editorContainer,
          editorTop = container.getBoundingClientRect().top;

      if (editorTop < offset) {
         return true;
      }

      return false;
   };

   editor.isAtBottom = function () {
      const container = editor.getContainer();

      const editorPosition = container.getBoundingClientRect().top,
            statusbar = container.querySelector('.mce-statusbar'),
            topPart = container.querySelector('.mce-top-part');

      const statusbarHeight = statusbar ? statusbar.offsetHeight : 0,
            topPartHeight = topPart ? topPart.offsetHeight : 0;

      const stickyHeight = -(container.offsetHeight - topPartHeight - statusbarHeight);

      if (editorPosition < stickyHeight + offset) {
         return true;
      }

      return false;
   };
});


/***/ }),

/***/ 6:
/***/ (function(module, exports) {

var g;

// This works in non-strict mode
g = (function() {
	return this;
})();

try {
	// This works if eval is allowed (see CSP)
	g = g || new Function("return this")();
} catch (e) {
	// This works if the window reference is available
	if (typeof window === "object") g = window;
}

// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}

module.exports = g;


/***/ }),

/***/ 7:
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(process, console) {// 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 getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors ||
  function getOwnPropertyDescriptors(obj) {
    var keys = Object.keys(obj);
    var descriptors = {};
    for (var i = 0; i < keys.length; i++) {
      descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]);
    }
    return descriptors;
  };

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) {
  if (typeof process !== 'undefined' && process.noDeprecation === true) {
    return fn;
  }

  // Allow for deprecating things in the process of starting up.
  if (typeof process === 'undefined') {
    return function() {
      return exports.deprecate(fn, msg).apply(this, arguments);
    };
  }

  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 = process.env.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 = __webpack_require__(9);

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 = __webpack_require__(10);

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);
}

var kCustomPromisifiedSymbol = typeof Symbol !== 'undefined' ? Symbol('util.promisify.custom') : undefined;

exports.promisify = function promisify(original) {
  if (typeof original !== 'function')
    throw new TypeError('The "original" argument must be of type Function');

  if (kCustomPromisifiedSymbol && original[kCustomPromisifiedSymbol]) {
    var fn = original[kCustomPromisifiedSymbol];
    if (typeof fn !== 'function') {
      throw new TypeError('The "util.promisify.custom" argument must be of type Function');
    }
    Object.defineProperty(fn, kCustomPromisifiedSymbol, {
      value: fn, enumerable: false, writable: false, configurable: true
    });
    return fn;
  }

  function fn() {
    var promiseResolve, promiseReject;
    var promise = new Promise(function (resolve, reject) {
      promiseResolve = resolve;
      promiseReject = reject;
    });

    var args = [];
    for (var i = 0; i < arguments.length; i++) {
      args.push(arguments[i]);
    }
    args.push(function (err, value) {
      if (err) {
        promiseReject(err);
      } else {
        promiseResolve(value);
      }
    });

    try {
      original.apply(this, args);
    } catch (err) {
      promiseReject(err);
    }

    return promise;
  }

  Object.setPrototypeOf(fn, Object.getPrototypeOf(original));

  if (kCustomPromisifiedSymbol) Object.defineProperty(fn, kCustomPromisifiedSymbol, {
    value: fn, enumerable: false, writable: false, configurable: true
  });
  return Object.defineProperties(
    fn,
    getOwnPropertyDescriptors(original)
  );
}

exports.promisify.custom = kCustomPromisifiedSymbol

function callbackifyOnRejected(reason, cb) {
  // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).
  // Because `null` is a special error value in callbacks which means "no error
  // occurred", we error-wrap so the callback consumer can distinguish between
  // "the promise rejected with null" or "the promise fulfilled with undefined".
  if (!reason) {
    var newReason = new Error('Promise was rejected with a falsy value');
    newReason.reason = reason;
    reason = newReason;
  }
  return cb(reason);
}

function callbackify(original) {
  if (typeof original !== 'function') {
    throw new TypeError('The "original" argument must be of type Function');
  }

  // We DO NOT return the promise as it gives the user a false sense that
  // the promise is actually somehow related to the callback's execution
  // and that the callback throwing will reject the promise.
  function callbackified() {
    var args = [];
    for (var i = 0; i < arguments.length; i++) {
      args.push(arguments[i]);
    }

    var maybeCb = args.pop();
    if (typeof maybeCb !== 'function') {
      throw new TypeError('The last argument must be of type Function');
    }
    var self = this;
    var cb = function() {
      return maybeCb.apply(self, arguments);
    };
    // In true node style we process the callback on `nextTick` with all the
    // implications (stack, `uncaughtException`, `async_hooks`)
    original.apply(this, args)
      .then(function(ret) { process.nextTick(cb, null, ret) },
            function(rej) { process.nextTick(callbackifyOnRejected, rej, cb) });
  }

  Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original));
  Object.defineProperties(callbackified,
                          getOwnPropertyDescriptors(original));
  return callbackified;
}
exports.callbackify = callbackify;

/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(8), __webpack_require__(5)))

/***/ }),

/***/ 8:
/***/ (function(module, exports) {

// 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.prependListener = noop;
process.prependOnceListener = noop;

process.listeners = function (name) { return [] }

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; };


/***/ }),

/***/ 9:
/***/ (function(module, exports) {

module.exports = function isBuffer(arg) {
  return arg && typeof arg === 'object'
    && typeof arg.copy === 'function'
    && typeof arg.fill === 'function'
    && typeof arg.readUInt8 === 'function';
}

/***/ })

/******/ });
//# sourceMappingURL=tinymce.js.map