PageSourceSearch

https://membres.aaof.ca/js/tinymce.js

js aaof.ca collected 2026-09-24 21:26:04 UTC 1,035,333 bytes, 27,762 lines download raw bytes

1/**
2 * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 * Licensed under the LGPL or a commercial license.
4 * For LGPL see License.txt in the project root for license information.
5 * For commercial licenses see https://www.tiny.cloud/
6 *
7 * Version: 5.0.4 (2019-04-23)
8 */
9(function () {
10(function (domGlobals) {
11    'use strict';
12
13    var noop = function () {
14      var args = [];
15      for (var _i = 0; _i < arguments.length; _i++) {
16        args[_i] = arguments[_i];
17      }
18    };
19    var noarg = function (f) {
20      return function () {
21        var args = [];
22        for (var _i = 0; _i < arguments.length; _i++) {
23          args[_i] = arguments[_i];
24        }
25        return f();
26      };
27    };
28    var compose = function (fa, fb) {
29      return function () {
30        var args = [];
31        for (var _i = 0; _i < arguments.length; _i++) {
32          args[_i] = arguments[_i];
33        }
34        return fa(fb.apply(null, args));
35      };
36    };
37    var constant = function (value) {
38      return function () {
39        return value;
40      };
41    };
42    var identity = function (x) {
43      return x;
44    };
45    var tripleEquals = function (a, b) {
46      return a === b;
47    };
48    function curry(fn) {
49      var initialArgs = [];
50      for (var _i = 1; _i < arguments.length; _i++) {
51        initialArgs[_i - 1] = arguments[_i];
52      }
53      return function () {
54        var restArgs = [];
55        for (var _i = 0; _i < arguments.length; _i++) {
56          restArgs[_i] = arguments[_i];
57        }
58        var all = initialArgs.concat(restArgs);
59        return fn.apply(null, all);
60      };
61    }
62    var not = function (f) {
63      return function () {
64        var args = [];
65        for (var _i = 0; _i < arguments.length; _i++) {
66          args[_i] = arguments[_i];
67        }
68        return !f.apply(null, args);
69      };
70    };
71    var die = function (msg) {
72      return function () {
73        throw new Error(msg);
74      };
75    };
76    var apply = function (f) {
77      return f();
78    };
79    var call = function (f) {
80      f();
81    };
82    var never = constant(false);
83    var always = constant(true);
84
85    var Fun = /*#__PURE__*/Object.freeze({
86        noop: noop,
87        noarg: noarg,
88        compose: compose,
89        constant: constant,
90        identity: identity,
91        tripleEquals: tripleEquals,
92        curry: curry,
93        not: not,
94        die: die,
95        apply: apply,
96        call: call,
97        never: never,
98        always: always
99    });
100
101    var never$1 = never;
102    var always$1 = always;
103    var none = function () {
104      return NONE;
105    };
106    var NONE = function () {
107      var eq = function (o) {
108        return o.isNone();
109      };
110      var call = function (thunk) {
111        return thunk();
112      };
113      var id = function (n) {
114        return n;
115      };
116      var noop = function () {
117      };
118      var nul = function () {
119        return null;
120      };
121      var undef = function () {
122        return undefined;
123      };
124      var me = {
125        fold: function (n, s) {
126          return n();
127        },
128        is: never$1,
129        isSome: never$1,
130        isNone: always$1,
131        getOr: id,
132        getOrThunk: call,
133        getOrDie: function (msg) {
134          throw new Error(msg || 'error: getOrDie called on none.');
135        },
136        getOrNull: nul,
137        getOrUndefined: undef,
138        or: id,
139        orThunk: call,
140        map: none,
141        ap: none,
142        each: noop,
143        bind: none,
144        flatten: none,
145        exists: never$1,
146        forall: always$1,
147        filter: none,
148        equals: eq,
149        equals_: eq,
150        toArray: function () {
151          return [];
152        },
153        toString: constant('none()')
154      };
155      if (Object.freeze)
156        Object.freeze(me);
157      return me;
158    }();
159    var some = function (a) {
160      var constant_a = function () {
161        return a;
162      };
163      var self = function () {
164        return me;
165      };
166      var map = function (f) {
167        return some(f(a));
168      };
169      var bind = function (f) {
170        return f(a);
171      };
172      var me = {
173        fold: function (n, s) {
174          return s(a);
175        },
176        is: function (v) {
177          return a === v;
178        },
179        isSome: always$1,
180        isNone: never$1,
181        getOr: constant_a,
182        getOrThunk: constant_a,
183        getOrDie: constant_a,
184        getOrNull: constant_a,
185        getOrUndefined: constant_a,
186        or: self,
187        orThunk: self,
188        map: map,
189        ap: function (optfab) {
190          return optfab.fold(none, function (fab) {
191            return some(fab(a));
192          });
193        },
194        each: function (f) {
195          f(a);
196        },
197        bind: bind,
198        flatten: constant_a,
199        exists: bind,
200        forall: bind,
201        filter: function (f) {
202          return f(a) ? me : NONE;
203        },
204        equals: function (o) {
205          return o.is(a);
206        },
207        equals_: function (o, elementEq) {
208          return o.fold(never$1, function (b) {
209            return elementEq(a, b);
210          });
211        },
212        toArray: function () {
213          return [a];
214        },
215        toString: function () {
216          return 'some(' + a + ')';
217        }
218      };
219      return me;
220    };
221    var from = function (value) {
222      return value === null || value === undefined ? NONE : some(value);
223    };
224    var Option = {
225      some: some,
226      none: none,
227      from: from
228    };
229
230    var typeOf = function (x) {
231      if (x === null)
232        return 'null';
233      var t = typeof x;
234      if (t === 'object' && Array.prototype.isPrototypeOf(x))
235        return 'array';
236      if (t === 'object' && String.prototype.isPrototypeOf(x))
237        return 'string';
238      return t;
239    };
240    var isType = function (type) {
241      return function (value) {
242        return typeOf(value) === type;
243      };
244    };
245    var isString = isType('string');
246    var isObject = isType('object');
247    var isArray = isType('array');
248    var isNull = isType('null');
249    var isBoolean = isType('boolean');
250    var isFunction = isType('function');
251    var isNumber = isType('number');
252
253    var rawIndexOf = function () {
254      var pIndexOf = Array.prototype.indexOf;
255      var fastIndex = function (xs, x) {
256        return pIndexOf.call(xs, x);
257      };
258      var slowIndex = function (xs, x) {
259        return slowIndexOf(xs, x);
260      };
261      return pIndexOf === undefined ? slowIndex : fastIndex;
262    }();
263    var indexOf = function (xs, x) {
264      var r = rawIndexOf(xs, x);
265      return r === -1 ? Option.none() : Option.some(r);
266    };
267    var contains = function (xs, x) {
268      return rawIndexOf(xs, x) > -1;
269    };
270    var exists = function (xs, pred) {
271      return findIndex(xs, pred).isSome();
272    };
273    var range = function (num, f) {
274      var r = [];
275      for (var i = 0; i < num; i++) {
276        r.push(f(i));
277      }
278      return r;
279    };
280    var chunk = function (array, size) {
281      var r = [];
282      for (var i = 0; i < array.length; i += size) {
283        var s = array.slice(i, i + size);
284        r.push(s);
285      }
286      return r;
287    };
288    var map = function (xs, f) {
289      var len = xs.length;
290      var r = new Array(len);
291      for (var i = 0; i < len; i++) {
292        var x = xs[i];
293        r[i] = f(x, i, xs);
294      }
295      return r;
296    };
297    var each = function (xs, f) {
298      for (var i = 0, len = xs.length; i < len; i++) {
299        var x = xs[i];
300        f(x, i, xs);
301      }
302    };
303    var eachr = function (xs, f) {
304      for (var i = xs.length - 1; i >= 0; i--) {
305        var x = xs[i];
306        f(x, i, xs);
307      }
308    };
309    var partition = function (xs, pred) {
310      var pass = [];
311      var fail = [];
312      for (var i = 0, len = xs.length; i < len; i++) {
313        var x = xs[i];
314        var arr = pred(x, i, xs) ? pass : fail;
315        arr.push(x);
316      }
317      return {
318        pass: pass,
319        fail: fail
320      };
321    };
322    var filter = function (xs, pred) {
323      var r = [];
324      for (var i = 0, len = xs.length; i < len; i++) {
325        var x = xs[i];
326        if (pred(x, i, xs)) {
327          r.push(x);
328        }
329      }
330      return r;
331    };
332    var groupBy = function (xs, f) {
333      if (xs.length === 0) {
334        return [];
335      } else {
336        var wasType = f(xs[0]);
337        var r = [];
338        var group = [];
339        for (var i = 0, len = xs.length; i < len; i++) {
340          var x = xs[i];
341          var type = f(x);
342          if (type !== wasType) {
343            r.push(group);
344            group = [];
345          }
346          wasType = type;
347          group.push(x);
348        }
349        if (group.length !== 0) {
350          r.push(group);
351        }
352        return r;
353      }
354    };
355    var foldr = function (xs, f, acc) {
356      eachr(xs, function (x) {
357        acc = f(acc, x);
358      });
359      return acc;
360    };
361    var foldl = function (xs, f, acc) {
362      each(xs, function (x) {
363        acc = f(acc, x);
364      });
365      return acc;
366    };
367    var find = function (xs, pred) {
368      for (var i = 0, len = xs.length; i < len; i++) {
369        var x = xs[i];
370        if (pred(x, i, xs)) {
371          return Option.some(x);
372        }
373      }
374      return Option.none();
375    };
376    var findIndex = function (xs, pred) {
377      for (var i = 0, len = xs.length; i < len; i++) {
378        var x = xs[i];
379        if (pred(x, i, xs)) {
380          return Option.some(i);
381        }
382      }
383      return Option.none();
384    };
385    var slowIndexOf = function (xs, x) {
386      for (var i = 0, len = xs.length; i < len; ++i) {
387        if (xs[i] === x) {
388          return i;
389        }
390      }
391      return -1;
392    };
393    var push = Array.prototype.push;
394    var flatten = function (xs) {
395      var r = [];
396      for (var i = 0, len = xs.length; i < len; ++i) {
397        if (!Array.prototype.isPrototypeOf(xs[i]))
398          throw new Error('Arr.flatten item ' + i + ' was not an array, input
398: ' + xs);
399        push.apply(r, xs[i]);
400      }
401      return r;
402    };
403    var bind = function (xs, f) {
404      var output = map(xs, f);
405      return flatten(output);
406    };
407    var forall = function (xs, pred) {
408      for (var i = 0, len = xs.length; i < len; ++i) {
409        var x = xs[i];
410        if (pred(x, i, xs) !== true) {
411          return false;
412        }
413      }
414      return true;
415    };
416    var equal = function (a1, a2) {
417      return a1.length === a2.length && forall(a1, function (x, i) {
418        return x === a2[i];
419      });
420    };
421    var slice = Array.prototype.slice;
422    var reverse = function (xs) {
423      var r = slice.call(xs, 0);
424      r.reverse();
425      return r;
426    };
427    var difference = function (a1, a2) {
428      return filter(a1, function (x) {
429        return !contains(a2, x);
430      });
431    };
432    var mapToObject = function (xs, f) {
433      var r = {};
434      for (var i = 0, len = xs.length; i < len; i++) {
435        var x = xs[i];
436        r[String(x)] = f(x, i);
437      }
438      return r;
439    };
440    var pure = function (x) {
441      return [x];
442    };
443    var sort = function (xs, comparator) {
444      var copy = slice.call(xs, 0);
445      copy.sort(comparator);
446      return copy;
447    };
448    var head = function (xs) {
449      return xs.length === 0 ? Option.none() : Option.some(xs[0]);
450    };
451    var last = function (xs) {
452      return xs.length === 0 ? Option.none() : Option.some(xs[xs.length - 1]);
453    };
454    var from$1 = isFunction(Array.from) ? Array.from : function (x) {
455      return slice.call(x);
456    };
457
458    var Arr = /*#__PURE__*/Object.freeze({
459        indexOf: indexOf,
460        contains: contains,
461        exists: exists,
462        range: range,
463        chunk: chunk,
464        map: map,
465        each: each,
466        eachr: eachr,
467        partition: partition,
468        filter: filter,
469        groupBy: groupBy,
470        foldr: foldr,
471        foldl: foldl,
472        find: find,
473        findIndex: findIndex,
474        flatten: flatten,
475        bind: bind,
476        forall: forall,
477        equal: equal,
478        reverse: reverse,
479        difference: difference,
480        mapToObject: mapToObject,
481        pure: pure,
482        sort: sort,
483        head: head,
484        last: last,
485        from: from$1
486    });
487
488    var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();
489
490    var path = function (parts, scope) {
491      var o = scope !== undefined && scope !== null ? scope : Global;
492      for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i)
493        o = o[parts[i]];
494      return o;
495    };
496    var resolve = function (p, scope) {
497      var parts = p.split('.');
498      return path(parts, scope);
499    };
500
501    var unsafe = function (name, scope) {
502      return resolve(name, scope);
503    };
504    var getOrDie = function (name, scope) {
505      var actual = unsafe(name, scope);
506      if (actual === undefined || actual === null)
507        throw name + ' not available on this browser';
508      return actual;
509    };
510    var Global$1 = { getOrDie: getOrDie };
511
512    var url = function () {
513      return Global$1.getOrDie('URL');
514    };
515    var createObjectURL = function (blob) {
516      return url().createObjectURL(blob);
517    };
518    var revokeObjectURL = function (u) {
519      url().revokeObjectURL(u);
520    };
521    var URL = {
522      createObjectURL: createObjectURL,
523      revokeObjectURL: revokeObjectURL
524    };
525
526    var nav = domGlobals.navigator, userAgent = nav.userAgent;
527    var opera, webkit, ie, ie11, ie12, gecko, mac, iDevice, android, fileApi, phone, tablet, windowsPhone;
528    var matchMediaQuery = function (query) {
529      return 'matchMedia' in domGlobals.window ? domGlobals.matchMedia(query).matches : false;
530    };
531    opera = false;
532    android = /Android/.test(userAgent);
533    webkit = /WebKit/.test(userAgent);
534    ie = !webkit && !opera && /MSIE/gi.test(userAgent) && /Explorer/gi.test(nav.appName);
535    ie = ie && /MSIE (\w+)\./.exec(userAgent)[1];
536    ie11 = userAgent.indexOf('Trident/') !== -1 && (userAgent.indexOf('rv:') !== -1 || nav.appName.indexOf('Netscape') !== -1) ? 11 : false;
537    ie12 = userAgent.indexOf('Edge/') !== -1 && !ie && !ie11 ? 12 : false;
538    ie = ie || ie11 || ie12;
539    gecko = !webkit && !ie11 && /Gecko/.test(userAgent);
540    mac = userAgent.indexOf('Mac') !== -1;
541    iDevice = /(iPad|iPhone)/.test(userAgent);
542    fileApi = 'FormData' in domGlobals.window && 'FileReader' in domGlobals.window && 'URL' in domGlobals.window && !!URL.createObjectURL;
543    phone = matchMediaQuery('only screen and (max-device-width: 480px)') && (android || iDevice);
544    tablet = matchMediaQuery('only screen and (min-width: 800px)') && (android || iDevice);
545    windowsPhone = userAgent.indexOf('Windows Phone') !== -1;
546    if (ie12) {
547      webkit = false;
548    }
549    var contentEditable = !iDevice || fileApi || parseInt(userAgent.match(/AppleWebKit\/(\d*)/)[1], 10) >= 534;
550    var Env = {
551      opera: opera,
552      webkit: webkit,
553      ie: ie,
554      gecko: gecko,
555      mac: mac,
556      iOS: iDevice,
557      android: android,
558      contentEditable: contentEditable,
559      transparentSrc: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
560      caretAfter: ie !== 8,
561      range: domGlobals.window.getSelection && 'Range' in domGlobals.window,
562      documentMode: ie && !ie12 ? domGlobals.document.documentMode || 7 : 10,
563      fileApi: fileApi,
564      ceFalse: ie === false || ie > 8,
565      cacheSuffix: null,
566      container: null,
567      overrideViewPort: null,
568      experimentalShadowDom: false,
569      canHaveCSP: ie === false || ie > 11,
570      desktop: !phone && !tablet,
571      windowsPhone: windowsPhone
572    };
573
574    var promise = function () {
575      function bind(fn, thisArg) {
576        return function () {
577          fn.apply(thisArg, arguments);
578        };
579      }
580      var isArray = Array.isArray || function (value) {
581        return Object.prototype.toString.call(value) === '[object Array]';
582      };
583      var Promise = function (fn) {
584        if (typeof this !== 'object') {
585          throw new TypeError('Promises must be constructed via new');
586        }
587        if (typeof fn !== 'function') {
588          throw new TypeError('not a function');
589        }
590        this._state = null;
591        this._value = null;
592        this._deferreds = [];
593        doResolve(fn, bind(resolve, this), bind(reject, this));
594      };
595      var asap = Promise.immediateFn || typeof domGlobals.setImmediate === 'function' && domGlobals.setImmediate || function (fn) {
596        domGlobals.setTimeout(fn, 1);
597      };
598      function handle(deferred) {
599        var me = this;
600        if (this._state === null) {
601          this._deferreds.push(deferred);
602          return;
603        }
604        asap(function () {
605          var cb = me._state ? deferred.onFulfilled : deferred.onRejected;
606          if (cb === null) {
607            (me._state ? deferred.resolve : deferred.reject)(me._value);
608            return;
609          }
610          var ret;
611          try {
612            ret = cb(me._value);
613          } catch (e) {
614            deferred.reject(e);
615            return;
616          }
617          deferred.resolve(ret);
618        });
619      }
620      function resolve(newValue) {
621        try {
622          if (newValue === this) {
623            throw new TypeError('A promise cannot be resolved with itself.');
624          }
625          if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
626            var then = newValue.then;
627            if (typeof then === 'function') {
628              doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this));
629              return;
630            }
631          }
632          this._state = true;
633          this._value = newValue;
634          finale.call(this);
635        } catch (e) {
636          reject.call(this, e);
637        }
638      }
639      function reject(newValue) {
640        this._state = false;
641        this._value = newValue;
642        finale.call(this);
643      }
644      function finale() {
645        for (var i = 0, len = this._deferreds.length; i < len; i++) {
646          handle.call(this, this._deferreds[i]);
647        }
648        this._deferreds = null;
649      }
650      function Handler(onFulfilled, onRejected, resolve, reject) {
651        this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
652        this.onRejected = typeof onRejected === 'function' ? onRejected : null;
653        this.resolve = resolve;
654        this.reject = reject;
655      }
656      function doResolve(fn, onFulfilled, onRejected) {
657        var done = false;
658        try {
659          fn(function (value) {
660            if (done) {
661              return;
662            }
663            done = true;
664            onFulfilled(value);
665          }, function (reason) {
666            if (done) {
667              return;
668            }
669            done = true;
670            onRejected(reason);
671          });
672        } catch (ex) {
673          if (done) {
674            return;
675          }
676          done = true;
677          onRejected(ex);
678        }
679      }
680      Promise.prototype.catch = function (onRejected) {
681        return this.then(null, onRejected);
682      };
683      Promise.prototype.then = function (onFulfilled, onRejected) {
684        var me = this;
685        return new Promise(function (resolve, reject) {
686          handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject));
687        });
688      };
689      Promise.all = function () {
690        var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments);
691        return new Promise(function (resolve, reject) {
692          if (args.length === 0) {
693            return resolve([]);
694          }
695          var remaining = args.length;
696          function res(i, val) {
697            try {
698              if (val && (typeof val === 'object' || typeof val === 'function')) {
699                var then = val.then;
700                if (typeof then === 'function') {
701                  then.call(val, function (val) {
702                    res(i, val);
703                  }, reject);
704                  return;
705                }
706              }
707              args[i] = val;
708              if (--remaining === 0) {
709                resolve(args);
710              }
711            } catch (ex) {
712              reject(ex);
713            }
714          }
715          for (var i = 0; i < args.length; i++) {
716            res(i, args[i]);
717          }
718        });
719      };
720      Promise.resolve = function (value) {
721        if (value && typeof value === 'object' && value.constructor === Promise) {
722          return value;
723        }
724        return new Promise(function (resolve) {
725          resolve(value);
726        });
727      };
728      Promise.reject = function (value) {
729        return new Promise(function (resolve, reject) {
730          reject(value);
731        });
732      };
733      Promise.race = function (values) {
734        return new Promise(function (resolve, reject) {
735          for (var i = 0, len = values.length; i < len; i++) {
736            values[i].then(resolve, reject);
737          }
738        });
739      };
740      return Promise;
741    };
742    var promiseObj = window.Promise ? window.Promise : promise();
743
744    var requestAnimationFramePromise;
745    var requestAnimationFrame = function (callback, element) {
746      var i, requestAnimationFrameFunc = domGlobals.window.requestAnimationFrame;
747      var vendors = [
748        'ms',
749        'moz',
750        'webkit'
751      ];
752      var featurefill = function (callback) {
753        domGlobals.window.setTimeout(callback, 0);
754      };
755      for (i = 0; i < vendors.length && !requestAnimationFrameFunc; i++) {
756        requestAnimationFrameFunc = domGlobals.window[vendors[i] + 'RequestAnimationFrame'];
757      }
758      if (!requestAnimationFrameFunc) {
759        requestAnimationFrameFunc = featurefill;
760      }
761      requestAnimationFrameFunc(callback, element);
762    };
763    var wrappedSetTimeout = function (callback, time) {
764      if (typeof time !== 'number') {
765        time = 0;
766      }
767      return domGlobals.setTimeout(callback, time);
768    };
769    var wrappedSetInterval = function (callback, time) {
770      if (typeof time !== 'number') {
771        time = 1;
772      }
773      return domGlobals.setInterval(callback, time);
774    };
775    var wrappedClearTimeout = function (id) {
776      return domGlobals.clearTimeout(id);
777    };
778    var wrappedClearInterval = function (id) {
779      return domGlobals.clearInterval(id);
780    };
781    var debounce = function (callback, time) {
782      var timer, func;
783      func = function () {
784        var args = [];
785        for (var _i = 0; _i < arguments.length; _i++) {
786          args[_i] = arguments[_i];
787        }
788        domGlobals.clearTimeout(timer);
789        timer = wrappedSetTimeout(function () {
790          callback.apply(this, args);
791        }, time);
792      };
793      func.stop = function () {
794        domGlobals.clearTimeout(timer);
795      };
796      return func;
797    };
798    var Delay = {
799      requestAnimationFrame: function (callback, element) {
800        if (requestAnimationFramePromise) {
801          requestAnimationFramePromise.then(callback);
802          return;
803        }
804        requestAnimationFramePromise = new promiseObj(function (resolve) {
805          if (!element) {
806            element = domGlobals.document.body;
807          }
808          requestAnimationFrame(resolve, element);
809        }).then(callback);
810      },
811      setTimeout: wrappedSetTimeout,
812      setInterval: wrappedSetInterval,
813      setEditorTimeout: function (editor, callback, time) {
814        return wrappedSetTimeout(function () {
815          if (!editor.removed) {
816            callback();
817          }
818        }, time);
819      },
820      setEditorInterval: function (editor, callback, time) {
821        var timer;
822        timer = wrappedSetInterval(function () {
823          if (!editor.removed) {
824            callback();
825          } else {
826            domGlobals.clearInterval(timer);
827          }
828        }, time);
829        return timer;
830      },
831      debounce: debounce,
832      throttle: debounce,
833      clearInterval: wrappedClearInterval,
834      clearTimeout: wrappedClearTimeout
835    };
836
837    var eventExpandoPrefix = 'mce-data-';
838    var mouseEventRe = /^(?:mouse|contextmenu)|click/;
839    var deprecated = {
840      keyLocation: 1,
841      layerX: 1,
842      layerY: 1,
843      returnValue: 1,
844      webkitMovementX: 1,
845      webkitMovementY: 1,
846      keyIdentifier: 1
847    };
848    var hasIsDefaultPrevented = function (event) {
849      return event.isDefaultPrevented === returnTrue || event.isDefaultPrevented === returnFalse;
850    };
851    var returnFalse = function () {
852      return false;
853    };
854    var returnTrue = function () {
855      return true;
856    };
857    var addEvent = function (target, name, callback, capture) {
858      if (target.addEventListener) {
859        target.addEventListener(name, callback, capture || false);
860      } else if (target.attachEvent) {
861        target.attachEvent('on' + name, callback);
862      }
863    };
864    var removeEvent = function (target, name, callback, capture) {
865      if (target.removeEventListener) {
866        target.removeEventListener(name, callback, capture || false);
867      } else if (target.detachEvent) {
868        target.detachEvent('on' + name, callback);
869      }
870    };
871    var getTargetFromShadowDom = function (event, defaultTarget) {
872      if (event.composedPath) {
873        var composedPath = event.composedPath();
874        if (composedPath && composedPath.length > 0) {
875          return composedPath[0];
876        }
877      }
878      return defaultTarget;
879    };
880    var fix = function (originalEvent, data) {
881      var name;
882      var event = data || {};
883      for (name in originalEvent) {
884        if (!deprecated[name]) {
885          event[name] = originalEvent[name];
886        }
887      }
888      if (!event.target) {
889        event.target = event.srcElement || domGlobals.document;
890      }
891      if (Env.experimentalShadowDom) {
892        event.target = getTargetFromShadowDom(originalEvent, event.target);
893      }
894      if (originalEvent && mouseEventRe.test(originalEvent.type) && originalEvent.pageX === undefined && originalEvent.clientX !== undefined) {
895        var eventDoc = event.target.ownerDocument || domGlobals.document;
896        var doc = eventDoc.documentElement;
897        var body = eventDoc.body;
898        event.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
899        event.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
900      }
901      event.preventDefault = function () {
902        event.isDefaultPrevented = returnTrue;
903        if (originalEvent) {
904          if (originalEvent.preventDefault) {
905            originalEvent.preventDefault();
906          } else {
907            originalEvent.returnValue = false;
908          }
909        }
910      };
911      event.stopPropagation = function () {
912        event.isPropagationStopped = returnTrue;
913        if (originalEvent) {
914          if (originalEvent.stopPropagation) {
915            originalEvent.stopPropagation();
916          } else {
917            originalEvent.cancelBubble = true;
918          }
919        }
920      };
921      event.stopImmediatePropagation = function () {
922        event.isImmediatePropagationStopped = returnTrue;
923        event.stopPropagation();
924      };
925      if (hasIsDefaultPrevented(event) === false) {
926        event.isDefaultPrevented = returnFalse;
927        event.isPropagationStopped = returnFalse;
928        event.isImmediatePropagationStopped = returnFalse;
929      }
930      if (typeof event.metaKey === 'undefined') {
931        event.metaKey = false;
932      }
933      return event;
934    };
935    var bindOnReady = function (win, callback, eventUtils) {
936      var doc = win.document, event = { type: 'ready' };
937      if (eventUtils.domLoaded) {
938        callback(event);
939        return;
940      }
941      var isDocReady = function () {
942        return doc.readyState === 'complete' || doc.readyState === 'interactive' && doc.body;
943      };
944      var readyHandler = function () {
945        removeEvent(win, 'DOMContentLoaded', readyHandler);
946        removeEvent(win, 'load', readyHandler);
947        if (!eventUtils.domLoaded) {
948          eventUtils.domLoaded = true;
949          callback(event);
950        }
951      };
952      var waitForDomLoaded = function () {
953        if (isDocReady()) {
954          removeEvent(doc, 'readystatechange', waitForDomLoaded);
955          readyHandler();
956        }
957      };
958      var tryScroll = function () {
959        try {
960          doc.documentElement.doScroll('left');
961        } catch (ex) {
962          Delay.setTimeout(tryScroll);
963          return;
964        }
965        readyHandler();
966      };
967      if (doc.addEventListener && !(Env.ie && Env.ie < 11)) {
968        if (isDocReady()) {
969          readyHandler();
970        } else {
971          addEvent(win, 'DOMContentLoaded', readyHandler);
972        }
973      } else {
974        addEvent(doc, 'readystatechange', waitForDomLoaded);
975        if (doc.documentElement.doScroll && win.self === win.top) {
976          tryScroll();
977        }
978      }
979      addEvent(win, 'load', readyHandler);
980    };
981    var EventUtils = function () {
982      function EventUtils() {
983        this.domLoaded = false;
984        this.events = {};
985        this.count = 1;
986        this.expando = eventExpandoPrefix + (+new Date()).toString(32);
987        this.hasMouseEnterLeave = 'onmouseenter' in domGlobals.document.documentElement;
988        this.hasFocusIn = 'onfocusin' in domGlobals.document.documentElement;
989        this.count = 1;
990      }
991      EventUtils.prototype.bind = function (target, names, callback, scope) {
992        var self = this;
993        var id, callbackList, i, name, fakeName, nativeHandler, capture;
994        var win = domGlobals.window;
995        var defaultNativeHandler = function (evt) {
996          self.executeHandlers(fix(evt || win.event), id);
997        };
998        if (!target || target.nodeType === 3 || target.nodeType === 8) {
999          return;
1000        }
1001        if (!target[self.expando]) {
1002          id = self.count++;
1003          target[self.expando] = id;
1004          self.events[id] = {};
1005        } else {
1006          id = target[self.expando];
1007        }
1008        scope = scope || target;
1009        var namesList = names.split(' ');
1010        i = namesList.length;
1011        while (i--) {
1012          name = namesList[i];
1013          nativeHandler = defaultNativeHandler;
1014          fakeName = capture = false;
1015          if (name === 'DOMContentLoaded') {
1016            name = 'ready';
1017          }
1018          if (self.domLoaded && name === 'ready' && target.readyState === 'complete') {
1019            callback.call(scope, fix({ type: name }));
1020            continue;
1021          }
1022          if (!self.hasMouseEnterLeave) {
1023            fakeName = self.mouseEnterLeave[name];
1024            if (fakeName) {
1025              nativeHandler = function (evt) {
1026                var current, related;
1027                current = evt.currentTarget;
1028                related = evt.relatedTarget;
1029                if (related && current.contains) {
1030                  related = current.contains(related);
1031                } else {
1032                  while (related && related !== current) {
1033                    related = related.parentNode;
1034                  }
1035                }
1036                if (!related) {
1037                  evt = fix(evt || win.event);
1038                  evt.type = evt.type === 'mouseout' ? 'mouseleave' : 'mouseenter';
1039                  evt.target = current;
1040                  self.executeHandlers(evt, id);
1041                }
1042              };
1043            }
1044          }
1045          if (!self.hasFocusIn && (name === 'focusin' || name === 'focusout')) {
1046            capture = true;
1047            fakeName = name === 'focusin' ? 'focus' : 'blur';
1048            nativeHandler = function (evt) {
1049              evt = fix(evt || win.event);
1050              evt.type = evt.type === 'focus' ? 'focusin' : 'focusout';
1051              self.executeHandlers(evt, id);
1052            };
1053          }
1054          callbackList = self.events[id][name];
1055          if (!callbackList) {
1056            self.events[id][name] = callbackList = [{
1057                func: callback,
1058                scope: scope
1059              }];
1060            callbackList.fakeName = fakeName;
1061            callbackList.capture = capture;
1062            callbackList.nativeHandler = nativeHandler;
1063            if (name === 'ready') {
1064              bindOnReady(target, nativeHandler, self);
1065            } else {
1066              addEvent(target, fakeName || name, nativeHandler, capture);
1067            }
1068          } else {
1069            if (name === 'ready' && self.domLoaded) {
1070              callback(fix({ type: name }));
1071            } else {
1072              callbackList.push({
1073                func: callback,
1074                scope: scope
1075              });
1076            }
1077          }
1078        }
1079        target = callbackList = 0;
1080        return callback;
1081      };
1082      EventUtils.prototype.unbind = function (target, names, callback) {
1083        var id, callbackList, i, ci, name, eventMap;
1084        if (!target || target.nodeType === 3 || target.nodeType === 8) {
1085          return this;
1086        }
1087        id = target[this.expando];
1088        if (id) {
1089          eventMap = this.events[id];
1090          if (names) {
1091            var namesList = names.split(' ');
1092            i = namesList.length;
1093            while (i--) {
1094              name = namesList[i];
1095              callbackList = eventMap[name];
1096              if (callbackList) {
1097                if (callback) {
1098                  ci = callbackList.length;
1099                  while (ci--) {
1100                    if (callbackList[ci].func === callback) {
1101                      var nativeHandler = callbackList.nativeHandler;
1102                      var fakeName = callbackList.fakeName, capture = callbackList.capture;
1103                      callbackList = callbackList.slice(0, ci).concat(callbackList.slice(ci + 1));
1104                      callbackList.nativeHandler = nativeHandler;
1105                      callbackList.fakeName = fakeName;
1106                      callbackList.capture = capture;
1107                      eventMap[name] = callbackList;
1108                    }
1109                  }
1110                }
1111                if (!callback || callbackList.length === 0) {
1112                  delete eventMap[name];
1113                  removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
1114                }
1115              }
1116            }
1117          } else {
1118            for (name in eventMap) {
1119              callbackList = eventMap[name];
1120              removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
1121            }
1122            eventMap = {};
1123          }
1124          for (name in eventMap) {
1125            return this;
1126          }
1127          delete this.events[id];
1128          try {
1129            delete target[this.expando];
1130          } catch (ex) {
1131            target[this.expando] = null;
1132          }
1133        }
1134        return this;
1135      };
1136      EventUtils.prototype.fire = function (target, name, args) {
1137        var id;
1138        if (!target || target.nodeType === 3 || target.nodeType === 8) {
1139          return this;
1140        }
1141        var event = fix(null, args);
1142        event.type = name;
1143        event.target = target;
1144        do {
1145          id = target[this.expando];
1146          if (id) {
1147            this.executeHandlers(event, id);
1148          }
1149          target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow;
1150        } while (target && !event.isPropagationStopped());
1151        return this;
1152      };
1153      EventUtils.prototype.clean = function (target) {
1154        var i, children;
1155        if (!target || target.nodeType === 3 || target.nodeType === 8) {
1156          return this;
1157        }
1158        if (target[this.expando]) {
1159          this.unbind(target);
1160        }
1161        if (!target.getElementsByTagName) {
1162          target = target.document;
1163        }
1164        if (target && target.getElementsByTagName) {
1165          this.unbind(target);
1166          children = target.getElementsByTagName('*');
1167          i = children.length;
1168          while (i--) {
1169            target = children[i];
1170            if (target[this.expando]) {
1171              this.unbind(target);
1172            }
1173          }
1174        }
1175        return this;
1176      };
1177      EventUtils.prototype.destroy = function () {
1178        this.events = {};
1179      };
1180      EventUtils.prototype.cancel = function (e) {
1181        if (e) {
1182          e.preventDefault();
1183          e.stopImmediatePropagation();
1184        }
1185        return false;
1186      };
1187      EventUtils.prototype.executeHandlers = function (evt, id) {
1188        var callbackList, i, l, callback;
1189        var container = this.events[id];
1190        callbackList = container && container[evt.type];
1191        if (callbackList) {
1192          for (i = 0, l = callbackList.length; i < l; i++) {
1193            callback = callbackList[i];
1194            if (callback && callback.func.call(callback.scope, evt) === false) {
1195              evt.preventDefault();
1196            }
1197            if (evt.isImmediatePropagationStopped()) {
1198              return;
1199            }
1200          }
1201        }
1202      };
1203      EventUtils.Event = new EventUtils();
1204      return EventUtils;
1205    }();
1206
1207    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) {
1208        if (a === b) {
1209          hasDuplicate = true;
1210        }
1211        return 0;
1212      }, strundefined = typeof undefined, MAX_NEGATIVE = 1 << 31, hasOwn = {}.hasOwnProperty, arr = [], pop = arr.pop, push_native = arr.push, push$1 = arr.push, slice$1 = arr.slice, indexOf$1 = arr.indexOf || function (elem) {
1213        var i = 0, len = this.length;
1214        for (; i < len; i++) {
1215          if (this[i] === elem) {
1216            return i;
1217          }
1218        }
1219        return -1;
1220      }, 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 = {
1221        ID: new RegExp('^#(' + identifier + ')'),
1222        CLASS: new RegExp('^\\.(' + identifier + ')'),
1223        TAG: new RegExp('^(' + identifier + '|[*])'),
1224        ATTR: new RegExp('^' + attributes),
1225        PSEUDO: new RegExp('^' + pseudos),
1226        CHILD: new RegExp('^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(' + whitespace + '*(even|odd|(([+-]|)(\\d*)n|)' + whitespace + '*(?:([+-]|)' + whitespace + '*(\\d+)|))' + whitespace + '*\\)|)', 'i'),
1227        bool: new RegExp('^(?:' + booleans + ')$', 'i'),
1228        needsContext: new RegExp('^' + whitespace + '*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(' + whitespace + '*((?:-\\d)?\\d*)' + whitespace + '*\\)|)(?=[^-]|$)', 'i')
1229      }, 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) {
1230        var high = '0x' + escaped - 65536;
1231        return high !== high || escapedWhitespace ? escaped : high < 0 ? String.fromCharCode(high + 65536) : String.fromCharCode(high >> 10 | 55296, high & 1023 | 56320);
1232      };
1233    try {
1234      push$1.apply(arr = slice$1.call(preferredDoc.childNodes), preferredDoc.childNodes);
1235      arr[preferredDoc.childNodes.length].nodeType;
1236    } catch (e) {
1237      push$1 = {
1238        apply: arr.length ? function (target, els) {
1239          push_native.apply(target, slice$1.call(els));
1240        } : function (target, els) {
1241          var j = target.length, i = 0;
1242          while (target[j++] = els[i++]) {
1243          }
1244          target.length = j - 1;
1245        }
1246      };
1247    }
1248    var Sizzle = function (selector, context, results, seed) {
1249      var match, elem, m, nodeType, i, groups, old, nid, newContext, newSelector;
1250      if ((context ? context.ownerDocument || context : preferredDoc) !== document) {
1251        setDocument(context);
1252      }
1253      context = context || document;
1254      results = results || [];
1255      if (!selector || typeof selector !== 'string') {
1256        return results;
1257      }
1258      if ((nodeType = context.nodeType) !== 1 && nodeType !== 9) {
1259        return [];
1260      }
1261      if (documentIsHTML && !seed) {
1262        if (match = rquickExpr.exec(selector)) {
1263          if (m = match[1]) {
1264            if (nodeType === 9) {
1265              elem = context.getElementById(m);
1266              if (elem && elem.parentNode) {
1267                if (elem.id === m) {
1268                  results.push(elem);
1269                  return results;
1270                }
1271              } else {
1272                return results;
1273              }
1274            } else {
1275              if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) && contains$1(context, elem) && elem.id === m) {
1276                results.push(elem);
1277                return results;
1278              }
1279            }
1280          } else if (match[2]) {
1281            push$1.apply(results, context.getElementsByTagName(selector));
1282            return results;
1283          } else if ((m = match[3]) && support.getElementsByClassName) {
1284            push$1.apply(results, context.getElementsByClassName(m));
1285            return results;
1286          }
1287        }
1288        if (support.qsa && (!rbuggyQSA || !rbuggyQSA.test(selector))) {
1289          nid = old = expando;
1290          newContext = context;
1291          newSelector = nodeType === 9 && selector;
1292          if (nodeType === 1 && context.nodeName.toLowerCase() !== 'object') {
1293            groups = tokenize(selector);
1294            if (old = context.getAttribute('id')) {
1295              nid = old.replace(rescape, '\\$&');
1296            } else {
1297              context.setAttribute('id', nid);
1298            }
1299            nid = '[id=\'' + nid + '\'] ';
1300            i = groups.length;
1301            while (i--) {
1302              groups[i] = nid + toSelector(groups[i]);
1303            }
1304            newContext = rsibling.test(selector) && testContext(context.parentNode) || context;
1305            newSelector = groups.join(',');
1306          }
1307          if (newSelector) {
1308            try {
1309              push$1.apply(results, newContext.querySelectorAll(newSelector));
1310              return results;
1311            } catch (qsaError) {
1312            } finally {
1313              if (!old) {
1314                context.removeAttribute('id');
1315              }
1316            }
1317          }
1318        }
1319      }
1320      return select(selector.replace(rtrim, '$1'), context, results, seed);
1321    };
1322    function createCache() {
1323      var keys = [];
1324      function cache(key, value) {
1325        if (keys.push(key + ' ') > Expr.cacheLength) {
1326          delete cache[keys.shift()];
1327        }
1328        return cache[key + ' '] = value;
1329      }
1330      return cache;
1331    }
1332    function markFunction(fn) {
1333      fn[expando] = true;
1334      return fn;
1335    }
1336    function siblingCheck(a, b) {
1337      var cur = b && a, diff = cur && a.nodeType === 1 && b.nodeType === 1 && (~b.sourceIndex || MAX_NEGATIVE) - (~a.sourceIndex || MAX_NEGATIVE);
1338      if (diff) {
1339        return diff;
1340      }
1341      if (cur) {
1342        while (cur = cur.nextSibling) {
1343          if (cur === b) {
1344            return -1;
1345          }
1346        }
1347      }
1348      return a ? 1 : -1;
1349    }
1350    function createInputPseudo(type) {
1351      return function (elem) {
1352        var name = elem.nodeName.toLowerCase();
1353        return name === 'input' && elem.type === type;
1354      };
1355    }
1356    function createButtonPseudo(type) {
1357      return function (elem) {
1358        var name = elem.nodeName.toLowerCase();
1359        return (name === 'input' || name === 'button') && elem.type === type;
1360      };
1361    }
1362    function createPositionalPseudo(fn) {
1363      return markFunction(function (argument) {
1364        argument = +argument;
1365        return markFunction(function (seed, matches) {
1366          var j, matchIndexes = fn([], seed.length, argument), i = matchIndexes.length;
1367          while (i--) {
1368            if (seed[j = matchIndexes[i]]) {
1369              seed[j] = !(matches[j] = seed[j]);
1370            }
1371          }
1372        });
1373      });
1374    }
1375    function testContext(context) {
1376      return context && typeof context.getElementsByTagName !== strundefined && context;
1377    }
1378    support = Sizzle.support = {};
1379    isXML = Sizzle.isXML = function (elem) {
1380      var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1381      return documentElement ? documentElement.nodeName !== 'HTML' : false;
1382    };
1383    setDocument = Sizzle.setDocument = function (node) {
1384      var hasCompare, doc = node ? node.ownerDocument || node : preferredDoc, parent = doc.defaultView;
1385      function getTop(win) {
1386        try {
1387          return win.top;
1388        } catch (ex) {
1389        }
1390        return null;
1391      }
1392      if (doc === document || doc.nodeType !== 9 || !doc.documentElement) {
1393        return document;
1394      }
1395      document = doc;
1396      docElem = doc.documentElement;
1397      documentIsHTML = !isXML(doc);
1398      if (parent && parent !== getTop(parent)) {
1399        if (parent.addEventListener) {
1400          parent.addEventListener('unload', function () {
1401            setDocument();
1402          }, false);
1403        } else if (parent.attachEvent) {
1404          parent.attachEvent('onunload', function () {
1405            setDocument();
1406          });
1407        }
1408      }
1409      support.attributes = true;
1410      support.getElementsByTagName = true;
1411      support.getElementsByClassName = rnative.test(doc.getElementsByClassName);
1412      support.getById = true;
1413      Expr.find.ID = function (id, context) {
1414        if (typeof context.getElementById !== strundefined && documentIsHTML) {
1415          var m = context.getElementById(id);
1416          return m && m.parentNode ? [m] : [];
1417        }
1418      };
1419      Expr.filter.ID = function (id) {
1420        var attrId = id.replace(runescape, funescape);
1421        return function (elem) {
1422          return elem.getAttribute('id') === attrId;
1423        };
1424      };
1425      Expr.find.TAG = support.getElementsByTagName ? function (tag, context) {
1426        if (typeof context.getElementsByTagName !== strundefined) {
1427          return context.getElementsByTagName(tag);
1428        }
1429      } : function (tag, context) {
1430        var elem, tmp = [], i = 0, results = context.getElementsByTagName(tag);
1431        if (tag === '*') {
1432          while (elem = results[i++]) {
1433            if (elem.nodeType === 1) {
1434              tmp.push(elem);
1435            }
1436          }
1437          return tmp;
1438        }
1439        return results;
1440      };
1441      Expr.find.CLASS = support.getElementsByClassName && function (className, context) {
1442        if (documentIsHTML) {
1443          return context.getElementsByClassName(className);
1444        }
1445      };
1446      rbuggyMatches = [];
1447      rbuggyQSA = [];
1448      support.disconnectedMatch = true;
1449      rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join('|'));
1450      rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join('|'));
1451      hasCompare = rnative.test(docElem.compareDocumentPosition);
1452      contains$1 = hasCompare || rnative.test(docElem.contains) ? function (a, b) {
1453        var adown = a.nodeType === 9 ? a.documentElement : a, bup = b && b.parentNode;
1454        return a === bup || !!(bup && bup.nodeType === 1 && (adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16));
1455      } : function (a, b) {
1456        if (b) {
1457          while (b = b.parentNode) {
1458            if (b === a) {
1459              return true;
1460            }
1461          }
1462        }
1463        return false;
1464      };
1465      sortOrder = hasCompare ? function (a, b) {
1466        if (a === b) {
1467          hasDuplicate = true;
1468          return 0;
1469        }
1470        var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1471        if (compare) {
1472          return compare;
1473        }
1474        compare = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : 1;
1475        if (compare & 1 || !support.sortDetached && b.compareDocumentPosition(a) === compare) {
1476          if (a === doc || a.ownerDocument === preferredDoc && contains$1(preferredDoc, a)) {
1477            return -1;
1478          }
1479          if (b === doc || b.ownerDocument === preferredDoc && contains$1(preferredDoc, b)) {
1480            return 1;
1481          }
1482          return sortInput ? indexOf$1.call(sortInput, a) - indexOf$1.call(sortInput, b) : 0;
1483        }
1484        return compare & 4 ? -1 : 1;
1485      } : function (a, b) {
1486        if (a === b) {
1487          hasDuplicate = true;
1488          return 0;
1489        }
1490        var cur, i = 0, aup = a.parentNode, bup = b.parentNode, ap = [a], bp = [b];
1491        if (!aup || !bup) {
1492          return a === doc ? -1 : b === doc ? 1 : aup ? -1 : bup ? 1 : sortInput ? indexOf$1.call(sortInput, a) - indexOf$1.call(sortInput, b) : 0;
1493        } else if (aup === bup) {
1494          return siblingCheck(a, b);
1495        }
1496        cur = a;
1497        while (cur = cur.parentNode) {
1498          ap.unshift(cur);
1499        }
1500        cur = b;
1501        while (cur = cur.parentNode) {
1502          bp.unshift(cur);
1503        }
1504        while (ap[i] === bp[i]) {
1505          i++;
1506        }
1507        return i ? siblingCheck(ap[i], bp[i]) : ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0;
1508      };
1509      return doc;
1510    };
1511    Sizzle.matches = function (expr, elements) {
1512      return Sizzle(expr, null, null, elements);
1513    };
1514    Sizzle.matchesSelector = function (elem, expr) {
1515      if ((elem.ownerDocument || elem) !== document) {
1516        setDocument(elem);
1517      }
1518      expr = expr.replace(rattributeQuotes, '=\'$1\']');
1519      if (support.matchesSelector && documentIsHTML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr))) {
1520        try {
1521          var ret = matches.call(elem, expr);
1522          if (ret || support.disconnectedMatch || elem.document && elem.document.nodeType !== 11) {
1523            return ret;
1524          }
1525        } catch (e) {
1526        }
1527      }
1528      return Sizzle(expr, document, null, [elem]).length > 0;
1529    };
1530    Sizzle.contains = function (context, elem) {
1531      if ((context.ownerDocument || context) !== document) {
1532        setDocument(context);
1533      }
1534      return contains$1(context, elem);
1535    };
1536    Sizzle.attr = function (elem, name) {
1537      if ((elem.ownerDocument || elem) !== document) {
1538        setDocument(elem);
1539      }
1540      var fn = Expr.attrHandle[name.toLowerCase()], val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined;
1541      return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;
1542    };
1543    Sizzle.error = function (msg) {
1544      throw new Error('Syntax error, unrecognized expression: ' + msg);
1545    };
1546    Sizzle.uniqueSort = function (results) {
1547      var elem, duplicates = [], j = 0, i = 0;
1548      hasDuplicate = !support.detectDuplicates;
1549      sortInput = !support.sortStable && results.slice(0);
1550      results.sort(sortOrder);
1551      if (hasDuplicate) {
1552        while (elem = results[i++]) {
1553          if (elem === results[i]) {
1554            j = duplicates.push(i);
1555          }
1556        }
1557        while (j--) {
1558          results.splice(duplicates[j], 1);
1559        }
1560      }
1561      sortInput = null;
1562      return results;
1563    };
1564    getText = Sizzle.getText = function (elem) {
1565      var node, ret = '', i = 0, nodeType = elem.nodeType;
1566      if (!nodeType) {
1567        while (node = elem[i++]) {
1568          ret += getText(node);
1569        }
1570      } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
1571        if (typeof elem.textContent === 'string') {
1572          return elem.textContent;
1573        } else {
1574          for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
1575            ret += getText(elem);
1576          }
1577        }
1578      } else if (nodeType === 3 || nodeType === 4) {
1579        return elem.nodeValue;
1580      }
1581      return ret;
1582    };
1583    Expr = Sizzle.selectors = {
1584      cacheLength: 50,
1585      createPseudo: markFunction,
1586      match: matchExpr,
1587      attrHandle: {},
1588      find: {},
1589      relative: {
1590        '>': {
1591          dir: 'parentNode',
1592          first: true
1593        },
1594        ' ': { dir: 'parentNode' },
1595        '+': {
1596          dir: 'previousSibling',
1597          first: true
1598        },
1599        '~': { dir: 'previousSibling' }
1600      },
1601      preFilter: {
1602        ATTR: function (match) {
1603          match[1] = match[1].replace(runescape, funescape);
1604          match[3] = (match[3] || match[4] || match[5] || '').replace(runescape, funescape);
1605          if (match[2] === '~=') {
1606            match[3] = ' ' + match[3] + ' ';
1607          }
1608          return match.slice(0, 4);
1609        },
1610        CHILD: function (match) {
1611          match[1] = match[1].toLowerCase();
1612          if (match[1].slice(0, 3) === 'nth') {
1613            if (!match[3]) {
1614              Sizzle.error(match[0]);
1615            }
1616            match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === 'even' || match[3] === 'odd'));
1617            match[5] = +(match[7] + match[8] || match[3] === 'odd');
1618          } else if (match[3]) {
1619            Sizzle.error(match[0]);
1620          }
1621          return match;
1622        },
1623        PSEUDO: function (match) {
1624          var excess, unquoted = !match[6] && match[2];
1625          if (matchExpr.CHILD.test(match[0])) {
1626            return null;
1627          }
1628          if (match[3]) {
1629            match[2] = match[4] || match[5] || '';
1630          } else if (unquoted && rpseudo.test(unquoted) && (excess = tokenize(unquoted, true)) && (excess = unquoted.indexOf(')', unquoted.length - excess) - unquoted.length)) {
1631            match[0] = match[0].slice(0, excess);
1632            match[2] = unquoted.slice(0, excess);
1633          }
1634          return match.slice(0, 3);
1635        }
1636      },
1637      filter: {
1638        TAG: function (nodeNameSelector) {
1639          var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();
1640          return nodeNameSelector === '*' ? function () {
1641            return true;
1642          } : function (elem) {
1643            return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1644          };
1645        },
1646        CLASS: function (className) {
1647          var pattern = classCache[className + ' '];
1648          return pattern || (pattern = new RegExp('(^|' + whitespace + ')' + className + '(' + whitespace + '|$)')) && classCache(className, function (elem) {
1649            return pattern.test(typeof elem.className === 'string' && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute('class') || '');
1650          });
1651        },
1652        ATTR: function (name, operator, check) {
1653          return function (elem) {
1654            var result = Sizzle.attr(elem, name);
1655            if (result == null) {
1656              return operator === '!=';
1657            }
1658            if (!operator) {
1659              return true;
1660            }
1661            result += '';
1662            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;
1663          };
1664        },
1665        CHILD: function (type, what, argument, first, last) {
1666          var simple = type.slice(0, 3) !== 'nth', forward = type.slice(-4) !== 'last', ofType = what === 'of-type';
1667          return first === 1 && last === 0 ? function (elem) {
1668            return !!elem.parentNode;
1669          } : function (elem, context, xml) {
1670            var cache, outerCache, node, diff, nodeIndex, start, dir = simple !== forward ? 'nextSibling' : 'previousSibling', parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), useCache = !xml && !ofType;
1671            if (parent) {
1672              if (simple) {
1673                while (dir) {
1674                  node = elem;
1675                  while (node = node[dir]) {
1676                    if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) {
1677                      return false;
1678                    }
1679                  }
1680                  start = dir = type === 'only' && !start && 'nextSibling';
1681                }
1682                return true;
1683              }
1684              start = [forward ? parent.firstChild : parent.lastChild];
1685              if (forward && useCache) {
1686                outerCache = parent[expando] || (parent[expando] = {});
1687                cache = outerCache[type] || [];
1688                nodeIndex = cache[0] === dirruns && cache[1];
1689                diff = cache[0] === dirruns && cache[2];
1690                node = nodeIndex && parent.childNodes[nodeIndex];
1691                while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) {
1692                  if (node.nodeType === 1 && ++diff && node === elem) {
1693                    outerCache[type] = [
1694                      dirruns,
1695                      nodeIndex,
1696                      diff
1697                    ];
1698                    break;
1699                  }
1700                }
1701              } else if (useCache && (cache = (elem[expando] || (elem[expando] = {}))[type]) && cache[0] === dirruns) {
1702                diff = cache[1];
1703              } else {
1704                while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) {
1705                  if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) {
1706                    if (useCache) {
1707                      (node[expando] || (node[expando] = {}))[type] = [
1708                        dirruns,
1709                        diff
1710                      ];
1711                    }
1712                    if (node === elem) {
1713                      break;
1714                    }
1715                  }
1716                }
1717              }
1718              diff -= last;
1719              return diff === first || diff % first === 0 && diff / first >= 0;
1720            }
1721          };
1722        },
1723        PSEUDO: function (pseudo, argument) {
1724          var args, fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error('unsupported pseudo: ' + pseudo);
1725          if (fn[expando]) {
1726            return fn(argument);
1727          }
1728          if (fn.length > 1) {
1729            args = [
1730              pseudo,
1731              pseudo,
1732              '',
1733              argument
1734            ];
1735            return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function (seed, matches) {
1736              var idx, matched = fn(seed, argument), i = matched.length;
1737              while (i--) {
1738                idx = indexOf$1.call(seed, matched[i]);
1739                seed[idx] = !(matches[idx] = matched[i]);
1740              }
1741            }) : function (elem) {
1742              return fn(elem, 0, args);
1743            };
1744          }
1745          return fn;
1746        }
1747      },
1748      pseudos: {
1749        not: markFunction(function (selector) {
1750          var input = [], results = [], matcher = compile(selector.replace(rtrim, '$1'));
1751          return matcher[expando] ? markFunction(function (seed, matches, context, xml) {
1752            var elem, unmatched = matcher(seed, null, xml, []), i = seed.length;
1753            while (i--) {
1754              if (elem = unmatched[i]) {
1755                seed[i] = !(matches[i] = elem);
1756              }
1757            }
1758          }) : function (elem, context, xml) {
1759            input[0] = elem;
1760            matcher(input, null, xml, results);
1761            return !results.pop();
1762          };
1763        }),
1764        has: markFunction(function (selector) {
1765          return function (elem) {
1766            return Sizzle(selector, elem).length > 0;
1767          };
1768        }),
1769        contains: markFunction(function (text) {
1770          text = text.replace(runescape, funescape);
1771          return function (elem) {
1772            return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1;
1773          };
1774        }),
1775        lang: markFunction(function (lang) {
1776          if (!ridentifier.test(lang || '')) {
1777            Sizzle.error('unsupported lang: ' + lang);
1778          }
1779          lang = lang.replace(runescape, funescape).toLowerCase();
1780          return function (elem) {
1781            var elemLang;
1782            do {
1783              if (elemLang = documentIsHTML ? elem.lang : elem.getAttribute('xml:lang') || elem.getAttribute('lang')) {
1784                elemLang = elemLang.toLowerCase();
1785                return elemLang === lang || elemLang.indexOf(lang + '-') === 0;
1786              }
1787            } while ((elem = elem.parentNode) && elem.nodeType === 1);
1788            return false;
1789          };
1790        }),
1791        target: function (elem) {
1792          var hash = domGlobals.window.location && domGlobals.window.location.hash;
1793          return hash && hash.slice(1) === elem.id;
1794        },
1795        root: function (elem) {
1796          return elem === docElem;
1797        },
1798        focus: function (elem) {
1799          return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
1800        },
1801        enabled: function (elem) {
1802          return elem.disabled === false;
1803        },
1804        disabled: function (elem) {
1805          return elem.disabled === true;
1806        },
1807        checked: function (elem) {
1808          var nodeName = elem.nodeName.toLowerCase();
1809          return nodeName === 'input' && !!elem.checked || nodeName === 'option' && !!elem.selected;
1810        },
1811        selected: function (elem) {
1812          if (elem.parentNode) {
1813            elem.parentNode.selectedIndex;
1814          }
1815          return elem.selected === true;
1816        },
1817        empty: function (elem) {
1818          for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
1819            if (elem.nodeType < 6) {
1820              return false;
1821            }
1822          }
1823          return true;
1824        },
1825        parent: function (elem) {
1826          return !Expr.pseudos.empty(elem);
1827        },
1828        header: function (elem) {
1829          return rheader.test(elem.nodeName);
1830        },
1831        input: function (elem) {
1832          return rinputs.test(elem.nodeName);
1833        },
1834        button: function (elem) {
1835          var name = elem.nodeName.toLowerCase();
1836          return name === 'input' && elem.type === 'button' || name === 'button';
1837        },
1838        text: function (elem) {
1839          var attr;
1840          return elem.nodeName.toLowerCase() === 'input' && elem.type === 'text' && ((attr = elem.getAttribute('type')) == null || attr.toLowerCase() === 'text');
1841        },
1842        first: createPositionalPseudo(function () {
1843          return [0];
1844        }),
1845        last: createPositionalPseudo(function (matchIndexes, length) {
1846          return [length - 1];
1847        }),
1848        eq: createPositionalPseudo(function (matchIndexes, length, argument) {
1849          return [argument < 0 ? argument + length : argument];
1850        }),
1851        even: createPositionalPseudo(function (matchIndexes, length) {
1852          var i = 0;
1853          for (; i < length; i += 2) {
1854            matchIndexes.push(i);
1855          }
1856          return matchIndexes;
1857        }),
1858        odd: createPositionalPseudo(function (matchIndexes, length) {
1859          var i = 1;
1860          for (; i < length; i += 2) {
1861            matchIndexes.push(i);
1862          }
1863          return matchIndexes;
1864        }),
1865        lt: createPositionalPseudo(function (matchIndexes, length, argument) {
1866          var i = argument < 0 ? argument + length : argument;
1867          for (; --i >= 0;) {
1868            matchIndexes.push(i);
1869          }
1870          return matchIndexes;
1871        }),
1872        gt: createPositionalPseudo(function (matchIndexes, length, argument) {
1873          var i = argument < 0 ? argument + length : argument;
1874          for (; ++i < length;) {
1875            matchIndexes.push(i);
1876          }
1877          return matchIndexes;
1878        })
1879      }
1880    };
1881    Expr.pseudos.nth = Expr.pseudos.eq;
1882    for (i in {
1883        radio: true,
1884        checkbox: true,
1885        file: true,
1886        password: true,
1887        image: true
1888      }) {
1889      Expr.pseudos[i] = createInputPseudo(i);
1890    }
1891    for (i in {
1892        submit: true,
1893        reset: true
1894      }) {
1895      Expr.pseudos[i] = createButtonPseudo(i);
1896    }
1897    function setFilters() {
1898    }
1899    setFilters.prototype = Expr.filters = Expr.pseudos;
1900    Expr.setFilters = new setFilters();
1901    tokenize = Sizzle.tokenize = function (selector, parseOnly) {
1902      var matched, match, tokens, type, soFar, groups, preFilters, cached = tokenCache[selector + ' '];
1903      if (cached) {
1904        return parseOnly ? 0 : cached.slice(0);
1905      }
1906      soFar = selector;
1907      groups = [];
1908      preFilters = Expr.preFilter;
1909      while (soFar) {
1910        if (!matched || (match = rcomma.exec(soFar))) {
1911          if (match) {
1912            soFar = soFar.slice(match[0].length) || soFar;
1913          }
1914          groups.push(tokens = []);
1915        }
1916        matched = false;
1917        if (match = rcombinators.exec(soFar)) {
1918          matched = match.shift();
1919          tokens.push({
1920            value: matched,
1921            type: match[0].replace(rtrim, ' ')
1922          });
1923          soFar = soFar.slice(matched.length);
1924        }
1925        for (type in Expr.filter) {
1926          if (!Expr.filter.hasOwnProperty(type))
1927            continue;
1928          if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || (match = preFilters[type](match)))) {
1929            matched = match.shift();
1930            tokens.push({
1931              value: matched,
1932              type: type,
1933              matches: match
1934            });
1935            soFar = soFar.slice(matched.length);
1936          }
1937        }
1938        if (!matched) {
1939          break;
1940        }
1941      }
1942      return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : tokenCache(selector, groups).slice(0);
1943    };
1944    function toSelector(tokens) {
1945      var i = 0, len = tokens.length, selector = '';
1946      for (; i < len; i++) {
1947        selector += tokens[i].value;
1948      }
1949      return selector;
1950    }
1951    function addCombinator(matcher, combinator, base) {
1952      var dir = combinator.dir, checkNonElements = base && dir === 'parentNode', doneName = done++;
1953      return combinator.first ? function (elem, context, xml) {
1954        while (elem = elem[dir]) {
1955          if (elem.nodeType === 1 || checkNonElements) {
1956            return matcher(elem, context, xml);
1957          }
1958        }
1959      } : function (elem, context, xml) {
1960        var oldCache, outerCache, newCache = [
1961            dirruns,
1962            doneName
1963          ];
1964        if (xml) {
1965          while (elem = elem[dir]) {
1966            if (elem.nodeType === 1 || checkNonElements) {
1967              if (matcher(elem, context, xml)) {
1968                return true;
1969              }
1970            }
1971          }
1972        } else {
1973          while (elem = elem[dir]) {
1974            if (elem.nodeType === 1 || checkNonElements) {
1975              outerCache = elem[expando] || (elem[expando] = {});
1976              if ((oldCache = outerCache[dir]) && oldCache[0] === dirruns && oldCache[1] === doneName) {
1977                return newCache[2] = oldCache[2];
1978              } else {
1979                outerCache[dir] = newCache;
1980                if (newCache[2] = matcher(elem, context, xml)) {
1981                  return true;
1982                }
1983              }
1984            }
1985          }
1986        }
1987      };
1988    }
1989    function elementMatcher(matchers) {
1990      return matchers.length > 1 ? function (elem, context, xml) {
1991        var i = matchers.length;
1992        while (i--) {
1993          if (!matchers[i](elem, context, xml)) {
1994            return false;
1995          }
1996        }
1997        return true;
1998      } : matchers[0];
1999    }
2000    function multipleContexts(selector, contexts, results) {
2001      var i = 0, len = contexts.length;
2002      for (; i < len; i++) {
2003        Sizzle(selector, contexts[i], results);
2004      }
2005      return results;
2006    }
2007    function condense(unmatched, map, filter, context, xml) {
2008      var elem, newUnmatched = [], i = 0, len = unmatched.length, mapped = map != null;
2009      for (; i < len; i++) {
2010        if (elem = unmatched[i]) {
2011          if (!filter || filter(elem, context, xml)) {
2012            newUnmatched.push(elem);
2013            if (mapped) {
2014              map.push(i);
2015            }
2016          }
2017        }
2018      }
2019      return newUnmatched;
2020    }
2021    function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) {
2022      if (postFilter && !postFilter[expando]) {
2023        postFilter = setMatcher(postFilter);
2024      }
2025      if (postFinder && !postFinder[expando]) {
2026        postFinder = setMatcher(postFinder, postSelector);
2027      }
2028      return markFunction(function (seed, results, context, xml) {
2029        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;
2030        if (matcher) {
2031          matcher(matcherIn, matcherOut, context, xml);
2032        }
2033        if (postFilter) {
2034          temp = condense(matcherOut, postMap);
2035          postFilter(temp, [], context, xml);
2036          i = temp.length;
2037          while (i--) {
2038            if (elem = temp[i]) {
2039              matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);
2040            }
2041          }
2042        }
2043        if (seed) {
2044          if (postFinder || preFilter) {
2045            if (postFinder) {
2046              temp = [];
2047              i = matcherOut.length;
2048              while (i--) {
2049                if (elem = matcherOut[i]) {
2050                  temp.push(matcherIn[i] = elem);
2051                }
2052              }
2053              postFinder(null, matcherOut = [], temp, xml);
2054            }
2055            i = matcherOut.length;
2056            while (i--) {
2057              if ((elem = matcherOut[i]) && (temp = postFinder ? indexOf$1.call(seed, elem) : preMap[i]) > -1) {
2058                seed[temp] = !(results[temp] = elem);
2059              }
2060            }
2061          }
2062        } else {
2063          matcherOut = condense(matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut);
2064          if (postFinder) {
2065            postFinder(null, results, matcherOut, xml);
2066          } else {
2067            push$1.apply(results, matcherOut);
2068          }
2069        }
2070      });
2071    }
2072    function matcherFromTokens(tokens) {
2073      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) {
2074          return elem === checkContext;
2075        }, implicitRelative, true), matchAnyContext = addCombinator(function (elem) {
2076          return indexOf$1.call(checkContext, elem) > -1;
2077        }, implicitRelative, true), matchers = [function (elem, context, xml) {
2078            return !leadingRelative && (xml || context !== outermostContext) || ((checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml));
2079          }];
2080      for (; i < len; i++) {
2081        if (matcher = Expr.relative[tokens[i].type]) {
2082          matchers = [addCombinator(elementMatcher(matchers), matcher)];
2083        } else {
2084          matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches);
2085          if (matcher[expando]) {
2086            j = ++i;
2087            for (; j < len; j++) {
2088              if (Expr.relative[tokens[j].type]) {
2089                break;
2090              }
2091            }
2092            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));
2093          }
2094          matchers.push(matcher);
2095        }
2096      }
2097      return elementMatcher(matchers);
2098    }
2099    function matcherFromGroupMatchers(elementMatchers, setMatchers) {
2100      var bySet = setMatchers.length > 0, byElement = elementMatchers.length > 0, superMatcher = function (seed, context, xml, results, outermost) {
2101          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;
2102          if (outermost) {
2103            outermostContext = context !== document && context;
2104          }
2105          for (; i !== len && (elem = elems[i]) != null; i++) {
2106            if (byElement && elem) {
2107              j = 0;
2108              while (matcher = elementMatchers[j++]) {
2109                if (matcher(elem, context, xml)) {
2110                  results.push(elem);
2111                  break;
2112                }
2113              }
2114              if (outermost) {
2115                dirruns = dirrunsUnique;
2116              }
2117            }
2118            if (bySet) {
2119              if (elem = !matcher && elem) {
2120                matchedCount--;
2121              }
2122              if (seed) {
2123                unmatched.push(elem);
2124              }
2125            }
2126          }
2127          matchedCount += i;
2128          if (bySet && i !== matchedCount) {
2129            j = 0;
2130            while (matcher = setMatchers[j++]) {
2131              matcher(unmatched, setMatched, context, xml);
2132            }
2133            if (seed) {
2134              if (matchedCount > 0) {
2135                while (i--) {
2136                  if (!(unmatched[i] || setMatched[i])) {
2137                    setMatched[i] = pop.call(results);
2138                  }
2139                }
2140              }
2141              setMatched = condense(setMatched);
2142            }
2143            push$1.apply(results, setMatched);
2144            if (outermost && !seed && setMatched.length > 0 && matchedCount + setMatchers.length > 1) {
2145              Sizzle.uniqueSort(results);
2146            }
2147          }
2148          if (outermost) {
2149            dirruns = dirrunsUnique;
2150            outermostContext = contextBackup;
2151          }
2152          return unmatched;
2153        };
2154      return bySet ? markFunction(superMatcher) : superMatcher;
2155    }
2156    compile = Sizzle.compile = function (selector, match) {
2157      var i, setMatchers = [], elementMatchers = [], cached = compilerCache[selector + ' '];
2158      if (!cached) {
2159        if (!match) {
2160          match = tokenize(selector);
2161        }
2162        i = match.length;
2163        while (i--) {
2164          cached = matcherFromTokens(match[i]);
2165          if (cached[expando]) {
2166            setMatchers.push(cached);
2167          } else {
2168            elementMatchers.push(cached);
2169          }
2170        }
2171        cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers));
2172        cached.selector = selector;
2173      }
2174      return cached;
2175    };
2176    select = Sizzle.select = function (selector, context, results, seed) {
2177      var i, tokens, token, type, find, compiled = typeof selector === 'function' && selector, match = !seed && tokenize(selector = compiled.selector || selector);
2178      results = results || [];
2179      if (match.length === 1) {
2180        tokens = match[0] = match[0].slice(0);
2181        if (tokens.length > 2 && (token = tokens[0]).type === 'ID' && support.getById && context.nodeType === 9 && documentIsHTML && Expr.relative[tokens[1].type]) {
2182          context = (Expr.find.ID(token.matches[0].replace(runescape, funescape), context) || [])[0];
2183          if (!context) {
2184            return results;
2185          } else if (compiled) {
2186            context = context.parentNode;
2187          }
2188          selector = selector.slice(tokens.shift().value.length);
2189        }
2190        i = matchExpr.needsContext.test(selector) ? 0 : tokens.length;
2191        while (i--) {
2192          token = tokens[i];
2193          if (Expr.relative[type = token.type]) {
2194            break;
2195          }
2196          if (find = Expr.find[type]) {
2197            if (seed = find(token.matches[0].replace(runescape, funescape), rsibling.test(tokens[0].type) && testC
2197ontext(context.parentNode) || context)) {
2198              tokens.splice(i, 1);
2199              selector = seed.length && toSelector(tokens);
2200              if (!selector) {
2201                push$1.apply(results, seed);
2202                return results;
2203              }
2204              break;
2205            }
2206          }
2207        }
2208      }
2209      (compiled || compile(selector, match))(seed, context, !documentIsHTML, results, rsibling.test(selector) && testContext(context.parentNode) || context);
2210      return results;
2211    };
2212    support.sortStable = expando.split('').sort(sortOrder).join('') === expando;
2213    support.detectDuplicates = !!hasDuplicate;
2214    setDocument();
2215    support.sortDetached = true;
2216
2217    var isArray$1 = Array.isArray;
2218    var toArray = function (obj) {
2219      var array = obj, i, l;
2220      if (!isArray$1(obj)) {
2221        array = [];
2222        for (i = 0, l = obj.length; i < l; i++) {
2223          array[i] = obj[i];
2224        }
2225      }
2226      return array;
2227    };
2228    var each$1 = function (o, cb, s) {
2229      var n, l;
2230      if (!o) {
2231        return 0;
2232      }
2233      s = s || o;
2234      if (o.length !== undefined) {
2235        for (n = 0, l = o.length; n < l; n++) {
2236          if (cb.call(s, o[n], n, o) === false) {
2237            return 0;
2238          }
2239        }
2240      } else {
2241        for (n in o) {
2242          if (o.hasOwnProperty(n)) {
2243            if (cb.call(s, o[n], n, o) === false) {
2244              return 0;
2245            }
2246          }
2247        }
2248      }
2249      return 1;
2250    };
2251    var map$1 = function (array, callback) {
2252      var out = [];
2253      each$1(array, function (item, index) {
2254        out.push(callback(item, index, array));
2255      });
2256      return out;
2257    };
2258    var filter$1 = function (a, f) {
2259      var o = [];
2260      each$1(a, function (v, index) {
2261        if (!f || f(v, index, a)) {
2262          o.push(v);
2263        }
2264      });
2265      return o;
2266    };
2267    var indexOf$2 = function (a, v) {
2268      var i, l;
2269      if (a) {
2270        for (i = 0, l = a.length; i < l; i++) {
2271          if (a[i] === v) {
2272            return i;
2273          }
2274        }
2275      }
2276      return -1;
2277    };
2278    var reduce = function (collection, iteratee, accumulator, thisArg) {
2279      var i = 0;
2280      if (arguments.length < 3) {
2281        accumulator = collection[0];
2282      }
2283      for (; i < collection.length; i++) {
2284        accumulator = iteratee.call(thisArg, accumulator, collection[i], i);
2285      }
2286      return accumulator;
2287    };
2288    var findIndex$1 = function (array, predicate, thisArg) {
2289      var i, l;
2290      for (i = 0, l = array.length; i < l; i++) {
2291        if (predicate.call(thisArg, array[i], i, array)) {
2292          return i;
2293        }
2294      }
2295      return -1;
2296    };
2297    var find$1 = function (array, predicate, thisArg) {
2298      var idx = findIndex$1(array, predicate, thisArg);
2299      if (idx !== -1) {
2300        return array[idx];
2301      }
2302      return undefined;
2303    };
2304    var last$1 = function (collection) {
2305      return collection[collection.length - 1];
2306    };
2307    var ArrUtils = {
2308      isArray: isArray$1,
2309      toArray: toArray,
2310      each: each$1,
2311      map: map$1,
2312      filter: filter$1,
2313      indexOf: indexOf$2,
2314      reduce: reduce,
2315      findIndex: findIndex$1,
2316      find: find$1,
2317      last: last$1
2318    };
2319
2320    var whiteSpaceRegExp = /^\s*|\s*$/g;
2321    var trim = function (str) {
2322      return str === null || str === undefined ? '' : ('' + str).replace(whiteSpaceRegExp, '');
2323    };
2324    var is = function (obj, type) {
2325      if (!type) {
2326        return obj !== undefined;
2327      }
2328      if (type === 'array' && ArrUtils.isArray(obj)) {
2329        return true;
2330      }
2331      return typeof obj === type;
2332    };
2333    var makeMap = function (items, delim, map) {
2334      var i;
2335      items = items || [];
2336      delim = delim || ',';
2337      if (typeof items === 'string') {
2338        items = items.split(delim);
2339      }
2340      map = map || {};
2341      i = items.length;
2342      while (i--) {
2343        map[items[i]] = {};
2344      }
2345      return map;
2346    };
2347    var hasOwnProperty = function (obj, prop) {
2348      return Object.prototype.hasOwnProperty.call(obj, prop);
2349    };
2350    var create = function (s, p, root) {
2351      var self = this;
2352      var sp, ns, cn, scn, c, de = 0;
2353      s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
2354      cn = s[3].match(/(^|\.)(\w+)$/i)[2];
2355      ns = self.createNS(s[3].replace(/\.\w+$/, ''), root);
2356      if (ns[cn]) {
2357        return;
2358      }
2359      if (s[2] === 'static') {
2360        ns[cn] = p;
2361        if (this.onCreate) {
2362          this.onCreate(s[2], s[3], ns[cn]);
2363        }
2364        return;
2365      }
2366      if (!p[cn]) {
2367        p[cn] = function () {
2368        };
2369        de = 1;
2370      }
2371      ns[cn] = p[cn];
2372      self.extend(ns[cn].prototype, p);
2373      if (s[5]) {
2374        sp = self.resolve(s[5]).prototype;
2375        scn = s[5].match(/\.(\w+)$/i)[1];
2376        c = ns[cn];
2377        if (de) {
2378          ns[cn] = function () {
2379            return sp[scn].apply(this, arguments);
2380          };
2381        } else {
2382          ns[cn] = function () {
2383            this.parent = sp[scn];
2384            return c.apply(this, arguments);
2385          };
2386        }
2387        ns[cn].prototype[cn] = ns[cn];
2388        self.each(sp, function (f, n) {
2389          ns[cn].prototype[n] = sp[n];
2390        });
2391        self.each(p, function (f, n) {
2392          if (sp[n]) {
2393            ns[cn].prototype[n] = function () {
2394              this.parent = sp[n];
2395              return f.apply(this, arguments);
2396            };
2397          } else {
2398            if (n !== cn) {
2399              ns[cn].prototype[n] = f;
2400            }
2401          }
2402        });
2403      }
2404      self.each(p.static, function (f, n) {
2405        ns[cn][n] = f;
2406      });
2407    };
2408    var extend = function (obj, ext) {
2409      var x = [];
2410      for (var _i = 2; _i < arguments.length; _i++) {
2411        x[_i - 2] = arguments[_i];
2412      }
2413      var i, l, name;
2414      var args = arguments;
2415      var value;
2416      for (i = 1, l = args.length; i < l; i++) {
2417        ext = args[i];
2418        for (name in ext) {
2419          if (ext.hasOwnProperty(name)) {
2420            value = ext[name];
2421            if (value !== undefined) {
2422              obj[name] = value;
2423            }
2424          }
2425        }
2426      }
2427      return obj;
2428    };
2429    var walk = function (o, f, n, s) {
2430      s = s || this;
2431      if (o) {
2432        if (n) {
2433          o = o[n];
2434        }
2435        ArrUtils.each(o, function (o, i) {
2436          if (f.call(s, o, i, n) === false) {
2437            return false;
2438          }
2439          walk(o, f, n, s);
2440        });
2441      }
2442    };
2443    var createNS = function (n, o) {
2444      var i, v;
2445      o = o || domGlobals.window;
2446      n = n.split('.');
2447      for (i = 0; i < n.length; i++) {
2448        v = n[i];
2449        if (!o[v]) {
2450          o[v] = {};
2451        }
2452        o = o[v];
2453      }
2454      return o;
2455    };
2456    var resolve$1 = function (n, o) {
2457      var i, l;
2458      o = o || domGlobals.window;
2459      n = n.split('.');
2460      for (i = 0, l = n.length; i < l; i++) {
2461        o = o[n[i]];
2462        if (!o) {
2463          break;
2464        }
2465      }
2466      return o;
2467    };
2468    var explode = function (s, d) {
2469      if (!s || is(s, 'array')) {
2470        return s;
2471      }
2472      return ArrUtils.map(s.split(d || ','), trim);
2473    };
2474    var _addCacheSuffix = function (url) {
2475      var cacheSuffix = Env.cacheSuffix;
2476      if (cacheSuffix) {
2477        url += (url.indexOf('?') === -1 ? '?' : '&') + cacheSuffix;
2478      }
2479      return url;
2480    };
2481    var Tools = {
2482      trim: trim,
2483      isArray: ArrUtils.isArray,
2484      is: is,
2485      toArray: ArrUtils.toArray,
2486      makeMap: makeMap,
2487      each: ArrUtils.each,
2488      map: ArrUtils.map,
2489      grep: ArrUtils.filter,
2490      inArray: ArrUtils.indexOf,
2491      hasOwn: hasOwnProperty,
2492      extend: extend,
2493      create: create,
2494      walk: walk,
2495      createNS: createNS,
2496      resolve: resolve$1,
2497      explode: explode,
2498      _addCacheSuffix: _addCacheSuffix
2499    };
2500
2501    var doc = domGlobals.document, push$2 = Array.prototype.push, slice$2 = Array.prototype.slice;
2502    var rquickExpr$1 = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;
2503    var Event = EventUtils.Event;
2504    var skipUniques = Tools.makeMap('children,contents,next,prev');
2505    var isDefined = function (obj) {
2506      return typeof obj !== 'undefined';
2507    };
2508    var isString$1 = function (obj) {
2509      return typeof obj === 'string';
2510    };
2511    var isWindow = function (obj) {
2512      return obj && obj === obj.window;
2513    };
2514    var createFragment = function (html, fragDoc) {
2515      var frag, node, container;
2516      fragDoc = fragDoc || doc;
2517      container = fragDoc.createElement('div');
2518      frag = fragDoc.createDocumentFragment();
2519      container.innerHTML = html;
2520      while (node = container.firstChild) {
2521        frag.appendChild(node);
2522      }
2523      return frag;
2524    };
2525    var domManipulate = function (targetNodes, sourceItem, callback, reverse) {
2526      var i;
2527      if (isString$1(sourceItem)) {
2528        sourceItem = createFragment(sourceItem, getElementDocument(targetNodes[0]));
2529      } else if (sourceItem.length && !sourceItem.nodeType) {
2530        sourceItem = DomQuery.makeArray(sourceItem);
2531        if (reverse) {
2532          for (i = sourceItem.length - 1; i >= 0; i--) {
2533            domManipulate(targetNodes, sourceItem[i], callback, reverse);
2534          }
2535        } else {
2536          for (i = 0; i < sourceItem.length; i++) {
2537            domManipulate(targetNodes, sourceItem[i], callback, reverse);
2538          }
2539        }
2540        return targetNodes;
2541      }
2542      if (sourceItem.nodeType) {
2543        i = targetNodes.length;
2544        while (i--) {
2545          callback.call(targetNodes[i], sourceItem);
2546        }
2547      }
2548      return targetNodes;
2549    };
2550    var hasClass = function (node, className) {
2551      return node && className && (' ' + node.className + ' ').indexOf(' ' + className + ' ') !== -1;
2552    };
2553    var wrap = function (elements, wrapper, all) {
2554      var lastParent, newWrapper;
2555      wrapper = DomQuery(wrapper)[0];
2556      elements.each(function () {
2557        var self = this;
2558        if (!all || lastParent !== self.parentNode) {
2559          lastParent = self.parentNode;
2560          newWrapper = wrapper.cloneNode(false);
2561          self.parentNode.insertBefore(newWrapper, self);
2562          newWrapper.appendChild(self);
2563        } else {
2564          newWrapper.appendChild(self);
2565        }
2566      });
2567      return elements;
2568    };
2569    var numericCssMap = Tools.makeMap('fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom', ' ');
2570    var booleanMap = Tools.makeMap('checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected', ' ');
2571    var propFix = {
2572      for: 'htmlFor',
2573      class: 'className',
2574      readonly: 'readOnly'
2575    };
2576    var cssFix = { float: 'cssFloat' };
2577    var attrHooks = {}, cssHooks = {};
2578    var DomQueryConstructor = function (selector, context) {
2579      return new DomQuery.fn.init(selector, context);
2580    };
2581    var inArray = function (item, array) {
2582      var i;
2583      if (array.indexOf) {
2584        return array.indexOf(item);
2585      }
2586      i = array.length;
2587      while (i--) {
2588        if (array[i] === item) {
2589          return i;
2590        }
2591      }
2592      return -1;
2593    };
2594    var whiteSpaceRegExp$1 = /^\s*|\s*$/g;
2595    var trim$1 = function (str) {
2596      return str === null || str === undefined ? '' : ('' + str).replace(whiteSpaceRegExp$1, '');
2597    };
2598    var each$2 = function (obj, callback) {
2599      var length, key, i, value;
2600      if (obj) {
2601        length = obj.length;
2602        if (length === undefined) {
2603          for (key in obj) {
2604            if (obj.hasOwnProperty(key)) {
2605              value = obj[key];
2606              if (callback.call(value, key, value) === false) {
2607                break;
2608              }
2609            }
2610          }
2611        } else {
2612          for (i = 0; i < length; i++) {
2613            value = obj[i];
2614            if (callback.call(value, i, value) === false) {
2615              break;
2616            }
2617          }
2618        }
2619      }
2620      return obj;
2621    };
2622    var grep = function (array, callback) {
2623      var out = [];
2624      each$2(array, function (i, item) {
2625        if (callback(item, i)) {
2626          out.push(item);
2627        }
2628      });
2629      return out;
2630    };
2631    var getElementDocument = function (element) {
2632      if (!element) {
2633        return doc;
2634      }
2635      if (element.nodeType === 9) {
2636        return element;
2637      }
2638      return element.ownerDocument;
2639    };
2640    DomQueryConstructor.fn = DomQueryConstructor.prototype = {
2641      constructor: DomQueryConstructor,
2642      selector: '',
2643      context: null,
2644      length: 0,
2645      init: function (selector, context) {
2646        var self = this;
2647        var match, node;
2648        if (!selector) {
2649          return self;
2650        }
2651        if (selector.nodeType) {
2652          self.context = self[0] = selector;
2653          self.length = 1;
2654          return self;
2655        }
2656        if (context && context.nodeType) {
2657          self.context = context;
2658        } else {
2659          if (context) {
2660            return DomQuery(selector).attr(context);
2661          }
2662          self.context = context = domGlobals.document;
2663        }
2664        if (isString$1(selector)) {
2665          self.selector = selector;
2666          if (selector.charAt(0) === '<' && selector.charAt(selector.length - 1) === '>' && selector.length >= 3) {
2667            match = [
2668              null,
2669              selector,
2670              null
2671            ];
2672          } else {
2673            match = rquickExpr$1.exec(selector);
2674          }
2675          if (match) {
2676            if (match[1]) {
2677              node = createFragment(selector, getElementDocument(context)).firstChild;
2678              while (node) {
2679                push$2.call(self, node);
2680                node = node.nextSibling;
2681              }
2682            } else {
2683              node = getElementDocument(context).getElementById(match[2]);
2684              if (!node) {
2685                return self;
2686              }
2687              if (node.id !== match[2]) {
2688                return self.find(selector);
2689              }
2690              self.length = 1;
2691              self[0] = node;
2692            }
2693          } else {
2694            return DomQuery(context).find(selector);
2695          }
2696        } else {
2697          this.add(selector, false);
2698        }
2699        return self;
2700      },
2701      toArray: function () {
2702        return Tools.toArray(this);
2703      },
2704      add: function (items, sort) {
2705        var self = this;
2706        var nodes, i;
2707        if (isString$1(items)) {
2708          return self.add(DomQuery(items));
2709        }
2710        if (sort !== false) {
2711          nodes = DomQuery.unique(self.toArray().concat(DomQuery.makeArray(items)));
2712          self.length = nodes.length;
2713          for (i = 0; i < nodes.length; i++) {
2714            self[i] = nodes[i];
2715          }
2716        } else {
2717          push$2.apply(self, DomQuery.makeArray(items));
2718        }
2719        return self;
2720      },
2721      attr: function (name, value) {
2722        var self = this;
2723        var hook;
2724        if (typeof name === 'object') {
2725          each$2(name, function (name, value) {
2726            self.attr(name, value);
2727          });
2728        } else if (isDefined(value)) {
2729          this.each(function () {
2730            var hook;
2731            if (this.nodeType === 1) {
2732              hook = attrHooks[name];
2733              if (hook && hook.set) {
2734                hook.set(this, value);
2735                return;
2736              }
2737              if (value === null) {
2738                this.removeAttribute(name, 2);
2739              } else {
2740                this.setAttribute(name, value, 2);
2741              }
2742            }
2743          });
2744        } else {
2745          if (self[0] && self[0].nodeType === 1) {
2746            hook = attrHooks[name];
2747            if (hook && hook.get) {
2748              return hook.get(self[0], name);
2749            }
2750            if (booleanMap[name]) {
2751              return self.prop(name) ? name : undefined;
2752            }
2753            value = self[0].getAttribute(name, 2);
2754            if (value === null) {
2755              value = undefined;
2756            }
2757          }
2758          return value;
2759        }
2760        return self;
2761      },
2762      removeAttr: function (name) {
2763        return this.attr(name, null);
2764      },
2765      prop: function (name, value) {
2766        var self = this;
2767        name = propFix[name] || name;
2768        if (typeof name === 'object') {
2769          each$2(name, function (name, value) {
2770            self.prop(name, value);
2771          });
2772        } else if (isDefined(value)) {
2773          this.each(function () {
2774            if (this.nodeType === 1) {
2775              this[name] = value;
2776            }
2777          });
2778        } else {
2779          if (self[0] && self[0].nodeType && name in self[0]) {
2780            return self[0][name];
2781          }
2782          return value;
2783        }
2784        return self;
2785      },
2786      css: function (name, value) {
2787        var self = this;
2788        var elm, hook;
2789        var camel = function (name) {
2790          return name.replace(/-(\D)/g, function (a, b) {
2791            return b.toUpperCase();
2792          });
2793        };
2794        var dashed = function (name) {
2795          return name.replace(/[A-Z]/g, function (a) {
2796            return '-' + a;
2797          });
2798        };
2799        if (typeof name === 'object') {
2800          each$2(name, function (name, value) {
2801            self.css(name, value);
2802          });
2803        } else {
2804          if (isDefined(value)) {
2805            name = camel(name);
2806            if (typeof value === 'number' && !numericCssMap[name]) {
2807              value = value.toString() + 'px';
2808            }
2809            self.each(function () {
2810              var style = this.style;
2811              hook = cssHooks[name];
2812              if (hook && hook.set) {
2813                hook.set(this, value);
2814                return;
2815              }
2816              try {
2817                this.style[cssFix[name] || name] = value;
2818              } catch (ex) {
2819              }
2820              if (value === null || value === '') {
2821                if (style.removeProperty) {
2822                  style.removeProperty(dashed(name));
2823                } else {
2824                  style.removeAttribute(name);
2825                }
2826              }
2827            });
2828          } else {
2829            elm = self[0];
2830            hook = cssHooks[name];
2831            if (hook && hook.get) {
2832              return hook.get(elm);
2833            }
2834            if (elm.ownerDocument.defaultView) {
2835              try {
2836                return elm.ownerDocument.defaultView.getComputedStyle(elm, null).getPropertyValue(dashed(name));
2837              } catch (ex) {
2838                return undefined;
2839              }
2840            } else if (elm.currentStyle) {
2841              return elm.currentStyle[camel(name)];
2842            } else {
2843              return '';
2844            }
2845          }
2846        }
2847        return self;
2848      },
2849      remove: function () {
2850        var self = this;
2851        var node, i = this.length;
2852        while (i--) {
2853          node = self[i];
2854          Event.clean(node);
2855          if (node.parentNode) {
2856            node.parentNode.removeChild(node);
2857          }
2858        }
2859        return this;
2860      },
2861      empty: function () {
2862        var self = this;
2863        var node, i = this.length;
2864        while (i--) {
2865          node = self[i];
2866          while (node.firstChild) {
2867            node.removeChild(node.firstChild);
2868          }
2869        }
2870        return this;
2871      },
2872      html: function (value) {
2873        var self = this;
2874        var i;
2875        if (isDefined(value)) {
2876          i = self.length;
2877          try {
2878            while (i--) {
2879              self[i].innerHTML = value;
2880            }
2881          } catch (ex) {
2882            DomQuery(self[i]).empty().append(value);
2883          }
2884          return self;
2885        }
2886        return self[0] ? self[0].innerHTML : '';
2887      },
2888      text: function (value) {
2889        var self = this;
2890        var i;
2891        if (isDefined(value)) {
2892          i = self.length;
2893          while (i--) {
2894            if ('innerText' in self[i]) {
2895              self[i].innerText = value;
2896            } else {
2897              self[0].textContent = value;
2898            }
2899          }
2900          return self;
2901        }
2902        return self[0] ? self[0].innerText || self[0].textContent : '';
2903      },
2904      append: function () {
2905        return domManipulate(this, arguments, function (node) {
2906          if (this.nodeType === 1 || this.host && this.host.nodeType === 1) {
2907            this.appendChild(node);
2908          }
2909        });
2910      },
2911      prepend: function () {
2912        return domManipulate(this, arguments, function (node) {
2913          if (this.nodeType === 1 || this.host && this.host.nodeType === 1) {
2914            this.insertBefore(node, this.firstChild);
2915          }
2916        }, true);
2917      },
2918      before: function () {
2919        var self = this;
2920        if (self[0] && self[0].parentNode) {
2921          return domManipulate(self, arguments, function (node) {
2922            this.parentNode.insertBefore(node, this);
2923          });
2924        }
2925        return self;
2926      },
2927      after: function () {
2928        var self = this;
2929        if (self[0] && self[0].parentNode) {
2930          return domManipulate(self, arguments, function (node) {
2931            this.parentNode.insertBefore(node, this.nextSibling);
2932          }, true);
2933        }
2934        return self;
2935      },
2936      appendTo: function (val) {
2937        DomQuery(val).append(this);
2938        return this;
2939      },
2940      prependTo: function (val) {
2941        DomQuery(val).prepend(this);
2942        return this;
2943      },
2944      replaceWith: function (content) {
2945        return this.before(content).remove();
2946      },
2947      wrap: function (content) {
2948        return wrap(this, content);
2949      },
2950      wrapAll: function (content) {
2951        return wrap(this, content, true);
2952      },
2953      wrapInner: function (content) {
2954        this.each(function () {
2955          DomQuery(this).contents().wrapAll(content);
2956        });
2957        return this;
2958      },
2959      unwrap: function () {
2960        return this.parent().each(function () {
2961          DomQuery(this).replaceWith(this.childNodes);
2962        });
2963      },
2964      clone: function () {
2965        var result = [];
2966        this.each(function () {
2967          result.push(this.cloneNode(true));
2968        });
2969        return DomQuery(result);
2970      },
2971      addClass: function (className) {
2972        return this.toggleClass(className, true);
2973      },
2974      removeClass: function (className) {
2975        return this.toggleClass(className, false);
2976      },
2977      toggleClass: function (className, state) {
2978        var self = this;
2979        if (typeof className !== 'string') {
2980          return self;
2981        }
2982        if (className.indexOf(' ') !== -1) {
2983          each$2(className.split(' '), function () {
2984            self.toggleClass(this, state);
2985          });
2986        } else {
2987          self.each(function (index, node) {
2988            var existingClassName, classState;
2989            classState = hasClass(node, className);
2990            if (classState !== state) {
2991              existingClassName = node.className;
2992              if (classState) {
2993                node.className = trim$1((' ' + existingClassName + ' ').replace(' ' + className + ' ', ' '));
2994              } else {
2995                node.className += existingClassName ? ' ' + className : className;
2996              }
2997            }
2998          });
2999        }
3000        return self;
3001      },
3002      hasClass: function (className) {
3003        return hasClass(this[0], className);
3004      },
3005      each: function (callback) {
3006        return each$2(this, callback);
3007      },
3008      on: function (name, callback) {
3009        return this.each(function () {
3010          Event.bind(this, name, callback);
3011        });
3012      },
3013      off: function (name, callback) {
3014        return this.each(function () {
3015          Event.unbind(this, name, callback);
3016        });
3017      },
3018      trigger: function (name) {
3019        return this.each(function () {
3020          if (typeof name === 'object') {
3021            Event.fire(this, name.type, name);
3022          } else {
3023            Event.fire(this, name);
3024          }
3025        });
3026      },
3027      show: function () {
3028        return this.css('display', '');
3029      },
3030      hide: function () {
3031        return this.css('display', 'none');
3032      },
3033      slice: function () {
3034        return new DomQuery(slice$2.apply(this, arguments));
3035      },
3036      eq: function (index) {
3037        return index === -1 ? this.slice(index) : this.slice(index, +index + 1);
3038      },
3039      first: function () {
3040        return this.eq(0);
3041      },
3042      last: function () {
3043        return this.eq(-1);
3044      },
3045      find: function (selector) {
3046        var i, l;
3047        var ret = [];
3048        for (i = 0, l = this.length; i < l; i++) {
3049          DomQuery.find(selector, this[i], ret);
3050        }
3051        return DomQuery(ret);
3052      },
3053      filter: function (selector) {
3054        if (typeof selector === 'function') {
3055          return DomQuery(grep(this.toArray(), function (item, i) {
3056            return selector(i, item);
3057          }));
3058        }
3059        return DomQuery(DomQuery.filter(selector, this.toArray()));
3060      },
3061      closest: function (selector) {
3062        var result = [];
3063        if (selector instanceof DomQuery) {
3064          selector = selector[0];
3065        }
3066        this.each(function (i, node) {
3067          while (node) {
3068            if (typeof selector === 'string' && DomQuery(node).is(selector)) {
3069              result.push(node);
3070              break;
3071            } else if (node === selector) {
3072              result.push(node);
3073              break;
3074            }
3075            node = node.parentNode;
3076          }
3077        });
3078        return DomQuery(result);
3079      },
3080      offset: function (offset) {
3081        var elm, doc, docElm;
3082        var x = 0, y = 0, pos;
3083        if (!offset) {
3084          elm = this[0];
3085          if (elm) {
3086            doc = elm.ownerDocument;
3087            docElm = doc.documentElement;
3088            if (elm.getBoundingClientRect) {
3089              pos = elm.getBoundingClientRect();
3090              x = pos.left + (docElm.scrollLeft || doc.body.scrollLeft) - docElm.clientLeft;
3091              y = pos.top + (docElm.scrollTop || doc.body.scrollTop) - docElm.clientTop;
3092            }
3093          }
3094          return {
3095            left: x,
3096            top: y
3097          };
3098        }
3099        return this.css(offset);
3100      },
3101      push: push$2,
3102      sort: Array.prototype.sort,
3103      splice: Array.prototype.splice
3104    };
3105    Tools.extend(DomQueryConstructor, {
3106      extend: Tools.extend,
3107      makeArray: function (object) {
3108        if (isWindow(object) || object.nodeType) {
3109          return [object];
3110        }
3111        return Tools.toArray(object);
3112      },
3113      inArray: inArray,
3114      isArray: Tools.isArray,
3115      each: each$2,
3116      trim: trim$1,
3117      grep: grep,
3118      find: Sizzle,
3119      expr: Sizzle.selectors,
3120      unique: Sizzle.uniqueSort,
3121      text: Sizzle.getText,
3122      contains: Sizzle.contains,
3123      filter: function (expr, elems, not) {
3124        var i = elems.length;
3125        if (not) {
3126          expr = ':not(' + expr + ')';
3127        }
3128        while (i--) {
3129          if (elems[i].nodeType !== 1) {
3130            elems.splice(i, 1);
3131          }
3132        }
3133        if (elems.length === 1) {
3134          elems = DomQuery.find.matchesSelector(elems[0], expr) ? [elems[0]] : [];
3135        } else {
3136          elems = DomQuery.find.matches(expr, elems);
3137        }
3138        return elems;
3139      }
3140    });
3141    var dir = function (el, prop, until) {
3142      var matched = [];
3143      var cur = el[prop];
3144      if (typeof until !== 'string' && until instanceof DomQuery) {
3145        until = until[0];
3146      }
3147      while (cur && cur.nodeType !== 9) {
3148        if (until !== undefined) {
3149          if (cur === until) {
3150            break;
3151          }
3152          if (typeof until === 'string' && DomQuery(cur).is(until)) {
3153            break;
3154          }
3155        }
3156        if (cur.nodeType === 1) {
3157          matched.push(cur);
3158        }
3159        cur = cur[prop];
3160      }
3161      return matched;
3162    };
3163    var sibling = function (node, siblingName, nodeType, until) {
3164      var result = [];
3165      if (until instanceof DomQuery) {
3166        until = until[0];
3167      }
3168      for (; node; node = node[siblingName]) {
3169        if (nodeType && node.nodeType !== nodeType) {
3170          continue;
3171        }
3172        if (until !== undefined) {
3173          if (node === until) {
3174            break;
3175          }
3176          if (typeof until === 'string' && DomQuery(node).is(until)) {
3177            break;
3178          }
3179        }
3180        result.push(node);
3181      }
3182      return result;
3183    };
3184    var firstSibling = function (node, siblingName, nodeType) {
3185      for (node = node[siblingName]; node; node = node[siblingName]) {
3186        if (node.nodeType === nodeType) {
3187          return node;
3188        }
3189      }
3190      return null;
3191    };
3192    each$2({
3193      parent: function (node) {
3194        var parent = node.parentNode;
3195        return parent && parent.nodeType !== 11 ? parent : null;
3196      },
3197      parents: function (node) {
3198        return dir(node, 'parentNode');
3199      },
3200      next: function (node) {
3201        return firstSibling(node, 'nextSibling', 1);
3202      },
3203      prev: function (node) {
3204        return firstSibling(node, 'previousSibling', 1);
3205      },
3206      children: function (node) {
3207        return sibling(node.firstChild, 'nextSibling', 1);
3208      },
3209      contents: function (node) {
3210        return Tools.toArray((node.nodeName === 'iframe' ? node.contentDocument || node.contentWindow.document : node).childNodes);
3211      }
3212    }, function (name, fn) {
3213      DomQueryConstructor.fn[name] = function (selector) {
3214        var self = this;
3215        var result = [];
3216        self.each(function () {
3217          var nodes = fn.call(result, this, selector, result);
3218          if (nodes) {
3219            if (DomQuery.isArray(nodes)) {
3220              result.push.apply(result, nodes);
3221            } else {
3222              result.push(nodes);
3223            }
3224          }
3225        });
3226        if (this.length > 1) {
3227          if (!skipUniques[name]) {
3228            result = DomQuery.unique(result);
3229          }
3230          if (name.indexOf('parents') === 0) {
3231            result = result.reverse();
3232          }
3233        }
3234        var wrappedResult = DomQuery(result);
3235        if (selector) {
3236          return wrappedResult.filter(selector);
3237        }
3238        return wrappedResult;
3239      };
3240    });
3241    each$2({
3242      parentsUntil: function (node, until) {
3243        return dir(node, 'parentNode', until);
3244      },
3245      nextUntil: function (node, until) {
3246        return sibling(node, 'nextSibling', 1, until).slice(1);
3247      },
3248      prevUntil: function (node, until) {
3249        return sibling(node, 'previousSibling', 1, until).slice(1);
3250      }
3251    }, function (name, fn) {
3252      DomQueryConstructor.fn[name] = function (selector, filter) {
3253        var self = this;
3254        var result = [];
3255        self.each(function () {
3256          var nodes = fn.call(result, this, selector, result);
3257          if (nodes) {
3258            if (DomQuery.isArray(nodes)) {
3259              result.push.apply(result, nodes);
3260            } else {
3261              result.push(nodes);
3262            }
3263          }
3264        });
3265        if (this.length > 1) {
3266          result = DomQuery.unique(result);
3267          if (name.indexOf('parents') === 0 || name === 'prevUntil') {
3268            result = result.reverse();
3269          }
3270        }
3271        var wrappedResult = DomQuery(result);
3272        if (filter) {
3273          return wrappedResult.filter(filter);
3274        }
3275        return wrappedResult;
3276      };
3277    });
3278    DomQueryConstructor.fn.is = function (selector) {
3279      return !!selector && this.filter(selector).length > 0;
3280    };
3281    DomQueryConstructor.fn.init.prototype = DomQueryConstructor.fn;
3282    DomQueryConstructor.overrideDefaults = function (callback) {
3283      var defaults;
3284      var sub = function (selector, context) {
3285        defaults = defaults || callback();
3286        if (arguments.length === 0) {
3287          selector = defaults.element;
3288        }
3289        if (!context) {
3290          context = defaults.context;
3291        }
3292        return new sub.fn.init(selector, context);
3293      };
3294      DomQuery.extend(sub, this);
3295      return sub;
3296    };
3297    var appendHooks = function (targetHooks, prop, hooks) {
3298      each$2(hooks, function (name, func) {
3299        targetHooks[name] = targetHooks[name] || {};
3300        targetHooks[name][prop] = func;
3301      });
3302    };
3303    if (Env.ie && Env.ie < 8) {
3304      appendHooks(attrHooks, 'get', {
3305        maxlength: function (elm) {
3306          var value = elm.maxLength;
3307          if (value === 2147483647) {
3308            return undefined;
3309          }
3310          return value;
3311        },
3312        size: function (elm) {
3313          var value = elm.size;
3314          if (value === 20) {
3315            return undefined;
3316          }
3317          return value;
3318        },
3319        class: function (elm) {
3320          return elm.className;
3321        },
3322        style: function (elm) {
3323          var value = elm.style.cssText;
3324          if (value.length === 0) {
3325            return undefined;
3326          }
3327          return value;
3328        }
3329      });
3330      appendHooks(attrHooks, 'set', {
3331        class: function (elm, value) {
3332          elm.className = value;
3333        },
3334        style: function (elm, value) {
3335          elm.style.cssText = value;
3336        }
3337      });
3338    }
3339    if (Env.ie && Env.ie < 9) {
3340      cssFix.float = 'styleFloat';
3341      appendHooks(cssHooks, 'set', {
3342        opacity: function (elm, value) {
3343          var style = elm.style;
3344          if (value === null || value === '') {
3345            style.removeAttribute('filter');
3346          } else {
3347            style.zoom = 1;
3348            style.filter = 'alpha(opacity=' + value * 100 + ')';
3349          }
3350        }
3351      });
3352    }
3353    DomQueryConstructor.attrHooks = attrHooks;
3354    DomQueryConstructor.cssHooks = cssHooks;
3355    var DomQuery = DomQueryConstructor;
3356
3357    var cached = function (f) {
3358      var called = false;
3359      var r;
3360      return function () {
3361        var args = [];
3362        for (var _i = 0; _i < arguments.length; _i++) {
3363          args[_i] = arguments[_i];
3364        }
3365        if (!called) {
3366          called = true;
3367          r = f.apply(null, args);
3368        }
3369        return r;
3370      };
3371    };
3372
3373    var firstMatch = function (regexes, s) {
3374      for (var i = 0; i < regexes.length; i++) {
3375        var x = regexes[i];
3376        if (x.test(s))
3377          return x;
3378      }
3379      return undefined;
3380    };
3381    var find$2 = function (regexes, agent) {
3382      var r = firstMatch(regexes, agent);
3383      if (!r)
3384        return {
3385          major: 0,
3386          minor: 0
3387        };
3388      var group = function (i) {
3389        return Number(agent.replace(r, '$' + i));
3390      };
3391      return nu(group(1), group(2));
3392    };
3393    var detect = function (versionRegexes, agent) {
3394      var cleanedAgent = String(agent).toLowerCase();
3395      if (versionRegexes.length === 0)
3396        return unknown();
3397      return find$2(versionRegexes, cleanedAgent);
3398    };
3399    var unknown = function () {
3400      return nu(0, 0);
3401    };
3402    var nu = function (major, minor) {
3403      return {
3404        major: major,
3405        minor: minor
3406      };
3407    };
3408    var Version = {
3409      nu: nu,
3410      detect: detect,
3411      unknown: unknown
3412    };
3413
3414    var edge = 'Edge';
3415    var chrome = 'Chrome';
3416    var ie$1 = 'IE';
3417    var opera$1 = 'Opera';
3418    var firefox = 'Firefox';
3419    var safari = 'Safari';
3420    var isBrowser = function (name, current) {
3421      return function () {
3422        return current === name;
3423      };
3424    };
3425    var unknown$1 = function () {
3426      return nu$1({
3427        current: undefined,
3428        version: Version.unknown()
3429      });
3430    };
3431    var nu$1 = function (info) {
3432      var current = info.current;
3433      var version = info.version;
3434      return {
3435        current: current,
3436        version: version,
3437        isEdge: isBrowser(edge, current),
3438        isChrome: isBrowser(chrome, current),
3439        isIE: isBrowser(ie$1, current),
3440        isOpera: isBrowser(opera$1, current),
3441        isFirefox: isBrowser(firefox, current),
3442        isSafari: isBrowser(safari, current)
3443      };
3444    };
3445    var Browser = {
3446      unknown: unknown$1,
3447      nu: nu$1,
3448      edge: constant(edge),
3449      chrome: constant(chrome),
3450      ie: constant(ie$1),
3451      opera: constant(opera$1),
3452      firefox: constant(firefox),
3453      safari: constant(safari)
3454    };
3455
3456    var windows = 'Windows';
3457    var ios = 'iOS';
3458    var android$1 = 'Android';
3459    var linux = 'Linux';
3460    var osx = 'OSX';
3461    var solaris = 'Solaris';
3462    var freebsd = 'FreeBSD';
3463    var isOS = function (name, current) {
3464      return function () {
3465        return current === name;
3466      };
3467    };
3468    var unknown$2 = function () {
3469      return nu$2({
3470        current: undefined,
3471        version: Version.unknown()
3472      });
3473    };
3474    var nu$2 = function (info) {
3475      var current = info.current;
3476      var version = info.version;
3477      return {
3478        current: current,
3479        version: version,
3480        isWindows: isOS(windows, current),
3481        isiOS: isOS(ios, current),
3482        isAndroid: isOS(android$1, current),
3483        isOSX: isOS(osx, current),
3484        isLinux: isOS(linux, current),
3485        isSolaris: isOS(solaris, current),
3486        isFreeBSD: isOS(freebsd, current)
3487      };
3488    };
3489    var OperatingSystem = {
3490      unknown: unknown$2,
3491      nu: nu$2,
3492      windows: constant(windows),
3493      ios: constant(ios),
3494      android: constant(android$1),
3495      linux: constant(linux),
3496      osx: constant(osx),
3497      solaris: constant(solaris),
3498      freebsd: constant(freebsd)
3499    };
3500
3501    var DeviceType = function (os, browser, userAgent) {
3502      var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
3503      var isiPhone = os.isiOS() && !isiPad;
3504      var isAndroid3 = os.isAndroid() && os.version.major === 3;
3505      var isAndroid4 = os.isAndroid() && os.version.major === 4;
3506      var isTablet = isiPad || isAndroid3 || isAndroid4 && /mobile/i.test(userAgent) === true;
3507      var isTouch = os.isiOS() || os.isAndroid();
3508      var isPhone = isTouch && !isTablet;
3509      var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
3510      return {
3511        isiPad: constant(isiPad),
3512        isiPhone: constant(isiPhone),
3513        isTablet: constant(isTablet),
3514        isPhone: constant(isPhone),
3515        isTouch: constant(isTouch),
3516        isAndroid: os.isAndroid,
3517        isiOS: os.isiOS,
3518        isWebView: constant(iOSwebview)
3519      };
3520    };
3521
3522    var detect$1 = function (candidates, userAgent) {
3523      var agent = String(userAgent).toLowerCase();
3524      return find(candidates, function (candidate) {
3525        return candidate.search(agent);
3526      });
3527    };
3528    var detectBrowser = function (browsers, userAgent) {
3529      return detect$1(browsers, userAgent).map(function (browser) {
3530        var version = Version.detect(browser.versionRegexes, userAgent);
3531        return {
3532          current: browser.name,
3533          version: version
3534        };
3535      });
3536    };
3537    var detectOs = function (oses, userAgent) {
3538      return detect$1(oses, userAgent).map(function (os) {
3539        var version = Version.detect(os.versionRegexes, userAgent);
3540        return {
3541          current: os.name,
3542          version: version
3543        };
3544      });
3545    };
3546    var UaString = {
3547      detectBrowser: detectBrowser,
3548      detectOs: detectOs
3549    };
3550
3551    var contains$2 = function (str, substr) {
3552      return str.indexOf(substr) !== -1;
3553    };
3554    var trim$2 = function (str) {
3555      return str.replace(/^\s+|\s+$/g, '');
3556    };
3557    var lTrim = function (str) {
3558      return str.replace(/^\s+/g, '');
3559    };
3560    var rTrim = function (str) {
3561      return str.replace(/\s+$/g, '');
3562    };
3563
3564    var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
3565    var checkContains = function (target) {
3566      return function (uastring) {
3567        return contains$2(uastring, target);
3568      };
3569    };
3570    var browsers = [
3571      {
3572        name: 'Edge',
3573        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
3574        search: function (uastring) {
3575          var monstrosity = contains$2(uastring, 'edge/') && contains$2(uastring, 'chrome') && contains$2(uastring, 'safari') && contains$2(uastring, 'applewebkit');
3576          return monstrosity;
3577        }
3578      },
3579      {
3580        name: 'Chrome',
3581        versionRegexes: [
3582          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
3583          normalVersionRegex
3584        ],
3585        search: function (uastring) {
3586          return contains$2(uastring, 'chrome') && !contains$2(uastring, 'chromeframe');
3587        }
3588      },
3589      {
3590        name: 'IE',
3591        versionRegexes: [
3592          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
3593          /.*?rv:([0-9]+)\.([0-9]+).*/
3594        ],
3595        search: function (uastring) {
3596          return contains$2(uastring, 'msie') || contains$2(uastring, 'trident');
3597        }
3598      },
3599      {
3600        name: 'Opera',
3601        versionRegexes: [
3602          normalVersionRegex,
3603          /.*?opera\/([0-9]+)\.([0-9]+).*/
3604        ],
3605        search: checkContains('opera')
3606      },
3607      {
3608        name: 'Firefox',
3609        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
3610        search: checkContains('firefox')
3611      },
3612      {
3613        name: 'Safari',
3614        versionRegexes: [
3615          normalVersionRegex,
3616          /.*?cpu os ([0-9]+)_([0-9]+).*/
3617        ],
3618        search: function (uastring) {
3619          return (contains$2(uastring, 'safari') || contains$2(uastring, 'mobile/')) && contains$2(uastring, 'applewebkit');
3620        }
3621      }
3622    ];
3623    var oses = [
3624      {
3625        name: 'Windows',
3626        search: checkContains('win'),
3627        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
3628      },
3629      {
3630        name: 'iOS',
3631        search: function (uastring) {
3632          return contains$2(uastring, 'iphone') || contains$2(uastring, 'ipad');
3633        },
3634        versionRegexes: [
3635          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
3636          /.*cpu os ([0-9]+)_([0-9]+).*/,
3637          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
3638        ]
3639      },
3640      {
3641        name: 'Android',
3642        search: checkContains('android'),
3643        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
3644      },
3645      {
3646        name: 'OSX',
3647        search: checkContains('os x'),
3648        versionRegexes: [/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]
3649      },
3650      {
3651        name: 'Linux',
3652        search: checkContains('linux'),
3653        versionRegexes: []
3654      },
3655      {
3656        name: 'Solaris',
3657        search: checkContains('sunos'),
3658        versionRegexes: []
3659      },
3660      {
3661        name: 'FreeBSD',
3662        search: checkContains('freebsd'),
3663        versionRegexes: []
3664      }
3665    ];
3666    var PlatformInfo = {
3667      browsers: constant(browsers),
3668      oses: constant(oses)
3669    };
3670
3671    var detect$2 = function (userAgent) {
3672      var browsers = PlatformInfo.browsers();
3673      var oses = PlatformInfo.oses();
3674      var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu);
3675      var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
3676      var deviceType = DeviceType(os, browser, userAgent);
3677      return {
3678        browser: browser,
3679        os: os,
3680        deviceType: deviceType
3681      };
3682    };
3683    var PlatformDetection = { detect: detect$2 };
3684
3685    var detect$3 = cached(function () {
3686      var userAgent = domGlobals.navigator.userAgent;
3687      return PlatformDetection.detect(userAgent);
3688    });
3689    var PlatformDetection$1 = { detect: detect$3 };
3690
3691    var fromHtml = function (html, scope) {
3692      var doc = scope || domGlobals.document;
3693      var div = doc.createElement('div');
3694      div.innerHTML = html;
3695      if (!div.hasChildNodes() || div.childNodes.length > 1) {
3696        domGlobals.console.error('HTML does not have a single root node', html);
3697        throw new Error('HTML must have a single root node');
3698      }
3699      return fromDom(div.childNodes[0]);
3700    };
3701    var fromTag = function (tag, scope) {
3702      var doc = scope || domGlobals.document;
3703      var node = doc.createElement(tag);
3704      return fromDom(node);
3705    };
3706    var fromText = function (text, scope) {
3707      var doc = scope || domGlobals.document;
3708      var node = doc.createTextNode(text);
3709      return fromDom(node);
3710    };
3711    var fromDom = function (node) {
3712      if (node === null || node === undefined) {
3713        throw new Error('Node cannot be null or undefined');
3714      }
3715      return { dom: constant(node) };
3716    };
3717    var fromPoint = function (docElm, x, y) {
3718      var doc = docElm.dom();
3719      return Option.from(doc.elementFromPoint(x, y)).map(fromDom);
3720    };
3721    var Element = {
3722      fromHtml: fromHtml,
3723      fromTag: fromTag,
3724      fromText: fromText,
3725      fromDom: fromDom,
3726      fromPoint: fromPoint
3727    };
3728
3729    var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE;
3730    var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE;
3731    var COMMENT = domGlobals.Node.COMMENT_NODE;
3732    var DOCUMENT = domGlobals.Node.DOCUMENT_NODE;
3733    var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE;
3734    var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE;
3735    var ELEMENT = domGlobals.Node.ELEMENT_NODE;
3736    var TEXT = domGlobals.Node.TEXT_NODE;
3737    var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE;
3738    var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE;
3739    var ENTITY = domGlobals.Node.ENTITY_NODE;
3740    var NOTATION = domGlobals.Node.NOTATION_NODE;
3741
3742    var name = function (element) {
3743      var r = element.dom().nodeName;
3744      return r.toLowerCase();
3745    };
3746    var type = function (element) {
3747      return element.dom().nodeType;
3748    };
3749    var isType$1 = function (t) {
3750      return function (element) {
3751        return type(element) === t;
3752      };
3753    };
3754    var isElement = isType$1(ELEMENT);
3755    var isText = isType$1(TEXT);
3756
3757    var keys = Object.keys;
3758    var hasOwnProperty$1 = Object.hasOwnProperty;
3759    var each$3 = function (obj, f) {
3760      var props = keys(obj);
3761      for (var k = 0, len = props.length; k < len; k++) {
3762        var i = props[k];
3763        var x = obj[i];
3764        f(x, i, obj);
3765      }
3766    };
3767    var map$2 = function (obj, f) {
3768      return tupleMap(obj, function (x, i, obj) {
3769        return {
3770          k: i,
3771          v: f(x, i, obj)
3772        };
3773      });
3774    };
3775    var tupleMap = function (obj, f) {
3776      var r = {};
3777      each$3(obj, function (x, i) {
3778        var tuple = f(x, i, obj);
3779        r[tuple.k] = tuple.v;
3780      });
3781      return r;
3782    };
3783    var bifilter = function (obj, pred) {
3784      var t = {};
3785      var f = {};
3786      each$3(obj, function (x, i) {
3787        var branch = pred(x, i) ? t : f;
3788        branch[i] = x;
3789      });
3790      return {
3791        t: t,
3792        f: f
3793      };
3794    };
3795    var get = function (obj, key) {
3796      return has(obj, key) ? Option.from(obj[key]) : Option.none();
3797    };
3798    var has = function (obj, key) {
3799      return hasOwnProperty$1.call(obj, key);
3800    };
3801
3802    var isSupported = function (dom) {
3803      return dom.style !== undefined;
3804    };
3805
3806    var inBody = function (element) {
3807      var dom = isText(element) ? element.dom().parentNode : element.dom();
3808      return dom !== undefined && dom !== null && dom.ownerDocument.body.contains(dom);
3809    };
3810
3811    var rawSet = function (dom, key, value) {
3812      if (isString(value) || isBoolean(value) || isNumber(value)) {
3813        dom.setAttribute(key, value + '');
3814      } else {
3815        domGlobals.console.error('Invalid call to Attr.set. Key ', key, ':: Value ', value, ':: Element ', dom);
3816        throw new Error('Attribute value was not simple');
3817      }
3818    };
3819    var set = function (element, key, value) {
3820      rawSet(element.dom(), key, value);
3821    };
3822    var setAll = function (element, attrs) {
3823      var dom = element.dom();
3824      each$3(attrs, function (v, k) {
3825        rawSet(dom, k, v);
3826      });
3827    };
3828    var get$1 = function (element, key) {
3829      var v = element.dom().getAttribute(key);
3830      return v === null ? undefined : v;
3831    };
3832    var has$1 = function (element, key) {
3833      var dom = element.dom();
3834      return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
3835    };
3836    var remove = function (element, key) {
3837      element.dom().removeAttribute(key);
3838    };
3839
3840    var get$2 = function (element, property) {
3841      var dom = element.dom();
3842      var styles = domGlobals.window.getComputedStyle(dom);
3843      var r = styles.getPropertyValue(property);
3844      var v = r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
3845      return v === null ? undefined : v;
3846    };
3847    var getUnsafeProperty = function (dom, property) {
3848      return isSupported(dom) ? dom.style.getPropertyValue(property) : '';
3849    };
3850    var getRaw = function (element, property) {
3851      var dom = element.dom();
3852      var raw = getUnsafeProperty(dom, property);
3853      return Option.from(raw).filter(function (r) {
3854        return r.length > 0;
3855      });
3856    };
3857
3858    var Immutable = function () {
3859      var fields = [];
3860      for (var _i = 0; _i < arguments.length; _i++) {
3861        fields[_i] = arguments[_i];
3862      }
3863      return function () {
3864        var values = [];
3865        for (var _i = 0; _i < arguments.length; _i++) {
3866          values[_i] = arguments[_i];
3867        }
3868        if (fields.length !== values.length) {
3869          throw new Error('Wrong number of arguments to struct. Expected "[' + fields.length + ']", got ' + values.length + ' arguments');
3870        }
3871        var struct = {};
3872        each(fields, function (name, i) {
3873          struct[name] = constant(values[i]);
3874        });
3875        return struct;
3876      };
3877    };
3878
3879    var toArray$1 = function (target, f) {
3880      var r = [];
3881      var recurse = function (e) {
3882        r.push(e);
3883        return f(e);
3884      };
3885      var cur = f(target);
3886      do {
3887        cur = cur.bind(recurse);
3888      } while (cur.isSome());
3889      return r;
3890    };
3891    var Recurse = { toArray: toArray$1 };
3892
3893    var node = function () {
3894      var f = Global$1.getOrDie('Node');
3895      return f;
3896    };
3897    var compareDocumentPosition = function (a, b, match) {
3898      return (a.compareDocumentPosition(b) & match) !== 0;
3899    };
3900    var documentPositionPreceding = function (a, b) {
3901      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_PRECEDING);
3902    };
3903    var documentPositionContainedBy = function (a, b) {
3904      return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_CONTAINED_BY);
3905    };
3906    var Node = {
3907      documentPositionPreceding: documentPositionPreceding,
3908      documentPositionContainedBy: documentPositionContainedBy
3909    };
3910
3911    var ELEMENT$1 = ELEMENT;
3912    var DOCUMENT$1 = DOCUMENT;
3913    var is$1 = function (element, selector) {
3914      var elem = element.dom();
3915      if (elem.nodeType !== ELEMENT$1) {
3916        return false;
3917      } else if (elem.matches !== undefined) {
3918        return elem.matches(selector);
3919      } else if (elem.msMatchesSelector !== undefined) {
3920        return elem.msMatchesSelector(selector);
3921      } else if (elem.webkitMatchesSelector !== undefined) {
3922        return elem.webkitMatchesSelector(selector);
3923      } else if (elem.mozMatchesSelector !== undefined) {
3924        return elem.mozMatchesSelector(selector);
3925      } else {
3926        throw new Error('Browser lacks native selectors');
3927      }
3928    };
3929    var bypassSelector = function (dom) {
3930      return dom.nodeType !== ELEMENT$1 && dom.nodeType !== DOCUMENT$1 || dom.childElementCount === 0;
3931    };
3932    var all = function (selector, scope) {
3933      var base = scope === undefined ? domGlobals.document : scope.dom();
3934      return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), Element.fromDom);
3935    };
3936    var one = function (selector, scope) {
3937      var base = scope === undefined ? domGlobals.document : scope.dom();
3938      return bypassSelector(base) ? Option.none() : Option.from(base.querySelector(selector)).map(Element.fromDom);
3939    };
3940
3941    var eq = function (e1, e2) {
3942      return e1.dom() === e2.dom();
3943    };
3944    var regularContains = function (e1, e2) {
3945      var d1 = e1.dom();
3946      var d2 = e2.dom();
3947      return d1 === d2 ? false : d1.contains(d2);
3948    };
3949    var ieContains = function (e1, e2) {
3950      return Node.documentPositionContainedBy(e1.dom(), e2.dom());
3951    };
3952    var browser = PlatformDetection$1.detect().browser;
3953    var contains$3 = browser.isIE() ? ieContains : regularContains;
3954
3955    var owner = function (element) {
3956      return Element.fromDom(element.dom().ownerDocument);
3957    };
3958    var documentElement = function (element) {
3959      return Element.fromDom(element.dom().ownerDocument.documentElement);
3960    };
3961    var defaultView = function (element) {
3962      var el = element.dom();
3963      var defView = el.ownerDocument.defaultView;
3964      return Element.fromDom(defView);
3965    };
3966    var parent = function (element) {
3967      var dom = element.dom();
3968      return Option.from(dom.parentNode).map(Element.fromDom);
3969    };
3970    var parents = function (element, isRoot) {
3971      var stop = isFunction(isRoot) ? isRoot : constant(false);
3972      var dom = element.dom();
3973      var ret = [];
3974      while (dom.parentNode !== null && dom.parentNode !== undefined) {
3975        var rawParent = dom.parentNode;
3976        var p = Element.fromDom(rawParent);
3977        ret.push(p);
3978        if (stop(p) === true) {
3979          break;
3980        } else {
3981          dom = rawParent;
3982        }
3983      }
3984      return ret;
3985    };
3986    var siblings = function (element) {
3987      var filterSelf = function (elements) {
3988        return filter(elements, function (x) {
3989          return !eq(element, x);
3990        });
3991      };
3992      return parent(element).map(children).map(filterSelf).getOr([]);
3993    };
3994    var prevSibling = function (element) {
3995      var dom = element.dom();
3996      return Option.from(dom.previousSibling).map(Element.fromDom);
3997    };
3998    var nextSibling = function (element) {
3999      var dom = element.dom();
4000      return Option.from(dom.nextSibling).map(Element.fromDom);
4001    };
4002    var prevSiblings = function (element) {
4003      return reverse(Recurse.toArray(element, prevSibling));
4004    };
4005    var nextSiblings = function (element) {
4006      return Recurse.toArray(element, nextSibling);
4007    };
4008    var children = function (element) {
4009      var dom = element.dom();
4010      return map(dom.childNodes, Element.fromDom);
4011    };
4012    var child = function (element, index) {
4013      var cs = element.dom().childNodes;
4014      return Option.from(cs[index]).map(Element.fromDom);
4015    };
4016    var firstChild = function (element) {
4017      return child(element, 0);
4018    };
4019    var lastChild = function (element) {
4020      return child(element, element.dom().childNodes.length - 1);
4021    };
4022    var childNodesCount = function (element) {
4023      return element.dom().childNodes.length;
4024    };
4025    var spot = Immutable('element', 'offset');
4026
4027    var browser$1 = PlatformDetection$1.detect().browser;
4028    var firstElement = function (nodes) {
4029      return find(nodes, isElement);
4030    };
4031    var getTableCaptionDeltaY = function (elm) {
4032      if (browser$1.isFirefox() && name(elm) === 'table') {
4033        return firstElement(children(elm)).filter(function (elm) {
4034          return name(elm) === 'caption';
4035        }).bind(function (caption) {
4036          return firstElement(nextSiblings(caption)).map(function (body) {
4037            var bodyTop = body.dom().offsetTop;
4038            var captionTop = caption.dom().offsetTop;
4039            var captionHeight = caption.dom().offsetHeight;
4040            return bodyTop <= captionTop ? -captionHeight : 0;
4041          });
4042        }).getOr(0);
4043      } else {
4044        return 0;
4045      }
4046    };
4047    var getPos = function (body, elm, rootElm) {
4048      var x = 0, y = 0, offsetParent;
4049      var doc = body.ownerDocument;
4050      var pos;
4051      rootElm = rootElm ? rootElm : body;
4052      if (elm) {
4053        if (rootElm === body && elm.getBoundingClientRect && get$2(Element.fromDom(body), 'position') === 'static') {
4054          pos = elm.getBoundingClientRect();
4055          x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - doc.documentElement.clientLeft;
4056          y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - doc.documentElement.clientTop;
4057          return {
4058            x: x,
4059            y: y
4060          };
4061        }
4062        offsetParent = elm;
4063        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType) {
4064          x += offsetParent.offsetLeft || 0;
4065          y += offsetParent.offsetTop || 0;
4066          offsetParent = offsetParent.offsetParent;
4067        }
4068        offsetParent = elm.parentNode;
4069        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType) {
4070          x -= offsetParent.scrollLeft || 0;
4071          y -= offsetParent.scrollTop || 0;
4072          offsetParent = offsetParent.parentNode;
4073        }
4074        y += getTableCaptionDeltaY(Element.fromDom(elm));
4075      }
4076      return {
4077        x: x,
4078        y: y
4079      };
4080    };
4081    var Position = { getPos: getPos };
4082
4083    var nu$3 = function (baseFn) {
4084      var data = Option.none();
4085      var callbacks = [];
4086      var map = function (f) {
4087        return nu$3(function (nCallback) {
4088          get(function (data) {
4089            nCallback(f(data));
4090          });
4091        });
4092      };
4093      var get = function (nCallback) {
4094        if (isReady())
4095          call(nCallback);
4096        else
4097          callbacks.push(nCallback);
4098      };
4099      var set = function (x) {
4100        data = Option.some(x);
4101        run(callbacks);
4102        callbacks = [];
4103      };
4104      var isReady = function () {
4105        return data.isSome();
4106      };
4107      var run = function (cbs) {
4108        each(cbs, call);
4109      };
4110      var call = function (cb) {
4111        data.each(function (x) {
4112          domGlobals.setTimeout(function () {
4113            cb(x);
4114          }, 0);
4115        });
4116      };
4117      baseFn(set);
4118      return {
4119        get: get,
4120        map: map,
4121        isReady: isReady
4122      };
4123    };
4124    var pure$1 = function (a) {
4125      return nu$3(function (callback) {
4126        callback(a);
4127      });
4128    };
4129    var LazyValue = {
4130      nu: nu$3,
4131      pure: pure$1
4132    };
4133
4134    var bounce = function (f) {
4135      return function () {
4136        var args = [];
4137        for (var _i = 0; _i < arguments.length; _i++) {
4138          args[_i] = arguments[_i];
4139        }
4140        var me = this;
4141        domGlobals.setTimeout(function () {
4142          f.apply(me, args);
4143        }, 0);
4144      };
4145    };
4146
4147    var nu$4 = function (baseFn) {
4148      var get = function (callback) {
4149        baseFn(bounce(callback));
4150      };
4151      var map = function (fab) {
4152        return nu$4(function (callback) {
4153          get(function (a) {
4154            var value = fab(a);
4155            callback(value);
4156          });
4157        });
4158      };
4159      var bind = function (aFutureB) {
4160        return nu$4(function (callback) {
4161          get(function (a) {
4162            aFutureB(a).get(callback);
4163          });
4164        });
4165      };
4166      var anonBind = function (futureB) {
4167        return nu$4(function (callback) {
4168          get(function (a) {
4169            futureB.get(callback);
4170          });
4171        });
4172      };
4173      var toLazy = function () {
4174        return LazyValue.nu(get);
4175      };
4176      var toCached = function () {
4177        var cache = null;
4178        return nu$4(function (callback) {
4179          if (cache === null) {
4180            cache = toLazy();
4181          }
4182          cache.get(callback);
4183        });
4184      };
4185      return {
4186        map: map,
4187        bind: bind,
4188        anonBind: anonBind,
4189        toLazy: toLazy,
4190        toCached: toCached,
4191        get: get
4192      };
4193    };
4194    var pure$2 = function (a) {
4195      return nu$4(function (callback) {
4196        callback(a);
4197      });
4198    };
4199    var Future = {
4200      nu: nu$4,
4201      pure: pure$2
4202    };
4203
4204    var par = function (asyncValues, nu) {
4205      return nu(function (callback) {
4206        var r = [];
4207        var count = 0;
4208        var cb = function (i) {
4209          return function (value) {
4210            r[i] = value;
4211            count++;
4212            if (count >= asyncValues.length) {
4213              callback(r);
4214            }
4215          };
4216        };
4217        if (asyncValues.length === 0) {
4218          callback([]);
4219        } else {
4220          each(asyncValues, function (asyncValue, i) {
4221            asyncValue.get(cb(i));
4222          });
4223        }
4224      });
4225    };
4226
4227    var par$1 = function (futures) {
4228      return par(futures, Future.nu);
4229    };
4230
4231    var value = function (o) {
4232      var is = function (v) {
4233        return o === v;
4234      };
4235      var or = function (opt) {
4236        return value(o);
4237      };
4238      var orThunk = function (f) {
4239        return value(o);
4240      };
4241      var map = function (f) {
4242        return value(f(o));
4243      };
4244      var mapError = function (f) {
4245        return value(o);
4246      };
4247      var each = function (f) {
4248        f(o);
4249      };
4250      var bind = function (f) {
4251        return f(o);
4252      };
4253      var fold = function (_, onValue) {
4254        return onValue(o);
4255      };
4256      var exists = function (f) {
4257        return f(o);
4258      };
4259      var forall = function (f) {
4260        return f(o);
4261      };
4262      var toOption = function () {
4263        return Option.some(o);
4264      };
4265      return {
4266        is: is,
4267        isValue: always,
4268        isError: never,
4269        getOr: constant(o),
4270        getOrThunk: constant(o),
4271        getOrDie: constant(o),
4272        or: or,
4273        orThunk: orThunk,
4274        fold: fold,
4275        map: map,
4276        mapError: mapError,
4277        each: each,
4278        bind: bind,
4279        exists: exists,
4280        forall: forall,
4281        toOption: toOption
4282      };
4283    };
4284    var error = function (message) {
4285      var getOrThunk = function (f) {
4286        return f();
4287      };
4288      var getOrDie = function () {
4289        return die(String(message))();
4290      };
4291      var or = function (opt) {
4292        return opt;
4293      };
4294      var orThunk = function (f) {
4295        return f();
4296      };
4297      var map = function (f) {
4298        return error(message);
4299      };
4300      var mapError = function (f) {
4301        return error(f(message));
4302      };
4303      var bind = function (f) {
4304        return error(message);
4305      };
4306      var fold = function (onError, _) {
4307        return onError(message);
4308      };
4309      return {
4310        is: never,
4311        isValue: never,
4312        isError: always,
4313        getOr: identity,
4314        getOrThunk: getOrThunk,
4315        getOrDie: getOrDie,
4316        or: or,
4317        orThunk: orThunk,
4318        fold: fold,
4319        map: map,
4320        mapError: mapError,
4321        each: noop,
4322        bind: bind,
4323        exists: never,
4324        forall: always,
4325        toOption: Option.none
4326      };
4327    };
4328    var Result = {
4329      value: value,
4330      error: error
4331    };
4332
4333    function StyleSheetLoader(document, settings) {
4334      if (settings === void 0) {
4335        settings = {};
4336      }
4337      var idCount = 0;
4338      var loadedStates = {};
4339      var maxLoadTime;
4340      maxLoadTime = settings.maxLoadTime || 5000;
4341      var appendToHead = function (node) {
4342        document.getElementsByTagName('head')[0].appendChild(node);
4343      };
4344      var load = function (url, loadedCallback, errorCallback) {
4345        var link, style, startTime, state;
4346        var resolve = function (status) {
4347          state.status = status;
4348          state.passed = [];
4349          state.failed = [];
4350          if (link) {
4351            link.onload = null;
4352            link.onerror = null;
4353            link = null;
4354          }
4355        };
4356        var passed = function () {
4357          var callbacks = state.passed;
4358          var i = callbacks.length;
4359          while (i--) {
4360            callbacks[i]();
4361          }
4362          resolve(2);
4363        };
4364        var failed = function () {
4365          var callbacks = state.failed;
4366          var i = callbacks.length;
4367          while (i--) {
4368            callbacks[i]();
4369          }
4370          resolve(3);
4371        };
4372        var isOldWebKit = function () {
4373          var webKitChunks = domGlobals.navigator.userAgent.match(/WebKit\/(\d*)/);
4374          return !!(webKitChunks && parseInt(webKitChunks[1], 10) < 536);
4375        };
4376        var wait = function (testCallback, waitCallback) {
4377          if (!testCallback()) {
4378            if (new Date().getTime() - startTime < maxLoadTime) {
4379              Delay.setTimeout(waitCallback);
4380            } else {
4381              failed();
4382            }
4383          }
4384        };
4385        var waitForWebKitLinkLoaded = function () {
4386          wait(function () {
4387            var styleSheets = document.styleSheets;
4388            var styleSheet, i = styleSheets.length, owner;
4389            while (i--) {
4390              styleSheet = styleSheets[i];
4391              owner = styleSheet.ownerNode ? styleSheet.ownerNode : styleSheet.owningElement;
4392              if (owner && owner.id === link.id) {
4393                passed();
4394                return true;
4395              }
4396            }
4397          }, waitForWebKitLinkLoaded);
4398        };
4399        var waitForGeckoLinkLoaded = function () {
4400          wait(function () {
4401            try {
4402              var cssRules = style.sheet.cssRules;
4403              passed();
4404              return !!cssRules;
4405            } catch (ex) {
4406            }
4407          }, waitForGeckoLinkLoaded);
4408        };
4409        url = Tools._addCacheSuffix(url);
4410        if (!loadedStates[url]) {
4411          state = {
4412            passed: [],
4413            failed: []
4414          };
4415          loadedStates[url] = state;
4416        } else {
4417          state = loadedStates[url];
4418        }
4419        if (loadedCallback) {
4420          state.passed.push(loadedCallback);
4421        }
4422        if (errorCallback) {
4423          state.failed.push(errorCallback);
4424        }
4425        if (state.status === 1) {
4426          return;
4427        }
4428        if (state.status === 2) {
4429          passed();
4430          return;
4431        }
4432        if (state.status === 3) {
4433          failed();
4434          return;
4435        }
4436        state.status = 1;
4437        link = document.createElement('link');
4438        link.rel = 'stylesheet';
4439        link.type = 'text/css';
4440        link.id = 'u' + idCount++;
4441        link.async = false;
4442        link.defer = false;
4443        startTime = new Date().getTime();
4444        if (settings.contentCssCors) {
4445          link.crossOrigin = 'anonymous';
4446        }
4447        if ('onload' in link && !isOldWebKit()) {
4448          link.onload = waitForWebKitLinkLoaded;
4449          link.onerror = failed;
4450        } else {
4451          if (domGlobals.navigator.userAgent.indexOf('Firefox') > 0) {
4452            style = document.createElement('style');
4453            style.textContent = '@import "' + url + '"';
4454            waitForGeckoLinkLoaded();
4455            appendToHead(style);
4456            return;
4457          }
4458          waitForWebKitLinkLoaded();
4459        }
4460        appendToHead(link);
4461        link.href = url;
4462      };
4463      var loadF = function (url) {
4464        return Future.nu(function (resolve) {
4465          load(url, compose(resolve, constant(Result.value(url))), compose(resolve, constant(Result.error(url))));
4466        });
4467      };
4468      var unbox = function (result) {
4469        return result.fold(identity, identity);
4470      };
4471      var loadAll = function (urls, success, failure) {
4472        par$1(map(urls, loadF)).get(function (result) {
4473          var parts = partition(result, function (r) {
4474            return r.isValue();
4475          });
4476          if (parts.fail.length > 0) {
4477            failure(parts.fail.map(unbox));
4478          } else {
4479            success(parts.pass.map(unbox));
4480          }
4481        });
4482      };
4483      return {
4484        load: load,
4485        loadAll: loadAll
4486      };
4487    }
4488
4489    var isNodeType = function (type) {
4490      return function (node) {
4491        return !!node && node.nodeType === type;
4492      };
4493    };
4494    var isElement$1 = isNodeType(1);
4495    var matchNodeNames = function (names) {
4496      var items = names.toLowerCase().split(' ');
4497      return function (node) {
4498        var i, name;
4499        if (node && node.nodeType) {
4500          name = node.nodeName.toLowerCase();
4501          for (i = 0; i < items.length; i++) {
4502            if (name === items[i]) {
4503              return true;
4504            }
4505          }
4506        }
4507        return false;
4508      };
4509    };
4510    var matchStyleValues = function (name, values) {
4511      var items = values.toLowerCase().split(' ');
4512      return function (node) {
4513        var i, cssValue;
4514        if (isElement$1(node)) {
4515          for (i = 0; i < items.length; i++) {
4516            var computed = node.ownerDocument.defaultView.getComputedStyle(node, null);
4517            cssValue = computed ? computed.getPropertyValue(name) : null;
4518            if (cssValue === items[i]) {
4519              return true;
4520            }
4521          }
4522        }
4523        return false;
4524      };
4525    };
4526    var hasPropValue = function (propName, propValue) {
4527      return function (node) {
4528        return isElement$1(node) && node[propName] === propValue;
4529      };
4530    };
4531    var hasAttribute = function (attrName, attrValue) {
4532      return function (node) {
4533        return isElement$1(node) && node.hasAttribute(attrName);
4534      };
4535    };
4536    var hasAttributeValue = function (attrName, attrValue) {
4537      return function (node) {
4538        return isElement$1(node) && node.getAttribute(attrName) === attrValue;
4539      };
4540    };
4541    var isBogus = function (node) {
4542      return isElement$1(node) && node.hasAttribute('data-mce-bogus');
4543    };
4544    var isBogusAll = function (node) {
4545      return isElement$1(node) && node.getAttribute('data-mce-bogus') === 'all';
4546    };
4547    var isTable = function (node) {
4548      return isElement$1(node) && node.tagName === 'TABLE';
4549    };
4550    var hasContentEditableState = function (value) {
4551      return function (node) {
4552        if (isElement$1(node)) {
4553          if (node.contentEditable === value) {
4554            return true;
4555          }
4556          if (node.getAttribute('data-mce-contenteditable') === value) {
4557            return true;
4558          }
4559        }
4560        return false;
4561      };
4562    };
4563    var isText$1 = isNodeType(3);
4564    var isComment = isNodeType(8);
4565    var isDocument = isNodeType(9);
4566    var isDocumentFragment = isNodeType(11);
4567    var isBr = matchNodeNames('br');
4568    var isContentEditableTrue = hasContentEditableState('true');
4569    var isContentEditableFalse = hasContentEditableState('false');
4570    var NodeType = {
4571      isText: isText$1,
4572      isElement: isElement$1,
4573      isComment: isComment,
4574      isDocument: isDocument,
4575      isDocumentFragment: isDocumentFragment,
4576      isBr: isBr,
4577      isContentEditableTrue: isContentEditableTrue,
4578      isContentEditableFalse: isContentEditableFalse,
4579      matchNodeNames: matchNodeNames,
4580      hasPropValue: hasPropValue,
4581      hasAttribute: hasAttribute,
4582      hasAttributeValue: hasAttributeValue,
4583      matchStyleValues: matchStyleValues,
4584      isBogus: isBogus,
4585      isBogusAll: isBogusAll,
4586      isTable: isTable
4587    };
4588
4589    var TreeWalker = function () {
4590      function TreeWalker(startNode, rootNode) {
4591        this.node = startNode;
4592        this.rootNode = rootNode;
4593        this.current = this.current.bind(this);
4594        this.next = this.next.bind(this);
4595        this.prev = this.prev.bind(this);
4596        this.prev2 = this.prev2.bind(this);
4597      }
4598      TreeWalker.prototype.current = function () {
4599        return this.node;
4600      };
4601      TreeWalker.prototype.next = function (shallow) {
4602        this.node = this.findSibling(this.node, 'firstChild', 'nextSibling', shallow);
4603        return this.node;
4604      };
4605      TreeWalker.prototype.prev = function (shallow) {
4606        this.node = this.findSibling(this.node, 'lastChild', 'previousSibling', shallow);
4607        return this.node;
4608      };
4609      TreeWalker.prototype.prev2 = function (shallow) {
4610        this.node = this.findPreviousNode(this.node, 'lastChild', 'previousSibling', shallow);
4611        return this.node;
4612      };
4613      TreeWalker.prototype.findSibling = function (node, startName, siblingName, shallow) {
4614        var sibling, parent;
4615        if (node) {
4616          if (!shallow && node[startName]) {
4617            return node[startName];
4618          }
4619          if (node !== this.rootNode) {
4620            sibling = node[siblingName];
4621            if (sibling) {
4622              return sibling;
4623            }
4624            for (parent = node.parentNode; parent && parent !== this.rootNode; parent = parent.parentNode) {
4625              sibling = parent[siblingName];
4626              if (sibling) {
4627                return sibling;
4628              }
4629            }
4630          }
4631        }
4632      };
4633      TreeWalker.prototype.findPreviousNode = function (node, startName, siblingName, shallow) {
4634        var sibling, parent, child;
4635        if (node) {
4636          sibling = node[siblingName];
4637          if (this.rootNode && sibling === this.rootNode) {
4638            return;
4639          }
4640          if (sibling) {
4641            if (!shallow) {
4642              for (child = sibling[startName]; child; child = child[startName]) {
4643                if (!child[startName]) {
4644                  return child;
4645                }
4646              }
4647            }
4648            return sibling;
4649          }
4650          parent = node.parentNode;
4651          if (parent && parent !== this.rootNode) {
4652            return parent;
4653          }
4654        }
4655      };
4656      return TreeWalker;
4657    }();
4658
4659    var blocks = [
4660      'article',
4661      'aside',
4662      'details',
4663      'div',
4664      'dt',
4665      'figcaption',
4666      'footer',
4667      'form',
4668      'fieldset',
4669      'header',
4670      'hgroup',
4671      'html',
4672      'main',
4673      'nav',
4674      'section',
4675      'summary',
4676      'body',
4677      'p',
4678      'dl',
4679      'multicol',
4680      'dd',
4681      'figure',
4682      'address',
4683      'center',
4684      'blockquote',
4685      'h1',
4686      'h2',
4687      'h3',
4688      'h4',
4689      'h5',
4690      'h6',
4691      'listing',
4692      'xmp',
4693      'pre',
4694      'plaintext',
4695      'menu',
4696      'dir',
4697      'ul',
4698      'ol',
4699      'li',
4700      'hr',
4701      'table',
4702      'tbody',
4703      'thead',
4704      'tfoot',
4705      'th',
4706      'tr',
4707      'td',
4708      'caption'
4709    ];
4710    var voids = [
4711      'area',
4712      'base',
4713      'basefont',
4714      'br',
4715      'col',
4716      'frame',
4717      'hr',
4718      'img',
4719      'input',
4720      'isindex',
4721      'link',
4722      'meta',
4723      'param',
4724      'embed',
4725      'source',
4726      'wbr',
4727      'track'
4728    ];
4729    var tableCells = [
4730      'td',
4731      'th'
4732    ];
4733    var tableSections = [
4734      'thead',
4735      'tbody',
4736      'tfoot'
4737    ];
4738    var textBlocks = [
4739      'h1',
4740      'h2',
4741      'h3',
4742      'h4',
4743      'h5',
4744      'h6',
4745      'p',
4746      'div',
4747      'address',
4748      'pre',
4749      'form',
4750      'blockquote',
4751      'center',
4752      'dir',
4753      'fieldset',
4754      'header',
4755      'footer',
4756      'article',
4757      'section',
4758      'hgroup',
4759      'aside',
4760      'nav',
4761      'figure'
4762    ];
4763    var headings = [
4764      'h1',
4765      'h2',
4766      'h3',
4767      'h4',
4768      'h5',
4769      'h6'
4770    ];
4771    var listItems = [
4772      'li',
4773      'dd',
4774      'dt'
4775    ];
4776    var lists = [
4777      'ul',
4778      'ol',
4779      'dl'
4780    ];
4781    var wsElements = [
4782      'pre',
4783      'script',
4784      'textarea',
4785      'style'
4786    ];
4787    var lazyLookup = function (items) {
4788      var lookup;
4789      return function (node) {
4790        lookup = lookup ? lookup : mapToObject(items, constant(true));
4791        return lookup.hasOwnProperty(name(node));
4792      };
4793    };
4794    var isHeading = lazyLookup(headings);
4795    var isBlock = lazyLookup(blocks);
4796    var isTable$1 = function (node) {
4797      return name(node) === 'table';
4798    };
4799    var isInline = function (node) {
4800      return isElement(node) && !isBlock(node);
4801    };
4802    var isBr$1 = function (node) {
4803      return isElement(node) && name(node) === 'br';
4804    };
4805    var isTextBlock = lazyLookup(textBlocks);
4806    var isList = lazyLookup(lists);
4807    var isListItem = lazyLookup(listItems);
4808    var isVoid = lazyLookup(voids);
4809    var isTableSection = lazyLookup(tableSections);
4810    var isTableCell = lazyLookup(tableCells);
4811    var isWsPreserveElement = lazyLookup(wsElements);
4812
4813    var surroundedBySpans = function (node) {
4814      var previousIsSpan = node.previousSibling && node.previousSibling.nodeName === 'SPAN';
4815      var nextIsSpan = node.nextSibling && node.nextSibling.nodeName === 'SPAN';
4816      return previousIsSpan && nextIsSpan;
4817    };
4818    var isBookmarkNode = function (node) {
4819      return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
4820    };
4821    var trimNode = function (dom, node) {
4822      var i, children = node.childNodes;
4823      if (NodeType.isElement(node) && isBookmarkNode(node)) {
4824        return;
4825      }
4826      for (i = children.length - 1; i >= 0; i--) {
4827        trimNode(dom, children[i]);
4828      }
4829      if (NodeType.isDocument(node) === false) {
4830        if (NodeType.isText(node) && node.nodeValue.length > 0) {
4831          var trimmedLength = Tools.trim(node.nodeValue).length;
4832          if (dom.isBlock(node.parentNode) || trimmedLength > 0) {
4833            return;
4834          }
4835          if (trimmedLength === 0 && surroundedBySpans(node)) {
4836            return;
4837          }
4838        } else if (NodeType.isElement(node)) {
4839          children = node.childNodes;
4840          if (children.length === 1 && isBookmarkNode(children[0])) {
4841            node.parentNode.insertBefore(children[0], node);
4842          }
4843          if (children.length || isVoid(Element.fromDom(node))) {
4844            return;
4845          }
4846        }
4847        dom.remove(node);
4848      }
4849      return node;
4850    };
4851    var TrimNode = { trimNode: trimNode };
4852
4853    var makeMap$1 = Tools.makeMap;
4854    var namedEntities, baseEntities, reverseEntities;
4855    var attrsCharsRegExp = /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
4856    var textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
4857    var rawCharsRegExp = /[<>&\"\']/g;
4858    var entityRegExp = /&#([a-z0-9]+);?|&([a-z0-9]+);/gi;
4859    var asciiMap = {
4860      128: '\u20AC',
4861      130: '\u201A',
4862      131: '\u0192',
4863      132: '\u201E',
4864      133: '\u2026',
4865      134: '\u2020',
4866      135: '\u2021',
4867      136: '\u02c6',
4868      137: '\u2030',
4869      138: '\u0160',
4870      139: '\u2039',
4871      140: '\u0152',
4872      142: '\u017d',
4873      145: '\u2018',
4874      146: '\u2019',
4875      147: '\u201C',
4876      148: '\u201D',
4877      149: '\u2022',
4878      150: '\u2013',
4879      151: '\u2014',
4880      152: '\u02DC',
4881      153: '\u2122',
4882      154: '\u0161',
4883      155: '\u203A',
4884      156: '\u0153',
4885      158: '\u017e',
4886      159: '\u0178'
4887    };
4888    baseEntities = {
4889      '"': '&quot;',
4890      '\'': '&#39;',
4891      '<': '&lt;',
4892      '>': '&gt;',
4893      '&': '&amp;',
4894      '`': '&#96;'
4895    };
4896    reverseEntities = {
4897      '&lt;': '<',
4898      '&gt;': '>',
4899      '&amp;': '&',
4900      '&quot;': '"',
4901      '&apos;': '\''
4902    };
4903    var nativeDecode = function (text) {
4904      var elm;
4905      elm = Element.fromTag('div').dom();
4906      elm.innerHTML = text;
4907      return elm.textContent || elm.innerText || text;
4908    };
4909    var buildEntitiesLookup = function (items, radix) {
4910      var i, chr, entity;
4911      var lookup = {};
4912      if (items) {
4913        items = items.split(',');
4914        radix = radix || 10;
4915        for (i = 0; i < items.length; i += 2) {
4916          chr = String.fromCharCode(parseInt(items[i], radix));
4917          if (!baseEntities[chr]) {
4918            entity = '&' + items[i + 1] + ';';
4919            lookup[chr] = entity;
4920            lookup[entity] = chr;
4921          }
4922        }
4923        return lookup;
4924      }
4925    };
4926    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,8
4926k4,' + '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);
4927    var encodeRaw = function (text, attr) {
4928      return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
4929        return baseEntities[chr] || chr;
4930      });
4931    };
4932    var encodeAllRaw = function (text) {
4933      return ('' + text).replace(rawCharsRegExp, function (chr) {
4934        return baseEntities[chr] || chr;
4935      });
4936    };
4937    var encodeNumeric = function (text, attr) {
4938      return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
4939        if (chr.length > 1) {
4940          return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
4941        }
4942        return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
4943      });
4944    };
4945    var encodeNamed = function (text, attr, entities) {
4946      entities = entities || namedEntities;
4947      return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
4948        return baseEntities[chr] || entities[chr] || chr;
4949      });
4950    };
4951    var getEncodeFunc = function (name, entities) {
4952      var entitiesMap = buildEntitiesLookup(entities) || namedEntities;
4953      var encodeNamedAndNumeric = function (text, attr) {
4954        return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
4955          if (baseEntities[chr] !== undefined) {
4956            return baseEntities[chr];
4957          }
4958          if (entitiesMap[chr] !== undefined) {
4959            return entitiesMap[chr];
4960          }
4961          if (chr.length > 1) {
4962            return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
4963          }
4964          return '&#' + chr.charCodeAt(0) + ';';
4965        });
4966      };
4967      var encodeCustomNamed = function (text, attr) {
4968        return encodeNamed(text, attr, entitiesMap);
4969      };
4970      var nameMap = makeMap$1(name.replace(/\+/g, ','));
4971      if (nameMap.named && nameMap.numeric) {
4972        return encodeNamedAndNumeric;
4973      }
4974      if (nameMap.named) {
4975        if (entities) {
4976          return encodeCustomNamed;
4977        }
4978        return encodeNamed;
4979      }
4980      if (nameMap.numeric) {
4981        return encodeNumeric;
4982      }
4983      return encodeRaw;
4984    };
4985    var decode = function (text) {
4986      return text.replace(entityRegExp, function (all, numeric) {
4987        if (numeric) {
4988          if (numeric.charAt(0).toLowerCase() === 'x') {
4989            numeric = parseInt(numeric.substr(1), 16);
4990          } else {
4991            numeric = parseInt(numeric, 10);
4992          }
4993          if (numeric > 65535) {
4994            numeric -= 65536;
4995            return String.fromCharCode(55296 + (numeric >> 10), 56320 + (numeric & 1023));
4996          }
4997          return asciiMap[numeric] || String.fromCharCode(numeric);
4998        }
4999        return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
5000      });
5001    };
5002    var Entities = {
5003      encodeRaw: encodeRaw,
5004      encodeAllRaw: encodeAllRaw,
5005      encodeNumeric: encodeNumeric,
5006      encodeNamed: encodeNamed,
5007      getEncodeFunc: getEncodeFunc,
5008      decode: decode
5009    };
5010
5011    var mapCache = {}, dummyObj = {};
5012    var makeMap$2 = Tools.makeMap, each$4 = Tools.each, extend$1 = Tools.extend, explode$1 = Tools.explode, inArray$1 = Tools.inArray;
5013    var split = function (items, delim) {
5014      items = Tools.trim(items);
5015      return items ? items.split(delim || ' ') : [];
5016    };
5017    var compileSchema = function (type) {
5018      var schema = {};
5019      var globalAttributes, blockContent;
5020      var phrasingContent, flowContent, html4BlockContent, html4PhrasingContent;
5021      var add = function (name, attributes, children) {
5022        var ni, attributesOrder, element;
5023        var arrayToMap = function (array, obj) {
5024          var map = {};
5025          var i, l;
5026          for (i = 0, l = array.length; i < l; i++) {
5027            map[array[i]] = obj || {};
5028          }
5029          return map;
5030        };
5031        children = children || [];
5032        attributes = attributes || '';
5033        if (typeof children === 'string') {
5034          children = split(children);
5035        }
5036        name = split(name);
5037        ni = name.length;
5038        while (ni--) {
5039          attributesOrder = split([
5040            globalAttributes,
5041            attributes
5042          ].join(' '));
5043          element = {
5044            attributes: arrayToMap(attributesOrder),
5045            attributesOrder: attributesOrder,
5046            children: arrayToMap(children, dummyObj)
5047          };
5048          schema[name[ni]] = element;
5049        }
5050      };
5051      var addAttrs = function (name, attributes) {
5052        var ni, schemaItem, i, l;
5053        name = split(name);
5054        ni = name.length;
5055        attributes = split(attributes);
5056        while (ni--) {
5057          schemaItem = schema[name[ni]];
5058          for (i = 0, l = attributes.length; i < l; i++) {
5059            schemaItem.attributes[attributes[i]] = {};
5060            schemaItem.attributesOrder.push(attributes[i]);
5061          }
5062        }
5063      };
5064      if (mapCache[type]) {
5065        return mapCache[type];
5066      }
5067      globalAttributes = 'id accesskey class dir lang style tabindex title role';
5068      blockContent = 'address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul';
5069      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';
5070      if (type !== 'html4') {
5071        globalAttributes += ' contenteditable contextmenu draggable dropzone ' + 'hidden spellcheck translate';
5072        blockContent += ' article aside details dialog figure main header footer hgroup section nav';
5073        phrasingContent += ' audio canvas command datalist mark meter output picture ' + 'progress time wbr video ruby bdi keygen';
5074      }
5075      if (type !== 'html5-strict') {
5076        globalAttributes += ' xml:lang';
5077        html4PhrasingContent = 'acronym applet basefont big font strike tt';
5078        phrasingContent = [
5079          phrasingContent,
5080          html4PhrasingContent
5081        ].join(' ');
5082        each$4(split(html4PhrasingContent), function (name) {
5083          add(name, '', phrasingContent);
5084        });
5085        html4BlockContent = 'center dir isindex noframes';
5086        blockContent = [
5087          blockContent,
5088          html4BlockContent
5089        ].join(' ');
5090        flowContent = [
5091          blockContent,
5092          phrasingContent
5093        ].join(' ');
5094        each$4(split(html4BlockContent), function (name) {
5095          add(name, '', flowContent);
5096        });
5097      }
5098      flowContent = flowContent || [
5099        blockContent,
5100        phrasingContent
5101      ].join(' ');
5102      add('html', 'manifest', 'head body');
5103      add('head', '', 'base command link meta noscript script style title');
5104      add('title hr noscript br');
5105      add('base', 'href target');
5106      add('link', 'href rel media hreflang type sizes hreflang');
5107      add('meta', 'name http-equiv content charset');
5108      add('style', 'media type scoped');
5109      add('script', 'src async defer type charset');
5110      add('body', 'onafterprint onbeforeprint onbeforeunload onblur onerror onfocus ' + 'onhashchange onload onmessage onoffline ononline onpagehide onpageshow ' + 'onpopstate onresize onscroll onstorage onunload', flowContent);
5111      add('address dt dd div caption', '', flowContent);
5112      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);
5113      add('blockquote', 'cite', flowContent);
5114      add('ol', 'reversed start type', 'li');
5115      add('ul', '', 'li');
5116      add('li', 'value', flowContent);
5117      add('dl', '', 'dt dd');
5118      add('a', 'href target rel media hreflang type', phrasingContent);
5119      add('q', 'cite', phrasingContent);
5120      add('ins del', 'cite datetime', flowContent);
5121      add('img', 'src sizes srcset alt usemap ismap width height');
5122      add('iframe', 'src name width height', flowContent);
5123      add('embed', 'src type width height');
5124      add('object', 'data type typemustmatch name usemap form width height', [
5125        flowContent,
5126        'param'
5127      ].join(' '));
5128      add('param', 'name value');
5129      add('map', 'name', [
5130        flowContent,
5131        'area'
5132      ].join(' '));
5133      add('area', 'alt coords shape href target rel media hreflang type');
5134      add('table', 'border', 'caption colgroup thead tfoot tbody tr' + (type === 'html4' ? ' col' : ''));
5135      add('colgroup', 'span', 'col');
5136      add('col', 'span');
5137      add('tbody thead tfoot', '', 'tr');
5138      add('tr', '', 'td th');
5139      add('td', 'colspan rowspan headers', flowContent);
5140      add('th', 'colspan rowspan headers scope abbr', flowContent);
5141      add('form', 'accept-charset action autocomplete enctype method name novalidate target', flowContent);
5142      add('fieldset', 'disabled form name', [
5143        flowContent,
5144        'legend'
5145      ].join(' '));
5146      add('label', 'form for', phrasingContent);
5147      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');
5148      add('button', 'disabled form formaction formenctype formmethod formnovalidate formtarget name type value', type === 'html4' ? flowContent : phrasingContent);
5149      add('select', 'disabled form multiple name required size', 'option optgroup');
5150      add('optgroup', 'disabled label', 'option');
5151      add('option', 'disabled label selected value');
5152      add('textarea', 'cols dirname disabled form maxlength name readonly required rows wrap');
5153      add('menu', 'type label', [
5154        flowContent,
5155        'li'
5156      ].join(' '));
5157      add('noscript', '', flowContent);
5158      if (type !== 'html4') {
5159        add('wbr');
5160        add('ruby', '', [
5161          phrasingContent,
5162          'rt rp'
5163        ].join(' '));
5164        add('figcaption', '', flowContent);
5165        add('mark rt rp summary bdi', '', phrasingContent);
5166        add('canvas', 'width height', flowContent);
5167        add('video', 'src crossorigin poster preload autoplay mediagroup loop ' + 'muted controls width height buffered', [
5168          flowContent,
5169          'track source'
5170        ].join(' '));
5171        add('audio', 'src crossorigin preload autoplay mediagroup loop muted controls ' + 'buffered volume', [
5172          flowContent,
5173          'track source'
5174        ].join(' '));
5175        add('picture', '', 'img source');
5176        add('source', 'src srcset type media sizes');
5177        add('track', 'kind src srclang label default');
5178        add('datalist', '', [
5179          phrasingContent,
5180          'option'
5181        ].join(' '));
5182        add('article section nav aside main header footer', '', flowContent);
5183        add('hgroup', '', 'h1 h2 h3 h4 h5 h6');
5184        add('figure', '', [
5185          flowContent,
5186          'figcaption'
5187        ].join(' '));
5188        add('time', 'datetime', phrasingContent);
5189        add('dialog', 'open', flowContent);
5190        add('command', 'type label icon disabled checked radiogroup command');
5191        add('output', 'for form name', phrasingContent);
5192        add('progress', 'value max', phrasingContent);
5193        add('meter', 'value min max low high optimum', phrasingContent);
5194        add('details', 'open', [
5195          flowContent,
5196          'summary'
5197        ].join(' '));
5198        add('keygen', 'autofocus challenge disabled form keytype name');
5199      }
5200      if (type !== 'html5-strict') {
5201        addAttrs('script', 'language xml:space');
5202        addAttrs('style', 'xml:space');
5203        addAttrs('object', 'declare classid code codebase codetype archive standby align border hspace vspace');
5204        addAttrs('embed', 'align name hspace vspace');
5205        addAttrs('param', 'valuetype type');
5206        addAttrs('a', 'charset name rev shape coords');
5207        addAttrs('br', 'clear');
5208        addAttrs('applet', 'codebase archive code object alt name width height align hspace vspace');
5209        addAttrs('img', 'name longdesc align border hspace vspace');
5210        addAttrs('iframe', 'longdesc frameborder marginwidth marginheight scrolling align');
5211        addAttrs('font basefont', 'size color face');
5212        addAttrs('input', 'usemap align');
5213        addAttrs('select', 'onchange');
5214        addAttrs('textarea');
5215        addAttrs('h1 h2 h3 h4 h5 h6 div p legend caption', 'align');
5216        addAttrs('ul', 'type compact');
5217        addAttrs('li', 'type');
5218        addAttrs('ol dl menu dir', 'compact');
5219        addAttrs('pre', 'width xml:space');
5220        addAttrs('hr', 'align noshade size width');
5221        addAttrs('isindex', 'prompt');
5222        addAttrs('table', 'summary width frame rules cellspacing cellpadding align bgcolor');
5223        addAttrs('col', 'width align char charoff valign');
5224        addAttrs('colgroup', 'width align char charoff valign');
5225        addAttrs('thead', 'align char charoff valign');
5226        addAttrs('tr', 'align char charoff valign bgcolor');
5227        addAttrs('th', 'axis align char charoff valign nowrap bgcolor width height');
5228        addAttrs('form', 'accept');
5229        addAttrs('td', 'abbr axis scope align char charoff valign nowrap bgcolor width height');
5230        addAttrs('tfoot', 'align char charoff valign');
5231        addAttrs('tbody', 'align char charoff valign');
5232        addAttrs('area', 'nohref');
5233        addAttrs('body', 'background bgcolor text link vlink alink');
5234      }
5235      if (type !== 'html4') {
5236        addAttrs('input button select textarea', 'autofocus');
5237        addAttrs('input textarea', 'placeholder');
5238        addAttrs('a', 'download');
5239        addAttrs('link script img', 'crossorigin');
5240        addAttrs('iframe', 'sandbox seamless allowfullscreen');
5241      }
5242      each$4(split('a form meter progress dfn'), function (name) {
5243        if (schema[name]) {
5244          delete schema[name].children[name];
5245        }
5246      });
5247      delete schema.caption.children.table;
5248      delete schema.script;
5249      mapCache[type] = schema;
5250      return schema;
5251    };
5252    var compileElementMap = function (value, mode) {
5253      var styles;
5254      if (value) {
5255        styles = {};
5256        if (typeof value === 'string') {
5257          value = { '*': value };
5258        }
5259        each$4(value, function (value, key) {
5260          styles[key] = styles[key.toUpperCase()] = mode === 'map' ? makeMap$2(value, /[, ]/) : explode$1(value, /[, ]/);
5261        });
5262      }
5263      return styles;
5264    };
5265    function Schema(settings) {
5266      var elements = {};
5267      var children = {};
5268      var patternElements = [];
5269      var validStyles;
5270      var invalidStyles;
5271      var schemaItems;
5272      var whiteSpaceElementsMap, selfClosingElementsMap, shortEndedElementsMap, boolAttrMap, validClasses;
5273      var blockElementsMap, nonEmptyElementsMap, moveCaretBeforeOnEnterElementsMap, textBlockElementsMap, textInlineElementsMap;
5274      var customElementsMap = {}, specialElements = {};
5275      var createLookupTable = function (option, defaultValue, extendWith) {
5276        var value = settings[option];
5277        if (!value) {
5278          value = mapCache[option];
5279          if (!value) {
5280            value = makeMap$2(defaultValue, ' ', makeMap$2(defaultValue.toUpperCase(), ' '));
5281            value = extend$1(value, extendWith);
5282            mapCache[option] = value;
5283          }
5284        } else {
5285          value = makeMap$2(value, /[, ]/, makeMap$2(value.toUpperCase(), /[, ]/));
5286        }
5287        return value;
5288      };
5289      settings = settings || {};
5290      schemaItems = compileSchema(settings.schema);
5291      if (settings.verify_html === false) {
5292        settings.valid_elements = '*[*]';
5293      }
5294      validStyles = compileElementMap(settings.valid_styles);
5295      invalidStyles = compileElementMap(settings.invalid_styles, 'map');
5296      validClasses = compileElementMap(settings.valid_classes, 'map');
5297      whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea video audio iframe object code');
5298      selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
5299      shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link ' + 'meta param embed source wbr track');
5300      boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' + 'noshade nowrap readonly selected autoplay loop controls');
5301      nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object ' + 'script pre code', shortEndedElementsMap);
5302      moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', 'table', nonEmptyElementsMap);
5303      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');
5304      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);
5305      textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font strike u var cite ' + 'dfn code mark q sup sub samp');
5306      each$4((settings.special || 'script noscript noframes noembed title style textarea xmp').split(' '), function (name) {
5307        specialElements[name] = new RegExp('</' + name + '[^>]*>', 'gi');
5308      });
5309      var patternToRegExp = function (str) {
5310        return new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$');
5311      };
5312      var addValidElements = function (validElements) {
5313        var ei, el, ai, al, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder, prefix, outputName, globalAttributes, globalAttributesOrder, key, value;
5314        var elementRuleRegExp = /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/, attrRuleRegExp = /^([!\-])?(\w+[\\:]:\w+|[^=:<]+)?(?:([=:<])(.*))?$/, hasPatternsRegExp = /[*?+]/;
5315        if (validElements) {
5316          validElements = split(validElements, ',');
5317          if (elements['@']) {
5318            globalAttributes = elements['@'].attributes;
5319            globalAttributesOrder = elements['@'].attributesOrder;
5320          }
5321          for (ei = 0, el = validElements.length; ei < el; ei++) {
5322            matches = elementRuleRegExp.exec(validElements[ei]);
5323            if (matches) {
5324              prefix = matches[1];
5325              elementName = matches[2];
5326              outputName = matches[3];
5327              attrData = matches[5];
5328              attributes = {};
5329              attributesOrder = [];
5330              element = {
5331                attributes: attributes,
5332                attributesOrder: attributesOrder
5333              };
5334              if (prefix === '#') {
5335                element.paddEmpty = true;
5336              }
5337              if (prefix === '-') {
5338                element.removeEmpty = true;
5339              }
5340              if (matches[4] === '!') {
5341                element.removeEmptyAttrs = true;
5342              }
5343              if (globalAttributes) {
5344                for (key in globalAttributes) {
5345                  attributes[key] = globalAttributes[key];
5346                }
5347                attributesOrder.push.apply(attributesOrder, globalAttributesOrder);
5348              }
5349              if (attrData) {
5350                attrData = split(attrData, '|');
5351                for (ai = 0, al = attrData.length; ai < al; ai++) {
5352                  matches = attrRuleRegExp.exec(attrData[ai]);
5353                  if (matches) {
5354                    attr = {};
5355                    attrType = matches[1];
5356                    attrName = matches[2].replace(/[\\:]:/g, ':');
5357                    prefix = matches[3];
5358                    value = matches[4];
5359                    if (attrType === '!') {
5360                      element.attributesRequired = element.attributesRequired || [];
5361                      element.attributesRequired.push(attrName);
5362                      attr.required = true;
5363                    }
5364                    if (attrType === '-') {
5365                      delete attributes[attrName];
5366                      attributesOrder.splice(inArray$1(attributesOrder, attrName), 1);
5367                      continue;
5368                    }
5369                    if (prefix) {
5370                      if (prefix === '=') {
5371                        element.attributesDefault = element.attributesDefault || [];
5372                        element.attributesDefault.push({
5373                          name: attrName,
5374                          value: value
5375                        });
5376                        attr.defaultValue = value;
5377                      }
5378                      if (prefix === ':') {
5379                        element.attributesForced = element.attributesForced || [];
5380                        element.attributesForced.push({
5381                          name: attrName,
5382                          value: value
5383                        });
5384                        attr.forcedValue = value;
5385                      }
5386                      if (prefix === '<') {
5387                        attr.validValues = makeMap$2(value, '?');
5388                      }
5389                    }
5390                    if (hasPatternsRegExp.test(attrName)) {
5391                      element.attributePatterns = element.attributePatterns || [];
5392                      attr.pattern = patternToRegExp(attrName);
5393                      element.attributePatterns.push(attr);
5394                    } else {
5395                      if (!attributes[attrName]) {
5396                        attributesOrder.push(attrName);
5397                      }
5398                      attributes[attrName] = attr;
5399                    }
5400                  }
5401                }
5402              }
5403              if (!globalAttributes && elementName === '@') {
5404                globalAttributes = attributes;
5405                globalAttributesOrder = attributesOrder;
5406              }
5407              if (outputName) {
5408                element.outputName = elementName;
5409                elements[outputName] = element;
5410              }
5411              if (hasPatternsRegExp.test(elementName)) {
5412                element.pattern = patternToRegExp(elementName);
5413                patternElements.push(element);
5414              } else {
5415                elements[elementName] = element;
5416              }
5417            }
5418          }
5419        }
5420      };
5421      var setValidElements = function (validElements) {
5422        elements = {};
5423        patternElements = [];
5424        addValidElements(validElements);
5425        each$4(schemaItems, function (element, name) {
5426          children[name] = element.children;
5427        });
5428      };
5429      var addCustomElements = function (customElements) {
5430        var customElementRegExp = /^(~)?(.+)$/;
5431        if (customElements) {
5432          mapCache.text_block_elements = mapCache.block_elements = null;
5433          each$4(split(customElements, ','), function (rule) {
5434            var matches = customElementRegExp.exec(rule), inline = matches[1] === '~', cloneName = inline ? 'span' : 'div', name = matches[2];
5435            children[name] = children[cloneName];
5436            customElementsMap[name] = cloneName;
5437            if (!inline) {
5438              blockElementsMap[name.toUpperCase()] = {};
5439              blockElementsMap[name] = {};
5440            }
5441            if (!elements[name]) {
5442              var customRule = elements[cloneName];
5443              customRule = extend$1({}, customRule);
5444              delete customRule.removeEmptyAttrs;
5445              delete customRule.removeEmpty;
5446              elements[name] = customRule;
5447            }
5448            each$4(children, function (element, elmName) {
5449              if (element[cloneName]) {
5450                children[elmName] = element = extend$1({}, children[elmName]);
5451                element[name] = element[cloneName];
5452              }
5453            });
5454          });
5455        }
5456      };
5457      var addValidChildren = function (validChildren) {
5458        var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/;
5459        mapCache[settings.schema] = null;
5460        if (validChildren) {
5461          each$4(split(validChildren, ','), function (rule) {
5462            var matches = childRuleRegExp.exec(rule);
5463            var parent, prefix;
5464            if (matches) {
5465              prefix = matches[1];
5466              if (prefix) {
5467                parent = children[matches[2]];
5468              } else {
5469                parent = children[matches[2]] = { '#comment': {} };
5470              }
5471              parent = children[matches[2]];
5472              each$4(split(matches[3], '|'), function (child) {
5473                if (prefix === '-') {
5474                  delete parent[child];
5475                } else {
5476                  parent[child] = {};
5477                }
5478              });
5479            }
5480          });
5481        }
5482      };
5483      var getElementRule = function (name) {
5484        var element = elements[name], i;
5485        if (element) {
5486          return element;
5487        }
5488        i = patternElements.length;
5489        while (i--) {
5490          element = patternElements[i];
5491          if (element.pattern.test(name)) {
5492            return element;
5493          }
5494        }
5495      };
5496      if (!settings.valid_elements) {
5497        each$4(schemaItems, function (element, name) {
5498          elements[name] = {
5499            attributes: element.attributes,
5500            attributesOrder: element.attributesOrder
5501          };
5502          children[name] = element.children;
5503        });
5504        if (settings.schema !== 'html5') {
5505          each$4(split('strong/b em/i'), function (item) {
5506            item = split(item, '/');
5507            elements[item[1]].outputName = item[0];
5508          });
5509        }
5510        each$4(split('ol ul sub sup blockquote span font a table tbody tr strong em b i'), function (name) {
5511          if (elements[name]) {
5512            elements[name].removeEmpty = true;
5513          }
5514        });
5515        each$4(split('p h1 h2 h3 h4 h5 h6 th td pre div address caption li'), function (name) {
5516          elements[name].paddEmpty = true;
5517        });
5518        each$4(split('span'), function (name) {
5519          elements[name].removeEmptyAttrs = true;
5520        });
5521      } else {
5522        setValidElements(settings.valid_elements);
5523      }
5524      addCustomElements(settings.custom_elements);
5525      addValidChildren(settings.valid_children);
5526      addValidElements(settings.extended_valid_elements);
5527      addValidChildren('+ol[ul|ol],+ul[ul|ol]');
5528      each$4({
5529        dd: 'dl',
5530        dt: 'dl',
5531        li: 'ul ol',
5532        td: 'tr',
5533        th: 'tr',
5534        tr: 'tbody thead tfoot',
5535        tbody: 'table',
5536        thead: 'table',
5537        tfoot: 'table',
5538        legend: 'fieldset',
5539        area: 'map',
5540        param: 'video audio object'
5541      }, function (parents, item) {
5542        if (elements[item]) {
5543          elements[item].parentsRequired = split(parents);
5544        }
5545      });
5546      if (settings.invalid_elements) {
5547        each$4(explode$1(settings.invalid_elements), function (item) {
5548          if (elements[item]) {
5549            delete elements[item];
5550          }
5551        });
5552      }
5553      if (!getElementRule('span')) {
5554        addValidElements('span[!data-mce-type|*]');
5555      }
5556      var getValidStyles = function () {
5557        return validStyles;
5558      };
5559      var getInvalidStyles = function () {
5560        return invalidStyles;
5561      };
5562      var getValidClasses = function () {
5563        return validClasses;
5564      };
5565      var getBoolAttrs = function () {
5566        return boolAttrMap;
5567      };
5568      var getBlockElements = function () {
5569        return blockElementsMap;
5570      };
5571      var getTextBlockElements = function () {
5572        return textBlockElementsMap;
5573      };
5574      var getTextInlineElements = function () {
5575        return textInlineElementsMap;
5576      };
5577      var getShortEndedElements = function () {
5578        return shortEndedElementsMap;
5579      };
5580      var getSelfClosingElements = function () {
5581        return selfClosingElementsMap;
5582      };
5583      var getNonEmptyElements = function () {
5584        return nonEmptyElementsMap;
5585      };
5586      var getMoveCaretBeforeOnEnterElements = function () {
5587        return moveCaretBeforeOnEnterElementsMap;
5588      };
5589      var getWhiteSpaceElements = function () {
5590        return whiteSpaceElementsMap;
5591      };
5592      var getSpecialElements = function () {
5593        return specialElements;
5594      };
5595      var isValidChild = function (name, child) {
5596        var parent = children[name.toLowerCase()];
5597        return !!(parent && parent[child.toLowerCase()]);
5598      };
5599      var isValid = function (name, attr) {
5600        var attrPatterns, i;
5601        var rule = getElementRule(name);
5602        if (rule) {
5603          if (attr) {
5604            if (rule.attributes[attr]) {
5605              return true;
5606            }
5607            attrPatterns = rule.attributePatterns;
5608            if (attrPatterns) {
5609              i = attrPatterns.length;
5610              while (i--) {
5611                if (attrPatterns[i].pattern.test(name)) {
5612                  return true;
5613                }
5614              }
5615            }
5616          } else {
5617            return true;
5618          }
5619        }
5620        return false;
5621      };
5622      var getCustomElements = function () {
5623        return customElementsMap;
5624      };
5625      return {
5626        children: children,
5627        elements: elements,
5628        getValidStyles: getValidStyles,
5629        getValidClasses: getValidClasses,
5630        getBlockElements: getBlockElements,
5631        getInvalidStyles: getInvalidStyles,
5632        getShortEndedElements: getShortEndedElements,
5633        getTextBlockElements: getTextBlockElements,
5634        getTextInlineElements: getTextInlineElements,
5635        getBoolAttrs: getBoolAttrs,
5636        getElementRule: getElementRule,
5637        getSelfClosingElements: getSelfClosingElements,
5638        getNonEmptyElements: getNonEmptyElements,
5639        getMoveCaretBeforeOnEnterElements: getMoveCaretBeforeOnEnterElements,
5640        getWhiteSpaceElements: getWhiteSpaceElements,
5641        getSpecialElements: getSpecialElements,
5642        isValidChild: isValidChild,
5643        isValid: isValid,
5644        getCustomElements: getCustomElements,
5645        addValidElements: addValidElements,
5646        setValidElements: setValidElements,
5647        addCustomElements: addCustomElements,
5648        addValidChildren: addValidChildren
5649      };
5650    }
5651
5652    var toHex = function (match, r, g, b) {
5653      var hex = function (val) {
5654        val = parseInt(val, 10).toString(16);
5655        return val.length > 1 ? val : '0' + val;
5656      };
5657      return '#' + hex(r) + hex(g) + hex(b);
5658    };
5659    var Styles = function (settings, schema) {
5660      var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi;
5661      var urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi;
5662      var styleRegExp = /\s*([^:]+):\s*([^;]+);?/g;
5663      var trimRightRegExp = /\s+$/;
5664      var i;
5665      var encodingLookup = {};
5666      var encodingItems;
5667      var validStyles;
5668      var invalidStyles;
5669      var invisibleChar = '\uFEFF';
5670      settings = settings || {};
5671      if (schema) {
5672        validStyles = schema.getValidStyles();
5673        invalidStyles = schema.getInvalidStyles();
5674      }
5675      encodingItems = ('\\" \\\' \\; \\: ; : ' + invisibleChar).split(' ');
5676      for (i = 0; i < encodingItems.length; i++) {
5677        encodingLookup[encodingItems[i]] = invisibleChar + i;
5678        encodingLookup[invisibleChar + i] = encodingItems[i];
5679      }
5680      return {
5681        toHex: function (color) {
5682          return color.replace(rgbRegExp, toHex);
5683        },
5684        parse: function (css) {
5685          var styles = {};
5686          var matches, name, value, isEncoded;
5687          var urlConverter = settings.url_converter;
5688          var urlConverterScope = settings.url_converter_scope || this;
5689          var compress = function (prefix, suffix, noJoin) {
5690            var top, right, bottom, left;
5691            top = styles[prefix + '-top' + suffix];
5692            if (!top) {
5693              return;
5694            }
5695            right = styles[prefix + '-right' + suffix];
5696            if (!right) {
5697              return;
5698            }
5699            bottom = styles[prefix + '-bottom' + suffix];
5700            if (!bottom) {
5701              return;
5702            }
5703            left = styles[prefix + '-left' + suffix];
5704            if (!left) {
5705              return;
5706            }
5707            var box = [
5708              top,
5709              right,
5710              bottom,
5711              left
5712            ];
5713            i = box.length - 1;
5714            while (i--) {
5715              if (box[i] !== box[i + 1]) {
5716                break;
5717              }
5718            }
5719            if (i > -1 && noJoin) {
5720              return;
5721            }
5722            styles[prefix + suffix] = i === -1 ? box[0] : box.join(' ');
5723            delete styles[prefix + '-top' + suffix];
5724            delete styles[prefix + '-right' + suffix];
5725            delete styles[prefix + '-bottom' + suffix];
5726            delete styles[prefix + '-left' + suffix];
5727          };
5728          var canCompress = function (key) {
5729            var value = styles[key], i;
5730            if (!value) {
5731              return;
5732            }
5733            value = value.split(' ');
5734            i = value.length;
5735            while (i--) {
5736              if (value[i] !== value[0]) {
5737                return false;
5738              }
5739            }
5740            styles[key] = value[0];
5741            return true;
5742          };
5743          var compress2 = function (target, a, b, c) {
5744            if (!canCompress(a)) {
5745              return;
5746            }
5747            if (!canCompress(b)) {
5748              return;
5749            }
5750            if (!canCompress(c)) {
5751              return;
5752            }
5753            styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c];
5754            delete styles[a];
5755            delete styles[b];
5756            delete styles[c];
5757          };
5758          var encode = function (str) {
5759            isEncoded = true;
5760            return encodingLookup[str];
5761          };
5762          var decode = function (str, keepSlashes) {
5763            if (isEncoded) {
5764              str = str.replace(/\uFEFF[0-9]/g, function (str) {
5765                return encodingLookup[str];
5766              });
5767            }
5768            if (!keepSlashes) {
5769              str = str.replace(/\\([\'\";:])/g, '$1');
5770            }
5771            return str;
5772          };
5773          var decodeSingleHexSequence = function (escSeq) {
5774            return String.fromCharCode(parseInt(escSeq.slice(1), 16));
5775          };
5776          var decodeHexSequences = function (value) {
5777            return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence);
5778          };
5779          var processUrl = function (match, url, url2, url3, str, str2) {
5780            str = str || str2;
5781            if (str) {
5782              str = decode(str);
5783              return '\'' + str.replace(/\'/g, '\\\'') + '\'';
5784            }
5785            url = decode(url || url2 || url3);
5786            if (!settings.allow_script_urls) {
5787              var scriptUrl = url.replace(/[\s\r\n]+/g, '');
5788              if (/(java|vb)script:/i.test(scriptUrl)) {
5789                return '';
5790              }
5791              if (!settings.allow_svg_data_urls && /^data:image\/svg/i.test(scriptUrl)) {
5792                return '';
5793              }
5794            }
5795            if (urlConverter) {
5796              url = urlConverter.call(urlConverterScope, url, 'style');
5797            }
5798            return 'url(\'' + url.replace(/\'/g, '\\\'') + '\')';
5799          };
5800          if (css) {
5801            css = css.replace(/[\u0000-\u001F]/g, '');
5802            css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, function (str) {
5803              return str.replace(/[;:]/g, encode);
5804            });
5805            while (matches = styleRegExp.exec(css)) {
5806              styleRegExp.lastIndex = matches.index + matches[0].length;
5807              name = matches[1].replace(trimRightRegExp, '').toLowerCase();
5808              value = matches[2].replace(trimRightRegExp, '');
5809              if (name && value) {
5810                name = decodeHexSequences(name);
5811                value = decodeHexSequences(value);
5812                if (name.indexOf(invisibleChar) !== -1 || name.indexOf('"') !== -1) {
5813                  continue;
5814                }
5815                if (!settings.allow_script_urls && (name === 'behavior' || /expression\s*\(|\/\*|\*\//.test(value))) {
5816                  continue;
5817                }
5818                if (name === 'font-weight' && value === '700') {
5819                  value = 'bold';
5820                } else if (name === 'color' || name === 'background-color') {
5821                  value = value.toLowerCase();
5822                }
5823                value = value.replace(rgbRegExp, toHex);
5824                value = value.replace(urlOrStrRegExp, processUrl);
5825                styles[name] = isEncoded ? decode(value, true) : value;
5826              }
5827            }
5828            compress('border', '', true);
5829            compress('border', '-width');
5830            compress('border', '-color');
5831            compress('border', '-style');
5832            compress('padding', '');
5833            compress('margin', '');
5834            compress2('border', 'border-width', 'border-style', 'border-color');
5835            if (styles.border === 'medium none') {
5836              delete styles.border;
5837            }
5838            if (styles['border-image'] === 'none') {
5839              delete styles['border-image'];
5840            }
5841          }
5842          return styles;
5843        },
5844        serialize: function (styles, elementName) {
5845          var css = '', name, value;
5846          var serializeStyles = function (name) {
5847            var styleList, i, l, value;
5848            styleList = validStyles[name];
5849            if (styleList) {
5850              for (i = 0, l = styleList.length; i < l; i++) {
5851                name = styleList[i];
5852                value = styles[name];
5853                if (value) {
5854                  css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
5855                }
5856              }
5857            }
5858          };
5859          var isValid = function (name, elementName) {
5860            var styleMap;
5861            styleMap = invalidStyles['*'];
5862            if (styleMap && styleMap[name]) {
5863              return false;
5864            }
5865            styleMap = invalidStyles[elementName];
5866            if (styleMap && styleMap[name]) {
5867              return false;
5868            }
5869            return true;
5870          };
5871          if (elementName && validStyles) {
5872            serializeStyles('*');
5873            serializeStyles(elementName);
5874          } else {
5875            for (name in styles) {
5876              value = styles[name];
5877              if (value && (!invalidStyles || isValid(name, elementName))) {
5878                css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
5879              }
5880            }
5881          }
5882          return css;
5883        }
5884      };
5885    };
5886
5887    var each$5 = Tools.each;
5888    var grep$1 = Tools.grep;
5889    var isIE = Env.ie;
5890    var simpleSelectorRe = /^([a-z0-9],?)+$/i;
5891    var whiteSpaceRegExp$2 = /^[ \t\r\n]*$/;
5892    var setupAttrHooks = function (styles, settings, getContext) {
5893      var keepValues = settings.keep_values;
5894      var keepUrlHook = {
5895        set: function ($elm, value, name) {
5896          if (settings.url_converter) {
5897            value = settings.url_converter.call(settings.url_converter_scope || getContext(), value, name, $elm[0]);
5898          }
5899          $elm.attr('data-mce-' + name, value).attr(name, value);
5900        },
5901        get: function ($elm, name) {
5902          return $elm.attr('data-mce-' + name) || $elm.attr(name);
5903        }
5904      };
5905      var attrHooks = {
5906        style: {
5907          set: function ($elm, value) {
5908            if (value !== null && typeof value === 'object') {
5909              $elm.css(value);
5910              return;
5911            }
5912            if (keepValues) {
5913              $elm.attr('data-mce-style', value);
5914            }
5915            $elm.attr('style', value);
5916          },
5917          get: function ($elm) {
5918            var value = $elm.attr('data-mce-style') || $elm.attr('style');
5919            value = styles.serialize(styles.parse(value), $elm[0].nodeName);
5920            return value;
5921          }
5922        }
5923      };
5924      if (keepValues) {
5925        attrHooks.href = attrHooks.src = keepUrlHook;
5926      }
5927      return attrHooks;
5928    };
5929    var updateInternalStyleAttr = function (styles, $elm) {
5930      var rawValue = $elm.attr('style');
5931      var value = styles.serialize(styles.parse(rawValue), $elm[0].nodeName);
5932      if (!value) {
5933        value = null;
5934      }
5935      $elm.attr('data-mce-style', value);
5936    };
5937    var findNodeIndex = function (node, normalized) {
5938      var idx = 0, lastNodeType, nodeType;
5939      if (node) {
5940        for (lastNodeType = node.nodeType, node = node.previousSibling; node; node = node.previousSibling) {
5941          nodeType = node.nodeType;
5942          if (normalized && nodeType === 3) {
5943            if (nodeType === lastNodeType || !node.nodeValue.length) {
5944              continue;
5945            }
5946          }
5947          idx++;
5948          lastNodeType = nodeType;
5949        }
5950      }
5951      return idx;
5952    };
5953    function DOMUtils(doc, settings) {
5954      var _this = this;
5955      if (settings === void 0) {
5956        settings = {};
5957      }
5958      var attrHooks;
5959      var addedStyles = {};
5960      var win = domGlobals.window;
5961      var files = {};
5962      var counter = 0;
5963      var stdMode = true;
5964      var boxModel = true;
5965      var styleSheetLoader = StyleSheetLoader(doc, { contentCssCors: settings.contentCssCors });
5966      var boundEvents = [];
5967      var schema = settings.schema ? settings.schema : Schema({});
5968      var styles = Styles({
5969        url_converter: settings.url_converter,
5970        url_converter_scope: settings.url_converter_scope
5971      }, settings.schema);
5972      var events = settings.ownEvents ? new EventUtils() : EventUtils.Event;
5973      var blockElementsMap = schema.getBlockElements();
5974      var $ = DomQuery.overrideDefaults(function () {
5975        return {
5976          context: doc,
5977          element: self.getRoot()
5978        };
5979      });
5980      var isBlock = function (node) {
5981        if (typeof node === 'string') {
5982          return !!blockElementsMap[node];
5983        } else if (node) {
5984          var type = node.nodeType;
5985          if (type) {
5986            return !!(type === 1 && blockElementsMap[node.nodeName]);
5987          }
5988        }
5989        return false;
5990      };
5991      var get = function (elm) {
5992        if (elm && doc && typeof elm === 'string') {
5993          var node = doc.getElementById(elm);
5994          if (node && node.id !== elm) {
5995            return doc.getElementsByName(elm)[1];
5996          } else {
5997            return node;
5998          }
5999        }
6000        return elm;
6001      };
6002      var $$ = function (elm) {
6003        if (typeof elm === 'string') {
6004          elm = get(elm);
6005        }
6006        return $(elm);
6007      };
6008      var getAttrib = function (elm, name, defaultVal) {
6009        var hook, value;
6010        var $elm = $$(elm);
6011        if ($elm.length) {
6012          hook = attrHooks[name];
6013          if (hook && hook.get) {
6014            value = hook.get($elm, name);
6015          } else {
6016            value = $elm.attr(name);
6017          }
6018        }
6019        if (typeof value === 'undefined') {
6020          value = defaultVal || '';
6021        }
6022        return value;
6023      };
6024      var getAttribs = function (elm) {
6025        var node = get(elm);
6026        if (!node) {
6027          return [];
6028        }
6029        return node.attributes;
6030      };
6031      var setAttrib = function (elm, name, value) {
6032        var originalValue, hook;
6033        if (value === '') {
6034          value = null;
6035        }
6036        var $elm = $$(elm);
6037        originalValue = $elm.attr(name);
6038        if (!$elm.length) {
6039          return;
6040        }
6041        hook = attrHooks[name];
6042        if (hook && hook.set) {
6043          hook.set($elm, value, name);
6044        } else {
6045          $elm.attr(name, value);
6046        }
6047        if (originalValue !== value && settings.onSetAttrib) {
6048          settings.onSetAttrib({
6049            attrElm: $elm,
6050            attrName: name,
6051            attrValue: value
6052          });
6053        }
6054      };
6055      var clone = function (node, deep) {
6056        if (!isIE || node.nodeType !== 1 || deep) {
6057          return node.cloneNode(deep);
6058        }
6059        if (!deep) {
6060          var clone_1 = doc.createElement(node.nodeName);
6061          each$5(getAttribs(node), function (attr) {
6062            setAttrib(clone_1, attr.nodeName, getAttrib(node, attr.nodeName));
6063          });
6064          return clone_1;
6065        }
6066        return null;
6067      };
6068      var getRoot = function () {
6069        return settings.root_element || doc.body;
6070      };
6071      var getViewPort = function (argWin) {
6072        var actWin = !argWin ? win : argWin;
6073        var doc = actWin.document;
6074        var rootElm = doc.documentElement;
6075        return {
6076          x: actWin.pageXOffset || rootElm.scrollLeft,
6077          y: actWin.pageYOffset || rootElm.scrollTop,
6078          w: actWin.innerWidth || rootElm.clientWidth,
6079          h: actWin.innerHeight || rootElm.clientHeight
6080        };
6081      };
6082      var getPos = function (elm, rootElm) {
6083        return Position.getPos(doc.body, get(elm), rootElm);
6084      };
6085      var setStyle = function (elm, name, value) {
6086        var $elm = isString(name) ? $$(elm).css(name, value) : $$(elm).css(name);
6087        if (settings.update_styles) {
6088          updateInternalStyleAttr(styles, $elm);
6089        }
6090      };
6091      var setStyles = function (elm, stylesArg) {
6092        var $elm = $$(elm).css(stylesArg);
6093        if (settings.update_styles) {
6094          updateInternalStyleAttr(styles, $elm);
6095        }
6096      };
6097      var getStyle = function (elm, name, computed) {
6098        var $elm = $$(elm);
6099        if (computed) {
6100          return $elm.css(name);
6101        }
6102        name = name.replace(/-(\D)/g, function (a, b) {
6103          return b.toUpperCase();
6104        });
6105        if (name === 'float') {
6106          name = Env.ie && Env.ie < 12 ? 'styleFloat' : 'cssFloat';
6107        }
6108        return $elm[0] && $elm[0].style ? $elm[0].style[name] : undefined;
6109      };
6110      var getSize = function (elm) {
6111        var w, h;
6112        elm = get(elm);
6113        w = getStyle(elm, 'width');
6114        h = getStyle(elm, 'height');
6115        if (w.indexOf('px') === -1) {
6116          w = 0;
6117        }
6118        if (h.indexOf('px') === -1) {
6119          h = 0;
6120        }
6121        return {
6122          w: parseInt(w, 10) || elm.offsetWidth || elm.clientWidth,
6123          h: parseInt(h, 10) || elm.offsetHeight || elm.clientHeight
6124        };
6125      };
6126      var getRect = function (elm) {
6127        var pos, size;
6128        elm = get(elm);
6129        pos = getPos(elm);
6130        size = getSize(elm);
6131        return {
6132          x: pos.x,
6133          y: pos.y,
6134          w: size.w,
6135          h: size.h
6136        };
6137      };
6138      var is = function (elm, selector) {
6139        var i;
6140        if (!elm) {
6141          return false;
6142        }
6143        if (!Array.isArray(elm)) {
6144          if (selector === '*') {
6145            return elm.nodeType === 1;
6146          }
6147          if (simpleSelectorRe.test(selector)) {
6148            var selectors = selector.toLowerCase().split(/,/);
6149            var elmName = elm.nodeName.toLowerCase();
6150            for (i = selectors.length - 1; i >= 0; i--) {
6151              if (selectors[i] === elmName) {
6152                return true;
6153              }
6154            }
6155            return false;
6156          }
6157          if (elm.nodeType && elm.nodeType !== 1) {
6158            return false;
6159          }
6160        }
6161        var elms = !Array.isArray(elm) ? [elm] : elm;
6162        return Sizzle(selector, elms[0].ownerDocument || elms[0], null, elms).length > 0;
6163      };
6164      var getParents = function (elm, selector, root, collect) {
6165        var result = [];
6166        var selectorVal;
6167        var node = get(elm);
6168        collect = collect === undefined;
6169        root = root || (getRoot().nodeName !== 'BODY' ? getRoot().parentNode : null);
6170        if (Tools.is(selector, 'string')) {
6171          selectorVal = selector;
6172          if (selector === '*') {
6173            selector = function (node) {
6174              return node.nodeType === 1;
6175            };
6176          } else {
6177            selector = function (node) {
6178              return is(node, selectorVal);
6179            };
6180          }
6181        }
6182        while (node) {
6183          if (node === root || !node.nodeType || node.nodeType === 9) {
6184            break;
6185          }
6186          if (!selector || typeof selector === 'function' && selector(node)) {
6187            if (collect) {
6188              result.push(node);
6189            } else {
6190              return [node];
6191            }
6192          }
6193          node = node.parentNode;
6194        }
6195        return collect ? result : null;
6196      };
6197      var getParent = function (node, selector, root) {
6198        var parents = getParents(node, selector, root, false);
6199        return parents && parents.length > 0 ? parents[0] : null;
6200      };
6201      var _findSib = function (node, selector, name) {
6202        var func = selector;
6203        if (node) {
6204          if (typeof selector === 'string') {
6205            func = function (node) {
6206              return is(node, selector);
6207            };
6208          }
6209          for (node = node[name]; node; node = node[name]) {
6210            if (typeof func === 'function' && func(node)) {
6211              return node;
6212            }
6213          }
6214        }
6215        return null;
6216      };
6217      var getNext = function (node, selector) {
6218        return _findSib(node, selector, 'nextSibling');
6219      };
6220      var getPrev = function (node, selector) {
6221        return _findSib(node, selector, 'previousSibling');
6222      };
6223      var select = function (selector, scope) {
6224        return Sizzle(selector, get(scope) || settings.root_element || doc, []);
6225      };
6226      var run = function (elm, func, scope) {
6227        var result;
6228        var node = typeof elm === 'string' ? get(elm) : elm;
6229        if (!node) {
6230          return false;
6231        }
6232        if (Tools.isArray(node) && (node.length || node.length === 0)) {
6233          result = [];
6234          each$5(node, function (elm, i) {
6235            if (elm) {
6236              if (typeof elm === 'string') {
6237                elm = get(elm);
6238              }
6239              result.push(func.call(scope, elm, i));
6240            }
6241          });
6242          return result;
6243        }
6244        var context = scope ? scope : _this;
6245        return func.call(context, node);
6246      };
6247      var setAttribs = function (elm, attrs) {
6248        $$(elm).each(function (i, node) {
6249          each$5(attrs, function (value, name) {
6250            setAttrib(node, name, value);
6251          });
6252        });
6253      };
6254      var setHTML = function (elm, html) {
6255        var $elm = $$(elm);
6256        if (isIE) {
6257          $elm.each(function (i, target) {
6258            if (target.canHaveHTML === false) {
6259              return;
6260            }
6261            while (target.firstChild) {
6262              target.removeChild(target.firstChild);
6263            }
6264            try {
6265              target.innerHTML = '<br>' + html;
6266              target.removeChild(target.firstChild);
6267            } catch (ex) {
6268              DomQuery('<div></div>').html('<br>' + html).contents().slice(1).appendTo(target);
6269            }
6270            return html;
6271          });
6272        } else {
6273          $elm.html(html);
6274        }
6275      };
6276      var add = function (parentElm, name, attrs, html, create) {
6277        return run(parentElm, function (parentElm) {
6278          var newElm = typeof name === 'string' ? doc.createElement(name) : name;
6279          setAttribs(newElm, attrs);
6280          if (html) {
6281            if (typeof html !== 'string' && html.nodeType) {
6282              newElm.appendChild(html);
6283            } else if (typeof html === 'string') {
6284              setHTML(newElm, html);
6285            }
6286          }
6287          return !create ? parentElm.appendChild(newElm) : newElm;
6288        });
6289      };
6290      var create = function (name, attrs, html) {
6291        return add(doc.createElement(name), name, attrs, html, true);
6292      };
6293      var decode = Entities.decode;
6294      var encode = Entities.encodeAllRaw;
6295      var createHTML = function (name, attrs, html) {
6296        var outHtml = '', key;
6297        outHtml += '<' + name;
6298        for (key in attrs) {
6299          if (attrs.hasOwnProperty(key) && attrs[key] !== null && typeof attrs[key] !== 'undefined') {
6300            outHtml += ' ' + key + '="' + encode(attrs[key]) + '"';
6301          }
6302        }
6303        if (typeof html !== 'undefined') {
6304          return outHtml + '>' + html + '</' + name + '>';
6305        }
6306        return outHtml + ' />';
6307      };
6308      var createFragment = function (html) {
6309        var node;
6310        var container = doc.createElement('div');
6311        var frag = doc.createDocumentFragment();
6312        if (html) {
6313          container.innerHTML = html;
6314        }
6315        while (node = container.firstChild) {
6316          frag.appendChild(node);
6317        }
6318        return frag;
6319      };
6320      var remove = function (node, keepChildren) {
6321        var $node = $$(node);
6322        if (keepChildren) {
6323          $node.each(function () {
6324            var child;
6325            while (child = this.firstChild) {
6326              if (child.nodeType === 3 && child.data.length === 0) {
6327                this.removeChild(child);
6328              } else {
6329                this.parentNode.insertBefore(child, this);
6330              }
6331            }
6332          }).remove();
6333        } else {
6334          $node.remove();
6335        }
6336        return $node.length >
6336 1 ? $node.toArray() : $node[0];
6337      };
6338      var removeAllAttribs = function (e) {
6339        return run(e, function (e) {
6340          var i;
6341          var attrs = e.attributes;
6342          for (i = attrs.length - 1; i >= 0; i--) {
6343            e.removeAttributeNode(attrs.item(i));
6344          }
6345        });
6346      };
6347      var parseStyle = function (cssText) {
6348        return styles.parse(cssText);
6349      };
6350      var serializeStyle = function (stylesArg, name) {
6351        return styles.serialize(stylesArg, name);
6352      };
6353      var addStyle = function (cssText) {
6354        var head, styleElm;
6355        if (self !== DOMUtils.DOM && doc === domGlobals.document) {
6356          if (addedStyles[cssText]) {
6357            return;
6358          }
6359          addedStyles[cssText] = true;
6360        }
6361        styleElm = doc.getElementById('mceDefaultStyles');
6362        if (!styleElm) {
6363          styleElm = doc.createElement('style');
6364          styleElm.id = 'mceDefaultStyles';
6365          styleElm.type = 'text/css';
6366          head = doc.getElementsByTagName('head')[0];
6367          if (head.firstChild) {
6368            head.insertBefore(styleElm, head.firstChild);
6369          } else {
6370            head.appendChild(styleElm);
6371          }
6372        }
6373        if (styleElm.styleSheet) {
6374          styleElm.styleSheet.cssText += cssText;
6375        } else {
6376          styleElm.appendChild(doc.createTextNode(cssText));
6377        }
6378      };
6379      var loadCSS = function (url) {
6380        var head;
6381        if (self !== DOMUtils.DOM && doc === domGlobals.document) {
6382          DOMUtils.DOM.loadCSS(url);
6383          return;
6384        }
6385        if (!url) {
6386          url = '';
6387        }
6388        head = doc.getElementsByTagName('head')[0];
6389        each$5(url.split(','), function (url) {
6390          var link;
6391          url = Tools._addCacheSuffix(url);
6392          if (files[url]) {
6393            return;
6394          }
6395          files[url] = true;
6396          link = create('link', {
6397            rel: 'stylesheet',
6398            href: url
6399          });
6400          head.appendChild(link);
6401        });
6402      };
6403      var toggleClass = function (elm, cls, state) {
6404        $$(elm).toggleClass(cls, state).each(function () {
6405          if (this.className === '') {
6406            DomQuery(this).attr('class', null);
6407          }
6408        });
6409      };
6410      var addClass = function (elm, cls) {
6411        $$(elm).addClass(cls);
6412      };
6413      var removeClass = function (elm, cls) {
6414        toggleClass(elm, cls, false);
6415      };
6416      var hasClass = function (elm, cls) {
6417        return $$(elm).hasClass(cls);
6418      };
6419      var show = function (elm) {
6420        $$(elm).show();
6421      };
6422      var hide = function (elm) {
6423        $$(elm).hide();
6424      };
6425      var isHidden = function (elm) {
6426        return $$(elm).css('display') === 'none';
6427      };
6428      var uniqueId = function (prefix) {
6429        return (!prefix ? 'mce_' : prefix) + counter++;
6430      };
6431      var getOuterHTML = function (elm) {
6432        var node = typeof elm === 'string' ? get(elm) : elm;
6433        return NodeType.isElement(node) ? node.outerHTML : DomQuery('<div></div>').append(DomQuery(node).clone()).html();
6434      };
6435      var setOuterHTML = function (elm, html) {
6436        $$(elm).each(function () {
6437          try {
6438            if ('outerHTML' in this) {
6439              this.outerHTML = html;
6440              return;
6441            }
6442          } catch (ex) {
6443          }
6444          remove(DomQuery(this).html(html), true);
6445        });
6446      };
6447      var insertAfter = function (node, reference) {
6448        var referenceNode = get(reference);
6449        return run(node, function (node) {
6450          var parent, nextSibling;
6451          parent = referenceNode.parentNode;
6452          nextSibling = referenceNode.nextSibling;
6453          if (nextSibling) {
6454            parent.insertBefore(node, nextSibling);
6455          } else {
6456            parent.appendChild(node);
6457          }
6458          return node;
6459        });
6460      };
6461      var replace = function (newElm, oldElm, keepChildren) {
6462        return run(oldElm, function (oldElm) {
6463          if (Tools.is(oldElm, 'array')) {
6464            newElm = newElm.cloneNode(true);
6465          }
6466          if (keepChildren) {
6467            each$5(grep$1(oldElm.childNodes), function (node) {
6468              newElm.appendChild(node);
6469            });
6470          }
6471          return oldElm.parentNode.replaceChild(newElm, oldElm);
6472        });
6473      };
6474      var rename = function (elm, name) {
6475        var newElm;
6476        if (elm.nodeName !== name.toUpperCase()) {
6477          newElm = create(name);
6478          each$5(getAttribs(elm), function (attrNode) {
6479            setAttrib(newElm, attrNode.nodeName, getAttrib(elm, attrNode.nodeName));
6480          });
6481          replace(newElm, elm, true);
6482        }
6483        return newElm || elm;
6484      };
6485      var findCommonAncestor = function (a, b) {
6486        var ps = a, pe;
6487        while (ps) {
6488          pe = b;
6489          while (pe && ps !== pe) {
6490            pe = pe.parentNode;
6491          }
6492          if (ps === pe) {
6493            break;
6494          }
6495          ps = ps.parentNode;
6496        }
6497        if (!ps && a.ownerDocument) {
6498          return a.ownerDocument.documentElement;
6499        }
6500        return ps;
6501      };
6502      var toHex = function (rgbVal) {
6503        return styles.toHex(Tools.trim(rgbVal));
6504      };
6505      var isEmpty = function (node, elements) {
6506        var i, attributes, type, name, brCount = 0;
6507        node = node.firstChild;
6508        if (node) {
6509          var walker = new TreeWalker(node, node.parentNode);
6510          var whitespace = schema ? schema.getWhiteSpaceElements() : {};
6511          elements = elements || (schema ? schema.getNonEmptyElements() : null);
6512          do {
6513            type = node.nodeType;
6514            if (NodeType.isElement(node)) {
6515              var bogusVal = node.getAttribute('data-mce-bogus');
6516              if (bogusVal) {
6517                node = walker.next(bogusVal === 'all');
6518                continue;
6519              }
6520              name = node.nodeName.toLowerCase();
6521              if (elements && elements[name]) {
6522                if (name === 'br') {
6523                  brCount++;
6524                  node = walker.next();
6525                  continue;
6526                }
6527                return false;
6528              }
6529              attributes = getAttribs(node);
6530              i = attributes.length;
6531              while (i--) {
6532                name = attributes[i].nodeName;
6533                if (name === 'name' || name === 'data-mce-bookmark') {
6534                  return false;
6535                }
6536              }
6537            }
6538            if (type === 8) {
6539              return false;
6540            }
6541            if (type === 3 && !whiteSpaceRegExp$2.test(node.nodeValue)) {
6542              return false;
6543            }
6544            if (type === 3 && node.parentNode && whitespace[node.parentNode.nodeName] && whiteSpaceRegExp$2.test(node.nodeValue)) {
6545              return false;
6546            }
6547            node = walker.next();
6548          } while (node);
6549        }
6550        return brCount <= 1;
6551      };
6552      var createRng = function () {
6553        return doc.createRange();
6554      };
6555      var split = function (parentElm, splitElm, replacementElm) {
6556        var r = createRng(), bef, aft, pa;
6557        if (parentElm && splitElm) {
6558          r.setStart(parentElm.parentNode, findNodeIndex(parentElm));
6559          r.setEnd(splitElm.parentNode, findNodeIndex(splitElm));
6560          bef = r.extractContents();
6561          r = createRng();
6562          r.setStart(splitElm.parentNode, findNodeIndex(splitElm) + 1);
6563          r.setEnd(parentElm.parentNode, findNodeIndex(parentElm) + 1);
6564          aft = r.extractContents();
6565          pa = parentElm.parentNode;
6566          pa.insertBefore(TrimNode.trimNode(self, bef), parentElm);
6567          if (replacementElm) {
6568            pa.insertBefore(replacementElm, parentElm);
6569          } else {
6570            pa.insertBefore(splitElm, parentElm);
6571          }
6572          pa.insertBefore(TrimNode.trimNode(self, aft), parentElm);
6573          remove(parentElm);
6574          return replacementElm || splitElm;
6575        }
6576      };
6577      var bind = function (target, name, func, scope) {
6578        if (Tools.isArray(target)) {
6579          var i = target.length;
6580          var rv = [];
6581          while (i--) {
6582            rv[i] = bind(target[i], name, func, scope);
6583          }
6584          return rv;
6585        }
6586        if (settings.collect && (target === doc || target === win)) {
6587          boundEvents.push([
6588            target,
6589            name,
6590            func,
6591            scope
6592          ]);
6593        }
6594        return events.bind(target, name, func, scope || self);
6595      };
6596      var unbind = function (target, name, func) {
6597        var i;
6598        if (Tools.isArray(target)) {
6599          i = target.length;
6600          var rv = [];
6601          while (i--) {
6602            rv[i] = unbind(target[i], name, func);
6603          }
6604          return rv;
6605        }
6606        if (boundEvents && (target === doc || target === win)) {
6607          i = boundEvents.length;
6608          while (i--) {
6609            var item = boundEvents[i];
6610            if (target === item[0] && (!name || name === item[1]) && (!func || func === item[2])) {
6611              events.unbind(item[0], item[1], item[2]);
6612            }
6613          }
6614        }
6615        return events.unbind(target, name, func);
6616      };
6617      var fire = function (target, name, evt) {
6618        return events.fire(target, name, evt);
6619      };
6620      var getContentEditable = function (node) {
6621        if (node && NodeType.isElement(node)) {
6622          var contentEditable = node.getAttribute('data-mce-contenteditable');
6623          if (contentEditable && contentEditable !== 'inherit') {
6624            return contentEditable;
6625          }
6626          return node.contentEditable !== 'inherit' ? node.contentEditable : null;
6627        } else {
6628          return null;
6629        }
6630      };
6631      var getContentEditableParent = function (node) {
6632        var root = getRoot();
6633        var state = null;
6634        for (; node && node !== root; node = node.parentNode) {
6635          state = getContentEditable(node);
6636          if (state !== null) {
6637            break;
6638          }
6639        }
6640        return state;
6641      };
6642      var destroy = function () {
6643        if (boundEvents) {
6644          var i = boundEvents.length;
6645          while (i--) {
6646            var item = boundEvents[i];
6647            events.unbind(item[0], item[1], item[2]);
6648          }
6649        }
6650        if (Sizzle.setDocument) {
6651          Sizzle.setDocument();
6652        }
6653      };
6654      var isChildOf = function (node, parent) {
6655        while (node) {
6656          if (parent === node) {
6657            return true;
6658          }
6659          node = node.parentNode;
6660        }
6661        return false;
6662      };
6663      var dumpRng = function (r) {
6664        return 'startContainer: ' + r.startContainer.nodeName + ', startOffset: ' + r.startOffset + ', endContainer: ' + r.endContainer.nodeName + ', endOffset: ' + r.endOffset;
6665      };
6666      var self = {
6667        doc: doc,
6668        settings: settings,
6669        win: win,
6670        files: files,
6671        stdMode: stdMode,
6672        boxModel: boxModel,
6673        styleSheetLoader: styleSheetLoader,
6674        boundEvents: boundEvents,
6675        styles: styles,
6676        schema: schema,
6677        events: events,
6678        isBlock: isBlock,
6679        $: $,
6680        $$: $$,
6681        root: null,
6682        clone: clone,
6683        getRoot: getRoot,
6684        getViewPort: getViewPort,
6685        getRect: getRect,
6686        getSize: getSize,
6687        getParent: getParent,
6688        getParents: getParents,
6689        get: get,
6690        getNext: getNext,
6691        getPrev: getPrev,
6692        select: select,
6693        is: is,
6694        add: add,
6695        create: create,
6696        createHTML: createHTML,
6697        createFragment: createFragment,
6698        remove: remove,
6699        setStyle: setStyle,
6700        getStyle: getStyle,
6701        setStyles: setStyles,
6702        removeAllAttribs: removeAllAttribs,
6703        setAttrib: setAttrib,
6704        setAttribs: setAttribs,
6705        getAttrib: getAttrib,
6706        getPos: getPos,
6707        parseStyle: parseStyle,
6708        serializeStyle: serializeStyle,
6709        addStyle: addStyle,
6710        loadCSS: loadCSS,
6711        addClass: addClass,
6712        removeClass: removeClass,
6713        hasClass: hasClass,
6714        toggleClass: toggleClass,
6715        show: show,
6716        hide: hide,
6717        isHidden: isHidden,
6718        uniqueId: uniqueId,
6719        setHTML: setHTML,
6720        getOuterHTML: getOuterHTML,
6721        setOuterHTML: setOuterHTML,
6722        decode: decode,
6723        encode: encode,
6724        insertAfter: insertAfter,
6725        replace: replace,
6726        rename: rename,
6727        findCommonAncestor: findCommonAncestor,
6728        toHex: toHex,
6729        run: run,
6730        getAttribs: getAttribs,
6731        isEmpty: isEmpty,
6732        createRng: createRng,
6733        nodeIndex: findNodeIndex,
6734        split: split,
6735        bind: bind,
6736        unbind: unbind,
6737        fire: fire,
6738        getContentEditable: getContentEditable,
6739        getContentEditableParent: getContentEditableParent,
6740        destroy: destroy,
6741        isChildOf: isChildOf,
6742        dumpRng: dumpRng
6743      };
6744      attrHooks = setupAttrHooks(styles, settings, function () {
6745        return self;
6746      });
6747      return self;
6748    }
6749    (function (DOMUtils) {
6750      DOMUtils.DOM = DOMUtils(domGlobals.document);
6751      DOMUtils.nodeIndex = findNodeIndex;
6752    }(DOMUtils || (DOMUtils = {})));
6753    var DOMUtils$1 = DOMUtils;
6754
6755    var DOM = DOMUtils$1.DOM;
6756    var each$6 = Tools.each, grep$2 = Tools.grep;
6757    var QUEUED = 0;
6758    var LOADING = 1;
6759    var LOADED = 2;
6760    var FAILED = 3;
6761    var ScriptLoader = function () {
6762      function ScriptLoader() {
6763        this.states = {};
6764        this.queue = [];
6765        this.scriptLoadedCallbacks = {};
6766        this.queueLoadedCallbacks = [];
6767        this.loading = 0;
6768      }
6769      ScriptLoader.prototype.loadScript = function (url, success, failure) {
6770        var dom = DOM;
6771        var elm, id;
6772        var done = function () {
6773          dom.remove(id);
6774          if (elm) {
6775            elm.onreadystatechange = elm.onload = elm = null;
6776          }
6777          success();
6778        };
6779        var error = function () {
6780          if (isFunction(failure)) {
6781            failure();
6782          } else {
6783            if (typeof domGlobals.console !== 'undefined' && domGlobals.console.log) {
6784              domGlobals.console.log('Failed to load script: ' + url);
6785            }
6786          }
6787        };
6788        id = dom.uniqueId();
6789        elm = domGlobals.document.createElement('script');
6790        elm.id = id;
6791        elm.type = 'text/javascript';
6792        elm.src = Tools._addCacheSuffix(url);
6793        elm.onload = done;
6794        elm.onerror = error;
6795        (domGlobals.document.getElementsByTagName('head')[0] || domGlobals.document.body).appendChild(elm);
6796      };
6797      ScriptLoader.prototype.isDone = function (url) {
6798        return this.states[url] === LOADED;
6799      };
6800      ScriptLoader.prototype.markDone = function (url) {
6801        this.states[url] = LOADED;
6802      };
6803      ScriptLoader.prototype.add = function (url, success, scope, failure) {
6804        var state = this.states[url];
6805        if (state === undefined) {
6806          this.queue.push(url);
6807          this.states[url] = QUEUED;
6808        }
6809        if (success) {
6810          if (!this.scriptLoadedCallbacks[url]) {
6811            this.scriptLoadedCallbacks[url] = [];
6812          }
6813          this.scriptLoadedCallbacks[url].push({
6814            success: success,
6815            failure: failure,
6816            scope: scope || this
6817          });
6818        }
6819      };
6820      ScriptLoader.prototype.load = function (url, success, scope, failure) {
6821        return this.add(url, success, scope, failure);
6822      };
6823      ScriptLoader.prototype.remove = function (url) {
6824        delete this.states[url];
6825        delete this.scriptLoadedCallbacks[url];
6826      };
6827      ScriptLoader.prototype.loadQueue = function (success, scope, failure) {
6828        this.loadScripts(this.queue, success, scope, failure);
6829      };
6830      ScriptLoader.prototype.loadScripts = function (scripts, success, scope, failure) {
6831        var self = this;
6832        var loadScripts;
6833        var failures = [];
6834        var execCallbacks = function (name, url) {
6835          each$6(self.scriptLoadedCallbacks[url], function (callback) {
6836            if (isFunction(callback[name])) {
6837              callback[name].call(callback.scope);
6838            }
6839          });
6840          self.scriptLoadedCallbacks[url] = undefined;
6841        };
6842        self.queueLoadedCallbacks.push({
6843          success: success,
6844          failure: failure,
6845          scope: scope || this
6846        });
6847        loadScripts = function () {
6848          var loadingScripts = grep$2(scripts);
6849          scripts.length = 0;
6850          each$6(loadingScripts, function (url) {
6851            if (self.states[url] === LOADED) {
6852              execCallbacks('success', url);
6853              return;
6854            }
6855            if (self.states[url] === FAILED) {
6856              execCallbacks('failure', url);
6857              return;
6858            }
6859            if (self.states[url] !== LOADING) {
6860              self.states[url] = LOADING;
6861              self.loading++;
6862              self.loadScript(url, function () {
6863                self.states[url] = LOADED;
6864                self.loading--;
6865                execCallbacks('success', url);
6866                loadScripts();
6867              }, function () {
6868                self.states[url] = FAILED;
6869                self.loading--;
6870                failures.push(url);
6871                execCallbacks('failure', url);
6872                loadScripts();
6873              });
6874            }
6875          });
6876          if (!self.loading) {
6877            var notifyCallbacks = self.queueLoadedCallbacks.slice(0);
6878            self.queueLoadedCallbacks.length = 0;
6879            each$6(notifyCallbacks, function (callback) {
6880              if (failures.length === 0) {
6881                if (isFunction(callback.success)) {
6882                  callback.success.call(callback.scope);
6883                }
6884              } else {
6885                if (isFunction(callback.failure)) {
6886                  callback.failure.call(callback.scope, failures);
6887                }
6888              }
6889            });
6890          }
6891        };
6892        loadScripts();
6893      };
6894      ScriptLoader.ScriptLoader = new ScriptLoader();
6895      return ScriptLoader;
6896    }();
6897
6898    var extendStatics = function (d, b) {
6899      extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {
6900        d.__proto__ = b;
6901      } || function (d, b) {
6902        for (var p in b)
6903          if (b.hasOwnProperty(p))
6904            d[p] = b[p];
6905      };
6906      return extendStatics(d, b);
6907    };
6908    function __extends(d, b) {
6909      extendStatics(d, b);
6910      function __() {
6911        this.constructor = d;
6912      }
6913      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6914    }
6915    var __assign = function () {
6916      __assign = Object.assign || function __assign(t) {
6917        for (var s, i = 1, n = arguments.length; i < n; i++) {
6918          s = arguments[i];
6919          for (var p in s)
6920            if (Object.prototype.hasOwnProperty.call(s, p))
6921              t[p] = s[p];
6922        }
6923        return t;
6924      };
6925      return __assign.apply(this, arguments);
6926    };
6927    function __rest(s, e) {
6928      var t = {};
6929      for (var p in s)
6930        if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
6931          t[p] = s[p];
6932      if (s != null && typeof Object.getOwnPropertySymbols === 'function')
6933        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++)
6934          if (e.indexOf(p[i]) < 0)
6935            t[p[i]] = s[p[i]];
6936      return t;
6937    }
6938    function __decorate(decorators, target, key, desc) {
6939      var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6940      if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function')
6941        r = Reflect.decorate(decorators, target, key, desc);
6942      else
6943        for (var i = decorators.length - 1; i >= 0; i--)
6944          if (d = decorators[i])
6945            r = (c < 3 ? d(r) : c >
6945 3 ? d(target, key, r) : d(target, key)) || r;
6946      return c > 3 && r && Object.defineProperty(target, key, r), r;
6947    }
6948    function __param(paramIndex, decorator) {
6949      return function (target, key) {
6950        decorator(target, key, paramIndex);
6951      };
6952    }
6953    function __metadata(metadataKey, metadataValue) {
6954      if (typeof Reflect === 'object' && typeof Reflect.metadata === 'function')
6955        return Reflect.metadata(metadataKey, metadataValue);
6956    }
6957    function __awaiter(thisArg, _arguments, P, generator) {
6958      return new (P || (P = Promise))(function (resolve, reject) {
6959        function fulfilled(value) {
6960          try {
6961            step(generator.next(value));
6962          } catch (e) {
6963            reject(e);
6964          }
6965        }
6966        function rejected(value) {
6967          try {
6968            step(generator['throw'](value));
6969          } catch (e) {
6970            reject(e);
6971          }
6972        }
6973        function step(result) {
6974          result.done ? resolve(result.value) : new P(function (resolve) {
6975            resolve(result.value);
6976          }).then(fulfilled, rejected);
6977        }
6978        step((generator = generator.apply(thisArg, _arguments || [])).next());
6979      });
6980    }
6981    function __generator(thisArg, body) {
6982      var _ = {
6983          label: 0,
6984          sent: function () {
6985            if (t[0] & 1)
6986              throw t[1];
6987            return t[1];
6988          },
6989          trys: [],
6990          ops: []
6991        }, f, y, t, g;
6992      return g = {
6993        next: verb(0),
6994        'throw': verb(1),
6995        'return': verb(2)
6996      }, typeof Symbol === 'function' && (g[Symbol.iterator] = function () {
6997        return this;
6998      }), g;
6999      function verb(n) {
7000        return function (v) {
7001          return step([
7002            n,
7003            v
7004          ]);
7005        };
7006      }
7007      function step(op) {
7008        if (f)
7009          throw new TypeError('Generator is already executing.');
7010        while (_)
7011          try {
7012            if (f = 1, y && (t = op[0] & 2 ? y['return'] : op[0] ? y['throw'] || ((t = y['return']) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
7013              return t;
7014            if (y = 0, t)
7015              op = [
7016                op[0] & 2,
7017                t.value
7018              ];
7019            switch (op[0]) {
7020            case 0:
7021            case 1:
7022              t = op;
7023              break;
7024            case 4:
7025              _.label++;
7026              return {
7027                value: op[1],
7028                done: false
7029              };
7030            case 5:
7031              _.label++;
7032              y = op[1];
7033              op = [0];
7034              continue;
7035            case 7:
7036              op = _.ops.pop();
7037              _.trys.pop();
7038              continue;
7039            default:
7040              if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
7041                _ = 0;
7042                continue;
7043              }
7044              if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
7045                _.label = op[1];
7046                break;
7047              }
7048              if (op[0] === 6 && _.label < t[1]) {
7049                _.label = t[1];
7050                t = op;
7051                break;
7052              }
7053              if (t && _.label < t[2]) {
7054                _.label = t[2];
7055                _.ops.push(op);
7056                break;
7057              }
7058              if (t[2])
7059                _.ops.pop();
7060              _.trys.pop();
7061              continue;
7062            }
7063            op = body.call(thisArg, _);
7064          } catch (e) {
7065            op = [
7066              6,
7067              e
7068            ];
7069            y = 0;
7070          } finally {
7071            f = t = 0;
7072          }
7073        if (op[0] & 5)
7074          throw op[1];
7075        return {
7076          value: op[0] ? op[1] : void 0,
7077          done: true
7078        };
7079      }
7080    }
7081    function __exportStar(m, exports) {
7082      for (var p in m)
7083        if (!exports.hasOwnProperty(p))
7084          exports[p] = m[p];
7085    }
7086    function __values(o) {
7087      var m = typeof Symbol === 'function' && o[Symbol.iterator], i = 0;
7088      if (m)
7089        return m.call(o);
7090      return {
7091        next: function () {
7092          if (o && i >= o.length)
7093            o = void 0;
7094          return {
7095            value: o && o[i++],
7096            done: !o
7097          };
7098        }
7099      };
7100    }
7101    function __read(o, n) {
7102      var m = typeof Symbol === 'function' && o[Symbol.iterator];
7103      if (!m)
7104        return o;
7105      var i = m.call(o), r, ar = [], e;
vendor: 3,121 bytes, lines 7106-7209
7106      try {
7107        while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
7108          ar.push(r.value);
7109      } catch (error) {
7110        e = { error: error };
7111      } finally {
7112        try {
7113          if (r && !r.done && (m = i['return']))
7114            m.call(i);
7115        } finally {
7116          if (e)
7117            throw e.error;
7118        }
7119      }
7120      return ar;
7121    }
7122    function __spread() {
7123      for (var ar = [], i = 0; i < arguments.length; i++)
7124        ar = ar.concat(__read(arguments[i]));
7125      return ar;
7126    }
7127    function __await(v) {
7128      return this instanceof __await ? (this.v = v, this) : new __await(v);
7129    }
7130    function __asyncGenerator(thisArg, _arguments, generator) {
7131      if (!Symbol.asyncIterator)
7132        throw new TypeError('Symbol.asyncIterator is not defined.');
7133      var g = generator.apply(thisArg, _arguments || []), i, q = [];
7134      return i = {}, verb('next'), verb('throw'), verb('return'), i[Symbol.asyncIterator] = function () {
7135        return this;
7136      }, i;
7137      function verb(n) {
7138        if (g[n])
7139          i[n] = function (v) {
7140            return new Promise(function (a, b) {
7141              q.push([
7142                n,
7143                v,
7144                a,
7145                b
7146              ]) > 1 || resume(n, v);
7147            });
7148          };
7149      }
7150      function resume(n, v) {
7151        try {
7152          step(g[n](v));
7153        } catch (e) {
7154          settle(q[0][3], e);
7155        }
7156      }
7157      function step(r) {
7158        r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
7159      }
7160      function fulfill(value) {
7161        resume('next', value);
7162      }
7163      function reject(value) {
7164        resume('throw', value);
7165      }
7166      function settle(f, v) {
7167        if (f(v), q.shift(), q.length)
7168          resume(q[0][0], q[0][1]);
7169      }
7170    }
7171    function __asyncDelegator(o) {
7172      var i, p;
7173      return i = {}, verb('next'), verb('throw', function (e) {
7174        throw e;
7175      }), verb('return'), i[Symbol.iterator] = function () {
7176        return this;
7177      }, i;
7178      function verb(n, f) {
7179        i[n] = o[n] ? function (v) {
7180          return (p = !p) ? {
7181            value: __await(o[n](v)),
7182            done: n === 'return'
7183          } : f ? f(v) : v;
7184        } : f;
7185      }
7186    }
7187    function __asyncValues(o) {
7188      if (!Symbol.asyncIterator)
7189        throw new TypeError('Symbol.asyncIterator is not defined.');
7190      var m = o[Symbol.asyncIterator], i;
7191      return m ? m.call(o) : (o = typeof __values === 'function' ? __values(o) : o[Symbol.iterator](), i = {}, verb('next'), verb('throw'), verb('return'), i[Symbol.asyncIterator] = function () {
7192        return this;
7193      }, i);
7194      function verb(n) {
7195        i[n] = o[n] && function (v) {
7196          return new Promise(function (resolve, reject) {
7197            v = o[n](v), settle(resolve, reject, v.done, v.value);
7198          });
7199        };
7200      }
7201      function settle(resolve, reject, d, v) {
7202        Promise.resolve(v).then(function (v) {
7203          resolve({
7204            value: v,
7205            done: d
7206          });
7207        }, reject);
7208      }
7209    }
7210    function __makeTemplateObject(cooked, raw) {
7211      if (Object.defineProperty) {
7212        Object.defineProperty(cooked, 'raw', { value: raw });
7213      } else {
7214        cooked.raw = raw;
7215      }
7216      return cooked;
7217    }
7218    function __importStar(mod) {
7219      if (mod && mod.__esModule)
7220        return mod;
7221      var result = {};
7222      if (mod != null)
7223        for (var k in mod)
7224          if (Object.hasOwnProperty.call(mod, k))
7225            result[k] = mod[k];
7226      result.default = mod;
7227      return result;
7228    }
7229    function __importDefault(mod) {
7230      return mod && mod.__esModule ? mod : { default: mod };
7231    }
7232
7233    var tslib_1 = /*#__PURE__*/Object.freeze({
7234        __extends: __extends,
7235        get __assign () { return __assign; },
7236        __rest: __rest,
7237        __decorate: __decorate,
7238        __param: __param,
7239        __metadata: __metadata,
7240        __awaiter: __awaiter,
7241        __generator: __generator,
7242        __exportStar: __exportStar,
7243        __values: __values,
7244        __read: __read,
7245        __spread: __spread,
7246        __await: __await,
7247        __asyncGenerator: __asyncGenerator,
7248        __asyncDelegator: __asyncDelegator,
7249        __asyncValues: __asyncValues,
7250        __makeTemplateObject: __makeTemplateObject,
7251        __importStar: __importStar,
7252        __importDefault: __importDefault
7253    });
7254
7255    var Cell = function (initial) {
7256      var value = initial;
7257      var get = function () {
7258        return value;
7259      };
7260      var set = function (v) {
7261        value = v;
7262      };
7263      var clone = function () {
7264        return Cell(get());
7265      };
7266      return {
7267        get: get,
7268        set: set,
7269        clone: clone
7270      };
7271    };
7272
7273    var isRaw = function (str) {
7274      return isObject(str) && has(str, 'raw');
7275    };
7276    var isTokenised = function (str) {
7277      return isArray(str) && str.length > 1;
7278    };
7279    var data = {};
7280    var currentCode = Cell('en');
7281    var getData = function () {
7282      return map$2(data, function (value) {
7283        return __assign({}, value);
7284      });
7285    };
7286    var setCode = function (newCode) {
7287      if (newCode) {
7288        currentCode.set(newCode);
7289      }
7290    };
7291    var getCode = function () {
7292      return currentCode.get();
7293    };
7294    var add = function (code, items) {
7295      var langData = data[code];
7296      if (!langData) {
7297        data[code] = langData = {};
7298      }
7299      for (var name in items) {
7300        langData[name.toLowerCase()] = items[name];
7301      }
7302    };
7303    var translate = function (text) {
7304      var langData = data[currentCode.get()] || {};
7305      var toString = function (obj) {
7306        if (isFunction(obj)) {
7307          return Object.prototype.toString.call(obj);
7308        }
7309        return !isEmpty(obj) ? '' + obj : '';
7310      };
7311      var isEmpty = function (text) {
7312        return text === '' || text === null || text === undefined;
7313      };
7314      var getLangData = function (text) {
7315        var textstr = toString(text);
7316        var lowercaseTextstr = textstr.toLowerCase();
7317        return has(langData, lowercaseTextstr) ? toString(langData[lowercaseTextstr]) : textstr;
7318      };
7319      var removeContext = function (str) {
7320        return str.replace(/{context:\w+}$/, '');
7321      };
7322      var translated = function (text) {
7323        return text;
7324      };
7325      if (isEmpty(text)) {
7326        return translated('');
7327      }
7328      if (isRaw(text)) {
7329        return translated(toString(text.raw));
7330      }
7331      if (isTokenised(text)) {
7332        var values_1 = text.slice(1);
7333        var substitued = getLangData(text[0]).replace(/\{([0-9]+)\}/g, function ($1, $2) {
7334          return has(values_1, $2) ? toString(values_1[$2]) : $1;
7335        });
7336        return translated(removeContext(substitued));
7337      }
7338      return translated(removeContext(getLangData(text)));
7339    };
7340    var isRtl = function () {
7341      return get(data, currentCode.get()).bind(function (items) {
7342        return get(items, '_dir');
7343      }).exists(function (dir) {
7344        return dir === 'rtl';
7345      });
7346    };
7347    var hasCode = function (code) {
7348      return has(data, code);
7349    };
7350    var I18n = {
7351      getData: getData,
7352      setCode: setCode,
7353      getCode: getCode,
7354      add: add,
7355      translate: translate,
7356      isRtl: isRtl,
7357      hasCode: hasCode
7358    };
7359
7360    var each$7 = Tools.each;
7361    function AddOnManager() {
7362      var _this = this;
7363      var items = [];
7364      var urls = {};
7365      var lookup = {};
7366      var _listeners = [];
7367      var get = function (name) {
7368        if (lookup[name]) {
7369          return lookup[name].instance;
7370        }
7371        return undefined;
7372      };
7373      var dependencies = function (name) {
7374        var result;
7375        if (lookup[name]) {
7376          result = lookup[name].dependencies;
7377        }
7378        return result || [];
7379      };
7380      var requireLangPack = function (name, languages) {
7381        var language = I18n.getCode();
7382        if (language && AddOnManager.languageLoad !== false) {
7383          if (languages) {
7384            languages = ',' + languages + ',';
7385            if (languages.indexOf(',' + language.substr(0, 2) + ',') !== -1) {
7386              language = language.substr(0, 2);
7387            } else if (languages.indexOf(',' + language + ',') === -1) {
7388              return;
7389            }
7390          }
7391          ScriptLoader.ScriptLoader.add(urls[name] + '/langs/' + language + '.js');
7392        }
7393      };
7394      var add = function (id, addOn, dependencies) {
7395        items.push(addOn);
7396        lookup[id] = {
7397          instance: addOn,
7398          dependencies: dependencies
7399        };
7400        var result = partition(_listeners, function (listener) {
7401          return listener.name === id;
7402        });
7403        _listeners = result.fail;
7404        each$7(result.pass, function (listener) {
7405          listener.callback();
7406        });
7407        return addOn;
7408      };
7409      var remove = function (name) {
7410        delete urls[name];
7411        delete lookup[name];
7412      };
7413      var createUrl = function (baseUrl, dep) {
7414        if (typeof dep === 'object') {
7415          return dep;
7416        }
7417        return typeof baseUrl === 'string' ? {
7418          prefix: '',
7419          resource: dep,
7420          suffix: ''
7421        } : {
7422          prefix: baseUrl.prefix,
7423          resource: dep,
7424          suffix: baseUrl.suffix
7425        };
7426      };
7427      var addComponents = function (pluginName, scripts) {
7428        var pluginUrl = _this.urls[pluginName];
7429        each$7(scripts, function (script) {
7430          ScriptLoader.ScriptLoader.add(pluginUrl + '/' + script);
7431        });
7432      };
7433      var loadDependencies = function (name, addOnUrl, success, scope) {
7434        var deps = dependencies(name);
7435        each$7(deps, function (dep) {
7436          var newUrl = createUrl(addOnUrl, dep);
7437          load(newUrl.resource, newUrl, undefined, undefined);
7438        });
7439        if (success) {
7440          if (scope) {
7441            success.call(scope);
7442          } else {
7443            success.call(ScriptLoader);
7444          }
7445        }
7446      };
7447      var load = function (name, addOnUrl, success, scope, failure) {
7448        if (urls[name]) {
7449          return;
7450        }
7451        var urlString = typeof addOnUrl === 'string' ? addOnUrl : addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
7452        if (urlString.indexOf('/') !== 0 && urlString.indexOf('://') === -1) {
7453          urlString = AddOnManager.baseURL + '/' + urlString;
7454        }
7455        urls[name] = urlString.substring(0, urlString.lastIndexOf('/'));
7456        if (lookup[name]) {
7457          loadDependencies(name, addOnUrl, success, scope);
7458        } else {
7459          ScriptLoader.ScriptLoader.add(urlString, function () {
7460            return loadDependencies(name, addOnUrl, success, scope);
7461          }, scope, failure);
7462        }
7463      };
7464      var waitFor = function (name, callback) {
7465        if (lookup.hasOwnProperty(name)) {
7466          callback();
7467        } else {
7468          _listeners.push({
7469            name: name,
7470            callback: callback
7471          });
7472        }
7473      };
7474      return {
7475        items: items,
7476        urls: urls,
7477        lookup: lookup,
7478        _listeners: _listeners,
7479        get: get,
7480        dependencies: dependencies,
7481        requireLangPack: requireLangPack,
7482        add: add,
7483        remove: remove,
7484        createUrl: createUrl,
7485        addComponents: addComponents,
7486        load: load,
7487        waitFor: waitFor
7488      };
7489    }
7490    (function (AddOnManager) {
7491      AddOnManager.PluginManager = AddOnManager();
7492      AddOnManager.ThemeManager = AddOnManager();
7493    }(AddOnManager || (AddOnManager = {})));
7494    var AddOnManager$1 = AddOnManager;
7495
7496    var before = function (marker, element) {
7497      var parent$1 = parent(marker);
7498      parent$1.each(function (v) {
7499        v.dom().insertBefore(element.dom(), marker.dom());
7500      });
7501    };
7502    var after = function (marker, element) {
7503      var sibling = nextSibling(marker);
7504      sibling.fold(function () {
7505        var parent$1 = parent(marker);
7506        parent$1.each(function (v) {
7507          append(v, element);
7508        });
7509      }, function (v) {
7510        before(v, element);
7511      });
7512    };
7513    var prepend = function (parent, element) {
7514      var firstChild$1 = firstChild(parent);
7515      firstChild$1.fold(function () {
7516        append(parent, element);
7517      }, function (v) {
7518        parent.dom().insertBefore(element.dom(), v.dom());
7519      });
7520    };
7521    var append = function (parent, element) {
7522      parent.dom().appendChild(element.dom());
7523    };
7524    var wrap$1 = function (element, wrapper) {
7525      before(element, wrapper);
7526      append(wrapper, element);
7527    };
7528
7529    var before$1 = function (marker, elements) {
7530      each(elements, function (x) {
7531        before(marker, x);
7532      });
7533    };
7534    var append$1 = function (parent, elements) {
7535      each(elements, function (x) {
7536        append(parent, x);
7537      });
7538    };
7539
7540    var empty = function (element) {
7541      element.dom().textContent = '';
7542      each(children(element), function (rogue) {
7543        remove$1(rogue);
7544      });
7545    };
7546    var remove$1 = function (element) {
7547      var dom = element.dom();
7548      if (dom.parentNode !== null) {
7549        dom.parentNode.removeChild(dom);
7550      }
7551    };
7552    var unwrap = function (wrapper) {
7553      var children$1 = children(wrapper);
7554      if (children$1.length > 0) {
7555        before$1(wrapper, children$1);
7556      }
7557      remove$1(wrapper);
7558    };
7559
7560    var first = function (fn, rate) {
7561      var timer = null;
7562      var cancel = function () {
7563        if (timer !== null) {
7564          domGlobals.clearTimeout(timer);
7565          timer = null;
7566        }
7567      };
7568      var throttle = function () {
7569        var args = [];
7570        for (var _i = 0; _i < arguments.length; _i++) {
7571          args[_i] = arguments[_i];
7572        }
7573        if (timer === null) {
7574          timer = domGlobals.setTimeout(function () {
7575            fn.apply(null, args);
7576            timer = null;
7577          }, rate);
7578        }
7579      };
7580      return {
7581        cancel: cancel,
7582        throttle: throttle
7583      };
7584    };
7585    var last$2 = function (fn, rate) {
7586      var timer = null;
7587      var cancel = function () {
7588        if (timer !== null) {
7589          domGlobals.clearTimeout(timer);
7590          timer = null;
7591        }
7592      };
7593      var throttle = function () {
7594        var args = [];
7595        for (var _i = 0; _i < arguments.length; _i++) {
7596          args[_i] = arguments[_i];
7597        }
7598        if (timer !== null)
7599          domGlobals.clearTimeout(timer);
7600        timer = domGlobals.setTimeout(function () {
7601          fn.apply(null, args);
7602          timer = null;
7603        }, rate);
7604      };
7605      return {
7606        cancel: cancel,
7607        throttle: throttle
7608      };
7609    };
7610
7611    var read = function (element, attr) {
7612      var value = get$1(element, attr);
7613      return value === undefined || value === '' ? [] : value.split(' ');
7614    };
7615    var add$1 = function (element, attr, id) {
7616      var old = read(element, attr);
7617      var nu = old.concat([id]);
7618      set(element, attr, nu.join(' '));
7619      return true;
7620    };
7621    var remove$2 = function (element, attr, id) {
7622      var nu = filter(read(element, attr), function (v) {
7623        return v !== id;
7624      });
7625      if (nu.length > 0) {
7626        set(element, attr, nu.join(' '));
7627      } else {
7628        remove(element, attr);
7629      }
7630      return false;
7631    };
7632
7633    var supports = function (element) {
7634      return element.dom().classList !== undefined;
7635    };
7636    var get$3 = function (element) {
7637      return read(element, 'class');
7638    };
7639    var add$2 = function (element, clazz) {
7640      return add$1(element, 'class', clazz);
7641    };
7642    var remove$3 = function (element, clazz) {
7643      return remove$2(element, 'class', clazz);
7644    };
7645    var toggle = function (element, clazz) {
7646      if (contains(get$3(element), clazz)) {
7647        return remove$3(element, clazz);
7648      } else {
7649        return add$2(element, clazz);
7650      }
7651    };
7652
7653    var ClassList = /*#__PURE__*/Object.freeze({
7654        get: get$3,
7655        add: add$2,
7656        remove: remove$3,
7657        toggle: toggle,
7658        supports: supports
7659    });
7660
7661    var add$3 = function (element, clazz) {
7662      if (supports(element)) {
7663        element.dom().classList.add(clazz);
7664      } else {
7665        add$2(element, clazz);
7666      }
7667    };
7668    var cleanClass = function (element) {
7669      var classList = supports(element) ? element.dom().classList : get$3(element);
7670      if (classList.length === 0) {
7671        remove(element, 'class');
7672      }
7673    };
7674    var remove$4 = function (element, clazz) {
7675      if (supports(element)) {
7676        var classList = element.dom().classList;
7677        classList.remove(clazz);
7678      } else {
7679        remove$3(element, clazz);
7680      }
7681      cleanClass(element);
7682    };
7683    var has$2 = function (element, clazz) {
7684      return supports(element) && element.dom().classList.contains(clazz);
7685    };
7686
7687    var ancestors = function (scope, predicate, isRoot) {
7688      return filter(parents(scope, isRoot), predicate);
7689    };
7690    var siblings$1 = function (scope, predicate) {
7691      return filter(siblings(scope), predicate);
7692    };
7693    var children$1 = function (scope, predicate) {
7694      return filter(children(scope), predicate);
7695    };
7696    var descendants = function (scope, predicate) {
7697      var result = [];
7698      each(children(scope), function (x) {
7699        if (predicate(x)) {
7700          result = result.concat([x]);
7701        }
7702        result = result.concat(descendants(x, predicate));
7703      });
7704      return result;
7705    };
7706
7707    var all$1 = function (selector) {
7708      return all(selector);
7709    };
7710    var ancestors$1 = function (scope, selector, isRoot) {
7711      return ancestors(scope, function (e) {
7712        return is$1(e, selector);
7713      }, isRoot);
7714    };
7715    var siblings$2 = function (scope, selector) {
7716      return siblings$1(scope, function (e) {
7717        return is$1(e, selector);
7718      });
7719    };
7720    var children$2 = function (scope, selector) {
7721      return children$1(scope, function (e) {
7722        return is$1(e, selector);
7723      });
7724    };
7725    var descendants$1 = function (scope, selector) {
7726      return all(selector, scope);
7727    };
7728
7729    var SelectorFilter = /*#__PURE__*/Object.freeze({
7730        all: all$1,
7731        ancestors: ancestors$1,
7732        siblings: siblings$2,
7733        children: children$2,
7734        descendants: descendants$1
7735    });
7736
7737    function ClosestOrAncestor (is, ancestor, scope, a, isRoot) {
7738      return is(scope, a) ? Option.some(scope) : isFunction(isRoot) && isRoot(scope) ? Option.none() : ancestor(scope, a, isRoot);
7739    }
7740
7741    var ancestor = function (scope, predicate, isRoot) {
7742      var element = scope.dom();
7743      var stop = isFunction(isRoot) ? isRoot : constant(false);
7744      while (element.parentNode) {
7745        element = element.parentNode;
7746        var el = Element.fromDom(element);
7747        if (predicate(el)) {
7748          return Option.some(el);
7749        } else if (stop(el)) {
7750          break;
7751        }
7752      }
7753      return Option.none();
7754    };
7755    var closest = function (scope, predicate, isRoot) {
7756      var is = function (s) {
7757        return predicate(s);
7758      };
7759      return ClosestOrAncestor(is, ancestor, scope, predicate, isRoot);
7760    };
7761
7762    var ancestor$1 = function (scope, selector, isRoot) {
7763      return ancestor(scope, function (e) {
7764        return is$1(e, selector);
7765      }, isRoot);
7766    };
7767    var descendant = function (scope, selector) {
7768      return one(selector, scope);
7769    };
7770    var closest$1 = function (scope, selector, isRoot) {
7771      return ClosestOrAncestor(is$1, ancestor$1, scope, selector, isRoot);
7772    };
7773
7774    var annotation = constant('mce-annotation');
7775    var dataAnnotation = constant('data-mce-annotation');
7776    var dataAnnotationId = constant('data-mce-annotation-uid');
7777
7778    var identify = function (editor, annotationName) {
7779      var rng = editor.selection.getRng();
7780      var start = Element.fromDom(rng.startContainer);
7781      var root = Element.fromDom(editor.getBody());
7782      var selector = annotationName.fold(function () {
7783        return '.' + annotation();
7784      }, function (an) {
7785        return '[' + dataAnnotation() + '="' + an + '"]';
7786      });
7787      var newStart = child(start, rng.startOffset).getOr(start);
7788      var closest = closest$1(newStart, selector, function (n) {
7789        return eq(n, root);
7790      });
7791      var getAttr = function (c, property) {
7792        if (has$1(c, property)) {
7793          return Option.some(get$1(c, property));
7794        } else {
7795          return Option.none();
7796        }
7797      };
7798      return closest.bind(function (c) {
7799        return getAttr(c, '' + dataAnnotationId()).bind(function (uid) {
7800          return getAttr(c, '' + dataAnnotation()).map(function (name) {
7801            var elements = findMarkers(editor, uid);
7802            return {
7803              uid: uid,
7804              name: name,
7805              elements: elements
7806            };
7807          });
7808        });
7809      });
7810    };
7811    var isAnnotation = function (elem) {
7812      return isElement(elem) && has$2(elem, annotation());
7813    };
7814    var findMarkers = function (editor, uid) {
7815      var body = Element.fromDom(editor.getBody());
7816      return descendants$1(body, '[' + dataAnnotationId() + '="' + uid + '"]');
7817    };
7818    var findAll = function (editor, name) {
7819      var body = Element.fromDom(editor.getBody());
7820      var markers = descendants$1(body, '[' + dataAnnotation() + '="' + name + '"]');
7821      var directory = {};
7822      each(markers, function (m) {
7823        var uid = get$1(m, dataAnnotationId());
7824        var nodesAlready = directory.hasOwnProperty(uid) ? directory[uid] : [];
7825        directory[uid] = nodesAlready.concat([m]);
7826      });
7827      return directory;
7828    };
7829
7830    var setup = function (editor, registry) {
7831      var changeCallbacks = Cell({});
7832      var initData = function () {
7833        return {
7834          listeners: [],
7835          previous: Cell(Option.none())
7836        };
7837      };
7838      var withCallbacks = function (name, f) {
7839        updateCallbacks(name, function (data) {
7840          f(data);
7841          return data;
7842        });
7843      };
7844      var updateCallbacks = function (name, f) {
7845        var callbackMap = changeCallbacks.get();
7846        var data = callbackMap.hasOwnProperty(name) ? callbackMap[name] : initData();
7847        var outputData = f(data);
7848        callbackMap[name] = outputData;
7849        changeCallbacks.set(callbackMap);
7850      };
7851      var fireCallbacks = function (name, uid, elements) {
7852        withCallbacks(name, function (data) {
7853          each(data.listeners, function (f) {
7854            return f(true, name, {
7855              uid: uid,
7856              nodes: map(elements, function (elem) {
7857                return elem.dom();
7858              })
7859            });
7860          });
7861        });
7862      };
7863      var fireNoAnnotation = function (name) {
7864        withCallbacks(name, function (data) {
7865          each(data.listeners, function (f) {
7866            return f(false, name);
7867          });
7868        });
7869      };
7870      var onNodeChange = last$2(function () {
7871        var callbackMap = changeCallbacks.get();
7872        var annotations = sort(keys(callbackMap));
7873        each(annotations, function (name) {
7874          updateCallbacks(name, function (data) {
7875            var prev = data.previous.get();
7876            identify(editor, Option.some(name)).fold(function () {
7877              if (prev.isSome()) {
7878                fireNoAnnotation(name);
7879                data.previous.set(Option.none());
7880              }
7881            }, function (_a) {
7882              var uid = _a.uid, name = _a.name, elements = _a.elements;
7883              if (!prev.is(uid)) {
7884                fireCallbacks(name, uid, elements);
7885                data.previous.set(Option.some(uid));
7886              }
7887            });
7888            return {
7889              previous: data.previous,
7890              listeners: data.listeners
7891            };
7892          });
7893        });
7894      }, 30);
7895      editor.on('remove', function () {
7896        onNodeChange.cancel();
7897      });
7898      editor.on('NodeChange', function () {
7899        onNodeChange.throttle();
7900      });
7901      var addListener = function (name, f) {
7902        updateCallbacks(name, function (data) {
7903          return {
7904            previous: data.previous,
7905            listeners: data.listeners.concat([f])
7906          };
7907        });
7908      };
7909      return { addListener: addListener };
7910    };
7911
7912    var setup$1 = function (editor, registry) {
7913      var identifyParserNode = function (span) {
7914        return Option.from(span.attr(dataAnnotation())).bind(registry.lookup);
7915      };
7916      editor.on('init', function () {
7917        editor.serializer.addNodeFilter('span', function (spans) {
7918          each(spans, function (span) {
7919            identifyParserNode(span).each(function (settings) {
7920              if (settings.persistent === false) {
7921                span.unwrap();
7922              }
7923            });
7924          });
7925        });
7926      });
7927    };
7928
7929    var create$1 = function () {
7930      var annotations = {};
7931      var register = function (name, settings) {
7932        annotations[name] = {
7933          name: name,
7934          settings: settings
7935        };
7936      };
7937      var lookup = function (name) {
7938        return annotations.hasOwnProperty(name) ? Option.from(annotations[name]).map(function (a) {
7939          return a.settings;
7940        }) : Option.none();
7941      };
7942      return {
7943        register: register,
7944        lookup: lookup
7945      };
7946    };
7947
7948    var unique = 0;
7949    var generate = function (prefix) {
7950      var date = new Date();
7951      var time = date.getTime();
7952      var random = Math.floor(Math.random() * 1000000000);
7953      unique++;
7954      return prefix + '_' + random + unique + String(time);
7955    };
7956
7957    var add$4 = function (element, classes) {
7958      each(classes, function (x) {
7959        add$3(element, x);
7960      });
7961    };
7962
7963    var clone = function (original, isDeep) {
7964      return Element.fromDom(original.dom().cloneNode(isDeep));
7965    };
7966    var shallow = function (original) {
7967      return clone(original, false);
7968    };
7969    var deep = function (original) {
7970      return clone(original, true);
7971    };
7972
7973    var fromHtml$1 = function (html, scope) {
7974      var doc = scope || domGlobals.document;
7975      var div = doc.createElement('div');
7976      div.innerHTML = html;
7977      return children(Element.fromDom(div));
7978    };
7979
7980    var get$4 = function (element) {
7981      return element.dom().innerHTML;
7982    };
7983    var set$1 = function (element, content) {
7984      var owner$1 = owner(element);
7985      var docDom = owner$1.dom();
7986      var fragment = Element.fromDom(docDom.createDocumentFragment());
7987      var contentElements = fromHtml$1(content, docDom);
7988      append$1(fragment, contentElements);
7989      empty(element);
7990      append(element, fragment);
7991    };
7992
7993    var ZWSP = '\uFEFF';
7994    var isZwsp = function (chr) {
7995      return chr === ZWSP;
7996    };
7997    var trim$3 = function (text) {
7998      return text.replace(new RegExp(ZWSP, 'g'), '');
7999    };
8000    var Zwsp = {
8001      isZwsp: isZwsp,
8002      ZWSP: ZWSP,
8003      trim: trim$3
8004    };
8005
8006    var isElement$2 = NodeType.isElement;
8007    var isText$2 = NodeType.isText;
8008    var isCaretContainerBlock = function (node) {
8009      if (isText$2(node)) {
8010        node = node.parentNode;
8011      }
8012      return isElement$2(node) && node.hasAttribute('data-mce-caret');
8013    };
8014    var isCaretContainerInline = function (node) {
8015      return isText$2(node) && Zwsp.isZwsp(node.data);
8016    };
8017    var isCaretContainer = function (node) {
8018      return isCaretContainerBlock(node) || isCaretContainerInline(node);
8019    };
8020    var hasContent = function (node) {
8021      return node.firstChild !== node.lastChild || !NodeType.isBr(node.firstChild);
8022    };
8023    var insertInline = function (node, before) {
8024      var doc, sibling, textNode, parentNode;
8025      doc = node.ownerDocument;
8026      textNode = doc.createTextNode(Zwsp.ZWSP);
8027      parentNode = node.parentNode;
8028      if (!before) {
8029        sibling = node.nextSibling;
8030        if (isText$2(sibling)) {
8031          if (isCaretContainer(sibling)) {
8032            return sibling;
8033          }
8034          if (startsWithCaretContainer(sibling)) {
8035            sibling.splitText(1);
8036            return sibling;
8037          }
8038        }
8039        if (node.nextSibling) {
8040          parentNode.insertBefore(textNode, node.nextSibling);
8041        } else {
8042          parentNode.appendChild(textNode);
8043        }
8044      } else {
8045        sibling = node.previousSibling;
8046        if (isText$2(sibling)) {
8047          if (isCaretContainer(sibling)) {
8048            return sibling;
8049          }
8050          if (endsWithCaretContainer(sibling)) {
8051            return sibling.splitText(sibling.data.length - 1);
8052          }
8053        }
8054        parentNode.insertBefore(textNode, node);
8055      }
8056      return textNode;
8057    };
8058    var prependInline = function (node) {
8059      if (NodeType.isText(node)) {
8060        var data = node.data;
8061        if (data.length > 0 && data.charAt(0) !== Zwsp.ZWSP) {
8062          node.insertData(0, Zwsp.ZWSP);
8063        }
8064        return node;
8065      } else {
8066        return null;
8067      }
8068    };
8069    var appendInline = function (node) {
8070      if (NodeType.isText(node)) {
8071        var data = node.data;
8072        if (data.length > 0 && data.charAt(data.length - 1) !== Zwsp.ZWSP) {
8073          node.insertData(data.length, Zwsp.ZWSP);
8074        }
8075        return node;
8076      } else {
8077        return null;
8078      }
8079    };
8080    var isBeforeInline = function (pos) {
8081      var container = pos.container();
8082      if (!pos || !NodeType.isText(container)) {
8083        return false;
8084      }
8085      return container.data.charAt(pos.offset()) === Zwsp.ZWSP || pos.isAtStart() && isCaretContainerInline(container.previousSibling);
8086    };
8087    var isAfterInline = function (pos) {
8088      var container = pos.container();
8089      if (!pos || !NodeType.isText(container)) {
8090        return false;
8091      }
8092      return container.data.charAt(pos.offset() - 1) === Zwsp.ZWSP || pos.isAtEnd() && isCaretContainerInline(container.nextSibling);
8093    };
8094    var createBogusBr = function () {
8095      var br = domGlobals.document.createElement('br');
8096      br.setAttribute('data-mce-bogus', '1');
8097      return br;
8098    };
8099    var insertBlock = function (blockName, node, before) {
8100      var doc, blockNode, parentNode;
8101      doc = node.ownerDocument;
8102      blockNode = doc.createElement(blockName);
8103      blockNode.setAttribute('data-mce-caret', before ? 'before' : 'after');
8104      blockNode.setAttribute('data-mce-bogus', 'all');
8105      blockNode.appendChild(createBogusBr());
8106      parentNode = node.parentNode;
8107      if (!before) {
8108        if (node.nextSibling) {
8109          parentNode.insertBefore(blockNode, node.nextSibling);
8110        } else {
8111          parentNode.appendChild(blockNode);
8112        }
8113      } else {
8114        parentNode.insertBefore(blockNode, node);
8115      }
8116      return blockNode;
8117    };
8118    var startsWithCaretContainer = function (node) {
8119      return isText$2(node) && node.data[0] === Zwsp.ZWSP;
8120    };
8121    var endsWithCaretContainer = function (node) {
8122      return isText$2(node) && node.data[node.data.length - 1] === Zwsp.ZWSP;
8123    };
8124    var trimBogusBr = function (elm) {
8125      var brs = elm.getElementsByTagName('br');
8126      var lastBr = brs[brs.length - 1];
8127      if (NodeType.isBogus(lastBr)) {
8128        lastBr.parentNode.removeChild(lastBr);
8129      }
8130    };
8131    var showCaretContainerBlock = function (caretContainer) {
8132      if (caretContainer && caretContainer.hasAttribute('data-mce-caret')) {
8133        trimBogusBr(caretContainer);
8134        caretContainer.removeAttribute('data-mce-caret');
8135        caretContainer.removeAttribute('data-mce-bogus');
8136        caretContainer.removeAttribute('style');
8137        caretContainer.removeAttribute('_moz_abspos');
8138        return caretContainer;
8139      }
8140      return null;
8141    };
8142    var isRangeInCaretContainerBlock = function (range) {
8143      return isCaretContainerBlock(range.startContainer);
8144    };
8145
8146    var CaretContainer = /*#__PURE__*/Object.freeze({
8147        isCaretContainer: isCaretContainer,
8148        isCaretContainerBlock: isCaretContainerBlock,
8149        isCaretContainerInline: isCaretContainerInline,
8150        showCaretContainerBlock: showCaretContainerBlock,
8151        insertInline: insertInline,
8152        prependInline: prependInline,
8153        appendInline: appendInline,
8154        isBeforeInline: isBeforeInline,
8155        isAfterInline: isAfterInline,
8156        insertBlock: insertBlock,
8157        hasContent: hasContent,
8158        startsWithCaretContainer: startsWithCaretContainer,
8159        endsWithCaretContainer: endsWithCaretContainer,
8160        isRangeInCaretContainerBlock: isRangeInCaretContainerBlock
8161    });
8162
8163    var isContentEditableTrue$1 = NodeType.isContentEditableTrue;
8164    var isContentEditableFalse$1 = NodeType.isContentEditableFalse;
8165    var isBr$2 = NodeType.isBr;
8166    var isText$3 = NodeType.isText;
8167    var isInvalidTextElement = NodeType.matchNodeNames('script style textarea');
8168    var isAtomicInline = NodeType.matchNodeNames('img input textarea hr iframe video audio object');
8169    var isTable$2 = NodeType.matchNodeNames('table');
8170    var isCaretContainer$1 = isCaretContainer;
8171    var isCaretCandidate = function (node) {
8172      if (isCaretContainer$1(node)) {
8173        return false;
8174      }
8175      if (isText$3(node)) {
8176        if (isInvalidTextElement(node.parentNode)) {
8177          return false;
8178        }
8179        return true;
8180      }
8181      return isAtomicInline(node) || isBr$2(node) || isTable$2(node) || isNonUiContentEditableFalse(node);
8182    };
8183    var isUnselectable = function (node) {
8184      return NodeType.isElement(node) && node.getAttribute('unselectable') === 'true';
8185    };
8186    var isNonUiContentEditableFalse = function (node) {
8187      return isUnselectable(node) === false && isContentEditableFalse$1(node);
8188    };
8189    var isInEditable = function (node, root) {
8190      for (node = node.parentNode; node && node !== root; node = node.parentNode) {
8191        if (isNonUiContentEditableFalse(node)) {
8192          return false;
8193        }
8194        if (isContentEditableTrue$1(node)) {
8195          return true;
8196        }
8197      }
8198      return true;
8199    };
8200    var isAtomicContentEditableFalse = function (node) {
8201      if (!isNonUiContentEditableFalse(node)) {
8202        return false;
8203      }
8204      return foldl(from$1(node.getElementsByTagName('*')), function (result, elm) {
8205        return result || isContentEditableTrue$1(elm);
8206      }, false) !== true;
8207    };
8208    var isAtomic = function (node) {
8209      return isAtomicInline(node) || isAtomicContentEditableFalse(node);
8210    };
8211    var isEditableCaretCandidate = function (node, root) {
8212      return isCaretCandidate(node) && isInEditable(node, root);
8213    };
8214
8215    var round = Math.round;
8216    var clone$1 = function (rect) {
8217      if (!rect) {
8218        return {
8219          left: 0,
8220          top: 0,
8221          bottom: 0,
8222          right: 0,
8223          width: 0,
8224          height: 0
8225        };
8226      }
8227      return {
8228        left: round(rect.left),
8229        top: round(rect.top),
8230        bottom: round(rect.bottom),
8231        right: round(rect.right),
8232        width: round(rect.width),
8233        height: round(rect.height)
8234      };
8235    };
8236    var collapse = function (rect, toStart) {
8237      rect = clone$1(rect);
8238      if (toStart) {
8239        rect.right = rect.left;
8240      } else {
8241        rect.left = rect.left + rect.width;
8242        rect.right = rect.left;
8243      }
8244      rect.width = 0;
8245      return rect;
8246    };
8247    var isEqual = function (rect1, rect2) {
8248      return rect1.left === rect2.left && rect1.top === rect2.top && rect1.bottom === rect2.bottom && rect1.right === rect2.right;
8249    };
8250    var isValidOverflow = function (overflowY, rect1, rect2) {
8251      return overflowY >= 0 && overflowY <= Math.min(rect1.height, rect2.height) / 2;
8252    };
8253    var isAbove = function (rect1, rect2) {
8254      if (rect1.bottom - rect1.height / 2 < rect2.top) {
8255        return true;
8256      }
8257      if (rect1.top > rect2.bottom) {
8258        return false;
8259      }
8260      return isValidOverflow(rect2.top - rect1.bottom, rect1, rect2);
8261    };
8262    var isBelow = function (rect1, rect2) {
8263      if (rect1.top > rect2.bottom) {
8264        return true;
8265      }
8266      if (rect1.bottom < rect2.top) {
8267        return false;
8268      }
8269      return isValidOverflow(rect2.bottom - rect1.top, rect1, rect2);
8270    };
8271    var containsXY = function (rect, clientX, clientY) {
8272      return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
8273    };
8274    var overflowX = function (outer, inner) {
8275      if (inner.left > outer.left && inner.right < outer.right) {
8276        return 0;
8277      } else {
8278        return inner.left < outer.left ? inner.left - outer.left : inner.right - outer.right;
8279      }
8280    };
8281    var overflowY = function (outer, inner) {
8282      if (inner.top > outer.top && inner.bottom < outer.bottom) {
8283        return 0;
8284      } else {
8285        return inner.top < outer.top ? inner.top - outer.top : inner.bottom - outer.bottom;
8286      }
8287    };
8288    var getOverflow = function (outer, inner) {
8289      return {
8290        x: overflowX(outer, inner),
8291        y: overflowY(outer, inner)
8292      };
8293    };
8294
8295    var getSelectedNode = function (range) {
8296      var startContainer = range.startContainer, startOffset = range.startOffset;
8297      if (startContainer.hasChildNodes() && range.endOffset === startOffset + 1) {
8298        return startContainer.childNodes[startOffset];
8299      }
8300      return null;
8301    };
8302    var getNode = function (container, offset) {
8303      if (container.nodeType === 1 && container.hasChildNodes()) {
8304        if (offset >= container.childNodes.length) {
8305          offset = container.childNodes.length - 1;
8306        }
8307        container = container.childNodes[offset];
8308      }
8309      return container;
8310    };
8311
8312    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
8312-\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]');
8313    var isExtendingChar = function (ch) {
8314      return typeof ch === 'string' && ch.charCodeAt(0) >= 768 && extendingChars.test(ch);
8315    };
8316
8317    var liftN = function (arr, f) {
8318      var r = [];
8319      for (var i = 0; i < arr.length; i++) {
8320        var x = arr[i];
8321        if (x.isSome()) {
8322          r.push(x.getOrDie());
8323        } else {
8324          return Option.none();
8325        }
8326      }
8327      return Option.some(f.apply(null, r));
8328    };
8329
8330    var slice$3 = [].slice;
8331    var or = function () {
8332      var x = [];
8333      for (var _i = 0; _i < arguments.length; _i++) {
8334        x[_i] = arguments[_i];
8335      }
8336      var args = slice$3.call(arguments);
8337      return function (x) {
8338        for (var i = 0; i < args.length; i++) {
8339          if (args[i](x)) {
8340            return true;
8341          }
8342        }
8343        return false;
8344      };
8345    };
8346    var and = function () {
8347      var x = [];
8348      for (var _i = 0; _i < arguments.length; _i++) {
8349        x[_i] = arguments[_i];
8350      }
8351      var args = slice$3.call(arguments);
8352      return function (x) {
8353        for (var i = 0; i < args.length; i++) {
8354          if (!args[i](x)) {
8355            return false;
8356          }
8357        }
8358        return true;
8359      };
8360    };
8361    var Predicate = {
8362      and: and,
8363      or: or
8364    };
8365
8366    var isElement$3 = NodeType.isElement;
8367    var isCaretCandidate$1 = isCaretCandidate;
8368    var isBlock$1 = NodeType.matchStyleValues('display', 'block table');
8369    var isFloated = NodeType.matchStyleValues('float', 'left right');
8370    var isValidElementCaretCandidate = Predicate.and(isElement$3, isCaretCandidate$1, not(isFloated));
8371    var isNotPre = not(NodeType.matchStyleValues('white-space', 'pre pre-line pre-wrap'));
8372    var isText$4 = NodeType.isText;
8373    var isBr$3 = NodeType.isBr;
8374    var nodeIndex = DOMUtils$1.nodeIndex;
8375    var resolveIndex = getNode;
8376    var createRange = function (doc) {
8377      return 'createRange' in doc ? doc.createRange() : DOMUtils$1.DOM.createRng();
8378    };
8379    var isWhiteSpace = function (chr) {
8380      return chr && /[\r\n\t ]/.test(chr);
8381    };
8382    var isRange = function (rng) {
8383      return !!rng.setStart && !!rng.setEnd;
8384    };
8385    var isHiddenWhiteSpaceRange = function (range) {
8386      var container = range.startContainer;
8387      var offset = range.startOffset;
8388      var text;
8389      if (isWhiteSpace(range.toString()) && isNotPre(container.parentNode) && NodeType.isText(container)) {
8390        text = container.data;
8391        if (isWhiteSpace(text[offset - 1]) || isWhiteSpace(text[offset + 1])) {
8392          return true;
8393        }
8394      }
8395      return false;
8396    };
8397    var getBrClientRect = function (brNode) {
8398      var doc = brNode.ownerDocument;
8399      var rng = createRange(doc);
8400      var nbsp = doc.createTextNode('\xA0');
8401      var parentNode = brNode.parentNode;
8402      var clientRect;
8403      parentNode.insertBefore(nbsp, brNode);
8404      rng.setStart(nbsp, 0);
8405      rng.setEnd(nbsp, 1);
8406      clientRect = clone$1(rng.getBoundingClientRect());
8407      parentNode.removeChild(nbsp);
8408      return clientRect;
8409    };
8410    var getBoundingClientRectWebKitText = function (rng) {
8411      var sc = rng.startContainer;
8412      var ec = rng.endContainer;
8413      var so = rng.startOffset;
8414      var eo = rng.endOffset;
8415      if (sc === ec && NodeType.isText(ec) && so === 0 && eo === 1) {
8416        var newRng = rng.cloneRange();
8417        newRng.setEndAfter(ec);
8418        return getBoundingClientRect(newRng);
8419      } else {
8420        return null;
8421      }
8422    };
8423    var isZeroRect = function (r) {
8424      return r.left === 0 && r.right === 0 && r.top === 0 && r.bottom === 0;
8425    };
8426    var getBoundingClientRect = function (item) {
8427      var clientRect, clientRects;
8428      clientRects = item.getClientRects();
8429      if (clientRects.length > 0) {
8430        clientRect = clone$1(clientRects[0]);
8431      } else {
8432        clientRect = clone$1(item.getBoundingClientRect());
8433      }
8434      if (!isRange(item) && isBr$3(item) && isZeroRect(clientRect)) {
8435        return getBrClientRect(item);
8436      }
8437      if (isZeroRect(clientRect) && isRange(item)) {
8438        return getBoundingClientRectWebKitText(item);
8439      }
8440      return clientRect;
8441    };
8442    var collapseAndInflateWidth = function (clientRect, toStart) {
8443      var newClientRect = collapse(clientRect, toStart);
8444      newClientRect.width = 1;
8445      newClientRect.right = newClientRect.left + 1;
8446      return newClientRect;
8447    };
8448    var getCaretPositionClientRects = function (caretPosition) {
8449      var clientRects = [];
8450      var beforeNode, node;
8451      var addUniqueAndValidRect = function (clientRect) {
8452        if (clientRect.height === 0) {
8453          return;
8454        }
8455        if (clientRects.length > 0) {
8456          if (isEqual(clientRect, clientRects[clientRects.length - 1])) {
8457            return;
8458          }
8459        }
8460        clientRects.push(clientRect);
8461      };
8462      var addCharacterOffset = function (container, offset) {
8463        var range = createRange(container.ownerDocument);
8464        if (offset < container.data.length) {
8465          if (isExtendingChar(container.data[offset])) {
8466            return clientRects;
8467          }
8468          if (isExtendingChar(container.data[offset - 1])) {
8469            range.setStart(container, offset);
8470            range.setEnd(container, offset + 1);
8471            if (!isHiddenWhiteSpaceRange(range)) {
8472              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false));
8473              return clientRects;
8474            }
8475          }
8476        }
8477        if (offset > 0) {
8478          range.setStart(container, offset - 1);
8479          range.setEnd(container, offset);
8480          if (!isHiddenWhiteSpaceRange(range)) {
8481            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false));
8482          }
8483        }
8484        if (offset < container.data.length) {
8485          range.setStart(container, offset);
8486          range.setEnd(container, offset + 1);
8487          if (!isHiddenWhiteSpaceRange(range)) {
8488            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), true));
8489          }
8490        }
8491      };
8492      if (isText$4(caretPosition.container())) {
8493        addCharacterOffset(caretPosition.container(), caretPosition.offset());
8494        return clientRects;
8495      }
8496      if (isElement$3(caretPosition.container())) {
8497        if (caretPosition.isAtEnd()) {
8498          node = resolveIndex(caretPosition.container(), caretPosition.offset());
8499          if (isText$4(node)) {
8500            addCharacterOffset(node, node.data.length);
8501          }
8502          if (isValidElementCaretCandidate(node) && !isBr$3(node)) {
8503            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false));
8504          }
8505        } else {
8506          node = resolveIndex(caretPosition.container(), caretPosition.offset());
8507          if (isText$4(node)) {
8508            addCharacterOffset(node, 0);
8509          }
8510          if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) {
8511            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false));
8512            return clientRects;
8513          }
8514          beforeNode = resolveIndex(caretPosition.container(), caretPosition.offset() - 1);
8515          if (isValidElementCaretCandidate(beforeNode) && !isBr$3(beforeNode)) {
8516            if (isBlock$1(beforeNode) || isBlock$1(node) || !isValidElementCaretCandidate(node)) {
8517              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(beforeNode), false));
8518            }
8519          }
8520          if (isValidElementCaretCandidate(node)) {
8521            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), true));
8522          }
8523        }
8524      }
8525      return clientRects;
8526    };
8527    function CaretPosition(container, offset, clientRects) {
8528      var isAtStart = function () {
8529        if (isText$4(container)) {
8530          return offset === 0;
8531        }
8532        return offset === 0;
8533      };
8534      var isAtEnd = function () {
8535        if (isText$4(container)) {
8536          return offset >= container.data.length;
8537        }
8538        return offset >= container.childNodes.length;
8539      };
8540      var toRange = function () {
8541        var range;
8542        range = createRange(container.ownerDocument);
8543        range.setStart(container, offset);
8544        range.setEnd(container, offset);
8545        return range;
8546      };
8547      var getClientRects = function () {
8548        if (!clientRects) {
8549          clientRects = getCaretPositionClientRects(CaretPosition(container, offset));
8550        }
8551        return clientRects;
8552      };
8553      var isVisible = function () {
8554        return getClientRects().length > 0;
8555      };
8556      var isEqual = function (caretPosition) {
8557        return caretPosition && container === caretPosition.container() && offset === caretPosition.offset();
8558      };
8559      var getNode = function (before) {
8560        return resolveIndex(container, before ? offset - 1 : offset);
8561      };
8562      return {
8563        container: constant(container),
8564        offset: constant(offset),
8565        toRange: toRange,
8566        getClientRects: getClientRects,
8567        isVisible: isVisible,
8568        isAtStart: isAtStart,
8569        isAtEnd: isAtEnd,
8570        isEqual: isEqual,
8571        getNode: getNode
8572      };
8573    }
8574    (function (CaretPosition) {
8575      CaretPosition.fromRangeStart = function (range) {
8576        return CaretPosition(range.startContainer, range.startOffset);
8577      };
8578      CaretPosition.fromRangeEnd = function (range) {
8579        return CaretPosition(range.endContainer, range.endOffset);
8580      };
8581      CaretPosition.after = function (node) {
8582        return CaretPosition(node.parentNode, nodeIndex(node) + 1);
8583      };
8584      CaretPosition.before = function (node) {
8585        return CaretPosition(node.parentNode, nodeIndex(node));
8586      };
8587      CaretPosition.isAbove = function (pos1, pos2) {
8588        return liftN([
8589          head(pos2.getClientRects()),
8590          last(pos1.getClientRects())
8591        ], isAbove).getOr(false);
8592      };
8593      CaretPosition.isBelow = function (pos1, pos2) {
8594        return liftN([
8595          last(pos2.getClientRects()),
8596          head(pos1.getClientRects())
8597        ], isBelow).getOr(false);
8598      };
8599      CaretPosition.isAtStart = function (pos) {
8600        return pos ? pos.isAtStart() : false;
8601      };
8602      CaretPosition.isAtEnd = function (pos) {
8603        return pos ? pos.isAtEnd() : false;
8604      };
8605      CaretPosition.isTextPosition = function (pos) {
8606        return pos ? NodeType.isText(pos.container()) : false;
8607      };
8608      CaretPosition.isElementPosition = function (pos) {
8609        return CaretPosition.isTextPosition(pos) === false;
8610      };
8611    }(CaretPosition || (CaretPosition = {})));
8612    var CaretPosition$1 = CaretPosition;
8613
8614    var isText$5 = NodeType.isText;
8615    var isBogus$1 = NodeType.isBogus;
8616    var nodeIndex$1 = DOMUtils$1.nodeIndex;
8617    var normalizedParent = function (node) {
8618      var parentNode = node.parentNode;
8619      if (isBogus$1(parentNode)) {
8620        return normalizedParent(parentNode);
8621      }
8622      return parentNode;
8623    };
8624    var getChildNodes = function (node) {
8625      if (!node) {
8626        return [];
8627      }
8628      return ArrUtils.reduce(node.childNodes, function (result, node) {
8629        if (isBogus$1(node) && node.nodeName !== 'BR') {
8630          result = result.concat(getChildNodes(node));
8631        } else {
8632          result.push(node);
8633        }
8634        return result;
8635      }, []);
8636    };
8637    var normalizedTextOffset = function (node, offset) {
8638      while (node = node.previousSibling) {
8639        if (!isText$5(node)) {
8640          break;
8641        }
8642        offset += node.data.length;
8643      }
8644      return offset;
8645    };
8646    var equal$1 = function (a) {
8647      return function (b) {
8648        return a === b;
8649      };
8650    };
8651    var normalizedNodeIndex = function (node) {
8652      var nodes, index, numTextFragments;
8653      nodes = getChildNodes(normalizedParent(node));
8654      index = ArrUtils.findIndex(nodes, equal$1(node), node);
8655      nodes = nodes.slice(0, index + 1);
8656      numTextFragments = ArrUtils.reduce(nodes, function (result, node, i) {
8657        if (isText$5(node) && isText$5(nodes[i - 1])) {
8658          result++;
8659        }
8660        return result;
8661      }, 0);
8662      nodes = ArrUtils.filter(nodes, NodeType.matchNodeNames(node.nodeName));
8663      index = ArrUtils.findIndex(nodes, equal$1(node), node);
8664      return index - numTextFragments;
8665    };
8666    var createPathItem = function (node) {
8667      var name;
8668      if (isText$5(node)) {
8669        name = 'text()';
8670      } else {
8671        name = node.nodeName.toLowerCase();
8672      }
8673      return name + '[' + normalizedNodeIndex(node) + ']';
8674    };
8675    var parentsUntil = function (root, node, predicate) {
8676      var parents = [];
8677      for (node = node.parentNode; node !== root; node = node.parentNode) {
8678        if (predicate && predicate(node)) {
8679          break;
8680        }
8681        parents.push(node);
8682      }
8683      return parents;
8684    };
8685    var create$2 = function (root, caretPosition) {
8686      var container, offset, path = [], outputOffset, childNodes, parents;
8687      container = caretPosition.container();
8688      offset = caretPosition.offset();
8689      if (isText$5(container)) {
8690        outputOffset = normalizedTextOffset(container, offset);
8691      } else {
8692        childNodes = container.childNodes;
8693        if (offset >= childNodes.length) {
8694          outputOffset = 'after';
8695          offset = childNodes.length - 1;
8696        } else {
8697          outputOffset = 'before';
8698        }
8699        container = childNodes[offset];
8700      }
8701      path.push(createPathItem(container));
8702      parents = parentsUntil(root, container);
8703      parents = ArrUtils.filter(parents, not(NodeType.isBogus));
8704      path = path.concat(ArrUtils.map(parents, function (node) {
8705        return createPathItem(node);
8706      }));
8707      return path.reverse().join('/') + ',' + outputOffset;
8708    };
8709    var resolvePathItem = function (node, name, index) {
8710      var nodes = getChildNodes(node);
8711      nodes = ArrUtils.filter(nodes, function (node, index) {
8712        return !isText$5(node) || !isText$5(nodes[index - 1]);
8713      });
8714      nodes = ArrUtils.filter(nodes, NodeType.matchNodeNames(name));
8715      return nodes[index];
8716    };
8717    var findTextPosition = function (container, offset) {
8718      var node = container, targetOffset = 0, dataLen;
8719      while (isText$5(node)) {
8720        dataLen = node.data.length;
8721        if (offset >= targetOffset && offset <= targetOffset + dataLen) {
8722          container = node;
8723          offset = offset - targetOffset;
8724          break;
8725        }
8726        if (!isText$5(node.nextSibling)) {
8727          container = node;
8728          offset = dataLen;
8729          break;
8730        }
8731        targetOffset += dataLen;
8732        node = node.nextSibling;
8733      }
8734      if (isText$5(container) && offset > container.data.length) {
8735        offset = container.data.length;
8736      }
8737      return CaretPosition$1(container, offset);
8738    };
8739    var resolve$2 = function (root, path) {
8740      var parts, container, offset;
8741      if (!path) {
8742        return null;
8743      }
8744      parts = path.split(',');
8745      path = parts[0].split('/');
8746      offset = parts.length > 1 ? parts[1] : 'before';
8747      container = ArrUtils.reduce(path, function (result, value) {
8748        value = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value);
8749        if (!value) {
8750          return null;
8751        }
8752        if (value[1] === 'text()') {
8753          value[1] = '#text';
8754        }
8755        return resolvePathItem(result, value[1], parseInt(value[2], 10));
8756      }, root);
8757      if (!container) {
8758        return null;
8759      }
8760      if (!isText$5(container)) {
8761        if (offset === 'after') {
8762          offset = nodeIndex$1(container) + 1;
8763        } else {
8764          offset = nodeIndex$1(container);
8765        }
8766        return CaretPosition$1(container.parentNode, offset);
8767      }
8768      return findTextPosition(container, parseInt(offset, 10));
8769    };
8770
8771    var trimEmptyTextNode = function (dom, node) {
8772      if (NodeType.isText(node) && node.data.length === 0) {
8773        dom.remove(node);
8774      }
8775    };
8776    var insertNode = function (dom, rng, node) {
8777      rng.insertNode(node);
8778      trimEmptyTextNode(dom, node.previousSibling);
8779      trimEmptyTextNode(dom, node.nextSibling);
8780    };
8781    var insertFragment = function (dom, rng, frag) {
8782      var firstChild = Option.from(frag.firstChild);
8783      var lastChild = Option.from(frag.lastChild);
8784      rng.insertNode(frag);
8785      firstChild.each(function (child) {
8786        return trimEmptyTextNode(dom, child.previousSibling);
8787      });
8788      lastChild.each(function (child) {
8789        return trimEmptyTextNode(dom, child.nextSibling);
8790      });
8791    };
8792    var rangeInsertNode = function (dom, rng, node) {
8793      if (NodeType.isDocumentFragment(node)) {
8794        insertFragment(dom, rng, node);
8795      } else {
8796        insertNode(dom, rng, node);
8797      }
8798    };
8799
8800    var isContentEditableFalse$2 = NodeType.isContentEditableFalse;
8801    var getNormalizedTextOffset = function (trim, container, offset) {
8802      var node, trimmedOffset;
8803      trimmedOffset = trim(container.data.slice(0, offset)).length;
8804      for (node = container.previousSibling; node && NodeType.isText(node); node = node.previousSibling) {
8805        trimmedOffset += trim(node.data).length;
8806      }
8807      return trimmedOffset;
8808    };
8809    var getPoint = function (dom, trim, normalized, rng, start) {
8810      var container = rng[start ? 'startContainer' : 'endContainer'];
8811      var offset = rng[start ? 'startOffset' : 'endOffset'];
8812      var point = [];
8813      var childNodes, after = 0;
8814      var root = dom.getRoot();
8815      if (NodeType.isText(container)) {
8816        point.push(normalized ? getNormalizedTextOffset(trim, container, offset) : offset);
8817      } else {
8818        childNodes = container.childNodes;
8819        if (offset >= childNodes.length && childNodes.length) {
8820          after = 1;
8821          offset = Math.max(0, childNodes.length - 1);
8822        }
8823        point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
8824      }
8825      for (; container && container !== root; container = container.parentNode) {
8826        point.push(dom.nodeIndex(container, normalized));
8827      }
8828      return point;
8829    };
8830    var getLocation = function (trim, selection, normalized, rng) {
8831      var dom = selection.dom, bookmark = {};
8832      bookmark.start = getPoint(dom, trim, normalized, rng, true);
8833      if (!selection.isCollapsed()) {
8834        bookmark.end = getPoint(dom, trim, normalized, rng, false);
8835      }
8836      return bookmark;
8837    };
8838    var findIndex$2 = function (dom, name, element) {
8839      var count = 0;
8840      Tools.each(dom.select(name), function (node) {
8841        if (node.getAttribute('data-mce-bogus') === 'all') {
8842          return;
8843        }
8844        if (node === element) {
8845          return false;
8846        }
8847        count++;
8848      });
8849      return count;
8850    };
8851    var moveEndPoint = function (rng, start) {
8852      var container, offset, childNodes;
8853      var prefix = start ? 'start' : 'end';
8854      container = rng[prefix + 'Container'];
8855      offset = rng[prefix + 'Offset'];
8856      if (NodeType.isElement(container) && container.nodeName === 'TR') {
8857        childNodes = container.childNodes;
8858        container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
8859        if (container) {
8860          offset = start ? 0 : container.childNodes.length;
8861          rng['set' + (start ? 'Start' : 'End')](container, offset);
8862        }
8863      }
8864    };
8865    var normalizeTableCellSelection = function (rng) {
8866      moveEndPoint(rng, true);
8867      moveEndPoint(rng, false);
8868      return rng;
8869    };
8870    var findSibling = function (node, offset) {
8871      var sibling;
8872      if (NodeType.isElement(node)) {
8873        node = getNode(node, offset);
8874        if (isContentEditableFalse$2(node)) {
8875          return node;
8876        }
8877      }
8878      if (isCaretContainer(node)) {
8879        if (NodeType.isText(node) && isCaretContainerBlock(node)) {
8880          node = node.parentNode;
8881        }
8882        sibling = node.previousSibling;
8883        if (isContentEditableFalse$2(sibling)) {
8884          return sibling;
8885        }
8886        sibling = node.nextSibling;
8887        if (isContentEditableFalse$2(sibling)) {
8888          return sibling;
8889        }
8890      }
8891    };
8892    var findAdjacentContentEditableFalseElm = function (rng) {
8893      return findSibling(rng.startContainer, rng.startOffset) || findSibling(rng.endContainer, rng.endOffset);
8894    };
8895    var getOffsetBookmark = function (trim, normalized, selection) {
8896      var element = selection.getNode();
8897      var name = element ? element.nodeName : null;
8898      var rng = selection.getRng();
8899      if (isContentEditableFalse$2(element) || name === 'IMG') {
8900        return {
8901          name: name,
8902          index: findIndex$2(selection.dom, name, element)
8903        };
8904      }
8905      var sibling = findAdjacentContentEditableFalseElm(rng);
8906      if (sibling) {
8907        name = sibling.tagName;
8908        return {
8909          name: name,
8910          index: findIndex$2(selection.dom, name, sibling)
8911        };
8912      }
8913      return getLocation(trim, selection, normalized, rng);
8914    };
8915    var getCaretBookmark = function (selection) {
8916      var rng = selection.getRng();
8917      return {
8918        start: create$2(selection.dom.getRoot(), CaretPosition$1.fromRangeStart(rng)),
8919        end: create$2(selection.dom.getRoot(), CaretPosition$1.fromRangeEnd(rng))
8920      };
8921    };
8922    var getRangeBookmark = function (selection) {
8923      return { rng: selection.getRng() };
8924    };
8925    var createBookmarkSpan = function (dom, id, filled) {
8926      var args = {
8927        'data-mce-type': 'bookmark',
8928        'id': id,
8929        'style': 'overflow:hidden;line-height:0px'
8930      };
8931      return filled ? dom.create('span', args, '&#xFEFF;
8931') : dom.create('span', args);
8932    };
8933    var getPersistentBookmark = function (selection, filled) {
8934      var dom = selection.dom;
8935      var rng = selection.getRng();
8936      var id = dom.uniqueId();
8937      var collapsed = selection.isCollapsed();
8938      var element = selection.getNode();
8939      var name = element.nodeName;
8940      if (name === 'IMG') {
8941        return {
8942          name: name,
8943          index: findIndex$2(dom, name, element)
8944        };
8945      }
8946      var rng2 = normalizeTableCellSelection(rng.cloneRange());
8947      if (!collapsed) {
8948        rng2.collapse(false);
8949        var endBookmarkNode = createBookmarkSpan(dom, id + '_end', filled);
8950        rangeInsertNode(dom, rng2, endBookmarkNode);
8951      }
8952      rng = normalizeTableCellSelection(rng);
8953      rng.collapse(true);
8954      var startBookmarkNode = createBookmarkSpan(dom, id + '_start', filled);
8955      rangeInsertNode(dom, rng, startBookmarkNode);
8956      selection.moveToBookmark({
8957        id: id,
8958        keep: 1
8959      });
8960      return { id: id };
8961    };
8962    var getBookmark = function (selection, type, normalized) {
8963      if (type === 2) {
8964        return getOffsetBookmark(Zwsp.trim, normalized, selection);
8965      } else if (type === 3) {
8966        return getCaretBookmark(selection);
8967      } else if (type) {
8968        return getRangeBookmark(selection);
8969      } else {
8970        return getPersistentBookmark(selection, false);
8971      }
8972    };
8973    var GetBookmark = {
8974      getBookmark: getBookmark,
8975      getUndoBookmark: curry(getOffsetBookmark, identity, true),
8976      getPersistentBookmark: getPersistentBookmark
8977    };
8978
8979    var CARET_ID = '_mce_caret';
8980    var isCaretNode = function (node) {
8981      return NodeType.isElement(node) && node.id === CARET_ID;
8982    };
8983    var getParentCaretContainer = function (body, node) {
8984      while (node && node !== body) {
8985        if (node.id === CARET_ID) {
8986          return node;
8987        }
8988        node = node.parentNode;
8989      }
8990      return null;
8991    };
8992
8993    var isElement$4 = NodeType.isElement;
8994    var isText$6 = NodeType.isText;
8995    var removeNode = function (node) {
8996      var parentNode = node.parentNode;
8997      if (parentNode) {
8998        parentNode.removeChild(node);
8999      }
9000    };
9001    var getNodeValue = function (node) {
9002      try {
9003        return node.nodeValue;
9004      } catch (ex) {
9005        return '';
9006      }
9007    };
9008    var setNodeValue = function (node, text) {
9009      if (text.length === 0) {
9010        removeNode(node);
9011      } else {
9012        node.nodeValue = text;
9013      }
9014    };
9015    var trimCount = function (text) {
9016      var trimmedText = Zwsp.trim(text);
9017      return {
9018        count: text.length - trimmedText.length,
9019        text: trimmedText
9020      };
9021    };
9022    var removeUnchanged = function (caretContainer, pos) {
9023      remove$5(caretContainer);
9024      return pos;
9025    };
9026    var removeTextAndReposition = function (caretContainer, pos) {
9027      var before = trimCount(caretContainer.data.substr(0, pos.offset()));
9028      var after = trimCount(caretContainer.data.substr(pos.offset()));
9029      var text = before.text + after.text;
9030      if (text.length > 0) {
9031        setNodeValue(caretContainer, text);
9032        return CaretPosition$1(caretContainer, pos.offset() - before.count);
9033      } else {
9034        return pos;
9035      }
9036    };
9037    var removeElementAndReposition = function (caretContainer, pos) {
9038      var parentNode = pos.container();
9039      var newPosition = indexOf(from$1(parentNode.childNodes), caretContainer).map(function (index) {
9040        return index < pos.offset() ? CaretPosition$1(parentNode, pos.offset() - 1) : pos;
9041      }).getOr(pos);
9042      remove$5(caretContainer);
9043      return newPosition;
9044    };
9045    var removeTextCaretContainer = function (caretContainer, pos) {
9046      return isText$6(caretContainer) && pos.container() === caretContainer ? removeTextAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
9047    };
9048    var removeElementCaretContainer = function (caretContainer, pos) {
9049      return pos.container() === caretContainer.parentNode ? removeElementAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
9050    };
9051    var removeAndReposition = function (container, pos) {
9052      return CaretPosition$1.isTextPosition(pos) ? removeTextCaretContainer(container, pos) : removeElementCaretContainer(container, pos);
9053    };
9054    var remove$5 = function (caretContainerNode) {
9055      if (isElement$4(caretContainerNode) && isCaretContainer(caretContainerNode)) {
9056        if (hasContent(caretContainerNode)) {
9057          caretContainerNode.removeAttribute('data-mce-caret');
9058        } else {
9059          removeNode(caretContainerNode);
9060        }
9061      }
9062      if (isText$6(caretContainerNode)) {
9063        var text = Zwsp.trim(getNodeValue(caretContainerNode));
9064        setNodeValue(caretContainerNode, text);
9065      }
9066    };
9067    var CaretContainerRemove = {
9068      removeAndReposition: removeAndReposition,
9069      remove: remove$5
9070    };
9071
9072    var browser$2 = PlatformDetection$1.detect().browser;
9073    var isContentEditableFalse$3 = NodeType.isContentEditableFalse;
9074    var isTableCell$1 = function (node) {
9075      return NodeType.isElement(node) && /^(TD|TH)$/i.test(node.tagName);
9076    };
9077    var getAbsoluteClientRect = function (root, element, before) {
9078      var clientRect = collapse(element.getBoundingClientRect(), before);
9079      var docElm, scrollX, scrollY, margin, rootRect;
9080      if (root.tagName === 'BODY') {
9081        docElm = root.ownerDocument.documentElement;
9082        scrollX = root.scrollLeft || docElm.scrollLeft;
9083        scrollY = root.scrollTop || docElm.scrollTop;
9084      } else {
9085        rootRect = root.getBoundingClientRect();
9086        scrollX = root.scrollLeft - rootRect.left;
9087        scrollY = root.scrollTop - rootRect.top;
9088      }
9089      clientRect.left += scrollX;
9090      clientRect.right += scrollX;
9091      clientRect.top += scrollY;
9092      clientRect.bottom += scrollY;
9093      clientRect.width = 1;
9094      margin = element.offsetWidth - element.clientWidth;
9095      if (margin > 0) {
9096        if (before) {
9097          margin *= -1;
9098        }
9099        clientRect.left += margin;
9100        clientRect.right += margin;
9101      }
9102      return clientRect;
9103    };
9104    var trimInlineCaretContainers = function (root) {
9105      var contentEditableFalseNodes, node, sibling, i, data;
9106      contentEditableFalseNodes = DomQuery('*[contentEditable=false]', root);
9107      for (i = 0; i < contentEditableFalseNodes.length; i++) {
9108        node = contentEditableFalseNodes[i];
9109        sibling = node.previousSibling;
9110        if (endsWithCaretContainer(sibling)) {
9111          data = sibling.data;
9112          if (data.length === 1) {
9113            sibling.parentNode.removeChild(sibling);
9114          } else {
9115            sibling.deleteData(data.length - 1, 1);
9116          }
9117        }
9118        sibling = node.nextSibling;
9119        if (startsWithCaretContainer(sibling)) {
9120          data = sibling.data;
9121          if (data.length === 1) {
9122            sibling.parentNode.removeChild(sibling);
9123          } else {
9124            sibling.deleteData(0, 1);
9125          }
9126        }
9127      }
9128    };
9129    var FakeCaret = function (root, isBlock, hasFocus) {
9130      var lastVisualCaret = Cell(Option.none());
9131      var cursorInterval, caretContainerNode;
9132      var show = function (before, element) {
9133        var clientRect, rng;
9134        hide();
9135        if (isTableCell$1(element)) {
9136          return null;
9137        }
9138        if (isBlock(element)) {
9139          caretContainerNode = insertBlock('p', element, before);
9140          clientRect = getAbsoluteClientRect(root, element, before);
9141          DomQuery(caretContainerNode).css('top', clientRect.top);
9142          var caret = DomQuery('<div class="mce-visual-caret" data-mce-bogus="all"></div>').css(clientRect).appendTo(root)[0];
9143          lastVisualCaret.set(Option.some({
9144            caret: caret,
9145            element: element,
9146            before: before
9147          }));
9148          lastVisualCaret.get().each(function (caretState) {
9149            if (before) {
9150              DomQuery(caretState.caret).addClass('mce-visual-caret-before');
9151            }
9152          });
9153          startBlink();
9154          rng = element.ownerDocument.createRange();
9155          rng.setStart(caretContainerNode, 0);
9156          rng.setEnd(caretContainerNode, 0);
9157        } else {
9158          caretContainerNode = insertInline(element, before);
9159          rng = element.ownerDocument.createRange();
9160          if (isContentEditableFalse$3(caretContainerNode.nextSibling)) {
9161            rng.setStart(caretContainerNode, 0);
9162            rng.setEnd(caretContainerNode, 0);
9163          } else {
9164            rng.setStart(caretContainerNode, 1);
9165            rng.setEnd(caretContainerNode, 1);
9166          }
9167          return rng;
9168        }
9169        return rng;
9170      };
9171      var hide = function () {
9172        trimInlineCaretContainers(root);
9173        if (caretContainerNode) {
9174          CaretContainerRemove.remove(caretContainerNode);
9175          caretContainerNode = null;
9176        }
9177        lastVisualCaret.get().each(function (caretState) {
9178          DomQuery(caretState.caret).remove();
9179          lastVisualCaret.set(Option.none());
9180        });
9181        Delay.clearInterval(cursorInterval);
9182      };
9183      var startBlink = function () {
9184        cursorInterval = Delay.setInterval(function () {
9185          if (hasFocus()) {
9186            DomQuery('div.mce-visual-caret', root).toggleClass('mce-visual-caret-hidden');
9187          } else {
9188            DomQuery('div.mce-visual-caret', root).addClass('mce-visual-caret-hidden');
9189          }
9190        }, 500);
9191      };
9192      var reposition = function () {
9193        lastVisualCaret.get().each(function (caretState) {
9194          var clientRect = getAbsoluteClientRect(root, caretState.element, caretState.before);
9195          DomQuery(caretState.caret).css(__assign({}, clientRect));
9196        });
9197      };
9198      var destroy = function () {
9199        return Delay.clearInterval(cursorInterval);
9200      };
9201      var getCss = function () {
9202        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;' + '}';
9203      };
9204      return {
9205        show: show,
9206        hide: hide,
9207        getCss: getCss,
9208        reposition: reposition,
9209        destroy: destroy
9210      };
9211    };
9212    var isFakeCaretTableBrowser = function () {
9213      return browser$2.isIE() || browser$2.isEdge() || browser$2.isFirefox();
9214    };
9215    var isFakeCaretTarget = function (node) {
9216      return isContentEditableFalse$3(node) || NodeType.isTable(node) && isFakeCaretTableBrowser();
9217    };
9218
9219    var isContentEditableFalse$4 = NodeType.isContentEditableFalse;
9220    var isBlockLike = NodeType.matchStyleValues('display', 'block table table-cell table-caption list-item');
9221    var isCaretContainer$2 = isCaretContainer;
9222    var isCaretContainerBlock$1 = isCaretContainerBlock;
9223    var isElement$5 = NodeType.isElement;
9224    var isCaretCandidate$2 = isCaretCandidate;
9225    var isForwards = function (direction) {
9226      return direction > 0;
9227    };
9228    var isBackwards = function (direction) {
9229      return direction < 0;
9230    };
9231    var skipCaretContainers = function (walk, shallow) {
9232      var node;
9233      while (node = walk(shallow)) {
9234        if (!isCaretContainerBlock$1(node)) {
9235          return node;
9236        }
9237      }
9238      return null;
9239    };
9240    var findNode = function (node, direction, predicateFn, rootNode, shallow) {
9241      var walker = new TreeWalker(node, rootNode);
9242      if (isBackwards(direction)) {
9243        if (isContentEditableFalse$4(node) || isCaretContainerBlock$1(node)) {
9244          node = skipCaretContainers(walker.prev, true);
9245          if (predicateFn(node)) {
9246            return node;
9247          }
9248        }
9249        while (node = skipCaretContainers(walker.prev, shallow)) {
9250          if (predicateFn(node)) {
9251            return node;
9252          }
9253        }
9254      }
9255      if (isForwards(direction)) {
9256        if (isContentEditableFalse$4(node) || isCaretContainerBlock$1(node)) {
9257          node = skipCaretContainers(walker.next, true);
9258          if (predicateFn(node)) {
9259            return node;
9260          }
9261        }
9262        while (node = skipCaretContainers(walker.next, shallow)) {
9263          if (predicateFn(node)) {
9264            return node;
9265          }
9266        }
9267      }
9268      return null;
9269    };
9270    var getParentBlock = function (node, rootNode) {
9271      while (node && node !== rootNode) {
9272        if (isBlockLike(node)) {
9273          return node;
9274        }
9275        node = node.parentNode;
9276      }
9277      return null;
9278    };
9279    var isInSameBlock = function (caretPosition1, caretPosition2, rootNode) {
9280      return getParentBlock(caretPosition1.container(), rootNode) === getParentBlock(caretPosition2.container(), rootNode);
9281    };
9282    var getChildNodeAtRelativeOffset = function (relativeOffset, caretPosition) {
9283      var container, offset;
9284      if (!caretPosition) {
9285        return null;
9286      }
9287      container = caretPosition.container();
9288      offset = caretPosition.offset();
9289      if (!isElement$5(container)) {
9290        return null;
9291      }
9292      return container.childNodes[offset + relativeOffset];
9293    };
9294    var beforeAfter = function (before, node) {
9295      var range = node.ownerDocument.createRange();
9296      if (before) {
9297        range.setStartBefore(node);
9298        range.setEndBefore(node);
9299      } else {
9300        range.setStartAfter(node);
9301        range.setEndAfter(node);
9302      }
9303      return range;
9304    };
9305    var isNodesInSameBlock = function (root, node1, node2) {
9306      return getParentBlock(node1, root) === getParentBlock(node2, root);
9307    };
9308    var lean = function (left, root, node) {
9309      var sibling, siblingName;
9310      if (left) {
9311        siblingName = 'previousSibling';
9312      } else {
9313        siblingName = 'nextSibling';
9314      }
9315      while (node && node !== root) {
9316        sibling = node[siblingName];
9317        if (isCaretContainer$2(sibling)) {
9318          sibling = sibling[siblingName];
9319        }
9320        if (isContentEditableFalse$4(sibling)) {
9321          if (isNodesInSameBlock(root, sibling, node)) {
9322            return sibling;
9323          }
9324          break;
9325        }
9326        if (isCaretCandidate$2(sibling)) {
9327          break;
9328        }
9329        node = node.parentNode;
9330      }
9331      return null;
9332    };
9333    var before$2 = curry(beforeAfter, true);
9334    var after$1 = curry(beforeAfter, false);
9335    var normalizeRange = function (direction, root, range) {
9336      var node, container, offset, location;
9337      var leanLeft = curry(lean, true, root);
9338      var leanRight = curry(lean, false, root);
9339      container = range.startContainer;
9340      offset = range.startOffset;
9341      if (isCaretContainerBlock(container)) {
9342        if (!isElement$5(container)) {
9343          container = container.parentNode;
9344        }
9345        location = container.getAttribute('data-mce-caret');
9346        if (location === 'before') {
9347          node = container.nextSibling;
9348          if (isFakeCaretTarget(node)) {
9349            return before$2(node);
9350          }
9351        }
9352        if (location === 'after') {
9353          node = container.previousSibling;
9354          if (isFakeCaretTarget(node)) {
9355            return after$1(node);
9356          }
9357        }
9358      }
9359      if (!range.collapsed) {
9360        return range;
9361      }
9362      if (NodeType.isText(container)) {
9363        if (isCaretContainer$2(container)) {
9364          if (direction === 1) {
9365            node = leanRight(container);
9366            if (node) {
9367              return before$2(node);
9368            }
9369            node = leanLeft(container);
9370            if (node) {
9371              return after$1(node);
9372            }
9373          }
9374          if (direction === -1) {
9375            node = leanLeft(container);
9376            if (node) {
9377              return after$1(node);
9378            }
9379            node = leanRight(container);
9380            if (node) {
9381              return before$2(node);
9382            }
9383          }
9384          return range;
9385        }
9386        if (endsWithCaretContainer(container) && offset >= container.data.length - 1) {
9387          if (direction === 1) {
9388            node = leanRight(container);
9389            if (node) {
9390              return before$2(node);
9391            }
9392          }
9393          return range;
9394        }
9395        if (startsWithCaretContainer(container) && offset <= 1) {
9396          if (directio
9396n === -1) {
9397            node = leanLeft(container);
9398            if (node) {
9399              return after$1(node);
9400            }
9401          }
9402          return range;
9403        }
9404        if (offset === container.data.length) {
9405          node = leanRight(container);
9406          if (node) {
9407            return before$2(node);
9408          }
9409          return range;
9410        }
9411        if (offset === 0) {
9412          node = leanLeft(container);
9413          if (node) {
9414            return after$1(node);
9415          }
9416          return range;
9417        }
9418      }
9419      return range;
9420    };
9421    var getRelativeCefElm = function (forward, caretPosition) {
9422      return Option.from(getChildNodeAtRelativeOffset(forward ? 0 : -1, caretPosition)).filter(isContentEditableFalse$4);
9423    };
9424    var getNormalizedRangeEndPoint = function (direction, root, range) {
9425      var normalizedRange = normalizeRange(direction, root, range);
9426      if (direction === -1) {
9427        return CaretPosition.fromRangeStart(normalizedRange);
9428      }
9429      return CaretPosition.fromRangeEnd(normalizedRange);
9430    };
9431    var getElementFromPosition = function (pos) {
9432      return Option.from(pos.getNode()).map(Element.fromDom);
9433    };
9434    var getElementFromPrevPosition = function (pos) {
9435      return Option.from(pos.getNode(true)).map(Element.fromDom);
9436    };
9437    var getVisualCaretPosition = function (walkFn, caretPosition) {
9438      while (caretPosition = walkFn(caretPosition)) {
9439        if (caretPosition.isVisible()) {
9440          return caretPosition;
9441        }
9442      }
9443      return caretPosition;
9444    };
9445    var isMoveInsideSameBlock = function (from, to) {
9446      var inSameBlock = isInSameBlock(from, to);
9447      if (!inSameBlock && NodeType.isBr(from.getNode())) {
9448        return true;
9449      }
9450      return inSameBlock;
9451    };
9452
9453    var HDirection;
9454    (function (HDirection) {
9455      HDirection[HDirection['Backwards'] = -1] = 'Backwards';
9456      HDirection[HDirection['Forwards'] = 1] = 'Forwards';
9457    }(HDirection || (HDirection = {})));
9458    var isContentEditableFalse$5 = NodeType.isContentEditableFalse;
9459    var isText$7 = NodeType.isText;
9460    var isElement$6 = NodeType.isElement;
9461    var isBr$4 = NodeType.isBr;
9462    var isCaretCandidate$3 = isCaretCandidate;
9463    var isAtomic$1 = isAtomic;
9464    var isEditableCaretCandidate$1 = isEditableCaretCandidate;
9465    var getParents = function (node, root) {
9466      var parents = [];
9467      while (node && node !== root) {
9468        parents.push(node);
9469        node = node.parentNode;
9470      }
9471      return parents;
9472    };
9473    var nodeAtIndex = function (container, offset) {
9474      if (container.hasChildNodes() && offset < container.childNodes.length) {
9475        return container.childNodes[offset];
9476      }
9477      return null;
9478    };
9479    var getCaretCandidatePosition = function (direction, node) {
9480      if (isForwards(direction)) {
9481        if (isCaretCandidate$3(node.previousSibling) && !isText$7(node.previousSibling)) {
9482          return CaretPosition$1.before(node);
9483        }
9484        if (isText$7(node)) {
9485          return CaretPosition$1(node, 0);
9486        }
9487      }
9488      if (isBackwards(direction)) {
9489        if (isCaretCandidate$3(node.nextSibling) && !isText$7(node.nextSibling)) {
9490          return CaretPosition$1.after(node);
9491        }
9492        if (isText$7(node)) {
9493          return CaretPosition$1(node, node.data.length);
9494        }
9495      }
9496      if (isBackwards(direction)) {
9497        if (isBr$4(node)) {
9498          return CaretPosition$1.before(node);
9499        }
9500        return CaretPosition$1.after(node);
9501      }
9502      return CaretPosition$1.before(node);
9503    };
9504    var moveForwardFromBr = function (root, nextNode) {
9505      var nextSibling = nextNode.nextSibling;
9506      if (nextSibling && isCaretCandidate$3(nextSibling)) {
9507        if (isText$7(nextSibling)) {
9508          return CaretPosition$1(nextSibling, 0);
9509        } else {
9510          return CaretPosition$1.before(nextSibling);
9511        }
9512      } else {
9513        return findCaretPosition(HDirection.Forwards, CaretPosition$1.after(nextNode), root);
9514      }
9515    };
9516    var findCaretPosition = function (direction, startPos, root) {
9517      var node, nextNode, innerNode;
9518      var rootContentEditableFalseElm, caretPosition;
9519      if (!isElement$6(root) || !startPos) {
9520        return null;
9521      }
9522      if (startPos.isEqual(CaretPosition$1.after(root)) && root.lastChild) {
9523        caretPosition = CaretPosition$1.after(root.lastChild);
9524        if (isBackwards(direction) && isCaretCandidate$3(root.lastChild) && isElement$6(root.lastChild)) {
9525          return isBr$4(root.lastChild) ? CaretPosition$1.before(root.lastChild) : caretPosition;
9526        }
9527      } else {
9528        caretPosition = startPos;
9529      }
9530      var container = caretPosition.container();
9531      var offset = caretPosition.offset();
9532      if (isText$7(container)) {
9533        if (isBackwards(direction) && offset > 0) {
9534          return CaretPosition$1(container, --offset);
9535        }
9536        if (isForwards(direction) && offset < container.length) {
9537          return CaretPosition$1(container, ++offset);
9538        }
9539        node = container;
9540      } else {
9541        if (isBackwards(direction) && offset > 0) {
9542          nextNode = nodeAtIndex(container, offset - 1);
9543          if (isCaretCandidate$3(nextNode)) {
9544            if (!isAtomic$1(nextNode)) {
9545              innerNode = findNode(nextNode, direction, isEditableCaretCandidate$1, nextNode);
9546              if (innerNode) {
9547                if (isText$7(innerNode)) {
9548                  return CaretPosition$1(innerNode, innerNode.data.length);
9549                }
9550                return CaretPosition$1.after(innerNode);
9551              }
9552            }
9553            if (isText$7(nextNode)) {
9554              return CaretPosition$1(nextNode, nextNode.data.length);
9555            }
9556            return CaretPosition$1.before(nextNode);
9557          }
9558        }
9559        if (isForwards(direction) && offset < container.childNodes.length) {
9560          nextNode = nodeAtIndex(container, offset);
9561          if (isCaretCandidate$3(nextNode)) {
9562            if (isBr$4(nextNode)) {
9563              return moveForwardFromBr(root, nextNode);
9564            }
9565            if (!isAtomic$1(nextNode)) {
9566              innerNode = findNode(nextNode, direction, isEditableCaretCandidate$1, nextNode);
9567              if (innerNode) {
9568                if (isText$7(innerNode)) {
9569                  return CaretPosition$1(innerNode, 0);
9570                }
9571                return CaretPosition$1.before(innerNode);
9572              }
9573            }
9574            if (isText$7(nextNode)) {
9575              return CaretPosition$1(nextNode, 0);
9576            }
9577            return CaretPosition$1.after(nextNode);
9578          }
9579        }
9580        node = nextNode ? nextNode : caretPosition.getNode();
9581      }
9582      if (isForwards(direction) && caretPosition.isAtEnd() || isBackwards(direction) && caretPosition.isAtStart()) {
9583        node = findNode(node, direction, constant(true), root, true);
9584        if (isEditableCaretCandidate$1(node, root)) {
9585          return getCaretCandidatePosition(direction, node);
9586        }
9587      }
9588      nextNode = findNode(node, direction, isEditableCaretCandidate$1, root);
9589      rootContentEditableFalseElm = ArrUtils.last(filter(getParents(container, root), isContentEditableFalse$5));
9590      if (rootContentEditableFalseElm && (!nextNode || !rootContentEditableFalseElm.contains(nextNode))) {
9591        if (isForwards(direction)) {
9592          caretPosition = CaretPosition$1.after(rootContentEditableFalseElm);
9593        } else {
9594          caretPosition = CaretPosition$1.before(rootContentEditableFalseElm);
9595        }
9596        return caretPosition;
9597      }
9598      if (nextNode) {
9599        return getCaretCandidatePosition(direction, nextNode);
9600      }
9601      return null;
9602    };
9603    var CaretWalker = function (root) {
9604      return {
9605        next: function (caretPosition) {
9606          return findCaretPosition(HDirection.Forwards, caretPosition, root);
9607        },
9608        prev: function (caretPosition) {
9609          return findCaretPosition(HDirection.Backwards, caretPosition, root);
9610        }
9611      };
9612    };
9613
9614    var walkToPositionIn = function (forward, root, start) {
9615      var position = forward ? CaretPosition$1.before(start) : CaretPosition$1.after(start);
9616      return fromPosition(forward, root, position);
9617    };
9618    var afterElement = function (node) {
9619      return NodeType.isBr(node) ? CaretPosition$1.before(node) : CaretPosition$1.after(node);
9620    };
9621    var isBeforeOrStart = function (position) {
9622      if (CaretPosition$1.isTextPosition(position)) {
9623        return position.offset() === 0;
9624      } else {
9625        return isCaretCandidate(position.getNode());
9626      }
9627    };
9628    var isAfterOrEnd = function (position) {
9629      if (CaretPosition$1.isTextPosition(position)) {
9630        var container = position.container();
9631        return position.offset() === container.data.length;
9632      } else {
9633        return isCaretCandidate(position.getNode(true));
9634      }
9635    };
9636    var isBeforeAfterSameElement = function (from, to) {
9637      return !CaretPosition$1.isTextPosition(from) && !CaretPosition$1.isTextPosition(to) && from.getNode() === to.getNode(true);
9638    };
9639    var isAtBr = function (position) {
9640      return !CaretPosition$1.isTextPosition(position) && NodeType.isBr(position.getNode());
9641    };
9642    var shouldSkipPosition = function (forward, from, to) {
9643      if (forward) {
9644        return !isBeforeAfterSameElement(from, to) && !isAtBr(from) && isAfterOrEnd(from) && isBeforeOrStart(to);
9645      } else {
9646        return !isBeforeAfterSameElement(to, from) && isBeforeOrStart(from) && isAfterOrEnd(to);
9647      }
9648    };
9649    var fromPosition = function (forward, root, pos) {
9650      var walker = CaretWalker(root);
9651      return Option.from(forward ? walker.next(pos) : walker.prev(pos));
9652    };
9653    var navigate = function (forward, root, from) {
9654      return fromPosition(forward, root, from).bind(function (to) {
9655        if (isInSameBlock(from, to, root) && shouldSkipPosition(forward, from, to)) {
9656          return fromPosition(forward, root, to);
9657        } else {
9658          return Option.some(to);
9659        }
9660      });
9661    };
9662    var navigateIgnore = function (forward, root, from, ignoreFilter) {
9663      return navigate(forward, root, from).bind(function (pos) {
9664        return ignoreFilter(pos) ? navigateIgnore(forward, root, pos, ignoreFilter) : Option.some(pos);
9665      });
9666    };
9667    var positionIn = function (forward, element) {
9668      var startNode = forward ? element.firstChild : element.lastChild;
9669      if (NodeType.isText(startNode)) {
9670        return Option.some(CaretPosition$1(startNode, forward ? 0 : startNode.data.length));
9671      } else if (startNode) {
9672        if (isCaretCandidate(startNode)) {
9673          return Option.some(forward ? CaretPosition$1.before(startNode) : afterElement(startNode));
9674        } else {
9675          return walkToPositionIn(forward, element, startNode);
9676        }
9677      } else {
9678        return Option.none();
9679      }
9680    };
9681    var nextPosition = curry(fromPosition, true);
9682    var prevPosition = curry(fromPosition, false);
9683    var CaretFinder = {
9684      fromPosition: fromPosition,
9685      nextPosition: nextPosition,
9686      prevPosition: prevPosition,
9687      navigate: navigate,
9688      navigateIgnore: navigateIgnore,
9689      positionIn: positionIn,
9690      firstPositionIn: curry(positionIn, true),
9691      lastPositionIn: curry(positionIn, false)
9692    };
9693
9694    var isStringPathBookmark = function (bookmark) {
9695      return typeof bookmark.start === 'string';
9696    };
9697    var isRangeBookmark = function (bookmark) {
9698      return bookmark.hasOwnProperty('rng');
9699    };
9700    var isIdBookmark = function (bookmark) {
9701      return bookmark.hasOwnProperty('id');
9702    };
9703    var isIndexBookmark = function (bookmark) {
9704      return bookmark.hasOwnProperty('name');
9705    };
9706    var isPathBookmark = function (bookmark) {
9707      return Tools.isArray(bookmark.start);
9708    };
9709
9710    var addBogus = function (dom, node) {
9711      if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
9712        node.innerHTML = '<br data-mce-bogus="1" />';
9713      }
9714      return node;
9715    };
9716    var resolveCaretPositionBookmark = function (dom, bookmark) {
9717      var rng, pos;
9718      rng = dom.createRng();
9719      pos = resolve$2(dom.getRoot(), bookmark.start);
9720      rng.setStart(pos.container(), pos.offset());
9721      pos = resolve$2(dom.getRoot(), bookmark.end);
9722      rng.setEnd(pos.container(), pos.offset());
9723      return rng;
9724    };
9725    var insertZwsp = function (node, rng) {
9726      var textNode = node.ownerDocument.createTextNode(Zwsp.ZWSP);
9727      node.appendChild(textNode);
9728      rng.setStart(textNode, 0);
9729      rng.setEnd(textNode, 0);
9730    };
9731    var isEmpty = function (node) {
9732      return node.hasChildNodes() === false;
9733    };
9734    var tryFindRangePosition = function (node, rng) {
9735      return CaretFinder.lastPositionIn(node).fold(function () {
9736        return false;
9737      }, function (pos) {
9738        rng.setStart(pos.container(), pos.offset());
9739        rng.setEnd(pos.container(), pos.offset());
9740        return true;
9741      });
9742    };
9743    var padEmptyCaretContainer = function (root, node, rng) {
9744      if (isEmpty(node) && getParentCaretContainer(root, node)) {
9745        insertZwsp(node, rng);
9746        return true;
9747      } else {
9748        return false;
9749      }
9750    };
9751    var setEndPoint = function (dom, start, bookmark, rng) {
9752      var point = bookmark[start ? 'start' : 'end'];
9753      var i, node, offset, children;
9754      var root = dom.getRoot();
9755      if (point) {
9756        offset = point[0];
9757        for (node = root, i = point.length - 1; i >= 1; i--) {
9758          children = node.childNodes;
9759          if (padEmptyCaretContainer(root, node, rng)) {
9760            return true;
9761          }
9762          if (point[i] > children.length - 1) {
9763            if (padEmptyCaretContainer(root, node, rng)) {
9764              return true;
9765            }
9766            return tryFindRangePosition(node, rng);
9767          }
9768          node = children[point[i]];
9769        }
9770        if (node.nodeType === 3) {
9771          offset = Math.min(point[0], node.nodeValue.length);
9772        }
9773        if (node.nodeType === 1) {
9774          offset = Math.min(point[0], node.childNodes.length);
9775        }
9776        if (start) {
9777          rng.setStart(node, offset);
9778        } else {
9779          rng.setEnd(node, offset);
9780        }
9781      }
9782      return true;
9783    };
9784    var isValidTextNode = function (node) {
9785      return NodeType.isText(node) && node.data.length > 0;
9786    };
9787    var restoreEndPoint = function (dom, suffix, bookmark) {
9788      var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev;
9789      var keep = bookmark.keep;
9790      var container, offset;
9791      if (marker) {
9792        node = marker.parentNode;
9793        if (suffix === 'start') {
9794          if (!keep) {
9795            idx = dom.nodeIndex(marker);
9796          } else {
9797            if (marker.hasChildNodes()) {
9798              node = marker.firstChild;
9799              idx = 1;
9800            } else if (isValidTextNode(marker.nextSibling)) {
9801              node = marker.nextSibling;
9802              idx = 0;
9803            } else if (isValidTextNode(marker.previousSibling)) {
9804              node = marker.previousSibling;
9805              idx = marker.previousSibling.data.length;
9806            } else {
9807              node = marker.parentNode;
9808              idx = dom.nodeIndex(marker) + 1;
9809            }
9810          }
9811          container = node;
9812          offset = idx;
9813        } else {
9814          if (!keep) {
9815            idx = dom.nodeIndex(marker);
9816          } else {
9817            if (marker.hasChildNodes()) {
9818              node = marker.firstChild;
9819              idx = 1;
9820            } else if (isValidTextNode(marker.previousSibling)) {
9821              node = marker.previousSibling;
9822              idx = marker.previousSibling.data.length;
9823            } else {
9824              node = marker.parentNode;
9825              idx = dom.nodeIndex(marker);
9826            }
9827          }
9828          container = node;
9829          offset = idx;
9830        }
9831        if (!keep) {
9832          prev = marker.previousSibling;
9833          next = marker.nextSibling;
9834          Tools.each(Tools.grep(marker.childNodes), function (node) {
9835            if (NodeType.isText(node)) {
9836              node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
9837            }
9838          });
9839          while (marker = dom.get(bookmark.id + '_' + suffix)) {
9840            dom.remove(marker, true);
9841          }
9842          if (prev && next && prev.nodeType === next.nodeType && NodeType.isText(prev) && !Env.opera) {
9843            idx = prev.nodeValue.length;
9844            prev.appendData(next.nodeValue);
9845            dom.remove(next);
9846            if (suffix === 'start') {
9847              container = prev;
9848              offset = idx;
9849            } else {
9850              container = prev;
9851              offset = idx;
9852            }
9853          }
9854        }
9855        return Option.some(CaretPosition$1(container, offset));
9856      } else {
9857        return Option.none();
9858      }
9859    };
9860    var alt = function (o1, o2) {
9861      return o1.isSome() ? o1 : o2;
9862    };
9863    var resolvePaths = function (dom, bookmark) {
9864      var rng = dom.createRng();
9865      if (setEndPoint(dom, true, bookmark, rng) && setEndPoint(dom, false, bookmark, rng)) {
9866        return Option.some(rng);
9867      } else {
9868        return Option.none();
9869      }
9870    };
9871    var resolveId = function (dom, bookmark) {
9872      var startPos = restoreEndPoint(dom, 'start', bookmark);
9873      var endPos = restoreEndPoint(dom, 'end', bookmark);
9874      return liftN([
9875        startPos,
9876        alt(endPos, startPos)
9877      ], function (spos, epos) {
9878        var rng = dom.createRng();
9879        rng.setStart(addBogus(dom, spos.container()), spos.offset());
9880        rng.setEnd(addBogus(dom, epos.container()), epos.offset());
9881        return rng;
9882      });
9883    };
9884    var resolveIndex$1 = function (dom, bookmark) {
9885      return Option.from(dom.select(bookmark.name)[bookmark.index]).map(function (elm) {
9886        var rng = dom.createRng();
9887        rng.selectNode(elm);
9888        return rng;
9889      });
9890    };
9891    var resolve$3 = function (selection, bookmark) {
9892      var dom = selection.dom;
9893      if (bookmark) {
9894        if (isPathBookmark(bookmark)) {
9895          return resolvePaths(dom, bookmark);
9896        } else if (isStringPathBookmark(bookmark)) {
9897          return Option.some(resolveCaretPositionBookmark(dom, bookmark));
9898        } else if (isIdBookmark(bookmark)) {
9899          return resolveId(dom, bookmark);
9900        } else if (isIndexBookmark(bookmark)) {
9901          return resolveIndex$1(dom, bookmark);
9902        } else if (isRangeBookmark(bookmark)) {
9903          return Option.some(bookmark.rng);
9904        }
9905      }
9906      return Option.none();
9907    };
9908    var ResolveBookmark = { resolve: resolve$3 };
9909
9910    var getBookmark$1 = function (selection, type, normalized) {
9911      return GetBookmark.getBookmark(selection, type, normalized);
9912    };
9913    var moveToBookmark = function (selection, bookmark) {
9914      ResolveBookmark.resolve(selection, bookmark).each(function (rng) {
9915        selection.setRng(rng);
9916      });
9917    };
9918    var isBookmarkNode$1 = function (node) {
9919      return NodeType.isElement(node) && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
9920    };
9921    var Bookmarks = {
9922      getBookmark: getBookmark$1,
9923      moveToBookmark: moveToBookmark,
9924      isBookmarkNode: isBookmarkNode$1
9925    };
9926
9927    var isInlineBlock = function (node) {
9928      return node && /^(IMG)$/.test(node.nodeName);
9929    };
9930    var moveStart = function (dom, selection, rng) {
9931      var offset = rng.startOffset;
9932      var container = rng.startContainer, walker, node, nodes;
9933      if (rng.startContainer === rng.endContainer) {
9934        if (isInlineBlock(rng.startContainer.childNodes[rng.startOffset])) {
9935          return;
9936        }
9937      }
9938      if (container.nodeType === 1) {
9939        nodes = container.childNodes;
9940        if (offset < nodes.length) {
9941          container = nodes[offset];
9942          walker = new TreeWalker(container, dom.getParent(container, dom.isBlock));
9943        } else {
9944          container = nodes[nodes.length - 1];
9945          walker = new TreeWalker(container, dom.getParent(container, dom.isBlock));
9946          walker.next(true);
9947        }
9948        for (node = walker.current(); node; node = walker.next()) {
9949          if (node.nodeType === 3 && !isWhiteSpaceNode(node)) {
9950            rng.setStart(node, 0);
9951            selection.setRng(rng);
9952            return;
9953          }
9954        }
9955      }
9956    };
9957    var getNonWhiteSpaceSibling = function (node, next, inc) {
9958      if (node) {
9959        next = next ? 'nextSibling' : 'previousSibling';
9960        for (node = inc ? node : node[next]; node; node = node[next]) {
9961          if (node.nodeType === 1 || !isWhiteSpaceNode(node)) {
9962            return node;
9963          }
9964        }
9965      }
9966    };
9967    var isTextBlock$1 = function (editor, name) {
9968      if (name.nodeType) {
9969        name = name.nodeName;
9970      }
9971      return !!editor.schema.getTextBlockElements()[name.toLowerCase()];
9972    };
9973    var isValid = function (ed, parent, child) {
9974      return ed.schema.isValidChild(parent, child);
9975    };
9976    var isWhiteSpaceNode = function (node) {
9977      return node && node.nodeType === 3 && /^([\t \r\n]+|)$/.test(node.nodeValue);
9978    };
9979    var replaceVars = function (value, vars) {
9980      if (typeof value !== 'string') {
9981        value = value(vars);
9982      } else if (vars) {
9983        value = value.replace(/%(\w+)/g, function (str, name) {
9984          return vars[name] || str;
9985        });
9986      }
9987      return value;
9988    };
9989    var isEq = function (str1, str2) {
9990      str1 = str1 || '';
9991      str2 = str2 || '';
9992      str1 = '' + (str1.nodeName || str1);
9993      str2 = '' + (str2.nodeName || str2);
9994      return str1.toLowerCase() === str2.toLowerCase();
9995    };
9996    var normalizeStyleValue = function (dom, value, name) {
9997      if (name === 'color' || name === 'backgroundColor') {
9998        value = dom.toHex(value);
9999      }
10000      if (name === 'fontWeight' && value === 700) {
10001        value = 'bold';
10002      }
10003      if (name === 'fontFamily') {
10004        value = value.replace(/[\'\"]/g, '').replace(/,\s+/g, ',');
10005      }
10006      return '' + value;
10007    };
10008    var getStyle = function (dom, node, name) {
10009      return normalizeStyleValue(dom, dom.getStyle(node, name), name);
10010    };
10011    var getTextDecoration = function (dom, node) {
10012      var decoration;
10013      dom.getParent(node, function (n) {
10014        decoration = dom.getStyle(n, 'text-decoration');
10015        return decoration && decoration !== 'none';
10016      });
10017      return decoration;
10018    };
10019    var getParents$1 = function (dom, node, selector) {
10020      return dom.getParents(node, selector, dom.getRoot());
10021    };
10022    var FormatUtils = {
10023      isInlineBlock: isInlineBlock,
10024      moveStart: moveStart,
10025      getNonWhiteSpaceSibling: getNonWhiteSpaceSibling,
10026      isTextBlock: isTextBlock$1,
10027      isValid: isValid,
10028      isWhiteSpaceNode: isWhiteSpaceNode,
10029      replaceVars: replaceVars,
10030      isEq: isEq,
10031      normalizeStyleValue: normalizeStyleValue,
10032      getStyle: getStyle,
10033      getTextDecoration: getTextDecoration,
10034      getParents: getParents$1
10035    };
10036
10037    var isBookmarkNode$2 = Bookmarks.isBookmarkNode;
10038    var getParents$2 = FormatUtils.getParents, isWhiteSpaceNode$1 = FormatUtils.isWhiteSpaceNode, isTextBlock$2 = FormatUtils.isTextBlock;
10039    var findLeaf = function (node, offset) {
10040      if (typeof offset === 'undefined') {
10041        offset = node.nodeType === 3 ? node.length : node.childNodes.length;
10042      }
10043      while (node && node.hasChildNodes()) {
10044        node = node.childNodes[offset];
10045        if (node) {
10046          offset = node.nodeType === 3 ? node.length : node.childNodes.length;
10047        }
10048      }
10049      return {
10050        node: node,
10051        offset: offset
10052      };
10053    };
10054    var excludeTrailingWhitespace = function (endContainer, endOffset) {
10055      var leaf = findLeaf(endContainer, endOffset);
10056      if (leaf.node) {
10057        while (leaf.node && leaf.offset === 0 && leaf.node.previousSibling) {
10058          leaf = findLeaf(leaf.node.previousSibling);
10059        }
10060        if (leaf.node && leaf.offset > 0 && leaf.node.nodeType === 3 && leaf.node.nodeValue.charAt(leaf.offset - 1) === ' ') {
10061          if (leaf.offset > 1) {
10062            endContainer = leaf.node;
10063            endContainer.splitText(leaf.offset - 1);
10064          }
10065        }
10066      }
10067      return endContainer;
10068    };
10069    var isBogusBr = function (node) {
10070      return node.nodeName === 'BR' && node.getAttribute('data-mce-bogus') && !node.nextSibling;
10071    };
10072    var findParentContentEditable = function (dom, node) {
10073      var parent = node;
10074      while (parent) {
10075        if (parent.nodeType === 1 && dom.getContentEditable(parent)) {
10076          return dom.getContentEditable(parent) === 'false' ? parent : node;
10077        }
10078        parent = parent.parentNode;
10079      }
10080      return node;
10081    };
10082    var findSpace = function (start, remove, node, offset) {
10083      var pos, pos2;
10084      var str = node.nodeValue;
10085      if (typeof offset === 'undefined') {
10086        offset = start ? str.length : 0;
10087      }
10088      if (start) {
10089        pos = str.lastIndexOf(' ', offset);
10090        pos2 = str.lastIndexOf('\xA0', offset);
10091        pos = pos > pos2 ? pos : pos2;
10092        if (pos !== -1 && !remove && (pos < offset || !start) && pos <= str.length) {
10093          pos++;
10094        }
10095      } else {
10096        pos = str.indexOf(' ', offset);
10097        pos2 = str.indexOf('\xA0', offset);
10098        pos = pos !== -1 && (pos2 === -1 || pos < pos2) ? pos : pos2;
10099      }
10100      return pos;
10101    };
10102    var findWordEndPoint = function (dom, body, container, offset, start, remove) {
10103      var node, pos, lastTextNode;
10104      if (container.nodeType === 3) {
10105        pos = findSpace(start, remove, container, offset);
10106        if (pos !== -1) {
10107          return {
10108            container: container,
10109            offset: pos
10110          };
10111        }
10112        lastTextNode = container;
10113      }
10114      var walker = new TreeWalker(container, dom.getParent(container, dom.isBlock) || body);
10115      while (node = walker[start ? 'prev' : 'next']()) {
10116        if (node.nodeType === 3 && !isBookmarkNode$2(node.parentNode)) {
10117          lastTextNode = node;
10118          pos = findSpace(start, remove, node);
10119          if (pos !== -1) {
10120            return {
10121              container: node,
10122              offset: pos
10123            };
10124          }
10125        } else if (dom.isBlock(node) || FormatUtils.isEq(node, 'BR')) {
10126          break;
10127        }
10128      }
10129      if (lastTextNode) {
10130        if (start) {
10131          offset = 0;
10132        } else {
10133          offset = lastTextNode.length;
10134        }
10135        return {
10136          container: lastTextNode,
10137          offset: offset
10138        };
10139      }
10140    };
10141    var findSelectorEndPoint = function (dom, format, rng, container, siblingName) {
10142      var parents, i, y, curFormat;
10143      if (container.nodeType === 3 && container.nodeValue.length === 0 && container[siblingName]) {
10144        container = container[siblingName];
10145      }
10146      parents = getParents$2(dom, container);
10147      for (i = 0; i < parents.length; i++) {
10148        for (y = 0; y < format.length; y++) {
10149          curFormat = format[y];
10150          if ('collapsed' in curFormat && curFormat.collapsed !== rng.collapsed) {
10151            continue;
10152          }
10153          if (dom.is(parents[i], curFormat.selector)) {
10154            return parents[i];
10155          }
10156        }
10157      }
10158      return container;
10159    };
10160    var findBlockEndPoint = function (editor, format, container, siblingName) {
10161      var node;
10162      var dom = editor.dom;
10163      var root = dom.getRoot();
10164      if (!format[0].wrapper) {
10165        node = dom.getParent(container, format[0].block, root);
10166      }
10167      if (!node) {
10168        var scopeRoot = dom.getParent(container, 'LI,TD,TH');
10169        node = dom.getParent(container.nodeType === 3 ? container.parentNode : container, function (node) {
10170          return node !== root && isTextBlock$2(editor, node);
10171        }, scopeRoot);
10172      }
10173      if (node && format[0].wrapper) {
10174        node = getParents$2(dom, node, 'ul,ol').reverse()[0] || node;
10175      }
10176      if (!node) {
10177        node = container;
10178        while (node[siblingName] && !dom.isBlock(node[siblingName])) {
10179          node = node[siblingName];
10180          if (FormatUtils.isEq(node, 'br')) {
10181            break;
10182          }
10183        }
10184      }
10185      return node || container;
10186    };
10187    var findParentContainer = function (dom, format, startContainer, startOffset, endContainer, endOffset, start) {
10188      var container, parent, sibling, siblingName, root;
10189      container = parent = start ? startContainer : endContainer;
10190      siblingName = start ? 'previousSibling' : 'nextSibling';
10191      root = dom.getRoot();
10192      if (container.nodeType === 3 && !isWhiteSpaceNode$1(container)) {
10193        if (start ? startOffset > 0 : endOffset < container.nodeValue.length) {
10194          return container;
10195        }
10196      }
10197      while (true) {
10198        if (!format[0].block_expand && dom.isBlock(parent)) {
10199          return parent;
10200        }
10201        for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
10202          if (!isBookmarkNode$2(sibling) && !isWhiteSpaceNode$1(sibling) && !isBogusBr(sibling)) {
10203            return parent;
10204          }
10205        }
10206        if (parent === root || parent.parentNode === root) {
10207          container = parent;
10208          break;
10209        }
10210        parent = parent.parentNode;
10211      }
10212      return container;
10213    };
10214    var expandRng = function (editor, rng, format, remove) {
10215      var endPoint, startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset;
10216      var dom = editor.dom;
10217      if (startContainer.nodeType === 1 && startContainer.hasChildNodes()) {
10218        startContainer = getNode(startContainer, startOffset);
10219        if (startContainer.nodeType === 3) {
10220          startOffset = 0;
10221        }
10222      }
10223      if (endContainer.nodeType === 1 && endContainer.hasChildNodes()) {
10224        endContainer = getNode(endContainer, rng.collapsed ? endOffset : endOffset - 1);
10225        if (endContainer.nodeType === 3) {
10226          endOffset = endContainer.nodeValue.length;
10227        }
10228      }
10229      startContainer = findParentContentEditable(dom, startContainer);
10230      endContainer = findParentContentEditable(dom, endContainer);
10231      if (isBookmarkNode$2(startContainer.parentNode) || isBookmarkNode$2(startContainer)) {
10232        startContainer = isBookmarkNode$2(startContainer) ? startContainer : startContainer.parentNode;
10233        if (rng.collapsed) {
10234          startContainer = startContainer.previousSibling || startContainer;
10235        } else {
10236          startContainer = startContainer.nextSibling || startContainer;
10237        }
10238        if (startContainer.nodeType === 3) {
10239          startOffset = rng.collapsed ? startContainer.length : 0;
10240        }
10241      }
10242      if (isBookmarkNode$2(endContainer.parentNode) || isBookmarkNode$2(endContainer)) {
10243        endContainer = isBookmarkNode$2(endContainer) ? endContainer : endContainer.parentNode;
10244        if (rng.collapsed) {
10245          endContainer = endContainer.nextSibling || endContainer;
10246        } else {
10247          endContainer = endContainer.previousSibling || endContainer;
10248        }
10249        if (endContainer.nodeType === 3) {
10250          endOffset = rng.collapsed ? 0 : endContainer.length;
10251        }
10252      }
10253      if (rng.collapsed) {
10254        endPoint = findWordEndPoint(dom, editor.getBody(), startContainer, startOffset, true, remove);
10255        if (endPoint) {
10256          startContainer = endPoint.container;
10257          startOffset = endPoint.offset;
10258        }
10259        endPoint = findWordEndPoint(dom, editor.getBody(), endContainer, endOffset, false, remove);
10260        if (endPoint) {
10261          endContainer = endPoint.container;
10262          endOffset = endPoint.offset;
10263        }
10264      }
10265      if (format[0].inline) {
10266        endContainer = remove ? endContainer : excludeTrailingWhitespace(endContainer, endOffset);
10267      }
10268      if (format[0].inline || format[0].block_expand) {
10269        if (!format[0].inline || (startContainer.nodeType !== 3 || startOffset === 0)) {
10270          startContainer = findParentContainer(dom, format, startContainer, startOffset, endContainer, endOffset, true);
10271        }
10272        if (!format[0].inline || (endContainer.nodeType !== 3 || endOffset === endContainer.nodeValue.length)) {
10273          endContainer = findParentContainer(dom, format, startContainer, startOffset, endContainer, endOffset, false);
10274        }
10275      }
10276      if (format[0].selector && format[0].expand !== false && !format[0].inline) {
10277        startContainer = findSelectorEndPoint(dom, format, rng, startContainer, 'previousSibling');
10278        endContainer = findSelectorEndPoint(dom, format, rng, endContainer, 'nextSibling');
10279      }
10280      if (format[0].block || format[0].selector) {
10281        startContainer = findBlockEndPoint(editor, format, startContainer, 'previousSibling');
10282        endContainer = findBlockEndPoint(editor, format, endContainer, 'nextSibling');
10283        if (format[0].block) {
10284          if (!dom.isBlock(startContainer)) {
10285            startContainer = findParentContainer(dom, format, startContainer, startOffset, endContainer, endOffset, true);
10286          }
10287          if (!dom.isBlock(endContainer)) {
10288            endContainer = findParentContainer(dom, format, startContainer, startOffset, endContainer, endOffset, false);
10289          }
10290        }
10291      }
10292      if (startContainer.nodeType === 1) {
10293        startOffset = dom.nodeIndex(startContainer);
10294        startContainer = startContainer.parentNode;
10295      }
10296      if (endContainer.nodeType === 1) {
10297        endOffset = dom.nodeIndex(endContainer) + 1;
10298        endContainer = endContainer.parentNode;
10299      }
10300      return {
10301        startContainer: startContainer,
10302        startOffset: startOffset,
10303        endContainer: endContainer,
10304        endOffset: endOffset
10305      };
10306    };
10307    var ExpandRange = { expandRng: expandRng };
10308
10309    var each$8 = Tools.each;
10310    var getEndChild = function (container, index) {
10311      var childNodes = container.childNodes;
10312      index--;
10313      if (index > childNodes.length - 1) {
10314        index = childNodes.length - 1;
10315      } else if (index < 0) {
10316        index = 0;
10317      }
10318      return childNodes[index] || container;
10319    };
10320    var walk$1 = function (dom, rng, callback) {
10321      var startContainer = rng.startContainer;
10322      var startOffset = rng.startOffset;
10323      var endContainer = rng.endContainer;
10324      var endOffset = rng.endOffset;
10325      var ancestor;
10326      var startPoint;
10327      var endPoint;
10328      var node;
10329      var parent;
10330      var siblings;
10331      var nodes;
10332      nodes = dom.select('td[data-mce-selected],th[data-mce-selected]');
10333      if (nodes.length > 0) {
10334        each$8(nodes, function (node) {
10335          callback([node]);
10336        });
10337        return;
10338      }
10339      var exclude = function (nodes) {
10340        var node;
10341        node = nodes[0];
10342        if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) {
10343          nodes.splice(0, 1);
10344        }
10345        node = nodes[nodes.length - 1];
10346        if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) {
10347          nodes.splice(nodes.length - 1, 1);
10348        }
10349        return nodes;
10350      };
10351      var collectSiblings = function (node, name, endNode) {
10352        var siblings = [];
10353        for (; node && node !== endNode; node = node[name]) {
10354          siblings.push(node);
10355        }
10356        return siblings;
10357      };
10358      var findEndPoint = function (node, root) {
10359        do {
10360          if (node.parentNode === root) {
10361            return node;
10362          }
10363          node = node.parentNode;
10364        } while (node);
10365      };
10366      var walkBoundary = function (startNode, endNode, next) {
10367        var siblingName = next ? 'nextSibling' : 'previousSibling';
10368        for (node = startNode, parent = node.parentNode; node && node !== endNode; node = parent) {
10369          parent = node.parentNode;
10370          siblings = collectSiblings(node === startNode ? node : node[siblingName], siblingName);
10371          if (siblings.length) {
10372            if (!next) {
10373              siblings.reverse();
10374            }
10375            callback(exclude(siblings));
10376          }
10377        }
10378      };
10379      if (startContainer.nodeType === 1 && startContainer.hasChildNodes()) {
10380        startContainer = startContainer.childNodes[startOffset];
10381      }
10382      if (endContainer.nodeType === 1 && endContainer.hasChildNodes()) {
10383        endContainer = getEndChild(endContainer, endOffset);
10384      }
10385      if (startContainer === endContainer) {
10386        return callback(exclude([startContainer]));
10387      }
10388      ancestor = dom.findCommonAncestor(startContainer, endContainer);
10389      for (node = startContainer; node; node = node.parentNode) {
10390        if (node === endContainer) {
10391          return walkBoundary(startContainer, ancestor, true);
10392        }
10393        if (node === ancestor) {
10394          break;
10395        }
10396      }
10397      for (node = endContainer; node; node = node.parentNode) {
10398        if (node === startContainer) {
10399          return walkBoundary(endContainer, ancestor);
10400        }
10401        if (node === ancestor) {
10402          break;
10403        }
10404      }
10405      startPoint = findEndPoint(startContainer, ancestor) || startContainer;
10406      endPoint = findEndPoint(endContainer, ancestor) || endContainer;
10407      walkBoundary(startContainer, startPoint, true);
10408      siblings = collectSiblings(startPoint === startContainer ? startPoint : startPoint.nextSibling, 'nextSibling', endPoint === endContainer ? endPoint.nextSibling : endPoint);
10409      if (siblings.length) {
10410        callback(exclude(siblings));
10411      }
10412      walkBoundary(endContainer, endPoint);
10413    };
10414    var RangeWalk = { walk: walk$1 };
10415
10416    var zeroWidth = function () {
10417      return '\uFEFF';
10418    };
10419
10420    function NodeValue (is, name) {
10421      var get = function (element) {
10422        if (!is(element)) {
10423          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
10424        }
10425        return getOption(element).getOr('');
10426      };
10427      var getOptionIE10 = function (element) {
10428        try {
10429          return getOptionSafe(element);
10430        } catch (e) {
10431          return Option.none();
10432        }
10433      };
10434      var getOptionSafe = function (element) {
10435        return is(element) ? Option.from(element.dom().nodeValue) : Option.none();
10436      };
10437      var browser = PlatformDetection$1.detect().browser;
10438      var getOption = browser.isIE() && browser.version.major === 10 ? getOptionIE10 : getOptionSafe;
10439      var set = function (element, value) {
10440        if (!is(element)) {
10441          throw new Error('Can only set raw ' + name + ' value of a ' + n
10441ame + ' node');
10442        }
10443        element.dom().nodeValue = value;
10444      };
10445      return {
10446        get: get,
10447        getOption: getOption,
10448        set: set
10449      };
10450    }
10451
10452    var api = NodeValue(isText, 'text');
10453    var get$5 = function (element) {
10454      return api.get(element);
10455    };
10456
10457    var isZeroWidth = function (elem) {
10458      return isText(elem) && get$5(elem) === zeroWidth();
10459    };
10460    var context = function (editor, elem, wrapName, nodeName) {
10461      return parent(elem).fold(function () {
10462        return 'skipping';
10463      }, function (parent) {
10464        if (nodeName === 'br' || isZeroWidth(elem)) {
10465          return 'valid';
10466        } else if (isAnnotation(elem)) {
10467          return 'existing';
10468        } else if (isCaretNode(elem)) {
10469          return 'caret';
10470        } else if (!FormatUtils.isValid(editor, wrapName, nodeName) || !FormatUtils.isValid(editor, name(parent), wrapName)) {
10471          return 'invalid-child';
10472        } else {
10473          return 'valid';
10474        }
10475      });
10476    };
10477
10478    var shouldApplyToTrailingSpaces = function (rng) {
10479      return rng.startContainer.nodeType === 3 && rng.startContainer.nodeValue.length >= rng.startOffset && rng.startContainer.nodeValue[rng.startOffset] === '\xA0';
10480    };
10481    var applyWordGrab = function (editor, rng) {
10482      var r = ExpandRange.expandRng(editor, rng, [{ inline: true }], shouldApplyToTrailingSpaces(rng));
10483      rng.setStart(r.startContainer, r.startOffset);
10484      rng.setEnd(r.endContainer, r.endOffset);
10485      editor.selection.setRng(rng);
10486    };
10487    var makeAnnotation = function (eDoc, _a, annotationName, decorate) {
10488      var _b = _a.uid, uid = _b === void 0 ? generate('mce-annotation') : _b, data = __rest(_a, ['uid']);
10489      var master = Element.fromTag('span', eDoc);
10490      add$3(master, annotation());
10491      set(master, '' + dataAnnotationId(), uid);
10492      set(master, '' + dataAnnotation(), annotationName);
10493      var _c = decorate(uid, data), _d = _c.attributes, attributes = _d === void 0 ? {} : _d, _e = _c.classes, classes = _e === void 0 ? [] : _e;
10494      setAll(master, attributes);
10495      add$4(master, classes);
10496      return master;
10497    };
10498    var annotate = function (editor, rng, annotationName, decorate, data) {
10499      var newWrappers = [];
10500      var master = makeAnnotation(editor.getDoc(), data, annotationName, decorate);
10501      var wrapper = Cell(Option.none());
10502      var finishWrapper = function () {
10503        wrapper.set(Option.none());
10504      };
10505      var getOrOpenWrapper = function () {
10506        return wrapper.get().getOrThunk(function () {
10507          var nu = shallow(master);
10508          newWrappers.push(nu);
10509          wrapper.set(Option.some(nu));
10510          return nu;
10511        });
10512      };
10513      var processElements = function (elems) {
10514        each(elems, processElement);
10515      };
10516      var processElement = function (elem) {
10517        var ctx = context(editor, elem, 'span', name(elem));
10518        switch (ctx) {
10519        case 'invalid-child': {
10520            finishWrapper();
10521            var children$1 = children(elem);
10522            processElements(children$1);
10523            finishWrapper();
10524            break;
10525          }
10526        case 'valid': {
10527            var w = getOrOpenWrapper();
10528            wrap$1(elem, w);
10529            break;
10530          }
10531        case 'skipping':
10532        case 'existing':
10533        case 'caret':
10534        }
10535      };
10536      var processNodes = function (nodes) {
10537        var elems = map(nodes, Element.fromDom);
10538        processElements(elems);
10539      };
10540      RangeWalk.walk(editor.dom, rng, function (nodes) {
10541        finishWrapper();
10542        processNodes(nodes);
10543      });
10544      return newWrappers;
10545    };
10546    var annotateWithBookmark = function (editor, name, settings, data) {
10547      editor.undoManager.transact(function () {
10548        var initialRng = editor.selection.getRng();
10549        if (initialRng.collapsed) {
10550          applyWordGrab(editor, initialRng);
10551        }
10552        if (editor.selection.getRng().collapsed) {
10553          var wrapper = makeAnnotation(editor.getDoc(), data, name, settings.decorate);
10554          set$1(wrapper, '\xA0');
10555          editor.selection.getRng().insertNode(wrapper.dom());
10556          editor.selection.select(wrapper.dom());
10557        } else {
10558          var bookmark = GetBookmark.getPersistentBookmark(editor.selection, false);
10559          var rng = editor.selection.getRng();
10560          annotate(editor, rng, name, settings.decorate, data);
10561          editor.selection.moveToBookmark(bookmark);
10562        }
10563      });
10564    };
10565
10566    var Annotator = function (editor) {
10567      var registry = create$1();
10568      setup$1(editor, registry);
10569      var changes = setup(editor, registry);
10570      return {
10571        register: function (name, settings) {
10572          registry.register(name, settings);
10573        },
10574        annotate: function (name, data) {
10575          registry.lookup(name).each(function (settings) {
10576            annotateWithBookmark(editor, name, settings, data);
10577          });
10578        },
10579        annotationChanged: function (name, callback) {
10580          changes.addListener(name, callback);
10581        },
10582        remove: function (name) {
10583          identify(editor, Option.some(name)).each(function (_a) {
10584            var elements = _a.elements;
10585            each(elements, unwrap);
10586          });
10587        },
10588        getAll: function (name) {
10589          var directory = findAll(editor, name);
10590          return map$2(directory, function (elems) {
10591            return map(elems, function (elem) {
10592              return elem.dom();
10593            });
10594          });
10595        }
10596      };
10597    };
10598
10599    var whiteSpaceRegExp$3 = /^[ \t\r\n]*$/;
10600    var typeLookup = {
10601      '#text': 3,
10602      '#comment': 8,
10603      '#cdata': 4,
10604      '#pi': 7,
10605      '#doctype': 10,
10606      '#document-fragment': 11
10607    };
10608    var walk$2 = function (node, root, prev) {
10609      var sibling;
10610      var parent;
10611      var startName = prev ? 'lastChild' : 'firstChild';
10612      var siblingName = prev ? 'prev' : 'next';
10613      if (node[startName]) {
10614        return node[startName];
10615      }
10616      if (node !== root) {
10617        sibling = node[siblingName];
10618        if (sibling) {
10619          return sibling;
10620        }
10621        for (parent = node.parent; parent && parent !== root; parent = parent.parent) {
10622          sibling = parent[siblingName];
10623          if (sibling) {
10624            return sibling;
10625          }
10626        }
10627      }
10628    };
10629    var Node$1 = function () {
10630      function Node(name, type) {
10631        this.name = name;
10632        this.type = type;
10633        if (type === 1) {
10634          this.attributes = [];
10635          this.attributes.map = {};
10636        }
10637      }
10638      Node.create = function (name, attrs) {
10639        var node, attrName;
10640        node = new Node(name, typeLookup[name] || 1);
10641        if (attrs) {
10642          for (attrName in attrs) {
10643            node.attr(attrName, attrs[attrName]);
10644          }
10645        }
10646        return node;
10647      };
10648      Node.prototype.replace = function (node) {
10649        var self = this;
10650        if (node.parent) {
10651          node.remove();
10652        }
10653        self.insert(node, self);
10654        self.remove();
10655        return self;
10656      };
10657      Node.prototype.attr = function (name, value) {
10658        var self = this;
10659        var attrs, i;
10660        if (typeof name !== 'string') {
10661          for (i in name) {
10662            self.attr(i, name[i]);
10663          }
10664          return self;
10665        }
10666        if (attrs = self.attributes) {
10667          if (value !== undefined) {
10668            if (value === null) {
10669              if (name in attrs.map) {
10670                delete attrs.map[name];
10671                i = attrs.length;
10672                while (i--) {
10673                  if (attrs[i].name === name) {
10674                    attrs = attrs.splice(i, 1);
10675                    return self;
10676                  }
10677                }
10678              }
10679              return self;
10680            }
10681            if (name in attrs.map) {
10682              i = attrs.length;
10683              while (i--) {
10684                if (attrs[i].name === name) {
10685                  attrs[i].value = value;
10686                  break;
10687                }
10688              }
10689            } else {
10690              attrs.push({
10691                name: name,
10692                value: value
10693              });
10694            }
10695            attrs.map[name] = value;
10696            return self;
10697          }
10698          return attrs.map[name];
10699        }
10700      };
10701      Node.prototype.clone = function () {
10702        var self = this;
10703        var clone = new Node(self.name, self.type);
10704        var i, l, selfAttrs, selfAttr, cloneAttrs;
10705        if (selfAttrs = self.attributes) {
10706          cloneAttrs = [];
10707          cloneAttrs.map = {};
10708          for (i = 0, l = selfAttrs.length; i < l; i++) {
10709            selfAttr = selfAttrs[i];
10710            if (selfAttr.name !== 'id') {
10711              cloneAttrs[cloneAttrs.length] = {
10712                name: selfAttr.name,
10713                value: selfAttr.value
10714              };
10715              cloneAttrs.map[selfAttr.name] = selfAttr.value;
10716            }
10717          }
10718          clone.attributes = cloneAttrs;
10719        }
10720        clone.value = self.value;
10721        clone.shortEnded = self.shortEnded;
10722        return clone;
10723      };
10724      Node.prototype.wrap = function (wrapper) {
10725        var self = this;
10726        self.parent.insert(wrapper, self);
10727        wrapper.append(self);
10728        return self;
10729      };
10730      Node.prototype.unwrap = function () {
10731        var self = this;
10732        var node, next;
10733        for (node = self.firstChild; node;) {
10734          next = node.next;
10735          self.insert(node, self, true);
10736          node = next;
10737        }
10738        self.remove();
10739      };
10740      Node.prototype.remove = function () {
10741        var self = this, parent = self.parent, next = self.next, prev = self.prev;
10742        if (parent) {
10743          if (parent.firstChild === self) {
10744            parent.firstChild = next;
10745            if (next) {
10746              next.prev = null;
10747            }
10748          } else {
10749            prev.next = next;
10750          }
10751          if (parent.lastChild === self) {
10752            parent.lastChild = prev;
10753            if (prev) {
10754              prev.next = null;
10755            }
10756          } else {
10757            next.prev = prev;
10758          }
10759          self.parent = self.next = self.prev = null;
10760        }
10761        return self;
10762      };
10763      Node.prototype.append = function (node) {
10764        var self = this;
10765        var last;
10766        if (node.parent) {
10767          node.remove();
10768        }
10769        last = self.lastChild;
10770        if (last) {
10771          last.next = node;
10772          node.prev = last;
10773          self.lastChild = node;
10774        } else {
10775          self.lastChild = self.firstChild = node;
10776        }
10777        node.parent = self;
10778        return node;
10779      };
10780      Node.prototype.insert = function (node, refNode, before) {
10781        var parent;
10782        if (node.parent) {
10783          node.remove();
10784        }
10785        parent = refNode.parent || this;
10786        if (before) {
10787          if (refNode === parent.firstChild) {
10788            parent.firstChild = node;
10789          } else {
10790            refNode.prev.next = node;
10791          }
10792          node.prev = refNode.prev;
10793          node.next = refNode;
10794          refNode.prev = node;
10795        } else {
10796          if (refNode === parent.lastChild) {
10797            parent.lastChild = node;
10798          } else {
10799            refNode.next.prev = node;
10800          }
10801          node.next = refNode.next;
10802          node.prev = refNode;
10803          refNode.next = node;
10804        }
10805        node.parent = parent;
10806        return node;
10807      };
10808      Node.prototype.getAll = function (name) {
10809        var self = this;
10810        var node;
10811        var collection = [];
10812        for (node = self.firstChild; node; node = walk$2(node, self)) {
10813          if (node.name === name) {
10814            collection.push(node);
10815          }
10816        }
10817        return collection;
10818      };
10819      Node.prototype.empty = function () {
10820        var self = this;
10821        var nodes, i, node;
10822        if (self.firstChild) {
10823          nodes = [];
10824          for (node = self.firstChild; node; node = walk$2(node, self)) {
10825            nodes.push(node);
10826          }
10827          i = nodes.length;
10828          while (i--) {
10829            node = nodes[i];
10830            node.parent = node.firstChild = node.lastChild = node.next = node.prev = null;
10831          }
10832        }
10833        self.firstChild = self.lastChild = null;
10834        return self;
10835      };
10836      Node.prototype.isEmpty = function (elements, whitespace, predicate) {
10837        var self = this;
10838        var node = self.firstChild, i, name;
10839        whitespace = whitespace || {};
10840        if (node) {
10841          do {
10842            if (node.type === 1) {
10843              if (node.attr('data-mce-bogus')) {
10844                continue;
10845              }
10846              if (elements[node.name]) {
10847                return false;
10848              }
10849              i = node.attributes.length;
10850              while (i--) {
10851                name = node.attributes[i].name;
10852                if (name === 'name' || name.indexOf('data-mce-bookmark') === 0) {
10853                  return false;
10854                }
10855              }
10856            }
10857            if (node.type === 8) {
10858              return false;
10859            }
10860            if (node.type === 3 && !whiteSpaceRegExp$3.test(node.value)) {
10861              return false;
10862            }
10863            if (node.type === 3 && node.parent && whitespace[node.parent.name] && whiteSpaceRegExp$3.test(node.value)) {
10864              return false;
10865            }
10866            if (predicate && predicate(node)) {
10867              return false;
10868            }
10869          } while (node = walk$2(node, self));
10870        }
10871        return true;
10872      };
10873      Node.prototype.walk = function (prev) {
10874        return walk$2(this, null, prev);
10875      };
10876      return Node;
10877    }();
10878
10879    var isValidPrefixAttrName = function (name) {
10880      return name.indexOf('data-') === 0 || name.indexOf('aria-') === 0;
10881    };
10882    var trimComments = function (text) {
10883      return text.replace(/<!--|-->/g, '');
10884    };
10885    var isInvalidUri = function (settings, uri) {
10886      if (settings.allow_html_data_urls) {
10887        return false;
10888      } else if (/^data:image\//i.test(uri)) {
10889        return settings.allow_svg_data_urls === false && /^data:image\/svg\+xml/i.test(uri);
10890      } else {
10891        return /^data:/i.test(uri);
10892      }
10893    };
10894    var findEndTagIndex = function (schema, html, startIndex) {
10895      var count = 1, index, matches, tokenRegExp, shortEndedElements;
10896      shortEndedElements = schema.getShortEndedElements();
10897      tokenRegExp = /<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g;
10898      tokenRegExp.lastIndex = index = startIndex;
10899      while (matches = tokenRegExp.exec(html)) {
10900        index = tokenRegExp.lastIndex;
10901        if (matches[1] === '/') {
10902          count--;
10903        } else if (!matches[1]) {
10904          if (matches[2] in shortEndedElements) {
10905            continue;
10906          }
10907          count++;
10908        }
10909        if (count === 0) {
10910          break;
10911        }
10912      }
10913      return index;
10914    };
10915    var checkBogusAttribute = function (regExp, attrString) {
10916      var matches = regExp.exec(attrString);
10917      if (matches) {
10918        var name = matches[1];
10919        var value = matches[2];
10920        return typeof name === 'string' && name.toLowerCase() === 'data-mce-bogus' ? value : null;
10921      } else {
10922        return null;
10923      }
10924    };
10925    function SaxParser(settings, schema) {
10926      if (schema === void 0) {
10927        schema = Schema();
10928      }
10929      var noop = function () {
10930      };
10931      settings = settings || {};
10932      if (settings.fix_self_closing !== false) {
10933        settings.fix_self_closing = true;
10934      }
10935      var comment = settings.comment ? settings.comment : noop;
10936      var cdata = settings.cdata ? settings.cdata : noop;
10937      var text = settings.text ? settings.text : noop;
10938      var start = settings.start ? settings.start : noop;
10939      var end = settings.end ? settings.end : noop;
10940      var pi = settings.pi ? settings.pi : noop;
10941      var doctype = settings.doctype ? settings.doctype : noop;
10942      var parse = function (html) {
10943        var matches, index = 0, value, endRegExp;
10944        var stack = [];
10945        var attrList, i, textData, name;
10946        var isInternalElement, removeInternalElements, shortEndedElements, fillAttrsMap, isShortEnded;
10947        var validate, elementRule, isValidElement, attr, attribsValue, validAttributesMap, validAttributePatterns;
10948        var attributesRequired, attributesDefault, attributesForced, processHtml;
10949        var anyAttributesRequired, selfClosing, tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0;
10950        var decode = Entities.decode;
10951        var fixSelfClosing;
10952        var filteredUrlAttrs = Tools.makeMap('src,href,data,background,formaction,poster,xlink:href');
10953        var scriptUriRegExp = /((java|vb)script|mhtml):/i;
10954        var processEndTag = function (name) {
10955          var pos, i;
10956          pos = stack.length;
10957          while (pos--) {
10958            if (stack[pos].name === name) {
10959              break;
10960            }
10961          }
10962          if (pos >= 0) {
10963            for (i = stack.length - 1; i >= pos; i--) {
10964              name = stack[i];
10965              if (name.valid) {
10966                end(name.name);
10967              }
10968            }
10969            stack.length = pos;
10970          }
10971        };
10972        var parseAttribute = function (match, name, value, val2, val3) {
10973          var attrRule, i;
10974          var trimRegExp = /[\s\u0000-\u001F]+/g;
10975          name = name.toLowerCase();
10976          value = name in fillAttrsMap ? name : decode(value || val2 || val3 || '');
10977          if (validate && !isInternalElement && isValidPrefixAttrName(name) === false) {
10978            attrRule = validAttributesMap[name];
10979            if (!attrRule && validAttributePatterns) {
10980              i = validAttributePatterns.length;
10981              while (i--) {
10982                attrRule = validAttributePatterns[i];
10983                if (attrRule.pattern.test(name)) {
10984                  break;
10985                }
10986              }
10987              if (i === -1) {
10988                attrRule = null;
10989              }
10990            }
10991            if (!attrRule) {
10992              return;
10993            }
10994            if (attrRule.validValues && !(value in attrRule.validValues)) {
10995              return;
10996            }
10997          }
10998          if (filteredUrlAttrs[name] && !settings.allow_script_urls) {
10999            var uri = value.replace(trimRegExp, '');
11000            try {
11001              uri = decodeURIComponent(uri);
11002            } catch (ex) {
11003              uri = unescape(uri);
11004            }
11005            if (scriptUriRegExp.test(uri)) {
11006              return;
11007            }
11008            if (isInvalidUri(settings, uri)) {
11009              return;
11010            }
11011          }
11012          if (isInternalElement && (name in filteredUrlAttrs || name.indexOf('on') === 0)) {
11013            return;
11014          }
11015          attrList.map[name] = value;
11016          attrList.push({
11017            name: name,
11018            value: value
11019          });
11020        };
11021        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');
11022        attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
11023        shortEndedElements = schema.getShortEndedElements();
11024        selfClosing = settings.self_closing_elements || schema.getSelfClosingElements();
11025        fillAttrsMap = schema.getBoolAttrs();
11026        validate = settings.validate;
11027        removeInternalElements = settings.remove_internals;
11028        fixSelfClosing = settings.fix_self_closing;
11029        specialElements = schema.getSpecialElements();
11030        processHtml = html + '>';
11031        while (matches = tokenRegExp.exec(processHtml)) {
11032          if (index < matches.index) {
11033            text(decode(html.substr(index, matches.index - index)));
11034          }
11035          if (value = matches[6]) {
11036            value = value.toLowerCase();
11037            if (value.charAt(0) === ':') {
11038              value = value.substr(1);
11039            }
11040            processEndTag(value);
11041          } else if (value = matches[7]) {
11042            if (matches.index + matches[0].length > html.length) {
11043              text(decode(html.substr(matches.index)));
11044              index = matches.index + matches[0].length;
11045              continue;
11046            }
11047            value = value.toLowerCase();
11048            if (value.charAt(0) === ':') {
11049              value = value.substr(1);
11050            }
11051            isShortEnded = value in shortEndedElements;
11052            if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value) {
11053              processEndTag(value);
11054            }
11055            var bogusValue = checkBogusAttribute(attrRegExp, matches[8]);
11056            if (bogusValue !== null) {
11057              if (bogusValue === 'all') {
11058                index = findEndTagIndex(schema, html, tokenRegExp.lastIndex);
11059                tokenRegExp.lastIndex = index;
11060                continue;
11061              }
11062              isValidElement = false;
11063            }
11064            if (!validate || (elementRule = schema.getElementRule(value))) {
11065              isValidElement = true;
11066              if (validate) {
11067                validAttributesMap = elementRule.attributes;
11068                validAttributePatterns = elementRule.attributePatterns;
11069              }
11070              if (attribsValue = matches[8]) {
11071                isInternalElement = attribsValue.indexOf('data-mce-type') !== -1;
11072                if (isInternalElement && removeInternalElements) {
11073                  isValidElement = false;
11074                }
11075                attrList = [];
11076                attrList.map = {};
11077                attribsValue.replace(attrRegExp, parseAttribute);
11078              } else {
11079                attrList = [];
11080                attrList.map = {};
11081              }
11082              if (validate && !isInternalElement) {
11083                attributesRequired = elementRule.attributesRequired;
11084                attributesDefault = elementRule.attributesDefault;
11085                attributesForced = elementRule.attributesForced;
11086                anyAttributesRequired = elementRule.removeEmptyAttrs;
11087                if (anyAttributesRequired && !attrList.length) {
11088                  isValidElement = false;
11089                }
11090                if (attributesForced) {
11091                  i = attributesForced.length;
11092                  while (i--) {
11093                    attr = attributesForced[i];
11094                    name = attr.name;
11095                    attrValue = attr.value;
11096                    if (attrValue === '{$uid}') {
11097                      attrValue = 'mce_' + idCount++;
11098                    }
11099                    attrList.map[name] = attrValue;
11100                    attrList.push({
11101                      name: name,
11102                      value: attrValue
11103                    });
11104                  }
11105                }
11106                if (attributesDefault) {
11107                  i = attributesDefault.length;
11108                  while (i--) {
11109                    attr = attributesDefault[i];
11110                    name = attr.name;
11111                    if (!(name in attrList.map)) {
11112                      attrValue = attr.value;
11113                      if (attrValue === '{$uid}') {
11114                        attrValue = 'mce_' + idCount++;
11115                      }
11116                      attrList.map[name] = attrValue;
11117                      attrList.push({
11118                        name: name,
11119                        value: attrValue
11120                      });
11121                    }
11122                  }
11123                }
11124                if (attributesRequired) {
11125                  i = attributesRequired.length;
11126                  while (i--) {
11127                    if (attributesRequired[i] in attrList.map) {
11128                      break;
11129                    }
11130                  }
11131                  if (i === -1) {
11132                    isValidElement = false;
11133                  }
11134                }
11135                if (attr = attrList.map['data-mce-bogus']) {
11136                  if (attr === 'all') {
11137                    index = findEndTagIndex(schema, html, tokenRegExp.lastIndex);
11138                    tokenRegExp.lastIndex = index;
11139                    continue;
11140                  }
11141                  isValidElement = false;
11142                }
11143              }
11144              if (isValidElement) {
11145                start(value, attrList, isShortEnded);
11146              }
11147            } else {
11148              isValidElement = false;
11149            }
11150            if (endRegExp = specialElements[value]) {
11151              endRegExp.lastIndex = index = matches.index + matches[0].length;
11152              if (matches = endRegExp.exec(html)) {
11153                if (isValidElement) {
11154                  textData = html.substr(index, matches.index - index);
11155                }
11156                index = matches.index + matches[0].length;
11157              } else {
11158                textData = html.substr(index);
11159                index = html.length;
11160              }
11161              if (isValidElement) {
11162                if (textData.length > 0) {
11163                  text(textData, true);
11164                }
11165                end(value);
11166              }
11167              tokenRegExp.lastIndex = index;
11168              continue;
11169            }
11170            if (!isShortEnded) {
11171              if (!attribsValue || attribsValue.indexOf('/') !== attribsValue.length - 1) {
11172                stack.push({
11173                  name: value,
11174                  valid: isValidElement
11175                });
11176              } else if (isValidElement) {
11177                end(value);
11178              }
11179            }
11180          } else if (value = matches[1]) {
11181            if (value.charAt(0) === '>') {
11182              value = ' ' + value;
11183            }
11184            if (!settings.allow_conditional_comments && value.substr(0, 3).toLowerCase() === '[if') {
11185              value = ' ' + value;
11186            }
11187            comment(value);
11188          } else if (value = matches[2]) {
11189            cdata(trimComments(value));
11190          } else if (value = matches[3]) {
11191            doctype(value);
11192          } else if (value = matches[4]) {
11193            pi(value, matches[5]);
11194          }
11195          index = matches.index + matches[0].length;
11196        }
11197        if (index < html.length) {
11198          text(decode(html.substr(index)));
11199        }
11200        for (i = stack.length - 1; i >= 0; i--) {
11201          value = stack[i];
11202          if (value.valid) {
11203            end(value.name);
11204          }
11205        }
11206      };
11207      return { parse: parse };
11208    }
11209    (function (SaxParser) {
11210      SaxParser.findEndTag = findEndTagIndex;
11211    }(SaxParser || (SaxParser = {})));
11212    var SaxParser$1 = SaxParser;
11213
11214    var trimHtml = function (tempAttrs, html) {
11215      var trimContentRegExp = new RegExp(['\\s?(' + tempAttrs.join('|') + ')="[^"]+"'].join('|'), 'gi');
11216      return html.replace(trimContentRegExp, '');
11217    };
11218    var trimInternal = function (serializer, html) {
11219      var content = html;
11220      var bogusAllRegExp = /<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g;
11221      var endTagIndex, index, matchLength, matches, shortEndedElements;
11222      var schema = serializer.schema;
11223      content = trimHtml(serializer.getTempAttrs(), content);
11224      shortEndedElements = schema.getShortEndedElements();
11225      while (matches = bogusAllRegExp.exec(content)) {
11226        index = bogusAllRegExp.lastIndex;
11227        matchLength = matches[0].length;
11228        if (shortEndedElements[matches[1]]) {
11229          endTagIndex = index;
11230        } else {
11231          endTagIndex = SaxParser$1.findEndTag(schema, content, index);
11232        }
11233        content = content.substring(0, index - matchLength) + content.substring(endTagIndex);
11234        bogusAllRegExp.lastIndex = index - matchLength;
11235      }
11236      return Zwsp.trim(content);
11237    };
11238    var trimExternal = trimInternal;
11239    var TrimHtml = {
11240      trimExternal: trimExternal,
11241      trimInternal: trimInternal
11242    };
11243
11244    var getBodySetting = function (editor, name, defaultValue) {
11245      var value = editor.getParam(name, defaultValue);
11246      if (value.indexOf('=') !== -1) {
11247        var bodyObj = editor.getParam(name, '', 'hash');
11248        return bodyObj.hasOwnProperty(editor.id) ? bodyObj[editor.id] : defaultValue;
11249      } else {
11250        return value;
11251      }
11252    };
11253    var getIframeAttrs = function (editor) {
11254      return editor.getParam('iframe_attrs', {});
11255    };
11256    var getDocType = function (editor) {
11257      return editor.getParam('doctype', '<!DOCTYPE html>');
11258    };
11259    var getDocumentBaseUrl = function (editor) {
11260      return editor.getParam('document_base_url', '');
11261    };
11262    var getBodyId = function (editor) {
11263      return getBodySetting(editor, 'body_id', 'tinymce');
11264    };
11265    var getBodyClass = function (editor) {
11266      return getBodySetting(editor, 'body_class', '');
11267    };
11268    var getContentSecurityPolicy = function (editor) {
11269      return editor.getParam('content_security_policy', '');
11270    };
11271    var shouldPutBrInPre = function (editor) {
11272      return editor.getParam('br_in_pre', true);
11273    };
11274    var getForcedRootBlock = function (editor) {
11275      if (editor.getParam('force_p_newlines', false)) {
11276        return 'p';
11277      }
11278      var block = editor.getParam('forced_root_block', 'p');
11279      if (block === false) {
11280        return '';
11281      } else if (block === true) {
11282        return 'p';
11283      } else {
11284        return block;
11285      }
11286    };
11287    var getForcedRootBlockAttrs = function (editor) {
11288      return editor.getParam('forced_root_block_attrs', {});
11289    };
11290    var getBrNewLineSelector = function (editor) {
11291      return editor.getParam('br_newline_selector', '.mce-toc h2,figcaption,caption');
11292    };
11293    var getNoNewLineSelector = function (editor) {
11294      return editor.getParam('no_newline_selector', '');
11295    };
11296    var shouldKeepStyles = function (editor) {
11297      return editor.getParam('keep_styles', true);
11298    };
11299    var shouldEndContainerOnEmptyBlock = function (editor) {
11300      return editor.getParam('end_container_on_empty_block', false);
11301    };
11302    var getFontStyleValues = function (editor) {
11303      return Tools.explode(editor.getParam('font_size_style_values', ''));
11304    };
11305    var getFontSizeClasses = function (editor) {
11306      return Tools.explode(editor.getParam('font_size_classes', ''));
11307    };
11308    var getImagesDataImgFilter = function (editor) {
11309      return editor.getParam('images_dataimg_filter', constant(true), 'function');
11310    };
11311    var isAutomaticUploadsEnabled = function (editor) {
11312      return editor.getParam('automatic_uploads', true, 'boolean');
11313    };
11314    var shouldReuseFileName = function (editor) {
11315      return editor.getParam('images_reuse_filename', false, 'boolean');
11316    };
11317    var shouldReplaceBlobUris = function (editor) {
11318      return editor.getParam('images_replace_blob_uris', true, 'boolean');
11319    };
11320    var getImageUploadUrl = function (editor) {
11321      return editor.getParam('images_upload_url', '', 'string');
11322    };
11323    var getImageUploadBasePath = function (editor) {
11324      return editor.getParam('images_upload_base_path', '', 'string');
11325    };
11326    var getImagesUploadCredentials = function (editor) {
11327      return editor.getParam('images_upload_credentials', false, 'boolean');
11328    };
11329    var getImagesUploadHandler = function (editor) {
11330      return editor.getParam('images_upload_handler', null, 'function');
11331    };
11332    var shouldUseContentCssCors = function (editor) {
11333      return editor.getParam('content_css_cors', false, 'boolean');
11334    };
11335    var getLanguageCode = function (editor) {
11336      return editor.getParam('language', 'en', 'string');
11337    };
11338    var getLanguageUrl = function (editor) {
11339      return editor.getParam('language_url', '', 'string');
11340    };
11341    var shouldIndentUseMargin = function (editor) {
11342      return editor.getParam('indent_use_margin', false);
11343    };
11344    var getIndentation = function (editor) {
11345      return editor.getParam('indentation', '40px', 'string');
11346    };
11347    var getContentCss = function (editor) {
11348      var contentCss = editor.settings.content_css;
11349      if (isString(contentCss)) {
11350        return map(contentCss.split(','), trim$2);
11351      } else if (isArray(contentCss)) {
11352        return contentCss;
11353      } else if (contentCss === false || editor.inline) {
11354        return [];
11355      } else {
11356        return ['default'];
11357      }
11358    };
11359    var Settings = {
11360      getIframeAttrs: getIframeAttrs,
11361      getDocType: getDocType,
11362      getDocumentBaseUrl: getDocumentBaseUrl,
11363      getBodyId: getBodyId,
11364      getBodyClass: getBodyClass,
11365      getContentSecurityPolicy: getContentSecurityPolicy,
11366      shouldPutBrInPre: shouldPutBrInPre,
11367      getForcedRootBlock: getForcedRootBlock,
11368      getForcedRootBlockAttrs: getForcedRootBlockAttrs,
11369      getBrNewLineSelector: getBrNewLineSelector,
11370      getNoNewLineSelector: getNoNewLineSelector,
11371      shouldKeepStyles: shouldKeepStyles,
11372      shouldEndContainerOnEmptyBlock: shouldEndContainerOnEmptyBlock,
11373      getFontStyleValues: getFontStyleValues,
11374      getFontSizeClasses: getFontSizeClasses,
11375      getImagesDataImgFilter: getImagesDataImgFilter,
11376      isAutomaticUploadsEnabled: isAutomaticUploadsEnabled,
11377      shouldReuseFileName: shouldReuseFileName,
11378      shouldReplaceBlobUris: shouldReplaceBlobUris,
11379      getImageUploadUrl: getImageUploadUrl,
11380      getImageUploadBasePath: getImageUploadBasePath,
11381      getImagesUploadCredentials: getImagesUploadCredentials,
11382      getImagesUploadHandler: getImagesUploadHandler,
11383      shouldUseContentCssCors: shouldUseContentCssCors,
11384      getLanguageCode: getLanguageCode,
11385      getLanguageUrl: getLanguageUrl,
11386      shouldIndentUseMargin: shouldIndentUseMargin,
11387      getIndentation: getIndentation,
11388      getContentCss: getContentCss
11389    };
11390
11391    var defaultFormat = 'html';
11392    var trimEmptyContents = function (editor, html) {
11393      var blockName = Settings.getForcedRootBlock(editor);
11394      var emptyRegExp = new RegExp('^(<' + blockName + '[^>]*>(&nbsp;|&#160;|\\s|\xA0|<br \\/>|)<\\/' + blockName + '>[\r\n]*|<br \\/>[\r\n]*)$');
11395      return html.replace(emptyRegExp, '');
11396    };
11397    var getContentFromBody = function (editor, args, body) {
11398      var content;
11399      args.format = args.format ? args.format : defaultFormat;
11400      args.get = true;
11401      args.getInner = true;
11402      if (!args.no_events) {
11403        editor.fire('BeforeGetContent', args);
11404      }
11405      if (args.format === 'raw') {
11406        content = Tools.trim(TrimHtml.trimExternal(editor.serializer, body.innerHTML));
11407      } else if (args.format === 'text') {
11408        content = Zwsp.trim(body.innerText || body.textContent);
11409      } else if (args.format === 'tree') {
11410        return editor.serializer.serialize(body, args);
11411      } else {
11412        content = trimEmptyContents(editor, editor.serializer.serialize(body, args));
11413      }
11414      if (args.format !== 'text' && !isWsPreserveElement(Element.fromDom(body))) {
11415        args.content = Tools.trim(content);
11416      } else {
11417        args.content = content;
11418      }
11419      if (!args.no_events) {
11420        editor.fire('GetContent', args);
11421      }
11422      return args.content;
11423    };
11424    var getContent = function (editor, args) {
11425      if (args === void 0) {
11426        args = {};
11427      }
11428      return Option.from(editor.getBody()).fold(constant(args.format === 'tree' ? new Node$1('body', 11) : ''), function (body) {
11429        return getContentFromBody(editor, args, body);
11430      });
11431    };
11432
11433    var makeMap$3 = Tools.makeMap;
11434    var Writer = function (settings) {
11435      var html = [];
11436      var indent, indentBefore, indentAfter, encode, htmlOutput;
11437      settings = settings || {};
11438      indent = settings.indent;
11439      indentBefore = makeMap$3(settings.indent_before || '');
11440      indentAfter = makeMap$3(settings.indent_after || '');
11441      encode = Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities);
11442      htmlOutput = settings.element_format === 'html';
11443      return {
11444        start: function (name, attrs, empty) {
11445          var i, l, attr, value;
11446          if (indent && indentBefore[name] && html.length > 0) {
11447            value = html[html.length - 1];
11448            if (value.length > 0 && value !== '\n') {
11449              html.push('\n');
11450            }
11451          }
11452          html.push('<', name);
11453          if (attrs) {
11454            for (i = 0, l = attrs.length; i < l; i++) {
11455              attr = attrs[i];
11456              html.push(' ', attr.name, '="', encode(attr.value, true), '"');
11457            }
11458          }
11459          if (!empty || htmlOutput) {
11460            html[html.length] = '>';
11461          } else {
11462            html[html.length] = ' />';
11463          }
11464          if (empty && indent && indentAfter[name] && html.length > 0) {
11465            value = html[html.length - 1];
11466            if (value.length > 0 && value !== '\n') {
11467              html.push('\n');
11468            }
11469          }
11470        },
11471        end: function (name) {
11472          var value;
11473          html.push('</', name, '>');
11474          if (indent && indentAfter[name] && html.length > 0) {
11475            value = html[html.length - 1];
11476            if (value.length > 0 && value !== '\n') {
11477              html.push('\n');
11478            }
11479          }
11480        },
11481        text: function (text, raw) {
11482          if (text.length > 0) {
11483            html[html.length] = raw ? text : encode(text);
11484          }
11485        },
11486        cdata: function (text) {
11487          html.push('<![CDATA[', text, ']]>');
11488        },
11489        comment: function (text) {
11490          html.push('<!--', text, '-->');
11491        },
11492        pi: function (name, text) {
11493          if (text) {
11494            html.push('<?', name, ' ', encode(text), '?>');
11495          } else {
11496            html.push('<?', name, '?>');
11497          }
11498          if (indent) {
11499            html.push('\n');
11500          }
11501        },
11502        doctype: function (text) {
11503          html.push('<!DOCTYPE', text, '>', indent ? '\n' : '');
11504        },
11505        reset: function () {
11506          html.length = 0;
11507        },
11508        getContent: function () {
11509          return html.join('').replace(/\n$/, '');
11510        }
11511      };
11512    };
11513
11514    var Serializer = function (settings, schema) {
11515      if (schema === void 0) {
11516        schema = Schema();
11517      }
11518      var writer = Writer(settings);
11519      settings = settings || {};
11520      settings.validate = 'validate' in settings ? settings.validate : true;
11521      var serialize = function (node) {
11522        var handlers, validate;
11523        validate = settings.validate;
11524        handlers = {
11525          3: function (node) {
11526            writer.text(node.value, node.raw);
11527          },
11528          8: function (node) {
11529            writer.comment(node.value);
11530          },
11531          7: function (node) {
11532            writer.pi(node.name, node.value);
11533          },
11534          10: function (node) {
11535            writer.doctype(node.value);
11536          },
11537          4: function (node) {
11538            writer.cdata(node.value);
11539          },
11540          11: function (node) {
11541            if (node = node.firstChild) {
11542              do {
11543                walk(node);
11544              } while (node = node.next);
11545            }
11546          }
11547        };
11548        writer.reset();
11549        var walk = function (node) {
11550          var handler = handlers[node.type];
11551          var name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule;
11552          if (!handler) {
11553            name = node.name;
11554            isEmpty = node.shortEnded;
11555            attrs = node.attributes;
11556            if (validate && attrs && attrs.length > 1) {
11557              sortedAttrs = [];
11558              sortedAttrs.map = {};
11559              elementRule = schema.getElementRule(node.name);
11560              if (elementRule) {
11561                for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) {
11562                  attrName = elementRule.attributesOrder[i];
11563                  if (attrName in attrs.map) {
11564                    attrValue = attrs.map[attrName];
11565                    sortedAttrs.map[attrName] = attrValue;
11566                    sortedAttrs.push({
11567                      name: attrName,
11568                      value: attrValue
11569                    });
11570                  }
11571                }
11572                for (i = 0, l = attrs.length; i < l; i++) {
11573                  attrName = attrs[i].name;
11574                  if (!(attrName in sortedAttrs.map)) {
11575                    attrValue = attrs.map[attrName];
11576                    sortedAttrs.map[attrName] = attrValue;
11577                    sortedAttrs.push({
11578                      name: attrName,
11579                      value: attrValue
11580                    });
11581                  }
11582                }
11583                attrs = sortedAttrs;
11584              }
11585            }
11586            writer.start(node.name, attrs, isEmpty);
11587            if (!isEmpty) {
11588              if (node = node.firstChild) {
11589                do {
11590                  walk(node);
11591                } while (node = node.next);
11592              }
11593              writer.end(name);
11594            }
11595          } else {
11596            handler(node);
11597          }
11598        };
11599        if (node.type === 1 && !settings.inner) {
11600          walk(node);
11601        } else {
11602          handlers[11](node);
11603        }
11604        return writer.getContent();
11605      };
11606      return { serialize: serialize };
11607    };
11608
11609    var traverse = function (node, fn) {
11610      fn(node);
11611      if (node.firstChild) {
11612        traverse(node.firstChild, fn);
11613      }
11614      if (node.next) {
11615        traverse(node.next, fn);
11616      }
11617    };
11618    var findMatchingNodes = function (nodeFilters, attributeFilters, node) {
11619      var nodeMatches = {};
11620      var attrMatches = {};
11621      var matches = [];
11622      if (node.firstChild) {
11623        traverse(node.firstChild, function (node) {
11624          each(nodeFilters, function (filter) {
11625            if (filter.name === node.name) {
11626              if (nodeMatches[filter.name]) {
11627                nodeMatches[filter.name].nodes.push(node);
11628              } else {
11629                nodeMatches[filter.name] = {
11630                  filter: filter,
11631                  nodes: [node]
11632                };
11633              }
11634            }
11635          });
11636          each(attributeFilters, function (filter) {
11637            if (typeof node.attr(filter.name) === 'string') {
11638              if (attrMatches[filter.name]) {
11639                attrMatches[filter.name].nodes.push(node);
11640              } else {
11641                attrMatches[filter.name] = {
11642                  filter: filter,
11643                  nodes: [node]
11644                };
11645              }
11646            }
11647          });
11648        });
11649      }
11650      for (var name in nodeMatches) {
11651        if (nodeMatches.hasOwnProperty(name)) {
11652          matches.push(nodeMatches[name]);
11653        }
11654      }
11655      for (var name in attrMatches) {
11656        if (attrMatches.hasOwnProperty(name)) {
11657          matches.push(attrMatches[name]);
11658        }
11659      }
11660      return matches;
11661    };
11662    var filter$2 = function (nodeFilters, attributeFilters, node) {
11663      var matches = findMatchingNodes(nodeFilters, attributeFilters, node);
11664      each(matches, function (match) {
11665        each(match.filter.callbacks, function (callback) {
11666          callback(match.nodes, match.filter.name, {});
11667        });
11668      });
11669    };
11670
11671    var hasFocus = function (element) {
11672      var doc = owner(element).dom();
11673      return element.dom() === doc.activeElement;
11674    };
11675    var active = function (_DOC) {
11676      var doc = _DOC !== undefined ? _DOC.dom() : domGlobals.document;
11677      return Option.from(doc.activeElement).map(Element.fromDom);
11678    };
11679    var search = function (element) {
11680      return active(owner(element)).filter(function (e) {
11681        return element.dom().contains(e.dom());
11682      });
11683    };
11684
11685    var generate$1 = function (cases) {
11686      if (!isArray(cases)) {
11687        throw new Error('cases must be an array');
11688      }
11689      if (cases.length === 0) {
11690        throw new Error('there must be at least one case');
11691      }
11692      var constructors = [];
11693      var adt = {};
11694      each(cases, function (acase, count) {
11695        var keys$1 = keys(acase);
11696        if (keys$1.length !== 1) {
11697          throw new Error('one and only one name per case');
11698        }
11699        var key = keys$1[0];
11700        var value = acase[key];
11701        if (adt[key] !== undefined) {
11702          throw new Error('duplicate key detected:' + key);
11703        } else if (key === 'cata') {
11704          throw new Error('cannot have a case named cata (sorry)');
11705        } else if (!isArray(value)) {
11706          throw new Error('case arguments must be an array');
11707        }
11708        constructors.push(key);
11709        adt[key] = function () {
11710          var argLength = arguments.length;
11711          if (argLength !== value.length) {
11712            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
11713          }
11714          var args = new Array(argLength);
11715          for (var i = 0; i < args.length; i++)
11716            args[i] = arguments[i];
11717          var match = function (branches) {
11718            var branchKeys = keys(branches);
11719            if (constructors.length !== branchKeys.length) {
11720              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
11721            }
11722            var allReqd = forall(constructors, function (reqKey) {
11723              return contains(branchKeys, reqKey);
11724            });
11725            if (!allReqd)
11726              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
11727            return branches[key].apply(null, args);
11728          };
11729          return {
11730            fold: function () {
11731              if (arguments.length !== cases.length) {
11732                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + arguments.length);
11733              }
11734              var target = arguments[count];
11735              return target.apply(null, args);
11736            },
11737            match: match,
11738            log: function (label) {
11739              domGlobals.console.log(label, {
11740                constructors: constructors,
11741                constructor: key,
11742                params: args
11743              });
11744            }
11745          };
11746        };
11747      });
11748      return adt;
11749    };
11750    var Adt = { generate: generate$1 };
11751
11752    var adt = Adt.generate([
11753      { before: ['element'] },
11754      {
11755        on: [
11756          'element',
11757          'offset'
11758        ]
11759      },
11760      { after: ['element'] }
11761    ]);
11762
11763    var type$1 = Adt.generate([
11764      { domRange: ['rng'] },
11765      {
11766        relative: [
11767          'startSitu',
11768          'finishSitu'
11769        ]
11770      },
11771      {
11772        exact: [
11773          'start',
11774          'soffset',
11775          'finish',
11776          'foffset'
11777        ]
11778      }
11779    ]);
11780    var range$1 = Immutable('start', 'soffset', 'finish', 'foffset');
11781
11782    var browser$3 = PlatformDetection$1.detect().browser;
11783    var clamp = function (offset, element) {
11784      var max = isText(element) ? get$5(element).length : children(element).length + 1;
11785      if (offset > max) {
11786        return max;
11787      } else if (offset < 0) {
11788        return 0;
11789      }
11790      return offset;
11791    };
11792    var normalizeRng = function (rng) {
11793      return range$1(rng.start(), clamp(rng.soffset(), rng.start()), rng.finish(), clamp(rng.foffset(), rng.finish()));
11794    };
11795    var isOrContains = function (root, elm) {
11796      return contains$3(root, elm) || eq(root, elm);
11797    };
11798    var isRngInRoot = function (root) {
11799      return function (rng) {
11800        return isOrContains(root, rng.start()) && isOrContains(root, rng.finish());
11801      };
11802    };
11803    var shouldStore = function (editor) {
11804      return editor.inline === true || browser$3.isIE();
11805    };
11806    var nativeRangeToSelectionRange = function (r) {
11807      return range$1(Element.fromDom(r.startContainer), r.startOffset, Element.fromDom(r.endContainer), r.endOffset);
11808    };
11809    var readRange = function (win) {
11810      var selection = win.getSelection();
11811      var rng = !selection || selection.rangeCount === 0 ? Option.none() : Option.from(selection.getRangeAt(0));
11812      return rng.map(nativeRangeToSelectionRange);
11813    };
11814    var getBookmark$2 = function (root) {
11815      var win = defaultView(root);
11816      return readRange(win.dom()).filter(isRngInRoot(root));
11817    };
11818    var validate = function (root, bookmark) {
11819      return Option.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng);
11820    };
11821    var bookmarkToNativeRng = function (bookmark) {
11822      var rng = domGlobals.document.createRange();
11823      try {
11824        rng.setStart(bookmark.start().dom(), bookmark.soffset());
11825        rng.setEnd(bookmark.finish().dom(), bookmark.foffset());
11826        return Option.some(rng);
11827      } catch (_) {
11828        return Option.none();
11829      }
11830    };
11831    var store = function (editor) {
11832      var newBookmark = shouldStore(editor) ? getBookmark$2(Element.fromDom(editor.getBody())) : Option.none();
11833      editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
11834    };
11835    var storeNative = function (editor, rng) {
11836      var root = Element.fromDom(editor.getBody());
11837      var range = shouldStore(editor) ? Option.from(rng) : Option.none();
11838      var newBookmark = range.map(nativeRangeToSelectionRange).filter(isRngInRoot(root));
11839      editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
11840    };
11841    var getRng = function (editor) {
11842      var bookmark = editor.bookmark ? editor.bookmark : Option.none();
11843      return bookmark.bind(curry(validate, Element.fromDom(editor.getBody()))).bind(bookmarkToNativeRng);
11844    };
11845    var restore = function (editor) {
11846      getRng(editor).each(function (rng) {
11847        editor.selection.setRng(rng);
11848      });
11849    };
11850    var SelectionBookmark = {
11851      store: store,
11852      storeNative: storeNative,
11853      readRange: readRange,
11854      restore: restore,
11855      getRng: getRng,
11856      getBookmark: getBookmark$2,
11857      validate: validate
11858    };
11859
11860    var getContentEditableHost = function (editor, node) {
11861      return editor.dom.getParent(node, function (node) {
11862        return editor.dom.getContentEditable(node) === 'true';
11863      });
11864    };
11865    var getCollapsedNode = function (rng) {
11866      return rng.collapsed ? Option.from(getNode(rng.startContainer, rng.startOffset)).map(Element.fromDom) : Option.none();
11867    };
11868    var getFocusInElement = function (root, rng) {
11869      return getCollapsedNode(rng).bind(function (node) {
11870        if (isTableSection(node)) {
11871          return Option.some(node);
11872        } else if (contains$3(root, node) === false) {
11873          return Option.some(root);
11874        } else {
11875          return Option.none();
11876        }
11877      });
11878    };
11879    var normalizeSelection = function (editor, rng) {
11880      getFocusInElement(Element.fromDom(editor.getBody()), rng).bind(function (elm) {
11881        return CaretFinder.firstPositionIn(elm.dom());
11882      }).fold(function () {
11883        editor.selection.normalize();
11884        return;
11885      }, function (caretPos) {
11886        return editor.selection.setRng(caretPos.toRange());
11887      });
11888    };
11889    var focusBody = function (body) {
11890      if (body.setActive) {
11891        try {
11892          body.setActive();
11893        } catch (ex) {
11894          body.focus();
11895        }
11896      } else {
11897        body.focus();
11898      }
11899    };
11900    var hasElementFocus = function (elm) {
11901      return hasFocus(elm) || search(elm).isSome();
11902    };
11903    var hasIframeFocus = function (editor) {
11904      return editor.iframeElement && hasFocus(Element.fromDom(editor.iframeElement));
11905    };
11906    var hasInlineFocus = function (editor) {
11907      var rawBody = editor.getBody();
11908      return rawBody && hasElementFocus(Element.fromDom(rawBody));
11909    };
11910    var hasFocus$1 = function (editor) {
11911      return editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor);
11912    };
11913    var focusEditor = function (editor) {
11914      var selection = editor.selection;
11915      var body = editor.getBody();
11916      var rng = selection.getRng();
11917      editor.quirks.refreshContentEditable();
11918      var contentEditableHost = getContentEditableHost(editor, selection.getNode());
11919      if (editor.$.contains(body, contentEditableHost)) {
11920        focusBody(contentEditableHost);
11921        normalizeSelection(editor, rng);
11922        activateEditor(editor);
11923        return;
11924      }
11925      if (editor.bookmark !== undefined && hasFocus$1(editor) === false) {
11926        SelectionBookmark.getRng(editor).each(function (bookmarkRng) {
11927          editor.selection.setRng(bookmarkRng);
11928          rng = bookmarkRng;
11929        });
11930      }
11931      if (!editor.inline) {
11932        if (!Env.opera) {
11933          focusBody(body);
11934        }
11935        editor.getWin().focus();
11936      }
11937      if (Env.gecko || editor.inline) {
11938        focusBody(body);
11939        normalizeSelection(editor, rng);
11940      }
11941      activateEditor(editor);
11942    };
11943    var activateEditor = function (editor) {
11944      return editor.editorManager.setActive(editor);
11945    };
11946    var focus = function (editor, skipFocus) {
11947      if (editor.removed) {
11948        return;
11949      }
11950      skipFocus ? activateEditor(editor) : focusEditor(editor);
11951    };
11952    var EditorFocus = {
11953      focus: focus,
11954      hasFocus: hasFocus$1
11955    };
11956
11957    var defaultFormat$1 = 'html';
11958    var isTreeNode = function (content) {
11959      return content instanceof Node$1;
11960    };
11961    var moveSelection = function (editor) {
11962      if (EditorFocus.hasFocus(editor)) {
11963        CaretFinder.firstPositionIn(editor.getBody()).each(function (pos) {
11964          var node = pos.getNode();
11965          var caretPos = NodeType.isTable(node) ? CaretFinder.firstPositionIn(node).getOr(pos) : pos;
11966          editor.selection.setRng(caretPos.toRange());
11967        });
11968      }
11969    };
11970    var setEditorHtml = function (editor, html) {
11971      editor.dom.setHTML(editor.getBody(), html);
11972      moveSelection(editor);
11973    };
11974    var setContentString = function (editor, body, content, args) {
11975      var forcedRootBlockName, padd;
11976      if (content.length === 0 || /^\s+$/.test(content)) {
11977        padd = '<br data-mce-bogus="1">';
11978        if (body.nodeName === 'TABLE') {
11979          content = '<tr><td>' + padd + '</td></tr>';
11980        } else if (/^(UL|OL)$/.test(body.nodeName)) {
11981          content = '<li>' + padd + '</li>';
11982        }
11983        forcedRootBlockName = Settings.getForcedRootBlock(editor);
11984        if (forcedRootBlockName && editor.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
11985          content = padd;
11986          content = editor.dom.createHTML(forcedRootBlockName, editor.settings.forced_root_block_attrs, content);
11987        } else if (!content) {
11988          content = '<br data-mce-bogus="1">';
11989        }
11990        setEditorHtml(editor, content);
11991        editor.fire('SetContent', args);
11992      } else {
11993        if (args.format !== 'raw') {
11994          content = Serializer({ validate: editor.validate }, editor.schema).serialize(editor.parser.parse(content, {
11995            isRootContent: true,
11996            insert: true
11997          }));
11998        }
11999        args.content = isWsPreserveElement(Element.fromDom(body)) ? content : Tools.trim(content);
12000        setEditorHtml(editor, args.content);
12001        if (!args.no_events) {
12002          editor.fire('SetContent', args);
12003        }
12004      }
12005      return args.content;
12006    };
12007    var setContentTree = function (editor, body, content, args) {
12008      filter$2(editor.parser.getNodeFilters(), editor.parser.getAttributeFilters(), content);
12009      var html = Serializer({ validate: editor.validate }, editor.schema).serialize(content);
12010      args.content = isWsPreserveElement(Element.fromDom(body)) ? html : Tools.trim(html);
12011      setEditorHtml(editor, args.content);
12012      if (!args.no_events) {
12013        editor.fire('SetContent', args);
12014      }
12015      return content;
12016    };
12017    var setContent = function (editor, content, args) {
12018      if (args === void 0) {
12019        args = {};
12020      }
12021      args.format = args.format ? args.format : defaultFormat$1;
12022      args.set = true;
12023      args.content = isTreeNode(content) ? '' : content;
12024      if (!isTreeNode(content) && !args.no_events) {
12025        editor.fire('BeforeSetContent', args);
12026        content = args.content;
12027      }
12028      return Option.from(editor.getBody()).fold(constant(content), function (body) {
12029        return isTreeNode(content) ? setContentTree(editor, body, content, args) : setContentString(editor, body, content, args);
12030      });
12031    };
12032
12033    var firePreProcess = function (editor, args) {
12034      return editor.fire('PreProcess', args);
12035    };
12036    var firePostProcess = function (editor, args) {
12037      return editor.fire('PostProcess', args);
12038    };
12039    var fireRemove = function (editor) {
12040      return editor.fire('remove');
12041    };
12042    var fireDetach = function (editor) {
12043      return editor.fire('detach');
12044    };
12045    var fireSwitchMode = function (editor, mode) {
12046      return editor.fire('SwitchMode', { mode: mode });
12047    };
12048    var fireObjectResizeStart = function (editor, target, width, height) {
12049      editor.fire('ObjectResizeStart', {
12050        target: target,
12051        width: width,
12052        height: height
12053      });
12054    };
12055    var fireObjectResized = function (editor, target, width, height) {
12056      editor.fire('ObjectResized', {
12057        target: target,
12058        width: width,
12059        height: height
12060      });
12061    };
12062    var Events = {
12063      firePreProcess: firePreProcess,
12064      firePostProcess: firePostProcess,
12065      fireRemove: fireRemove,
12066      fireDetach: fireDetach,
12067      fireSwitchMode: fireSwitchMode,
12068      fireObjectResizeStart: fireObjectResizeStart,
12069      fireObjectResized: fireObjectResized
12070    };
12071
12072    var DOM$1 = DOMUtils$1.DOM;
12073    var restoreOriginalStyles = function (editor) {
12074      DOM$1.setStyle(editor.id, 'display', editor.orgDisplay);
12075    };
12076    var safeDestroy = function (x) {
12077      return Option.from(x).each(function (x) {
12078        return x.destroy();
12079      });
12080    };
12081    var clearDomReferences = function (editor) {
12082      editor.contentAreaContainer = editor.formElement = editor.container = editor.editorContainer = null;
12083      editor.bodyElement = editor.contentDocument = editor.contentWindow = null;
12084      editor.iframeElement = editor.targetElm = null;
12085      if (editor.selection) {
12086        editor.selection = editor.selection.win = editor.selection.dom = editor.selection.dom.doc = null;
12087      }
12088    };
12089    var restoreForm = function (editor) {
12090      var form = editor.formElement;
12091      if (form) {
12092        if (form._mceOldSubmit) {
12093          form.submit = form._mceOldSubmit;
12094          form._mceOldSubmit = null;
12095        }
12096        DOM$1.unbind(form, 'submit reset', editor.formEventDelegate);
12097      }
12098    };
12099    var remove$6 = function (editor) {
12100      if (!editor.removed) {
12101        var _selectionOverrides = editor._selectionOverrides, editorUpload = editor.editorUpload;
12102        var body = editor.getBody();
12103        var element = editor.getElement();
12104        if (body) {
12105          editor.save({ is_removing: true });
12106        }
12107        editor.removed = true;
12108        editor.unbindAllNativeEvents();
12109        if (editor.hasHiddenInput && element) {
12110          DOM$1.remove(element.nextSibling);
12111        }
12112        Events.fireRemove(editor);
12113        editor.editorManager.remove(editor);
12114        if (!editor.inline && body) {
12115          restoreOriginalStyles(editor);
12116        }
12117        Events.fireDetach(editor);
12118        DOM$1.remove(editor.getContainer());
12119        safeDestroy(_selectionOverrides);
12120        safeDestroy(editorUpload);
12121        editor.destroy();
12122      }
12123    };
12124    var destroy = function (editor, automatic) {
12125      var selection = editor.selection, dom = editor.dom;
12126      if (editor.destroyed) {
12127        return;
12128      }
12129      if (!automatic && !editor.removed) {
12130        editor.remove();
12131        return;
12132      }
12133      if (!automatic) {
12134        editor.editorManager.off('beforeunload', editor._beforeUnload);
12135        if (editor.theme && editor.theme.destroy) {
12136          editor.theme.destroy();
12137        }
12138        safeDestroy(selection);
12139        safeDestroy(dom);
12140      }
12141      restoreForm(editor);
12142      clearDomReferences(editor);
12143      editor.destroyed = true;
12144    };
12145
12146    var sectionResult = Immutable('sections', 'settings');
12147    var detection = PlatformDetection$1.detect();
12148    var isTouch = detection.deviceType.isTouch();
12149    var isPhone = detection.deviceType.isPhone();
12150    var mobilePlugins = [
12151      'lists',
12152      'autolink',
12153      'autosave'
12154    ];
12155    var defaultMobileSettings = isPhone ? { theme: 'mobile' } : {};
12156    var normalizePlugins = function (plugins) {
12157      var pluginNames = isArray(plugins) ? plugins.join(' ') : plugins;
12158      var trimmedPlugins = map(isString(pluginNames) ? pluginNames.split(' ') : [], trim$2);
12159      return filter(trimmedPlugins, function (item) {
12160        return item.length > 0;
12161      });
12162    };
12163    var filterMobilePlugins = function (plugins) {
12164      return filter(plugins, curry(contains, mobilePlugins));
12165    };
12166    var extractSections = function (keys, settings) {
12167      var result = bifilter(settings, function (value, key) {
12168        return contains(keys, key);
12169      });
12170      return sectionResult(result.t, result.f);
12171    };
12172    var getSection = function (sectionResult, name, defaults) {
12173      var sections = sectionResult.sections();
12174      var sectionSettings = sections.hasOwnProperty(name) ? sections[name] : {};
12175      return Tools.extend({}, defaults, sectionSettings);
12176    };
12177    var hasSection = function (sectionResult, name) {
12178      return sectionResult.sections().hasOwnProperty(name);
12179    };
12180    var getDefaultSettings = function (id, documentBaseUrl, editor) {
12181      return {
12182        id: id,
12183        theme: 'silver',
12184        popup_css: '',
12185        plugins: '',
12186        document_base_url: documentBaseUrl,
12187        add_form_submit_trigger: true,
12188        submit_patch: true,
12189        add_unload_trigger: true,
12190        convert_urls: true,
12191        relative_urls: true,
12192        remove_script_host: true,
12193        object_resizing: true,
12194        doctype: '<!DOCTYPE html>',
12195        visual: true,
12196        font_size_style_values: 'xx-small,x-small,small,medium,large,x-large,xx-large',
12197        font_size_legacy_values: 'xx-small,small,medium,large,x-large,xx-large,300%',
12198        forced_root_block: 'p',
12199        hidden_input: true,
12200        render_ui: true,
12201        inline_styles: true,
12202        convert_fonts_to_spans: true,
12203        indent: true,
12204        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,f
12204igure,figcaption,option,optgroup,datalist',
12205        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',
12206        entity_encoding: 'named',
12207        url_converter: editor.convertURL,
12208        url_converter_scope: editor,
12209        ie7_compat: true
12210      };
12211    };
12212    var getExternalPlugins = function (overrideSettings, settings) {
12213      var userDefinedExternalPlugins = settings.external_plugins ? settings.external_plugins : {};
12214      if (overrideSettings && overrideSettings.external_plugins) {
12215        return Tools.extend({}, overrideSettings.external_plugins, userDefinedExternalPlugins);
12216      } else {
12217        return userDefinedExternalPlugins;
12218      }
12219    };
12220    var combinePlugins = function (forcedPlugins, plugins) {
12221      return [].concat(normalizePlugins(forcedPlugins)).concat(normalizePlugins(plugins));
12222    };
12223    var processPlugins = function (isTouchDevice, sectionResult, defaultOverrideSettings, settings) {
12224      var forcedPlugins = normalizePlugins(defaultOverrideSettings.forced_plugins);
12225      var plugins = normalizePlugins(settings.plugins);
12226      var platformPlugins = isTouchDevice && hasSection(sectionResult, 'mobile') ? filterMobilePlugins(plugins) : plugins;
12227      var combinedPlugins = combinePlugins(forcedPlugins, platformPlugins);
12228      return Tools.extend(settings, { plugins: combinedPlugins.join(' ') });
12229    };
12230    var isOnMobile = function (isTouchDevice, sectionResult) {
12231      var isInline = sectionResult.settings().inline;
12232      return isTouchDevice && !isInline;
12233    };
12234    var combineSettings = function (isTouchDevice, defaultSettings, defaultOverrideSettings, settings) {
12235      var sectionResult = extractSections(['mobile'], settings);
12236      var extendedSettings = Tools.extend(defaultSettings, defaultOverrideSettings, sectionResult.settings(), isOnMobile(isTouchDevice, sectionResult) ? getSection(sectionResult, 'mobile', defaultMobileSettings) : {}, {
12237        validate: true,
12238        external_plugins: getExternalPlugins(defaultOverrideSettings, sectionResult.settings())
12239      });
12240      return processPlugins(isTouchDevice, sectionResult, defaultOverrideSettings, extendedSettings);
12241    };
12242    var getEditorSettings = function (editor, id, documentBaseUrl, defaultOverrideSettings, settings) {
12243      var defaultSettings = getDefaultSettings(id, documentBaseUrl, editor);
12244      return combineSettings(isTouch, defaultSettings, defaultOverrideSettings, settings);
12245    };
12246    var getFiltered = function (predicate, editor, name) {
12247      return Option.from(editor.settings[name]).filter(predicate);
12248    };
12249    var getString = curry(getFiltered, isString);
12250    var getParamObject = function (value) {
12251      var output = {};
12252      if (typeof value === 'string') {
12253        each(value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(','), function (val) {
12254          var arr = val.split('=');
12255          if (arr.length > 1) {
12256            output[Tools.trim(arr[0])] = Tools.trim(arr[1]);
12257          } else {
12258            output[Tools.trim(arr[0])] = Tools.trim(arr[0]);
12259          }
12260        });
12261      } else {
12262        output = value;
12263      }
12264      return output;
12265    };
12266    var isArrayOf = function (p) {
12267      return function (a) {
12268        return isArray(a) && forall(a, p);
12269      };
12270    };
12271    var getParam = function (editor, name, defaultVal, type) {
12272      var value = name in editor.settings ? editor.settings[name] : defaultVal;
12273      if (type === 'hash') {
12274        return getParamObject(value);
12275      } else if (type === 'string') {
12276        return getFiltered(isString, editor, name).getOr(defaultVal);
12277      } else if (type === 'number') {
12278        return getFiltered(isNumber, editor, name).getOr(defaultVal);
12279      } else if (type === 'boolean') {
12280        return getFiltered(isBoolean, editor, name).getOr(defaultVal);
12281      } else if (type === 'object') {
12282        return getFiltered(isObject, editor, name).getOr(defaultVal);
12283      } else if (type === 'array') {
12284        return getFiltered(isArray, editor, name).getOr(defaultVal);
12285      } else if (type === 'string[]') {
12286        return getFiltered(isArrayOf(isString), editor, name).getOr(defaultVal);
12287      } else if (type === 'function') {
12288        return getFiltered(isFunction, editor, name).getOr(defaultVal);
12289      } else {
12290        return value;
12291      }
12292    };
12293
12294    var getProp = function (propName, elm) {
12295      var rawElm = elm.dom();
12296      return rawElm[propName];
12297    };
12298    var getComputedSizeProp = function (propName, elm) {
12299      return parseInt(get$2(elm, propName), 10);
12300    };
12301    var getClientWidth = curry(getProp, 'clientWidth');
12302    var getClientHeight = curry(getProp, 'clientHeight');
12303    var getMarginTop = curry(getComputedSizeProp, 'margin-top');
12304    var getMarginLeft = curry(getComputedSizeProp, 'margin-left');
12305    var getBoundingClientRect$1 = function (elm) {
12306      return elm.dom().getBoundingClientRect();
12307    };
12308    var isInsideElementContentArea = function (bodyElm, clientX, clientY) {
12309      var clientWidth = getClientWidth(bodyElm);
12310      var clientHeight = getClientHeight(bodyElm);
12311      return clientX >= 0 && clientY >= 0 && clientX <= clientWidth && clientY <= clientHeight;
12312    };
12313    var transpose = function (inline, elm, clientX, clientY) {
12314      var clientRect = getBoundingClientRect$1(elm);
12315      var deltaX = inline ? clientRect.left + elm.dom().clientLeft + getMarginLeft(elm) : 0;
12316      var deltaY = inline ? clientRect.top + elm.dom().clientTop + getMarginTop(elm) : 0;
12317      var x = clientX - deltaX;
12318      var y = clientY - deltaY;
12319      return {
12320        x: x,
12321        y: y
12322      };
12323    };
12324    var isXYInContentArea = function (editor, clientX, clientY) {
12325      var bodyElm = Element.fromDom(editor.getBody());
12326      var targetElm = editor.inline ? bodyElm : documentElement(bodyElm);
12327      var transposedPoint = transpose(editor.inline, targetElm, clientX, clientY);
12328      return isInsideElementContentArea(targetElm, transposedPoint.x, transposedPoint.y);
12329    };
12330    var fromDomSafe = function (node) {
12331      return Option.from(node).map(Element.fromDom);
12332    };
12333    var isEditorAttachedToDom = function (editor) {
12334      var rawContainer = editor.inline ? editor.getBody() : editor.getContentAreaContainer();
12335      return fromDomSafe(rawContainer).map(function (container) {
12336        return contains$3(owner(container), container);
12337      }).getOr(false);
12338    };
12339    var EditorView = {
12340      isXYInContentArea: isXYInContentArea,
12341      isEditorAttachedToDom: isEditorAttachedToDom
12342    };
12343
12344    function NotificationManagerImpl() {
12345      var unimplemented = function () {
12346        throw new Error('Theme did not provide a NotificationManager implementation.');
12347      };
12348      return {
12349        open: unimplemented,
12350        close: unimplemented,
12351        reposition: unimplemented,
12352        getArgs: unimplemented
12353      };
12354    }
12355
12356    function NotificationManager(editor) {
12357      var notifications = [];
12358      var getImplementation = function () {
12359        var theme = editor.theme;
12360        return theme && theme.getNotificationManagerImpl ? theme.getNotificationManagerImpl() : NotificationManagerImpl();
12361      };
12362      var getTopNotification = function () {
12363        return Option.from(notifications[0]);
12364      };
12365      var isEqual = function (a, b) {
12366        return a.type === b.type && a.text === b.text && !a.progressBar && !a.timeout && !b.progressBar && !b.timeout;
12367      };
12368      var reposition = function () {
12369        if (notifications.length > 0) {
12370          getImplementation().reposition(notifications);
12371        }
12372      };
12373      var addNotification = function (notification) {
12374        notifications.push(notification);
12375      };
12376      var closeNotification = function (notification) {
12377        findIndex(notifications, function (otherNotification) {
12378          return otherNotification === notification;
12379        }).each(function (index) {
12380          notifications.splice(index, 1);
12381        });
12382      };
12383      var open = function (spec) {
12384        if (editor.removed || !EditorView.isEditorAttachedToDom(editor)) {
12385          return;
12386        }
12387        return find(notifications, function (notification) {
12388          return isEqual(getImplementation().getArgs(notification), spec);
12389        }).getOrThunk(function () {
12390          editor.editorManager.setActive(editor);
12391          var notification = getImplementation().open(spec, function () {
12392            closeNotification(notification);
12393            reposition();
12394          });
12395          addNotification(notification);
12396          reposition();
12397          return notification;
12398        });
12399      };
12400      var close = function () {
12401        getTopNotification().each(function (notification) {
12402          getImplementation().close(notification);
12403          closeNotification(notification);
12404          reposition();
12405        });
12406      };
12407      var getNotifications = function () {
12408        return notifications;
12409      };
12410      var registerEvents = function (editor) {
12411        editor.on('SkinLoaded', function () {
12412          var serviceMessage = editor.settings.service_message;
12413          if (serviceMessage) {
12414            open({
12415              text: serviceMessage,
12416              type: 'warn',
12417              timeout: 0
12418            });
12419          }
12420        });
12421        editor.on('ResizeEditor ResizeWindow NodeChange', function () {
12422          Delay.requestAnimationFrame(reposition);
12423        });
12424        editor.on('remove', function () {
12425          each(notifications.slice(), function (notification) {
12426            getImplementation().close(notification);
12427          });
12428        });
12429      };
12430      registerEvents(editor);
12431      return {
12432        open: open,
12433        close: close,
12434        getNotifications: getNotifications
12435      };
12436    }
12437
12438    function WindowManagerImpl () {
12439      var unimplemented = function () {
12440        throw new Error('Theme did not provide a WindowManager implementation.');
12441      };
12442      return {
12443        open: unimplemented,
12444        openUrl: unimplemented,
12445        alert: unimplemented,
12446        confirm: unimplemented,
12447        close: unimplemented,
12448        getParams: unimplemented,
12449        setParams: unimplemented
12450      };
12451    }
12452
12453    var WindowManager = function (editor) {
12454      var dialogs = [];
12455      var getImplementation = function () {
12456        var theme = editor.theme;
12457        return theme && theme.getWindowManagerImpl ? theme.getWindowManagerImpl() : WindowManagerImpl();
12458      };
12459      var funcBind = function (scope, f) {
12460        return function () {
12461          return f ? f.apply(scope, arguments) : undefined;
12462        };
12463      };
12464      var fireOpenEvent = function (dialog) {
12465        editor.fire('OpenWindow', { dialog: dialog });
12466      };
12467      var fireCloseEvent = function (dialog) {
12468        editor.fire('CloseWindow', { dialog: dialog });
12469      };
12470      var addDialog = function (dialog) {
12471        dialogs.push(dialog);
12472        fireOpenEvent(dialog);
12473      };
12474      var closeDialog = function (dialog) {
12475        fireCloseEvent(dialog);
12476        dialogs = filter(dialogs, function (otherDialog) {
12477          return otherDialog !== dialog;
12478        });
12479        if (dialogs.length === 0) {
12480          editor.focus();
12481        }
12482      };
12483      var getTopDialog = function () {
12484        return Option.from(dialogs[dialogs.length - 1]);
12485      };
12486      var storeSelectionAndOpenDialog = function (openDialog) {
12487        editor.editorManager.setActive(editor);
12488        SelectionBookmark.store(editor);
12489        var dialog = openDialog();
12490        addDialog(dialog);
12491        return dialog;
12492      };
12493      var open = function (args, params) {
12494        return storeSelectionAndOpenDialog(function () {
12495          return getImplementation().open(args, params, closeDialog);
12496        });
12497      };
12498      var openUrl = function (args) {
12499        return storeSelectionAndOpenDialog(function () {
12500          return getImplementation().openUrl(args, closeDialog);
12501        });
12502      };
12503      var alert = function (message, callback, scope) {
12504        getImplementation().alert(message, funcBind(scope ? scope : this, callback));
12505      };
12506      var confirm = function (message, callback, scope) {
12507        getImplementation().confirm(message, funcBind(scope ? scope : this, callback));
12508      };
12509      var close = function () {
12510        getTopDialog().each(function (dialog) {
12511          getImplementation().close(dialog);
12512          closeDialog(dialog);
12513        });
12514      };
12515      editor.on('remove', function () {
12516        each(dialogs, function (dialog) {
12517          getImplementation().close(dialog);
12518        });
12519      });
12520      return {
12521        open: open,
12522        openUrl: openUrl,
12523        alert: alert,
12524        confirm: confirm,
12525        close: close
12526      };
12527    };
12528
12529    var PluginManager = AddOnManager$1.PluginManager;
12530    var resolvePluginName = function (targetUrl, suffix) {
12531      for (var name in PluginManager.urls) {
12532        var matchUrl = PluginManager.urls[name] + '/plugin' + suffix + '.js';
12533        if (matchUrl === targetUrl) {
12534          return name;
12535        }
12536      }
12537      return null;
12538    };
12539    var pluginUrlToMessage = function (editor, url) {
12540      var plugin = resolvePluginName(url, editor.suffix);
12541      return plugin ? I18n.translate([
12542        'Failed to load plugin: {0} from url {1}',
12543        plugin,
12544        url
12545      ]) : I18n.translate([
12546        'Failed to load plugin url: {0}',
12547        url
12548      ]);
12549    };
12550    var displayNotification = function (editor, message) {
12551      editor.notificationManager.open({
12552        type: 'error',
12553        text: message
12554      });
12555    };
12556    var displayError = function (editor, message) {
12557      if (editor._skinLoaded) {
12558        displayNotification(editor, message);
12559      } else {
12560        editor.on('SkinLoaded', function () {
12561          displayNotification(editor, message);
12562        });
12563      }
12564    };
12565    var uploadError = function (editor, message) {
12566      displayError(editor, I18n.translate([
12567        'Failed to upload image: {0}',
12568        message
12569      ]));
12570    };
12571    var pluginLoadError = function (editor, url) {
12572      displayError(editor, pluginUrlToMessage(editor, url));
12573    };
12574    var pluginInitError = function (editor, name, err) {
12575      var message = I18n.translate([
12576        'Failed to initialize plugin: {0}',
12577        name
12578      ]);
12579      initError(message, err);
12580      displayError(editor, message);
12581    };
12582    var initError = function (message) {
12583      var x = [];
12584      for (var _i = 1; _i < arguments.length; _i++) {
12585        x[_i - 1] = arguments[_i];
12586      }
12587      var console = domGlobals.window.console;
12588      if (console) {
12589        if (console.error) {
12590          console.error.apply(console, arguments);
12591        } else {
12592          console.log.apply(console, arguments);
12593        }
12594      }
12595    };
12596    var ErrorReporter = {
12597      pluginLoadError: pluginLoadError,
12598      pluginInitError: pluginInitError,
12599      uploadError: uploadError,
12600      displayError: displayError,
12601      initError: initError
12602    };
12603
12604    var getAll = function () {
12605      return {
12606        'accessibility-check': '<svg width="24" height="24"><path d="M12 2a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2c0-1.1.9-2 2-2zm8 7h-5v12c0 .6-.4 1-1 1a1 1 0 0 1-1-1v-5c0-.6-.4-1-1-1a1 1 0 0 0-1 1v5c0 .6-.4 1-1 1a1 1 0 0 1-1-1V9H4a1 1 0 1 1 0-2h16c.6 0 1 .4 1 1s-.4 1-1 1z" fill-rule="nonzero"/></svg>',
12607        'align-center': '<svg width="24" height="24"><path d="M5 5h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2zm3 4h8c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 1 1 0-2zm0 8h8c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 0 1 0-2zm-3-4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2z" fill-rule="evenodd"/></svg>',
12608        'align-justify': '<svg width="24" height="24"><path d="M5 5h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2zm0 4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2zm0 4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2zm0 4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2z" fill-rule="evenodd"/></svg>',
12609        'align-left': '<svg width="24" height="24"><path d="M5 5h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2zm0 4h8c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2zm0 8h8c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2zm0-4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2z" fill-rule="evenodd"/></svg>',
12610        'align-none': '<svg width="24" height="24"><path d="M14.2 5L13 7H5a1 1 0 1 1 0-2h9.2zm4 0h.8a1 1 0 0 1 0 2h-2l1.2-2zm-6.4 4l-1.2 2H5a1 1 0 0 1 0-2h6.8zm4 0H19a1 1 0 0 1 0 2h-4.4l1.2-2zm-6.4 4l-1.2 2H5a1 1 0 0 1 0-2h4.4zm4 0H19a1 1 0 0 1 0 2h-6.8l1.2-2zM7 17l-1.2 2H5a1 1 0 0 1 0-2h2zm4 0h8a1 1 0 0 1 0 2H9.8l1.2-2zm5.2-13.5l1.3.7-9.7 16.3-1.3-.7 9.7-16.3z" fill-rule="evenodd"/></svg>',
12611        'align-right': '<svg width="24" height="24">
12611<path d="M5 5h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2zm6 4h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zm0 8h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zm-6-4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2z" fill-rule="evenodd"/></svg>',
12612        'arrow-left': '<svg width="24" height="24"><path d="M5.6 13l12 6a1 1 0 0 0 1.4-1V6a1 1 0 0 0-1.4-.9l-12 6a1 1 0 0 0 0 1.8z" fill-rule="evenodd"/></svg>',
12613        'arrow-right': '<svg width="24" height="24"><path d="M18.5 13l-12 6A1 1 0 0 1 5 18V6a1 1 0 0 1 1.4-.9l12 6a1 1 0 0 1 0 1.8z" fill-rule="evenodd"/></svg>',
12614        'bold': '<svg width="24" height="24"><path d="M7.8 19c-.3 0-.5 0-.6-.2l-.2-.5V5.7c0-.2 0-.4.2-.5l.6-.2h5c1.5 0 2.7.3 3.5 1 .7.6 1.1 1.4 1.1 2.5a3 3 0 0 1-.6 1.9c-.4.6-1 1-1.6 1.2.4.1.9.3 1.3.6s.8.7 1 1.2c.4.4.5 1 .5 1.6 0 1.3-.4 2.3-1.3 3-.8.7-2.1 1-3.8 1H7.8zm5-8.3c.6 0 1.2-.1 1.6-.5.4-.3.6-.7.6-1.3 0-1.1-.8-1.7-2.3-1.7H9.3v3.5h3.4zm.5 6c.7 0 1.3-.1 1.7-.4.4-.4.6-.9.6-1.5s-.2-1-.7-1.4c-.4-.3-1-.4-2-.4H9.4v3.8h4z" fill-rule="evenodd"/></svg>',
12615        'bookmark': '<svg width="24" height="24"><path d="M6 4v17l6-4 6 4V4c0-.6-.4-1-1-1H7a1 1 0 0 0-1 1z" fill-rule="nonzero"/></svg>',
12616        'border-width': '<svg width="24" height="24"><path d="M5 14.8h14a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zm-.5 3.7h15c.3 0 .5.2.5.5s-.2.5-.5.5h-15a.5.5 0 1 1 0-1zm.5-8.3h14c.6 0 1 .4 1 1v1c0 .5-.4 1-1 1H5a1 1 0 0 1-1-1v-1c0-.6.4-1 1-1zm0-5.7h14c.6 0 1 .4 1 1v2c0 .6-.4 1-1 1H5a1 1 0 0 1-1-1v-2c0-.6.4-1 1-1z" fill-rule="evenodd"/></svg>',
12617        'brightness': '<svg width="24" height="24"><path d="M12 17c.3 0 .5.1.7.3.2.2.3.4.3.7v1c0 .3-.1.5-.3.7a1 1 0 0 1-.7.3 1 1 0 0 1-.7-.3 1 1 0 0 1-.3-.7v-1c0-.3.1-.5.3-.7.2-.2.4-.3.7-.3zm0-10a1 1 0 0 1-.7-.3A1 1 0 0 1 11 6V5c0-.3.1-.5.3-.7.2-.2.4-.3.7-.3.3 0 .5.1.7.3.2.2.3.4.3.7v1c0 .3-.1.5-.3.7a1 1 0 0 1-.7.3zm7 4c.3 0 .5.1.7.3.2.2.3.4.3.7 0 .3-.1.5-.3.7a1 1 0 0 1-.7.3h-1a1 1 0 0 1-.7-.3 1 1 0 0 1-.3-.7c0-.3.1-.5.3-.7.2-.2.4-.3.7-.3h1zM7 12c0 .3-.1.5-.3.7a1 1 0 0 1-.7.3H5a1 1 0 0 1-.7-.3A1 1 0 0 1 4 12c0-.3.1-.5.3-.7.2-.2.4-.3.7-.3h1c.3 0 .5.1.7.3.2.2.3.4.3.7zm10 3.5l.7.8c.2.1.3.4.3.6 0 .3-.1.6-.3.8a1 1 0 0 1-.8.3 1 1 0 0 1-.6-.3l-.8-.7a1 1 0 0 1-.3-.8c0-.2.1-.5.3-.7a1 1 0 0 1 1.4 0zm-10-7l-.7-.8a1 1 0 0 1-.3-.6c0-.3.1-.6.3-.8.2-.2.5-.3.8-.3.2 0 .5.1.7.3l.7.7c.2.2.3.5.3.8 0 .2-.1.5-.3.7a1 1 0 0 1-.7.3 1 1 0 0 1-.8-.3zm10 0a1 1 0 0 1-.8.3 1 1 0 0 1-.7-.3 1 1 0 0 1-.3-.7c0-.3.1-.6.3-.8l.8-.7c.1-.2.4-.3.6-.3.3 0 .6.1.8.3.2.2.3.5.3.8 0 .2-.1.5-.3.7l-.7.7zm-10 7c.2-.2.5-.3.8-.3.2 0 .5.1.7.3a1 1 0 0 1 0 1.4l-.8.8a1 1 0 0 1-.6.3 1 1 0 0 1-.8-.3 1 1 0 0 1-.3-.8c0-.2.1-.5.3-.6l.7-.8zM12 8a4 4 0 0 1 3.7 2.4 4 4 0 0 1 0 3.2A4 4 0 0 1 12 16a4 4 0 0 1-3.7-2.4 4 4 0 0 1 0-3.2A4 4 0 0 1 12 8zm0 6.5c.7 0 1.3-.2 1.8-.7.5-.5.7-1.1.7-1.8s-.2-1.3-.7-1.8c-.5-.5-1.1-.7-1.8-.7s-1.3.2-1.8.7c-.5.5-.7 1.1-.7 1.8s.2 1.3.7 1.8c.5.5 1.1.7 1.8.7z" fill-rule="evenodd"/></svg>',
12618        'browse': '<svg width="24" height="24"><path d="M19 4a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-4v-2h4V8H5v10h4v2H5a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2h14zm-8 9.4l-2.3 2.3a1 1 0 1 1-1.4-1.4l4-4a1 1 0 0 1 1.4 0l4 4a1 1 0 0 1-1.4 1.4L13 13.4V20a1 1 0 0 1-2 0v-6.6z" fill-rule="nonzero"/></svg>',
12619        'cancel': '<svg width="24" height="24"><path d="M12 4.6a7.4 7.4 0 1 1 0 14.8 7.4 7.4 0 0 1 0-14.8zM12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zm0 8L14.8 8l1 1.1-2.7 2.8 2.7 2.7-1.1 1.1-2.7-2.7-2.7 2.7-1-1.1 2.6-2.7-2.7-2.7 1-1.1 2.8 2.7z" fill-rule="nonzero"/></svg>',
12620        'change-case': '<svg width="24" height="24"><path d="M18.4 18.2v-.6c-.5.8-1.3 1.2-2.4 1.2-2.2 0-3.3-1.6-3.3-4.8 0-3.1 1-4.7 3.3-4.7 1.1 0 1.8.3 2.4 1.1v-.6c0-.5.4-.8.8-.8s.8.3.8.8v8.4c0 .5-.4.8-.8.8a.8.8 0 0 1-.8-.8zm-2-7.4c-1.3 0-1.8.9-1.8 3.2 0 2.4.5 3.3 1.7 3.3 1.3 0 1.8-.9 1.8-3.2 0-2.4-.5-3.3-1.7-3.3zM10 15.7H5.5l-.8 2.6a1 1 0 0 1-1 .7h-.2a.7.7 0 0 1-.7-1l4-12a1 1 0 1 1 2 0l4 12a.7.7 0 0 1-.8 1h-.2a1 1 0 0 1-1-.7l-.8-2.6zm-.3-1.5l-2-6.5-1.9 6.5h3.9z" fill-rule="evenodd"/></svg>',
12621        'character-count': '<svg width="24" height="24"><path d="M4 11.5h16v1H4v-1zm4.8-6.8V10H7.7V5.8h-1v-1h2zM11 8.3V9h2v1h-3V7.7l2-1v-.9h-2v-1h3v2.4l-2 1zm6.3-3.4V10h-3.1V9h2.1V8h-2.1V6.8h2.1v-1h-2.1v-1h3.1zM
126215.8 16.4c0-.5.2-.8.5-1 .2-.2.6-.3 1.2-.3l.8.1c.2 0 .4.2.5.3l.4.4v2.8l.2.3H8.2v-.1-.2l-.6.3H7c-.4 0-.7 0-1-.2a1 1 0 0 1-.3-.9c0-.3 0-.6.3-.8.3-.2.7-.4 1.2-.4l.6-.2h.3v-.2l-.1-.2a.8.8 0 0 0-.5-.1 1 1 0 0 0-.4 0l-.3.4h-1zm2.3.8h-.2l-.2.1-.4.1a1 1 0 0 0-.4.2l-.2.2.1.3.5.1h.4l.4-.4v-.6zm2-3.4h1.2v1.7l.5-.3h.5c.5 0 .9.1 1.2.5.3.4.5.8.5 1.4 0 .6-.2 1.1-.5 1.5-.3.4-.7.6-1.3.6l-.6-.1-.4-.4v.4h-1.1v-5.4zm1.1 3.3c0 .3 0 .6.2.8a.7.7 0 0 0 1.2 0l.2-.8c0-.4 0-.6-.2-.8a.7.7 0 0 0-.6-.3l-.6.3-.2.8zm6.1-.5c0-.2 0-.3-.2-.4a.8.8 0 0 0-.5-.2c-.3 0-.5.1-.6.3l-.2.9c0 .3 0 .6.2.8.1.2.3.3.6.3.2 0 .4 0 .5-.2l.2-.4h1.1c0 .5-.3.8-.6 1.1a2 2 0 0 1-1.3.4c-.5 0-1-.2-1.3-.6a2 2 0 0 1-.5-1.4c0-.6.1-1.1.5-1.5.3-.4.8-.5 1.4-.5.5 0 1 0 1.2.3.4.3.5.7.5 1.2h-1v-.1z" fill-rule="evenodd"/></svg>',
12622        'checklist': '<svg width="24" height="24"><path d="M11 17h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zm0-6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zm0-6h8a1 1 0 0 1 0 2h-8a1 1 0 0 1 0-2zM7.2 16c.2-.4.6-.5.9-.3.3.2.4.6.2 1L6 20c-.2.3-.7.4-1 0l-1.3-1.3a.7.7 0 0 1 0-1c.3-.2.7-.2 1 0l.7.9 1.7-2.8zm0-6c.2-.4.6-.5.9-.3.3.2.4.6.2 1L6 14c-.2.3-.7.4-1 0l-1.3-1.3a.7.7 0 0 1 0-1c.3-.2.7-.2 1 0l.7.9 1.7-2.8zm0-6c.2-.4.6-.5.9-.3.3.2.4.6.2 1L6 8c-.2.3-.7.4-1 0L3.8 6.9a.7.7 0 0 1 0-1c.3-.2.7-.2 1 0l.7.9 1.7-2.8z" fill-rule="evenodd"/></svg>',
12623        'checkmark': '<svg width="24" height="24"><path d="M18.2 5.4a1 1 0 0 1 1.6 1.2l-8 12a1 1 0 0 1-1.5.1l-5-5a1 1 0 1 1 1.4-1.4l4.1 4.1 7.4-11z" fill-rule="nonzero"/></svg>',
12624        'chevron-down': '<svg width="10" height="10"><path d="M8.7 2.2c.3-.3.8-.3 1 0 .4.4.4.9 0 1.2L5.7 7.8c-.3.3-.9.3-1.2 0L.2 3.4a.8.8 0 0 1 0-1.2c.3-.3.8-.3 1.1 0L5 6l3.7-3.8z" fill-rule="nonzero"/></svg>',
12625        'chevron-left': '<svg width="10" height="10"><path d="M7.8 1.3L4 5l3.8 3.7c.3.3.3.8 0 1-.4.4-.9.4-1.2 0L2.2 5.7a.8.8 0 0 1 0-1.2L6.6.2C7 0 7.4 0 7.8.2c.3.3.3.8 0 1.1z" fill-rule="nonzero"/></svg>',
12626        'chevron-right': '<svg width="10" height="10"><path d="M2.2 1.3a.8.8 0 0 1 0-1c.4-.4.9-.4 1.2 0l4.4 4.1c.3.4.3.9 0 1.2L3.4 9.8c-.3.3-.8.3-1.2 0a.8.8 0 0 1 0-1.1L6 5 2.2 1.3z" fill-rule="nonzero"/></svg>',
12627        'chevron-up': '<svg width="10" height="10"><path d="M8.7 7.8L5 4 1.3 7.8c-.3.3-.8.3-1 0a.8.8 0 0 1 0-1.2l4.1-4.4c.3-.3.9-.3 1.2 0l4.2 4.4c.3.3.3.9 0 1.2-.3.3-.8.3-1.1 0z" fill-rule="nonzero"/></svg>',
12628        'close': '<svg width="24" height="24"><path d="M17.3 8.2L13.4 12l3.9 3.8a1 1 0 0 1-1.5 1.5L12 13.4l-3.8 3.9a1 1 0 0 1-1.5-1.5l3.9-3.8-3.9-3.8a1 1 0 0 1 1.5-1.5l3.8 3.9 3.8-3.9a1 1 0 0 1 1.5 1.5z" fill-rule="evenodd"/></svg>',
12629        'code-sample': '<svg width="24" height="26"><path d="M7.1 11a2.8 2.8 0 0 1-.8 2 2.8 2.8 0 0 1 .8 2v1.7c0 .3.1.6.4.8.2.3.5.4.8.4.3 0 .4.2.4.4v.8c0 .2-.1.4-.4.4-.7 0-1.4-.3-2-.8-.5-.6-.8-1.3-.8-2V15c0-.3-.1-.6-.4-.8-.2-.3-.5-.4-.8-.4a.4.4 0 0 1-.4-.4v-.8c0-.2.2-.4.4-.4.3 0 .6-.1.8-.4.3-.2.4-.5.4-.8V9.3c0-.7.3-1.4.8-2 .6-.5 1.3-.8 2-.8.3 0 .4.2.4.4v.8c0 .2-.1.4-.4.4-.3 0-.6.1-.8.4-.3.2-.4.5-.4.8V11zm9.8 0V9.3c0-.3-.1-.6-.4-.8-.2-.3-.5-.4-.8-.4a.4.4 0 0 1-.4-.4V7c0-.2.1-.4.4-.4.7 0 1.4.3 2 .8.5.6.8 1.3.8 2V11c0 .3.1.6.4.8.2.3.5.4.8.4.2 0 .4.2.4.4v.8c0 .2-.2.4-.4.4-.3 0-.6.1-.8.4-.3.2-.4.5-.4.8v1.7c0 .7-.3 1.4-.8 2-.6.5-1.3.8-2 .8a.4.4 0 0 1-.4-.4v-.8c0-.2.1-.4.4-.4.3 0 .6-.1.8-.4.3-.2.4-.5.4-.8V15a2.8 2.8 0 0 1 .8-2 2.8 2.8 0 0 1-.8-2zm-3.3-.4c0 .4-.1.8-.5 1.1-.3.3-.7.5-1.1.5-.4 0-.8-.2-1.1-.5-.4-.3-.5-.7-.5-1.1 0-.5.1-.9.5-1.2.3-.3.7-.4 1.1-.4.4 0 .8.1 1.1.4.4.3.5.7.5 1.2zM12 13c.4 0 .8.1 1.1.5.4.3.5.7.5 1.1 0 1-.1 1.6-.5 2a3 3 0 0 1-1.1 1c-.4.3-.8.4-1.1.4a.5.5 0 0 1-.5-.5V17a3 3 0 0 0 1-.2l.6-.6c-.6 0-1-.2-1.3-.5-.2-.3-.3-.7-.3-1 0-.5.1-1 .5-1.2.3-.4.7-.5 1.1-.5z" fill-rule="evenodd"/></svg>',
12630        'color-levels': '<svg width="24" height="24"><path d="M17.5 11.4A9 9 0 0 1 18 14c0 .5 0 1-.2 1.4 0 .4-.3.9-.5 1.3a6.2 6.2 0 0 1-3.7 3 5.7 5.7 0 0 1-3.2 0A5.9 5.9 0 0 1 7.6 18a6.2 6.2 0 0 1-1.4-2.6 6.7 6.7 0 0 1 0-2.8c0-.4.1-.9.3-1.3a13.6 13.6 0 0 1 2.3-4A20 20 0 0 1 12 4a26.4 26.4 0 0 1 3.2 3.4 18.2 18.2 0 0 1 2.3 4zm-2 4.5c.4-.7.5-1.4.5-2a7.3 7.3 0 0 0-1-3.2c.2.6.2 1.2.2 1.9a4.5 4.5 0 0 1-1.3 3 5.3 5.3 0 0 1-2.3 1.5 4.9 4.9 0 0 1-2 .1 4.3 4.3 0 0 0 2.4.8 4 4 0 0 0 2-.6 4 4 0 0 0 1.5-1.5z" fill-rule="evenodd"/></svg>',
12631        'color-picker': '<svg width="24" height="24">
12631<path d="M12 3a9 9 0 0 0 0 18 1.5 1.5 0 0 0 1.1-2.5c-.2-.3-.4-.6-.4-1 0-.8.7-1.5 1.5-1.5H16a5 5 0 0 0 5-5c0-4.4-4-8-9-8zm-5.5 9a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm3-4a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm3 4a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z" fill-rule="nonzero"/></svg>',
12632        'color-swatch-remove-color': '<svg width="24" height="24"><path stroke="#000" stroke-width="2" d="M21 3L3 21" fill-rule="evenodd"/></svg>',
12633        'color-swatch': '<svg width="24" height="24"><rect x="3" y="3" width="18" height="18" rx="1" fill-rule="evenodd"/></svg>',
12634        'comment': '<svg width="24" height="24"><path d="M9 19l3-2h7c.6 0 1-.4 1-1V6c0-.6-.4-1-1-1H5a1 1 0 0 0-1 1v10c0 .6.4 1 1 1h4v2zm-2 4v-4H5a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h14a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3h-6.4L7 23z" fill-rule="nonzero"/></svg>',
12635        'contrast': '<svg width="24" height="24"><path d="M12 4a7.8 7.8 0 0 1 5.7 2.3A8 8 0 1 1 12 4zm-6 8a6 6 0 0 0 6 6V6a6 6 0 0 0-6 6z" fill-rule="evenodd"/></svg>',
12636        'copy': '<svg width="24" height="24"><path d="M16 3H6a2 2 0 0 0-2 2v11h2V5h10V3zm1 4a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-7a2 2 0 0 1-2-2V9c0-1.2.9-2 2-2h7zm0 12V9h-7v10h7z" fill-rule="nonzero"/></svg>',
12637        'crop': '<svg width="24" height="24"><path d="M17 8v7h2c.6 0 1 .4 1 1s-.4 1-1 1h-2v2c0 .6-.4 1-1 1a1 1 0 0 1-1-1v-2H7V9H5a1 1 0 1 1 0-2h2V5c0-.6.4-1 1-1s1 .4 1 1v2h7l3-3 1 1-3 3zM9 9v5l5-5H9zm1 6h5v-5l-5 5z" fill-rule="evenodd"/></svg>',
12638        'cut': '<svg width="24" height="24"><path d="M18 15c.6.7 1 1.4 1 2.3 0 .8-.2 1.5-.7 2l-.8.5-1 .2c-.4 0-.8 0-1.2-.3a3.9 3.9 0 0 1-2.1-2.2c-.2-.5-.3-1-.2-1.5l-1-1-1 1c0 .5 0 1-.2 1.5-.1.5-.4 1-.9 1.4-.3.4-.7.6-1.2.8l-1.2.3c-.4 0-.7 0-1-.2-.3 0-.6-.3-.8-.5-.5-.5-.8-1.2-.7-2 0-.9.4-1.6 1-2.2A3.7 3.7 0 0 1 8.6 14H9l1-1-4-4-.5-1a3.3 3.3 0 0 1 0-2c0-.4.3-.7.5-1l6 6 6-6 .5 1a3.3 3.3 0 0 1 0 2c0 .4-.3.7-.5 1l-4 4 1 1h.5c.4 0 .8 0 1.2.3.5.2.9.4 1.2.8zm-8.5 2.2l.1-.4v-.3-.4a1 1 0 0 0-.2-.5 1 1 0 0 0-.4-.2 1.6 1.6 0 0 0-.8 0 2.6 2.6 0 0 0-.8.3 2.5 2.5 0 0 0-.9 1.1l-.1.4v.7l.2.5.5.2h.7a2.5 2.5 0 0 0 .8-.3 2.8 2.8 0 0 0 1-1zm2.5-2.8c.4 0 .7-.1 1-.4.3-.3.4-.6.4-1s-.1-.7-.4-1c-.3-.3-.6-.4-1-.4s-.7.1-1 .4c-.3.3-.4.6-.4 1s.1.7.4 1c.3.3.6.4 1 .4zm5.4 4l.2-.5v-.4-.3a2.6 2.6 0 0 0-.3-.8 2.4 2.4 0 0 0-.7-.7 2.5 2.5 0 0 0-.8-.3 1.5 1.5 0 0 0-.8 0 1 1 0 0 0-.4.2 1 1 0 0 0-.2.5 1.5 1.5 0 0 0 0 .7v.4l.3.4.3.4a2.8 2.8 0 0 0 .8.5l.4.1h.7l.5-.2z" fill-rule="evenodd"/></svg>',
12639        'document-properties': '<svg width="24" height="24"><path d="M14.4 3H7a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h10a2 2 0 0 0 2-2V7.6L14.4 3zM17 19H7V5h6v4h4v10z" fill-rule="nonzero"/></svg>',
12640        'drag': '<svg width="24" height="24"><path d="M13 5h2v2h-2V5zm0 4h2v2h-2V9zM9 9h2v2H9V9zm4 4h2v2h-2v-2zm-4 0h2v2H9v-2zm0 4h2v2H9v-2zm4 0h2v2h-2v-2zM9 5h2v2H9V5z" fill-rule="evenodd"/></svg>',
12641        'duplicate': '<svg width="24" height="24"><g fill-rule="nonzero"><path d="M16 3v2H6v11H4V5c0-1.1.9-2 2-2h10zm3 8h-2V9h-7v10h9a2 2 0 0 1-2 2h-7a2 2 0 0 1-2-2V9c0-1.2.9-2 2-2h7a2 2 0 0 1 2 2v2z"/><path d="M17 14h1a1 1 0 0 1 0 2h-1v1a1 1 0 0 1-2 0v-1h-1a1 1 0 0 1 0-2h1v-1a1 1 0 0 1 2 0v1z"/></g></svg>',
12642        'edit-image': '<svg width="24" height="24"><path d="M18 16h2V7a2 2 0 0 0-2-2H7v2h11v9zM6 17h15a1 1 0 0 1 0 2h-1v1a1 1 0 0 1-2 0v-1H6a2 2 0 0 1-2-2V7H3a1 1 0 1 1 0-2h1V4a1 1 0 1 1 2 0v13zm3-5.3l1.3 2 3-4.7 3.7 6H7l2-3.3z" fill-rule="nonzero"/></svg>',
12643        'embed-page': '<svg width="24" height="24"><path d="M19 6V5H5v14h2A13 13 0 0 1 19 6zm0 1.4c-.8.8-1.6 2.4-2.2 4.6H19V7.4zm0 5.6h-2.4c-.4 1.8-.6 3.8-.6 6h3v-6zm-4 6c0-2.2.2-4.2.6-6H13c-.7 1.8-1.1 3.8-1.1 6h3zm-4 0c0-2.2.4-4.2 1-6H9.6A12 12 0 0 0 8 19h3zM4 3h16c.6 0 1 .4 1 1v16c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V4c0-.6.4-1 1-1zm11.8 9c.4-1.9 1-3.4 1.8-4.5a9.2 9.2 0 0 0-4 4.5h2.2zm-3.4 0a12 12 0 0 1 2.8-4 12 12 0 0 0-5 4h2.2z" fill-rule="nonzero"/></svg>',
12644        'embed': '<svg width="24" height="24"><path d="M4 3h16c.6 0 1 .4 1 1v16c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V4c0-.6.4-1 1-1zm1 2v14h14V5H5zm4.8 2.6l5.6 4a.5.5 0 0 1 0 .8l-5.6 4A.5.5 0 0 1 9 16V8a.5.5 0 0 1 .8-.4z" fill-rule="nonzero"/></svg>',
12645        'emoji': '<svg width="24" height="24">
12645<path d="M9 11c.6 0 1-.4 1-1s-.4-1-1-1a1 1 0 0 0-1 1c0 .6.4 1 1 1zm6 0c.6 0 1-.4 1-1s-.4-1-1-1a1 1 0 0 0-1 1c0 .6.4 1 1 1zm-3 5.5c2.1 0 4-1.5 4.4-3.5H7.6c.5 2 2.3 3.5 4.4 3.5zM12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16zm0 14.5a6.5 6.5 0 1 1 0-13 6.5 6.5 0 0 1 0 13z" fill-rule="nonzero"/></svg>',
12646        'fill': '<svg width="24" height="26"><path d="M16.6 12l-9-9-1.4 1.4 2.4 2.4-5.2 5.1c-.5.6-.5 1.6 0 2.2L9 19.6a1.5 1.5 0 0 0 2.2 0l5.5-5.5c.5-.6.5-1.6 0-2.2zM5.2 13L10 8.2l4.8 4.8H5.2zM19 14.5s-2 2.2-2 3.5c0 1.1.9 2 2 2a2 2 0 0 0 2-2c0-1.3-2-3.5-2-3.5z" fill-rule="nonzero"/></svg>',
12647        'flip-horizontally': '<svg width="24" height="24"><path d="M14 19h2v-2h-2v2zm4-8h2V9h-2v2zM4 7v10c0 1.1.9 2 2 2h3v-2H6V7h3V5H6a2 2 0 0 0-2 2zm14-2v2h2a2 2 0 0 0-2-2zm-7 16h2V3h-2v18zm7-6h2v-2h-2v2zm-4-8h2V5h-2v2zm4 12a2 2 0 0 0 2-2h-2v2z" fill-rule="nonzero"/></svg>',
12648        'flip-vertically': '<svg width="24" height="24"><path d="M5 14v2h2v-2H5zm8 4v2h2v-2h-2zm4-14H7a2 2 0 0 0-2 2v3h2V6h10v3h2V6a2 2 0 0 0-2-2zm2 14h-2v2a2 2 0 0 0 2-2zM3 11v2h18v-2H3zm6 7v2h2v-2H9zm8-4v2h2v-2h-2zM5 18c0 1.1.9 2 2 2v-2H5z" fill-rule="nonzero"/></svg>',
12649        'format-painter': '<svg width="24" height="24"><path d="M18 5V4c0-.5-.4-1-1-1H5a1 1 0 0 0-1 1v4c0 .6.5 1 1 1h12c.6 0 1-.4 1-1V7h1v4H9v9c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-7h8V5h-3z" fill-rule="nonzero"/></svg>',
12650        'fullscreen': '<svg width="24" height="24"><path d="M15.3 10l-1.2-1.3 2.9-3h-2.3a.9.9 0 1 1 0-1.7H19c.5 0 .9.4.9.9v4.4a.9.9 0 1 1-1.8 0V7l-2.9 3zm0 4l3 3v-2.3a.9.9 0 1 1 1.7 0V19c0 .5-.4.9-.9.9h-4.4a.9.9 0 1 1 0-1.8H17l-3-2.9 1.3-1.2zM10 15.4l-2.9 3h2.3a.9.9 0 1 1 0 1.7H5a.9.9 0 0 1-.9-.9v-4.4a.9.9 0 1 1 1.8 0V17l2.9-3 1.2 1.3zM8.7 10L5.7 7v2.3a.9.9 0 0 1-1.7 0V5c0-.5.4-.9.9-.9h4.4a.9.9 0 0 1 0 1.8H7l3 2.9-1.3 1.2z" fill-rule="nonzero"/></svg>',
12651        'gamma': '<svg width="24" height="24"><path d="M4 3h16c.6 0 1 .4 1 1v16c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V4c0-.6.4-1 1-1zm1 2v14h14V5H5zm6.5 11.8V14L9.2 8.7a5.1 5.1 0 0 0-.4-.8l-.1-.2H8 8v-1l.3-.1.3-.1h.7a1 1 0 0 1 .6.5l.1.3a8.5 8.5 0 0 1 .3.6l1.9 4.6 2-5.2a1 1 0 0 1 1-.6.5.5 0 0 1 .5.6L13 14v2.8a.7.7 0 0 1-1.4 0z" fill-rule="nonzero"/></svg>',
12652        'help': '<svg width="24" height="24"><g fill-rule="evenodd"><path d="M12 5.5a6.5 6.5 0 0 0-6 9 6.3 6.3 0 0 0 1.4 2l1 1a6.3 6.3 0 0 0 3.6 1 6.5 6.5 0 0 0 6-9 6.3 6.3 0 0 0-1.4-2l-1-1a6.3 6.3 0 0 0-3.6-1zM12 4a7.8 7.8 0 0 1 5.7 2.3A8 8 0 1 1 12 4z"/><path d="M9.6 9.7a.7.7 0 0 1-.7-.8c0-1.1 1.5-1.8 3.2-1.8 1.8 0 3.2.8 3.2 2.4 0 1.4-.4 2.1-1.5 2.8-.2 0-.3.1-.3.2a2 2 0 0 0-.8.8.8.8 0 0 1-1.4-.6c.3-.7.8-1 1.3-1.5l.4-.2c.7-.4.8-.6.8-1.5 0-.5-.6-.9-1.7-.9-.5 0-1 .1-1.4.3-.2 0-.3.1-.3.2v-.2c0 .4-.4.8-.8.8z" fill-rule="nonzero"/><circle cx="12" cy="16" r="1"/></g></svg>',
12653        'highlight-bg-color': '<svg width="24" height="24"><g fill-rule="evenodd"><path id="tox-icon-highlight-bg-color__color" d="M3 18h18v3H3z"/><path fill-rule="nonzero" d="M7.7 16.7H3l3.3-3.3-.7-.8L10.2 8l4 4.1-4 4.2c-.2.2-.6.2-.8 0l-.6-.7-1.1 1.1zm5-7.5L11 7.4l3-2.9a2 2 0 0 1 2.6 0L18 6c.7.7.7 2 0 2.7l-2.9 2.9-1.8-1.8-.5-.6"/></g></svg>',
12654        'home': '<svg width="24" height="24"><path fill-rule="nonzero" d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></svg>',
12655        'horizontal-rule': '<svg width="24" height="24"><path d="M4 11h16v2H4z" fill-rule="evenodd"/></svg>',
12656        'image-options': '<svg width="24" height="24"><path d="M6 10a2 2 0 0 0-2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2zm12 0a2 2 0 0 0-2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2zm-6 0a2 2 0 0 0-2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2z" fill-rule="nonzero"/></svg>',
12657        'image': '<svg width="24" height="24"><path d="M5 15.7l3.3-3.2c.3-.3.7-.3 1 0L12 15l4.1-4c.3-.4.8-.4 1 0l2 1.9V5H5v10.7zM5 18V19h3l2.8-2.9-2-2L5 17.9zm14-3l-2.5-2.4-6.4 6.5H19v-4zM4 3h16c.6 0 1 .4 1 1v16c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V4c0-.6.4-1 1-1zm6 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4z" fill-rule="nonzero"/></svg>',
12658        'indent': '<svg width="24" height="24"><path d="M7 5h12c.6 0 1 .4 1 1s-.4 1-1 1H7a1 1 0 1 1 0-2zm5 4h7c.6 0 1 .4 1 1s-.4 1-1 1h-7a1 1 0 0 1 0-2zm0 4h7c.6 0 1 .4 1 1s-.4 1-1 1h-7a1 1 0 0 1 0-2zm-5 4h12a1 1 0 0 1 0 2H7a1 1 0 0 1 0-2zm-2.6-3.8L6.2 12l-1.8-1.2a1 1 0 0 1 1.2-1.6l3 2a1 1 0 0 1 0 1.6l-3 2a1 1 0 1 1-1.2-1.6z" fill-rule="evenodd"/></svg>',
12659        'info': '<svg width="24" height="24">
12659<path d="M12 4a7.8 7.8 0 0 1 5.7 2.3A8 8 0 1 1 12 4zm-1 3v2h2V7h-2zm3 10v-1h-1v-5h-3v1h1v4h-1v1h4z" fill-rule="evenodd"/></svg>',
12660        'insert-character': '<svg width="24" height="24"><path d="M15 18h4l1-2v4h-6v-3.3l1.4-1a6 6 0 0 0 1.8-2.9 6.3 6.3 0 0 0-.1-4.1 5.8 5.8 0 0 0-3-3.2c-.6-.3-1.3-.5-2.1-.5a5.1 5.1 0 0 0-3.9 1.8 6.3 6.3 0 0 0-1.3 6 6.2 6.2 0 0 0 1.8 3l1.4.9V20H4v-4l1 2h4v-.5l-2-1L5.4 15A6.5 6.5 0 0 1 4 11c0-1 .2-1.9.6-2.7A7 7 0 0 1 6.3 6C7.1 5.4 8 5 9 4.5c1-.3 2-.5 3.1-.5a8.8 8.8 0 0 1 5.7 2 7 7 0 0 1 1.7 2.3 6 6 0 0 1 .2 4.8c-.2.7-.6 1.3-1 1.9a7.6 7.6 0 0 1-3.6 2.5v.5z" fill-rule="evenodd"/></svg>',
12661        'insert-time': '<svg width="24" height="24"><g fill-rule="nonzero"><path d="M12 19a7 7 0 1 0 0-14 7 7 0 0 0 0 14zm0 2a9 9 0 1 1 0-18 9 9 0 0 1 0 18z"/><path d="M16 12h-3V7c0-.6-.4-1-1-1a1 1 0 0 0-1 1v7h5c.6 0 1-.4 1-1s-.4-1-1-1z"/></g></svg>',
12662        'invert': '<svg width="24" height="24"><path d="M18 19.3L16.5 18a5.8 5.8 0 0 1-3.1 1.9 6.1 6.1 0 0 1-5.5-1.6A5.8 5.8 0 0 1 6 14v-.3l.1-1.2A13.9 13.9 0 0 1 7.7 9l-3-3 .7-.8 2.8 2.9 9 8.9 1.5 1.6-.7.6zm0-5.5v.3l-.1 1.1-.4 1-1.2-1.2a4.3 4.3 0 0 0 .2-1v-.2c0-.4 0-.8-.2-1.3l-.5-1.4a14.8 14.8 0 0 0-3-4.2L12 6a26.1 26.1 0 0 0-2.2 2.5l-1-1a20.9 20.9 0 0 1 2.9-3.3L12 4l1 .8a22.2 22.2 0 0 1 4 5.4c.6 1.2 1 2.4 1 3.6z" fill-rule="evenodd"/></svg>',
12663        'italic': '<svg width="24" height="24"><path d="M16.7 4.7l-.1.9h-.3c-.6 0-1 0-1.4.3-.3.3-.4.6-.5 1.1l-2.1 9.8v.6c0 .5.4.8 1.4.8h.2l-.2.8H8l.2-.8h.2c1.1 0 1.8-.5 2-1.5l2-9.8.1-.5c0-.6-.4-.8-1.4-.8h-.3l.2-.9h5.8z" fill-rule="evenodd"/></svg>',
12664        'line': '<svg width="24" height="24"><path d="M15 9l-8 8H4v-3l8-8 3 3zm1-1l-3-3 1-1h1c-.2 0 0 0 0 0l2 2s0 .2 0 0v1l-1 1zM4 18h16v2H4v-2z" fill-rule="evenodd"/></svg>',
12665        'link': '<svg width="24" height="24"><path d="M6.2 12.3a1 1 0 0 1 1.4 1.4l-2.1 2a2 2 0 1 0 2.7 2.8l4.8-4.8a1 1 0 0 0 0-1.4 1 1 0 1 1 1.4-1.3 2.9 2.9 0 0 1 0 4L9.6 20a3.9 3.9 0 0 1-5.5-5.5l2-2zm11.6-.6a1 1 0 0 1-1.4-1.4l2-2a2 2 0 1 0-2.6-2.8L11 10.3a1 1 0 0 0 0 1.4A1 1 0 1 1 9.6 13a2.9 2.9 0 0 1 0-4L14.4 4a3.9 3.9 0 0 1 5.5 5.5l-2 2z" fill-rule="nonzero"/></svg>',
12666        'list-bull-circle': '<svg width="48" height="48"><g fill-rule="evenodd"><path d="M11 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0 1a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM11 26a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0 1a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM11 36a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0 1a3 3 0 1 1 0-6 3 3 0 0 1 0 6z" fill-rule="nonzero"/><path opacity=".2" d="M18 12h22v4H18zM18 22h22v4H18zM18 32h22v4H18z"/></g></svg>',
12667        'list-bull-default': '<svg width="48" height="48"><g fill-rule="evenodd"><circle cx="11" cy="14" r="3"/><circle cx="11" cy="24" r="3"/><circle cx="11" cy="34" r="3"/><path opacity=".2" d="M18 12h22v4H18zM18 22h22v4H18zM18 32h22v4H18z"/></g></svg>',
12668        'list-bull-square': '<svg width="48" height="48"><g fill-rule="evenodd"><path d="M8 11h6v6H8zM8 21h6v6H8zM8 31h6v6H8z"/><path opacity=".2" d="M18 12h22v4H18zM18 22h22v4H18zM18 32h22v4H18z"/></g></svg>',
12669        'list-num-default': '<svg width="48" height="48"><g fill-rule="evenodd"><path opacity=".2" d="M18 12h22v4H18zM18 22h22v4H18zM18 32h22v4H18z"/><path d="M10 17v-4.8l-1.5 1v-1.1l1.6-1h1.2V17h-1.2zm3.6.1c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7.5 0 .7.3.7.7 0 .4-.2.7-.7.7zm-5 5.7c0-1.2.8-2 2.1-2s2.1.8 2.1 1.8c0 .7-.3 1.2-1.4 2.2l-1.1 1v.2h2.6v1H8.6v-.9l2-1.9c.8-.8 1-1.1 1-1.5 0-.5-.4-.8-1-.8-.5 0-.9.3-.9.9H8.5zm6.3 4.3c-.5 0-.7-.3-.7-.7 0-.4.2-.7.7-.7.4 0 .7.3.7.7 0 .4-.3.7-.7.7zM10 34.4v-1h.7c.6 0 1-.3 1-.8 0-.4-.4-.7-1-.7s-1 .3-1 .8H8.6c0-1.1 1-1.8 2.2-1.8 1.3 0 2.1.6 2.1 1.6 0 .7-.4 1.2-1 1.3v.1c.8.1 1.3.7 1.3 1.4 0 1-1 1.9-2.4 1.9-1.3 0-2.2-.8-2.3-2h1.2c0 .6.5 1 1.1 1 .7 0 1-.4 1-1 0-.5-.3-.8-1-.8h-.7zm4.7 2.7c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7.5 0 .8.3.8.7 0 .4-.3.7-.8.7z"/></g></svg>',
12670        'list-num-lower-alpha': '<svg width="48" height="48"><g fill-rule="evenodd"><path opacity=".2" d="M18 12h22v4H18zM18 22h22v4H18zM18 32h22v4H18z"/><path d="M10.3 15.2c.5 0 1-.4 1-.9V14h-1c-.5.1-.8.3-.8.6 0 .4.3.6.8.6zm-.4.9c-1 0-1.5-.6-1.5-1.4 0-.8.6-1.3 1.7-1.4h1.1v-.4c0-.4-.2-.6-.7-.6-.5 0-.8.1-.9.4h-1c0-.8.8-1.4 2-1.4 1.1 0 1.8.6 1.8 1.6V16h-1.1v-.6h-.1c-.2.4-.7.7-1.3.7zm4.6 0c-.5 0-.7-.3-.7-.7 0-.4.2-.7.7-.7.4 0 .7.3.7.7 0 .4-.3.7-.7.7zm-3.2 10c-.6 0-1.2-.3-1.4-.8v.7H8.5v-6.3H10v2.5c.3-.5.8-.9 1.4-.9 1.2 0 1.9 1 1.9 2.4 0 1.5-.7 2.4-1.9 2.4zm-.4-3.7c-.7 0-1 .5-1 1.3s.3 1.4 1 1.4c.6 0 1-.6 1-1.4 0-.8-.4-1.3-1-1.3zm4 3.7c-.5 0-.7-.3-.7-.7 0-.4.2-.7.7-.7.4 0 .7.3.7.7 0 .4-.3.7-.7.7zm-2.2 7h-1.2c0-.5-.4-.8-.9-.8-.6 0-1 .5-1 1.4 0 1 .4 1.4 1 1.4.5 0 .8-.2 1-.7h1c0 1-.8 1.7-2 1.7-1.4 0-2.2-.9-2.2-2.4s.8-2.4 2.2-2.4c1.2 0 2 .7 2 1.7zm1.8 3c-.5 0-.8-.3-.8-.7 0-.4.3-.7.8-.7.4 0 .7.3.7.7 0 .4-.3.7-.7.7z"/></g></svg>',
12671        'list-num-lower-greek': '<svg width="48" height="48"><g fill-rule="evenodd"><path opacity=".2" d="M18 12h22v4H18zM18 22h22v4H18zM18 32h22v4H18z"/><path d="M10.5 15c.7 0 1-.5 1-1.3s-.3-1.3-1-1.3c-.5 0-.9.5-.9 1.3s.4 1.4 1 1.4zm-.3 1c-1.1 0-1.8-.8-1.8-2.3 0-1.5.7-2.4 1.8-2.4.7 0 1.1.4 1.3 1h.1v-.9h1.2v3.2c0 .4.1.5.4.5h.2v.9h-.6c-.6 0-1-.2-1.1-.7h-.1c-.2.4-.7.8-1.4.8zm5 .1c-.5 0-.8-.3-.8-.7 0-.4.3-.7.7-.7.5 0 .8.3.8.7 0 .4-.3.7-.8.7zm-4.9 7v-1h.3c.6 0 1-.2 1-.7 0-.5-.4-.8-1-.8-.5 0-.8.3-.8 1v2.2c0 .8.4 1.3 1.1 1.3.6 0 1-.4 1-1s-.5-1-1.3-1h-.3zM8.6 22c0-1.5.7-2.3 2-2.3 1.2 0 2 .6 2 1.6 0 .6-.3 1-.8 1.3.8.3 1.3.8 1.3 1.7 0 1.2-.8 1.9-1.9 1.9-.6 0-1.1-.3-1.3-.8v2.2H8.5V22zm6.2 4.2c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7.5 0 .7.3.7.7 0 .4-.2.7-.7.7zm-4.5 8.5L8 30h1.4l1.7 3.5 1.7-3.5h1.1l-2.2 4.6v.1c.5.8.7 1.4.7 1.8 0 .4-.1.8-.4 1-.2.2-.6.3-1 .3-.9 0-1.3-.4-1.3-1.2 0-.5.2-1 .5-1.7l.1-.2zm.7 1a2 2 0 0 0-.4.9c0 .3.1.4.4.4.3 0 .4-.1.4-.4 0-.2-.1-.6-.4-1zm4.5.5c-.5 0-.8-.3-.8-.7 0-.4.3-.7.8-.7.4 0 .7.3.7.7 0 .4-.3.7-.7.7z"/></g></svg>',
12672        'list-num-lower-roman': '<svg width="48" height="48"><g fill-rule="evenodd"><path opacity=".2" d="M18 12h22v4H18zM18 22h22v4H18zM18 32h22v4H18z"/><path d="M15.1 16v-1.2h1.3V16H15zm0 10v-1.2h1.3V26H15zm0 10v-1.2h1.3V36H15z"/><path fill-rule="nonzero" d="M12 21h1.5v5H12zM12 31h1.5v5H12zM9 21h1.5v5H9zM9 31h1.5v5H9zM6 31h1.5v5H6zM12 11h1.5v5H12zM12 19h1.5v1H12zM12 29h1.5v1H12zM9 19h1.5v1H9zM9 29h1.5v1H9zM6 29h1.5v1H6zM12 9h1.5v1H12z"/></g></svg>',
12673        'list-num-upper-alpha': '<svg width="48" height="48"><g fill-rule="evenodd"><path opacity=".2" d="M18 12h22v4H18zM18 22h22v4H18zM18 32h22v4H18z"/><path d="M12.6 17l-.5-1.4h-2L9.5 17H8.3l2-6H12l2 6h-1.3zM11 12.3l-.7 2.3h1.6l-.8-2.3zm4.7 4.8c-.4 0-.7-.3-.7-.7 0-.4.3-.7.7-.7.5 0 .7.3.7.7 0 .4-.2.7-.7.7zM11.4 27H8.7v-6h2.6c1.2 0 1.9.6 1.9 1.5 0 .6-.5 1.2-1 1.3.7.1 1.3.7 1.3 1.5 0 1-.8 1.7-2 1.7zM10 22v1.5h1c.6 0 1-.3 1-.8 0-.4-.4-.7-1-.7h-1zm0 4H11c.7 0 1.1-.3 1.1-.8 0-.6-.4-.9-1.1-.9H10V26zm5.4 1.1c-.5 0-.8-.3-.8-.7 0-.4.3-.7.8-.7.4 0 .7.3.7.7 0 .4-.3.7-.7.7zm-4.1 10c-1.8 0-2.8-1.1-2.8-3.1s1-3.1 2.8-3.1c1.4 0 2.5.9 2.6 2.2h-1.3c0-.7-.6-1.1-1.3-1.1-1 0-1.6.7-1.6 2s.6 2 1.6 2c.7 0 1.2-.4 1.4-1h1.2c-.1 1.3-1.2 2.2-2.6 2.2zm4.5 0c-.5 0-.8-.3-.8-.7 0-.4.3-.7.8-.7.4 0 .7.3.7.7 0 .4-.3.7-.7.7z"/></g></svg>',
12674        'list-num-upper-roman': '<svg width="48" height="48"><g fill-rule="evenodd"><path opacity=".2" d="M18 12h22v4H18zM18 22h22v4H18zM18 32h22v4H18z"/><path d="M15.1 17v-1.2h1.3V17H15zm0 10v-1.2h1.3V27H15zm0 10v-1.2h1.3V37H15z"/><path fill-rule="nonzero" d="M12 20h1.5v7H12zM12 30h1.5v7H12zM9 20h1.5v7H9zM9 30h1.5v7H9zM6 30h1.5v7H6zM12 10h1.5v7H12z"/></g></svg>',
12675        'lock': '<svg width="24" height="24">
12675<path d="M16.3 11c.2 0 .3 0 .5.2l.2.6v7.4c0 .3 0 .4-.2.6l-.6.2H7.8c-.3 0-.4 0-.6-.2a.7.7 0 0 1-.2-.6v-7.4c0-.3 0-.4.2-.6l.5-.2H8V8c0-.8.3-1.5.9-2.1.6-.6 1.3-.9 2.1-.9h2c.8 0 1.5.3 2.1.9.6.6.9 1.3.9 2.1v3h.3zM10 8v3h4V8a1 1 0 0 0-.3-.7A1 1 0 0 0 13 7h-2a1 1 0 0 0-.7.3 1 1 0 0 0-.3.7z" fill-rule="evenodd"/></svg>',
12676        'ltr': '<svg width="24" height="24"><path d="M11 5h7a1 1 0 0 1 0 2h-1v11a1 1 0 0 1-2 0V7h-2v11a1 1 0 0 1-2 0v-6c-.5 0-1 0-1.4-.3A3.4 3.4 0 0 1 7.8 10a3.3 3.3 0 0 1 0-2.8 3.4 3.4 0 0 1 1.8-1.8L11 5zM4.4 16.2L6.2 15l-1.8-1.2a1 1 0 0 1 1.2-1.6l3 2a1 1 0 0 1 0 1.6l-3 2a1 1 0 1 1-1.2-1.6z" fill-rule="evenodd"/></svg>',
12677        'more-drawer': '<svg width="24" height="24"><path d="M6 10a2 2 0 0 0-2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2zm12 0a2 2 0 0 0-2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2zm-6 0a2 2 0 0 0-2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2z" fill-rule="nonzero"/></svg>',
12678        'new-document': '<svg width="24" height="24"><path d="M14.4 3H7a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h10a2 2 0 0 0 2-2V7.6L14.4 3zM17 19H7V5h6v4h4v10z" fill-rule="nonzero"/></svg>',
12679        'new-tab': '<svg width="24" height="24"><path d="M15 13l2-2v8H5V7h8l-2 2H7v8h8v-4zm4-8v5.5l-2-2-5.6 5.5H10v-1.4L15.5 7l-2-2H19z" fill-rule="evenodd"/></svg>',
12680        'non-breaking': '<svg width="24" height="24"><path d="M11 11H8a1 1 0 1 1 0-2h3V6c0-.6.4-1 1-1s1 .4 1 1v3h3c.6 0 1 .4 1 1s-.4 1-1 1h-3v3c0 .6-.4 1-1 1a1 1 0 0 1-1-1v-3zm10 4v5H3v-5c0-.6.4-1 1-1s1 .4 1 1v3h14v-3c0-.6.4-1 1-1s1 .4 1 1z" fill-rule="evenodd"/></svg>',
12681        'notice': '<svg width="24" height="24"><path d="M17.8 9.8L15.4 4 20 8.5v7L15.5 20h-7L4 15.5v-7L8.5 4h7l2.3 5.8zm0 0l2.2 5.7-2.3-5.8zM13 17v-2h-2v2h2zm0-4V7h-2v6h2z" fill-rule="evenodd"/></svg>',
12682        'ordered-list': '<svg width="24" height="24"><path d="M10 17h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zm0-6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zm0-6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 1 1 0-2zM6 4v3.5c0 .3-.2.5-.5.5a.5.5 0 0 1-.5-.5V5h-.5a.5.5 0 0 1 0-1H6zm-1 8.8l.2.2h1.3c.3 0 .5.2.5.5s-.2.5-.5.5H4.9a1 1 0 0 1-.9-1V13c0-.4.3-.8.6-1l1.2-.4.2-.3a.2.2 0 0 0-.2-.2H4.5a.5.5 0 0 1-.5-.5c0-.3.2-.5.5-.5h1.6c.5 0 .9.4.9 1v.1c0 .4-.3.8-.6 1l-1.2.4-.2.3zM7 17v2c0 .6-.4 1-1 1H4.5a.5.5 0 0 1 0-1h1.2c.2 0 .3-.1.3-.3 0-.2-.1-.3-.3-.3H4.4a.4.4 0 1 1 0-.8h1.3c.2 0 .3-.1.3-.3 0-.2-.1-.3-.3-.3H4.5a.5.5 0 1 1 0-1H6c.6 0 1 .4 1 1z" fill-rule="evenodd"/></svg>',
12683        'orientation': '<svg width="24" height="24"><path d="M7.3 6.4L1 13l6.4 6.5 6.5-6.5-6.5-6.5zM3.7 13l3.6-3.7L11 13l-3.7 3.7-3.6-3.7zM12 6l2.8 2.7c.3.3.3.8 0 1-.3.4-.9.4-1.2 0L9.2 5.7a.8.8 0 0 1 0-1.2L13.6.2c.3-.3.9-.3 1.2 0 .3.3.3.8 0 1.1L12 4h1a9 9 0 1 1-4.3 16.9l1.5-1.5A7 7 0 1 0 13 6h-1z" fill-rule="nonzero"/></svg>',
12684        'outdent': '<svg width="24" height="24"><path d="M7 5h12c.6 0 1 .4 1 1s-.4 1-1 1H7a1 1 0 1 1 0-2zm5 4h7c.6 0 1 .4 1 1s-.4 1-1 1h-7a1 1 0 0 1 0-2zm0 4h7c.6 0 1 .4 1 1s-.4 1-1 1h-7a1 1 0 0 1 0-2zm-5 4h12a1 1 0 0 1 0 2H7a1 1 0 0 1 0-2zm1.6-3.8a1 1 0 0 1-1.2 1.6l-3-2a1 1 0 0 1 0-1.6l3-2a1 1 0 0 1 1.2 1.6L6.8 12l1.8 1.2z" fill-rule="evenodd"/></svg>',
12685        'page-break': '<svg width="24" height="24"><g fill-rule="evenodd"><path d="M5 11c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 0 1 0-2zm3 0h1c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 0 1 0-2zm4 0c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 0 1 0-2zm3 0h1c.6 0 1 .4 1 1s-.4 1-1 1h-1a1 1 0 0 1 0-2zm4 0c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 0 1 0-2zM7 3v5h10V3c0-.6.4-1 1-1s1 .4 1 1v7H5V3c0-.6.4-1 1-1s1 .4 1 1zM6 22a1 1 0 0 1-1-1v-7h14v7c0 .6-.4 1-1 1a1 1 0 0 1-1-1v-5H7v5c0 .6-.4 1-1 1z"/></g></svg>',
12686        'paragraph': '<svg width="24" height="24"><path d="M10 5h7a1 1 0 0 1 0 2h-1v11a1 1 0 0 1-2 0V7h-2v11a1 1 0 0 1-2 0v-6c-.5 0-1 0-1.4-.3A3.4 3.4 0 0 1 6.8 10a3.3 3.3 0 0 1 0-2.8 3.4 3.4 0 0 1 1.8-1.8L10 5z" fill-rule="evenodd"/></svg>',
12687        'paste-text': '<svg width="24" height="24"><path d="M18 9V5h-2v1c0 .6-.4 1-1 1H9a1 1 0 0 1-1-1V5H6v13h3V9h9zM9 20H6a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2h3.2A3 3 0 0 1 12 1a3 3 0 0 1 2.8 2H18a2 2 0 0 1 2 2v4h1v12H9v-1zm1.5-9.5v9h9v-9h-9zM12 3a1 1 0 0 0-1 1c0 .5.4 1 1 1s1-.5 1-1-.4-1-1-1zm0 9h6v2h-.5l-.5-1h-1v4h.8v1h-3.6v-1h.8v-4h-1l-.5 1H12v-2z" fill-rule="nonzero"/></svg>',
12688        'paste': '<svg width="24" height="24">
12688<path d="M18 9V5h-2v1c0 .6-.4 1-1 1H9a1 1 0 0 1-1-1V5H6v13h3V9h9zM9 20H6a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2h3.2A3 3 0 0 1 12 1a3 3 0 0 1 2.8 2H18a2 2 0 0 1 2 2v4h1v12H9v-1zm1.5-9.5v9h9v-9h-9zM12 3a1 1 0 0 0-1 1c0 .5.4 1 1 1s1-.5 1-1-.4-1-1-1z" fill-rule="nonzero"/></svg>',
12689        'permanent-pen': '<svg width="24" height="24"><path d="M10.5 17.5L8 20H3v-3l3.5-3.5a2 2 0 0 1 0-3L14 3l1 1-7.3 7.3a1 1 0 0 0 0 1.4l3.6 3.6c.4.4 1 .4 1.4 0L20 9l1 1-7.6 7.6a2 2 0 0 1-2.8 0l-.1-.1z" fill-rule="nonzero"/></svg>',
12690        'plus': '<svg width="24" height="24"><g fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke="#000" stroke-width="2"><path d="M12 5v14M5 12h14"/></g></svg>',
12691        'preferences': '<svg width="24" height="24"><path d="M20.1 13.5l-1.9.2a5.8 5.8 0 0 1-.6 1.5l1.2 1.5c.4.4.3 1 0 1.4l-.7.7a1 1 0 0 1-1.4 0l-1.5-1.2a6.2 6.2 0 0 1-1.5.6l-.2 1.9c0 .5-.5.9-1 .9h-1a1 1 0 0 1-1-.9l-.2-1.9a5.8 5.8 0 0 1-1.5-.6l-1.5 1.2a1 1 0 0 1-1.4 0l-.7-.7a1 1 0 0 1 0-1.4l1.2-1.5a6.2 6.2 0 0 1-.6-1.5l-1.9-.2a1 1 0 0 1-.9-1v-1c0-.5.4-1 .9-1l1.9-.2a5.8 5.8 0 0 1 .6-1.5L5.2 7.3a1 1 0 0 1 0-1.4l.7-.7a1 1 0 0 1 1.4 0l1.5 1.2a6.2 6.2 0 0 1 1.5-.6l.2-1.9c0-.5.5-.9 1-.9h1c.5 0 1 .4 1 .9l.2 1.9a5.8 5.8 0 0 1 1.5.6l1.5-1.2a1 1 0 0 1 1.4 0l.7.7c.3.4.4 1 0 1.4l-1.2 1.5a6.2 6.2 0 0 1 .6 1.5l1.9.2c.5 0 .9.5.9 1v1c0 .5-.4 1-.9 1zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" fill-rule="evenodd"/></svg>',
12692        'preview': '<svg width="24" height="24"><path d="M3.5 12.5c.5.8 1.1 1.6 1.8 2.3 2 2 4.2 3.2 6.7 3.2s4.7-1.2 6.7-3.2a16.2 16.2 0 0 0 2.1-2.8 15.7 15.7 0 0 0-2.1-2.8c-2-2-4.2-3.2-6.7-3.2a9.3 9.3 0 0 0-6.7 3.2A16.2 16.2 0 0 0 3.2 12c0 .2.2.3.3.5zm-2.4-1l.7-1.2L4 7.8C6.2 5.4 8.9 4 12 4c3 0 5.8 1.4 8.1 3.8a18.2 18.2 0 0 1 2.8 3.7v1l-.7 1.2-2.1 2.5c-2.3 2.4-5 3.8-8.1 3.8-3 0-5.8-1.4-8.1-3.8a18.2 18.2 0 0 1-2.8-3.7 1 1 0 0 1 0-1zm12-3.3a2 2 0 1 0 2.7 2.6 4 4 0 1 1-2.6-2.6z" fill-rule="nonzero"/></svg>',
12693        'print': '<svg width="24" height="24"><path d="M18 8H6a3 3 0 0 0-3 3v6h2v3h14v-3h2v-6a3 3 0 0 0-3-3zm-1 10H7v-4h10v4zm.5-5c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm.5-8H6v2h12V5z" fill-rule="nonzero"/></svg>',
12694        'quote': '<svg width="24" height="24"><path d="M7.5 17h.9c.4 0 .7-.2.9-.6L11 13V8c0-.6-.4-1-1-1H6a1 1 0 0 0-1 1v4c0 .6.4 1 1 1h2l-1.3 2.7a1 1 0 0 0 .8 1.3zm8 0h.9c.4 0 .7-.2.9-.6L19 13V8c0-.6-.4-1-1-1h-4a1 1 0 0 0-1 1v4c0 .6.4 1 1 1h2l-1.3 2.7a1 1 0 0 0 .8 1.3z" fill-rule="nonzero"/></svg>',
12695        'redo': '<svg width="24" height="24"><path d="M17.6 10H12c-2.8 0-4.4 1.4-4.9 3.5-.4 2 .3 4 1.4 4.6a1 1 0 1 1-1 1.8c-2-1.2-2.9-4.1-2.3-6.8.6-3 3-5.1 6.8-5.1h5.6l-3.3-3.3a1 1 0 1 1 1.4-1.4l5 5a1 1 0 0 1 0 1.4l-5 5a1 1 0 0 1-1.4-1.4l3.3-3.3z" fill-rule="nonzero"/></svg>',
12696        'reload': '<svg width="24" height="24"><g fill-rule="nonzero"><path d="M5 22.1l-1.2-4.7v-.2a1 1 0 0 1 1-1l5 .4a1 1 0 1 1-.2 2l-2.2-.2a7.8 7.8 0 0 0 8.4.2 7.5 7.5 0 0 0 3.5-6.4 1 1 0 1 1 2 0 9.5 9.5 0 0 1-4.5 8 9.9 9.9 0 0 1-10.2 0l.4 1.4a1 1 0 1 1-2 .5zM13.6 7.4c0-.5.5-1 1-.9l2.8.2a8 8 0 0 0-9.5-1 7.5 7.5 0 0 0-3.6 7 1 1 0 0 1-2 0 9.5 9.5 0 0 1 4.5-8.6 10 10 0 0 1 10.9.3l-.3-1a1 1 0 0 1 2-.5l1.1 4.8a1 1 0 0 1-1 1.2l-5-.4a1 1 0 0 1-.9-1z"/></g></svg>',
12697        'remove-formatting': '<svg width="24" height="24"><path d="M13.2 6a1 1 0 0 1 0 .2l-2.6 10a1 1 0 0 1-1 .8h-.2a.8.8 0 0 1-.8-1l2.6-10H8a1 1 0 1 1 0-2h9a1 1 0 0 1 0 2h-3.8zM5 18h7a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zm13 1.5L16.5 18 15 19.5a.7.7 0 0 1-1-1l1.5-1.5-1.5-1.5a.7.7 0 0 1 1-1l1.5 1.5 1.5-1.5a.7.7 0 0 1 1 1L17.5 17l1.5 1.5a.7.7 0 0 1-1 1z" fill-rule="evenodd"/></svg>',
12698        'remove': '<svg width="24" height="24"><path d="M16 7h3a1 1 0 0 1 0 2h-1v9a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V9H5a1 1 0 1 1 0-2h3V6a3 3 0 0 1 3-3h2a3 3 0 0 1 3 3v1zm-2 0V6c0-.6-.4-1-1-1h-2a1 1 0 0 0-1 1v1h4zm2 2H8v9c0 .6.4 1 1 1h6c.6 0 1-.4 1-1V9zm-7 3a1 1 0 0 1 2 0v4a1 1 0 0 1-2 0v-4zm4 0a1 1 0 0 1 2 0v4a1 1 0 0 1-2 0v-4z" fill-rule="nonzero"/></svg>',
12699        'resize-handle': '<svg width="10" height="10"><g fill-rule="nonzero"><path d="M8.1 1.1A.5.5 0 1 1 9 2l-7 7A.5.5 0 1 1 1 8l7-7zM8.1 5.1A.5.5 0 1 1 9 6l-3 3A.5.5 0 1 1 5 8l3-3z"/></g></svg>',
12700        'resize': '<svg width="24" height="24">
12700<path d="M4 5c0-.3.1-.5.3-.7.2-.2.4-.3.7-.3h6c.3 0 .5.1.7.3.2.2.3.4.3.7 0 .3-.1.5-.3.7a1 1 0 0 1-.7.3H7.4L18 16.6V13c0-.3.1-.5.3-.7.2-.2.4-.3.7-.3.3 0 .5.1.7.3.2.2.3.4.3.7v6c0 .3-.1.5-.3.7a1 1 0 0 1-.7.3h-6a1 1 0 0 1-.7-.3 1 1 0 0 1-.3-.7c0-.3.1-.5.3-.7.2-.2.4-.3.7-.3h3.6L6 7.4V11c0 .3-.1.5-.3.7a1 1 0 0 1-.7.3 1 1 0 0 1-.7-.3A1 1 0 0 1 4 11V5z" fill-rule="evenodd"/></svg>',
12701        'restore-draft': '<svg width="24" height="24"><g fill-rule="evenodd"><path d="M17 13c0 .6-.4 1-1 1h-4V8c0-.6.4-1 1-1s1 .4 1 1v4h2c.6 0 1 .4 1 1z"/><path d="M4.7 10H9a1 1 0 0 1 0 2H3a1 1 0 0 1-1-1V5a1 1 0 1 1 2 0v3l2.5-2.4a9.2 9.2 0 0 1 10.8-1.5A9 9 0 0 1 13.4 21c-2.4.1-4.7-.7-6.5-2.2a1 1 0 1 1 1.3-1.5 7.2 7.2 0 0 0 11.6-3.7 7 7 0 0 0-3.5-7.7A7.2 7.2 0 0 0 8 7L4.7 10z" fill-rule="nonzero"/></g></svg>',
12702        'rotate-left': '<svg width="24" height="24"><path d="M4.7 10H9a1 1 0 0 1 0 2H3a1 1 0 0 1-1-1V5a1 1 0 1 1 2 0v3l2.5-2.4a9.2 9.2 0 0 1 10.8-1.5A9 9 0 0 1 13.4 21c-2.4.1-4.7-.7-6.5-2.2a1 1 0 1 1 1.3-1.5 7.2 7.2 0 0 0 11.6-3.7 7 7 0 0 0-3.5-7.7A7.2 7.2 0 0 0 8 7L4.7 10z" fill-rule="nonzero"/></svg>',
12703        'rotate-right': '<svg width="24" height="24"><path d="M20 8V5a1 1 0 0 1 2 0v6c0 .6-.4 1-1 1h-6a1 1 0 0 1 0-2h4.3L16 7A7.2 7.2 0 0 0 7.7 6a7 7 0 0 0 3 13.1c1.9.1 3.7-.5 5-1.7a1 1 0 0 1 1.4 1.5A9.2 9.2 0 0 1 2.2 14c-.9-3.9 1-8 4.5-9.9 3.5-1.9 8-1.3 10.8 1.5L20 8z" fill-rule="nonzero"/></svg>',
12704        'rtl': '<svg width="24" height="24"><path d="M8 5h8v2h-2v12h-2V7h-2v12H8v-7c-.5 0-1 0-1.4-.3A3.4 3.4 0 0 1 4.8 10a3.3 3.3 0 0 1 0-2.8 3.4 3.4 0 0 1 1.8-1.8L8 5zm12 11.2a1 1 0 1 1-1 1.6l-3-2a1 1 0 0 1 0-1.6l3-2a1 1 0 1 1 1 1.6L18.4 15l1.8 1.2z" fill-rule="evenodd"/></svg>',
12705        'save': '<svg width="24" height="24"><path d="M5 16h14a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-2c0-1.1.9-2 2-2zm0 2v2h14v-2H5zm10 0h2v2h-2v-2zm-4-6.4L8.7 9.3a1 1 0 1 0-1.4 1.4l4 4c.4.4 1 .4 1.4 0l4-4a1 1 0 1 0-1.4-1.4L13 11.6V4a1 1 0 0 0-2 0v7.6z" fill-rule="nonzero"/></svg>',
12706        'search': '<svg width="24" height="24"><path d="M16 17.3a8 8 0 1 1 1.4-1.4l4.3 4.4a1 1 0 0 1-1.4 1.4l-4.4-4.3zm-5-.3a6 6 0 1 0 0-12 6 6 0 0 0 0 12z" fill-rule="nonzero"/></svg>',
12707        'select-all': '<svg width="24" height="24"><path d="M3 5h2V3a2 2 0 0 0-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2a2 2 0 0 0-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8a2 2 0 0 0 2-2h-2v2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM7 17h10V7H7v10zm2-8h6v6H9V9z" fill-rule="nonzero"/></svg>',
12708        'selected': '<svg width="24" height="24"><path fill-rule="nonzero" d="M6 4h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2zm3.6 10.9L7 12.3a.7.7 0 0 0-1 1L9.6 17 18 8.6a.7.7 0 0 0 0-1 .7.7 0 0 0-1 0l-7.4 7.3z"/></svg>',
12709        'settings': '<svg width="24" height="24"><path d="M11 6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8v.3c0 .2 0 .3-.2.5l-.6.2H7.8c-.3 0-.4 0-.6-.2a.7.7 0 0 1-.2-.6V8H5a1 1 0 1 1 0-2h2v-.3c0-.2 0-.3.2-.5l.5-.2h2.5c.3 0 .4 0 .6.2l.2.5V6zM8 8h2V6H8v2zm9 2.8v.2h2c.6 0 1 .4 1 1s-.4 1-1 1h-2v.3c0 .2 0 .3-.2.5l-.6.2h-2.4c-.3 0-.4 0-.6-.2a.7.7 0 0 1-.2-.6V13H5a1 1 0 0 1 0-2h8v-.3c0-.2 0-.3.2-.5l.6-.2h2.4c.3 0 .4 0 .6.2l.2.6zM14 13h2v-2h-2v2zm-3 2.8v.2h8c.6 0 1 .4 1 1s-.4 1-1 1h-8v.3c0 .2 0 .3-.2.5l-.6.2H7.8c-.3 0-.4 0-.6-.2a.7.7 0 0 1-.2-.6V18H5a1 1 0 0 1 0-2h2v-.3c0-.2 0-.3.2-.5l.5-.2h2.5c.3 0 .4 0 .6.2l.2.6zM8 18h2v-2H8v2z" fill-rule="evenodd"/></svg>',
12710        'sharpen': '<svg width="24" height="24"><path d="M16 6l4 4-8 9-8-9 4-4h8zm-4 10.2l5.5-6.2-.1-.1H12v-.3h5.1l-.2-.2H12V9h4.6l-.2-.2H12v-.3h4.1l-.2-.2H12V8h3.6l-.2-.2H8.7L6.5 10l.1.1H12v.3H6.9l.2.2H12v.3H7.3l.2.2H12v.3H7.7l.3.2h4v.3H8.2l.2.2H12v.3H8.6l.3.2H12v.3H9l.3.2H12v.3H9.5l.2.2H12v.3h-2l.2.2H12v.3h-1.6l.2.2H12v.3h-1.1l.2.2h.9v.3h-.7l.2.2h.5v.3h-.3l.3.2z" fill-rule="evenodd"/></svg>',
12711        'sourcecode': '<svg width="24" height="24"><g fill-rule="nonzero"><path d="M9.8 15.7c.3.3.3.8 0 1-.3.4-.9.4-1.2 0l-4.4-4.1a.8.8 0 0 1 0-1.2l4.4-4.2c.3-.3.9-.3 1.2 0 .3.3.3.8 0 1.1L6 12l3.8 3.7zM14.2 15.7c-.3.3-.3.8 0 1 .4.4.9.4 1.2 0l4.4-4.1c.3-.3.3-.9 0-1.2l-4.4-4.2a.8.8 0 0 0-1.2 0c-.3.3-.3.8 0 1.1L18 12l-3.8 3.7z"/></g></svg>',
12712        'spell-check': '<svg width="24" height="24">
12712<path d="M6 8v3H5V5c0-.3.1-.5.3-.7.2-.2.4-.3.7-.3h2c.3 0 .5.1.7.3.2.2.3.4.3.7v6H8V8H6zm0-3v2h2V5H6zm13 0h-3v5h3v1h-3a1 1 0 0 1-.7-.3 1 1 0 0 1-.3-.7V5c0-.3.1-.5.3-.7.2-.2.4-.3.7-.3h3v1zm-5 1.5l-.1.7c-.1.2-.3.3-.6.3.3 0 .5.1.6.3l.1.7V10c0 .3-.1.5-.3.7a1 1 0 0 1-.7.3h-3V4h3c.3 0 .5.1.7.3.2.2.3.4.3.7v1.5zM13 10V8h-2v2h2zm0-3V5h-2v2h2zm3 5l1 1-6.5 7L7 15.5l1.3-1 2.2 2.2L16 12z" fill-rule="evenodd"/></svg>',
12713        'strike-through': '<svg width="24" height="24"><g fill-rule="evenodd"><path d="M15.6 8.5c-.5-.7-1-1.1-1.3-1.3-.6-.4-1.3-.6-2-.6-2.7 0-2.8 1.7-2.8 2.1 0 1.6 1.8 2 3.2 2.3 4.4.9 4.6 2.8 4.6 3.9 0 1.4-.7 4.1-5 4.1A6.2 6.2 0 0 1 7 16.4l1.5-1.1c.4.6 1.6 2 3.7 2 1.6 0 2.5-.4 3-1.2.4-.8.3-2-.8-2.6-.7-.4-1.6-.7-2.9-1-1-.2-3.9-.8-3.9-3.6C7.6 6 10.3 5 12.4 5c2.9 0 4.2 1.6 4.7 2.4l-1.5 1.1z"/><path d="M5 11h14a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2z" fill-rule="nonzero"/></g></svg>',
12714        'subscript': '<svg width="24" height="24"><path d="M10.4 10l4.6 4.6-1.4 1.4L9 11.4 4.4 16 3 14.6 7.6 10 3 5.4 4.4 4 9 8.6 13.6 4 15 5.4 10.4 10zM21 19h-5v-1l1-.8 1.7-1.6c.3-.4.5-.8.5-1.2 0-.3 0-.6-.2-.7-.2-.2-.5-.3-.9-.3a2 2 0 0 0-.8.2l-.7.3-.4-1.1 1-.6 1.2-.2c.8 0 1.4.3 1.8.7.4.4.6.9.6 1.5s-.2 1.1-.5 1.6a8 8 0 0 1-1.3 1.3l-.6.6h2.6V19z" fill-rule="nonzero"/></svg>',
12715        'superscript': '<svg width="24" height="24"><path d="M15 9.4L10.4 14l4.6 4.6-1.4 1.4L9 15.4 4.4 20 3 18.6 7.6 14 3 9.4 4.4 8 9 12.6 13.6 8 15 9.4zm5.9 1.6h-5v-1l1-.8 1.7-1.6c.3-.5.5-.9.5-1.3 0-.3 0-.5-.2-.7-.2-.2-.5-.3-.9-.3l-.8.2-.7.4-.4-1.2c.2-.2.5-.4 1-.5.3-.2.8-.2 1.2-.2.8 0 1.4.2 1.8.6.4.4.6 1 .6 1.6 0 .5-.2 1-.5 1.5l-1.3 1.4-.6.5h2.6V11z" fill-rule="nonzero"/></svg>',
12716        'table-cell-properties': '<svg width="24" height="24"><path d="M4 5h16v14H4V5zm10 10h-4v3h4v-3zm0-8h-4v3h4V7zM9 7H5v3h4V7zm-4 4v3h4v-3H5zm10 0v3h4v-3h-4zm0-1h4V7h-4v3zM5 15v3h4v-3H5zm10 3h4v-3h-4v3z" fill-rule="evenodd"/></svg>',
12717        'table-cell-select-all': '<svg width="24" height="24"><path d="M12.5 5.5v6h6v-6h-6zm-1 0h-6v6h6v-6zm1 13h6v-6h-6v6zm-1 0v-6h-6v6h6zm-7-14h15v15h-15v-15z" fill-rule="nonzero"/></svg>',
12718        'table-cell-select-inner': '<svg width="24" height="24"><g fill-rule="nonzero"><path d="M5.5 5.5v13h13v-13h-13zm-1-1h15v15h-15v-15z" opacity=".2"/><path d="M11.5 11.5v-7h1v7h7v1h-7v7h-1v-7h-7v-1h7z"/></g></svg>',
12719        'table-delete-column': '<svg width="24" height="24"><path d="M9 11.2l1 1v.2l-1 1v-2.2zm5 1l1-1v2.2l-1-1v-.2zM20 5v14H4V5h16zm-1 2h-4v.8l-.2-.2-.8.8V7h-4v1.4l-.8-.8-.2.2V7H5v11h4v-1.8l.5.5.5-.4V18h4v-1.8l.8.8.2-.3V18h4V7zm-3.9 3.4l-1.8 1.9 1.8 1.9c.4.3.4.9 0 1.2-.3.3-.8.3-1.2 0L12 13.5l-1.8 1.9a.8.8 0 0 1-1.2 0 .9.9 0 0 1 0-1.2l1.8-1.9-1.9-2a.9.9 0 0 1 1.2-1.2l2 2 1.8-1.8c.3-.4.9-.4 1.2 0a.8.8 0 0 1 0 1.1z" fill-rule="evenodd"/></svg>',
12720        'table-delete-row': '<svg width="24" height="24"><path d="M16.7 8.8l1.1 1.2-2.4 2.5L18 15l-1.2 1.2-2.5-2.5-2.4 2.5-1.3-1.2 2.5-2.5-2.5-2.5 1.2-1.3 2.6 2.6 2.4-2.5zM4 5h16v14H4V5zm15 5V7H5v3h4.8l1 1H5v3h5.8l-1 1H5v3h14v-3h-.4l-1-1H19v-3h-1.3l1-1h.3z" fill-rule="evenodd"/></svg>',
12721        'table-delete-table': '<svg width="24" height="26"><path d="M4 6h16v14H4V6zm1 2v11h14V8H5zm11.7 8.7l-1.5 1.5L12 15l-3.3 3.2-1.4-1.5 3.2-3.2-3.3-3.2 1.5-1.5L12 12l3.2-3.2 1.5 1.5-3.2 3.2 3.2 3.2z" fill-rule="evenodd"/></svg>',
12722        'table-insert-column-after': '<svg width="24" height="24"><path d="M14.3 9c.4 0 .7.3.7.6v2.2h2.1c.4 0 .7.3.7.7 0 .4-.3.7-.7.7H15v2.2c0 .3-.3.6-.7.6a.7.7 0 0 1-.6-.6v-2.2h-2.2a.7.7 0 0 1 0-1.4h2.2V9.6c0-.3.3-.6.6-.6zM4 5h16v14H4V5zm5 13v-3H5v3h4zm0-4v-3H5v3h4zm0-4V7H5v3h4zm10 8V7h-9v11h9z" fill-rule="evenodd"/></svg>',
12723        'table-insert-column-before': '<svg width="24" height="24"><path d="M9.7 16a.7.7 0 0 1-.7-.6v-2.2H6.9a.7.7 0 0 1 0-1.4H9V9.6c0-.3.3-.6.7-.6.3 0 .6.3.6.6v2.2h2.2c.4 0 .8.3.8.7 0 .4-.4.7-.8.7h-2.2v2.2c0 .3-.3.6-.6.6zM4 5h16v14H4V5zm10 13V7H5v11h9zm5 0v-3h-4v3h4zm0-4v-3h-4v3h4zm0-4V7h-4v3h4z" fill-rule="evenodd"/></svg>',
12724        'table-insert-row-above': '<svg width="24" height="24"><path d="M14.8 10.5c0 .3-.2.5-.5.5h-1.8v1.8c0 .3-.2.5-.5.5a.5.5 0 0 1-.5-.6V11H9.7a.5.5 0 0 1 0-1h1.8V8.3c0-.3.2-.6.5-.6s.5.3.5.
127246V10h1.8c.3 0 .5.2.5.5zM4 5h16v14H4V5zm5 13v-3H5v3h4zm5 0v-3h-4v3h4zm5 0v-3h-4v3h4zm0-4V7H5v7h14z" fill-rule="evenodd"/></svg>',
12725        'table-insert-row-after': '<svg width="24" height="24"><path d="M9.2 14.5c0-.3.2-.5.5-.5h1.8v-1.8c0-.3.2-.5.5-.5s.5.2.5.6V14h1.8c.3 0 .5.2.5.5s-.2.5-.5.5h-1.8v1.7c0 .3-.2.6-.5.6a.5.5 0 0 1-.5-.6V15H9.7a.5.5 0 0 1-.5-.5zM4 5h16v14H4V5zm6 2v3h4V7h-4zM5 7v3h4V7H5zm14 11v-7H5v7h14zm0-8V7h-4v3h4z" fill-rule="evenodd"/></svg>',
12726        'table-left-header': '<svg width="24" height="24"><path d="M4 5h16v13H4V5zm10 12v-3h-4v3h4zm0-4v-3h-4v3h4zm0-4V6h-4v3h4zm5 8v-3h-4v3h4zm0-4v-3h-4v3h4zm0-4V6h-4v3h4z" fill-rule="evenodd"/></svg>',
12727        'table-merge-cells': '<svg width="24" height="24"><path d="M4 5h16v14H4V5zm6 13h9v-7h-9v7zm4-11h-4v3h4V7zM9 7H5v3h4V7zm-4 4v3h4v-3H5zm10-1h4V7h-4v3zM5 15v3h4v-3H5z" fill-rule="evenodd"/></svg>',
12728        'table-row-properties': '<svg width="24" height="24"><path d="M4 5h16v14H4V5zm10 10h-4v3h4v-3zm0-8h-4v3h4V7zM9 7H5v3h4V7zm6 3h4V7h-4v3zM5 15v3h4v-3H5zm10 3h4v-3h-4v3z" fill-rule="evenodd"/></svg>',
12729        'table-split-cells': '<svg width="24" height="24"><path d="M4 5h16v14H4V5zm6 2v3h4V7h-4zM9 18v-3H5v3h4zm0-4v-3H5v3h4zm0-4V7H5v3h4zm10 8v-7h-9v7h9zm0-8V7h-4v3h4zm-3.5 4.5l1.5 1.6c.3.2.3.7 0 1-.2.2-.7.2-1 0l-1.5-1.6-1.6 1.5c-.2.3-.7.3-1 0a.7.7 0 0 1 0-1l1.6-1.5-1.5-1.6a.7.7 0 0 1 1-1l1.5 1.6 1.6-1.5c.2-.3.7-.3 1 0 .2.2.2.7 0 1l-1.6 1.5z" fill-rule="evenodd"/></svg>',
12730        'table-top-header': '<svg width="24" height="24"><path d="M4 5h16v13H4V5zm5 12v-3H5v3h4zm0-4v-3H5v3h4zm5 4v-3h-4v3h4zm0-4v-3h-4v3h4zm5 4v-3h-4v3h4zm0-4v-3h-4v3h4z" fill-rule="evenodd"/></svg>',
12731        'table': '<svg width="24" height="24"><path d="M4 5h16v14H4V5zm6 9h4v-3h-4v3zm4 1h-4v3h4v-3zm0-8h-4v3h4V7zM9 7H5v3h4V7zm-4 4v3h4v-3H5zm10 0v3h4v-3h-4zm0-1h4V7h-4v3zM5 15v3h4v-3H5zm10 3h4v-3h-4v3z" fill-rule="evenodd"/></svg>',
12732        'template': '<svg width="24" height="24"><path d="M19 19v-1H5v1h14zM9 16v-4a5 5 0 1 1 6 0v4h4a2 2 0 0 1 2 2v3H3v-3c0-1.1.9-2 2-2h4zm4 0v-5l.8-.6a3 3 0 1 0-3.6 0l.8.6v5h2z" fill-rule="nonzero"/></svg>',
12733        'temporary-placeholder': '<svg width="24" height="24"><g fill-rule="evenodd"><path d="M9 7.6V6h2.5V4.5a.5.5 0 1 1 1 0V6H15v1.6a8 8 0 1 1-6 0zm-2.6 5.3a.5.5 0 0 0 .3.6c.3 0 .6 0 .6-.3l.1-.2a5 5 0 0 1 3.3-2.8c.3-.1.4-.4.4-.6-.1-.3-.4-.5-.6-.4a6 6 0 0 0-4.1 3.7z"/><circle cx="14" cy="4" r="1"/><circle cx="12" cy="2" r="1"/><circle cx="10" cy="4" r="1"/></g></svg>',
12734        'text-color': '<svg width="24" height="24"><g fill-rule="evenodd"><path id="tox-icon-text-color__color" d="M3 18h18v3H3z"/><path d="M8.7 16h-.8a.5.5 0 0 1-.5-.6l2.7-9c.1-.3.3-.4.5-.4h2.8c.2 0 .4.1.5.4l2.7 9a.5.5 0 0 1-.5.6h-.8a.5.5 0 0 1-.4-.4l-.7-2.2c0-.3-.3-.4-.5-.4h-3.4c-.2 0-.4.1-.5.4l-.7 2.2c0 .3-.2.4-.4.4zm2.6-7.6l-.6 2a.5.5 0 0 0 .5.6h1.6a.5.5 0 0 0 .5-.6l-.6-2c0-.3-.3-.4-.5-.4h-.4c-.2 0-.4.1-.5.4z"/></g></svg>',
12735        'toc': '<svg width="24" height="24"><path d="M5 5c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 1 1 0-2zm3 0h11c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 1 1 0-2zm-3 8c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 0 1 0-2zm3 0h11c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 0 1 0-2zm0-4c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 1 1 0-2zm3 0h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zm-3 8c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 0 1 0-2zm3 0h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2z" fill-rule="evenodd"/></svg>',
12736        'translate': '<svg width="24" height="24"><path d="M12.7 14.3l-.3.7-.4.7-2.2-2.2-3.1 3c-.3.4-.8.4-1 0a.7.7 0 0 1 0-1l3.1-3A12.4 12.4 0 0 1 6.7 9H8a10.1 10.1 0 0 0 1.7 2.4c.5-.5 1-1.1 1.4-1.8l.9-2H4.7a.7.7 0 1 1 0-1.5h4.4v-.7c0-.4.3-.8.7-.8.4 0 .7.4.7.8v.7H15c.4 0 .8.3.8.7 0 .4-.4.8-.8.8h-1.4a12.3 12.3 0 0 1-1 2.4 13.5 13.5 0 0 1-1.7 2.3l1.9 1.8zm4.3-3l2.7 7.3a.5.5 0 0 1-.4.7 1 1 0 0 1-1-.7l-.6-1.5h-3.4l-.6 1.5a1 1 0 0 1-1 .7.5.5 0 0 1-.4-.7l2.7-7.4a1 1 0 1 1 2 0zm-2.2 4.4h2.4L16 12.5l-1.2 3.2z" fill-rule="evenodd"/></svg>',
12737        'underline': '<svg width="24" height="24"><path d="M16 5c.6 0 1 .4 1 1v5.5a4 4 0 0 1-.4 1.8l-1 1.4a5.3 5.3 0 0 1-5.5 1 5 5 0 0 1-1.6-1c-.5-.4-.8-.9-1.1-1.4a4 4 0 0 1-.4-1.8V6c0-.6.4-1 1-1s1 .4 1 1v5.5c0 .3 0 .6.2 1l.6.7a3.3 3.3 0 0 0 2.2.8 3.4 3.4 0 0 0 2.2-.8c.3-.2.4-.5.6-.8l.2-.9V6c0-.6.4-1 1-1zM8 17h8c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 0 1 0-2z" fill-rule="evenodd"/></svg>',
12738        'undo': '<svg width="24" height="24">
12738<path d="M6.4 8H12c3.7 0 6.2 2 6.8 5.1.6 2.7-.4 5.6-2.3 6.8a1 1 0 0 1-1-1.8c1.1-.6 1.8-2.7 1.4-4.6-.5-2.1-2.1-3.5-4.9-3.5H6.4l3.3 3.3a1 1 0 1 1-1.4 1.4l-5-5a1 1 0 0 1 0-1.4l5-5a1 1 0 0 1 1.4 1.4L6.4 8z" fill-rule="nonzero"/></svg>',
12739        'unlink': '<svg width="24" height="24"><path d="M6.2 12.3a1 1 0 0 1 1.4 1.4l-2 2a2 2 0 1 0 2.6 2.8l4.8-4.8a1 1 0 0 0 0-1.4 1 1 0 1 1 1.4-1.3 2.9 2.9 0 0 1 0 4L9.6 20a3.9 3.9 0 0 1-5.5-5.5l2-2zm11.6-.6a1 1 0 0 1-1.4-1.4l2.1-2a2 2 0 1 0-2.7-2.8L11 10.3a1 1 0 0 0 0 1.4A1 1 0 1 1 9.6 13a2.9 2.9 0 0 1 0-4L14.4 4a3.9 3.9 0 0 1 5.5 5.5l-2 2zM7.6 6.3a.8.8 0 0 1-1 1.1L3.3 4.2a.7.7 0 1 1 1-1l3.2 3.1zM5.1 8.6a.8.8 0 0 1 0 1.5H3a.8.8 0 0 1 0-1.5H5zm5-3.5a.8.8 0 0 1-1.5 0V3a.8.8 0 0 1 1.5 0V5zm6 11.8a.8.8 0 0 1 1-1l3.2 3.2a.8.8 0 0 1-1 1L16 17zm-2.2 2a.8.8 0 0 1 1.5 0V21a.8.8 0 0 1-1.5 0V19zm5-3.5a.7.7 0 1 1 0-1.5H21a.8.8 0 0 1 0 1.5H19z" fill-rule="nonzero"/></svg>',
12740        'unlock': '<svg width="24" height="24"><path d="M16 5c.8 0 1.5.3 2.1.9.6.6.9 1.3.9 2.1v3h-2V8a1 1 0 0 0-.3-.7A1 1 0 0 0 16 7h-2a1 1 0 0 0-.7.3 1 1 0 0 0-.3.7v3h.3c.2 0 .3 0 .5.2l.2.6v7.4c0 .3 0 .4-.2.6l-.6.2H4.8c-.3 0-.4 0-.6-.2a.7.7 0 0 1-.2-.6v-7.4c0-.3 0-.4.2-.6l.5-.2H11V8c0-.8.3-1.5.9-2.1.6-.6 1.3-.9 2.1-.9h2z" fill-rule="evenodd"/></svg>',
12741        'unordered-list': '<svg width="24" height="24"><path d="M11 5h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zm0 6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zm0 6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2zM4.5 6c0-.4.1-.8.4-1 .3-.4.7-.5 1.1-.5.4 0 .8.1 1 .4.4.3.5.7.5 1.1 0 .4-.1.8-.4 1-.3.4-.7.5-1.1.5-.4 0-.8-.1-1-.4-.4-.3-.5-.7-.5-1.1zm0 6c0-.4.1-.8.4-1 .3-.4.7-.5 1.1-.5.4 0 .8.1 1 .4.4.3.5.7.5 1.1 0 .4-.1.8-.4 1-.3.4-.7.5-1.1.5-.4 0-.8-.1-1-.4-.4-.3-.5-.7-.5-1.1zm0 6c0-.4.1-.8.4-1 .3-.4.7-.5 1.1-.5.4 0 .8.1 1 .4.4.3.5.7.5 1.1 0 .4-.1.8-.4 1-.3.4-.7.5-1.1.5-.4 0-.8-.1-1-.4-.4-.3-.5-.7-.5-1.1z" fill-rule="evenodd"/></svg>',
12742        'unselected': '<svg width="24" height="24"><path fill-rule="nonzero" d="M6 4h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2zm0 1a1 1 0 0 0-1 1v12c0 .6.4 1 1 1h12c.6 0 1-.4 1-1V6c0-.6-.4-1-1-1H6z"/></svg>',
12743        'upload': '<svg width="24" height="24"><path d="M18 19v-2a1 1 0 0 1 2 0v3c0 .6-.4 1-1 1H5a1 1 0 0 1-1-1v-3a1 1 0 0 1 2 0v2h12zM11 6.4L8.7 8.7a1 1 0 0 1-1.4-1.4l4-4a1 1 0 0 1 1.4 0l4 4a1 1 0 1 1-1.4 1.4L13 6.4V16a1 1 0 0 1-2 0V6.4z" fill-rule="nonzero"/></svg>',
12744        'user': '<svg width="24" height="24"><path d="M12 24a12 12 0 1 1 0-24 12 12 0 0 1 0 24zm-8.7-5.3a11 11 0 0 0 17.4 0C19.4 16.3 14.6 15 12 15c-2.6 0-7.4 1.3-8.7 3.7zM12 13c2.2 0 4-2 4-4.5S14.2 4 12 4 8 6 8 8.5 9.8 13 12 13z" fill-rule="nonzero"/></svg>',
12745        'warning': '<svg width="24" height="24"><path d="M19.8 18.3c.2.5.3.9 0 1.2-.1.3-.5.5-1 .5H5.2c-.5 0-.9-.2-1-.5-.3-.3-.2-.7 0-1.2L11 4.7l.5-.5.5-.2c.2 0 .3 0 .5.2.2 0 .3.3.5.5l6.8 13.6zM12 18c.3 0 .5-.1.7-.3.2-.2.3-.4.3-.7a1 1 0 0 0-.3-.7 1 1 0 0 0-.7-.3 1 1 0 0 0-.7.3 1 1 0 0 0-.3.7c0 .3.1.5.3.7.2.2.4.3.7.3zm.7-3l.3-4a1 1 0 0 0-.3-.7 1 1 0 0 0-.7-.3 1 1 0 0 0-.7.3 1 1 0 0 0-.3.7l.3 4h1.4z" fill-rule="evenodd"/></svg>',
12746        'zoom-in': '<svg width="24" height="24"><path d="M16 17.3a8 8 0 1 1 1.4-1.4l4.3 4.4a1 1 0 0 1-1.4 1.4l-4.4-4.3zm-5-.3a6 6 0 1 0 0-12 6 6 0 0 0 0 12zm-1-9a1 1 0 0 1 2 0v6a1 1 0 0 1-2 0V8zm-2 4a1 1 0 0 1 0-2h6a1 1 0 0 1 0 2H8z" fill-rule="nonzero"/></svg>',
12747        'zoom-out': '<svg width="24" height="24"><path d="M16 17.3a8 8 0 1 1 1.4-1.4l4.3 4.4a1 1 0 0 1-1.4 1.4l-4.4-4.3zm-5-.3a6 6 0 1 0 0-12 6 6 0 0 0 0 12zm-3-5a1 1 0 0 1 0-2h6a1 1 0 0 1 0 2H8z" fill-rule="nonzero"/></svg>'
12748      };
12749    };
12750
12751    var CreateIconManager = function () {
12752      var lookup = {};
12753      var add = function (id, iconPack) {
12754        lookup[id] = iconPack;
12755      };
12756      var get = function (id) {
12757        if (lookup[id]) {
12758          return lookup[id];
12759        }
12760        return { icons: {} };
12761      };
12762      var has$1 = function (id) {
12763        return has(lookup, id);
12764      };
12765      return {
12766        add: add,
12767        get: get,
12768        has: has$1
12769      };
12770    };
12771    var IconManager = CreateIconManager();
12772
12773    var PluginManager$1 = AddOnManager$1.PluginManager;
12774
12775    var ThemeManager = AddOnManager$1.ThemeManager;
12776
12777    function XMLHttpRequest () {
12778      var f = Global$1.getOrDie('XMLHttpRequest');
12779      return new f();
12780    }
12781
12782    function Uploader(uploadStatus, settings) {
12783      var pendingPromises = {};
12784      var pathJoin = function (path1, path2) {
12785        if (path1) {
12786          return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '');
12787        }
12788        return path2;
12789      };
12790      var defaultHandler = function (blobInfo, success, failure, progress) {
12791        var xhr, formData;
12792        xhr = XMLHttpRequest();
12793        xhr.open('POST', settings.url);
12794        xhr.withCredentials = settings.credentials;
12795        xhr.upload.onprogress = function (e) {
12796          progress(e.loaded / e.total * 100);
12797        };
12798        xhr.onerror = function () {
12799          failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
12800        };
12801        xhr.onload = function () {
12802          var json;
12803          if (xhr.status < 200 || xhr.status >= 300) {
12804            failure('HTTP Error: ' + xhr.status);
12805            return;
12806          }
12807          json = JSON.parse(xhr.responseText);
12808          if (!json || typeof json.location !== 'string') {
12809            failure('Invalid JSON: ' + xhr.responseText);
12810            return;
12811          }
12812          success(pathJoin(settings.basePath, json.location));
12813        };
12814        formData = new domGlobals.FormData();
12815        formData.append('file', blobInfo.blob(), blobInfo.filename());
12816        xhr.send(formData);
12817      };
12818      var noUpload = function () {
12819        return new promiseObj(function (resolve) {
12820          resolve([]);
12821        });
12822      };
12823      var handlerSuccess = function (blobInfo, url) {
12824        return {
12825          url: url,
12826          blobInfo: blobInfo,
12827          status: true
12828        };
12829      };
12830      var handlerFailure = function (blobInfo, error) {
12831        return {
12832          url: '',
12833          blobInfo: blobInfo,
12834          status: false,
12835          error: error
12836        };
12837      };
12838      var resolvePending = function (blobUri, result) {
12839        Tools.each(pendingPromises[blobUri], function (resolve) {
12840          resolve(result);
12841        });
12842        delete pendingPromises[blobUri];
12843      };
12844      var uploadBlobInfo = function (blobInfo, handler, openNotification) {
12845        uploadStatus.markPending(blobInfo.blobUri());
12846        return new promiseObj(function (resolve) {
12847          var notification, progress;
12848          var noop = function () {
12849          };
12850          try {
12851            var closeNotification_1 = function () {
12852              if (notification) {
12853                notification.close();
12854                progress = noop;
12855              }
12856            };
12857            var success = function (url) {
12858              closeNotification_1();
12859              uploadStatus.markUploaded(blobInfo.blobUri(), url);
12860              resolvePending(blobInfo.blobUri(), handlerSuccess(blobInfo, url));
12861              resolve(handlerSuccess(blobInfo, url));
12862            };
12863            var failure = function (error) {
12864              closeNotification_1();
12865              uploadStatus.removeFailed(blobInfo.blobUri());
12866              resolvePending(blobInfo.blobUri(), handlerFailure(blobInfo, error));
12867              resolve(handlerFailure(blobInfo, error));
12868            };
12869            progress = function (percent) {
12870              if (percent < 0 || percent > 100) {
12871                return;
12872              }
12873              if (!notification) {
12874                notification = openNotification();
12875              }
12876              notification.progressBar.value(percent);
12877            };
12878            handler(blobInfo, success, failure, progress);
12879          } catch (ex) {
12880            resolve(handlerFailure(blobInfo, ex.message));
12881          }
12882        });
12883      };
12884      var isDefaultHandler = function (handler) {
12885        return handler === defaultHandler;
12886      };
12887      var pendingUploadBlobInfo = function (blobInfo) {
12888        var blobUri = blobInfo.blobUri();
12889        return new promiseObj(function (resolve) {
12890          pendingPromises[blobUri] = pendingPromises[blobUri] || [];
12891          pendingPromises[blobUri].push(resolve);
12892        });
12893      };
12894      var uploadBlobs = function (blobInfos, openNotification) {
12895        blobInfos = Tools.grep(blobInfos, function (blobInfo) {
12896          return !uploadStatus.isUploaded(blobInfo.blobUri());
12897        });
12898        return promiseObj.all(Tools.map(blobInfos, function (blobInfo) {
12899          return uploadStatus.isPending(blobInfo.blobUri()) ? pe
12899ndingUploadBlobInfo(blobInfo) : uploadBlobInfo(blobInfo, settings.handler, openNotification);
12900        }));
12901      };
12902      var upload = function (blobInfos, openNotification) {
12903        return !settings.url && isDefaultHandler(settings.handler) ? noUpload() : uploadBlobs(blobInfos, openNotification);
12904      };
12905      if (isFunction(settings.handler) === false) {
12906        settings.handler = defaultHandler;
12907      }
12908      return { upload: upload };
12909    }
12910
12911    function FileReader () {
12912      var f = Global$1.getOrDie('FileReader');
12913      return new f();
12914    }
12915
12916    function Uint8Array (arr) {
12917      var f = Global$1.getOrDie('Uint8Array');
12918      return new f(arr);
12919    }
12920
12921    var requestAnimationFrame$1 = function (callback) {
12922      var f = Global$1.getOrDie('requestAnimationFrame');
12923      f(callback);
12924    };
12925    var atob = function (base64) {
12926      var f = Global$1.getOrDie('atob');
12927      return f(base64);
12928    };
12929    var Window = {
12930      atob: atob,
12931      requestAnimationFrame: requestAnimationFrame$1
12932    };
12933
12934    var blobUriToBlob = function (url) {
12935      return new promiseObj(function (resolve, reject) {
12936        var rejectWithError = function () {
12937          reject('Cannot convert ' + url + ' to Blob. Resource might not exist or is inaccessible.');
12938        };
12939        try {
12940          var xhr = XMLHttpRequest();
12941          xhr.open('GET', url, true);
12942          xhr.responseType = 'blob';
12943          xhr.onload = function () {
12944            if (this.status === 200) {
12945              resolve(this.response);
12946            } else {
12947              rejectWithError();
12948            }
12949          };
12950          xhr.onerror = rejectWithError;
12951          xhr.send();
12952        } catch (ex) {
12953          rejectWithError();
12954        }
12955      });
12956    };
12957    var parseDataUri = function (uri) {
12958      var type, matches;
12959      var uriParts = decodeURIComponent(uri).split(',');
12960      matches = /data:([^;]+)/.exec(uriParts[0]);
12961      if (matches) {
12962        type = matches[1];
12963      }
12964      return {
12965        type: type,
12966        data: uriParts[1]
12967      };
12968    };
12969    var dataUriToBlob = function (uri) {
12970      return new promiseObj(function (resolve) {
12971        var str, arr, i;
12972        var uriParts = parseDataUri(uri);
12973        try {
12974          str = Window.atob(uriParts.data);
12975        } catch (e) {
12976          resolve(new domGlobals.Blob([]));
12977          return;
12978        }
12979        arr = Uint8Array(str.length);
12980        for (i = 0; i < arr.length; i++) {
12981          arr[i] = str.charCodeAt(i);
12982        }
12983        resolve(new domGlobals.Blob([arr], { type: uriParts.type }));
12984      });
12985    };
12986    var uriToBlob = function (url) {
12987      if (url.indexOf('blob:') === 0) {
12988        return blobUriToBlob(url);
12989      }
12990      if (url.indexOf('data:') === 0) {
12991        return dataUriToBlob(url);
12992      }
12993      return null;
12994    };
12995    var blobToDataUri = function (blob) {
12996      return new promiseObj(function (resolve) {
12997        var reader = FileReader();
12998        reader.onloadend = function () {
12999          resolve(reader.result);
13000        };
13001        reader.readAsDataURL(blob);
13002      });
13003    };
13004    var Conversions = {
13005      uriToBlob: uriToBlob,
13006      blobToDataUri: blobToDataUri,
13007      parseDataUri: parseDataUri
13008    };
13009
13010    var count = 0;
13011    var uniqueId = function (prefix) {
13012      return (prefix || 'blobid') + count++;
13013    };
13014    var imageToBlobInfo = function (blobCache, img, resolve, reject) {
13015      var base64, blobInfo;
13016      if (img.src.indexOf('blob:') === 0) {
13017        blobInfo = blobCache.getByUri(img.src);
13018        if (blobInfo) {
13019          resolve({
13020            image: img,
13021            blobInfo: blobInfo
13022          });
13023        } else {
13024          Conversions.uriToBlob(img.src).then(function (blob) {
13025            Conversions.blobToDataUri(blob).then(function (dataUri) {
13026              base64 = Conversions.parseDataUri(dataUri).data;
13027              blobInfo = blobCache.create(uniqueId(), blob, base64);
13028              blobCache.add(blobInfo);
13029              resolve({
13030                image: img,
13031                blobInfo: blobInfo
13032              });
13033            });
13034          }, function (err) {
13035            reject(err);
13036          });
13037        }
13038        return;
13039      }
13040      base64 = Conversions.parseDataUri(img.src).data;
13041      blobInfo = blobCache.findFirst(function (cachedBlobInfo) {
13042        return cachedBlobInfo.base64() === base64;
13043      });
13044      if (blobInfo) {
13045        resolve({
13046          image: img,
13047          blobInfo: blobInfo
13048        });
13049      } else {
13050        Conversions.uriToBlob(img.src).then(function (blob) {
13051          blobInfo = blobCache.create(uniqueId(), blob, base64);
13052          blobCache.add(blobInfo);
13053          resolve({
13054            image: img,
13055            blobInfo: blobInfo
13056          });
13057        }, function (err) {
13058          reject(err);
13059        });
13060      }
13061    };
13062    var getAllImages = function (elm) {
13063      return elm ? from$1(elm.getElementsByTagName('img')) : [];
13064    };
13065    function ImageScanner(uploadStatus, blobCache) {
13066      var cachedPromises = {};
13067      var findAll = function (elm, predicate) {
13068        var images;
13069        if (!predicate) {
13070          predicate = constant(true);
13071        }
13072        images = filter(getAllImages(elm), function (img) {
13073          var src = img.src;
13074          if (!Env.fileApi) {
13075            return false;
13076          }
13077          if (img.hasAttribute('data-mce-bogus')) {
13078            return false;
13079          }
13080          if (img.hasAttribute('data-mce-placeholder')) {
13081            return false;
13082          }
13083          if (!src || src === Env.transparentSrc) {
13084            return false;
13085          }
13086          if (src.indexOf('blob:') === 0) {
13087            return !uploadStatus.isUploaded(src) && predicate(img);
13088          }
13089          if (src.indexOf('data:') === 0) {
13090            return predicate(img);
13091          }
13092          return false;
13093        });
13094        var promises = map(images, function (img) {
13095          if (cachedPromises[img.src]) {
13096            return new promiseObj(function (resolve) {
13097              cachedPromises[img.src].then(function (imageInfo) {
13098                if (typeof imageInfo === 'string') {
13099                  return imageInfo;
13100                }
13101                resolve({
13102                  image: img,
13103                  blobInfo: imageInfo.blobInfo
13104                });
13105              });
13106            });
13107          }
13108          var newPromise = new promiseObj(function (resolve, reject) {
13109            imageToBlobInfo(blobCache, img, resolve, reject);
13110          }).then(function (result) {
13111            delete cachedPromises[result.image.src];
13112            return result;
13113          }).catch(function (error) {
13114            delete cachedPromises[img.src];
13115            return error;
13116          });
13117          cachedPromises[img.src] = newPromise;
13118          return newPromise;
13119        });
13120        return promiseObj.all(promises);
13121      };
13122      return { findAll: findAll };
13123    }
13124
13125    var count$1 = 0;
13126    var seed = function () {
13127      var rnd = function () {
13128        return Math.round(Math.random() * 4294967295).toString(36);
13129      };
13130      var now = new Date().getTime();
13131      return 's' + now.toString(36) + rnd() + rnd() + rnd();
13132    };
13133    var uuid = function (prefix) {
13134      return prefix + count$1++ + seed();
13135    };
13136    var Uuid = { uuid: uuid };
13137
13138    var BlobCache = function () {
13139      var cache = [];
13140      var mimeToExt = function (mime) {
13141        var mimes = {
13142          'image/jpeg': 'jpg',
13143          'image/jpg': 'jpg',
13144          'image/gif': 'gif',
13145          'image/png': 'png'
13146        };
13147        return mimes[mime.toLowerCase()] || 'dat';
13148      };
13149      var create = function (o, blob, base64, filename) {
13150        if (isString(o)) {
13151          var id = o;
13152          return toBlobInfo({
13153            id: id,
13154            name: filename,
13155            blob: blob,
13156            base64: base64
13157          });
13158        } else if (isObject(o)) {
13159          return toBlobInfo(o);
13160        } else {
13161          throw new Error('Unknown input type');
13162        }
13163      };
13164      var toBlobInfo = function (o) {
13165        var id, name;
13166        if (!o.blob || !o.base64) {
13167          throw new Error('blob and base64 representations of the image are required for BlobInfo to be created');
13168        }
13169        id = o.id || Uuid.uuid('blobid');
13170        name = o.name || id;
13171        return {
13172          id: constant(id),
13173          name: constant(name),
13174          filename: constant(name + '.' + mimeToExt(o.blob.type)),
13175          blob: constant(o.blob),
13176          base64: constant(o.base64),
13177          blobUri: constant(o.blobUri || URL.createObjectURL(o.blob)),
13178          uri: constant(o.uri)
13179        };
13180      };
13181      var add = function (blobInfo) {
13182        if (!get(blobInfo.id())) {
13183          cache.push(blobInfo);
13184        }
13185      };
13186      var get = function (id) {
13187        return findFirst(function (cachedBlobInfo) {
13188          return cachedBlobInfo.id() === id;
13189        });
13190      };
13191      var findFirst = function (predicate) {
13192        return filter(cache, predicate)[0];
13193      };
13194      var getByUri = function (blobUri) {
13195        return findFirst(function (blobInfo) {
13196          return blobInfo.blobUri() === blobUri;
13197        });
13198      };
13199      var removeByUri = function (blobUri) {
13200        cache = filter(cache, function (blobInfo) {
13201          if (blobInfo.blobUri() === blobUri) {
13202            URL.revokeObjectURL(blobInfo.blobUri());
13203            return false;
13204          }
13205          return true;
13206        });
13207      };
13208      var destroy = function () {
13209        each(cache, function (cachedBlobInfo) {
13210          URL.revokeObjectURL(cachedBlobInfo.blobUri());
13211        });
13212        cache = [];
13213      };
13214      return {
13215        create: create,
13216        add: add,
13217        get: get,
13218        getByUri: getByUri,
13219        findFirst: findFirst,
13220        removeByUri: removeByUri,
13221        destroy: destroy
13222      };
13223    };
13224
13225    function UploadStatus () {
13226      var PENDING = 1, UPLOADED = 2;
13227      var blobUriStatuses = {};
13228      var createStatus = function (status, resultUri) {
13229        return {
13230          status: status,
13231          resultUri: resultUri
13232        };
13233      };
13234      var hasBlobUri = function (blobUri) {
13235        return blobUri in blobUriStatuses;
13236      };
13237      var getResultUri = function (blobUri) {
13238        var result = blobUriStatuses[blobUri];
13239        return result ? result.resultUri : null;
13240      };
13241      var isPending = function (blobUri) {
13242        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === PENDING : false;
13243      };
13244      var isUploaded = function (blobUri) {
13245        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === UPLOADED : false;
13246      };
13247      var markPending = function (blobUri) {
13248        blobUriStatuses[blobUri] = createStatus(PENDING, null);
13249      };
13250      var markUploaded = function (blobUri, resultUri) {
13251        blobUriStatuses[blobUri] = createStatus(UPLOADED, resultUri);
13252      };
13253      var removeFailed = function (blobUri) {
13254        delete blobUriStatuses[blobUri];
13255      };
13256      var destroy = function () {
13257        blobUriStatuses = {};
13258      };
13259      return {
13260        hasBlobUri: hasBlobUri,
13261        getResultUri: getResultUri,
13262        isPending: isPending,
13263        isUploaded: isUploaded,
13264        markPending: markPending,
13265        markUploaded: markUploaded,
13266        removeFailed: removeFailed,
13267        destroy: destroy
13268      };
13269    }
13270
13271    var EditorUpload = function (editor) {
13272      var blobCache = BlobCache();
13273      var uploader, imageScanner;
13274      var uploadStatus = UploadStatus();
13275      var urlFilters = [];
13276      var aliveGuard = function (callback) {
13277        return function (result) {
13278          if (editor.selection) {
13279            return callback(result);
13280          }
13281          return [];
13282        };
13283      };
13284      var cacheInvalidator = function () {
13285        return '?' + new Date().getTime();
13286      };
13287      var replaceString = function (content, search, replace) {
13288        var index = 0;
13289        do {
13290          index = content.indexOf(search, index);
13291          if (index !== -1) {
13292            content = content.substring(0, index) + replace + content.substr(index + search.length);
13293            index += replace.length - search.length + 1;
13294          }
13295        } while (index !== -1);
13296        return content;
13297      };
13298      var replaceImageUrl = function (content, targetUrl, replacementUrl) {
13299        content = replaceString(content, 'src="' + targetUrl + '"', 'src="' + replacementUrl + '"');
13300        content = replaceString(content, 'data-mce-src="' + targetUrl + '"', 'data-mce-src="' + replacementUrl + '"');
13301        return content;
13302      };
13303      var replaceUrlInUndoStack = function (targetUrl, replacementUrl) {
13304        each(editor.undoManager.data, function (level) {
13305          if (level.type === 'fragmented') {
13306            level.fragments = map(level.fragments, function (fragment) {
13307              return replaceImageUrl(fragment, targetUrl, replacementUrl);
13308            });
13309          } else {
13310            level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
13311          }
13312        });
13313      };
13314      var openNotification = function () {
13315        return editor.notificationManager.open({
13316          text: editor.translate('Image uploading...'),
13317          type: 'info',
13318          timeout: -1,
13319          progressBar: true
13320        });
13321      };
13322      var replaceImageUri = function (image, resultUri) {
13323        blobCache.removeByUri(image.src);
13324        replaceUrlInUndoStack(image.src, resultUri);
13325        editor.$(image).attr({
13326          'src': Settings.shouldReuseFileName(editor) ? resultUri + cacheInvalidator() : resultUri,
13327          'data-mce-src': editor.convertURL(resultUri, 'src')
13328        });
13329      };
13330      var uploadImages = function (callback) {
13331        if (!uploader) {
13332          uploader = Uploader(uploadStatus, {
13333            url: Settings.getImageUploadUrl(editor),
13334            basePath: Settings.getImageUploadBasePath(editor),
13335            credentials: Settings.getImagesUploadCredentials(editor),
13336            handler: Settings.getImagesUploadHandler(editor)
13337          });
13338        }
13339        return scanForImages().then(aliveGuard(function (imageInfos) {
13340          var blobInfos;
13341          blobInfos = map(imageInfos, function (imageInfo) {
13342            return imageInfo.blobInfo;
13343          });
13344          return uploader.upload(blobInfos, openNotification).then(aliveGuard(function (result) {
13345            var filteredResult = map(result, function (uploadInfo, index) {
13346              var image = imageInfos[index].image;
13347              if (uploadInfo.status && Settings.shouldReplaceBlobUris(editor)) {
13348                replaceImageUri(image, uploadInfo.url);
13349              } else if (uploadInfo.error) {
13350                ErrorReporter.uploadError(editor, uploadInfo.error);
13351              }
13352              return {
13353                element: image,
13354                status: uploadInfo.status
13355              };
13356            });
13357            if (callback) {
13358              callback(filteredResult);
13359            }
13360            return filteredResult;
13361          }));
13362        }));
13363      };
13364      var uploadImagesAuto = function (callback) {
13365        if (Settings.isAutomaticUploadsEnabled(editor)) {
13366          return uploadImages(callback);
13367        }
13368      };
13369      var isValidDataUriImage = function (imgElm) {
13370        if (forall(urlFilters, function (filter) {
13371            return filter(imgElm);
13372          }) === false) {
13373          return false;
13374        }
13375        if (imgElm.getAttribute('src').indexOf('data:') === 0) {
13376          var dataImgFilter = Settings.getImagesDataImgFilter(editor);
13377          return dataImgFilter(imgElm);
13378        }
13379        return true;
13380      };
13381      var addFilter = function (filter) {
13382        urlFilters.push(filter);
13383      };
13384      var scanForImages = function () {
13385        if (!imageScanner) {
13386          imageScanner = ImageScanner(uploadStatus, blobCache);
13387        }
13388        return imageScanner.findAll(editor.getBody(), isValidDataUriImage).then(aliveGuard(function (result) {
13389          result = filter(result, function (resultItem) {
13390            if (typeof resultItem === 'string') {
13391              ErrorReporter.displayError(editor, resultItem);
13392              return false;
13393            }
13394            return true;
13395          });
13396          each(result, function (resultItem) {
13397            replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
13398            resultItem.image.src = resultItem.blobInfo.blobUri();
13399            resultItem.image.removeAttribute('data-mce-src');
13400          });
13401          return result;
13402        }));
13403      };
13404      var destroy = function () {
13405        blobCache.destroy();
13406        uploadStatus.destroy();
13407        imageScanner = uploader = null;
13408      };
13409      var replaceBlobUris = function (content) {
13410        return content.replace(/src="(blob:[^"]+)"/g, function (match, blobUri) {
13411          var resultUri = uploadStatus.getResultUri(blobUri);
13412          if (resultUri) {
13413            return 'src="' + resultUri + '"';
13414          }
13415          var blobInfo = blobCache.getByUri(blobUri);
13416          if (!blobInfo) {
13417            blobInfo = foldl(editor.editorManager.get(), function (result, editor) {
13418              return result || editor.editorUpload && editor.editorUpload.blobCache.getByUri(blobUri);
13419            }, null);
13420          }
13421          if (blobInfo) {
13422            var blob = blobInfo.blob();
13423            return 'src="data:' + blob.type + ';base64,' + blobInfo.base64() + '"';
13424          }
13425          return match;
13426        });
13427      };
13428      editor.on('SetContent', function () {
13429        if (Settings.isAutomaticUploadsEnabled(editor)) {
13430          uploadImagesAuto();
13431        } else {
13432          scanForImages();
13433        }
13434      });
13435      editor.on('RawSaveContent', function (e) {
13436        e.content = replaceBlobUris(e.content);
13437      });
13438      editor.on('GetContent', function (e) {
13439        if (e.source_view || e.format === 'raw') {
13440          return;
13441        }
13442        e.content = replaceBlobUris(e.content);
13443      });
13444      editor.on('PostRender', function () {
13445        editor.parser.addNodeFilter('img', function (images) {
13446          each(images, function (img) {
13447            var src = img.attr('src');
13448            if (blobCache.getByUri(src)) {
13449              return;
13450            }
13451            var resultUri = uploadStatus.getResultUri(src);
13452            if (resultUri) {
13453              img.attr('src', resultUri);
13454            }
13455          });
13456        });
13457      });
13458      return {
13459        blobCache: blobCache,
13460        addFilter: addFilter,
13461        uploadImages: uploadImages,
13462        uploadImagesAuto: uploadImagesAuto,
13463        scanForImages: scanForImages,
13464        destroy: destroy
13465      };
13466    };
13467
13468    var dropLast = function (xs) {
13469      return xs.slice(0, -1);
13470    };
13471    var parentsUntil$1 = function (start, root, predicate) {
13472      if (contains$3(root, start)) {
13473        return dropLast(parents(start, function (elm) {
13474          return predicate(elm) || eq(elm, root);
13475        }));
13476      } else {
13477        return [];
13478      }
13479    };
13480    var parents$1 = function (start, root) {
13481      return parentsUntil$1(start, root, constant(false));
13482    };
13483    var parentsAndSelf = function (start, root) {
13484      return [start].concat(parents$1(start, root));
13485    };
13486    var Parents = {
13487      parentsUntil: parentsUntil$1,
13488      parents: parents$1,
13489      parentsAndSelf: parentsAndSelf
13490    };
13491
13492    var isBlockElement = function (blockElements, node) {
13493      return blockElements.hasOwnProperty(node.nodeName);
13494    };
13495    var isValidTarget = function (blockElements, node) {
13496      if (NodeType.isText(node)) {
13497        return true;
13498      } else if (NodeType.isElement(node)) {
13499        return !isBlockElement(blockElements, node) && !Bookmarks.isBookmarkNode(node);
13500      } else {
13501        return false;
13502      }
13503    };
13504    var hasBlockParent = function (blockElements, root, node) {
13505      return exists(Parents.parents(Element.fromDom(node), Element.fromDom(root)), function (elm) {
13506        return isBlockElement(blockElements, elm.dom());
13507      });
13508    };
13509    var shouldRemoveTextNode = function (blockElements, node) {
13510      if (NodeType.isText(node)) {
13511        if (node.nodeValue.length === 0) {
13512          return true;
13513        } else if (/^\s+$/.test(node.nodeValue) && (!node.nextSibling || isBlockElement(blockElements, node.nextSibling))) {
13514          return true;
13515        }
13516      }
13517      return false;
13518    };
13519    var addRootBlocks = function (editor) {
13520      var dom = editor.dom, selection = editor.selection;
13521      var schema = editor.schema, blockElements = schema.getBlockElements();
13522      var node = selection.getStart();
13523      var rootNode = editor.getBody();
13524      var rng;
13525      var startContainer, startOffset, endContainer, endOffset, rootBlockNode;
13526      var tempNode, wrapped, restoreSelection;
13527      var rootNodeName;
13528      var forcedRootBlock = Settings.getForcedRootBlock(editor);
13529      if (!node || !NodeType.isElement(node) || !forcedRootBlock) {
13530        return;
13531      }
13532      rootNodeName = rootNode.nodeName.toLowerCase();
13533      if (!schema.isValidChild(rootNodeName, forcedRootBlock.toLowerCase()) || hasBlockParent(blockElements, rootNode, node)) {
13534        return;
13535      }
13536      rng = selection.getRng();
13537      startContainer = rng.startContainer;
13538      startOffset = rng.startOffset;
13539      endContainer = rng.endContainer;
13540      endOffset = rng.endOffset;
13541      restoreSelection = EditorFocus.hasFocus(editor);
13542      node = rootNode.firstChild;
13543      while (node) {
13544        if (isValidTarget(blockElements, node)) {
13545          if (shouldRemoveTextNode(blockElements, node)) {
13546            tempNode = node;
13547            node = node.nextSibling;
13548            dom.remove(tempNode);
13549            continue;
13550          }
13551          if (!rootBlockNode) {
13552            rootBlockNode = dom.create(forcedRootBlock, Settings.getForcedRootBlockAttrs(editor));
13553            node.parentNode.insertBefore(rootBlockNode, node);
13554            wrapped = true;
13555          }
13556          tempNode = node;
13557          node = node.nextSibling;
13558          rootBlockNode.appendChild(tempNode);
13559        } else {
13560          rootBlockNode = null;
13561          node = node.nextSibling;
13562        }
13563      }
13564      if (wrapped && restoreSelection) {
13565        rng.setStart(startContainer, startOffset);
13566        rng.setEnd(endContainer, endOffset);
13567        selection.setRng(rng);
13568        editor.nodeChanged();
13569      }
13570    };
13571    var setup$2 = function (editor) {
13572      if (Settings.getForcedRootBlock(editor)) {
13573        editor.on('NodeChange', curry(addRootBlocks, editor));
13574      }
13575    };
13576    var ForceBlocks = { setup: setup$2 };
13577
13578    var isEq$1 = function (rng1, rng2) {
13579      return rng1 && rng2 && (rng1.startContainer === rng2.startContainer && rng1.startOffset === rng2.startOffset) && (rng1.endContainer === rng2.endContainer && rng1.endOffset === rng2.endOffset);
13580    };
13581    var RangeCompare = { isEq: isEq$1 };
13582
13583    var getStartNode = function (rng) {
13584      var sc = rng.startContainer, so = rng.startOffset;
13585      if (NodeType.isText(sc)) {
13586        return so === 0 ? Option.some(Element.fromDom(sc)) : Option.none();
13587      } else {
13588        return Option.from(sc.childNodes[so]).map(Element.fromDom);
13589      }
13590    };
13591    var getEndNode = function (rng) {
13592      var ec = rng.endContainer, eo = rng.endOffset;
13593      if (NodeType.isText(ec)) {
13594        return eo === ec.data.length ? Option.some(Element.fromDom(ec)) : Option.none();
13595      } else {
13596        return Option.from(ec.childNodes[eo - 1]).map(Element.fromDom);
13597      }
13598    };
13599    var getFirstChildren = function (node) {
13600      return firstChild(node).fold(constant([node]), function (child) {
13601        return [node].concat(getFirstChildren(child));
13602      });
13603    };
13604    var getLastChildren = function (node) {
13605      return lastChild(node).fold(constant([node]), function (child) {
13606        if (name(child) === 'br') {
13607          return prevSibling(child).map(function (sibling) {
13608            return [node].concat(getLastChildren(sibling));
13609          }).getOr([]);
13610        } else {
13611          return [node].concat(getLastChildren(child));
13612        }
13613      });
13614    };
13615    var hasAllContentsSelected = function (elm, rng) {
13616      return liftN([
13617        getStartNode(rng),
13618        getEndNode(rng)
13619      ], function (startNode, endNode) {
13620        var start = find(getFirstChildren(elm), curry(eq, startNode));
13621        var end = find(getLastChildren(elm), curry(eq, endNode));
13622        return start.isSome() && end.isSome();
13623      }).getOr(false);
13624    };
13625    var moveEndPoint$1 = function (dom, rng, node, start) {
13626      var root = node, walker = new TreeWalker(node, root);
13627      var nonEmptyElementsMap = dom.schema.getNonEmptyElements();
13628      do {
13629        if (node.nodeType === 3 && Tools.trim(node.nodeValue).length !== 0) {
13630          if (start) {
13631            rng.setStart(node, 0);
13632          } else {
13633            rng.setEnd(node, node.nodeValue.length);
13634          }
13635          return;
13636        }
13637        if (nonEmptyElementsMap[node.nodeName] && !/^(TD|TH)$/.test(node.nodeName)) {
13638          if (start) {
13639            rng.setStartBefore(node);
13640          } else {
13641            if (node.nodeName === 'BR') {
13642              rng.setEndBefore(node);
13643            } else {
13644              rng.setEndAfter(node);
13645            }
13646          }
13647          return;
13648        }
13649        if (Env.ie && Env.ie < 11 && dom.isBlock(node) && dom.isEmpty(node)) {
13650          if (start) {
13651            rng.setStart(node, 0);
13652          } else {
13653            rng.setEnd(node, 0);
13654          }
13655          return;
13656        }
13657      } while (node = start ? walker.next() : walker.prev());
13658      if (root.nodeName === 'BODY') {
13659        if (start) {
13660          rng.setStart(root, 0);
13661        } else {
13662          rng.setEnd(root, root.childNodes.length);
13663        }
13664      }
13665    };
13666    var hasAnyRanges = function (editor) {
13667      var sel = editor.selection.getSel();
13668      return sel && sel.rangeCount > 0;
13669    };
13670
13671    var NodeChange = function () {
13672      function NodeChange(editor) {
13673        this.lastPath = [];
13674        this.editor = editor;
13675        var lastRng;
13676        var self = this;
13677        if (!('onselectionchange' in editor.getDoc())) {
13678          editor.on('NodeChange click mouseup keyup focus', function (e) {
13679            var nativeRng, fakeRng;
13680            nativeRng = editor.selection.getRng();
13681            fakeRng = {
13682              startContainer: nativeRng.startContainer,
13683              startOffset: nativeRng.startOffset,
13684              endContainer: nativeRng.endContainer,
13685              endOffset: nativeRng.endOffset
13686            };
13687            if (e.type === 'nodechange' || !RangeCompare.isEq(fakeRng, lastRng)) {
13688              editor.fire('SelectionChange');
13689            }
13690            lastRng = fakeRng;
13691          });
13692        }
13693        editor.on('contextmenu', function () {
13694          editor.fire('SelectionChange');
13695        });
13696        editor.on('SelectionChange', function () {
13697          var startElm = editor.selection.getStart(true);
13698          if (!startElm || !Env.range && editor.selection.isCollapsed()) {
13699            return;
13700          }
13701          if (hasAnyRanges(editor) && !self.isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
13702            editor.nodeChanged({ selectionChange: true });
13703          }
13704        });
13705        editor.on('mouseup', function (e) {
13706          if (!e.isDefaultPrevented() && hasAnyRanges(editor)) {
13707            if (editor.selection.getNode().nodeName === 'IMG') {
13708              Delay.setEditorTimeout(editor, function () {
13709                editor.nodeChanged();
13710              });
13711            } else {
13712              editor.nodeChanged();
13713            }
13714          }
13715        });
13716      }
13717      NodeChange.prototype.nodeChanged = function (args) {
13718        var selection = this.editor.selection;
13719        var node, parents, root;
13720        if (this.editor.initialized && selection && !this.editor.settings.disable_nodechange && !this.editor.readonly) {
13721          root = this.editor.getBody();
13722          node = selection.getStart(true) || root;
13723          if (node.ownerDocument !== this.editor.getDoc() || !this.editor.dom.isChildOf(node, root)) {
13724            node = root;
13725          }
13726          parents = [];
13727          this.editor.dom.getParent(node, function (node) {
13728            if (node === root) {
13729              return true;
13730            }
13731            parents.push(node);
13732          });
13733          args = args || {};
13734          args.element = node;
13735          args.parents = parents;
13736          this.editor.fire('NodeChange', args);
13737        }
13738      };
13739      NodeChange.prototype.isSameElementPath = function (startElm) {
13740        var i, currentPath;
13741        currentPath = this.editor.$(startElm).parentsUntil(this.editor.getBody()).add(startElm);
13742        if (currentPath.length === this.lastPath.length) {
13743          for (i = currentPath.length; i >= 0; i--) {
13744            if (currentPath[i] !== this.lastPath[i]) {
13745              break;
13746            }
13747          }
13748          if (i === -1) {
13749            this.lastPath = currentPath;
13750            return true;
13751          }
13752        }
13753        this.lastPath = currentPath;
13754        return false;
13755      };
13756      return NodeChange;
13757    }();
13758
13759    var getAbsolutePosition = function (elm) {
13760      var doc, docElem, win, clientRect;
13761      clientRect = elm.getBoundingClientRect();
13762      doc = elm.ownerDocument;
13763      docElem = doc.documentElement;
13764      win = doc.defaultView;
13765      return {
13766        top: clientRect.top + win.pageYOffset - docElem.clientTop,
13767        left: clientRect.left + win.pageXOffset - docElem.clientLeft
13768      };
13769    };
13770    var getBodyPosition = function (editor) {
13771      return editor.inline ? getAbsolutePosition(editor.getBody()) : {
13772        left: 0,
13773        top: 0
13774      };
13775    };
13776    var getScrollPosition = function (editor) {
13777      var body = editor.getBody();
13778      return editor.inline ? {
13779        left: body.scrollLeft,
13780        top: body.scrollTop
13781      } : {
13782        left: 0,
13783        top: 0
13784      };
13785    };
13786    var getBodyScroll = function (editor) {
13787      var body = editor.getBody(), docElm = editor.getDoc().documentElement;
13788      var inlineScroll = {
13789        left: body.scrollLeft,
13790        top: body.scrollTop
13791      };
13792      var iframeScroll = {
13793        left: body.scrollLeft || docElm.scrollLeft,
13794        top: body.scrollTop || docElm.scrollTop
13795      };
13796      return editor.inline ? inlineScroll : iframeScroll;
13797    };
13798    var getMousePosition = function (editor, event) {
13799      if (event.target.ownerDocument !== editor.getDoc()) {
13800        var iframePosition = getAbsolutePosition(editor.getContentAreaContainer());
13801        var scrollPosition = getBodyScroll(editor);
13802        return {
13803          left: event.pageX - iframePosition.left + scrollPosition.left,
13804          top: event.pageY - iframePosition.top + scrollPosition.top
13805        };
13806      }
13807      return {
13808        left: event.pageX,
13809        top: event.pageY
13810      };
13811    };
13812    var calculatePosition = function (bodyPosition, scrollPosition, mousePosition) {
13813      return {
13814        pageX: mousePosition.left - bodyPosition.left + scrollPosition.left,
13815        pageY: mousePosition.top - bodyPosition.top + scrollPosition.top
13816      };
13817    };
13818    var calc = function (editor, event) {
13819      return calculatePosition(getBodyPosition(editor), getScrollPosition(editor), getMousePosition(editor, event));
13820    };
13821    var MousePosition = { calc: calc };
13822
13823    var isContentEditableFalse$6 = NodeType.isContentEditableFalse, isContentEditableTrue$2 = NodeType.isContentEditableTrue;
13824    var isDraggable = function (rootElm, elm) {
13825      return isContentEditableFalse$6(elm) && elm !== rootElm;
13826    };
13827    var isValidDropTarget = function (editor, targetElement, dragElement) {
13828      if (targetElement === dragElement || editor.dom.isChildOf(targetElement, dragElement)) {
13829        return false;
13830      }
13831      return !isContentEditableFalse$6(targetElement);
13832    };
13833    var cloneElement = function (elm) {
13834      var cloneElm = elm.cloneNode(true);
13835      cloneElm.removeAttribute('data-mce-selected');
13836      return cloneElm;
13837    };
13838    var createGhost = function (editor, elm, width, height) {
13839      var clonedElm = elm.cloneNode(true);
13840      editor.dom.setStyles(clonedElm, {
13841        width: width,
13842        height: height
13843      });
13844      editor.dom.setAttrib(clonedElm, 'data-mce-selected', null);
13845      var ghostElm = editor.dom.create('div', {
13846        'class': 'mce-drag-container',
13847        'data-mce-bogus': 'all',
13848        'unselectable': 'on',
13849        'contenteditable': 'false'
13850      });
13851      editor.dom.setStyles(ghostElm, {
13852        position: 'absolute',
13853        opacity: 0.5,
13854        overflow: 'hidden',
13855        border: 0,
13856        padding: 0,
13857        margin: 0,
13858        width: width,
13859        height: height
13860      });
13861      editor.dom.setStyles(clonedElm, {
13862        margin: 0,
13863        boxSizing: 'border-box'
13864      });
13865      ghostElm.appendChild(clonedElm);
13866      return ghostElm;
13867    };
13868    var appendGhostToBody = function (ghostElm, bodyElm) {
13869      if (ghostElm.parentNode !== bodyElm) {
13870        bodyElm.appendChild(ghostElm);
13871      }
13872    };
13873    var moveGhost = function (ghostElm, position, width, height, maxX, maxY) {
13874      var overflowX = 0, overflowY = 0;
13875      ghostElm.style.left = position.pageX + 'px';
13876      ghostElm.style.top = position.pageY + 'px';
13877      if (position.pageX + width > maxX) {
13878        overflowX = position.pageX + width - maxX;
13879      }
13880      if (position.pageY + height > maxY) {
13881        overflowY = position.pageY + height - maxY;
13882      }
13883      ghostElm.style.width = width - overflowX + 'px';
13884      ghostElm.style.height = height - overflowY + 'px';
13885    };
13886    var removeElement = function (elm) {
13887      if (elm && elm.parentNode) {
13888        elm.parentNode.removeChild(elm);
13889      }
13890    };
13891    var isLeftMouseButtonPressed = function (e) {
13892      return e.button === 0;
13893    };
13894    var hasDraggableElement = function (state) {
13895      return state.element;
13896    };
13897    var applyRelPos = function (state, position) {
13898      return {
13899        pageX: position.pageX - state.relX,
13900        pageY: position.pageY + 5
13901      };
13902    };
13903    var start = function (state, editor) {
13904      return function (e) {
13905        if (isLeftMouseButtonPressed(e)) {
13906          var ceElm = find(editor.dom.getParents(e.target), Predicate.or(isContentEditableFalse$6, isContentEditableTrue$2)).getOr(null);
13907          if (isDraggable(editor.getBody(), ceElm)) {
13908            var elmPos = editor.dom.getPos(ceElm);
13909            var bodyElm = editor.getBody();
13910            var docElm = editor.getDoc().documentElement;
13911            state.element = ceElm;
13912            state.screenX = e.screenX;
13913            state.screenY = e.screenY;
13914            state.maxX = (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2;
13915            state.maxY = (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2;
13916            state.relX = e.pageX - elmPos.x;
13917            state.relY = e.pageY - elmPos.y;
13918            state.width = ceElm.offsetWidth;
13919            state.height = ceElm.offsetHeight;
13920            state.ghost = createGhost(editor, ceElm, state.width, state.height);
13921          }
13922        }
13923      };
13924    };
13925    var move = function (state, editor) {
13926      var throttledPlaceCaretAt = Delay.throttle(function (clientX, clientY) {
13927        editor._selectionOverrides.hideFakeCaret();
13928        editor.selection.placeCaretAt(clientX, clientY);
13929      }, 0);
13930      return function (e) {
13931        var movement = Math.max(Math.abs(e.screenX - state.screenX), Math.abs(e.screenY - state.screenY));
13932        if (hasDraggableElement(state) && !state.dragging && movement > 10) {
13933          var args = editor.fire('dragstart', { target: state.element });
13934          if (args.isDefaultPrevented()) {
13935            return;
13936          }
13937          state.dragging = true;
13938          editor.focus();
13939        }
13940        if (state.dragging) {
13941          var targetPos = applyRelPos(state, MousePosition.calc(editor, e));
13942          appendGhostToBody(state.ghost, editor.getBody());
13943          moveGhost(state.ghost, targetPos, state.width, state.height, state.maxX, state.maxY);
13944          throttledPlaceCaretAt(e.clientX, e.clientY);
13945        }
13946      };
13947    };
13948    var getRawTarget = function (selection) {
13949      var rng = selection.getSel().getRangeAt(0);
13950      var startContainer = rng.startContainer;
13951      return startContainer.nodeType === 3 ? startContainer.parentNode : startContainer;
13952    };
13953    var drop = function (state, editor) {
13954      return function (e) {
13955        if (state.dragging) {
13956          if (isValidDropTarget(editor, getRawTarget(editor.selection), state.element)) {
13957            var targetClone_1 = cloneElement(state.element);
13958            var args = editor.fire('drop', {
13959              targetClone: targetClone_1,
13960              clientX: e.clientX,
13961              clientY: e.clientY
13962            });
13963            if (!args.isDefaultPrevented()) {
13964              targetClone_1 = args.targetClone;
13965              editor.undoManager.transact(function () {
13966                removeElement(state.element);
13967                editor.insertContent(editor.dom.getOuterHTML(targetClone_1));
13968                editor._selectionOverrides.hideFakeCaret();
13969              });
13970            }
13971          }
13972        }
13973        removeDragState(state);
13974      };
13975    };
13976    var stop = function (state, editor) {
13977      return function () {
13978        if (state.dragging) {
13979          editor.fire('dragend');
13980        }
13981        removeDragState(state);
13982      };
13983    };
13984    var removeDragState = function (state) {
13985      state.dragging = false;
13986      state.element = null;
13987      removeElement(state.ghost);
13988    };
13989    var bindFakeDragEvents = function (editor) {
13990      var state = {};
13991      var pageDom, dragStartHandler, dragHandler, dropHandler, dragEndHandler, rootDocument;
13992      pageDom = DOMUtils$1.DOM;
13993      rootDocument = domGlobals.document;
13994      dragStartHandler = start(state, editor);
13995      dragHandler = move(state, editor);
13996      dropHandler = drop(state, editor);
13997      dragEndHandler = stop(state, editor);
13998      editor.on('mousedown', dragStartHandler);
13999      editor.on('mousemove', dragHandler);
14000      editor.on('mouseup', dropHandler);
14001      pageDom.bind(rootDocument, 'mousemove', dragHandler);
14002      pageDom.bind(rootDocument, 'mouseup', dragEndHandler);
14003      editor.on('remove', function () {
14004        pageDom.unbind(rootDocument, 'mousemove', dragHandler);
14005        pageDom.unbind(rootDocument, 'mouseup', dragEndHandler);
14006      });
14007    };
14008    var blockIeDrop = function (editor) {
14009      editor.on('drop', function (e) {
14010        var realTarget = typeof e.clientX !== 'undefined' ? editor.getDoc().elementFromPoint(e.clientX, e.clientY) : null;
14011        if (isContentEditableFalse$6(realTarget) || isContentEditableFalse$6(editor.dom.getContentEditableParent(realTarget))) {
14012          e.preventDefault();
14013        }
14014      });
14015    };
14016    var init = function (editor) {
14017      bindFakeDragEvents(editor);
14018      blockIeDrop(editor);
14019    };
14020    var DragDropOverrides = { init: init };
14021
14022    var getNodeClientRects = function (node) {
14023      var toArrayWithNode = function (clientRects) {
14024        return map(clientRects, function (clientRect) {
14025          clientRect = clone$1(clientRect);
14026          clientRect.node = node;
14027          return clientRect;
14028        });
14029      };
14030      if (NodeType.isElement(node)) {
14031        return toArrayWithNode(node.getClientRects());
14032      }
14033      if (NodeType.isText(node)) {
14034        var rng = node.ownerDocument.createRange();
14035        rng.setStart(node, 0);
14036        rng.setEnd(node, node.data.length);
14037        return toArrayWithNode(rng.getClientRects());
14038      }
14039    };
14040    var getClientRects = function (node) {
14041      return foldl(node, function (result, node) {
14042        return result.concat(getNodeClientRects(node));
14043      }, []);
14044    };
14045
14046    var VDirection;
14047    (function (VDirection) {
14048      VDirection[VDirection['Up'] = -1] = 'Up';
14049      VDirection[VDirection['Down'] = 1] = 'Down';
14050    }(VDirection || (VDirection = {})));
14051    var findUntil = function (direction, root, predicateFn, node) {
14052      while (node = findNode(node, direction, isEditableCaretCandidate, root)) {
14053        if (predicateFn(node)) {
14054          return;
14055        }
14056      }
14057    };
14058    var walkUntil = function (direction, isAboveFn, isBeflowFn, root, predicateFn, caretPosition) {
14059      var line = 0, node;
14060      var result = [];
14061      var targetClientRect;
14062      var add = function (node) {
14063        var i, clientRect, clientRects;
14064        clientRects = getClientRects([node]);
14065        if (direction === -1) {
14066          clientRects = clientRects.reverse();
14067        }
14068        for (i = 0; i < clientRects.length; i++) {
14069          clientRect = clientRects[i];
14070          if (isBeflowFn(clientRect, targetClientRect)) {
14071            continue;
14072          }
14073          if (result.length > 0 && isAboveFn(clientRect, ArrUtils.last(result))) {
14074            line++;
14075          }
14076          clientRect.line = line;
14077          if (predicateFn(clientRect)) {
14078            return true;
14079          }
14080          result.push(clientRect);
14081        }
14082      };
14083      targetClientRect = ArrUtils.last(caretPosition.getClientRects());
14084      if (!targetClientRect) {
14085        return result;
14086      }
14087      node = caretPosition.getNode();
14088      add(node);
14089      findUntil(direction, root, add, node);
14090      return result;
14091    };
14092    var aboveLineNumber = function (lineNumber, clientRect) {
14093      return clientRect.line > lineNumber;
14094    };
14095    var isLineNumber = function (lineNumber, clientRect) {
14096      return clientRect.line === lineNumber;
14097    };
14098    var upUntil = curry(walkUntil, VDirection.Up, isAbove, isBelow);
14099    var downUntil = curry(walkUntil, VDirection.Down, isBelow, isAbove);
14100    var positionsUntil = function (direction, root, predicateFn, node) {
14101      var caretWalker = CaretWalker(root);
14102      var walkFn, isBelowFn, isAboveFn, caretPosition;
14103      var result = [];
14104      var line = 0, clientRect, targetClientRect;
14105      var getClientRect = function (caretPosition) {
14106        if (direction === 1) {
14107          return ArrUtils.last(caretPosition.getClientRects());
14108        }
14109        return ArrUtils.last(caretPosition.getClientRects());
14110      };
14111      if (direction === 1) {
14112        walkFn = caretWalker.next;
14113        isBelowFn = isBelow;
14114        isAboveFn = isAbove;
14115        caretPosition = CaretPosition$1.after(node);
14116      } else {
14117        walkFn = caretWalker.prev;
14118        isBelowFn = isAbove;
14119        isAboveFn = isBelow;
14120        caretPosition = CaretPosition$1.before(node);
14121      }
14122      targetClientRect = getClientRect(caretPosition);
14123      do {
14124        if (!caretPosition.isVisible()) {
14125          continue;
14126        }
14127        clientRect = getClientRect(caretPosition);
14128        if (isAboveFn(clientRect, targetClientRect)) {
14129          continue;
14130        }
14131        if (result.length > 0 && isBelowFn(clientRect, ArrUtils.last(result))) {
14132          line++;
14133        }
14134        clientRect = clone$1(clientRect);
14135        clientRect.position = caretPosition;
14136        clientRect.line = line;
14137        if (predicateFn(clientRect)) {
14138          return result;
14139        }
14140        result.push(clientRect);
14141      } while (caretPosition = walkFn(caretPosition));
14142      return result;
14143    };
14144    var isAboveLine = function (lineNumber) {
14145      return function (clientRect) {
14146        return aboveLineNumber(lineNumber, clientRect);
14147      };
14148    };
14149    var isLine = function (lineNumber) {
14150      return function (clientRect) {
14151        return isLineNumber(lineNumber, clientRect);
14152      };
14153    };
14154
14155    var isContentEditableFalse$7 = NodeType.isContentEditableFalse;
14156    var findNode$1 = findNode;
14157    var distanceToRectLeft = function (clientRect, clientX) {
14158      return Math.abs(clientRect.left - clientX);
14159    };
14160    var distanceToRectRight = function (clientRect, clientX) {
14161      return Math.abs(clientRect.right - clientX);
14162    };
14163    var isInside = function (clientX, clientRect) {
14164      return clientX >= clientRect.left && clientX <= clientRect.right;
14165    };
14166    var findClosestClientRect = function (clientRects, clientX) {
14167      return ArrUtils.reduce(clientRects, function (oldClientRect, clientRect) {
14168        var oldDistance, newDistance;
14169        oldDistance = Math.min(distanceToRectLeft(oldClientRect, clientX), distanceToRectRight(oldClientRect, clientX));
14170        newDistance = Math.min(distanceToRectLeft(clientRect, clientX), distanceToRectRight(clientRect, clientX));
14171        if (isInside(clientX, clientRect)) {
14172          return clientRect;
14173        }
14174        if (isInside(clientX, oldClientRect)) {
14175          return oldClientRect;
14176        }
14177        if (newDistance === oldDistance && isContentEditableFalse$7(clientRect.node)) {
14178          return clientRect;
14179        }
14180        if (newDistance < oldDistance) {
14181          return clientRect;
14182        }
14183        return oldClientRect;
14184      });
14185    };
14186    var walkUntil$1 = function (direction, root, predicateFn, node) {
14187      while (node = findNode$1(node, direction, isEditableCaretCandidate, root)) {
14188        if (predicateFn(node)) {
14189          return;
14190        }
14191      }
14192    };
14193    var findLineNodeRects = function (root, targetNodeRect) {
14194      var clientRects = [];
14195      var collect = function (checkPosFn, node) {
14196        var lineRects;
14197        lineRects = filter(getClientRects([node]), function (clientRect) {
14198          return !checkPosFn(clientRect, targetNodeRect);
14199        });
14200        clientRects = clientRects.concat(lineRects);
14201        return lineRects.length === 0;
14202      };
14203      clientRects.push(targetNodeRect);
14204      walkUntil$1(VDirection.Up, root, curry(collect, isAbove), targetNodeRect.node);
14205      walkUntil$1(VDirection.Down, root, curry(collect, isBelow), targetNodeRect.node);
14206      return clientRects;
14207    };
14208    var getFakeCaretTargets = function (root) {
14209      return filter(from$1(root.getElementsByTagName('*')), isFakeCaretTarget);
14210    };
14211    var caretInfo = function (clientRect, clientX) {
14212      return {
14213        node: clientRect.node,
14214        before: distanceToRectLeft(clientRect, clientX) < distanceToRectRight(clientRect, clientX)
14215      };
14216    };
14217    var closestCaret = function (root, clientX, clientY) {
14218      var closestNodeRect;
14219      var contentEditableFalseNodeRects = getClientRects(getFakeCaretTargets(root));
14220      var targetNodeRects = filter(contentEditableFalseNodeRects, function (rect) {
14221        return clientY >= rect.top && clientY <= rect.bottom;
14222      });
14223      closestNodeRect = findClosestClientRect(targetNodeRects, clientX);
14224      if (closestNodeRect) {
14225        closestNodeRect = findClosestClientRect(findLineNodeRects(root, closestNodeRect), clientX);
14226        if (closestNodeRect && isFakeCaretTarget(closestNodeRect.node)) {
14227          return caretInfo(closestNodeRect, clientX);
14228        }
14229      }
14230      return null;
14231    };
14232
14233    var isXYWithinRange = function (clientX, clientY, range) {
14234      if (range.collapsed) {
14235        return false;
14236      }
14237      return foldl(range.getClientRects(), function (state, rect) {
14238        return state || containsXY(rect, clientX, clientY);
14239      }, false);
14240    };
14241    var RangePoint = { isXYWithinRange: isXYWithinRange };
14242
14243    var isContentEditableTrue$3 = NodeType.isContentEditableTrue;
14244    var isContentEditableFalse$8 = NodeType.isContentEditableFalse;
14245    var showCaret = function (direction, editor, node, before, scrollIntoView) {
14246      return editor._selectionOverrides.showCaret(direction, node, before, scrollIntoView);
14247    };
14248    var getNodeRange = function (node) {
14249      var rng = node.ownerDocument.createRange();
14250      rng.selectNode(node);
14251      return rng;
14252    };
14253    var selectNode = function (editor, node) {
14254      var e = editor.fire('BeforeObjectSelected', { target: node });
14255      if (e.isDefaultPrevented()) {
14256        return null;
14257      }
14258      return getNodeRange(node);
14259    };
14260    var renderCaretAtRange = function (editor, range, scrollIntoView) {
14261      var normalizedRange = normalizeRange(1, editor.getBody(), range);
14262      var caretPosition = CaretPosition$1.fromRangeStart(normalizedRange);
14263      var caretPositionNode = caretPosition.getNode();
14264      if (isContentEditableFalse$8(caretPositionNode)) {
14265        return showCaret(1, editor, caretPositionNode, !caretPosition.isAt
14265End(), false);
14266      }
14267      var caretPositionBeforeNode = caretPosition.getNode(true);
14268      if (isContentEditableFalse$8(caretPositionBeforeNode)) {
14269        return showCaret(1, editor, caretPositionBeforeNode, false, false);
14270      }
14271      var ceRoot = editor.dom.getParent(caretPosition.getNode(), function (node) {
14272        return isContentEditableFalse$8(node) || isContentEditableTrue$3(node);
14273      });
14274      if (isContentEditableFalse$8(ceRoot)) {
14275        return showCaret(1, editor, ceRoot, false, scrollIntoView);
14276      }
14277      return null;
14278    };
14279    var renderRangeCaret = function (editor, range, scrollIntoView) {
14280      if (!range || !range.collapsed) {
14281        return range;
14282      }
14283      var caretRange = renderCaretAtRange(editor, range, scrollIntoView);
14284      if (caretRange) {
14285        return caretRange;
14286      }
14287      return range;
14288    };
14289
14290    var setup$3 = function (editor) {
14291      var renderFocusCaret = first(function () {
14292        if (!editor.removed && editor.getBody().contains(domGlobals.document.activeElement)) {
14293          var rng = editor.selection.getRng();
14294          if (rng.collapsed) {
14295            var caretRange = renderRangeCaret(editor, editor.selection.getRng(), false);
14296            editor.selection.setRng(caretRange);
14297          }
14298        }
14299      }, 0);
14300      editor.on('focus', function () {
14301        renderFocusCaret.throttle();
14302      });
14303      editor.on('blur', function () {
14304        renderFocusCaret.cancel();
14305      });
14306    };
14307    var CefFocus = { setup: setup$3 };
14308
14309    var VK = {
14310      BACKSPACE: 8,
14311      DELETE: 46,
14312      DOWN: 40,
14313      ENTER: 13,
14314      LEFT: 37,
14315      RIGHT: 39,
14316      SPACEBAR: 32,
14317      TAB: 9,
14318      UP: 38,
14319      END: 35,
14320      HOME: 36,
14321      modifierPressed: function (e) {
14322        return e.shiftKey || e.ctrlKey || e.altKey || this.metaKeyPressed(e);
14323      },
14324      metaKeyPressed: function (e) {
14325        return Env.mac ? e.metaKey : e.ctrlKey && !e.altKey;
14326      }
14327    };
14328
14329    var is$2 = function (expected) {
14330      return function (actual) {
14331        return expected === actual;
14332      };
14333    };
14334    var isNbsp = is$2('\xA0');
14335    var isWhiteSpace$1 = function (chr) {
14336      return /^[\r\n\t ]$/.test(chr);
14337    };
14338    var isContent = function (chr) {
14339      return !isWhiteSpace$1(chr) && !isNbsp(chr);
14340    };
14341
14342    var isChar = function (forward, predicate, pos) {
14343      return Option.from(pos.container()).filter(NodeType.isText).exists(function (text) {
14344        var delta = forward ? 0 : -1;
14345        return predicate(text.data.charAt(pos.offset() + delta));
14346      });
14347    };
14348    var isBeforeSpace = curry(isChar, true, isWhiteSpace$1);
14349    var isAfterSpace = curry(isChar, false, isWhiteSpace$1);
14350    var isEmptyText = function (pos) {
14351      var container = pos.container();
14352      return NodeType.isText(container) && container.data.length === 0;
14353    };
14354    var matchesElementPosition = function (before, predicate) {
14355      return function (pos) {
14356        return Option.from(getChildNodeAtRelativeOffset(before ? 0 : -1, pos)).filter(predicate).isSome();
14357      };
14358    };
14359    var isImageBlock = function (node) {
14360      return node.nodeName === 'IMG' && get$2(Element.fromDom(node), 'display') === 'block';
14361    };
14362    var isCefNode = function (node) {
14363      return NodeType.isContentEditableFalse(node) && !NodeType.isBogusAll(node);
14364    };
14365    var isBeforeImageBlock = matchesElementPosition(true, isImageBlock);
14366    var isAfterImageBlock = matchesElementPosition(false, isImageBlock);
14367    var isBeforeTable = matchesElementPosition(true, NodeType.isTable);
14368    var isAfterTable = matchesElementPosition(false, NodeType.isTable);
14369    var isBeforeContentEditableFalse = matchesElementPosition(true, isCefNode);
14370    var isAfterContentEditableFalse = matchesElementPosition(false, isCefNode);
14371
14372    var isContentEditableTrue$4 = NodeType.isContentEditableTrue;
14373    var isContentEditableFalse$9 = NodeType.isContentEditableFalse;
14374    var getContentEditableRoot = function (editor, node) {
14375      var root = editor.getBody();
14376      while (node && node !== root) {
14377        if (isContentEditableTrue$4(node) || isContentEditableFalse$9(node)) {
14378          return node;
14379        }
14380        node = node.parentNode;
14381      }
14382      return null;
14383    };
14384    var SelectionOverrides = function (editor) {
14385      var isBlock = function (node) {
14386        return editor.dom.isBlock(node);
14387      };
14388      var rootNode = editor.getBody();
14389      var fakeCaret = FakeCaret(editor.getBody(), isBlock, function () {
14390        return EditorFocus.hasFocus(editor);
14391      });
14392      var realSelectionId = 'sel-' + editor.dom.uniqueId();
14393      var selectedContentEditableNode;
14394      var isFakeSelectionElement = function (elm) {
14395        return editor.dom.hasClass(elm, 'mce-offscreen-selection');
14396      };
14397      var getRealSelectionElement = function () {
14398        var container = editor.dom.get(realSelectionId);
14399        return container ? container.getElementsByTagName('*')[0] : container;
14400      };
14401      var setRange = function (range) {
14402        if (range) {
14403          editor.selection.setRng(range);
14404        }
14405      };
14406      var getRange = function () {
14407        return editor.selection.getRng();
14408      };
14409      var showCaret = function (direction, node, before, scrollIntoView) {
14410        if (scrollIntoView === void 0) {
14411          scrollIntoView = true;
14412        }
14413        var e;
14414        e = editor.fire('ShowCaret', {
14415          target: node,
14416          direction: direction,
14417          before: before
14418        });
14419        if (e.isDefaultPrevented()) {
14420          return null;
14421        }
14422        if (scrollIntoView) {
14423          editor.selection.scrollIntoView(node, direction === -1);
14424        }
14425        return fakeCaret.show(before, node);
14426      };
14427      var getNormalizedRangeEndPoint = function (direction, range) {
14428        range = normalizeRange(direction, rootNode, range);
14429        if (direction === -1) {
14430          return CaretPosition$1.fromRangeStart(range);
14431        }
14432        return CaretPosition$1.fromRangeEnd(range);
14433      };
14434      var showBlockCaretContainer = function (blockCaretContainer) {
14435        if (blockCaretContainer.hasAttribute('data-mce-caret')) {
14436          showCaretContainerBlock(blockCaretContainer);
14437          setRange(getRange());
14438          editor.selection.scrollIntoView(blockCaretContainer[0]);
14439        }
14440      };
14441      var registerEvents = function () {
14442        editor.on('mouseup', function (e) {
14443          var range = getRange();
14444          if (range.collapsed && EditorView.isXYInContentArea(editor, e.clientX, e.clientY)) {
14445            setRange(renderCaretAtRange(editor, range, false));
14446          }
14447        });
14448        editor.on('click', function (e) {
14449          var contentEditableRoot;
14450          contentEditableRoot = getContentEditableRoot(editor, e.target);
14451          if (contentEditableRoot) {
14452            if (isContentEditableFalse$9(contentEditableRoot)) {
14453              e.preventDefault();
14454              editor.focus();
14455            }
14456            if (isContentEditableTrue$4(contentEditableRoot)) {
14457              if (editor.dom.isChildOf(contentEditableRoot, editor.selection.getNode())) {
14458                removeContentEditableSelection();
14459              }
14460            }
14461          }
14462        });
14463        editor.on('blur NewBlock', function () {
14464          removeContentEditableSelection();
14465        });
14466        editor.on('ResizeWindow FullscreenStateChanged', function () {
14467          return fakeCaret.reposition();
14468        });
14469        var handleTouchSelect = function (editor) {
14470          var moved = false;
14471          editor.on('touchstart', function () {
14472            moved = false;
14473          });
14474          editor.on('touchmove', function () {
14475            moved = true;
14476          });
14477          editor.on('touchend', function (e) {
14478            var contentEditableRoot = getContentEditableRoot(editor, e.target);
14479            if (isContentEditableFalse$9(contentEditableRoot)) {
14480              if (!moved) {
14481                e.preventDefault();
14482                setContentEditableSelection(selectNode(editor, contentEditableRoot));
14483              }
14484            }
14485          });
14486        };
14487        var hasNormalCaretPosition = function (elm) {
14488          var caretWalker = CaretWalker(elm);
14489          if (!elm.firstChild) {
14490            return false;
14491          }
14492          var startPos = CaretPosition$1.before(elm.firstChild);
14493          var newPos = caretWalker.next(startPos);
14494          return newPos && !isBeforeContentEditableFalse(newPos) && !isAfterContentEditableFalse(newPos);
14495        };
14496        var isInSameBlock = function (node1, node2) {
14497          var block1 = editor.dom.getParent(node1, editor.dom.isBlock);
14498          var block2 = editor.dom.getParent(node2, editor.dom.isBlock);
14499          return block1 === block2;
14500        };
14501        var hasBetterMouseTarget = function (targetNode, caretNode) {
14502          var targetBlock = editor.dom.getParent(targetNode, editor.dom.isBlock);
14503          var caretBlock = editor.dom.getParent(caretNode, editor.dom.isBlock);
14504          if (targetBlock && editor.dom.isChildOf(targetBlock, caretBlock) && isContentEditableFalse$9(getContentEditableRoot(editor, targetBlock)) === false) {
14505            return true;
14506          }
14507          return targetBlock && !isInSameBlock(targetBlock, caretBlock) && hasNormalCaretPosition(targetBlock);
14508        };
14509        handleTouchSelect(editor);
14510        editor.on('mousedown', function (e) {
14511          var contentEditableRoot;
14512          var targetElm = e.target;
14513          if (targetElm !== rootNode && targetElm.nodeName !== 'HTML' && !editor.dom.isChildOf(targetElm, rootNode)) {
14514            return;
14515          }
14516          if (EditorView.isXYInContentArea(editor, e.clientX, e.clientY) === false) {
14517            return;
14518          }
14519          contentEditableRoot = getContentEditableRoot(editor, targetElm);
14520          if (contentEditableRoot) {
14521            if (isContentEditableFalse$9(contentEditableRoot)) {
14522              e.preventDefault();
14523              setContentEditableSelection(selectNode(editor, contentEditableRoot));
14524            } else {
14525              removeContentEditableSelection();
14526              if (!(isContentEditableTrue$4(contentEditableRoot) && e.shiftKey) && !RangePoint.isXYWithinRange(e.clientX, e.clientY, editor.selection.getRng())) {
14527                hideFakeCaret();
14528                editor.selection.placeCaretAt(e.clientX, e.clientY);
14529              }
14530            }
14531          } else if (isFakeCaretTarget(targetElm) === false) {
14532            removeContentEditableSelection();
14533            hideFakeCaret();
14534            var caretInfo = closestCaret(rootNode, e.clientX, e.clientY);
14535            if (caretInfo) {
14536              if (!hasBetterMouseTarget(e.target, caretInfo.node)) {
14537                e.preventDefault();
14538                var range = showCaret(1, caretInfo.node, caretInfo.before, false);
14539                editor.getBody().focus();
14540                setRange(range);
14541              }
14542            }
14543          }
14544        });
14545        editor.on('keypress', function (e) {
14546          if (VK.modifierPressed(e)) {
14547            return;
14548          }
14549          switch (e.keyCode) {
14550          default:
14551            if (isContentEditableFalse$9(editor.selection.getNode())) {
14552              e.preventDefault();
14553            }
14554            break;
14555          }
14556        });
14557        editor.on('GetSelectionRange', function (e) {
14558          var rng = e.range;
14559          if (selectedContentEditableNode) {
14560            if (!selectedContentEditableNode.parentNode) {
14561              selectedContentEditableNode = null;
14562              return;
14563            }
14564            rng = rng.cloneRange();
14565            rng.selectNode(selectedContentEditableNode);
14566            e.range = rng;
14567          }
14568        });
14569        editor.on('SetSelectionRange', function (e) {
14570          var rng;
14571          rng = setContentEditableSelection(e.range, e.forward);
14572          if (rng) {
14573            e.range = rng;
14574          }
14575        });
14576        var isPasteBin = function (node) {
14577          return node.id === 'mcepastebin';
14578        };
14579        editor.on('AfterSetSelectionRange', function (e) {
14580          var rng = e.range;
14581          if (!isRangeInCaretContainer(rng) && !isPasteBin(rng.startContainer.parentNode)) {
14582            hideFakeCaret();
14583          }
14584          if (!isFakeSelectionElement(rng.startContainer.parentNode)) {
14585            removeContentEditableSelection();
14586          }
14587        });
14588        editor.on('copy', function (e) {
14589          var clipboardData = e.clipboardData;
14590          if (!e.isDefaultPrevented() && e.clipboardData && !Env.ie) {
14591            var realSelectionElement = getRealSelectionElement();
14592            if (realSelectionElement) {
14593              e.preventDefault();
14594              clipboardData.clearData();
14595              clipboardData.setData('text/html', realSelectionElement.outerHTML);
14596              clipboardData.setData('text/plain', realSelectionElement.outerText);
14597            }
14598          }
14599        });
14600        DragDropOverrides.init(editor);
14601        CefFocus.setup(editor);
14602      };
14603      var isWithinCaretContainer = function (node) {
14604        return isCaretContainer(node) || startsWithCaretContainer(node) || endsWithCaretContainer(node);
14605      };
14606      var isRangeInCaretContainer = function (rng) {
14607        return isWithinCaretContainer(rng.startContainer) || isWithinCaretContainer(rng.endContainer);
14608      };
14609      var setContentEditableSelection = function (range, forward) {
14610        var node;
14611        var $ = editor.$;
14612        var dom = editor.dom;
14613        var $realSelectionContainer, sel, startContainer, startOffset, endOffset, e, caretPosition, targetClone, origTargetClone;
14614        if (!range) {
14615          return null;
14616        }
14617        if (range.collapsed) {
14618          if (!isRangeInCaretContainer(range)) {
14619            if (forward === false) {
14620              caretPosition = getNormalizedRangeEndPoint(-1, range);
14621              if (isFakeCaretTarget(caretPosition.getNode(true))) {
14622                return showCaret(-1, caretPosition.getNode(true), false, false);
14623              }
14624              if (isFakeCaretTarget(caretPosition.getNode())) {
14625                return showCaret(-1, caretPosition.getNode(), !caretPosition.isAt
14625End(), false);
14626              }
14627            } else {
14628              caretPosition = getNormalizedRangeEndPoint(1, range);
14629              if (isFakeCaretTarget(caretPosition.getNode())) {
14630                return showCaret(1, caretPosition.getNode(), !caretPosition.isAtEnd(), false);
14631              }
14632              if (isFakeCaretTarget(caretPosition.getNode(true))) {
14633                return showCaret(1, caretPosition.getNode(true), false, false);
14634              }
14635            }
14636          }
14637          return null;
14638        }
14639        startContainer = range.startContainer;
14640        startOffset = range.startOffset;
14641        endOffset = range.endOffset;
14642        if (startContainer.nodeType === 3 && startOffset === 0 && isContentEditableFalse$9(startContainer.parentNode)) {
14643          startContainer = startContainer.parentNode;
14644          startOffset = dom.nodeIndex(startContainer);
14645          startContainer = startContainer.parentNode;
14646        }
14647        if (startContainer.nodeType !== 1) {
14648          return null;
14649        }
14650        if (endOffset === startOffset + 1) {
14651          node = startContainer.childNodes[startOffset];
14652        }
14653        if (!isContentEditableFalse$9(node)) {
14654          return null;
14655        }
14656        targetClone = origTargetClone = node.cloneNode(true);
14657        e = editor.fire('ObjectSelected', {
14658          target: node,
14659          targetClone: targetClone
14660        });
14661        if (e.isDefaultPrevented()) {
14662          return null;
14663        }
14664        $realSelectionContainer = descendant(Element.fromDom(editor.getBody()), '#' + realSelectionId).fold(function () {
14665          return $([]);
14666        }, function (elm) {
14667          return $([elm.dom()]);
14668        });
14669        targetClone = e.targetClone;
14670        if ($realSelectionContainer.length === 0) {
14671          $realSelectionContainer = $('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>').attr('id', realSelectionId);
14672          $realSelectionContainer.appendTo(editor.getBody());
14673        }
14674        range = editor.dom.createRng();
14675        if (targetClone === origTargetClone && Env.ie) {
14676          $realSelectionContainer.empty().append('<p style="font-size: 0" data-mce-bogus="all">\xA0</p>').append(targetClone);
14677          range.setStartAfter($realSelectionContainer[0].firstChild.firstChild);
14678          range.setEndAfter(targetClone);
14679        } else {
14680          $realSelectionContainer.empty().append('\xA0').append(targetClone).append('\xA0');
14681          range.setStart($realSelectionContainer[0].firstChild, 1);
14682          range.setEnd($realSelectionContainer[0].lastChild, 0);
14683        }
14684        $realSelectionContainer.css({ top: dom.getPos(node, editor.getBody()).y });
14685        $realSelectionContainer[0].focus();
14686        sel = editor.selection.getSel();
14687        sel.removeAllRanges();
14688        sel.addRange(range);
14689        each(descendants$1(Element.fromDom(editor.getBody()), '*[data-mce-selected]'), function (elm) {
14690          remove(elm, 'data-mce-selected');
14691        });
14692        node.setAttribute('data-mce-selected', '1');
14693        selectedContentEditableNode = node;
14694        hideFakeCaret();
14695        return range;
14696      };
14697      var removeContentEditableSelection = function () {
14698        if (selectedContentEditableNode) {
14699          selectedContentEditableNode.removeAttribute('data-mce-selected');
14700          descendant(Element.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$1);
14701          selectedContentEditableNode = null;
14702        }
14703        descendant(Element.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$1);
14704        selectedContentEditableNode = null;
14705      };
14706      var destroy = function () {
14707        fakeCaret.destroy();
14708        selectedContentEditableNode = null;
14709      };
14710      var hideFakeCaret = function () {
14711        fakeCaret.hide();
14712      };
14713      if (Env.ceFalse) {
14714        registerEvents();
14715      }
14716      return {
14717        showCaret: showCaret,
14718        showBlockCaretContainer: showBlockCaretContainer,
14719        hideFakeCaret: hideFakeCaret,
14720        destroy: destroy
14721      };
14722    };
14723
14724    var KEEP = 0, INSERT = 1, DELETE = 2;
14725    var diff = function (left, right) {
14726      var size = left.length + right.length + 2;
14727      var vDown = new Array(size);
14728      var vUp = new Array(size);
14729      var snake = function (start, end, diag) {
14730        return {
14731          start: start,
14732          end: end,
14733          diag: diag
14734        };
14735      };
14736      var buildScript = function (start1, end1, start2, end2, script) {
14737        var middle = getMiddleSnake(start1, end1, start2, end2);
14738        if (middle === null || middle.start === end1 && middle.diag === end1 - end2 || middle.end === start1 && middle.diag === start1 - start2) {
14739          var i = start1;
14740          var j = start2;
14741          while (i < end1 || j < end2) {
14742            if (i < end1 && j < end2 && left[i] === right[j]) {
14743              script.push([
14744                KEEP,
14745                left[i]
14746              ]);
14747              ++i;
14748              ++j;
14749            } else {
14750              if (end1 - start1 > end2 - start2) {
14751                script.push([
14752                  DELETE,
14753                  left[i]
14754                ]);
14755                ++i;
14756              } else {
14757                script.push([
14758                  INSERT,
14759                  right[j]
14760                ]);
14761                ++j;
14762              }
14763            }
14764          }
14765        } else {
14766          buildScript(start1, middle.start, start2, middle.start - middle.diag, script);
14767          for (var i2 = middle.start; i2 < middle.end; ++i2) {
14768            script.push([
14769              KEEP,
14770              left[i2]
14771            ]);
14772          }
14773          buildScript(middle.end, end1, middle.end - middle.diag, end2, script);
14774        }
14775      };
14776      var buildSnake = function (start, diag, end1, end2) {
14777        var end = start;
14778        while (end - diag < end2 && end < end1 && left[end] === right[end - diag]) {
14779          ++end;
14780        }
14781        return snake(start, end, diag);
14782      };
14783      var getMiddleSnake = function (start1, end1, start2, end2) {
14784        var m = end1 - start1;
14785        var n = end2 - start2;
14786        if (m === 0 || n === 0) {
14787          return null;
14788        }
14789        var delta = m - n;
14790        var sum = n + m;
14791        var offset = (sum % 2 === 0 ? sum : sum + 1) / 2;
14792        vDown[1 + offset] = start1;
14793        vUp[1 + offset] = end1 + 1;
14794        var d, k, i, x, y;
14795        for (d = 0; d <= offset; ++d) {
14796          for (k = -d; k <= d; k += 2) {
14797            i = k + offset;
14798            if (k === -d || k !== d && vDown[i - 1] < vDown[i + 1]) {
14799              vDown[i] = vDown[i + 1];
14800            } else {
14801              vDown[i] = vDown[i - 1] + 1;
14802            }
14803            x = vDown[i];
14804            y = x - start1 + start2 - k;
14805            while (x < end1 && y < end2 && left[x] === right[y]) {
14806              vDown[i] = ++x;
14807              ++y;
14808            }
14809            if (delta % 2 !== 0 && delta - d <= k && k <= delta + d) {
14810              if (vUp[i - delta] <= vDown[i]) {
14811                return buildSnake(vUp[i - delta], k + start1 - start2, end1, end2);
14812              }
14813            }
14814          }
14815          for (k = delta - d; k <= delta + d; k += 2) {
14816            i = k + offset - delta;
14817            if (k === delta - d || k !== delta + d && vUp[i + 1] <= vUp[i - 1]) {
14818              vUp[i] = vUp[i + 1] - 1;
14819            } else {
14820              vUp[i] = vUp[i - 1];
14821            }
14822            x = vUp[i] - 1;
14823            y = x - start1 + start2 - k;
14824            while (x >= start1 && y >= start2 && left[x] === right[y]) {
14825              vUp[i] = x--;
14826              y--;
14827            }
14828            if (delta % 2 === 0 && -d <= k && k <= d) {
14829              if (vUp[i] <= vDown[i + delta]) {
14830                return buildSnake(vUp[i], k + start1 - start2, end1, end2);
14831              }
14832            }
14833          }
14834        }
14835      };
14836      var script = [];
14837      buildScript(0, left.length, 0, right.length, script);
14838      return script;
14839    };
14840    var Diff = {
14841      KEEP: KEEP,
14842      DELETE: DELETE,
14843      INSERT: INSERT,
14844      diff: diff
14845    };
14846
14847    var getOuterHtml = function (elm) {
14848      if (NodeType.isElement(elm)) {
14849        return elm.outerHTML;
14850      } else if (NodeType.isText(elm)) {
14851        return Entities.encodeRaw(elm.data, false);
14852      } else if (NodeType.isComment(elm)) {
14853        return '<!--' + elm.data + '-->';
14854      }
14855      return '';
14856    };
14857    var createFragment$1 = function (html) {
14858      var frag, node, container;
14859      container = domGlobals.document.createElement('div');
14860      frag = domGlobals.document.createDocumentFragment();
14861      if (html) {
14862        container.innerHTML = html;
14863      }
14864      while (node = container.firstChild) {
14865        frag.appendChild(node);
14866      }
14867      return frag;
14868    };
14869    var insertAt = function (elm, html, index) {
14870      var fragment = createFragment$1(html);
14871      if (elm.hasChildNodes() && index < elm.childNodes.length) {
14872        var target = elm.childNodes[index];
14873        target.parentNode.insertBefore(fragment, target);
14874      } else {
14875        elm.appendChild(fragment);
14876      }
14877    };
14878    var removeAt = function (elm, index) {
14879      if (elm.hasChildNodes() && index < elm.childNodes.length) {
14880        var target = elm.childNodes[index];
14881        target.parentNode.removeChild(target);
14882      }
14883    };
14884    var applyDiff = function (diff, elm) {
14885      var index = 0;
14886      each(diff, function (action) {
14887        if (action[0] === Diff.KEEP) {
14888          index++;
14889        } else if (action[0] === Diff.INSERT) {
14890          insertAt(elm, action[1], index);
14891          index++;
14892        } else if (action[0] === Diff.DELETE) {
14893          removeAt(elm, index);
14894        }
14895      });
14896    };
14897    var read$1 = function (elm) {
14898      return filter(map(from$1(elm.childNodes), getOuterHtml), function (item) {
14899        return item.length > 0;
14900      });
14901    };
14902    var write = function (fragments, elm) {
14903      var currentFragments = map(from$1(elm.childNodes), getOuterHtml);
14904      applyDiff(Diff.diff(currentFragments, fragments), elm);
14905      return elm;
14906    };
14907    var Fragments = {
14908      read: read$1,
14909      write: write
14910    };
14911
14912    var undoLevelDocument = Cell(Option.none());
14913    var lazyTempDocument = function () {
14914      return undoLevelDocument.get().getOrThunk(function () {
14915        var doc = domGlobals.document.implementation.createHTMLDocument('undo');
14916        undoLevelDocument.set(Option.some(doc));
14917        return doc;
14918      });
14919    };
14920    var hasIframes = function (html) {
14921      return html.indexOf('</iframe>') !== -1;
14922    };
14923    var createFragmentedLevel = function (fragments) {
14924      return {
14925        type: 'fragmented',
14926        fragments: fragments,
14927        content: '',
14928        bookmark: null,
14929        beforeBookmark: null
14930      };
14931    };
14932    var createCompleteLevel = function (content) {
14933      return {
14934        type: 'complete',
14935        fragments: null,
14936        content: content,
14937        bookmark: null,
14938        beforeBookmark: null
14939      };
14940    };
14941    var createFromEditor = function (editor) {
14942      var fragments, content, trimmedFragments;
14943      fragments = Fragments.read(editor.getBody());
14944      trimmedFragments = bind(fragments, function (html) {
14945        var trimmed = TrimHtml.trimInternal(editor.serializer, html);
14946        return trimmed.length > 0 ? [trimmed] : [];
14947      });
14948      content = trimmedFragments.join('');
14949      return hasIframes(content) ? createFragmentedLevel(trimmedFragments) : createCompleteLevel(content);
14950    };
14951    var applyToEditor = function (editor, level, before) {
14952      if (level.type === 'fragmented') {
14953        Fragments.write(level.fragments, editor.getBody());
14954      } else {
14955        editor.setContent(level.content, { format: 'raw' });
14956      }
14957      editor.selection.moveToBookmark(before ? level.beforeBookmark : level.bookmark);
14958    };
14959    var getLevelContent = function (level) {
14960      return level.type === 'fragmented' ? level.fragments.join('') : level.content;
14961    };
14962    var getCleanLevelContent = function (level) {
14963      var elm = Element.fromTag('body', lazyTempDocument());
14964      set$1(elm, getLevelContent(level));
14965      each(descendants$1(elm, '*[data-mce-bogus]'), unwrap);
14966      return get$4(elm);
14967    };
14968    var hasEqualContent = function (level1, level2) {
14969      return getLevelContent(level1) === getLevelContent(level2);
14970    };
14971    var hasEqualCleanedContent = function (level1, level2) {
14972      return getCleanLevelContent(level1) === getCleanLevelContent(level2);
14973    };
14974    var isEq$2 = function (level1, level2) {
14975      if (!level1 || !level2) {
14976        return false;
14977      } else if (hasEqualContent(level1, level2)) {
14978        return true;
14979      } else {
14980        return hasEqualCleanedContent(level1, level2);
14981      }
14982    };
14983    var Levels = {
14984      createFragmentedLevel: createFragmentedLevel,
14985      createCompleteLevel: createCompleteLevel,
14986      createFromEditor: createFromEditor,
14987      applyToEditor: applyToEditor,
14988      isEq: isEq$2
14989    };
14990
14991    var UndoManager = function (editor) {
14992      var self = this, index = 0, data = [], beforeBookmark, isFirstTypedCharacter, locks = 0;
14993      var isUnlocked = function () {
14994        return locks === 0;
14995      };
14996      var setTyping = function (typing) {
14997        if (isUnlocked()) {
14998          self.typing = typing;
14999        }
15000      };
15001      var setDirty = function (state) {
15002        editor.setDirty(state);
15003      };
15004      var addNonTypingUndoLevel = function (e) {
15005        setTyping(false);
15006        self.add({}, e);
15007      };
15008      var endTyping = function () {
15009        if (self.typing) {
15010          setTyping(false);
15011          self.add();
15012        }
15013      };
15014      editor.on('init', function () {
15015        self.add();
15016      });
15017      editor.on('BeforeExecCommand', function (e) {
15018        var cmd = e.command;
15019        if (cmd !== 'Undo' && cmd !== 'Redo' && cmd !== 'mceRepaint') {
15020          endTyping();
15021          self.beforeChange();
15022        }
15023      });
15024      editor.on('ExecCommand', function (e) {
15025        var cmd = e.command;
15026        if (cmd !== 'Undo' && cmd !== 'Redo' && cmd !== 'mceRepaint') {
15027          addNonTypingUndoLevel(e);
15028        }
15029      });
15030      editor.on('ObjectResizeStart cut', function () {
15031        self.beforeChange();
15032      });
15033      editor.on('SaveContent ObjectResized blur', addNonTypingUndoLevel);
15034      editor.on('dragend', addNonTypingUndoLevel);
15035      editor.on('keyup', function (e) {
15036        var keyCode = e.keyCode;
15037        if (e.isDefaultPrevented()) {
15038          return;
15039        }
15040        if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45 || e.ctrlKey) {
15041          addNonTypingUndoLevel();
15042          editor.nodeChanged();
15043        }
15044        if (keyCode === 46 || keyCode === 8) {
15045          editor.nodeChanged();
15046        }
15047        if (isFirstTypedCharacter && self.typing && Levels.isEq(Levels.createFromEditor(editor), data[0]) === false) {
15048          if (editor.isDirty() === false) {
15049            setDirty(true);
15050            editor.fire('change', {
15051              level: data[0],
15052              lastLevel: null
15053            });
15054          }
15055          editor.fire('TypingUndo');
15056          isFirstTypedCharacter = false;
15057          editor.nodeChanged();
15058        }
15059      });
15060      editor.on('keydown', function (e) {
15061        var keyCode = e.keyCode;
15062        if (e.isDefaultPrevented()) {
15063          return;
15064        }
15065        if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45) {
15066          if (self.typing) {
15067            addNonTypingUndoLevel(e);
15068          }
15069          return;
15070        }
15071        var modKey = e.ctrlKey && !e.altKey || e.metaKey;
15072        if ((keyCode < 16 || keyCode > 20) && keyCode !== 224 && keyCode !== 91 && !self.typing && !modKey) {
15073          self.beforeChange();
15074          setTyping(true);
15075          self.add({}, e);
15076          isFirstTypedCharacter = true;
15077        }
15078      });
15079      editor.on('mousedown', function (e) {
15080        if (self.typing) {
15081          addNonTypingUndoLevel(e);
15082        }
15083      });
15084      var isInsertReplacementText = function (event) {
15085        return event.inputType === 'insertReplacementText';
15086      };
15087      var isInsertTextDataNull = function (event) {
15088        return event.inputType === 'insertText' && event.data === null;
15089      };
15090      editor.on('input', function (e) {
15091        if (e.inputType && (isInsertReplacementText(e) || isInsertTextDataNull(e))) {
15092          addNonTypingUndoLevel(e);
15093        }
15094      });
15095      editor.addShortcut('meta+z', '', 'Undo');
15096      editor.addShortcut('meta+y,meta+shift+z', '', 'Redo');
15097      editor.on('AddUndo Undo Redo ClearUndos', function (e) {
15098        if (!e.isDefaultPrevented()) {
15099          editor.nodeChanged();
15100        }
15101      });
15102      self = {
15103        data: data,
15104        typing: false,
15105        beforeChange: function () {
15106          if (isUnlocked()) {
15107            beforeBookmark = GetBookmark.getUndoBookmark(editor.selection);
15108          }
15109        },
15110        add: function (level, event) {
15111          var i;
15112          var settings = editor.settings;
15113          var lastLevel, currentLevel;
15114          currentLevel = Levels.createFromEditor(editor);
15115          level = level || {};
15116          level = Tools.extend(level, currentLevel);
15117          if (isUnlocked() === false || editor.removed) {
15118            return null;
15119          }
15120          lastLevel = data[index];
15121          if (editor.fire('BeforeAddUndo', {
15122              level: level,
15123              lastLevel: lastLevel,
15124              originalEvent: event
15125            }).isDefaultPrevented()) {
15126            return null;
15127          }
15128          if (lastLevel && Levels.isEq(lastLevel, level)) {
15129            return null;
15130          }
15131          if (data[index]) {
15132            data[index].beforeBookmark = beforeBookmark;
15133          }
15134          if (settings.custom_undo_redo_levels) {
15135            if (data.length > settings.custom_undo_redo_levels) {
15136              for (i = 0; i < data.length - 1; i++) {
15137                data[i] = data[i + 1];
15138              }
15139              data.length--;
15140              index = data.length;
15141            }
15142          }
15143          level.bookmark = GetBookmark.getUndoBookmark(editor.selection);
15144          if (index < data.length - 1) {
15145            data.length = index + 1;
15146          }
15147          data.push(level);
15148          index = data.length - 1;
15149          var args = {
15150            level: level,
15151            lastLevel: lastLevel,
15152            originalEvent: event
15153          };
15154          editor.fire('AddUndo', args);
15155          if (index > 0) {
15156            setDirty(true);
15157            editor.fire('change', args);
15158          }
15159          return level;
15160        },
15161        undo: function () {
15162          var level;
15163          if (self.typing) {
15164            self.add();
15165            self.typing = false;
15166            setTyping(false);
15167          }
15168          if (index > 0) {
15169            level = data[--index];
15170            Levels.applyToEditor(editor, level, true);
15171            setDirty(true);
15172            editor.fire('Undo', { level: level });
15173          }
15174          return level;
15175        },
15176        redo: function () {
15177          var level;
15178          if (index < data.length - 1) {
15179            level = data[++index];
15180            Levels.applyToEditor(editor, level, false);
15181            setDirty(true);
15182            editor.fire('Redo', { level: level });
15183          }
15184          return level;
15185        },
15186        clear: function () {
15187          data = [];
15188          index = 0;
15189          self.typing = false;
15190          self.data = data;
15191          editor.fire('ClearUndos');
15192        },
15193        reset: function () {
15194          self.clear();
15195          self.add();
15196        },
15197        hasUndo: function () {
15198          return index > 0 || self.typing && data[0] && !Levels.isEq(Levels.createFromEditor(editor), data[0]);
15199        },
15200        hasRedo: function () {
15201          return index < data.length - 1 && !self.typing;
15202        },
15203        transact: function (callback) {
15204          endTyping();
15205          self.beforeChange();
15206          self.ignore(callback);
15207          return self.add();
15208        },
15209        ignore: function (callback) {
15210          try {
15211            locks++;
15212            callback();
15213          } finally {
15214            locks--;
15215          }
15216        },
15217        extra: function (callback1, callback2) {
15218          var lastLevel, bookmark;
15219          if (self.transact(callback1)) {
15220            bookmark = data[index].bookmark;
15221            lastLevel = data[index - 1];
15222            Levels.applyToEditor(editor, lastLevel, true);
15223            if (self.transact(callback2)) {
15224              data[index - 1].beforeBookmark = bookmark;
15225            }
15226          }
15227        }
15228      };
15229      return self;
15230    };
15231
15232    var getLastChildren$1 = function (elm) {
15233      var children = [];
15234      var rawNode = elm.dom();
15235      while (rawNode) {
15236        children.push(Element.fromDom(rawNode));
15237        rawNode = rawNode.lastChild;
15238      }
15239      return children;
15240    };
15241    var removeTrailingBr = function (elm) {
15242      var allBrs = descendants$1(elm, 'br');
15243      var brs = filter(getLastChildren$1(elm).slice(-1), isBr$1);
15244      if (allBrs.length === brs.length) {
15245        each(brs, remove$1);
15246      }
15247    };
15248    var fillWithPaddingBr = function (elm) {
15249      empty(elm);
15250      append(elm, Element.fromHtml('<br data-mce-bogus="1">'));
15251    };
15252    var isPaddingContents = function (elm) {
15253      return isText(elm) ? get$5(elm) === '\xA0' : isBr$1(elm);
15254    };
15255    var isPaddedElement = function (elm) {
15256      return filter(children(elm), isPaddingContents).length === 1;
15257    };
15258    var trimBlockTrailingBr = function (elm) {
15259      lastChild(elm).each(function (lastChild) {
15260        prevSibling(lastChild).each(function (lastChildPrevSibling) {
15261          if (isBlock(elm) && isBr$1(lastChild) && isBlock(lastChildPrevSibling)) {
15262            remove$1(lastChild);
15263          }
15264        });
15265      });
15266    };
15267    var PaddingBr = {
15268      removeTrailingBr: removeTrailingBr,
15269      fillWithPaddingBr: fillWithPaddingBr,
15270      isPaddedElement: isPaddedElement,
15271      trimBlockTrailingBr: trimBlockTrailingBr
15272    };
15273
15274    var isEq$3 = FormatUtils.isEq;
15275    var matchesUnInheritedFormatSelector = function (ed, node, name) {
15276      var formatList = ed.formatter.get(name);
15277      if (formatList) {
15278        for (var i = 0; i < formatList.length; i++) {
15279          if (formatList[i].inherit === false && ed.dom.is(node, formatList[i].selector)) {
15280            return true;
15281          }
15282        }
15283      }
15284      return false;
15285    };
15286    var matchParents = function (editor, node, name, vars) {
15287      var root = editor.dom.getRoot();
15288      if (node === root) {
15289        return false;
15290      }
15291      node = editor.dom.getParent(node, function (node) {
15292        if (matchesUnInheritedFormatSelector(editor, node, name)) {
15293          return true;
15294        }
15295        return node.parentNode === root || !!matchNode(editor, node, name, vars, true);
15296      });
15297      return matchNode(editor, node, name, vars);
15298    };
15299    var matchName = function (dom, node, format) {
15300      if (isEq$3(node, format.inline)) {
15301        return true;
15302      }
15303      if (isEq$3(node, format.block)) {
15304        return true;
15305      }
15306      if (format.selector) {
15307        return node.nodeType === 1 && dom.is(node, format.selector);
15308      }
15309    };
15310    var matchItems = function (dom, node, format, itemName, similar, vars) {
15311      var key, value;
15312      var items = format[itemName];
15313      var i;
15314      if (format.onmatch) {
15315        return format.onmatch(node, format, itemName);
15316      }
15317      if (items) {
15318        if (typeof items.length === 'undefined') {
15319          for (key in items) {
15320            if (items.hasOwnProperty(key)) {
15321              if (itemName === 'attributes') {
15322                value = dom.getAttrib(node, key);
15323              } else {
15324                value = FormatUtils.getStyle(dom, node, key);
15325              }
15326              if (similar && !value && !format.exact) {
15327                return;
15328              }
15329              if ((!similar || format.exact) && !isEq$3(value, FormatUtils.normalizeStyleValue(dom, FormatUtils.replaceVars(items[key], vars), key))) {
15330                return;
15331              }
15332            }
15333          }
15334        } else {
15335          for (i = 0; i < items.length; i++) {
15336            if (itemName === 'attributes' ? dom.getAttrib(node, items[i]) : FormatUtils.getStyle(dom, node, items[i])) {
15337              return format;
15338            }
15339          }
15340        }
15341      }
15342      return format;
15343    };
15344    var matchNode = function (ed, node, name, vars, similar) {
15345      var formatList = ed.formatter.get(name);
15346      var format, i, x, classes;
15347      var dom = ed.dom;
15348      if (formatList && node) {
15349        for (i = 0; i < formatList.length; i++) {
15350          format = formatList[i];
15351          if (matchName(ed.dom, node, format) && matchItems(dom, node, format, 'attributes', similar, vars) && matchItems(dom, node, format, 'styles', similar, vars)) {
15352            if (classes = format.classes) {
15353              for (x = 0; x < classes.length; x++) {
15354                if (!ed.dom.hasClass(node, classes[x])) {
15355                  return;
15356                }
15357              }
15358            }
15359            return format;
15360          }
15361        }
15362      }
15363    };
15364    var match = function (editor, name, vars, node) {
15365      var startNode;
15366      if (node) {
15367        return matchParents(editor, node, name, vars);
15368      }
15369      node = editor.selection.getNode();
15370      if (matchParents(editor, node, name, vars)) {
15371        return true;
15372      }
15373      startNode = editor.selection.getStart();
15374      if (startNode !== node) {
15375        if (matchParents(editor, startNode, name, vars)) {
15376          return true;
15377        }
15378      }
15379      return false;
15380    };
15381    var matchAll = function (editor, names, vars) {
15382      var startElement;
15383      var matchedFormatNames = [];
15384      var checkedMap = {};
15385      startElement = editor.selection.getStart();
15386      editor.dom.getParent(startElement, function (node) {
15387        var i, name;
15388        for (i = 0; i < names.length; i++) {
15389          name = names[i];
15390          if (!checkedMap[name] && matchNode(editor, node, name, vars)) {
15391            checkedMap[name] = true;
15392            matchedFormatNames.push(name);
15393          }
15394        }
15395      }, editor.dom.getRoot());
15396      return matchedFormatNames;
15397    };
15398    var canApply = function (editor, name) {
15399      var formatList = editor.formatter.get(name);
15400      var startNode, parents, i, x, selector;
15401      var dom = editor.dom;
15402      if (formatList) {
15403        startNode = editor.selection.getStart();
15404        parents = FormatUtils.getParents(dom, startNode);
15405        for (x = formatList.length - 1; x >= 0; x--) {
15406          selector = formatList[x].selector;
15407          if (!selector || formatList[x].defaultBlock) {
15408            return true;
15409          }
15410          for (i = parents.length - 1; i >= 0; i--) {
15411            if (dom.is(parents[i], selector)) {
15412              return true;
15413            }
15414          }
15415        }
15416      }
15417      return false;
15418    };
15419    var MatchFormat = {
15420      matchNode: matchNode,
15421      matchName: matchName,
15422      match: match,
15423      matchAll: matchAll,
15424      canApply: canApply,
15425      matchesUnInheritedFormatSelector: matchesUnInheritedFormatSelector
15426    };
15427
15428    var splitText = function (node, offset) {
15429      return node.splitText(offset);
15430    };
15431    var split$1 = function (rng) {
15432      var startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset;
15433      if (startContainer === endContainer && NodeType.isText(startContainer)) {
15434        if (startOffset > 0 && startOffset < startContainer.nodeValue.length) {
15435          endContainer = splitText(startContainer, startOffset);
15436          startContainer = endContainer.previousSibling;
15437          if (endOffset > startOffset) {
15438            endOffset = endOffset - startOffset;
15439            startContainer = endContainer = splitText(endContainer, endOffset).previousSibling;
15440            endOffset = endContainer.nodeValue.length;
15441            startOffset = 0;
15442          } else {
15443            endOffset = 0;
15444          }
15445        }
15446      } else {
15447        if (NodeType.isText(startContainer) && startOffset > 0 && startOffset < startContainer.nodeValue.length) {
15448          startContainer = splitText(startContainer, startOffset);
15449          startOffset = 0;
15450        }
15451        if (NodeType.isText(endContainer) && endOffset > 0 && endOffset < endContainer.nodeValue.length) {
15452          endContainer = splitText(endContainer, endOffset).previousSibling;
15453          endOffset = endContainer.nodeValue.length;
15454        }
15455      }
15456      return {
15457        startContainer: startContainer,
15458        startOffset: startOffset,
15459        endContainer: endContainer,
15460        endOffset: endOffset
15461      };
15462    };
15463
15464    var isCollapsibleWhitespace = function (c) {
15465      return ' \f\n\r\t\x0B'.indexOf(c) !== -1;
15466    };
15467    var normalizeContent = function (content, isStartOfContent, isEndOfContent) {
15468      var result = foldl(content.split(''), function (acc, c) {
15469        if (isCollapsibleWhitespace(c) || c === '\xA0') {
15470          if (acc.previousCharIsSpace || acc.str === '' && isStartOfContent || acc.str.length === content.length - 1 && isEndOfContent) {
15471            return {
15472              previousCharIsSpace: false,
15473              str: acc.str + '\xA0'
15474            };
15475          } else {
15476            return {
15477              previousCharIsSpace: true,
15478              str: acc.str + ' '
15479            };
15480          }
15481        } else {
15482          return {
15483            previousCharIsSpace: false,
15484            str: acc.str + c
15485          };
15486        }
15487      }, {
15488        previousCharIsSpace: false,
15489        str: ''
15490      });
15491      return result.str;
15492    };
15493    var normalize = function (node, offset, count) {
15494      if (count === 0) {
15495        return;
15496      }
15497      var whitespace = node.data.slice(offset, offset + count);
15498      var isEndOfContent = offset + count >= node.data.length;
15499      var isStartOfContent = offset === 0;
15500      node.replaceData(offset, count, normalizeContent(whitespace, isStartOfContent, isEndOfContent));
15501    };
15502    var normalizeWhitespaceAfter = function (node, offset) {
15503      var content = node.data.slice(offset);
15504      var whitespaceCount = content.length - lTrim(content).length;
15505      return normalize(node, offset, whitespaceCount);
15506    };
15507    var normalizeWhitespaceBefore = function (node, offset) {
15508      var content = node.data.slice(0, offset);
15509      var whitespaceCount = content.length - rTrim(content).length;
15510      return normalize(node, offset - whitespaceCount, whitespaceCount);
15511    };
15512    var mergeTextNodes = function (prevNode, nextNode, normalizeWhitespace) {
15513      var whitespaceOffset = rTrim(prevNode.data).length;
15514      prevNode.appendData(nextNode.data);
15515      remove$1(Element.fromDom(nextNode));
15516      if (normalizeWhitespace) {
15517        normalizeWhitespaceAfter(prevNode, whitespaceOffset);
15518      }
15519      return prevNode;
15520    };
15521
15522    var ancestor$2 = function (scope, selector, isRoot) {
15523      return ancestor$1(scope, selector, isRoot).isSome();
15524    };
15525
15526    var hasWhitespacePreserveParent = function (rootNode, node) {
15527      var rootElement = Element.fromDom(rootNode);
15528      var startNode = Element.fromDom(node);
15529      return ancestor$2(startNode, 'pre,code', curry(eq, rootElement));
15530    };
15531    var isWhitespace = function (rootNode, node) {
15532      return NodeType.isText(node) && /^[ \t\r\n]*$/.test(node.data) && hasWhitespacePreserveParent(rootNode, node) === false;
15533    };
15534    var isNamedAnchor = function (node) {
15535      return NodeType.isElement(node) && node.nodeName === 'A' && node.hasAttribute('name');
15536    };
15537    var isContent$1 = function (rootNode, node) {
15538      return isCaretCandidate(node) && isWhitespace(rootNode, node) === false || isNamedAnchor(node) || isBookmark(node);
15539    };
15540    var isBookmark = NodeType.hasAttribute('data-mce-bookmark');
15541    var isBogus$2 = NodeType.hasAttribute('data-mce-bogus');
15542    var isBogusAll$1 = NodeType.hasAttributeValue('data-mce-bogus', 'all');
15543    var isEmptyNode = function (targetNode) {
15544      var node, brCount = 0;
15545      if (isContent$1(targetNode, targetNode)) {
15546        return false;
15547      } else {
15548        node = targetNode.firstChild;
15549        if (!node) {
15550          return true;
15551        }
15552        var walker = new TreeWalker(node, targetNode);
15553        do {
15554          if (isBogusAll$1(node)) {
15555            node = walker.next(true);
15556            continue;
15557          }
15558          if (isBogus$2(node)) {
15559            node = walker.next();
15560            continue;
15561          }
15562          if (NodeType.isBr(node)) {
15563            brCount++;
15564            node = walker.next();
15565            continue;
15566          }
15567          if (isContent$1(targetNode, node)) {
15568            return false;
15569          }
15570          node = walker.next();
15571        } while (node);
15572        return brCount <= 1;
15573      }
15574    };
15575    var isEmpty$1 = function (elm) {
15576      return isEmptyNode(elm.dom());
15577    };
15578    var Empty = { isEmpty: isEmpty$1 };
15579
15580    var needsReposition = function (pos, elm) {
15581      var container = pos.container();
15582      var offset = pos.offset();
15583      return CaretPosition$1.isTextPosition(pos) === false && container === elm.parentNode && offset > CaretPosition$1.before(elm).offset();
15584    };
15585    var reposition = function (elm, pos) {
15586      return needsReposition(pos, elm) ? CaretPosition$1(pos.container(), pos.offset() - 1) : pos;
15587    };
15588    var beforeOrStartOf = function (node) {
15589      return NodeType.isText(node) ? CaretPosition$1(node, 0) : CaretPosition$1.before(node);
15590    };
15591    var afterOrEndOf = function (node) {
15592      return NodeType.isText(node) ? CaretPosition$1(node, node.data.length) : CaretPosition$1.after(node);
15593    };
15594    var getPreviousSiblingCaretPosition = function (elm) {
15595      if (isCaretCandidate(elm.previousSibling)) {
15596        return Option.some(afterOrEndOf(elm.previousSibling));
15597      } else {
15598        return elm.previousSibling ? CaretFinder.lastPositionIn(elm.previousSibling) : Option.none();
15599      }
15600    };
15601    var getNextSiblingCaretPosition = function (elm) {
15602      if (isCaretCandidate(elm.nextSibling)) {
15603        return Option.some(beforeOrStartOf(elm.nextSibling));
15604      } else {
15605        return elm.nextSibling ? CaretFinder.firstPositionIn(elm.nextSibling) : Option.none();
15606      }
15607    };
15608    var findCaretPositionBackwardsFromElm = function (rootElement, elm) {
15609      var startPosition = CaretPosition$1.before(elm.previousSibling ? elm.previousSibling : elm.parentNode);
15610      return CaretFinder.prevPosition(rootElement, startPosition).fold(function () {
15611        return CaretFinder.nextPosition(rootElement, CaretPosition$1.after(elm));
15612      }, Option.some);
15613    };
15614    var findCaretPositionForwardsFromElm = function (rootElement, elm) {
15615      return CaretFinder.nextPosition(rootElement, CaretPosition$1.after(elm)).fold(function () {
15616        return CaretFinder.prevPosition(rootElement, CaretPosition$1.before(elm));
15617      }, Option.some);
15618    };
15619    var findCaretPositionBackwards = function (rootElement, elm) {
15620      return getPreviousSiblingCaretPosition(elm).orThunk(function () {
15621        return getNextSiblingCaretPosition(elm);
15622      }).orThunk(function () {
15623        return findCaretPositionBackwardsFromElm(rootElement, elm);
15624      });
15625    };
15626    var findCaretPositionForward = function (rootElement, elm) {
15627      return getNextSiblingCaretPosition(elm).orThunk(function () {
15628        return getPreviousSiblingCaretPosition(elm);
15629      }).orThunk(function () {
15630        return findCaretPositionForwardsFromElm(rootElement, elm);
15631      });
15632    };
15633    var findCaretPosition$1 = function (forward, rootElement, elm) {
15634      return forward ? findCaretPositionForward(rootElement, elm) : findCaretPositionBackwards(rootElement, elm);
15635    };
15636    var findCaretPosOutsideElmAfterDelete = function (forward, rootElement, elm) {
15637      return findCaretPosition$1(forward, rootElement, elm).map(curry(reposition, elm));
15638    };
15639    var setSelection = function (editor, forward, pos) {
15640      pos.fold(function () {
15641        editor.focus();
15642      }, function (pos) {
15643        editor.selection.setRng(pos.toRange(), forward);
15644      });
15645    };
15646    var eqRawNode = function (rawNode) {
15647      return function (elm) {
15648        return elm.dom() === rawNode;
15649      };
15650    };
15651    var isBlock$2 = function (editor, elm) {
15652      return elm && editor.schema.getBlockElements().hasOwnProperty(name(elm));
15653    };
15654    var paddEmptyBlock = function (elm) {
15655      if (Empty.isEmpty(elm)) {
15656        var br = Element.fromHtml('<br data-mce-bogus="1">');
15657        empty(elm);
15658        append(elm, br);
15659        return Option.some(CaretPosition$1.before(br.dom()));
15660      } else {
15661        return Option.none();
15662      }
15663    };
15664    var deleteNormalized = function (elm, afterDeletePosOpt, normalizeWhitespace) {
15665      var prevTextOpt = prevSibling(elm).filter(function (e) {
15666        return NodeType.isText(e.dom());
15667      });
15668      var nextTextOpt = nextSibling(elm).filter(function (e) {
15669        return NodeType.isText(e.dom());
15670      });
15671      remove$1(elm);
15672      return liftN([
15673        prevTextOpt,
15674        nextTextOpt,
15675        afterDeletePosOpt
15676      ], function (prev, next, pos) {
15677        var prevNode = prev.dom(), nextNode = next.dom();
15678        var offset = prevNode.data.length;
15679        mergeTextNodes(prevNode, nextNode, normalizeWhitespace);
15680        return pos.container() === nextNode ? CaretPosition$1(prevNode, offset) : pos;
15681      }).orThunk(function () {
15682        if (normalizeWhitespace) {
15683          prevTextOpt.each(function (elm) {
15684            return normalizeWhitespaceBefore(elm.dom(), elm.dom().length);
15685          });
15686          nextTextOpt.each(function (elm) {
15687            return normalizeWhitespaceAfter(elm.dom(), 0);
15688          });
15689        }
15690        return afterDeletePosOpt;
15691      });
15692    };
15693    var isInlineElement = function (editor, element) {
15694      return has(editor.schema.getTextInlineElements(), name(element));
15695    };
15696    var deleteElement = function (editor, forward, elm, moveCaret) {
15697      if (moveCaret === void 0) {
15698        moveCaret = true;
15699      }
15700      var afterDeletePos = findCaretPosOutsideElmAfterDelete(forward, editor.getBody(), elm.dom());
15701      var parentBlock = ancestor(elm, curry(isBlock$2, editor), eqRawNode(editor.getBody()));
15702      var normalizedAfterDeletePos = deleteNormalized(elm, afterDeletePos, isInlineElement(editor, elm));
15703      if (editor.dom.isEmpty(editor.getBody())) {
15704        editor.setContent('');
15705        editor.selection.setCursorLocation();
15706      } else {
15707        parentBlock.bind(paddEmptyBlock).fold(function () {
15708          if (moveCaret) {
15709            setSelection(editor, forward, normalizedAfterDeletePos);
15710          }
15711        }, function (paddPos) {
15712          if (moveCaret) {
15713            setSelection(editor, forward, Option.some(paddPos));
15714          }
15715        });
15716      }
15717    };
15718    var DeleteElement = { deleteElement: deleteElement };
15719
15720    var ZWSP$1 = Zwsp.ZWSP, CARET_ID$1 = '_mce_caret';
15721    var importNode = function (ownerDocument, node) {
15722      return ownerDocument.importNode(node, true);
15723    };
15724    var getEmptyCaretContainers = function (node) {
15725      var nodes = [];
15726      while (node) {
15727        if (node.nodeType === 3 && node.nodeValue !== ZWSP$1 || node.childNodes.length > 1) {
15728          return [];
15729        }
15730        if (node.nodeType === 1) {
15731          nodes.push(node);
15732        }
15733        node = node.firstChild;
15734      }
15735      return nodes;
15736    };
15737    var isCaretContainerEmpty = function (node) {
15738      return getEmptyCaretContainers(node).length > 0;
15739    };
15740    var findFirstTextNode = function (node) {
15741      if (node) {
15742        var walker = new TreeWalker(node, node);
15743        for (node = walker.current(); node; node = walker.next()) {
15744          if (node.nodeType === 3) {
15745            return node;
15746          }
15747        }
15748      }
15749      return null;
15750    };
15751    var createCaretContainer = function (fill) {
15752      var caretContainer = Element.fromTag('span');
15753      setAll(caretContainer, {
15754        'id': CARET_ID$1,
15755        'data-mce-bogus': '1',
15756        'data-mce-type': 'format-caret'
15757      });
15758      if (fill) {
15759        append(caretContainer, Element.fromText(ZWSP$1));
15760      }
15761      return caretContainer;
15762    };
15763    var trimZwspFromCaretContainer = function (caretContainerNode) {
15764      var textNode = findFirstTextNode(caretContainerNode);
15765      if (textNode && textNode.nodeValue.charAt(0) === ZWSP$1) {
15766        textNode.deleteData(0, 1);
15767      }
15768      return textNode;
15769    };
15770    var removeCaretContainerNode = function (editor, node, moveCaret) {
15771      if (moveCaret === void 0) {
15772        moveCaret = true;
15773      }
15774      var dom = editor.dom, selection = editor.selection;
15775      if (isCaretContainerEmpty(node)) {
15776        DeleteElement.deleteElement(editor, false, Element.fromDom(node), moveCaret);
15777      } else {
15778        var rng = selection.getRng();
15779        var block = dom.getParent(node, dom.isBlock);
15780        var textNode = trimZwspFromCaretContainer(node);
15781        if (rng.startContainer === textNode && rng.startOffset > 0) {
15782          rng.setStart(textNode, rng.startOffset - 1);
15783        }
15784        if (rng.endContainer === textNode && rng.endOffset > 0) {
15785          rng.setEnd(textNode, rng.endOffset - 1);
15786        }
15787        dom.remove(node, true);
15788        if (block && dom.isEmpty(block)) {
15789          PaddingBr.fillWithPaddingBr(Element.fromDom(block));
15790        }
15791        selection.setRng(rng);
15792      }
15793    };
15794    var removeCaretContainer = function (editor, node, moveCaret) {
15795      if (moveCaret === void 0) {
15796        moveCaret = true;
15797      }
15798      var dom = editor.dom, selection = editor.selection;
15799      if (!node) {
15800        node = getParentCaretContainer(editor.getBody(), selection.getStart());
15801        if (!node) {
15802          while (node = dom.get(CARET_ID$1)) {
15803            removeCaretContainerNode(editor, node, false);
15804          }
15805        }
15806      } else {
15807        removeCaretContainerNode(editor, node, moveCaret);
15808      }
15809    };
15810    var insertCaretContainerNode = function (editor, caretContainer, formatNode) {
15811      var dom = editor.dom, block = dom.getParent(formatNode, curry(FormatUtils.isTextBlock, editor));
15812      if (block && dom.isEmpty(block)) {
15813        formatNode.parentNode.replaceChild(caretContainer, formatNode);
15814      } else {
15815        PaddingBr.removeTrailingBr(Element.fromDom(formatNode));
15816        if (dom.isEmpty(formatNode)) {
15817          formatNode.parentNode.replaceChild(caretContainer, formatNode);
15818        } else {
15819          dom.insertAfter(caretContainer, formatNode);
15820        }
15821      }
15822    };
15823    var appendNode = function (parentNode, node) {
15824      parentNode.appendChild(node);
15825      return node;
15826    };
15827    var insertFormatNodesIntoCaretContainer = function (formatNodes, caretContainer) {
15828      var innerMostFormatNode = foldr(formatNodes, function (parentNode, formatNode) {
15829        return appendNode(parentNode, formatNode.cloneNode(false));
15830      }, caretContainer);
15831      return appendNode(innerMostFormatNode, innerMostFormatNode.ownerDocument.createTextNode(ZWSP$1));
15832    };
15833    var applyCaretFormat = function (editor, name, vars) {
15834      var rng, caretContainer, textNode, offset, bookmark, container, text;
15835      var selection = editor.selection;
15836      rng = selection.getRng();
15837      offset = rng.startOffset;
15838      container = rng.startContainer;
15839      text = container.nodeValue;
15840      caretContainer = getParentCaretContainer(editor.getBody(), selection.getStart());
15841      if (caretContainer) {
15842        textNode = findFirstTextNode(caretContainer);
15843      }
15844      var wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/;
15845      if (text && offset > 0 && offset < text.length && wordcharRegex.test(text.charAt(offset)) && wordcharRegex.test(text.charAt(offset - 1))) {
15846        bookmark = selection.getBookmark();
15847        rng.collapse(true);
15848        rng = ExpandRange.expandRng(editor, rng, editor.formatter.get(name));
15849        rng = split$1(rng);
15850        editor.formatter.apply(name, vars, rng);
15851        selection.moveToBookmark(bookmark);
15852      } else {
15853        if (!caretContainer || textNode.nodeValue !== ZWSP$1) {
15854          caretContainer = importNode(editor.getDoc(), createCaretContainer(true).dom());
15855          textNode = caretContainer.firstChild;
15856          rng.insertNode(caretContainer);
15857          offset = 1;
15858          editor.formatter.apply(name, vars, caretContainer);
15859        } else {
15860          editor.formatter.apply(name, vars, caretContainer);
15861        }
15862        selection.setCursorLocation(textNode, offset);
15863      }
15864    };
15865    var removeCaretFormat = function (editor, name, vars, similar) {
15866      var dom = editor.dom, selection = editor.selection;
15867      var container, offset, bookmark;
15868      var hasContentAfter, node, formatNode;
15869      var parents = [], rng = selection.getRng();
15870      var caretContainer;
15871      container = rng.startContainer;
15872      offset = rng.startOffset;
15873      node = container;
15874      if (container.nodeType === 3) {
15875        if (offset !== container.nodeValue.length) {
15876          hasContentAfter = true;
15877        }
15878        node = node.parentNode;
15879      }
15880      while (node) {
15881        if (MatchFormat.matchNode(editor, node, name, vars, similar)) {
15882          formatNode = node;
15883          break;
15884        }
15885        if (node.nextSibling) {
15886          hasContentAfter = true;
15887        }
15888        parents.push(node);
15889        node = node.parentNode;
15890      }
15891      if (!formatNode) {
15892        return;
15893      }
15894      if (hasContentAfter) {
15895        bookmark = selection.getBookmark();
15896        rng.collapse(true);
15897        var expandedRng = ExpandRange.expandRng(editor, rng, editor.formatter.get(name), true);
15898        expandedRng = split$1(expandedRng);
15899        editor.formatter.remove(name, vars, expandedRng);
15900        selection.moveToBookmark(bookmark);
15901      } else {
15902        caretContainer = getParentCaretContainer(editor.getBody(), formatNode);
15903        var newCaretContainer = createCaretContainer(false).dom();
15904        var caretNode = insertFormatNodesIntoCaretContainer(parents, newCaretContainer);
15905        if (caretContainer) {
15906          insertCaretContainerNode(editor, newCaretContainer, caretContainer);
15907        } else {
15908          insertCaretContainerNode(editor, newCaretContainer, formatNode);
15909        }
15910        removeCaretContainerNode(editor, caretContainer, false);
15911        selection.setCursorLocation(caretNode, 1);
15912        if (dom.isEmpty(formatNode)) {
15913          dom.remove(formatNode);
15914        }
15915      }
15916    };
15917    var disableCaretContainer = function (editor, keyCode) {
15918      var selection = editor.selection, body = editor.getBody();
15919      removeCaretContainer(editor, null, false);
15920      if ((keyCode === 8 || keyCode === 46) && selection.isCollapsed() && selection.getStart().innerHTML === ZWSP$1) {
15921        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()));
15922      }
15923      if (keyCode === 37 || keyCode === 39) {
15924        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()));
15925      }
15926    };
15927    var setup$4 = function (editor) {
15928      editor.on('mouseup keydown', function (e) {
15929        disableCaretContainer(editor, e.keyCode);
15930      });
15931    };
15932    var replaceWithCaretFormat = function (targetNode, formatNodes) {
15933      var caretContainer = createCaretContainer(false);
15934      var innerMost = insertFormatNodesIntoCaretContainer(formatNodes, caretContainer.dom());
15935      before(Element.fromDom(targetNode), caretContainer);
15936      remove$1(Element.fromDom(targetNode));
15937      return CaretPosition$1(innerMost, 0);
15938    };
15939    var isFormatElement = function (editor, element) {
15940      var inlineElements = editor.schema.getTextInlineElements();
15941      return inlineElements.hasOwnProperty(name(element)) && !isCaretNode(element.dom()) && !NodeType.isBogus(element.dom());
15942    };
15943    var isEmptyCaretFormatElement = function (element) {
15944      return isCaretNode(element.dom()) && isCaretContainerEmpty(element.dom());
15945    };
15946
15947    var postProcessHooks = {}, filter$3 = ArrUtils.filter, each$9 = ArrUtils.each;
15948    var addPostProcessHook = function (name, hook) {
15949      var hooks = postProcessHooks[name];
15950      if (!hooks) {
15951        postProcessHooks[name] = hooks = [];
15952      }
15953      postProcessHooks[name].push(hook);
15954    };
15955    var postProcess = function (name, editor) {
15956      each$9(postProcessHooks[name], function (hook) {
15957        hook(editor);
15958      });
15959    };
15960    addPostProcessHook('pre', function (editor) {
15961      var rng = editor.selection.getRng();
15962      var isPre, blocks;
15963      var hasPreSibling = function (pre) {
15964        return isPre(pre.previousSibling) && ArrUtils.indexOf(blocks, pre.previousSibling) !== -1;
15965      };
15966      var joinPre = function (pre1, pre2) {
15967        DomQuery(pre2).remove();
15968        DomQuery(pre1).append('<br><br>').append(pre2.childNodes);
15969      };
15970      isPre = NodeType.matchNodeNames('pre');
15971      if (!rng.collapsed) {
15972        blocks = editor.selection.getSelectedBlocks();
15973        each$9(filter$3(filter$3(blocks, isPre), hasPreSibling), function (pre) {
15974          joinPre(pre.previousSibling, pre);
15975        });
15976      }
15977    });
15978    var Hooks = { postProcess: postProcess };
15979
15980    var each$a = Tools.each;
15981    var ElementUtils = function (dom) {
15982      this.compare = function (node1, node2) {
15983        if (node1.nodeName !== node2.nodeName) {
15984          return false;
15985        }
15986        var getAttribs = function (node) {
15987          var attribs = {};
15988          each$a(dom.getAttribs(node), function (attr) {
15989            var name = attr.nodeName.toLowerCase();
15990            if (name.indexOf('_') !== 0 && name !== 'style' && name.indexOf('data-') !== 0) {
15991              attribs[name] = dom.getAttrib(node, name);
15992            }
15993          });
15994          return attribs;
15995        };
15996        var compareObjects = function (obj1, obj2) {
15997          var value, name;
15998          for (name in obj1) {
15999            if (obj1.hasOwnProperty(name)) {
16000              value = obj2[name];
16001              if (typeof value === 'undefined') {
16002                return false;
16003              }
16004              if (obj1[name] !== value) {
16005                return false;
16006              }
16007              delete obj2[name];
16008            }
16009          }
16010          for (name in obj2) {
16011            if (obj2.hasOwnProperty(name)) {
16012              return false;
16013            }
16014          }
16015          return true;
16016        };
16017        if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
16018          return false;
16019        }
16020        if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) {
16021          return false;
16022        }
16023        return !Bookmarks.isBookmarkNode(node1) && !Bookmarks.isBookmarkNode(node2);
16024      };
16025    };
16026
16027    var MCE_ATTR_RE = /^(src|href|style)$/;
16028    var each$b = Tools.each;
16029    var isEq$4 = FormatUtils.isEq;
16030    var isTableCell$2 = function (node) {
16031      return /^(TH|TD)$/.test(node.nodeName);
16032    };
16033    var isChildOfInlineParent = function (dom, node, parent) {
16034      return dom.isChildOf(node, parent) && node !== parent && !dom.isBlock(parent);
16035    };
16036    var getContainer = function (ed, rng, start) {
16037      var container, offset, lastIdx;
16038      container = rng[start ? 'startContainer' : 'endContainer'];
16039      offset = rng[start ? 'startOffset' : 'endOffset'];
16040      if (NodeType.isElement(container)) {
16041        lastIdx = container.childNodes.length - 1;
16042        if (!start && offset) {
16043          offset--;
16044        }
16045        container = container.childNodes[offset > lastIdx ? lastIdx : offset];
16046      }
16047      if (NodeType.isText(container) && start && offset >= container.nodeValue.length) {
16048        container = new TreeWalker(container, ed.getBody()).next() || container;
16049      }
16050      if (NodeType.isText(container) && !start && offset === 0) {
16051        container = new TreeWalker(container, ed.getBody()).prev() || container;
16052      }
16053      return container;
16054    };
16055    var wrap$2 = function (dom, node, name, attrs) {
16056      var wrapper = dom.create(name, attrs);
16057      node.parentNode.insertBefore(wrapper, node);
16058      wrapper.appendChild(node);
16059      return wrapper;
16060    };
16061    var wrapWithSiblings = function (dom, node, next, name, attrs) {
16062      var start = Element.fromDom(node);
16063      var wrapper = Element.fromDom(dom.create(name, attrs));
16064      var siblings = next ? nextSiblings(start) : prevSiblings(start);
16065      append$1(wrapper, siblings);
16066      if (next) {
16067        before(start, wrapper);
16068        prepend(wrapper, start);
16069      } else {
16070        after(start, wrapper);
16071        append(wrapper, start);
16072      }
16073      return wrapper.dom();
16074    };
16075    var matchName$1 = function (dom, node, format) {
16076      if (isEq$4(node, format.inline)) {
16077        return true;
16078      }
16079      if (isEq$4(node, format.block)) {
16080        return true;
16081      }
16082      if (format.selector) {
16083        return NodeType.isElement(node) && dom.is(node, format.selector);
16084      }
16085    };
16086    var isColorFormatAndAnchor = function (node, format) {
16087      return format.links && node.tagName === 'A';
16088    };
16089    var find$3 = function (dom, node, next, inc) {
16090      node = FormatUtils.getNonWhiteSpaceSibling(node, next, inc);
16091      return !node || (node.nodeName === 'BR' || dom.isBlock(node));
16092    };
16093    var removeNode$1 = function (ed, node, format) {
16094      var parentNode = node.parentNode;
16095      var rootBlockElm;
16096      var dom = ed.dom, forcedRootBlock = Settings.getForcedRootBlock(ed);
16097      if (format.block) {
16098        if (!forcedRootBlock) {
16099          if (dom.isBlock(node) && !dom.isBlock(parentNode)) {
16100            if (!find$3(dom, node, false) && !find$3(dom, node.firstChild, true, 1)) {
16101              node.insertBefore(dom.create('br'), node.firstChild);
16102            }
16103            if (!find$3(dom, node, true) && !find$3(dom, node.lastChild, false, 1)) {
16104              node.appendChild(dom.create('br'));
16105            }
16106          }
16107        } else {
16108          if (parentNode === dom.getRoot()) {
16109            if (!format.list_block || !isEq$4(node, format.list_block)) {
16110              each$b(Tools.grep(node.childNodes), function (node) {
16111                if (FormatUtils.isValid(ed, forcedRootBlock, node.nodeName.toLowerCase())) {
16112                  if (!rootBlockElm) {
16113                    rootBlockElm = wrap$2(dom, node, forcedRootBlock);
16114                    dom.setAttribs(rootBlockElm, ed.settings.forced_root_block_attrs);
16115                  } else {
16116                    rootBlockElm.appendChild(node);
16117                  }
16118                } else {
16119                  rootBlockElm = 0;
16120                }
16121              });
16122            }
16123          }
16124        }
16125      }
16126      if (format.selector && format.inline && !isEq$4(format.inline, node)) {
16127        return;
16128      }
16129      dom.remove(node, 1);
16130    };
16131    var removeFormat = function (ed, format, vars, node, compareNode) {
16132      var i, attrs, stylesModified;
16133      var dom = ed.dom;
16134      if (!matchName$1(dom, node, format) && !isColorFormatAndAnchor(node, format)) {
16135        return false;
16136      }
16137      if (format.remove !== 'all') {
16138        each$b(format.styles, function (value, name) {
16139          value = FormatUtils.normalizeStyleValue(dom, FormatUtils.replaceVars(value, vars), name);
16140          if (typeof name === 'number') {
16141            name = value;
16142            compareNode = 0;
16143          }
16144          if (format.remove_similar || (!compareNode || isEq$4(FormatUtils.getStyle(dom, compareNode, name), value))) {
16145            dom.setStyle(node, name, '');
16146          }
16147          stylesModified = 1;
16148        });
16149        if (stylesModified && dom.getAttrib(node, 'style') === '') {
16150          node.removeAttribute('style');
16151          node.removeAttribute('data-mce-style');
16152        }
16153        each$b(format.attributes, function (value, name) {
16154          var valueOut;
16155          value = FormatUtils.replaceVars(value, vars);
16156          if (typeof name === 'number') {
16157            name = value;
16158            compareNode = 0;
16159          }
16160          if (!compareNode || isEq$4(dom.getAttrib(compareNode, name), value)) {
16161            if (name === 'class') {
16162              value = dom.getAttrib(node, name);
16163              if (value) {
16164                valueOut = '';
16165                each$b(value.split(/\s+/), function (cls) {
16166                  if (/mce\-\w+/.test(cls)) {
16167                    valueOut += (valueOut ? ' ' : '') + cls;
16168                  }
16169                });
16170                if (valueOut) {
16171                  dom.setAttrib(node, name, valueOut);
16172                  return;
16173                }
16174              }
16175            }
16176            if (name === 'class') {
16177              node.removeAttribute('className');
16178            }
16179            if (MCE_ATTR_RE.test(name)) {
16180              node.removeAttribute('data-mce-' + name);
16181            }
16182            node.removeAttribute(name);
16183          }
16184        });
16185        each$b(format.classes, function (value) {
16186          value = FormatUtils.replaceVars(value, vars);
16187          if (!compareNode || dom.hasClass(compareNode, value)) {
16188            dom.removeClass(node, value);
16189          }
16190        });
16191        attrs = dom.getAttribs(node);
16192        for (i = 0; i < attrs.length; i++) {
16193          var attrName = attrs[i].nodeName;
16194          if (attrName.indexOf('_') !== 0 && attrName.indexOf('data-') !== 0) {
16195            return false;
16196          }
16197        }
16198      }
16199      if (format.remove !== 'none') {
16200        removeNode$1(ed, node, format);
16201        return true;
16202      }
16203    };
16204    var findFormatRoot = function (editor, container, name, vars, similar) {
16205      var formatRoot;
16206      each$b(FormatUtils.getParents(editor.dom, container.parentNode).reverse(), function (parent) {
16207        var format;
16208        if (!formatRoot && parent.id !== '_start' && parent.id !== '_end') {
16209          format = MatchFormat.matchNode(editor, parent, name, vars, similar);
16210          if (format && format.split !== false) {
16211            formatRoot = parent;
16212          }
16213        }
16214      });
16215      return formatRoot;
16216    };
16217    var wrapAndSplit = function (editor, formatList, formatRoot, container, target, split, format, vars) {
16218      var parent, clone, lastClone, firstClone, i, formatRootParent;
16219      var dom = editor.dom;
16220      if (formatRoot) {
16221        formatRootParent = formatRoot.parentNode;
16222        for (parent = container.parentNode; parent && parent !== formatRootParent; parent = parent.parentNode) {
16223          clone = dom.clone(parent, false);
16224          for (i = 0; i < formatList.length; i++) {
16225            if (removeFormat(editor, formatList[i], vars, clone, clone)) {
16226              clone = 0;
16227              break;
16228            }
16229          }
16230          if (clone) {
16231            if (lastClone) {
16232              clone.appendChild(lastClone);
16233            }
16234            if (!firstClone) {
16235              firstClone = clone;
16236            }
16237            lastClone = clone;
16238          }
16239        }
16240        if (split && (!format.mixed || !dom.isBlock(formatRoot))) {
16241          container = dom.split(formatRoot, container);
16242        }
16243        if (lastClone) {
16244          target.parentNode.insertBefore(lastClone, target);
16245          firstClone.appendChild(target);
16246        }
16247      }
16248      return container;
16249    };
16250    var remove$7 = function (ed, name, vars, node, similar) {
16251      var formatList = ed.formatter.get(name), format = formatList[0];
16252      var bookmark, rng, contentEditable = true;
16253      var dom = ed.dom;
16254      var selection = ed.selection;
16255      var splitToFormatRoot = function (container) {
16256        var formatRoot = findFormatRoot(ed, container, name, vars, similar);
16257        return wrapAndSplit(ed, formatList, formatRoot, container, container, true, format, vars);
16258      };
16259      var isRemoveBookmarkNode = function (node) {
16260        return Bookmarks.isBookmarkNode(node) && NodeType.isElement(node) && (node.id === '_start' || node.id === '_end');
16261      };
16262      var process = function (node) {
16263        var children, i, l, lastContentEditable, hasContentEditableState;
16264        if (NodeType.isElement(node) && dom.getContentEditable(node)) {
16265          lastContentEditable = contentEditable;
16266          contentEditable = dom.getContentEditable(node) === 'true';
16267          hasContentEditableState = true;
16268        }
16269        children = Tools.grep(node.childNodes);
16270        if (contentEditable && !hasContentEditableState) {
16271          for (i = 0, l = formatList.length; i < l; i++) {
16272            if (removeFormat(ed, formatList[i], vars, node, node)) {
16273              break;
16274            }
16275          }
16276        }
16277        if (format.deep) {
16278          if (children.length) {
16279            for (i = 0, l = children.length; i < l; i++) {
16280              process(children[i]);
16281            }
16282            if (hasContentEditableState) {
16283              contentEditable = lastContentEditable;
16284            }
16285          }
16286        }
16287      };
16288      var unwrap = function (start) {
16289        var node = dom.get(start ? '_start' : '_end');
16290        var out = node[start ? 'firstChild' : 'lastChild'];
16291        if (isRemoveBookmarkNode(out)) {
16292          out = out[start ? 'firstChild' : 'lastChild'];
16293        }
16294        if (NodeType.isText(out) && out.data.length === 0) {
16295          out = start ? node.previousSibling || node.nextSibling : node.nextSibling || node.previousSibling;
16296        }
16297        dom.remove(node, true);
16298        return out;
16299      };
16300      var removeRngStyle = function (rng) {
16301        var startContainer, endContainer;
16302        var commonAncestorContainer = rng.commonAncestorContainer;
16303        rng = ExpandRange.expandRng(ed, rng, formatList, true);
16304        if (format.split) {
16305          rng = split$1(rng);
16306          startContainer = getContainer(ed, rng, true);
16307          endContainer = getContainer(ed, rng);
16308          if (startContainer !== endContainer) {
16309            if (/^(TR|TH|TD)$/.test(startContainer.nodeName) && startContainer.firstChild) {
16310              if (startContainer.nodeName === 'TR') {
16311                startContainer = startContainer.firstChild.firstChild || startContainer;
16312              } else {
16313                startContainer = startContainer.firstChild || startContainer;
16314              }
16315            }
16316            if (commonAncestorContainer && /^T(HEAD|BODY|FOOT|R)$/.test(commonAncestorContainer.nodeName) && isTableCell$2(endContainer) && endContainer.firstChild) {
16317              endContainer = endContainer.firstChild || endContainer;
16318            }
16319            if (isChildOfInlineParent(dom, startContainer, endContainer)) {
16320              var marker = Option.from(startContainer.firstChild).getOr(startContainer);
16321              splitToFormatRoot(wrapWithSiblings(dom, marker, true, 'span', {
16322                'id': '_start',
16323                'data-mce-type': 'bookmark'
16324              }));
16325              unwrap(true);
16326              return;
16327            }
16328            if (isChildOfInlineParent(dom, endContainer, startContainer)) {
16329              var marker = Option.from(endContainer.lastChild).getOr(endContainer);
16330              splitToFormatRoot(wrapWithSiblings(dom, marker, false, 'span', {
16331                'id': '_end',
16332                'data-mce-type': 'bookmark'
16333              }));
16334              unwrap(false);
16335              return;
16336            }
16337            startContainer = wrap$2(dom, startContainer, 'span', {
16338              'id': '_start',
16339              'data-mce-type': 'bookmark'
16340            });
16341            endContainer = wrap$2(dom, endContainer, 'span', {
16342              'id': '_end',
16343              'data-mce-type': 'bookmark'
16344            });
16345            splitToFormatRoot(startContainer);
16346            splitToFormatRoot(endContainer);
16347            startContainer = unwrap(true);
16348            endContainer = unwrap();
16349          } else {
16350            startContainer = endContainer = splitToFormatRoot(startContainer);
16351          }
16352          rng.startContainer = startContainer.parentNode ? startContainer.parentNode : startContainer;
16353          rng.startOffset = dom.nodeIndex(startContainer);
16354          rng.endContainer = endContainer.parentNode ? endContainer.parentNode : endContainer;
16355          rng.endOffset = dom.nodeIndex(endContainer) + 1;
16356        }
16357        RangeWalk.walk(dom, rng, function (nodes) {
16358          each$b(nodes, function (node) {
16359            process(node);
16360            if (NodeType.isElement(node) && ed.dom.getStyle(node, 'text-decoration') === 'underline' && node.parentNode && FormatUtils.getTextDecoration(dom, node.parentNode) === 'underline') {
16361              removeFormat(ed, {
16362                deep: false,
16363                exact: true,
16364                inline: 'span',
16365                styles: { textDecoration: 'underline' }
16366              }, null, node);
16367            }
16368          });
16369        });
16370      };
16371      if (node) {
16372        if (node.nodeType) {
16373          rng = dom.createRng();
16374          rng.setStartBefore(node);
16375          rng.setEndAfter(node);
16376          removeRngStyle(rng);
16377        } else {
16378          removeRngStyle(node);
16379        }
16380        return;
16381      }
16382      if (dom.getContentEditable(selection.getNode()) === 'false') {
16383        node = selection.getNode();
16384        for (var i = 0, l = formatList.length; i < l; i++) {
16385          if (formatList[i].ceFalseOverride) {
16386            if (removeFormat(ed, formatList[i], vars, node, node)) {
16387              break;
16388            }
16389          }
16390        }
16391        return;
16392      }
16393      if (!selection.isCollapsed() || !format.inline || dom.select('td[data-mce-selected],th[data-mce-selected]').length) {
16394        bookmark = GetBookmark.getPersistentBookmark(ed.selection, true);
16395        removeRngStyle(selection.getRng());
16396        selection.moveToBookmark(bookmark);
16397        if (format.inline && MatchFormat.match(ed, name, vars, selection.getStart())) {
16398          FormatUtils.moveStart(dom, selection, selection.getRng());
16399        }
16400        ed.nodeChanged();
16401      } else {
16402        removeCaretFormat(ed, name, vars, similar);
16403      }
16404    };
16405    var RemoveFormat = {
16406      removeFormat: removeFormat,
16407      remove: remove$7
16408    };
16409
16410    var each$c = Tools.each;
16411    var isElementNode = function (node) {
16412      return node && node.nodeType === 1 && !Bookmarks.isBookmarkNode(node) && !isCaretNode(node) && !NodeType.isBogus(node);
16413    };
16414    var findElementSibling = function (node, siblingName) {
16415      var sibling;
16416      for (sibling = node; sibling; sibling = sibling[siblingName]) {
16417        if (sibling.nodeType === 3 && sibling.nodeValue.length !== 0) {
16418          return node;
16419        }
16420        if (sibling.nodeType === 1 && !Bookmarks.isBookmarkNode(sibling)) {
16421          return sibling;
16422        }
16423      }
16424      return node;
16425    };
16426    var mergeSiblingsNodes = function (dom, prev, next) {
16427      var sibling, tmpSibling;
16428      var elementUtils = new ElementUtils(dom);
16429      if (prev && next) {
16430        prev = findElementSibling(prev, 'previousSibling');
16431        next = findElementSibling(next, 'nextSibling');
16432        if (elementUtils.compare(prev, next)) {
16433          for (sibling = prev.nextSibling; sibling && sibling !== next;) {
16434            tmpSibling = sibling;
16435            sibling = sibling.nextSibling;
16436            prev.appendChild(tmpSibling);
16437          }
16438          dom.remove(next);
16439          Tools.each(Tools.grep(next.childNodes), function (node) {
16440            prev.appendChild(node);
16441          });
16442          return prev;
16443        }
16444      }
16445      return next;
16446    };
16447    var processChildElements = function (node, filter, process) {
16448      each$c(node.childNodes, function (node) {
16449        if (isElementNode(node)) {
16450          if (filter(node)) {
16451            process(node);
16452          }
16453          if (node.hasChildNodes()) {
16454            processChildElements(node, filter, process);
16455          }
16456        }
16457      });
16458    };
16459    var hasStyle = function (dom, name) {
16460      return curry(function (name, node) {
16461        return !!(node && FormatUtils.getStyle(dom, node, name));
16462      }, name);
16463    };
16464    var applyStyle = function (dom, name, value) {
16465      return curry(function (name, value, node) {
16466        dom.setStyle(node, name, value);
16467        if (node.getAttribute('style') === '') {
16468          node.removeAttribute('style');
16469        }
16470        unwrapEmptySpan(dom, node);
16471      }, name, value);
16472    };
16473    var unwrapEmptySpan = function (dom, node) {
16474      if (node.nodeName === 'SPAN' && dom.getAttribs(node).length === 0) {
16475        dom.remove(node, true);
16476      }
16477    };
16478    var processUnderlineAndColor = function (dom, node) {
16479      var textDecoration;
16480      if (node.nodeType === 1 && node.parentNode && node.parentNode.nodeType === 1) {
16481        textDecoration = FormatUtils.getTextDecoration(dom, node.parentNode);
16482        if (dom.getStyle(node, 'color') && textDecoration) {
16483          dom.setStyle(node, 'text-decoration', textDecoration);
16484        } else if (dom.getStyle(node, 'text-decoration') === textDecoration) {
16485          dom.setStyle(node, 'text-decoration', null);
16486        }
16487      }
16488    };
16489    var mergeUnderlineAndColor = function (dom, format, vars, node) {
16490      if (format.styles.color || format.styles.textDecoration) {
16491        Tools.walk(node, curry(processUnderlineAndColor, dom), 'childNodes');
16492        processUnderlineAndColor(dom, node);
16493      }
16494    };
16495    var mergeBackgroundColorAndFontSize = function (dom, format, vars, node) {
16496      if (format.styles && format.styles.backgroundColor) {
16497        processChildElements(node, hasStyle(dom, 'fontSize'), applyStyle(dom, 'backgroundColor', FormatUtils.replaceVars(format.styles.backgroundColor, vars)));
16498      }
16499    };
16500    var mergeSubSup = function (dom, format, vars, node) {
16501      if (format.inline === 'sub' || format.inline === 'sup') {
16502        processChildElements(node, hasStyle(dom, 'fontSize'), applyStyle(dom, 'fontSize', ''));
16503        dom.remove(dom.select(format.inline === 'sup' ? 'sub' : 'sup', node), true);
16504      }
16505    };
16506    var mergeSiblings = function (dom, format, vars, node) {
16507      if (node && format.merge_siblings !== false) {
16508        node = mergeSiblingsNodes(dom, FormatUtils.getNonWhiteSpaceSibling(node), node);
16509        node = mergeSiblingsNodes(dom, node, FormatUtils.getNonWhiteSpaceSibling(node, true));
16510      }
16511    };
16512    var clearChildStyles = function (dom, format, node) {
16513      if (format.clear_child_styles) {
16514        var selector = format.links ? '*:not(a)' : '*';
16515        each$c(dom.select(selector, node), function (node) {
16516          if (isElementNode(node)) {
16517            each$c(format.styles, function (value, name) {
16518              dom.setStyle(node, name, '');
16519            });
16520          }
16521        });
16522      }
16523    };
16524    var mergeWithChildren = function (editor, formatList, vars, node) {
16525      each$c(formatList, function (format) {
16526        each$c(editor.dom.select(format.inline, node), function (child) {
16527          if (!isElementNode(child)) {
16528            return;
16529          }
16530          RemoveFormat.removeFormat(editor, format, vars, child, format.exact ? child : null);
16531        });
16532        clearChildStyles(editor.dom, format, node);
16533      });
16534    };
16535    var mergeWithParents = function (editor, format, name, vars, node) {
16536      if (MatchFormat.matchNode(editor, node.parentNode, name, vars)) {
16537        if (RemoveFormat.removeFormat(editor, format, vars, node)) {
16538          return;
16539        }
16540      }
16541      if (format.merge_with_parents) {
16542        editor.dom.getParent(node.parentNode, function (parent) {
16543          if (MatchFormat.matchNode(editor, parent, name, vars)) {
16544            RemoveFormat.removeFormat(editor, format, vars, node);
16545            return true;
16546          }
16547        });
16548      }
16549    };
16550    var MergeFormats = {
16551      mergeWithChildren: mergeWithChildren,
16552      mergeUnderlineAndColor: mergeUnderlineAndColor,
16553      mergeBackgroundColorAndFontSize: mergeBackgroundColorAndFontSize,
16554      mergeSubSup: mergeSubSup,
16555      mergeSiblings: mergeSiblings,
16556      mergeWithParents: mergeWithParents
16557    };
16558
16559    var createRange$1 = function (sc, so, ec, eo) {
16560      var rng = domGlobals.document.createRange();
16561      rng.setStart(sc, so);
16562      rng.setEnd(ec, eo);
16563      return rng;
16564    };
16565    var normalizeBlockSelectionRange = function (rng) {
16566      var startPos = CaretPosition$1.fromRangeStart(rng);
16567      var endPos = CaretPosition$1.fromRangeEnd(rng);
16568      var rootNode = rng.commonAncestorContainer;
16569      return CaretFinder.fromPosition(false, rootNode, endPos).map(function (newEndPos) {
16570        if (!isInSameBlock(startPos, endPos, rootNode) && isInSameBlock(startPos, newEndPos, rootNode)) {
16571          return createRange$1(startPos.container(), startPos.offset(), newEndPos.container(), newEndPos.offset());
16572        } else {
16573          return rng;
16574        }
16575      }).getOr(rng);
16576    };
16577    var normalize$1 = function (rng) {
16578      return rng.collapsed ? rng : normalizeBlockSelectionRange(rng);
16579    };
16580    var RangeNormalizer = { normalize: normalize$1 };
16581
16582    var each$d = Tools.each;
16583    var isElementNode$1 = function (node) {
16584      return node && node.nodeType === 1 && !Bookmarks.isBookmarkNode(node) && !isCaretNode(node) && !NodeType.isBogus(node);
16585    };
16586    var applyFormat = function (ed, name, vars, node) {
16587      var formatList = ed.formatter.get(name);
16588      var format = formatList[0];
16589      var bookmark, rng;
16590      var isCollapsed = !node && ed.selection.isCollapsed();
16591      var dom = ed.dom, selection = ed.selection;
16592      var setElementFormat = function (elm, fmt) {
16593        fmt = fmt || format;
16594        if (elm) {
16595          if (fmt.onformat) {
16596            fmt.onformat(elm, fmt, vars, node);
16597          }
16598          each$d(fmt.styles, function (value, name) {
16599            dom.setStyle(elm, name, FormatUtils.replaceVars(value, vars));
16600          });
16601          if (fmt.styles) {
16602            var styleVal = dom.getAttrib(elm, 'style');
16603            if (styleVal) {
16604              elm.setAttribute('data-mce-style', styleVal);
16605            }
16606          }
16607          each$d(fmt.attributes, function (value, name) {
16608            dom.setAttrib(elm, name, FormatUtils.replaceVars(value, vars));
16609          });
16610          each$d(fmt.classes, function (value) {
16611            value = FormatUtils.replaceVars(value, vars);
16612            if (!dom.hasClass(elm, value)) {
16613              dom.addClass(elm, value);
16614            }
16615          });
16616        }
16617      };
16618      var applyNodeStyle = function (formatList, node) {
16619        var found = false;
16620        if (!format.selector) {
16621          return false;
16622        }
16623        each$d(formatList, function (format) {
16624          if ('collapsed' in format && format.collapsed !== isCollapsed) {
16625            return;
16626          }
16627          if (dom.is(node, format.selector) && !isCaretNode(node)) {
16628            setElementFormat(node, format);
16629            found = true;
16630            return false;
16631          }
16632        });
16633        return found;
16634      };
16635      var applyRngStyle = function (dom, rng, bookmark, nodeSpecific) {
16636        var newWrappers = [];
16637        var wrapName, wrapElm, contentEditable = true;
16638        wrapName = format.inline || format.block;
16639        wrapElm = dom.create(wrapName);
16640        setElementFormat(wrapElm);
16641        RangeWalk.walk(dom, rng, function (nodes) {
16642          var currentWrapElm;
16643          var process = function (node) {
16644            var nodeName, parentName, hasContentEditableState, lastContentEditable;
16645            lastContentEditable = contentEditable;
16646            nodeName = node.nodeName.toLowerCase();
16647            parentName = node.parentNode.nodeName.toLowerCase();
16648            if (node.nodeType === 1 && dom.getContentEditable(node)) {
16649              lastContentEditable = contentEditable;
16650              contentEditable = dom.getContentEditable(node) === 'true';
16651              hasContentEditableState = true;
16652            }
16653            if (FormatUtils.isEq(nodeName, 'br')) {
16654              currentWrapElm = 0;
16655              if (format.block) {
16656                dom.remove(node);
16657              }
16658              return;
16659            }
16660            if (format.wrapper && MatchFormat.matchNode(ed, node, name, vars)) {
16661              currentWrapElm = 0;
16662              return;
16663            }
16664            if (contentEditable && !hasContentEditableState && format.block && !format.wrapper && FormatUtils.isTextBlock(ed, nodeName) && FormatUtils.isValid(ed, parentName, wrapName)) {
16665              node = dom.rename(node, wrapName);
16666              setElementFormat(node);
16667              newWrappers.push(node);
16668              currentWrapElm = 0;
16669              return;
16670            }
16671            if (format.selector) {
16672              var found = applyNodeStyle(formatList, node);
16673              if (!format.inline || found) {
16674                currentWrapElm = 0;
16675                return;
16676              }
16677            }
16678            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))) {
16679              if (!currentWrapElm) {
16680                currentWrapElm = dom.clone(wrapElm, false);
16681                node.parentNode.insertBefore(currentWrapElm, node);
16682                newWrappers.push(currentWrapElm);
16683              }
16684              currentWrapElm.appendChild(node);
16685            } else {
16686              currentWrapElm = 0;
16687              each$d(Tools.grep(node.childNodes), process);
16688              if (hasContentEditableState) {
16689                contentEditable = lastContentEditable;
16690              }
16691              currentWrapElm = 0;
16692            }
16693          };
16694          each$d(nodes, process);
16695        });
16696        if (format.links === true) {
16697          each$d(newWrappers, function (node) {
16698            var process = function (node) {
16699              if (node.nodeName === 'A') {
16700                setElementFormat(node, format);
16701              }
16702              each$d(Tools.grep(node.childNodes), process);
16703            };
16704            process(node);
16705          });
16706        }
16707        each$d(newWrappers, function (node) {
16708          var childCount;
16709          var getChildCount = function (node) {
16710            var count = 0;
16711            each$d(node.childNodes, function (node) {
16712              if (!FormatUtils.isWhiteSpaceNode(node) && !Bookmarks.isBookmarkNode(node)) {
16713                count++;
16714              }
16715            });
16716            return count;
16717          };
16718          var getChildElementNode = function (root) {
16719            var child = false;
16720            each$d(root.childNodes, function (node) {
16721              if (isElementNode$1(node)) {
16722                child = node;
16723                return false;
16724              }
16725            });
16726            return child;
16727          };
16728          var mergeStyles = function (node) {
16729            var child, clone;
16730            child = getChildElementNode(node);
16731            if (child && !Bookmarks.isBookmarkNode(child) && MatchFormat.matchName(dom, child, format)) {
16732              clone = dom.clone(child, false);
16733              setElementFormat(clone);
16734              dom.replace(clone, node, true);
16735              dom.remove(child, 1);
16736            }
16737            return clone || node;
16738          };
16739          childCount = getChildCount(node);
16740          if ((newWrappers.length > 1 || !dom.isBlock(node)) && childCount === 0) {
16741            dom.remove(node, 1);
16742            return;
16743          }
16744          if (format.inline || format.wrapper) {
16745            if (!format.exact && childCount === 1) {
16746              node = mergeStyles(node);
16747            }
16748            MergeFormats.mergeWithChildren(ed, formatList, vars, node);
16749            MergeFormats.mergeWithParents(ed, format, name, vars, node);
16750            MergeFormats.mergeBackgroundColorAndFontSize(dom, format, vars, node);
16751            MergeFormats.mergeSubSup(dom, format, vars, node);
16752            MergeFormats.mergeSiblings(dom, format, vars, node);
16753          }
16754        });
16755      };
16756      if (dom.getContentEditable(selection.getNode()) === 'false') {
16757        node = selection.getNode();
16758        for (var i = 0, l = formatList.length; i < l; i++) {
16759          if (formatList[i].ceFalseOverride && dom.is(node, formatList[i].selector)) {
16760            setElementFormat(node, formatList[i]);
16761            return;
16762          }
16763        }
16764        return;
16765      }
16766      if (format) {
16767        if (node) {
16768          if (node.nodeType) {
16769            if (!applyNodeStyle(formatList, node)) {
16770              rng = dom.createRng();
16771              rng.setStartBefore(node);
16772              rng.setEndAfter(node);
16773              applyRngStyle(dom, ExpandRange.expandRng(ed, rng, formatList), null, true);
16774            }
16775          } else {
16776            applyRngStyle(dom, node, null, true);
16777          }
16778        } else {
16779          if (!isCollapsed || !format.inline || dom.select('td[data-mce-selected],th[data-mce-selected]').length) {
16780            var curSelNode = ed.selection.getNode();
16781            if (!ed.settings.forced_root_block && formatList[0].defaultBlock && !dom.getParent(curSelNode, dom.isBlock)) {
16782              applyFormat(ed, formatList[0].defaultBlock);
16783            }
16784            ed.selection.setRng(RangeNormalizer.normalize(ed.selection.getRng()));
16785            bookmark = GetBookmark.getPersistentBookmark(ed.selection, true);
16786            applyRngStyle(dom, ExpandRange.expandRng(ed, selection.getRng(), formatList), bookmark);
16787            if (format.styles) {
16788              MergeFormats.mergeUnderlineAndColor(dom, format, vars, curSelNode);
16789            }
16790            selection.moveToBookmark(bookmark);
16791            FormatUtils.moveStart(dom, selection, selection.getRng());
16792            ed.nodeChanged();
16793          } else {
16794            applyCaretFormat(ed, name, vars);
16795          }
16796        }
16797        Hooks.postProcess(name, ed);
16798      }
16799    };
16800    var ApplyFormat = { applyFormat: applyFormat };
16801
16802    var setup$5 = function (registeredFormatListeners, editor) {
16803      var currentFormats = Cell({});
16804      registeredFormatListeners.set({});
16805      editor.on('NodeChange', function (e) {
16806        updateAndFireChangeCallbacks(editor, e.element, currentFormats, registeredFormatListeners.get());
16807      });
16808    };
16809    var updateAndFireChangeCallbacks = function (editor, elm, currentFormats, formatChangeData) {
16810      var formatsList = keys(currentFormats.get());
16811      var newFormats = {};
16812      var matchedFormats = {};
16813      var parents = filter(FormatUtils.getParents(editor.dom, elm), function (node) {
16814        return node.nodeType === 1 && !node.getAttribute('data-mce-bogus');
16815      });
16816      each$3(formatChangeData, function (data, format) {
16817        Tools.each(parents, function (node) {
16818          if (editor.formatter.matchNode(node, format, {}, data.similar)) {
16819            if (formatsList.indexOf(format) === -1) {
16820              each(data.callbacks, function (callback) {
16821                callback(true, {
16822                  node: node,
16823                  format: format,
16824                  parents: parents
16825                });
16826              });
16827              newFormats[format] = data.callbacks;
16828            }
16829            matchedFormats[format] = data.callbacks;
16830            return false;
16831          }
16832          if (MatchFormat.matchesUnInheritedFormatSelector(editor, node, format)) {
16833            return false;
16834          }
16835        });
16836      });
16837      var remainingFormats = filterRemainingFormats(currentFormats.get(), matchedFormats, elm, parents);
16838      currentFormats.set(__assign({}, newFormats, remainingFormats));
16839    };
16840    var filterRemainingFormats = function (currentFormats, matchedFormats, elm, parents) {
16841      return bifilter(currentFormats, function (callbacks, format) {
16842        if (!has(matchedFormats, format)) {
16843          each(callbacks, function (callback) {
16844            callback(false, {
16845              node: elm,
16846              format: format,
16847              parents: parents
16848            });
16849          });
16850          return false;
16851        } else {
16852          return true;
16853        }
16854      }).t;
16855    };
16856    var addListeners = function (registeredFormatListeners, formats, callback, similar) {
16857      var formatChangeItems = registeredFormatListeners.get();
16858      each(formats.split(','), function (format) {
16859        if (!formatChangeItems[format]) {
16860          formatChangeItems[format] = {
16861            similar: similar,
16862            callbacks: []
16863          };
16864        }
16865        formatChangeItems[format].callbacks.push(callback);
16866      });
16867      registeredFormatListeners.set(formatChangeItems);
16868    };
16869    var removeListeners = function (registeredFormatListeners, formats, callback) {
16870      var formatChangeItems = registeredFormatListeners.get();
16871      each(formats.split(','), function (format) {
16872        formatChangeItems[format].callbacks = filter(formatChangeItems[format].callbacks, function (c) {
16873          return c !== callback;
16874        });
16875        if (formatChangeItems[format].callbacks.length === 0) {
16876          delete formatChangeItems[format];
16877        }
16878      });
16879      registeredFormatListeners.set(formatChangeItems);
16880    };
16881    var formatChanged = function (editor, registeredFormatListeners, formats, callback, similar) {
16882      if (registeredFormatListeners.get() === null) {
16883        setup$5(registeredFormatListeners, editor);
16884      }
16885      addListeners(registeredFormatListeners, formats, callback, similar);
16886      return {
16887        unbind: function () {
16888          return removeListeners(registeredFormatListeners, formats, callback);
16889        }
16890      };
16891    };
16892
16893    var get$6 = function (dom) {
16894      var formats = {
16895        valigntop: [{
16896            selector: 'td,th',
16897            styles: { verticalAlign: 'top' }
16898          }],
16899        valignmiddle: [{
16900            selector: 'td,th',
16901            styles: { verticalAlign: 'middle' }
16902          }],
16903        valignbottom: [{
16904            selector: 'td,th',
16905            styles: { verticalAlign: 'bottom' }
16906          }],
16907        alignleft: [
16908          {
16909            selector: 'figure.image',
16910            collapsed: false,
16911            classes: 'align-left',
16912            ceFalseOverride: true,
16913            preview: 'font-family font-size'
16914          },
16915          {
16916            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
16917            styles: { textAlign: 'left' },
16918            inherit: false,
16919            preview: false,
16920            defaultBlock: 'div'
16921          },
16922          {
16923            selector: 'img,table',
16924            collapsed: false,
16925            styles: { float: 'left' },
16926            preview: 'font-family font-size'
16927          }
16928        ],
16929        aligncenter: [
16930          {
16931            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
16932            styles: { textAlign: 'center' },
16933            inherit: false,
16934            preview: 'font-family font-size',
16935            defaultBlock: 'div'
16936          },
16937          {
16938            selector: 'figure.image',
16939            collapsed: false,
16940            classes: 'align-center',
16941            ceFalseOverride: true,
16942            preview: 'font-family font-size'
16943          },
16944          {
16945            selector: 'img',
16946            collapsed: false,
16947            styles: {
16948              display: 'block',
16949              marginLeft: 'auto',
16950              marginRight: 'auto'
16951            },
16952            preview: false
16953          },
16954          {
16955            selector: 'table',
16956            collapsed: false,
16957            styles: {
16958              marginLeft: 'auto',
16959              marginRight: 'auto'
16960            },
16961            preview: 'font-family font-size'
16962          }
16963        ],
16964        alignright: [
16965          {
16966            selector: 'figure.image',
16967            collapsed: false,
16968            classes: 'align-right',
16969            ceFalseOverride: true,
16970            preview: 'font-family font-size'
16971          },
16972          {
16973            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
16974            styles: { textAlign: 'right' },
16975            inherit: false,
16976            preview: 'font-family font-size',
16977            defaultBlock: 'div'
16978          },
16979          {
16980            selector: 'img,table',
16981            collapsed: false,
16982            styles: { float: 'right' },
16983            preview: 'font-family font-size'
16984          }
16985        ],
16986        alignjustify: [{
16987            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
16988            styles: { textAlign: 'justify' },
16989            inherit: false,
16990            defaultBlock: 'div',
16991            preview: 'font-family font-size'
16992          }],
16993        bold: [
16994          {
16995            inline: 'strong',
16996            remove: 'all'
16997          },
16998          {
16999            inline: 'span',
17000            styles: { fontWeight: 'bold' }
17001          },
17002          {
17003            inline: 'b',
17004            remove: 'all'
17005          }
17006        ],
17007        italic: [
17008          {
17009            inline: 'em',
17010            remove: 'all'
17011          },
17012          {
17013            inline: 'span',
17014            styles: { fontStyle: 'italic' }
17015          },
17016          {
17017            inline: 'i',
17018            remove: 'all'
17019          }
17020        ],
17021        underline: [
17022          {
17023            inline: 'span',
17024            styles: { textDecoration: 'underline' },
17025            exact: true
17026          },
17027          {
17028            inline: 'u',
17029            remove: 'all'
17030          }
17031        ],
17032        strikethrough: [
17033          {
17034            inline: 'span',
17035            styles: { textDecoration: 'line-through' },
17036            exact: true
17037          },
17038          {
17039            inline: 'strike',
17040            remove: 'all'
17041          }
17042        ],
17043        forecolor: {
17044          inline: 'span',
17045          styles: { color: '%value' },
17046          links: true,
17047          remove_similar: true,
17048          clear_child_styles: true
17049        },
17050        hilitecolor: {
17051          inline: 'span',
17052          styles: { backgroundColor: '%value' },
17053          links: true,
17054          remove_similar: true,
17055          clear_child_styles: true
17056        },
17057        fontname: {
17058          inline: 'span',
17059          toggle: false,
17060          styles: { fontFamily: '%value' },
17061          clear_child_styles: true
17062        },
17063        fontsize: {
17064          inline: 'span',
17065          toggle: false,
17066          styles: { fontSize: '%value' },
17067          clear_child_styles: true
17068        },
17069        fontsize_class: {
17070          inline: 'span',
17071          attributes: { class: '%value' }
17072        },
17073        blockquote: {
17074          block: 'blockquote',
17075          wrapper: true,
17076          remove: 'all'
17077        },
17078        subscript: { inline: 'sub' },
17079        superscript: { inline: 'sup' },
17080        code: { inline: 'code' },
17081        link: {
17082          inline: 'a',
17083          selector: 'a',
17084          remove: 'all',
17085          split: true,
17086          deep: true,
17087          onmatch: function () {
17088            return true;
17089          },
17090          onformat: function (elm, fmt, vars) {
17091            Tools.each(vars, function (value, key) {
17092              dom.setAttrib(elm, key, value);
17093            });
17094          }
17095        },
17096        removeformat: [
17097          {
17098            selector: 'b,strong,em,i,font,u,strike,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins',
17099            remove: 'all',
17100            split: true,
17101            expand: false,
17102            block_expand: true,
17103            deep: true
17104          },
17105          {
17106            selector: 'span',
17107            attributes: [
17108              'style',
17109              'class'
17110            ],
17111            remove: 'empty',
17112            split: true,
17113            expand: false,
17114            deep: true
17115          },
17116          {
17117            selector: '*',
17118            attributes: [
17119              'style',
17120              'class'
17121            ],
17122            split: false,
17123            expand: false,
17124            deep: true
17125          }
17126        ]
17127      };
17128      Tools.each('p h1 h2 h3 h4 h5 h6 div address pre div dt dd samp'.split(/\s/), function (name) {
17129        formats[name] = {
17130          block: name,
17131          remove: 'all'
17132        };
17133      });
17134      return formats;
17135    };
17136    var DefaultFormats = { get: get$6 };
17137
17138    function FormatRegistry(editor) {
17139      var formats = {};
17140      var get = function (name) {
17141        return name ? formats[name] : formats;
17142      };
17143      var has$1 = function (name) {
17144        return has(formats, name);
17145      };
17146      var register = function (name, format) {
17147        if (name) {
17148          if (typeof name !== 'string') {
17149            Tools.each(name, function (format, name) {
17150              register(name, format);
17151            });
17152          } else {
17153            if (!isArray(format)) {
17154              format = [format];
17155            }
17156            Tools.each(format, function (format) {
17157              if (typeof format.deep === 'undefined') {
17158                format.deep = !format.selector;
17159              }
17160              if (typeof format.split === 'undefined') {
17161                format.split = !format.selector || format.inline;
17162              }
17163              if (typeof format.remove === 'undefined' && format.selector && !format.inline) {
17164                format.remove = 'none';
17165              }
17166              if (format.selector && format.inline) {
17167                format.mixed = true;
17168                format.block_expand = true;
17169              }
17170              if (typeof format.classes === 'string') {
17171                format.classes = format.classes.split(/\s+/);
17172              }
17173            });
17174            formats[name] = format;
17175          }
17176        }
17177      };
17178      var unregister = function (name) {
17179        if (name && formats[name]) {
17180          delete formats[name];
17181        }
17182        return formats;
17183      };
17184      register(DefaultFormats.get(editor.dom));
17185      register(editor.settings.formats);
17186      return {
17187        get: get,
17188        has: has$1,
17189        register: register,
17190        unregister: unregister
17191      };
17192    }
17193
17194    var each$e = Tools.each;
17195    var dom = DOMUtils$1.DOM;
17196    var parsedSelectorToHtml = function (ancestry, editor) {
17197      var elm, item, fragment;
17198      var schema = editor && editor.schema || Schema({});
17199      var decorate = function (elm, item) {
17200        if (item.classes.length) {
17201          dom.addClass(elm, item.classes.join(' '));
17202        }
17203        dom.setAttribs(elm, item.attrs);
17204      };
17205      var createElement = function (sItem) {
17206        var elm;
17207        item = typeof sItem === 'string' ? {
17208          name: sItem,
17209          classes: [],
17210          attrs: {}
17211        } : sItem;
17212        elm = dom.create(item.name);
17213        decorate(elm, item);
17214        return elm;
17215      };
17216      var getRequiredParent = function (elm, candidate) {
17217        var name = typeof elm !== 'string' ? elm.nodeName.toLowerCase() : elm;
17218        var elmRule = schema.getElementRule(name);
17219        var parentsRequired = elmRule && elmRule.parentsRequired;
17220        if (parentsRequired && parentsRequired.length) {
17221          return candidate && Tools.inArray(parentsRequired, candidate) !== -1 ? candidate : parentsRequired[0];
17222        } else {
17223          return false;
17224        }
17225      };
17226      var wrapInHtml = function (elm, ancestry, siblings) {
17227        var parent, parentCandidate, parentRequired;
17228        var ancestor = ancestry.length > 0 && ancestry[0];
17229        var ancestorName = ancestor && ancestor.name;
17230        parentRequired = getRequiredParent(elm, ancestorName);
17231        if (parentRequired) {
17232          if (ancestorName === parentRequired) {
17233            parentCandidate = ancestry[0];
17234            ancestry = ancestry.slice(1);
17235          } else {
17236            parentCandidate = parentRequired;
17237          }
17238        } else if (ancestor) {
17239          parentCandidate = ancestry[0];
17240          ancestry = ancestry.slice(1);
17241        } else if (!siblings) {
17242          return elm;
17243        }
17244        if (parentCandidate) {
17245          parent = createElement(parentCandidate);
17246          parent.appendChild(elm);
17247        }
17248        if (siblings) {
17249          if (!parent) {
17250            parent = dom.create('div');
17251            parent.appendChild(elm);
17252          }
17253          Tools.each(siblings, function (sibling) {
17254            var siblingElm = createElement(sibling);
17255            parent.insertBefore(siblingElm, elm);
17256          });
17257        }
17258        return wrapInHtml(parent, ancestry, parentCandidate && parentCandidate.siblings);
17259      };
17260      if (ancestry && ancestry.length) {
17261        item = ancestry[0];
17262        elm = createElement(item);
17263        fragment = dom.create('div');
17264        fragment.appendChild(wrapInHtml(elm, ancestry.slice(1), item.siblings));
17265        return fragment;
17266      } else {
17267        return '';
17268      }
17269    };
17270    var selectorToHtml = function (selector, editor) {
17271      return parsedSelectorToHtml(parseSelector(selector), editor);
17272    };
17273    var parseSelectorItem = function (item) {
17274      var tagName;
17275      var obj = {
17276        classes: [],
17277        attrs: {}
17278      };
17279      item = obj.selector = Tools.trim(item);
17280      if (item !== '*') {
17281        tagName = item.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g, function ($0, $1, $2, $3, $4) {
17282          switch ($1) {
17283          case '#':
17284            obj.attrs.id = $2;
17285            break;
17286          case '.':
17287            obj.classes.push($2);
17288            break;
17289          case ':':
17290            if (Tools.inArray('checked disabled enabled read-only required'.split(' '), $2) !== -1) {
17291              obj.attrs[$2] = $2;
17292            }
17293            break;
17294          }
17295          if ($3 === '[') {
17296            var m = $4.match(/([\w\-]+)(?:\=\"([^\"]+))?/);
17297            if (m) {
17298              obj.attrs[m[1]] = m[2];
17299            }
17300          }
17301          return '';
17302        });
17303      }
17304      obj.name = tagName || 'div';
17305      return obj;
17306    };
17307    var parseSelector = function (selector) {
17308      if (!selector || typeof selector !== 'string') {
17309        return [];
17310      }
17311      selector = selector.split(/\s*,\s*/)[0];
17312      selector = selector.replace(/\s*(~\+|~|\+|>)\s*/g, '$1');
17313      return Tools.map(selector.split(/(?:>|\s+(?![^\[\]]+\]))/), function (item) {
17314        var siblings = Tools.map(item.split(/(?:~\+|~|\+)/), parseSelectorItem);
17315        var obj = siblings.pop();
17316        if (siblings.length) {
17317          obj.siblings = siblings;
17318        }
17319        return obj;
17320      }).reverse();
17321    };
17322    var getCssText = function (editor, format) {
17323      var name, previewFrag, previewElm, items;
17324      var previewCss = '', parentFontSize, previewStyles;
17325      previewStyles = editor.settings.preview_styles;
17326      if (previewStyles === false) {
17327        return '';
17328      }
17329      if (typeof previewStyles !== 'string') {
17330        previewStyles = 'font-family font-size font-weight font-style text-decoration ' + 'text-transform color background-color border border-radius outline text-shadow';
17331      }
17332      var removeVars = function (val) {
17333        return val.replace(/%(\w+)/g, '');
17334      };
17335      if (typeof format === 'string') {
17336        format = editor.formatter.get(format);
17337        if (!format) {
17338          return;
17339        }
17340        format = format[0];
17341      }
17342      if ('preview' in format) {
17343        previewStyles = format.preview;
17344        if (previewStyles === false) {
17345          return '';
17346        }
17347      }
17348      name = format.block || format.inline || 'span';
17349      items = parseSelector(format.selector);
17350      if (items.length) {
17351        if (!items[0].name) {
17352          items[0].name = name;
17353        }
17354        name = format.selector;
17355        previewFrag = parsedSelectorToHtml(items, editor);
17356      } else {
17357        previewFrag = parsedSelectorToHtml([name], editor);
17358      }
17359      previewElm = dom.select(name, previewFrag)[0] || previewFrag.firstChild;
17360      each$e(format.styles, function (value, name) {
17361        value = removeVars(value);
17362        if (value) {
17363          dom.setStyle(previewElm, name, value);
17364        }
17365      });
17366      each$e(format.attributes, function (value, name) {
17367        value = removeVars(value);
17368        if (value) {
17369          dom.setAttrib(previewElm, name, value);
17370        }
17371      });
17372      each$e(format.classes, function (value) {
17373        value = removeVars(value);
17374        if (!dom.hasClass(previewElm, value)) {
17375          dom.addClass(previewElm, value);
17376        }
17377      });
17378      editor.fire('PreviewFormats');
17379      dom.setStyles(previewFrag, {
17380        position: 'absolute',
17381        left: -65535
17382      });
17383      editor.getBody().appendChild(previewFrag);
17384      parentFontSize = dom.getStyle(editor.getBody(), 'fontSize', true);
17385      parentFontSize = /px$/.test(parentFontSize) ? parseInt(parentFontSize, 10) : 0;
17386      each$e(previewStyles.split(' '), function (name) {
17387        var value = dom.getStyle(previewElm, name, true);
17388        if (name === 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) {
17389          value = dom.getStyle(editor.getBody(), name, true);
17390          if (dom.toHex(value).toLowerCase() === '#ffffff') {
17391            return;
17392          }
17393        }
17394        if (name === 'color') {
17395          if (dom.toHex(value).toLowerCase() === '#000000') {
17396            return;
17397          }
17398        }
17399        if (name === 'font-size') {
17400          if (/em|%$/.test(value)) {
17401            if (parentFontSize === 0) {
17402              return;
17403            }
17404            var numValue = parseFloat(value) / (/%$/.test(value) ? 100 : 1);
17405            value = numValue * parentFontSize + 'px';
17406          }
17407        }
17408        if (name === 'border' && value) {
17409          previewCss += 'padding:0 2px;';
17410        }
17411        previewCss += name + ':' + value + ';';
17412      });
17413      editor.fire('AfterPreviewFormats');
17414      dom.remove(previewFrag);
17415      return previewCss;
17416    };
17417    var Preview = {
17418      getCssText: getCssText,
17419      parseSelector: parseSelector,
17420      selectorToHtml: selectorToHtml
17421    };
17422
17423    var toggle$1 = function (editor, formats, name, vars, node) {
17424      var fmt = formats.get(name);
17425      if (MatchFormat.match(editor, name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) {
17426        RemoveFormat.remove(editor, name, vars, node);
17427      } else {
17428        ApplyFormat.applyFormat(editor, name, vars, node);
17429      }
17430    };
17431    var ToggleFormat = { toggle: toggle$1 };
17432
17433    var setup$6 = function (editor) {
17434      editor.addShortcut('meta+b', '', 'Bold');
17435      editor.addShortcut('meta+i', '', 'Italic');
17436      editor.addShortcut('meta+u', '', 'Underline');
17437      for (var i = 1; i <= 6; i++) {
17438        editor.addShortcut('access+' + i, '', [
17439          'FormatBlock',
17440          false,
17441          'h' + i
17442        ]);
17443      }
17444      editor.addShortcut('access+7', '', [
17445        'FormatBlock',
17446        false,
17447        'p'
17448      ]);
17449      editor.addShortcut('access+8', '', [
17450        'FormatBlock',
17451        false,
17452        'div'
17453      ]);
17454      editor.addShortcut('access+9', '', [
17455        'FormatBlock',
17456        false,
17457        'address'
17458      ]);
17459    };
17460    var FormatShortcuts = { setup: setup$6 };
17461
17462    var Formatter = function (editor) {
17463      var formats = FormatRegistry(editor);
17464      var formatChangeState = Cell(null);
17465      FormatShortcuts.setup(editor);
17466      setup$4(editor);
17467      return {
17468        get: formats.get,
17469        has: formats.has,
17470        register: formats.register,
17471        unregister: formats.unregister,
17472        apply: curry(ApplyFormat.applyFormat, editor),
17473        remove: curry(RemoveFormat.remove, editor),
17474        toggle: curry(ToggleFormat.toggle, editor, formats),
17475        match: curry(MatchFormat.match, editor),
17476        matchAll: curry(MatchFormat.matchAll, editor),
17477        matchNode: curry(MatchFormat.matchNode, editor),
17478        canApply: curry(MatchFormat.canApply, editor),
17479        formatChanged: curry(formatChanged, editor, formatChangeState),
17480        getCssText: curry(Preview.getCssText, editor)
17481      };
17482    };
17483
17484    var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
17485    var shallow$1 = function (old, nu) {
17486      return nu;
17487    };
17488    var baseMerge = function (merger) {
17489      return function () {
17490        var objects = new Array(arguments.length);
17491        for (var i = 0; i < objects.length; i++)
17492          objects[i] = arguments[i];
17493        if (objects.length === 0)
17494          throw new Error('Can\'t merge zero objects');
17495        var ret = {};
17496        for (var j = 0; j < objects.length; j++) {
17497          var curObject = objects[j];
17498          for (var key in curObject)
17499            if (hasOwnProperty$2.call(curObject, key)) {
17500              ret[key] = merger(ret[key], curObject[key]);
17501            }
17502        }
17503        return ret;
17504      };
17505    };
17506    var merge = baseMerge(shallow$1);
17507
17508    var register = function (htmlParser, settings, dom) {
17509      htmlParser.addAttributeFilter('data-mce-tabindex', function (nodes, name) {
17510        var i = nodes.length, node;
17511        while (i--) {
17512          node = nodes[i];
17513          node.attr('tabindex', node.attr('data-mce-tabindex'));
17514          node.attr(name, null);
17515        }
17516      });
17517      htmlParser.addAttributeFilter('src,href,style', function (nodes, name) {
17518        var i = nodes.length, node, value;
17519        var internalName = 'data-mce-' + name;
17520        var urlConverter = settings.url_converter;
17521        var urlConverterScope = settings.url_converter_scope;
17522        while (i--) {
17523          node = nodes[i];
17524          value = node.attr(internalName);
17525          if (value !== undefined) {
17526            node.attr(name, value.length > 0 ? value : null);
17527            node.attr(internalName, null);
17528          } else {
17529            value = node.attr(name);
17530            if (name === 'style') {
17531              value = dom.serializeStyle(dom.parseStyle(value), node.name);
17532            } else if (urlConverter) {
17533              value = urlConverter.call(urlConverterScope, value, name, node.name);
17534            }
17535            node.attr(name, value.length > 0 ? value : null);
17536          }
17537        }
17538      });
17539      htmlParser.addAttributeFilter('class', function (nodes) {
17540        var i = nodes.length, node, value;
17541        while (i--) {
17542          node = nodes[i];
17543          value = node.attr('class');
17544          if (value) {
17545            value = node.attr('class').replace(/(?:^|\s)mce-item-\w+(?!\S)/g, '');
17546            node.attr('class', value.length > 0 ? value : null);
17547          }
17548        }
17549      });
17550      htmlParser.addAttributeFilter('data-mce-type', function (nodes, name, args) {
17551        var i = nodes.length, node;
17552        while (i--) {
17553          node = nodes[i];
17554          if (node.attr('data-mce-type') === 'bookmark' && !args.cleanup) {
17555            var hasChildren = Option.from(node.firstChild).exists(function (firstChild) {
17556              return !Zwsp.isZwsp(firstChild.value);
17557            });
17558            if (hasChildren) {
17559              node.unwrap();
17560            } else {
17561              node.remove();
17562            }
17563          }
17564        }
17565      });
17566      htmlParser.addNodeFilter('noscript', function (nodes) {
17567        var i = nodes.length, node;
17568        while (i--) {
17569          node = nodes[i].firstChild;
17570          if (node) {
17571            node.value = Entities.decode(node.value);
17572          }
17573        }
17574      });
17575      htmlParser.addNodeFilter('script,style', function (nodes, name) {
17576        var i = nodes.length, node, value, type;
17577        var trim = function (value) {
17578          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, '');
17579        };
17580        while (i--) {
17581          node = nodes[i];
17582          value = node.firstChild ? node.firstChild.value : '';
17583          if (name === 'script') {
17584            type = node.attr('type');
17585            if (type) {
17586              node.attr('type', type === 'mce-no/type' ? null : type.replace(/^mce\-/, ''));
17587            }
17588            if (settings.element_format === 'xhtml' && value.length > 0) {
17589              node.firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>';
17590            }
17591          } else {
17592            if (settings.element_format === 'xhtml' && value.length > 0) {
17593              node.firstChild.value = '<!--\n' + trim(value) + '\n-->';
17594            }
17595          }
17596        }
17597      });
17598      htmlParser.addNodeFilter('#comment', function (nodes) {
17599        var i = nodes.length, node;
17600        while (i--) {
17601          node = nodes[i];
17602          if (node.value.indexOf('[CDATA[') === 0) {
17603            node.name = '#cdata';
17604            node.type = 4;
17605            node.value = node.value.replace(/^\[CDATA\[|\]\]$/g, '');
17606          } else if (node.value.indexOf('mce:protected ') === 0) {
17607            node.name = '#text';
17608            node.type = 3;
17609            node.raw = true;
17610            node.value = unescape(node.value).substr(14);
17611          }
17612        }
17613      });
17614      htmlParser.addNodeFilter('xml:namespace,input', function (nodes, name) {
17615        var i = nodes.length, node;
17616        while (i--) {
17617          node = nodes[i];
17618          if (node.type === 7) {
17619            node.remove();
17620          } else if (node.type === 1) {
17621            if (name === 'input' && !node.attr('type')) {
17622              node.attr('type', 'text');
17623            }
17624          }
17625        }
17626      });
17627      htmlParser.addAttributeFilter('data-mce-type', function (nodes) {
17628        each(nodes, function (node) {
17629          if (node.attr('data-mce-type') === 'format-caret') {
17630            if (node.isEmpty(htmlParser.schema.getNonEmptyElements())) {
17631              node.remove();
17632            } else {
17633              node.unwrap();
17634            }
17635          }
17636        });
17637      });
17638      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) {
17639        var i = nodes.length;
17640        while (i--) {
17641          nodes[i].attr(name, null);
17642        }
17643      });
17644    };
17645    var trimTrailingBr = function (rootNode) {
17646      var brNode1, brNode2;
17647      var isBr = function (node) {
17648        return node && node.name === 'br';
17649      };
17650      brNode1 = rootNode.lastChild;
17651      if (isBr(brNode1)) {
17652        brNode2 = brNode1.prev;
17653        if (isBr(brNode2)) {
17654          brNode1.remove();
17655          brNode2.remove();
17656        }
17657      }
17658    };
17659    var DomSerializerFilters = {
17660      register: register,
17661      trimTrailingBr: trimTrailingBr
17662    };
17663
17664    var preProcess = function (editor, node, args) {
17665      var impl, doc, oldDoc;
17666      var dom = editor.dom;
17667      node = node.cloneNode(true);
17668      impl = domGlobals.document.implementation;
17669      if (impl.createHTMLDocument) {
17670        doc = impl.createHTMLDocument('');
17671        Tools.each(node.nodeName === 'BODY' ? node.childNodes : [node], function (node) {
17672          doc.body.appendChild(doc.importNode(node, true));
17673        });
17674        if (node.nodeName !== 'BODY') {
17675          node = doc.body.firstChild;
17676        } else {
17677          node = doc.body;
17678        }
17679        oldDoc = dom.doc;
17680        dom.doc = doc;
17681      }
17682      Events.firePreProcess(editor, merge(args, { node: node }));
17683      if (oldDoc) {
17684        dom.doc = oldDoc;
17685      }
17686      return node;
17687    };
17688    var shouldFireEvent = function (editor, args) {
17689      return editor && editor.hasEventListeners('PreProcess') && !args.no_events;
17690    };
17691    var process = function (editor, node, args) {
17692      return shouldFireEvent(editor, args) ? preProcess(editor, node, args) : node;
17693    };
17694    var DomSerializerPreProcess = { process: process };
17695
17696    var removeAttrs = function (node, names) {
17697      each(names, function (name) {
17698        node.attr(name, null);
17699      });
17700    };
17701    var addFontToSpansFilter = function (domParser, styles, fontSizes) {
17702      domParser.addNodeFilter('font', function (nodes) {
17703        each(nodes, function (node) {
17704          var props = styles.parse(node.attr('style'));
17705          var color = node.attr('color');
17706          var face = node.attr('face');
17707          var size = node.attr('size');
17708          if (color) {
17709            props.color = color;
17710          }
17711          if (face) {
17712            props['font-family'] = face;
17713          }
17714          if (size) {
17715            props['font-size'] = fontSizes[parseInt(node.attr('size'), 10) - 1];
17716          }
17717          node.name = 'span';
17718          node.attr('style', styles.serialize(props));
17719          removeAttrs(node, [
17720            'color',
17721            'face',
17722            'size'
17723          ]);
17724        });
17725      });
17726    };
17727    var addStrikeToSpanFilter = function (domParser, styles) {
17728      domParser.addNodeFilter('strike', function (nodes) {
17729        each(nodes, function (node) {
17730          var props = styles.parse(node.attr('style'));
17731          props['text-decoration'] = 'line-through';
17732          node.name = 'span';
17733          node.attr('style', styles.serialize(props));
17734        });
17735      });
17736    };
17737    var addFilters = function (domParser, settings) {
17738      var styles = Styles();
17739      if (settings.convert_fonts_to_spans) {
17740        addFontToSpansFilter(domParser, styles, Tools.explode(settings.font_size_legacy_values));
17741      }
17742      addStrikeToSpanFilter(domParser, styles);
17743    };
17744    var register$1 = function (domParser, settings) {
17745      if (settings.inline_styles) {
17746        addFilters(domParser, settings);
17747      }
17748    };
17749    var LegacyFilter = { register: register$1 };
17750
17751    var paddEmptyNode = function (settings, args, blockElements, node) {
17752      var brPreferred = settings.padd_empty_with_br || args.insert;
17753      if (brPreferred && blockElements[node.name]) {
17754        node.empty().append(new Node$1('br', 1)).shortEnded = true;
17755      } else {
17756        node.empty().append(new Node$1('#text', 3)).value = '\xA0';
17757      }
17758    };
17759    var isPaddedWithNbsp = function (node) {
17760      return hasOnlyChild(node, '#text') && node.firstChild.value === '\xA0';
17761    };
17762    var hasOnlyChild = function (node, name) {
17763      return node && node.firstChild && node.firstChild === node.lastChild && node.firstChild.name === name;
17764    };
17765    var isPadded = function (schema, node) {
17766      var rule = schema.getElementRule(node.name);
17767      return rule && rule.paddEmpty;
17768    };
17769    var isEmpty$2 = function (schema, nonEmptyElements, whitespaceElements, node) {
17770      return node.isEmpty(nonEmptyElements, whitespaceElements, function (node) {
17771        return isPadded(schema, node);
17772      });
17773    };
17774    var isLineBreakNode = function (node, blockElements) {
17775      return node && (blockElements[node.name] || node.name === 'br');
17776    };
17777
17778    var register$2 = function (parser, settings) {
17779      var schema = parser.schema;
17780      if (settings.remove_trailing_brs) {
17781        parser.addNodeFilter('br', function (nodes, _, args) {
17782          var i;
17783          var l = nodes.length;
17784          var node;
17785          var blockElements = Tools.extend({}, schema.getBlockElements());
17786          var nonEmptyElements = schema.getNonEmptyElements();
17787          var parent, lastParent, prev, prevName;
17788          var whiteSpaceElements = schema.getNonEmptyElements();
17789          var elementRule, textNode;
17790          blockElements.body = 1;
17791          for (i = 0; i < l; i++) {
17792            node = nodes[i];
17793            parent = node.parent;
17794            if (blockElements[node.parent.name] && node === parent.lastChild) {
17795              prev = node.prev;
17796              while (prev) {
17797                prevName = prev.name;
17798                if (prevName !== 'span' || prev.attr('data-mce-type') !== 'bookmark') {
17799                  if (prevName !== 'br') {
17800                    break;
17801                  }
17802                  if (prevName === 'br') {
17803                    node = null;
17804                    break;
17805                  }
17806                }
17807                prev = prev.prev;
17808              }
17809              if (node) {
17810                node.remove();
17811                if (isEmpty$2(schema, nonEmptyElements, whiteSpaceElements, parent)) {
17812                  elementRule = schema.getElementRule(parent.name);
17813                  if (elementRule) {
17814                    if (elementRule.removeEmpty) {
17815                      parent.remove();
17816                    } else if (elementRule.paddEmpty) {
17817                      paddEmptyNode(settings, args, blockElements, parent);
17818                    }
17819                  }
17820                }
17821              }
17822            } else {
17823              lastParent = node;
17824              while (parent && parent.firstChild === lastParent && parent.lastChild === lastParent) {
17825                lastParent = parent;
17826                if (blockElements[parent.name]) {
17827                  break;
17828                }
17829                parent = parent.parent;
17830              }
17831              if (lastParent === parent && settings.padd_empty_with_br !== true) {
17832                textNode = new Node$1('#text', 3);
17833                textNode.value = '\xA0';
17834                node.replace(textNode);
17835              }
17836            }
17837          }
17838        });
17839      }
17840      parser.addAttributeFilter('href', function (nodes) {
17841        var i = nodes.length, node;
17842        var appendRel = function (rel) {
17843          var parts = rel.split(' ').filter(function (p) {
17844            return p.length > 0;
17845          });
17846          return parts.concat(['noopener']).sort().join(' ');
17847        };
17848        var addNoOpener = function (rel) {
17849          var newRel = rel ? Tools.trim(rel) : '';
17850          if (!/\b(noopener)\b/g.test(newRel)) {
17851            return appendRel(newRel);
17852          } else {
17853            return newRel;
17854          }
17855        };
17856        if (!settings.allow_unsafe_link_target) {
17857          while (i--) {
17858            node = nodes[i];
17859            if (node.name === 'a' && node.attr('target') === '_blank') {
17860              node.attr('rel', addNoOpener(node.attr('rel')));
17861            }
17862          }
17863        }
17864      });
17865      if (!settings.allow_html_in_named_anchor) {
17866        parser.addAttributeFilter('id,name', function (nodes) {
17867          var i = nodes.length, sibling, prevSibling, parent, node;
17868          while (i--) {
17869            node = nodes[i];
17870            if (node.name === 'a' && node.firstChild && !node.attr('href')) {
17871              parent = node.parent;
17872              sibling = node.lastChild;
17873              do {
17874                prevSibling = sibling.prev;
17875                parent.insert(sibling, node);
17876                sibling = prevSibling;
17877              } while (sibling);
17878            }
17879          }
17880        });
17881      }
17882      if (settings.fix_list_elements) {
17883        parser.addNodeFilter('ul,ol', function (nodes) {
17884          var i = nodes.length, node, parentNode;
17885          while (i--) {
17886            node = nodes[i];
17887            parentNode = node.parent;
17888            if (parentNode.name === 'ul' || parentNode.name === 'ol') {
17889              if (node.prev && node.prev.name === 'li') {
17890                node.prev.append(node);
17891              } else {
17892                var li = new Node$1('li', 1);
17893                li.attr('style', 'list-style-type: none');
17894                node.wrap(li);
17895              }
17896            }
17897          }
17898        });
17899      }
17900      if (settings.validate && schema.getValidClasses()) {
17901        parser.addAttributeFilter('class', function (nodes) {
17902          var i = nodes.length, node, classList, ci, className, classValue;
17903          var validClasses = schema.getValidClasses();
17904          var validClassesMap, valid;
17905          while (i--) {
17906            node = nodes[i];
17907            classList = node.attr('class').split(' ');
17908            classValue = '';
17909            for (ci = 0; ci < classList.length; ci++) {
17910              className = classList[ci];
17911              valid = false;
17912              validClassesMap = validClasses['*'];
17913              if (validClassesMap && validClassesMap[className]) {
17914                valid = true;
17915              }
17916              validClassesMap = validClasses[node.name];
17917              if (!valid && validClassesMap && validClassesMap[className]) {
17918                valid = true;
17919              }
17920              if (valid) {
17921                if (classValue) {
17922                  classValue += ' ';
17923                }
17924                classValue += className;
17925              }
17926            }
17927            if (!classValue.length) {
17928              classValue = null;
17929            }
17930            node.attr('class', classValue);
17931          }
17932        });
17933      }
17934    };
17935
17936    var makeMap$4 = Tools.makeMap, each$f = Tools.each, explode$2 = Tools.explode, extend$2 = Tools.extend;
17937    var DomParser = function (settings, schema) {
17938      if (schema === void 0) {
17939        schema = Schema();
17940      }
17941      var nodeFilters = {};
17942      var attributeFilters = [];
17943      var matchedNodes = {};
17944      var matchedAttributes = {};
17945      settings = settings || {};
17946      settings.validate = 'validate' in settings ? settings.validate : true;
17947      settings.root_name = settings.root_name || 'body';
17948      var fixInvalidChildren = function (nodes) {
17949        var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i;
17950        var nonEmptyElements, whitespaceElements, nonSplitableElements, textBlockElements, specialElements, sibling, nextNode;
17951        nonSplitableElements = makeMap$4('tr,td,th,tbody,thead,tfoot,table');
17952        nonEmptyElements = schema.getNonEmptyElements();
17953        whitespaceElements = schema.getWhiteSpaceElements();
17954        textBlockElements = schema.getTextBlockElements();
17955        specialElements = schema.getSpecialElements();
17956        for (ni = 0; ni < nodes.length; ni++) {
17957          node = nodes[ni];
17958          if (!node.parent || node.fixed) {
17959            continue;
17960          }
17961          if (textBlockElements[node.name] && node.parent.name === 'li') {
17962            sibling = node.next;
17963            while (sibling) {
17964              if (textBlockElements[sibling.name]) {
17965                sibling.name = 'li';
17966                sibling.fixed = true;
17967                node.parent.insert(sibling, node.parent);
17968              } else {
17969                break;
17970              }
17971              sibling = sibling.next;
17972            }
17973            node.unwrap(node);
17974            continue;
17975          }
17976          parents = [node];
17977          for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && !nonSplitableElements[parent.name]; parent = parent.parent) {
17978            parents.push(parent);
17979          }
17980          if (parent && parents.length > 1) {
17981            parents.reverse();
17982            newParent = currentNode = filterNode(parents[0].clone());
17983            for (i = 0; i < parents.length - 1; i++) {
17984              if (schema.isValidChild(currentNode.name, parents[i].name)) {
17985                tempNode = filterNode(parents[i].clone());
17986                currentNode.append(tempNode);
17987              } else {
17988                tempNode = currentNode;
17989              }
17990              for (childNode = parents[i].firstChild; childNode && childNode !== parents[i + 1];) {
17991                nextNode = childNode.next;
17992                tempNode.append(childNode);
17993                childNode = nextNode;
17994              }
17995              currentNode = tempNode;
17996            }
17997            if (!isEmpty$2(schema, nonEmptyElements, whitespaceElements, newParent)) {
17998              parent.insert(newParent, parents[0], true);
17999              parent.insert(node, newParent);
18000            } else {
18001              parent.insert(node, parents[0], true);
18002            }
18003            parent = parents[0];
18004            if (isEmpty$2(schema, nonEmptyElements, whitespaceElements, parent) || hasOnlyChild(parent, 'br')) {
18005              parent.empty().remove();
18006            }
18007          } else if (node.parent) {
18008            if (node.name === 'li') {
18009              sibling = node.prev;
18010              if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) {
18011                sibling.append(node);
18012                continue;
18013              }
18014              sibling = node.next;
18015              if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) {
18016                sibling.insert(node, sibling.firstChild, true);
18017                continue;
18018              }
18019              node.wrap(filterNode(new Node$1('ul', 1)));
18020              continue;
18021            }
18022            if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) {
18023              node.wrap(filterNode(new Node$1('div', 1)));
18024            } else {
18025              if (specialElements[node.name]) {
18026                node.empty().remove();
18027              } else {
18028                node.unwrap();
18029              }
18030            }
18031          }
18032        }
18033      };
18034      var filterNode = function (node) {
18035        var i, name, list;
18036        name = node.name;
18037        if (name in nodeFilters) {
18038          list = matchedNodes[name];
18039          if (list) {
18040            list.push(node);
18041          } else {
18042            matchedNodes[name] = [node];
18043          }
18044        }
18045        i = attributeFilters.length;
18046        while (i--) {
18047          name = attributeFilters[i].name;
18048          if (name in node.attributes.map) {
18049            list = matchedAttributes[name];
18050            if (list) {
18051              list.push(node);
18052            } else {
18053              matchedAttributes[name] = [node];
18054            }
18055          }
18056        }
18057        return node;
18058      };
18059      var addNodeFilter = function (name, callback) {
18060        each$f(explode$2(name), function (name) {
18061          var list = nodeFilters[name];
18062          if (!list) {
18063            nodeFilters[name] = list = [];
18064          }
18065          list.push(callback);
18066        });
18067      };
18068      var getNodeFilters = function () {
18069        var out = [];
18070        for (var name in nodeFilters) {
18071          if (nodeFilters.hasOwnProperty(name)) {
18072            out.push({
18073              name: name,
18074              callbacks: nodeFilters[name]
18075            });
18076          }
18077        }
18078        return out;
18079      };
18080      var addAttributeFilter = function (name, callback) {
18081        each$f(explode$2(name), function (name) {
18082          var i;
18083          for (i = 0; i < attributeFilters.length; i++) {
18084            if (attributeFilters[i].name === name) {
18085              attributeFilters[i].callbacks.push(callback);
18086              return;
18087            }
18088          }
18089          attributeFilters.push({
18090            name: name,
18091            callbacks: [callback]
18092          });
18093        });
18094      };
18095      var getAttributeFilters = function () {
18096        return [].concat(attributeFilters);
18097      };
18098      var parse = function (html, args) {
18099        var parser, nodes, i, l, fi, fl, list, name;
18100        var blockElements;
18101        var invalidChildren = [];
18102        var isInWhiteSpacePreservedElement;
18103        var node;
18104        var getRootBlockName = function (name) {
18105          if (name === false) {
18106            return '';
18107          } else if (name === true) {
18108            return 'p';
18109          } else {
18110            return name;
18111          }
18112        };
18113        args = args || {};
18114        matchedNodes = {};
18115        matchedAttributes = {};
18116        blockElements = extend$2(makeMap$4('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
18117        var nonEmptyElements = schema.getNonEmptyElements();
18118        var children = schema.children;
18119        var validate = settings.validate;
18120        var forcedRootBlockName = 'forced_root_block' in args ? args.forced_root_block : settings.forced_root_block;
18121        var rootBlockName = getRootBlockName(forcedRootBlockName);
18122        var whiteSpaceElements = schema.getWhiteSpaceElements();
18123        var startWhiteSpaceRegExp = /^[ \t\r\n]+/;
18124        var endWhiteSpaceRegExp = /[ \t\r\n]+$/;
18125        var allWhiteSpaceRegExp = /[ \t\r\n]+/g;
18126        var isAllWhiteSpaceRegExp = /^[ \t\r\n]+$/;
18127        isInWhiteSpacePreservedElement = whiteSpaceElements.hasOwnProperty(args.context) || whiteSpaceElements.hasOwnProperty(settings.root_name);
18128        var addRootBlocks = function () {
18129          var node = rootNode.firstChild, next, rootBlockNode;
18130          var trim = function (rootBlockNode) {
18131            if (rootBlockNode) {
18132              node = rootBlockNode.firstChild;
18133              if (node && node.type === 3) {
18134                node.value = node.value.replace(startWhiteSpaceRegExp, '');
18135              }
18136              node = rootBlockNode.lastChild;
18137              if (node && node.type === 3) {
18138                node.value = node.value.replace(endWhiteSpaceRegExp, '');
18139              }
18140            }
18141          };
18142          if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) {
18143            return;
18144          }
18145          while (node) {
18146            next = node.next;
18147            if (node.type === 3 || node.type === 1 && node.name !== 'p' && !blockElements[node.name] && !node.attr('data-mce-type')) {
18148              if (!rootBlockNode) {
18149                rootBlockNode = createNode(rootBlockName, 1);
18150                rootBlockNode.attr(settings.forced_root_block_attrs);
18151                rootNode.insert(rootBlockNode, node);
18152                rootBlockNode.append(node);
18153              } else {
18154                rootBlockNode.append(node);
18155              }
18156            } else {
18157              trim(rootBlockNode);
18158              rootBlockNode = null;
18159            }
18160            node = next;
18161          }
18162          trim(rootBlockNode);
18163        };
18164        var createNode = function (name, type) {
18165          var node = new Node$1(name, type);
18166          var list;
18167          if (name in nodeFilters) {
18168            list = matchedNodes[name];
18169            if (list) {
18170              list.push(node);
18171            } else {
18172              matchedNodes[name] = [node];
18173            }
18174          }
18175          return node;
18176        };
18177        var removeWhitespaceBefore = function (node) {
18178          var textNode, textNodeNext, textVal, sibling;
18179          var blockElements = schema.getBlockElements();
18180          for (textNode = node.prev; textNode && textNode.type === 3;) {
18181            textVal = textNode.value.replace(endWhiteSpaceRegExp, '');
18182            if (textVal.length > 0) {
18183              textNode.value = textVal;
18184              return;
18185            }
18186            textNodeNext = textNode.next;
18187            if (textNodeNext) {
18188              if (textNodeNext.type === 3 && textNodeNext.value.length) {
18189                textNode = textNode.prev;
18190                continue;
18191              }
18192              if (!blockElements[textNodeNext.name] && textNodeNext.name !== 'script' && textNodeNext.name !== 'style') {
18193                textNode = textNode.prev;
18194                continue;
18195              }
18196            }
18197            sibling = textNode.prev;
18198            textNode.remove();
18199            textNode = sibling;
18200          }
18201        };
18202        var cloneAndExcludeBlocks = function (input) {
18203          var name;
18204          var output = {};
18205          for (name in input) {
18206            if (name !== 'li' && name !== 'p') {
18207              output[name] = input[name];
18208            }
18209          }
18210          return output;
18211        };
18212        parser = SaxParser$1({
18213          validate: validate,
18214          allow_script_urls: settings.allow_script_urls,
18215          allow_conditional_comments: settings.allow_conditional_comments,
18216          self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()),
18217          cdata: function (text) {
18218            node.append(createNode('#cdata', 4)).value = text;
18219          },
18220          text: function (text, raw) {
18221            var textNode;
18222            if (!isInWhiteSpacePreservedElement) {
18223              text = text.replace(allWhiteSpaceRegExp, ' ');
18224              if (isLineBreakNode(node.lastChild, blockElements)) {
18225                text = text.replace(startWhiteSpaceRegExp, '');
18226              }
18227            }
18228            if (text.length !== 0) {
18229              textNode = createNode('#text', 3);
18230              textNode.raw = !!raw;
18231              node.append(textNode).value = text;
18232            }
18233          },
18234          comment: function (text) {
18235            node.append(createNode('#comment', 8)).value = text;
18236          },
18237          pi: function (name, text) {
18238            node.append(createNode(name, 7)).value = text;
18239            removeWhitespaceBefore(node);
18240          },
18241          doctype: function (text) {
18242            var newNode;
18243            newNode = node.append(createNode('#doctype', 10));
18244            newNode.value = text;
18245            removeWhitespaceBefore(node);
18246          },
18247          start: function (name, attrs, empty) {
18248            var newNode, attrFiltersLen, elementRule, attrName, parent;
18249            elementRule = validate ? schema.getElementRule(name) : {};
18250            if (elementRule) {
18251              newNode = createNode(elementRule.outputName || name, 1);
18252              newNode.attributes = attrs;
18253              newNode.shortEnded = empty;
18254              node.append(newNode);
18255              parent = children[node.name];
18256              if (parent && children[newNode.name] && !parent[newNode.name]) {
18257                invalidChildren.push(newNode);
18258              }
18259              attrFiltersLen = attributeFilters.length;
18260              while (attrFiltersLen--) {
18261                attrName = attributeFilters[attrFiltersLen].name;
18262                if (attrName in attrs.map) {
18263                  list = matchedAttributes[attrName];
18264                  if (list) {
18265                    list.push(newNode);
18266                  } else {
18267                    matchedAttributes[attrName] = [newNode];
18268                  }
18269                }
18270              }
18271              if (blockElements[name]) {
18272                removeWhitespaceBefore(newNode);
18273              }
18274              if (!empty) {
18275                node = newNode;
18276              }
18277              if (!isInWhiteSpacePreservedElement && whiteSpaceElements[name]) {
18278                isInWhiteSpacePreservedElement = true;
18279              }
18280            }
18281          },
18282          end: function (name) {
18283            var textNode, elementRule, text, sibling, tempNode;
18284            elementRule = validate ? schema.getElementRule(name) : {};
18285            if (elementRule) {
18286              if (blockElements[name]) {
18287                if (!isInWhiteSpacePreservedElement) {
18288                  textNode = node.firstChild;
18289                  if (textNode && textNode.type === 3) {
18290                    text = textNode.value.replace(startWhiteSpaceRegExp, '');
18291                    if (text.length > 0) {
18292                      textNode.value = text;
18293                      textNode = textNode.next;
18294                    } else {
18295                      sibling = textNode.next;
18296                      textNode.remove();
18297                      textNode = sibling;
18298                      while (textNode && textNode.type === 3) {
18299                        text = textNode.value;
18300                        sibling = textNode.next;
18301                        if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
18302                          textNode.remove();
18303                          textNode = sibling;
18304                        }
18305                        textNode = sibling;
18306                      }
18307                    }
18308                  }
18309                  textNode = node.lastChild;
18310                  if (textNode && textNode.type === 3) {
18311                    text = textNode.value.replace(endWhiteSpaceRegExp, '');
18312                    if (text.length > 0) {
18313                      textNode.value = text;
18314                      textNode = textNode.prev;
18315                    } else {
18316                      sibling = textNode.prev;
18317                      textNode.remove();
18318                      textNode = sibling;
18319                      while (textNode && textNode.type === 3) {
18320                        text = textNode.value;
18321                        sibling = textNode.prev;
18322                        if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
18323                          textNode.remove();
18324                          textNode = sibling;
18325                        }
18326                        textNode = sibling;
18327                      }
18328                    }
18329                  }
18330                }
18331              }
18332              if (isInWhiteSpacePreservedElement && whiteSpaceElements[name]) {
18333                isInWhiteSpacePreservedElement = false;
18334              }
18335              if (elementRule.removeEmpty && isEmpty$2(schema, nonEmptyElements, whiteSpaceElements, node)) {
18336                if (!node.attr('name') && !node.attr('id')) {
18337                  tempNode = node.parent;
18338                  if (blockElements[node.name]) {
18339                    node.empty().remove();
18340                  } else {
18341                    node.unwrap();
18342                  }
18343                  node = tempNode;
18344                  return;
18345                }
18346              }
18347              if (elementRule.paddEmpty && (isPaddedWithNbsp(node) || isEmpty$2(schema, nonEmptyElements, whiteSpaceElements, node))) {
18348                paddEmptyNode(settings, args, blockElements, node);
18349              }
18350              node = node.parent;
18351            }
18352          }
18353        }, schema);
18354        var rootNode = node = new Node$1(args.context || settings.root_name, 11);
18355        parser.parse(html);
18356        if (validate && invalidChildren.length) {
18357          if (!args.context) {
18358            fixInvalidChildren(invalidChildren);
18359          } else {
18360            args.invalid = true;
18361          }
18362        }
18363        if (rootBlockName && (rootNode.name === 'body' || args.isRootContent)) {
18364          addRootBlocks();
18365        }
18366        if (!args.invalid) {
18367          for (name in matchedNodes) {
18368            if (!matchedNodes.hasOwnProperty(name)) {
18369              continue;
18370            }
18371            list = nodeFilters[name];
18372            nodes = matchedNodes[name];
18373            fi = nodes.length;
18374            while (fi--) {
18375              if (!nodes[fi].parent) {
18376                nodes.splice(fi, 1);
18377              }
18378            }
18379            for (i = 0, l = list.length; i < l; i++) {
18380              list[i](nodes, name, args);
18381            }
18382          }
18383          for (i = 0, l = attributeFilters.length; i < l; i++) {
18384            list = attributeFilters[i];
18385            if (list.name in matchedAttributes) {
18386              nodes = matchedAttributes[list.name];
18387              fi = nodes.length;
18388              while (fi--) {
18389                if (!nodes[fi].parent) {
18390                  nodes.splice(fi, 1);
18391                }
18392              }
18393              for (fi = 0, fl = list.callbacks.length; fi < fl; fi++) {
18394                list.callbacks[fi](nodes, list.name, args);
18395              }
18396            }
18397          }
18398        }
18399        return rootNode;
18400      };
18401      var exports = {
18402        schema: schema,
18403        addAttributeFilter: addAttributeFilter,
18404        getAttributeFilters: getAttributeFilters,
18405        addNodeFilter: addNodeFilter,
18406        getNodeFilters: getNodeFilters,
18407        filterNode: filterNode,
18408        parse: parse
18409      };
18410      register$2(exports, settings);
18411      LegacyFilter.register(exports, settings);
18412      return exports;
18413    };
18414
18415    var addTempAttr = function (htmlParser, tempAttrs, name) {
18416      if (Tools.inArray(tempAttrs, name) === -1) {
18417        htmlParser.addAttributeFilter(name, function (nodes, name) {
18418          var i = nodes.length;
18419          while (i--) {
18420            nodes[i].attr(name, null);
18421          }
18422        });
18423        tempAttrs.push(name);
18424      }
18425    };
18426    var postProcess$1 = function (editor, args, content) {
18427      if (!args.no_events && editor) {
18428        var outArgs = Events.firePostProcess(editor, merge(args, { content: content }));
18429        return outArgs.content;
18430      } else {
18431        return content;
18432      }
18433    };
18434    var getHtmlFromNode = function (dom, node, args) {
18435      var html = Zwsp.trim(args.getInner ? node.innerHTML : dom.getOuterHTML(node));
18436      return args.selection || isWsPreserveElement(Element.fromDom(node)) ? html : Tools.trim(html);
18437    };
18438    var parseHtml = function (htmlParser, html, args) {
18439      var parserArgs = args.selection ? merge({ forced_root_block: false }, args) : args;
18440      var rootNode = htmlParser.parse(html, parserArgs);
18441      DomSerializerFilters.trimTrailingBr(rootNode);
18442      return rootNode;
18443    };
18444    var serializeNode = function (settings, schema, node) {
18445      var htmlSerializer = Serializer(settings, schema);
18446      return htmlSerializer.serialize(node);
18447    };
18448    var toHtml = function (editor, settings, schema, rootNode, args) {
18449      var content = serializeNode(settings, schema, rootNode);
18450      return postProcess$1(editor, args, content);
18451    };
18452    var DomSerializer = function (settings, editor) {
18453      var dom, schema, htmlParser;
18454      var tempAttrs = ['data-mce-selected'];
18455      dom = editor && editor.dom ? editor.dom : DOMUtils$1.DOM;
18456      schema = editor && editor.schema ? editor.schema : Schema(settings);
18457      settings.entity_encoding = settings.entity_encoding || 'named';
18458      settings.remove_trailing_brs = 'remove_trailing_brs' in settings ? settings.remove_trailing_brs : true;
18459      htmlParser = DomParser(settings, schema);
18460      DomSerializerFilters.register(htmlParser, settings, dom);
18461      var serialize = function (node, parserArgs) {
18462        var args = merge({ format: 'html' }, parserArgs ? parserArgs : {});
18463        var targetNode = DomSerializerPreProcess.process(editor, node, args);
18464        var html = getHtmlFromNode(dom, targetNode, args);
18465        var rootNode = parseHtml(htmlParser, html, args);
18466        return args.format === 'tree' ? rootNode : toHtml(editor, settings, schema, rootNode, args);
18467      };
18468      return {
18469        schema: schema,
18470        addNodeFilter: htmlParser.addNodeFilter,
18471        addAttributeFilter: htmlParser.addAttributeFilter,
18472        serialize: serialize,
18473        addRules: function (rules) {
18474          schema.addValidElements(rules);
18475        },
18476        setRules: function (rules) {
18477          schema.setValidElements(rules);
18478        },
18479        addTempAttr: curry(addTempAttr, htmlParser, tempAttrs),
18480        getTempAttrs: function () {
18481          return tempAttrs;
18482        }
18483      };
18484    };
18485
18486    var Serializer$1 = function (settings, editor) {
18487      var domSerializer = DomSerializer(settings, editor);
18488      return {
18489        schema: domSerializer.schema,
18490        addNodeFilter: domSerializer.addNodeFilter,
18491        addAttributeFilter: domSerializer.addAttributeFilter,
18492        serialize: domSerializer.serialize,
18493        addRules: domSerializer.addRules,
18494        setRules: domSerializer.setRules,
18495        addTempAttr: domSerializer.addTempAttr,
18496        getTempAttrs: domSerializer.getTempAttrs
18497      };
18498    };
18499
18500    function BookmarkManager(selection) {
18501      return {
18502        getBookmark: curry(Bookmarks.getBookmark, selection),
18503        moveToBookmark: curry(Bookmarks.moveToBookmark, selection)
18504      };
18505    }
18506    (function (BookmarkManager) {
18507      BookmarkManager.isBookmarkNode = Bookmarks.isBookmarkNode;
18508    }(BookmarkManager || (BookmarkManager = {})));
18509    var BookmarkManager$1 = BookmarkManager;
18510
18511    var isContentEditableFalse$a = NodeType.isContentEditableFalse;
18512    var isContentEditableTrue$5 = NodeType.isContentEditableTrue;
18513    var getContentEditableRoot$1 = function (root, node) {
18514      while (node && node !== root) {
18515        if (isContentEditableTrue$5(node) || isContentEditableFalse$a(node)) {
18516          return node;
18517        }
18518        node = node.parentNode;
18519      }
18520      return null;
18521    };
18522    var ControlSelection = function (selection, editor) {
18523      var dom = editor.dom, each = Tools.each;
18524      var selectedElm, selectedElmGhost, resizeHelper, resizeHandles, selectedHandle;
18525      var startX, startY, selectedElmX, selectedElmY, startW, startH, ratio, resizeStarted;
18526      var width, height;
18527      var editableDoc = editor.getDoc(), rootDocument = domGlobals.document;
18528      var abs = Math.abs, round = Math.round, rootElement = editor.getBody();
18529      var startScrollWidth, startScrollHeight;
18530      resizeHandles = {
18531        nw: [
18532          0,
18533          0,
18534          -1,
18535          -1
18536        ],
18537        ne: [
18538          1,
18539          0,
18540          1,
18541          -1
18542        ],
18543        se: [
18544          1,
18545          1,
18546          1,
18547          1
18548        ],
18549        sw: [
18550          0,
18551          1,
18552          -1,
18553          1
18554        ]
18555      };
18556      var isImage = function (elm) {
18557        return elm && (elm.nodeName === 'IMG' || editor.dom.is(elm, 'figure.image'));
18558      };
18559      var isEventOnImageOutsideRange = function (evt, range) {
18560        return isImage(evt.target) && !RangePoint.isXYWithinRange(evt.clientX, evt.clientY, range);
18561      };
18562      var contextMenuSelectImage = function (evt) {
18563        var target = evt.target;
18564        if (isEventOnImageOutsideRange(evt, editor.selection.getRng()) && !evt.isDefaultPrevented()) {
18565          evt.preventDefault();
18566          editor.selection.select(target);
18567        }
18568      };
18569      var getResizeTarget = function (elm) {
18570        return editor.dom.is(elm, 'figure.image') ? elm.querySelector('img') : elm;
18571      };
18572      var isResizable = function (elm) {
18573        var selector = editor.settings.object_resizing;
18574        if (selector === false || Env.iOS) {
18575          return false;
18576        }
18577        if (typeof selector !== 'string') {
18578          selector = 'table,img,figure.image,div';
18579        }
18580        if (elm.getAttribute('data-mce-resize') === 'false') {
18581          return false;
18582        }
18583        if (elm === editor.getBody()) {
18584          return false;
18585        }
18586        return is$1(Element.fromDom(elm), selector);
18587      };
18588      var resizeGhostElement = function (e) {
18589        var deltaX, deltaY, proportional;
18590        var resizeHelperX, resizeHelperY;
18591        deltaX = e.screenX - startX;
18592        deltaY = e.screenY - startY;
18593        width = deltaX * selectedHandle[2] + startW;
18594        height = deltaY * selectedHandle[3] + startH;
18595        width = width < 5 ? 5 : width;
18596        height = height < 5 ? 5 : height;
18597        if (isImage(selectedElm) && editor.settings.resize_img_proportional !== false) {
18598          proportional = !VK.modifierPressed(e);
18599        } else {
18600          proportional = VK.modifierPressed(e) || isImage(selectedElm) && selectedHandle[2] * selectedHandle[3] !== 0;
18601        }
18602        if (proportional) {
18603          if (abs(deltaX) > abs(deltaY)) {
18604            height = round(width * ratio);
18605            width = round(height / ratio);
18606          } else {
18607            width = round(height / ratio);
18608            height = round(width * ratio);
18609          }
18610        }
18611        dom.setStyles(getResizeTarget(selectedElmGhost), {
18612          width: width,
18613          height: height
18614        });
18615        resizeHelperX = selectedHandle.startPos.x + deltaX;
18616        resizeHelperY = selectedHandle.startPos.y + deltaY;
18617        resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
18618        resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
18619        dom.setStyles(resizeHelper, {
18620          left: resizeHelperX,
18621          top: resizeHelperY,
18622          display: 'block'
18623        });
18624        resizeHelper.innerHTML = width + ' &times; ' + height;
18625        if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
18626          dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
18627        }
18628        if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
18629          dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
18630        }
18631        deltaX = rootElement.scrollWidth - startScrollWidth;
18632        deltaY = rootElement.scrollHeight - startScrollHeight;
18633        if (deltaX + deltaY !== 0) {
18634          dom.setStyles(resizeHelper, {
18635            left: resizeHelperX - deltaX,
18636            top: resizeHelperY - deltaY
18637          });
18638        }
18639        if (!resizeStarted) {
18640          Events.fireObjectResizeStart(editor, selectedElm, startW, startH);
18641          resizeStarted = true;
18642        }
18643      };
18644      var endGhostResize = function () {
18645        resizeStarted = false;
18646        var setSizeProp = function (name, value) {
18647          if (value) {
18648            if (selectedElm.style[name] || !editor.schema.isValid(selectedElm.nodeName.toLowerCase(), name)) {
18649              dom.setStyle(getResizeTarget(selectedElm), name, value);
18650            } else {
18651              dom.setAttrib(getResizeTarget(selectedElm), name, value);
18652            }
18653          }
18654        };
18655        setSizeProp('width', width);
18656        setSizeProp('height', height);
18657        dom.unbind(editableDoc, 'mousemove', resizeGhostElement);
18658        dom.unbind(editableDoc, 'mouseup', endGhostResize);
18659        if (rootDocument !== editableDoc) {
18660          dom.unbind(rootDocument, 'mousemove', resizeGhostElement);
18661          dom.unbind(rootDocument, 'mouseup', endGhostResize);
18662        }
18663        dom.remove(selectedElmGhost);
18664        dom.remove(resizeHelper);
18665        showResizeRect(selectedElm);
18666        Events.fireObjectResized(editor, selectedElm, width, height);
18667        dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
18668        editor.nodeChanged();
18669      };
18670      var showResizeRect = function (targetElm) {
18671        var position, targetWidth, targetHeight, e, rect;
18672        hideResizeRect();
18673        unbindResizeHandleEvents();
18674        position = dom.getPos(targetElm, rootElement);
18675        selectedElmX = position.x;
18676        selectedElmY = position.y;
18677        rect = targetElm.getBoundingClientRect();
18678        targetWidth = rect.width || rect.right - rect.left;
18679        targetHeight = rect.height || rect.bottom - rect.top;
18680        if (selectedElm !== targetElm) {
18681          selectedElm = targetElm;
18682          width = height = 0;
18683        }
18684        e = editor.fire('ObjectSelected', { target: targetElm });
18685        if (isResizable(targetElm) && !e.isDefaultPrevented()) {
18686          each(resizeHandles, function (handle, name) {
18687            var handleElm;
18688            var startDrag = function (e) {
18689              startX = e.screenX;
18690              startY = e.screenY;
18691              startW = getResizeTarget(selectedElm).clientWidth;
18692              startH = getResizeTarget(selectedElm).clientHeight;
18693              ratio = startH / startW;
18694              selectedHandle = handle;
18695              handle.startPos = {
18696                x: targetWidth * handle[0] + selectedElmX,
18697                y: targetHeight * handle[1] + selectedElmY
18698              };
18699              startScrollWidth = rootElement.scrollWidth;
18700              startScrollHeight = rootElement.scrollHeight;
18701              selectedElmGhost = selectedElm.cloneNode(true);
18702              dom.addClass(selectedElmGhost, 'mce-clonedresizable');
18703              dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all');
18704              selectedElmGhost.contentEditable = false;
18705              selectedElmGhost.unSelectabe = true;
18706              dom.setStyles(selectedElmGhost, {
18707                left: selectedElmX,
18708                top: selectedElmY,
18709                margin: 0
18710              });
18711              selectedElmGhost.removeAttribute('data-mce-selected');
18712              rootElement.appendChild(selectedElmGhost);
18713              dom.bind(editableDoc, 'mousemove', resizeGhostElement);
18714              dom.bind(editableDoc, 'mouseup', endGhostResize);
18715              if (rootDocument !== editableDoc) {
18716                dom.bind(rootDocument, 'mousemove', resizeGhostElement);
18717                dom.bind(rootDocument, 'mouseup', endGhostResize);
18718              }
18719              resizeHelper = dom.add(rootElement, 'div', {
18720                'class': 'mce-resize-helper',
18721                'data-mce-bogus': 'all'
18722              }, startW + ' &times; ' + startH);
18723            };
18724            handleElm = dom.get('mceResizeHandle' + name);
18725            if (handleElm) {
18726              dom.remove(handleElm);
18727            }
18728            handleElm = dom.add(rootElement, 'div', {
18729              'id': 'mceResizeHandle' + name,
18730              'data-mce-bogus': 'all',
18731              'class': 'mce-resizehandle',
18732              'unselectable': true,
18733              'style': 'cursor:' + name + '-resize; margin:0; padding:0'
18734            });
18735            if (Env.ie === 11) {
18736              handleElm.contentEditable = false;
18737            }
18738            dom.bind(handleElm, 'mousedown', function (e) {
18739              e.stopImmediatePropagation();
18740              e.preventDefault();
18741              startDrag(e);
18742            });
18743            handle.elm = handleElm;
18744            dom.setStyles(handleElm, {
18745              left: targetWidth * handle[0] + selectedElmX - handleElm.offsetWidth / 2,
18746              top: targetHeight * handle[1] + selectedElmY - handleElm.offsetHeight / 2
18747            });
18748          });
18749        } else {
18750          hideResizeRect();
18751        }
18752        selectedElm.setAttribute('data-mce-selected', '1');
18753      };
18754      var hideResizeRect = function () {
18755        var name, handleElm;
18756        unbindResizeHandleEvents();
18757        if (selectedElm) {
18758          selectedElm.removeAttribute('data-mce-selected');
18759        }
18760        for (name in resizeHandles) {
18761          handleElm = dom.get('mceResizeHandle' + name);
18762          if (handleElm) {
18763            dom.unbind(handleElm);
18764            dom.remove(handleElm);
18765          }
18766        }
18767      };
18768      var updateResizeRect = function (e) {
18769        var startElm, controlElm;
18770        var isChildOrEqual = function (node, parent) {
18771          if (node) {
18772            do {
18773              if (node === parent) {
18774                return true;
18775              }
18776            } while (node = node.parentNode);
18777          }
18778        };
18779        if (resizeStarted || editor.removed) {
18780          return;
18781        }
18782        each(dom.select('img[data-mce-selected],hr[data-mce-selected]'), function (img) {
18783          img.removeAttribute('data-mce-selected');
18784        });
18785        controlElm = e.type === 'mousedown' ? e.target : selection.getNode();
18786        controlElm = dom.$(controlElm).closest('table,img,figure.image,hr')[0];
18787        if (isChildOrEqual(controlElm, rootElement)) {
18788          disableGeckoResize();
18789          startElm = selection.getStart(true);
18790          if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
18791            showResizeRect(controlElm);
18792            return;
18793          }
18794        }
18795        hideResizeRect();
18796      };
18797      var isWithinContentEditableFalse = function (elm) {
18798        return isContentEditableFalse$a(getContentEditableRoot$1(editor.getBody(), elm));
18799      };
18800      var unbindResizeHandleEvents = function () {
18801        for (var name in resizeHandles) {
18802          var handle = resizeHandles[name];
18803          if (handle.elm) {
18804            dom.unbind(handle.elm);
18805            delete handle.elm;
18806          }
18807        }
18808      };
18809      var disableGeckoResize = function () {
18810        try {
18811          editor.getDoc().execCommand('enableObjectResizing', false, false);
18812        } catch (ex) {
18813        }
18814      };
18815      editor.on('init', function () {
18816        disableGeckoResize();
18817        if (Env.ie && Env.ie >= 11) {
18818          editor.on('mousedown click', function (e) {
18819            var target = e.target, nodeName = target.nodeName;
18820            if (!resizeStarted && /^(TABLE|IMG|HR)$/.test(nodeName) && !isWithinContentEditableFalse(target)) {
18821              if (e.button !== 2) {
18822                editor.selection.select(target, nodeName === 'TABLE');
18823              }
18824              if (e.type === 'mousedown') {
18825                editor.nodeChanged();
18826              }
18827            }
18828          });
18829          editor.dom.bind(rootElement, 'mscontrolselect', function (e) {
18830            var delayedSelect = function (node) {
18831              Delay.setEditorTimeout(editor, function () {
18832                editor.selection.select(node);
18833              });
18834            };
18835            if (isWithinContentEditableFalse(e.target)) {
18836              e.preventDefault();
18837              delayedSelect(e.target);
18838              return;
18839            }
18840            if (/^(TABLE|IMG|HR)$/.test(e.target.nodeName)) {
18841              e.preventDefault();
18842              if (e.target.tagName === 'IMG') {
18843                delayedSelect(e.target);
18844              }
18845            }
18846          });
18847        }
18848        var throttledUpdateResizeRect = Delay.throttle(function (e) {
18849          if (!editor.composing) {
18850            updateResizeRect(e);
18851          }
18852        });
18853        editor.on('nodechange ResizeEditor ResizeWindow drop FullscreenStateChanged', throttledUpdateResizeRect);
18854        editor.on('keyup compositionend', function (e) {
18855          if (selectedElm && selectedElm.nodeName === 'TABLE') {
18856            throttledUpdateResizeRect(e);
18857          }
18858        });
18859        editor.on('hide blur', hideResizeRect);
18860        editor.on('contextmenu', contextMenuSelectImage);
18861      });
18862      editor.on('remove', unbindResizeHandleEvents);
18863      var destroy = function () {
18864        selectedElm = selectedElmGhost = null;
18865      };
18866      return {
18867        isResizable: isResizable,
18868        showResizeRect: showResizeRect,
18869        hideResizeRect: hideResizeRect,
18870        updateResizeRect: updateResizeRect,
18871        destroy: destroy
18872      };
18873    };
18874
18875    var getPos$1 = function (elm) {
18876      var x = 0, y = 0;
18877      var offsetParent = elm;
18878      while (offsetParent && offsetParent.nodeType) {
18879        x += offsetParent.offsetLeft || 0;
18880        y += offsetParent.offsetTop || 0;
18881        offsetParent = offsetParent.offsetParent;
18882      }
18883      return {
18884        x: x,
18885        y: y
18886      };
18887    };
18888    var fireScrollIntoViewEvent = function (editor, elm, alignToTop) {
18889      var scrollEvent = {
18890        elm: elm,
18891        alignToTop: alignToTop
18892      };
18893      editor.fire('ScrollIntoView', scrollEvent);
18894      return scrollEvent.isDefaultPrevented();
18895    };
18896    var scrollElementIntoView = function (editor, elm, alignToTop) {
18897      var y, viewPort;
18898      var dom = editor.dom;
18899      var root = dom.getRoot();
18900      var viewPortY, viewPortH, offsetY = 0;
18901      if (fireScrollIntoViewEvent(editor, elm, alignToTop)) {
18902        return;
18903      }
18904      if (!NodeType.isElement(elm)) {
18905        return;
18906      }
18907      if (alignToTop === false) {
18908        offsetY = elm.offsetHeight;
18909      }
18910      if (root.nodeName !== 'BODY') {
18911        var scrollContainer = editor.selection.getScrollContainer();
18912        if (scrollContainer) {
18913          y = getPos$1(elm).y - getPos$1(scrollContainer).y + offsetY;
18914          viewPortH = scrollContainer.clientHeight;
18915          viewPortY = scrollContainer.scrollTop;
18916          if (y < viewPortY || y + 25 > viewPortY + viewPortH) {
18917            scrollContainer.scrollTop = y < viewPortY ? y : y - viewPortH + 25;
18918          }
18919          return;
18920        }
18921      }
18922      viewPort = dom.getViewPort(editor.getWin());
18923      y = dom.getPos(elm).y + offsetY;
18924      viewPortY = viewPort.y;
18925      viewPortH = viewPort.h;
18926      if (y < viewPort.y || y + 25 > viewPortY + viewPortH) {
18927        editor.getWin().scrollTo(0, y < viewPortY ? y : y - viewPortH + 25);
18928      }
18929    };
18930    var getViewPortRect = function (editor) {
18931      if (editor.inline) {
18932        return editor.getBody().getBoundingClientRect();
18933      } else {
18934        var win = editor.getWin();
18935        return {
18936          left: 0,
18937          right: win.innerWidth,
18938          top: 0,
18939          bottom: win.innerHeight,
18940          width: win.innerWidth,
18941          height: win.innerHeight
18942        };
18943      }
18944    };
18945    var scrollBy = function (editor, dx, dy) {
18946      if (editor.inline) {
18947        editor.getBody().scrollLeft += dx;
18948        editor.getBody().scrollTop += dy;
18949      } else {
18950        editor.getWin().scrollBy(dx, dy);
18951      }
18952    };
18953    var scrollRangeIntoView = function (editor, rng) {
18954      head(CaretPosition.fromRangeStart(rng).getClientRects()).each(function (rngRect) {
18955        var bodyRect = getViewPortRect(editor);
18956        var overflow = getOverflow(bodyRect, rngRect);
18957        var margin = 4;
18958        var dx = overflow.x > 0 ? overflow.x + margin : overflow.x - margin;
18959        var dy = overflow.y > 0 ? overflow.y + margin : overflow.y - margin;
18960        scrollBy(editor, overflow.x !== 0 ? dx : 0, overflow.y !== 0 ? dy : 0);
18961      });
18962    };
18963    var ScrollIntoView = {
18964      scrollElementIntoView: scrollElementIntoView,
18965      scrollRangeIntoView: scrollRangeIntoView
18966    };
18967
18968    var hasCeProperty = function (node) {
18969      return NodeType.isContentEditableTrue(node) || NodeType.isContentEditableFalse(node);
18970    };
18971    var findParent = function (node, rootNode, predicate) {
18972      while (node && node !== rootNode) {
18973        if (predicate(node)) {
18974          return node;
18975        }
18976        node = node.parentNode;
18977      }
18978      return null;
18979    };
18980    var findClosestIeRange = function (clientX, clientY, doc) {
18981      var element, rng, rects;
18982      element = doc.elementFromPoint(clientX, clientY);
18983      rng = doc.body.createTextRange();
18984      if (!element || element.tagName === 'HTML') {
18985        element = doc.body;
18986      }
18987      rng.moveToElementText(element);
18988      rects = Tools.toArray(rng.getClientRects());
18989      rects = rects.sort(function (a, b) {
18990        a = Math.abs(Math.max(a.top - clientY, a.bottom - clientY));
18991        b = Math.abs(Math.max(b.top - clientY, b.bottom - clientY));
18992        return a - b;
18993      });
18994      if (rects.length > 0) {
18995        clientY = (rects[0].bottom + rects[0].top) / 2;
18996        try {
18997          rng.moveToPoint(clientX, clientY);
18998          rng.collapse(true);
18999          return rng;
19000        } catch (ex) {
19001        }
19002      }
19003      return null;
19004    };
19005    var moveOutOfContentEditableFalse = function (rng, rootNode) {
19006      var parentElement = rng && rng.parentElement ? rng.parentElement() : null;
19007      return NodeType.isContentEditableFalse(findParent(parentElement, rootNode, hasCeProperty)) ? null : rng;
19008    };
19009    var fromPoint$1 = function (clientX, clientY, doc) {
19010      var rng, point;
19011      var pointDoc = doc;
19012      if (pointDoc.caretPositionFromPoint) {
19013        point = pointDoc.caretPositionFromPoint(clientX, clientY);
19014        if (point) {
19015          rng = doc.createRange();
19016          rng.setStart(point.offsetNode, point.offset);
19017          rng.collapse(true);
19018        }
19019      } else if (doc.caretRangeFromPoint) {
19020        rng = doc.caretRangeFromPoint(clientX, clientY);
19021      } else if (pointDoc.body.createTextRange) {
19022        rng = pointDoc.body.createTextRange();
19023        try {
19024          rng.moveToPoint(clientX, clientY);
19025          rng.collapse(true);
19026        } catch (ex) {
19027          rng = findClosestIeRange(clientX, clientY, doc);
19028        }
19029        return moveOutOfContentEditableFalse(rng, doc.body);
19030      }
19031      return rng;
19032    };
19033    var CaretRangeFromPoint = { fromPoint: fromPoint$1 };
19034
19035    var processRanges = function (editor, ranges) {
19036      return map(ranges, function (range) {
19037        var evt = editor.fire('GetSelectionRange', { range: range });
19038        return evt.range !== range ? evt.range : range;
19039      });
19040    };
19041    var EventProcessRanges = { processRanges: processRanges };
19042
19043    var fromElements = function (elements, scope) {
19044      var doc = scope || domGlobals.document;
19045      var fragment = doc.createDocumentFragment();
19046      each(elements, function (element) {
19047        fragment.appendChild(element.dom());
19048      });
19049      return Element.fromDom(fragment);
19050    };
19051
19052    var tableModel = Immutable('element', 'width', 'rows');
19053    var tableRow = Immutable('element', 'cells');
19054    var cellPosition = Immutable('x', 'y');
19055    var getSpan = function (td, key) {
19056      var value = parseInt(get$1(td, key), 10);
19057      return isNaN(value) ? 1 : value;
19058    };
19059    var fillout = function (table, x, y, tr, td) {
19060      var rowspan = getSpan(td, 'rowspan');
19061      var colspan = getSpan(td, 'colspan');
19062      var rows = table.rows();
19063      for (var y2 = y; y2 < y + rowspan; y2++) {
19064        if (!rows[y2]) {
19065          rows[y2] = tableRow(deep(tr), []);
19066        }
19067        for (var x2 = x; x2 < x + colspan; x2++) {
19068          var cells = rows[y2].cells();
19069          cells[x2] = y2 === y && x2 === x ? td : shallow(td);
19070        }
19071      }
19072    };
19073    var cellExists = function (table, x, y) {
19074      var rows = table.rows();
19075      var cells = rows[y] ? rows[y].cells() : [];
19076      return !!cells[x];
19077    };
19078    var skipCellsX = function (table, x, y) {
19079      while (cellExists(table, x, y)) {
19080        x++;
19081      }
19082      return x;
19083    };
19084    var getWidth = function (rows) {
19085      return foldl(rows, function (acc, row) {
19086        return row.cells().length > acc ? row.cells().length : acc;
19087      }, 0);
19088    };
19089    var findElementPos = function (table, element) {
19090      var rows = table.rows();
19091      for (var y = 0; y < rows.length; y++) {
19092        var cells = rows[y].cells();
19093        for (var x = 0; x < cells.length; x++) {
19094          if (eq(cells[x], element)) {
19095            return Option.some(cellPosition(x, y));
19096          }
19097        }
19098      }
19099      return Option.none();
19100    };
19101    var extractRows = function (table, sx, sy, ex, ey) {
19102      var newRows = [];
19103      var rows = table.rows();
19104      for (var y = sy; y <= ey; y++) {
19105        var cells = rows[y].cells();
19106        var slice = sx < ex ? cells.slice(sx, ex + 1) : cells.slice(ex, sx + 1);
19107        newRows.push(tableRow(rows[y].element(), slice));
19108      }
19109      return newRows;
19110    };
19111    var subTable = function (table, startPos, endPos) {
19112      var sx = startPos.x(), sy = startPos.y();
19113      var ex = endPos.x(), ey = endPos.y();
19114      var newRows = sy < ey ? extractRows(table, sx, sy, ex, ey) : extractRows(table, sx, ey, ex, sy);
19115      return tableModel(table.element(), getWidth(newRows), newRows);
19116    };
19117    var createDomTable = function (table, rows) {
19118      var tableElement = shallow(table.element());
19119      var tableBody = Element.fromTag('tbody');
19120      append$1(tableBody, rows);
19121      append(tableElement, tableBody);
19122      return tableElement;
19123    };
19124    var modelRowsToDomRows = function (table) {
19125      return map(table.rows(), function (row) {
19126        var cells = map(row.cells(), function (cell) {
19127          var td = deep(cell);
19128          remove(td, 'colspan');
19129          remove(td, 'rowspan');
19130          return td;
19131        });
19132        var tr = shallow(row.element());
19133        append$1(tr, cells);
19134        return tr;
19135      });
19136    };
19137    var fromDom$1 = function (tableElm) {
19138      var table = tableModel(shallow(tableElm), 0, []);
19139      each(descendants$1(tableElm, 'tr'), function (tr, y) {
19140        each(descendants$1(tr, 'td,th'), function (td, x) {
19141          fillout(table, skipCellsX(table, x, y), y, tr, td);
19142        });
19143      });
19144      return tableModel(table.element(), getWidth(table.rows()), table.rows());
19145    };
19146    var toDom = function (table) {
19147      return createDomTable(table, modelRowsToDomRows(table));
19148    };
19149    var subsection = function (table, startElement, endElement) {
19150      return findElementPos(table, startElement).bind(function (startPos) {
19151        return findElementPos(table, endElement).map(function (endPos) {
19152          return subTable(table, startPos, endPos);
19153        });
19154      });
19155    };
19156    var SimpleTableModel = {
19157      fromDom: fromDom$1,
19158      toDom: toDom,
19159      subsection: subsection
19160    };
19161
19162    var getRanges = function (selection) {
19163      var ranges = [];
19164      if (selection) {
19165        for (var i = 0; i < selection.rangeCount; i++) {
19166          ranges.push(selection.getRangeAt(i));
19167        }
19168      }
19169      return ranges;
19170    };
19171    var getSelectedNodes = function (ranges) {
19172      return bind(ranges, function (range) {
19173        var node = getSelectedNode(range);
19174        return node ? [Element.fromDom(node)] : [];
19175      });
19176    };
19177    var hasMultipleRanges = function (selection) {
19178      return getRanges(selection).length > 1;
19179    };
19180    var MultiRange = {
19181      getRanges: getRanges,
19182      getSelectedNodes: getSelectedNodes,
19183      hasMultipleRanges: hasMultipleRanges
19184    };
19185
19186    var getCellsFromRanges = function (ranges) {
19187      return filter(MultiRange.getSelectedNodes(ranges), isTableCell);
19188    };
19189    var getCellsFromElement = function (elm) {
19190      return descendants$1(elm, 'td[data-mce-selected],th[data-mce-selected]');
19191    };
19192    var getCellsFromElementOrRanges = function (ranges, element) {
19193      var selectedCells = getCellsFromElement(element);
19194      var rangeCells = getCellsFromRanges(ranges);
19195      return selectedCells.length > 0 ? selectedCells : rangeCells;
19196    };
19197    var getCellsFromEditor = function (editor) {
19198      return getCellsFromElementOrRanges(MultiRange.getRanges(editor.selection.getSel()), Element.fromDom(editor.getBody()));
19199    };
19200    var TableCellSelection = {
19201      getCellsFromRanges: getCellsFromRanges,
19202      getCellsFromElement: getCellsFromElement,
19203      getCellsFromElementOrRanges: getCellsFromElementOrRanges,
19204      getCellsFromEditor: getCellsFromEditor
19205    };
19206
19207    var findParentListContainer = function (parents) {
19208      return find(parents, function (elm) {
19209        return name(elm) === 'ul' || name(elm) === 'ol';
19210      });
19211    };
19212    var getFullySelectedListWrappers = function (parents, rng) {
19213      return find(parents, function (elm) {
19214        return name(elm) === 'li' && hasAllContentsSelected(elm, rng);
19215      }).fold(constant([]), function (li) {
19216        return findParentListContainer(parents).map(function (listCont) {
19217          return [
19218            Element.fromTag('li'),
19219            Element.fromTag(name(listCont))
19220          ];
19221        }).getOr([]);
19222      });
19223    };
19224    var wrap$3 = function (innerElm, elms) {
19225      var wrapped = foldl(elms, function (acc, elm) {
19226        append(elm, acc);
19227        return elm;
19228      }, innerElm);
19229      return elms.length > 0 ? fromElements([wrapped]) : wrapped;
19230    };
19231    var directListWrappers = function (commonAnchorContainer) {
19232      if (isListItem(commonAnchorContainer)) {
19233        return parent(commonAnchorContainer).filter(isList).fold(constant([]), function (listElm) {
19234          return [
19235            commonAnchorContainer,
19236            listElm
19237          ];
19238        });
19239      } else {
19240        return isList(commonAnchorContainer) ? [commonAnchorContainer] : [];
19241      }
19242    };
19243    var getWrapElements = function (rootNode, rng) {
19244      var commonAnchorContainer = Element.fromDom(rng.commonAncestorContainer);
19245      var parents = Parents.parentsAndSelf(commonAnchorContainer, rootNode);
19246      var wrapElements = filter(parents, function (elm) {
19247        return isInline(elm) || isHeading(elm);
19248      });
19249      var listWrappers = getFullySelectedListWrappers(parents, rng);
19250      var allWrappers = wrapElements.concat(listWrappers.length ? listWrappers : directListWrappers(commonAnchorContainer));
19251      return map(allWrappers, shallow);
19252    };
19253    var emptyFragment = function () {
19254      return fromElements([]);
19255    };
19256    var getFragmentFromRange = function (rootNode, rng) {
19257      return wrap$3(Element.fromDom(rng.cloneContents()), getWrapElements(rootNode, rng));
19258    };
19259    var getParentTable = function (rootElm, cell) {
19260      return ancestor$1(cell, 'table', curry(eq, rootElm));
19261    };
19262    var getTableFragment = function (rootNode, selectedTableCells) {
19263      return getParentTable(rootNode, selectedTableCells[0]).bind(function (tableElm) {
19264        var firstCell = selectedTableCells[0];
19265        var lastCell = selectedTableCells[selectedTableCells.length - 1];
19266        var fullTableModel = SimpleTableModel.fromDom(tableElm);
19267        return SimpleTableModel.subsection(fullTableModel, firstCell, lastCell).map(function (sectionedTableModel) {
19268          return fromElements([SimpleTableModel.toDom(sectionedTableModel)]);
19269        });
19270      }).getOrThunk(emptyFragment);
19271    };
19272    var getSelectionFragment = function (rootNode, ranges) {
19273      return ranges.length > 0 && ranges[0].collapsed ? emptyFragment() : getFragmentFromRange(rootNode, ranges[0]);
19274    };
19275    var read$2 = function (rootNode, ranges) {
19276      var selectedCells = TableCellSelection.getCellsFromElementOrRanges(ranges, rootNode);
19277      return selectedCells.length > 0 ? getTableFragment(rootNode, selectedCells) : getSelectionFragment(rootNode, ranges);
19278    };
19279    var FragmentReader = { read: read$2 };
19280
19281    var getTextContent = function (editor) {
19282      return Option.from(editor.selection.getRng()).map(function (rng) {
19283        var bin = editor.dom.add(editor.getBody(), 'div', {
19284          'data-mce-bogus': 'all',
19285          'style': 'overflow: hidden; opacity: 0;'
19286        }, rng.cloneContents());
19287        var text = Zwsp.trim(bin.innerText);
19288        editor.dom.remove(bin);
19289        return text;
19290      }).getOr('');
19291    };
19292    var getHtmlContent = function (editor, args) {
19293      var rng = editor.selection.getRng(), tmpElm = editor.dom.create('body');
19294      var sel = editor.selection.getSel();
19295      var fragment;
19296      var ranges = EventProcessRanges.processRanges(editor, MultiRange.getRanges(sel));
19297      fragment = args.contextual ? FragmentReader.read(Element.fromDom(editor.getBody()), ranges).dom() : rng.cloneContents();
19298      if (fragment) {
19299        tmpElm.appendChild(fragment);
19300      }
19301      return editor.selection.serializer.serialize(tmpElm, args);
19302    };
19303    var getContent$1 = function (editor, args) {
19304      if (args === void 0) {
19305        args = {};
19306      }
19307      args.get = true;
19308      args.format = args.format || 'html';
19309      args.selection = true;
19310      args = editor.fire('BeforeGetContent', args);
19311      if (args.isDefaultPrevented()) {
19312        editor.fire('GetContent', args);
19313        return args.content;
19314      }
19315      if (args.format === 'text') {
19316        return getTextContent(editor);
19317      } else {
19318        args.getInner = true;
19319        var content = getHtmlContent(editor, args);
19320        if (args.format === 'tree') {
19321          return content;
19322        } else {
19323          args.content = editor.selection.isCollapsed() ? '' : content;
19324          editor.fire('GetContent', args);
19325          return args.content;
19326        }
19327      }
19328    };
19329    var GetSelectionContent = { getContent: getContent$1 };
19330
19331    var findParent$1 = function (node, rootNode, predicate) {
19332      while (node && node !== rootNode) {
19333        if (predicate(node)) {
19334          return node;
19335        }
19336        node = node.parentNode;
19337      }
19338      return null;
19339    };
19340    var hasParent = function (node, rootNode, predicate) {
19341      return findParent$1(node, rootNode, predicate) !== null;
19342    };
19343    var hasParentWithName = function (node, rootNode, name) {
19344      return hasParent(node, rootNode, function (node) {
19345        return node.nodeName === name;
19346      });
19347    };
19348    var isTable$3 = function (node) {
19349      return node && node.nodeName === 'TABLE';
19350    };
19351    var isTableCell$3 = function (node) {
19352      return node && /^(TD|TH|CAPTION)$/.test(node.nodeName);
19353    };
19354    var isCeFalseCaretContainer = function (node, rootNode) {
19355      return isCaretContainer(node) && hasParent(node, rootNode, isCaretNode) === false;
19356    };
19357    var hasBrBeforeAfter = function (dom, node, left) {
19358      var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || dom.getRoot());
19359      while (node = walker[left ? 'prev' : 'next']()) {
19360        if (NodeType.isBr(node)) {
19361          return true;
19362        }
19363      }
19364    };
19365    var isPrevNode = function (node, name) {
19366      return node.previousSibling && node.previousSibling.nodeName === name;
19367    };
19368    var hasContentEditableFalseParent = function (body, node) {
19369      while (node && node !== body) {
19370        if (NodeType.isContentEditableFalse(node)) {
19371          return true;
19372        }
19373        node = node.parentNode;
19374      }
19375      return false;
19376    };
19377    var findTextNodeRelative = function (dom, isAfterNode, collapsed, left, startNode) {
19378      var lastInlineElement;
19379      var body = dom.getRoot();
19380      var node;
19381      var nonEmptyElementsMap = dom.schema.getNonEmptyElements();
19382      var parentBlockContainer = dom.getParent(startNode.parentNode, dom.isBlock) || body;
19383      if (left && NodeType.isBr(startNode) && isAfterNode && dom.isEmpty(parentBlockContainer)) {
19384        return Option.some(CaretPosition(startNode.parentNode, dom.nodeIndex(startNode)));
19385      }
19386      var walker = new TreeWalker(startNode, parentBlockContainer);
19387      while (node = walker[left ? 'prev' : 'next']()) {
19388        if (dom.getContentEditableParent(node) === 'false' || isCeFalseCaretContainer(node, body)) {
19389          return Option.none();
19390        }
19391        if (NodeType.isText(node) && node.nodeValue.length > 0) {
19392          if (hasParentWithName(node, body, 'A') === false) {
19393            return Option.some(CaretPosition(node, left ? node.nodeValue.length : 0));
19394          }
19395          return Option.none();
19396        }
19397        if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
19398          return Option.none();
19399        }
19400        lastInlineElement = node;
19401      }
19402      if (collapsed && lastInlineElement) {
19403        return Option.some(CaretPosition(lastInlineElement, 0));
19404      }
19405      return Option.none();
19406    };
19407    var normalizeEndPoint = function (dom, collapsed, start, rng) {
19408      var container, offset;
19409      var body = dom.getRoot();
19410      var node, nonEmptyElementsMap;
19411      var directionLeft, isAfterNode, normalized = false;
19412      container = rng[(start ? 'start' : 'end') + 'Container'];
19413      offset = rng[(start ? 'start' : 'end') + 'Offset'];
19414      isAfterNode = NodeType.isElement(container) && offset === container.childNodes.length;
19415      nonEmptyElementsMap = dom.schema.getNonEmptyElements();
19416      directionLeft = start;
19417      if (isCaretContainer(container)) {
19418        return Option.none();
19419      }
19420      if (NodeType.isElement(container) && offset > container.childNodes.length - 1) {
19421        directionLeft = false;
19422      }
19423      if (NodeType.isDocument(container)) {
19424        container = body;
19425        offset = 0;
19426      }
19427      if (container === body) {
19428        if (directionLeft) {
19429          node = container.childNodes[offset > 0 ? offset - 1 : 0];
19430          if (node) {
19431            if (isCaretContainer(node)) {
19432              return Option.none();
19433            }
19434            if (nonEmptyElementsMap[node.nodeName] || isTable$3(node)) {
19435              return Option.none();
19436            }
19437          }
19438        }
19439        if (container.hasChildNodes()) {
19440          offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
19441          container = container.childNodes[offset];
19442          offset = NodeType.isText(container) && isAfterNode ? container.data.length : 0;
19443          if (!collapsed && container === body.lastChild && isTable$3(container)) {
19444            return Option.none();
19445          }
19446          if (hasContentEditableFalseParent(body, container) || isCaretContainer(container)) {
19447            return Option.none();
19448          }
19449          if (container.hasChildNodes() && isTable$3(container) === false) {
19450            node = container;
19451            var walker = new TreeWalker(container, body);
19452            do {
19453              if (NodeType.isContentEditableFalse(node) || isCaretContainer(node)) {
19454                normalized = false;
19455                break;
19456              }
19457              if (NodeType.isText(node) && node.nodeValue.length > 0) {
19458                offset = directionLeft ? 0 : node.nodeValue.length;
19459                container = node;
19460                normalized = true;
19461                break;
19462              }
19463              if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCell$3(node)) {
19464                offset = dom.nodeIndex(node);
19465                container = node.parentNode;
19466                if (!directionLeft) {
19467                  offset++;
19468                }
19469                normalized = true;
19470                break;
19471              }
19472            } while (node = directionLeft ? walker.next() : walker.prev());
19473          }
19474        }
19475      }
19476      if (collapsed) {
19477        if (NodeType.isText(container) && offset === 0) {
19478          findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(function (pos) {
19479            container = pos.container();
19480            offset = pos.offset();
19481            normalized = true;
19482          });
19483        }
19484        if (NodeType.isElement(container)) {
19485          node = container.childNodes[offset];
19486          if (!node) {
19487            node = container.childNodes[offset - 1];
19488          }
19489          if (node && NodeType.isBr(node) && !isPrevNode(node, 'A') && !hasBrBeforeAfter(dom, node, false) && !hasBrBeforeAfter(dom, node, true)) {
19490            findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(function (pos) {
19491              container = pos.container();
19492              offset = pos.offset();
19493              normalized = true;
19494            });
19495          }
19496        }
19497      }
19498      if (directionLeft && !collapsed && NodeType.isText(container) && offset === container.nodeValue.length) {
19499        findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(function (pos) {
19500          container = pos.container();
19501          offset = pos.offset();
19502          normalized = true;
19503        });
19504      }
19505      return normalized ? Option.some(CaretPosition(container, offset)) : Option.none();
19506    };
19507    var normalize$2 = function (dom, rng) {
19508      var collapsed = rng.collapsed, normRng = rng.cloneRange();
19509      var startPos = CaretPosition.fromRangeStart(rng);
19510      normalizeEndPoint(dom, collapsed, true, normRng).each(function (pos) {
19511        if (!collapsed || !CaretPosition.isAbove(startPos, pos)) {
19512          normRng.setStart(pos.container(), pos.offset());
19513        }
19514      });
19515      if (!collapsed) {
19516        normalizeEndPoint(dom, collapsed, false, normRng).each(function (pos) {
19517          normRng.setEnd(pos.container(), pos.offset());
19518        });
19519      }
19520      if (collapsed) {
19521        normRng.collapse(true);
19522      }
19523      return RangeCompare.isEq(rng, normRng) ? Option.none() : Option.some(normRng);
19524    };
19525    var NormalizeRange = { normalize: normalize$2 };
19526
19527    var prependData = function (target, data) {
19528      target.insertData(0, data);
19529    };
19530    var removeEmpty = function (text) {
19531      if (text.dom().length === 0) {
19532        remove$1(text);
19533        return Option.none();
19534      }
19535      return Option.some(text);
19536    };
19537    var rngSetContent = function (rng, fragment) {
19538      var firstChild = Option.from(fragment.firstChild).map(Element.fromDom);
19539      var lastChild = Option.from(fragment.lastChild).map(Element.fromDom);
19540      rng.deleteContents();
19541      rng.insertNode(fragment);
19542      var prevText = firstChild.bind(prevSibling).filter(isText).bind(removeEmpty);
19543      var nextText = lastChild.bind(nextSibling).filter(isText).bind(removeEmpty);
19544      liftN([
19545        prevText,
19546        firstChild.filter(isText)
19547      ], function (prev, start) {
19548        prependData(start.dom(), prev.dom().data);
19549        remove$1(prev);
19550      });
19551      liftN([
19552        nextText,
19553        lastChild.filter(isText)
19554      ], function (next, end) {
19555        var oldLength = end.dom().length;
19556        end.dom().appendData(next.dom().data);
19557        rng.setEnd(end.dom(), oldLength);
19558        remove$1(next);
19559      });
19560      rng.collapse(false);
19561    };
19562    var setupArgs = function (args, content) {
19563      args = args || { format: 'html' };
19564      args.set = true;
19565      args.selection = true;
19566      args.content = content;
19567      return args;
19568    };
19569    var setContent$1 = function (editor, content, args) {
19570      args = setupArgs(args, content);
19571      if (!args.no_events) {
19572        args = editor.fire('BeforeSetContent', args);
19573        if (args.isDefaultPrevented()) {
19574          editor.fire('SetContent', args);
19575          return;
19576        }
19577      }
19578      var rng = editor.selection.getRng();
19579      rngSetContent(rng, rng.createContextualFragment(args.content));
19580      editor.selection.setRng(rng);
19581      ScrollIntoView.scrollRangeIntoView(editor, rng);
19582      if (!args.no_events) {
19583        editor.fire('SetContent', args);
19584      }
19585    };
19586    var SetSelectionContent = { setContent: setContent$1 };
19587
19588    var getEndpointElement = function (root, rng, start, real, resolve) {
19589      var container = start ? rng.startContainer : rng.endContainer;
19590      var offset = start ? rng.startOffset : rng.endOffset;
19591      return Option.from(container).map(Element.fromDom).map(function (elm) {
19592        return !real || !rng.collapsed ? child(elm, resolve(elm, offset)).getOr(elm) : elm;
19593      }).bind(function (elm) {
19594        return isElement(elm) ? Option.some(elm) : parent(elm);
19595      }).map(function (elm) {
19596        return elm.dom();
19597      }).getOr(root);
19598    };
19599    var getStart = function (root, rng, real) {
19600      return getEndpointElement(root, rng, true, real, function (elm, offset) {
19601        return Math.min(childNodesCount(elm), offset);
19602      });
19603    };
19604    var getEnd = function (root, rng, real) {
19605      return getEndpointElement(root, rng, false, real, function (elm, offset) {
19606        return offset > 0 ? offset - 1 : offset;
19607      });
19608    };
19609    var skipEmptyTextNodes = function (node, forwards) {
19610      var orig = node;
19611      while (node && NodeType.isText(node) && node.length === 0) {
19612        node = forwards ? node.nextSibling : node.previousSibling;
19613      }
19614      return node || orig;
19615    };
19616    var getNode$1 = function (root, rng) {
19617      var elm, startContainer, endContainer, startOffset, endOffset;
19618      if (!rng) {
19619        return root;
19620      }
19621      startContainer = rng.startContainer;
19622      endContainer = rng.endContainer;
19623      startOffset = rng.startOffset;
19624      endOffset = rng.endOffset;
19625      elm = rng.commonAncestorContainer;
19626      if (!rng.collapsed) {
19627        if (startContainer === endContainer) {
19628          if (endOffset - startOffset < 2) {
19629            if (startContainer.hasChildNodes()) {
19630              elm = startContainer.childNodes[startOffset];
19631            }
19632          }
19633        }
19634        if (startContainer.nodeType === 3 && endContainer.nodeType === 3) {
19635          if (startContainer.length === startOffset) {
19636            startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
19637          } else {
19638            startContainer = startContainer.parentNode;
19639          }
19640          if (endOffset === 0) {
19641            endContainer = skipEmptyTextNodes(endContainer.previousSibling, false);
19642          } else {
19643            endContainer = endContainer.parentNode;
19644          }
19645          if (startContainer && startContainer === endContainer) {
19646            return startContainer;
19647          }
19648        }
19649      }
19650      if (elm && elm.nodeType === 3) {
19651        return elm.parentNode;
19652      }
19653      return elm;
19654    };
19655    var getSelectedBlocks = function (dom, rng, startElm, endElm) {
19656      var node, root;
19657      var selectedBlocks = [];
19658      root = dom.getRoot();
19659      startElm = dom.getParent(startElm || getStart(root, rng, rng.collapsed), dom.isBlock);
19660      endElm = dom.getParent(endElm || getEnd(root, rng, rng.collapsed), dom.isBlock);
19661      if (startElm && startElm !== root) {
19662        selectedBlocks.push(startElm);
19663      }
19664      if (startElm && endElm && startElm !== endElm) {
19665        node = startElm;
19666        var walker = new TreeWalker(startElm, root);
19667        while ((node = walker.next()) && node !== endElm) {
19668          if (dom.isBlock(node)) {
19669            selectedBlocks.push(node);
19670          }
19671        }
19672      }
19673      if (endElm && startElm !== endElm && endElm !== root) {
19674        selectedBlocks.push(endElm);
19675      }
19676      return selectedBlocks;
19677    };
19678    var select$1 = function (dom, node, content) {
19679      return Option.from(node).map(function (node) {
19680        var idx = dom.nodeIndex(node);
19681        var rng = dom.createRng();
19682        rng.setStart(node.parentNode, idx);
19683        rng.setEnd(node.parentNode, idx + 1);
19684        if (content) {
19685          moveEndPoint$1(dom, rng, node, true);
19686          moveEndPoint$1(dom, rng, node, false);
19687        }
19688        return rng;
19689      });
19690    };
19691
19692    var deleteFromCallbackMap = function (callbackMap, selector, callback) {
19693      if (callbackMap && callbackMap.hasOwnProperty(selector)) {
19694        var newCallbacks = filter(callbackMap[selector], function (cb) {
19695          return cb !== callback;
19696        });
19697        if (newCallbacks.length === 0) {
19698          delete callbackMap[selector];
19699        } else {
19700          callbackMap[selector] = newCallbacks;
19701        }
19702      }
19703    };
19704    function SelectorChanged (dom, editor) {
19705      var selectorChangedData, currentSelectors;
19706      return {
19707        selectorChangedWithUnbind: function (selector, callback) {
19708          if (!selectorChangedData) {
19709            selectorChangedData = {};
19710            currentSelectors = {};
19711            editor.on('NodeChange', function (e) {
19712              var node = e.element, parents = dom.getParents(node, null, dom.getRoot()), matchedSelectors = {};
19713              Tools.each(selectorChangedData, function (callbacks, selector) {
19714                Tools.each(parents, function (node) {
19715                  if (dom.is(node, selector)) {
19716                    if (!currentSelectors[selector]) {
19717                      Tools.each(callbacks, function (callback) {
19718                        callback(true, {
19719                          node: node,
19720                          selector: selector,
19721                          parents: parents
19722                        });
19723                      });
19724                      currentSelectors[selector] = callbacks;
19725                    }
19726                    matchedSelectors[selector] = callbacks;
19727                    return false;
19728                  }
19729                });
19730              });
19731              Tools.each(currentSelectors, function (callbacks, selector) {
19732                if (!matchedSelectors[selector]) {
19733                  delete currentSelectors[selector];
19734                  Tools.each(callbacks, function (callback) {
19735                    callback(false, {
19736                      node: node,
19737                      selector: selector,
19738                      parents: parents
19739                    });
19740                  });
19741                }
19742              });
19743            });
19744          }
19745          if (!selectorChangedData[selector]) {
19746            selectorChangedData[selector] = [];
19747          }
19748          selectorChangedData[selector].push(callback);
19749          return {
19750            unbind: function () {
19751              deleteFromCallbackMap(selectorChangedData, selector, callback);
19752              deleteFromCallbackMap(currentSelectors, selector, callback);
19753            }
19754          };
19755        }
19756      };
19757    }
19758
19759    var isNativeIeSelection = function (rng) {
19760      return !!rng.select;
19761    };
19762    var isAttachedToDom = function (node) {
19763      return !!(node && node.ownerDocument) && contains$3(Element.fromDom(node.ownerDocument), Element.fromDom(node));
19764    };
19765    var isValidRange = function (rng) {
19766      if (!rng) {
19767        return false;
19768      } else if (isNativeIeSelection(rng)) {
19769        return true;
19770      } else {
19771        return isAttachedToDom(rng.startContainer) && isAttachedToDom(rng.endContainer);
19772      }
19773    };
19774    var Selection = function (dom, win, serializer, editor) {
19775      var bookmarkManager, controlSelection;
19776      var selectedRange, explicitRange;
19777      var selectorChangedWithUnbind = SelectorChanged(dom, editor).selectorChangedWithUnbind;
19778      var setCursorLocation = function (node, offset) {
19779        var rng = dom.createRng();
19780        if (!node) {
19781          moveEndPoint$1(dom, rng, editor.getBody(), true);
19782          setRng(rng);
19783        } else {
19784          rng.setStart(node, offset);
19785          rng.setEnd(node, offset);
19786          setRng(rng);
19787          collapse(false);
19788        }
19789      };
19790      var getContent = function (args) {
19791        return GetSelectionContent.getContent(editor, args);
19792      };
19793      var setContent = function (content, args) {
19794        return SetSelectionContent.setContent(editor, content, args);
19795      };
19796      var getStart$1 = function (real) {
19797        return getStart(editor.getBody(), getRng(), real);
19798      };
19799      var getEnd$1 = function (real) {
19800        return getEnd(editor.getBody(), getRng(), real);
19801      };
19802      var getBookmark = function (type, normalized) {
19803        return bookmarkManager.getBookmark(type, normalized);
19804      };
19805      var moveToBookmark = function (bookmark) {
19806        return bookmarkManager.moveToBookmark(bookmark);
19807      };
19808      var select = function (node, content) {
19809        select$1(dom, node, content).each(setRng);
19810        return node;
19811      };
19812      var isCollapsed = function () {
19813        var rng = getRng(), sel = getSel();
19814        if (!rng || rng.item) {
19815          return false;
19816        }
19817        if (rng.compareEndPoints) {
19818          return rng.compareEndPoints('StartToEnd', rng) === 0;
19819        }
19820        return !sel || rng.collapsed;
19821      };
19822      var collapse = function (toStart) {
19823        var rng = getRng();
19824        rng.collapse(!!toStart);
19825        setRng(rng);
19826      };
19827      var getSel = function () {
19828        return win.getSelection ? win.getSelection() : win.document.selection;
19829      };
19830      var getRng = function () {
19831        var selection, rng, elm, doc;
19832        var tryCompareBoundaryPoints = function (how, sourceRange, destinationRange) {
19833          try {
19834            return sourceRange.compareBoundaryPoints(how, destinationRange);
19835          } catch (ex) {
19836            return -1;
19837          }
19838        };
19839        if (!win) {
19840          return null;
19841        }
19842        doc = win.document;
19843        if (typeof doc === 'undefined' || doc === null) {
19844          return null;
19845        }
19846        if (editor.bookmark !== undefined && EditorFocus.hasFocus(editor) === false) {
19847          var bookmark = SelectionBookmark.getRng(editor);
19848          if (bookmark.isSome()) {
19849            return bookmark.map(function (r) {
19850              return EventProcessRanges.processRanges(editor, [r])[0];
19851            }).getOr(doc.createRange());
19852          }
19853        }
19854        try {
19855          if (selection = getSel()) {
19856            if (selection.rangeCount > 0) {
19857              rng = selection.getRangeAt(0);
19858            } else {
19859              rng = selection.createRange ? selection.createRange() : doc.createRange();
19860            }
19861          }
19862        } catch (ex) {
19863        }
19864        rng = EventProcessRanges.processRanges(editor, [rng])[0];
19865        if (!rng) {
19866          rng = doc.createRange ? doc.createRange() : doc.body.createTextRange();
19867        }
19868        if (rng.setStart && rng.startContainer.nodeType === 9 && rng.collapsed) {
19869          elm = dom.getRoot();
19870          rng.setStart(elm, 0);
19871          rng.setEnd(elm, 0);
19872        }
19873        if (selectedRange && explicitRange) {
19874          if (tryCompareBoundaryPoints(rng.START_TO_START, rng, selectedRange) === 0 && tryCompareBoundaryPoints(rng.END_TO_END, rng, selectedRange) === 0) {
19875            rng = explicitRange;
19876          } else {
19877            selectedRange = null;
19878            explicitRange = null;
19879          }
19880        }
19881        return rng;
19882      };
19883      var setRng = function (rng, forward) {
19884        var sel, node, evt;
19885        if (!isValidRange(rng)) {
19886          return;
19887        }
19888        var ieRange = isNativeIeSelection(rng) ? rng : null;
19889        if (ieRange) {
19890          explicitRange = null;
19891          try {
19892            ieRange.select();
19893          } catch (ex) {
19894          }
19895          return;
19896        }
19897        sel = getSel();
19898        evt = editor.fire('SetSelectionRange', {
19899          range: rng,
19900          forward: forward
19901        });
19902        rng = evt.range;
19903        if (sel) {
19904          explicitRange = rng;
19905          try {
19906            sel.removeAllRanges();
19907            sel.addRange(rng);
19908          } catch (ex) {
19909          }
19910          if (forward === false && sel.extend) {
19911            sel.collapse(rng.endContainer, rng.endOffset);
19912            sel.extend(rng.startContainer, rng.startOffset);
19913          }
19914          selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
19915        }
19916        if (!rng.collapsed && rng.startContainer === rng.endContainer && sel.setBaseAndExtent && !Env.ie) {
19917          if (rng.endOffset - rng.startOffset < 2) {
19918            if (rng.startContainer.hasChildNodes()) {
19919              node = rng.startContainer.childNodes[rng.startOffset];
19920              if (node && node.tagName === 'IMG') {
19921                sel.setBaseAndExtent(rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset);
19922                if (sel.anchorNode !== rng.startContainer || sel.focusNode !== rng.endContainer) {
19923                  sel.setBaseAndExtent(node, 0, node, 1);
19924                }
19925              }
19926            }
19927          }
19928        }
19929        editor.fire('AfterSetSelectionRange', {
19930          range: rng,
19931          forward: forward
19932        });
19933      };
19934      var setNode = function (elm) {
19935        setContent(dom.getOuterHTML(elm));
19936        return elm;
19937      };
19938      var getNode = function () {
19939        return getNode$1(editor.getBody(), getRng());
19940      };
19941      var getSelectedBlocks$1 = function (startElm, endElm) {
19942        return getSelectedBlocks(dom, getRng(), startElm, endElm);
19943      };
19944      var isForward = function () {
19945        var sel = getSel();
19946        var anchorRange, focusRange;
19947        if (!sel || !sel.anchorNode || !sel.focusNode) {
19948          return true;
19949        }
19950        anchorRange = dom.createRng();
19951        anchorRange.setStart(sel.anchorNode, sel.anchorOffset);
19952        anchorRange.collapse(true);
19953        focusRange = dom.createRng();
19954        focusRange.setStart(sel.focusNode, sel.focusOffset);
19955        focusRange.collapse(true);
19956        return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
19957      };
19958      var normalize = function () {
19959        var rng = getRng();
19960        var sel = getSel();
19961        if (!MultiRange.hasMultipleRanges(sel) && hasAnyRanges(editor)) {
19962          var normRng = NormalizeRange.normalize(dom, rng);
19963          normRng.each(function (normRng) {
19964            setRng(normRng, isForward());
19965          });
19966          return normRng.getOr(rng);
19967        }
19968        return rng;
19969      };
19970      var selectorChanged = function (selector, callback) {
19971        selectorChangedWithUnbind(selector, callback);
19972        return exports;
19973      };
19974      var getScrollContainer = function () {
19975        var scrollContainer;
19976        var node = dom.getRoot();
19977        while (node && node.nodeName !== 'BODY') {
19978          if (node.scrollHeight > node.clientHeight) {
19979            scrollContainer = node;
19980            break;
19981          }
19982          node = node.parentNode;
19983        }
19984        return scrollContainer;
19985      };
19986      var scrollIntoView = function (elm, alignToTop) {
19987        return ScrollIntoView.scrollElementIntoView(editor, elm, alignToTop);
19988      };
19989      var placeCaretAt = function (clientX, clientY) {
19990        return setRng(CaretRangeFromPoint.fromPoint(clientX, clientY, editor.getDoc()));
19991      };
19992      var getBoundingClientRect = function () {
19993        var rng = getRng();
19994        return rng.collapsed ? CaretPosition$1.fromRangeStart(rng).getClientRects()[0] : rng.getBoundingClientRect();
19995      };
19996      var destroy = function () {
19997        win = selectedRange = explicitRange = null;
19998        controlSelection.destroy();
19999      };
20000      var exports = {
20001        bookmarkManager: null,
20002        controlSelection: null,
20003        dom: dom,
20004        win: win,
20005        serializer: serializer,
20006        editor: editor,
20007        collapse: collapse,
20008        setCursorLocation: setCursorLocation,
20009        getContent: getContent,
20010        setContent: setContent,
20011        getBookmark: getBookmark,
20012        moveToBookmark: moveToBookmark,
20013        select: select,
20014        isCollapsed: isCollapsed,
20015        isForward: isForward,
20016        setNode: setNode,
20017        getNode: getNode,
20018        getSel: getSel,
20019        setRng: setRng,
20020        getRng: getRng,
20021        getStart: getStart$1,
20022        getEnd: getEnd$1,
20023        getSelectedBlocks: getSelectedBlocks$1,
20024        normalize: normalize,
20025        selectorChanged: selectorChanged,
20026        selectorChangedWithUnbind: selectorChangedWithUnbind,
20027        getScrollContainer: getScrollContainer,
20028        scrollIntoView: scrollIntoView,
20029        placeCaretAt: placeCaretAt,
20030        getBoundingClientRect: getBoundingClientRect,
20031        destroy: destroy
20032      };
20033      bookmarkManager = BookmarkManager$1(exports);
20034      controlSelection = ControlSelection(exports, editor);
20035      exports.bookmarkManager = bookmarkManager;
20036      exports.controlSelection = controlSelection;
20037      return exports;
20038    };
20039
20040    var isText$8 = NodeType.isText;
20041    var startsWithCaretContainer$1 = function (node) {
20042      return isText$8(node) && node.data[0] === Zwsp.ZWSP;
20043    };
20044    var endsWithCaretContainer$1 = function (node) {
20045      return isText$8(node) && node.data[node.data.length - 1] === Zwsp.ZWSP;
20046    };
20047    var createZwsp = function (node) {
20048      return node.ownerDocument.createTextNode(Zwsp.ZWSP);
20049    };
20050    var insertBefore = function (node) {
20051      if (isText$8(node.previousSibling)) {
20052        if (endsWithCaretContainer$1(node.previousSibling)) {
20053          return node.previousSibling;
20054        } else {
20055          node.previousSibling.appendData(Zwsp.ZWSP);
20056          return node.previousSibling;
20057        }
20058      } else if (isText$8(node)) {
20059        if (startsWithCaretContainer$1(node)) {
20060          return node;
20061        } else {
20062          node.insertData(0, Zwsp.ZWSP);
20063          return node;
20064        }
20065      } else {
20066        var newNode = createZwsp(node);
20067        node.parentNode.insertBefore(newNode, node);
20068        return newNode;
20069      }
20070    };
20071    var insertAfter = function (node) {
20072      if (isText$8(node.nextSibling)) {
20073        if (startsWithCaretContainer$1(node.nextSibling)) {
20074          return node.nextSibling;
20075        } else {
20076          node.nextSibling.insertData(0, Zwsp.ZWSP);
20077          return node.nextSibling;
20078        }
20079      } else if (isText$8(node)) {
20080        if (endsWithCaretContainer$1(node)) {
20081          return node;
20082        } else {
20083          node.appendData(Zwsp.ZWSP);
20084          return node;
20085        }
20086      } else {
20087        var newNode = createZwsp(node);
20088        if (node.nextSibling) {
20089          node.parentNode.insertBefore(newNode, node.nextSibling);
20090        } else {
20091          node.parentNode.appendChild(newNode);
20092        }
20093        return newNode;
20094      }
20095    };
20096    var insertInline$1 = function (before, node) {
20097      return before ? insertBefore(node) : insertAfter(node);
20098    };
20099    var insertInlineBefore = curry(insertInline$1, true);
20100    var insertInlineAfter = curry(insertInline$1, false);
20101
20102    var insertInlinePos = function (pos, before) {
20103      if (NodeType.isText(pos.container())) {
20104        return insertInline$1(before, pos.container());
20105      } else {
20106        return insertInline$1(before, pos.getNode());
20107      }
20108    };
20109    var isPosCaretContainer = function (pos, caret) {
20110      var caretNode = caret.get();
20111      return caretNode && pos.container() === caretNode && isCaretContainerInline(caretNode);
20112    };
20113    var renderCaret = function (caret, location) {
20114      return location.fold(function (element) {
20115        CaretContainerRemove.remove(caret.get());
20116        var text = insertInlineBefore(element);
20117        caret.set(text);
20118        return Option.some(CaretPosition$1(text, text.length - 1));
20119      }, function (element) {
20120        return CaretFinder.firstPositionIn(element).map(function (pos) {
20121          if (!isPosCaretContainer(pos, caret)) {
20122            CaretContainerRemove.remove(caret.get());
20123            var text = insertInlinePos(pos, true);
20124            caret.set(text);
20125            return CaretPosition$1(text, 1);
20126          } else {
20127            return CaretPosition$1(caret.get(), 1);
20128          }
20129        });
20130      }, function (element) {
20131        return CaretFinder.lastPositionIn(element).map(function (pos) {
20132          if (!isPosCaretContainer(pos, caret)) {
20133            CaretContainerRemove.remove(caret.get());
20134            var text = insertInlinePos(pos, false);
20135            caret.set(text);
20136            return CaretPosition$1(text, text.length - 1);
20137          } else {
20138            return CaretPosition$1(caret.get(), caret.get().length - 1);
20139          }
20140        });
20141      }, function (element) {
20142        CaretContainerRemove.remove(caret.get());
20143        var text = insertInlineAfter(element);
20144        caret.set(text);
20145        return Option.some(CaretPosition$1(text, 1));
20146      });
20147    };
20148    var BoundaryCaret = { renderCaret: renderCaret };
20149
20150    var strongRtl = /[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/;
20151    var hasStrongRtl = function (text) {
20152      return strongRtl.test(text);
20153    };
20154
20155    var isInlineTarget = function (editor, elm) {
20156      var selector = getString(editor, 'inline_boundaries_selector').getOr('a[href],code');
20157      return is$1(Element.fromDom(elm), selector);
20158    };
20159    var isRtl$1 = function (element) {
20160      return DOMUtils$1.DOM.getStyle(element, 'direction', true) === 'rtl' || hasStrongRtl(element.textContent);
20161    };
20162    var findInlineParents = function (isInlineTarget, rootNode, pos) {
20163      return filter(DOMUtils$1.DOM.getParents(pos.container(), '*', rootNode), isInlineTarget);
20164    };
20165    var findRootInline = function (isInlineTarget, rootNode, pos) {
20166      var parents = findInlineParents(isInlineTarget, rootNode, pos);
20167      return Option.from(parents[parents.length - 1]);
20168    };
20169    var hasSameParentBlock = function (rootNode, node1, node2) {
20170      var block1 = getParentBlock(node1, rootNode);
20171      var block2 = getParentBlock(node2, rootNode);
20172      return block1 && block1 === block2;
20173    };
20174    var isAtZwsp = function (pos) {
20175      return isBeforeInline(pos) || isAfterInline(pos);
20176    };
20177    var normalizePosition = function (forward, pos) {
20178      if (!pos) {
20179        return pos;
20180      }
20181      var container = pos.container(), offset = pos.offset();
20182      if (forward) {
20183        if (isCaretContainerInline(container)) {
20184          if (NodeType.isText(container.nextSibling)) {
20185            return CaretPosition$1(container.nextSibling, 0);
20186          } else {
20187            return CaretPosition$1.after(container);
20188          }
20189        } else {
20190          return isBeforeInline(pos) ? CaretPosition$1(container, offset + 1) : pos;
20191        }
20192      } else {
20193        if (isCaretContainerInline(container)) {
20194          if (NodeType.isText(container.previousSibling)) {
20195            return CaretPosition$1(container.previousSibling, container.previousSibling.data.length);
20196          } else {
20197            return CaretPosition$1.before(container);
20198          }
20199        } else {
20200          return isAfterInline(pos) ? CaretPosition$1(container, offset - 1) : pos;
20201        }
20202      }
20203    };
20204    var normalizeForwards = curry(normalizePosition, true);
20205    var normalizeBackwards = curry(normalizePosition, false);
20206    var InlineUtils = {
20207      isInlineTarget: isInlineTarget,
20208      findRootInline: findRootInline,
20209      isRtl: isRtl$1,
20210      isAtZwsp: isAtZwsp,
20211      normalizePosition: normalizePosition,
20212      normalizeForwards: normalizeForwards,
20213      normalizeBackwards: normalizeBackwards,
20214      hasSameParentBlock: hasSameParentBlock
20215    };
20216
20217    var evaluateUntil = function (fns, args) {
20218      for (var i = 0; i < fns.length; i++) {
20219        var result = fns[i].apply(null, args);
20220        if (result.isSome()) {
20221          return result;
20222        }
20223      }
20224      return Option.none();
20225    };
20226    var LazyEvaluator = { evaluateUntil: evaluateUntil };
20227
20228    var Location = Adt.generate([
20229      { before: ['element'] },
20230      { start: ['element'] },
20231      { end: ['element'] },
20232      { after: ['element'] }
20233    ]);
20234    var rescope = function (rootNode, node) {
20235      var parentBlock = getParentBlock(node, rootNode);
20236      return parentBlock ? parentBlock : rootNode;
20237    };
20238    var before$3 = function (isInlineTarget, rootNode, pos) {
20239      var nPos = InlineUtils.normalizeForwards(pos);
20240      var scope = rescope(rootNode, nPos.container());
20241      return InlineUtils.findRootInline(isInlineTarget, scope, nPos).fold(function () {
20242        return CaretFinder.nextPosition(scope, nPos).bind(curry(InlineUtils.findRootInline, isInlineTarget, scope)).map(function (inline) {
20243          return Location.before(inline);
20244        });
20245      }, Option.none);
20246    };
20247    var isNotInsideFormatCaretContainer = function (rootNode, elm) {
20248      return getParentCaretContainer(rootNode, elm) === null;
20249    };
20250    var findInsideRootInline = function (isInlineTarget, rootNode, pos) {
20251      return InlineUtils.findRootInline(isInlineTarget, rootNode, pos).filter(curry(isNotInsideFormatCaretContainer, rootNode));
20252    };
20253    var start$1 = function (isInlineTarget, rootNode, pos) {
20254      var nPos = InlineUtils.normalizeBackwards(pos);
20255      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(function (inline) {
20256        var prevPos = CaretFinder.prevPosition(inline, nPos);
20257        return prevPos.isNone() ? Option.some(Location.start(inline)) : Option.none();
20258      });
20259    };
20260    var end = function (isInlineTarget, rootNode, pos) {
20261      var nPos = InlineUtils.normalizeForwards(pos);
20262      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(function (inline) {
20263        var nextPos = CaretFinder.nextPosition(inline, nPos);
20264        return nextPos.isNone() ? Option.some(Location.end(inline)) : Option.none();
20265      });
20266    };
20267    var after$2 = function (isInlineTarget, rootNode, pos) {
20268      var nPos = InlineUtils.normalizeBackwards(pos);
20269      var scope = rescope(rootNode, nPos.container());
20270      return InlineUtils.findRootInline(isInlineTarget, scope, nPos).fold(function () {
20271        return CaretFinder.prevPosition(scope, nPos).bind(curry(InlineUtils.findRootInline, isInlineTarget, scope)).map(function (inline) {
20272          return Location.after(inline);
20273        });
20274      }, Option.none);
20275    };
20276    var isValidLocation = function (location) {
20277      return InlineUtils.isRtl(getElement(location)) === false;
20278    };
20279    var readLocation = function (isInlineTarget, rootNode, pos) {
20280      var location = LazyEvaluator.evaluateUntil([
20281        before$3,
20282        start$1,
20283        end,
20284        after$2
20285      ], [
20286        isInlineTarget,
20287        rootNode,
20288        pos
20289      ]);
20290      return location.filter(isValidLocation);
20291    };
20292    var getElement = function (location) {
20293      return location.fold(identity, identity, identity, identity);
20294    };
20295    var getName = function (location) {
20296      return location.fold(constant('before'), constant('start'), constant('end'), constant('after'));
20297    };
20298    var outside = function (location) {
20299      return location.fold(Location.before, Location.before, Location.after, Location.after);
20300    };
20301    var inside = function (location) {
20302      return location.fold(Location.start, Location.start, Location.end, Location.end);
20303    };
20304    var isEq$5 = function (location1, location2) {
20305      return getName(location1) === getName(location2) && getElement(location1) === getElement(location2);
20306    };
20307    var betweenInlines = function (forward, isInlineTarget, rootNode, from, to, location) {
20308      return liftN([
20309        InlineUtils.findRootInline(isInlineTarget, rootNode, from),
20310        InlineUtils.findRootInline(isInlineTarget, rootNode, to)
20311      ], function (fromInline, toInline) {
20312        if (fromInline !== toInline && InlineUtils.hasSameParentBlock(rootNode, fromInline, toInline)) {
20313          return Location.after(forward ? fromInline : toInline);
20314        } else {
20315          return location;
20316        }
20317      }).getOr(location);
20318    };
20319    var skipNoMovement = function (fromLocation, toLocation) {
20320      return fromLocation.fold(constant(true), function (fromLocation) {
20321        return !isEq$5(fromLocation, toLocation);
20322      });
20323    };
20324    var findLocationTraverse = function (forward, isInlineTarget, rootNode, fromLocation, pos) {
20325      var from = InlineUtils.normalizePosition(forward, pos);
20326      var to = CaretFinder.fromPosition(forward, rootNode, from).map(curry(InlineUtils.normalizePosition, forward));
20327      var location = to.fold(function () {
20328        return fromLocation.map(outside);
20329      }, function (to) {
20330        return readLocation(isInlineTarget, rootNode, to).map(curry(betweenInlines, forward, isInlineTarget, rootNode, from, to)).filter(curry(skipNoMovement, fromLocation));
20331      });
20332      return location.filter(isValidLocation);
20333    };
20334    var findLocationSimple = function (forward, location) {
20335      if (forward) {
20336        return location.fold(compose(Option.some, Location.start), Option.none, compose(Option.some, Location.after), Option.none);
20337      } else {
20338        return location.fold(Option.none, compose(Option.some, Location.before), Option.none, compose(Option.some, Location.end));
20339      }
20340    };
20341    var findLocation = function (forward, isInlineTarget, rootNode, pos) {
20342      var from = InlineUtils.normalizePosition(forward, pos);
20343      var fromLocation = readLocation(isInlineTarget, rootNode, from);
20344      return readLocation(isInlineTarget, rootNode, from).bind(curry(findLocationSimple, forward)).orThunk(function () {
20345        return findLocationTraverse(forward, isInlineTarget, rootNode, fromLocation, pos);
20346      });
20347    };
20348    var BoundaryLocation = {
20349      readLocation: readLocation,
20350      findLocation: findLocation,
20351      prevLocation: curry(findLocation, false),
20352      nextLocation: curry(findLocation, true),
20353      getElement: getElement,
20354      outside: outside,
20355      inside: inside
20356    };
20357
20358    var hasSelectionModifyApi = function (editor) {
20359      return isFunction(editor.selection.getSel().modify);
20360    };
20361    var moveRel = function (forward, selection, pos) {
20362      var delta = forward ? 1 : -1;
20363      selection.setRng(CaretPosition$1(pos.container(), pos.offset() + delta).toRange());
20364      selection.getSel().modify('move', forward ? 'forward' : 'backward', 'word');
20365      return true;
20366    };
20367    var moveByWord = function (forward, editor) {
20368      var rng = editor.selection.getRng();
20369      var pos = forward ? CaretPosition$1.fromRangeEnd(rng) : CaretPosition$1.fromRangeStart(rng);
20370      if (!hasSelectionModifyApi(editor)) {
20371        return false;
20372      } else if (forward && isBeforeInline(pos)) {
20373        return moveRel(true, editor.selection, pos);
20374      } else if (!forward && isAfterInline(pos)) {
20375        return moveRel(false, editor.selection, pos);
20376      } else {
20377        return false;
20378      }
20379    };
20380    var WordSelection = {
20381      hasSelectionModifyApi: hasSelectionModifyApi,
20382      moveByWord: moveByWord
20383    };
20384
20385    var setCaretPosition = function (editor, pos) {
20386      var rng = editor.dom.createRng();
20387      rng.setStart(pos.container(), pos.offset());
20388      rng.setEnd(pos.container(), pos.offset());
20389      editor.selection.setRng(rng);
20390    };
20391    var isFeatureEnabled = function (editor) {
20392      return editor.settings.inline_boundaries !== false;
20393    };
20394    var setSelected = function (state, elm) {
20395      if (state) {
20396        elm.setAttribute('data-mce-selected', 'inline-boundary');
20397      } else {
20398        elm.removeAttribute('data-mce-selected');
20399      }
20400    };
20401    var renderCaretLocation = function (editor, caret, location) {
20402      return BoundaryCaret.renderCaret(caret, location).map(function (pos) {
20403        setCaretPosition(editor, pos);
20404        return location;
20405      });
20406    };
20407    var findLocation$1 = function (editor, caret, forward) {
20408      var rootNode = editor.getBody();
20409      var from = CaretPosition$1.fromRangeStart(editor.selection.getRng());
20410      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
20411      var location = BoundaryLocation.findLocation(forward, isInlineTarget, rootNode, from);
20412      return location.bind(function (location) {
20413        return renderCaretLocation(editor, caret, location);
20414      });
20415    };
20416    var toggleInlines = function (isInlineTarget, dom, elms) {
20417      var selectedInlines = filter(dom.select('*[data-mce-selected="inline-boundary"]'), isInlineTarget);
20418      var targetInlines = filter(elms, isInlineTarget);
20419      each(difference(selectedInlines, targetInlines), curry(setSelected, false));
20420      each(difference(targetInlines, selectedInlines), curry(setSelected, true));
20421    };
20422    var safeRemoveCaretContainer = function (editor, caret) {
20423      if (editor.selection.isCollapsed() && editor.composing !== true && caret.get()) {
20424        var pos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
20425        if (CaretPosition$1.isTextPosition(pos) && InlineUtils.isAtZwsp(pos) === false) {
20426          setCaretPosition(editor, CaretContainerRemove.removeAndReposition(caret.get(), pos));
20427          caret.set(null);
20428        }
20429      }
20430    };
20431    var renderInsideInlineCaret = function (isInlineTarget, editor, caret, elms) {
20432      if (editor.selection.isCollapsed()) {
20433        var inlines = filter(elms, isInlineTarget);
20434        each(inlines, function (inline) {
20435          var pos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
20436          BoundaryLocation.readLocation(isInlineTarget, editor.getBody(), pos).bind(function (location) {
20437            return renderCaretLocation(editor, caret, location);
20438          });
20439        });
20440      }
20441    };
20442    var move$1 = function (editor, caret, forward) {
20443      return function () {
20444        return isFeatureEnabled(editor) ? findLocation$1(editor, caret, forward).isSome() : false;
20445      };
20446    };
20447    var moveWord = function (forward, editor, caret) {
20448      return function () {
20449        return isFeatureEnabled(editor) ? WordSelection.moveByWord(forward, editor) : false;
20450      };
20451    };
20452    var setupSelectedState = function (editor) {
20453      var caret = Cell(null);
20454      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
20455      editor.on('NodeChange', function (e) {
20456        if (isFeatureEnabled(editor)) {
20457          toggleInlines(isInlineTarget, editor.dom, e.parents);
20458          safeRemoveCaretContainer(editor, caret);
20459          renderInsideInlineCaret(isInlineTarget, editor, caret, e.parents);
20460        }
20461      });
20462      return caret;
20463    };
20464    var moveNextWord = curry(moveWord, true);
20465    var movePrevWord = curry(moveWord, false);
20466    var BoundarySelection = {
20467      move: move$1,
20468      moveNextWord: moveNextWord,
20469      movePrevWord: movePrevWord,
20470      setupSelectedState: setupSelectedState,
20471      setCaretPosition: setCaretPosition
20472    };
20473
20474    var BreakType;
20475    (function (BreakType) {
20476      BreakType[BreakType['Br'] = 0] = 'Br';
20477      BreakType[BreakType['Block'] = 1] = 'Block';
20478      BreakType[BreakType['Wrap'] = 2] = 'Wrap';
20479      BreakType[BreakType['Eol'] = 3] = 'Eol';
20480    }(BreakType || (BreakType = {})));
20481    var flip = function (direction, positions) {
20482      return direction === HDirection.Backwards ? positions.reverse() : positions;
20483    };
20484    var walk$3 = function (direction, caretWalker, pos) {
20485      return direction === HDirection.Forwards ? caretWalker.next(pos) : caretWalker.prev(pos);
20486    };
20487    var getBreakType = function (scope, direction, currentPos, nextPos) {
20488      if (NodeType.isBr(nextPos.getNode(direction === HDirection.Forwards))) {
20489        return BreakType.Br;
20490      } else if (isInSameBlock(currentPos, nextPos) === false) {
20491        return BreakType.Block;
20492      } else {
20493        return BreakType.Wrap;
20494      }
20495    };
20496    var getPositionsUntil = function (predicate, direction, scope, start) {
20497      var caretWalker = CaretWalker(scope);
20498      var currentPos = start, nextPos;
20499      var positions = [];
20500      while (currentPos) {
20501        nextPos = walk$3(direction, caretWalker, currentPos);
20502        if (!nextPos) {
20503          break;
20504        }
20505        if (NodeType.isBr(nextPos.getNode(false))) {
20506          if (direction === HDirection.Forwards) {
20507            return {
20508              positions: flip(direction, positions).concat([nextPos]),
20509              breakType: BreakType.Br,
20510              breakAt: Option.some(nextPos)
20511            };
20512          } else {
20513            return {
20514              positions: flip(direction, positions),
20515              breakType: BreakType.Br,
20516              breakAt: Option.some(nextPos)
20517            };
20518          }
20519        }
20520        if (!nextPos.isVisible()) {
20521          currentPos = nextPos;
20522          continue;
20523        }
20524        if (predicate(currentPos, nextPos)) {
20525          var breakType = getBreakType(scope, direction, currentPos, nextPos);
20526          return {
20527            positions: flip(direction, positions),
20528            breakType: breakType,
20529            breakAt: Option.some(nextPos)
20530          };
20531        }
20532        positions.push(nextPos);
20533        currentPos = nextPos;
20534      }
20535      return {
20536        positions: flip(direction, positions),
20537        breakType: BreakType.Eol,
20538        breakAt: Option.none()
20539      };
20540    };
20541    var getAdjacentLinePositions = function (direction, getPositionsUntilBreak, scope, start) {
20542      return getPositionsUntilBreak(scope, start).breakAt.map(function (pos) {
20543        var positions = getPositionsUntilBreak(scope, pos).positions;
20544        return direction === HDirection.Backwards ? positions.concat(pos) : [pos].concat(positions);
20545      }).getOr([]);
20546    };
20547    var findClosestHorizontalPositionFromPoint = function (positions, x) {
20548      return foldl(positions, function (acc, newPos) {
20549        return acc.fold(function () {
20550          return Option.some(newPos);
20551        }, function (lastPos) {
20552          return liftN([
20553            head(lastPos.getClientRects()),
20554            head(newPos.getClientRects())
20555          ], function (lastRect, newRect) {
20556            var lastDist = Math.abs(x - lastRect.left);
20557            var newDist = Math.abs(x - newRect.left);
20558            return newDist <= lastDist ? newPos : lastPos;
20559          }).or(acc);
20560        });
20561      }, Option.none());
20562    };
20563    var findClosestHorizontalPosition = function (positions, pos) {
20564      return head(pos.getClientRects()).bind(function (targetRect) {
20565        return findClosestHorizontalPositionFromPoint(positions, targetRect.left);
20566      });
20567    };
20568    var getPositionsUntilPreviousLine = curry(getPositionsUntil, CaretPosition.isAbove, -1);
20569    var getPositionsUntilNextLine = curry(getPositionsUntil, CaretPosition.isBelow, 1);
20570    var isAtFirstLine = function (scope, pos) {
20571      return getPositionsUntilPreviousLine(scope, pos).breakAt.isNone();
20572    };
20573    var isAtLastLine = function (scope, pos) {
20574      return getPositionsUntilNextLine(scope, pos).breakAt.isNone();
20575    };
20576    var getPositionsAbove = curry(getAdjacentLinePositions, -1, getPositionsUntilPreviousLine);
20577    var getPositionsBelow = curry(getAdjacentLinePositions, 1, getPositionsUntilNextLine);
20578    var getFirstLinePositions = function (scope) {
20579      return CaretFinder.firstPositionIn(scope).map(function (pos) {
20580        return [pos].concat(getPositionsUntilNextLine(scope, pos).positions);
20581      }).getOr([]);
20582    };
20583    var getLastLinePositions = function (scope) {
20584      return CaretFinder.lastPositionIn(scope).map(function (pos) {
20585        return getPositionsUntilPreviousLine(scope, pos).positions.concat(pos);
20586      }).getOr([]);
20587    };
20588
20589    var isContentEditableFalse$b = NodeType.isContentEditableFalse;
20590    var getSelectedNode$1 = getSelectedNode;
20591    var moveToCeFalseHorizontally = function (direction, editor, getNextPosFn, range) {
20592      var forwards = direction === HDirection.Forwards;
20593      var isBeforeContentEditableFalseFn = forwards ? isBeforeContentEditableFalse : isAfterContentEditableFalse;
20594      if (!range.collapsed) {
20595        var node = getSelectedNode$1(range);
20596        if (isContentEditableFalse$b(node)) {
20597          return showCaret(direction, editor, node, direction === HDirection.Backwards, true);
20598        }
20599      }
20600      var rangeIsInContainerBlock = isRangeInCaretContainerBlock(range);
20601      var caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
20602      if (isBeforeContentEditableFalseFn(caretPosition)) {
20603        return selectNode(editor, caretPosition.getNode(!forwards));
20604      }
20605      var nextCaretPosition = InlineUtils.normalizePosition(forwards, getNextPosFn(caretPosition));
20606      if (!nextCaretPosition) {
20607        if (rangeIsInContainerBlock) {
20608          return range;
20609        }
20610        return null;
20611      }
20612      if (isBeforeContentEditableFalseFn(nextCaretPosition)) {
20613        return showCaret(direction, editor, nextCaretPosition.getNode(!forwards), forwards, true);
20614      }
20615      var peekCaretPosition = getNextPosFn(nextCaretPosition);
20616      if (peekCaretPosition && isBeforeContentEditableFalseFn(peekCaretPosition)) {
20617        if (isMoveInsideSameBlock(nextCaretPosition, peekCaretPosition)) {
20618          return showCaret(direction, editor, peekCaretPosition.getNode(!forwards), forwards, true);
20619        }
20620      }
20621      if (rangeIsInContainerBlock) {
20622        return renderRangeCaret(editor, nextCaretPosition.toRange(), true);
20623      }
20624      return null;
20625    };
20626    var moveToCeFalseVertically = function (direction, editor, walkerFn, range) {
20627      var caretPosition, linePositions, nextLinePositions;
20628      var closestNextLineRect, caretClientRect, clientX;
20629      var dist1, dist2, contentEditableFalseNode;
20630      contentEditableFalseNode = getSelectedNode$1(range);
20631      caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
20632      linePositions = walkerFn(editor.getBody(), isAboveLine(1), caretPosition);
20633      nextLinePositions = filter(linePositions, isLine(1));
20634      caretClientRect = ArrUtils.last(caretPosition.getClientRects());
20635      if (isBeforeContentEditableFalse(caretPosition) || isBeforeTable(caretPosition)) {
20636        contentEditableFalseNode = caretPosition.getNode();
20637      }
20638      if (isAfterContentEditableFalse(caretPosition) || isAfterTable(caretPosition)) {
20639        contentEditableFalseNode = caretPosition.getNode(true);
20640      }
20641      if (!caretClientRect) {
20642        return null;
20643      }
20644      clientX = caretClientRect.left;
20645      closestNextLineRect = findClosestClientRect(nextLinePositions, clientX);
20646      if (closestNextLineRect) {
20647        if (isContentEditableFalse$b(closestNextLineRect.node)) {
20648          dist1 = Math.abs(clientX - closestNextLineRect.left);
20649          dist2 = Math.abs(clientX - closestNextLineRect.right);
20650          return showCaret(direction, editor, closestNextLineRect.node, dist1 < dist2, true);
20651        }
20652      }
20653      if (contentEditableFalseNode) {
20654        var caretPositions = positionsUntil(direction, editor.getBody(), isAboveLine(1), contentEditableFalseNode);
20655        closestNextLineRect = findClosestClientRect(filter(caretPositions, isLine(1)), clientX);
20656        if (closestNextLineRect) {
20657          return renderRangeCaret(editor, closestNextLineRect.position.toRange(), true);
20658        }
20659        closestNextLineRect = ArrUtils.last(filter(caretPositions, isLine(0)));
20660        if (closestNextLineRect) {
20661          return renderRangeCaret(editor, closestNextLineRect.position.toRange(), true);
20662        }
20663      }
20664    };
20665    var createTextBlock = function (editor) {
20666      var textBlock = editor.dom.create(Settings.getForcedRootBlock(editor));
20667      if (!Env.ie || Env.ie >= 11) {
20668        textBlock.innerHTML = '<br data-mce-bogus="1">';
20669      }
20670      return textBlock;
20671    };
20672    var exitPreBlock = function (editor, direction, range) {
20673      var pre, caretPos, newBlock;
20674      var caretWalker = CaretWalker(editor.getBody());
20675      var getNextVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.next);
20676      var getPrevVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.prev);
20677      if (range.collapsed && editor.settings.forced_root_block) {
20678        pre = editor.dom.getParent(range.startContainer, 'PRE');
20679        if (!pre) {
20680          return;
20681        }
20682        if (direction === 1) {
20683          caretPos = getNextVisualCaretPosition(CaretPosition$1.fromRangeStart(range));
20684        } else {
20685          caretPos = getPrevVisualCaretPosition(CaretPosition$1.fromRangeStart(range));
20686        }
20687        if (!caretPos) {
20688          newBlock = createTextBlock(editor);
20689          if (direction === 1) {
20690            editor.$(pre).after(newBlock);
20691          } else {
20692            editor.$(pre).before(newBlock);
20693          }
20694          editor.selection.select(newBlock, true);
20695          editor.selection.collapse();
20696        }
20697      }
20698    };
20699    var getHorizontalRange = function (editor, forward) {
20700      var caretWalker = CaretWalker(editor.getBody());
20701      var getNextVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.next);
20702      var getPrevVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.prev);
20703      var newRange;
20704      var direction = forward ? HDirection.Forwards : HDirection.Backwards;
20705      var getNextPosFn = forward ? getNextVisualCaretPosition : getPrevVisualCaretPosition;
20706      var range = editor.selection.getRng();
20707      newRange = moveToCeFalseHorizontally(direction, editor, getNextPosFn, range);
20708      if (newRange) {
20709        return newRange;
20710      }
20711      newRange = exitPreBlock(editor, direction, range);
20712      if (newRange) {
20713        return newRange;
20714      }
20715      return null;
20716    };
20717    var getVerticalRange = function (editor, down) {
20718      var newRange;
20719      var direction = down ? 1 : -1;
20720      var walkerFn = down ? downUntil : upUntil;
20721      var range = editor.selection.getRng();
20722      newRange = moveToCeFalseVertically(direction, editor, walkerFn, range);
20723      if (newRange) {
20724        return newRange;
20725      }
20726      newRange = exitPreBlock(editor, direction, range);
20727      if (newRange) {
20728        return newRange;
20729      }
20730      return null;
20731    };
20732    var moveH = function (editor, forward) {
20733      return function () {
20734        var newRng = getHorizontalRange(editor, forward);
20735        if (newRng) {
20736          editor.selection.setRng(newRng);
20737          return true;
20738        } else {
20739          return false;
20740        }
20741      };
20742    };
20743    var moveV = function (editor, down) {
20744      return function () {
20745        var newRng = getVerticalRange(editor, down);
20746        if (newRng) {
20747          editor.selection.setRng(newRng);
20748          return true;
20749        } else {
20750          return false;
20751        }
20752      };
20753    };
20754    var isCefPosition = function (forward) {
20755      return function (pos) {
20756        return forward ? isAfterContentEditableFalse(pos) : isBeforeContentEditableFalse(pos);
20757      };
20758    };
20759    var moveToLineEndPoint = function (editor, forward) {
20760      return function () {
20761        var from = forward ? CaretPosition$1.fromRangeEnd(editor.selection.getRng()) : CaretPosition$1.fromRangeStart(editor.selection.getRng());
20762        var result = forward ? getPositionsUntilNextLine(editor.getBody(), from) : getPositionsUntilPreviousLine(editor.getBody(), from);
20763        var to = forward ? last(result.positions) : head(result.positions);
20764        return to.filter(isCefPosition(forward)).fold(constant(false), function (pos) {
20765          editor.selection.setRng(pos.toRange());
20766          return true;
20767        });
20768      };
20769    };
20770
20771    var deflate = function (rect, delta) {
20772      return {
20773        left: rect.left - delta,
20774        top: rect.top - delta,
20775        right: rect.right + delta * 2,
20776        bottom: rect.bottom + delta * 2,
20777        width: rect.width + delta,
20778        height: rect.height + delta
20779      };
20780    };
20781    var getCorners = function (getYAxisValue, tds) {
20782      return bind(tds, function (td) {
20783        var rect = deflate(clone$1(td.getBoundingClientRect()), -1);
20784        return [
20785          {
20786            x: rect.left,
20787            y: getYAxisValue(rect),
20788            cell: td
20789          },
20790          {
20791            x: rect.right,
20792            y: getYAxisValue(rect),
20793            cell: td
20794          }
20795        ];
20796      });
20797    };
20798    var findClosestCorner = function (corners, x, y) {
20799      return foldl(corners, function (acc, newCorner) {
20800        return acc.fold(function () {
20801          return Option.some(newCorner);
20802        }, function (oldCorner) {
20803          var oldDist = Math.sqrt(Math.abs(oldCorner.x - x) + Math.abs(oldCorner.y - y));
20804          var newDist = Math.sqrt(Math.abs(newCorner.x - x) + Math.abs(newCorner.y - y));
20805          return Option.some(newDist < oldDist ? newCorner : oldCorner);
20806        });
20807      }, Option.none());
20808    };
20809    var getClosestCell = function (getYAxisValue, isTargetCorner, table, x, y) {
20810      var cells = descendants$1(Element.fromDom(table), 'td,th,caption').map(function (e) {
20811        return e.dom();
20812      });
20813      var corners = filter(getCorners(getYAxisValue, cells), function (corner) {
20814        return isTargetCorner(corner, y);
20815      });
20816      return findClosestCorner(corners, x, y).map(function (corner) {
20817        return corner.cell;
20818      });
20819    };
20820    var getBottomValue = function (rect) {
20821      return rect.bottom;
20822    };
20823    var getTopValue = function (rect) {
20824      return rect.top;
20825    };
20826    var isAbove$1 = function (corner, y) {
20827      return corner.y < y;
20828    };
20829    var isBelow$1 = function (corner, y) {
20830      return corner.y > y;
20831    };
20832    var getClosestCellAbove = curry(getClosestCell, getBottomValue, isAbove$1);
20833    var getClosestCellBelow = curry(getClosestCell, getTopValue, isBelow$1);
20834    var findClosestPositionInAboveCell = function (table, pos) {
20835      return head(pos.getClientRects()).bind(function (rect) {
20836        return getClosestCellAbove(table, rect.left, rect.top);
20837      }).bind(function (cell) {
20838        return findClosestHorizontalPosition(getLastLinePositions(cell), pos);
20839      });
20840    };
20841    var findClosestPositionInBelowCell = function (table, pos) {
20842      return last(pos.getClientRects()).bind(function (rect) {
20843        return getClosestCellBelow(table, rect.left, rect.top);
20844      }).bind(function (cell) {
20845        return findClosestHorizontalPosition(getFirstLinePositions(cell), pos);
20846      });
20847    };
20848
20849    var moveToRange = function (editor, rng) {
20850      editor.selection.setRng(rng);
20851      ScrollIntoView.scrollRangeIntoView(editor, rng);
20852    };
20853    var hasNextBreak = function (getPositionsUntil, scope, lineInfo) {
20854      return lineInfo.breakAt.map(function (breakPos) {
20855        return getPositionsUntil(scope, breakPos).breakAt.isSome();
20856      }).getOr(false);
20857    };
20858    var startsWithWrapBreak = function (lineInfo) {
20859      return lineInfo.breakType === BreakType.Wrap && lineInfo.positions.length === 0;
20860    };
20861    var startsWithBrBreak = function (lineInfo) {
20862      return lineInfo.breakType === BreakType.Br && lineInfo.positions.length === 1;
20863    };
20864    var isAtTableCellLine = function (getPositionsUntil, scope, pos) {
20865      var lineInfo = getPositionsUntil(scope, pos);
20866      if (startsWithWrapBreak(lineInfo) || !NodeType.isBr(pos.getNode()) && startsWithBrBreak(lineInfo)) {
20867        return !hasNextBreak(getPositionsUntil, scope, lineInfo);
20868      } else {
20869        return lineInfo.breakAt.isNone();
20870      }
20871    };
20872    var isAtFirstTableCellLine = curry(isAtTableCellLine, getPositionsUntilPreviousLine);
20873    var isAtLastTableCellLine = curry(isAtTableCellLine, getPositionsUntilNextLine);
20874    var isCaretAtStartOrEndOfTable = function (forward, rng, table) {
20875      var caretPos = CaretPosition$1.fromRangeStart(rng);
20876      return CaretFinder.positionIn(!forward, table).map(function (pos) {
20877        return pos.isEqual(caretPos);
20878      }).getOr(false);
20879    };
20880    var navigateHorizontally = function (editor, forward, table, td) {
20881      var rng = editor.selection.getRng();
20882      var direction = forward ? 1 : -1;
20883      if (isFakeCaretTableBrowser() && isCaretAtStartOrEndOfTable(forward, rng, table)) {
20884        var newRng = showCaret(direction, editor, table, !forward, true);
20885        moveToRange(editor, newRng);
20886        return true;
20887      }
20888      return false;
20889    };
20890    var getClosestAbovePosition = function (root, table, start) {
20891      return findClosestPositionInAboveCell(table, start).orThunk(function () {
20892        return head(start.getClientRects()).bind(function (rect) {
20893          return findClosestHorizontalPositionFromPoint(getPositionsAbove(root, CaretPosition$1.before(table)), rect.left);
20894        });
20895      }).getOr(CaretPosition$1.before(table));
20896    };
20897    var getClosestBelowPosition = function (root, table, start) {
20898      return findClosestPositionInBelowCell(table, start).orThunk(function () {
20899        return head(start.getClientRects()).bind(function (rect) {
20900          return findClosestHorizontalPositionFromPoint(getPositionsBelow(root, CaretPosition$1.after(table)), rect.left);
20901        });
20902      }).getOr(CaretPosition$1.after(table));
20903    };
20904    var getTable = function (previous, pos) {
20905      var node = pos.getNode(previous);
20906      return NodeType.isElement(node) && node.nodeName === 'TABLE' ? Option.some(node) : Option.none();
20907    };
20908    var renderBlock = function (down, editor, table, pos) {
20909      var forcedRootBlock = Settings.getForcedRootBlock(editor);
20910      if (forcedRootBlock) {
20911        editor.undoManager.transact(function () {
20912          var element = Element.fromTag(forcedRootBlock);
20913          setAll(element, Settings.getForcedRootBlockAttrs(editor));
20914          append(element, Element.fromTag('br'));
20915          if (down) {
20916            after(Element.fromDom(table), element);
20917          } else {
20918            before(Element.fromDom(table), element);
20919          }
20920          var rng = editor.dom.createRng();
20921          rng.setStart(element.dom(), 0);
20922          rng.setEnd(element.dom(), 0);
20923          moveToRange(editor, rng);
20924        });
20925      } else {
20926        moveToRange(editor, pos.toRange());
20927      }
20928    };
20929    var moveCaret = function (editor, down, pos) {
20930      var table = down ? getTable(true, pos) : getTable(false, pos);
20931      var last = down === false;
20932      table.fold(function () {
20933        return moveToRange(editor, pos.toRange());
20934      }, function (table) {
20935        return CaretFinder.positionIn(last, editor.getBody()).filter(function (lastPos) {
20936          return lastPos.isEqual(pos);
20937        }).fold(function () {
20938          return moveToRange(editor, pos.toRange());
20939        }, function (_) {
20940          return renderBlock(down, editor, table, pos);
20941        });
20942      });
20943    };
20944    var navigateVertically = function (editor, down, table, td) {
20945      var rng = editor.selection.getRng();
20946      var pos = CaretPosition$1.fromRangeStart(rng);
20947      var root = editor.getBody();
20948      if (!down && isAtFirstTableCellLine(td, pos)) {
20949        var newPos = getClosestAbovePosition(root, table, pos);
20950        moveCaret(editor, down, newPos);
20951        return true;
20952      } else if (down && isAtLastTableCellLine(td, pos)) {
20953        var newPos = getClosestBelowPosition(root, table, pos);
20954        moveCaret(editor, down, newPos);
20955        return true;
20956      } else {
20957        return false;
20958      }
20959    };
20960    var moveH$1 = function (editor, forward) {
20961      return function () {
20962        return Option.from(editor.dom.getParent(editor.selection.getNode(), 'td,th')).bind(function (td) {
20963          return Option.from(editor.dom.getParent(td, 'table')).map(function (table) {
20964            return navigateHorizontally(editor, forward, table, td);
20965          });
20966        }).getOr(false);
20967      };
20968    };
20969    var moveV$1 = function (editor, forward) {
20970      return function () {
20971        return Option.from(editor.dom.getParent(editor.selection.getNode(), 'td,th')).bind(function (td) {
20972          return Option.from(editor.dom.getParent(td, 'table')).map(function (table) {
20973            return navigateVertically(editor, forward, table, td);
20974          });
20975        }).getOr(false);
20976      };
20977    };
20978
20979    var isTarget = function (node) {
20980      return contains(['figcaption'], name(node));
20981    };
20982    var rangeBefore = function (target) {
20983      var rng = domGlobals.document.createRange();
20984      rng.setStartBefore(target.dom());
20985      rng.setEndBefore(target.dom());
20986      return rng;
20987    };
20988    var insertElement = function (root, elm, forward) {
20989      if (forward) {
20990        append(root, elm);
20991      } else {
20992        prepend(root, elm);
20993      }
20994    };
20995    var insertBr = function (root, forward) {
20996      var br = Element.fromTag('br');
20997      insertElement(root, br, forward);
20998      return rangeBefore(br);
20999    };
21000    var insertBlock$1 = function (root, forward, blockName, attrs) {
21001      var block = Element.fromTag(blockName);
21002      var br = Element.fromTag('br');
21003      setAll(block, attrs);
21004      append(block, br);
21005      insertElement(root, block, forward);
21006      return rangeBefore(br);
21007    };
21008    var insertEmptyLine = function (root, rootBlockName, attrs, forward) {
21009      if (rootBlockName === '') {
21010        return insertBr(root, forward);
21011      } else {
21012        return insertBlock$1(root, forward, rootBlockName, attrs);
21013      }
21014    };
21015    var getClosestTargetBlock = function (pos, root) {
21016      var isRoot = curry(eq, root);
21017      return closest(Element.fromDom(pos.container()), isBlock, isRoot).filter(isTarget);
21018    };
21019    var isAtFirstOrLastLine = function (root, forward, pos) {
21020      return forward ? isAtLastLine(root.dom(), pos) : isAtFirstLine(root.dom(), pos);
21021    };
21022    var moveCaretToNewEmptyLine = function (editor, forward) {
21023      var root = Element.fromDom(editor.getBody());
21024      var pos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
21025      var rootBlock = Settings.getForcedRootBlock(editor);
21026      var rootBlockAttrs = Settings.getForcedRootBlockAttrs(editor);
21027      return getClosestTargetBlock(pos, root).exists(function () {
21028        if (isAtFirstOrLastLine(root, forward, pos)) {
21029          var rng = insertEmptyLine(root, rootBlock, rootBlockAttrs, forward);
21030          editor.selection.setRng(rng);
21031          return true;
21032        } else {
21033          return false;
21034        }
21035      });
21036    };
21037    var moveV$2 = function (editor, forward) {
21038      return function () {
21039        if (editor.selection.isCollapsed()) {
21040          return moveCaretToNewEmptyLine(editor, forward);
21041        } else {
21042          return false;
21043        }
21044      };
21045    };
21046
21047    var defaultPatterns = function (patterns) {
21048      return map(patterns, function (pattern) {
21049        return merge({
21050          shiftKey: false,
21051          altKey: false,
21052          ctrlKey: false,
21053          metaKey: false,
21054          keyCode: 0,
21055          action: noop
21056        }, pattern);
21057      });
21058    };
21059    var matchesEvent = function (pattern, evt) {
21060      return evt.keyCode === pattern.keyCode && evt.shiftKey === pattern.shiftKey && evt.altKey === pattern.altKey && evt.ctrlKey === pattern.ctrlKey && evt.metaKey === pattern.metaKey;
21061    };
21062    var match$1 = function (patterns, evt) {
21063      return bind(defaultPatterns(patterns), function (pattern) {
21064        return matchesEvent(pattern, evt) ? [pattern] : [];
21065      });
21066    };
21067    var action = function (f) {
21068      var x = [];
21069      for (var _i = 1; _i < arguments.length; _i++) {
21070        x[_i - 1] = arguments[_i];
21071      }
21072      var args = Array.prototype.slice.call(arguments, 1);
21073      return function () {
21074        return f.apply(null, args);
21075      };
21076    };
21077    var execute = function (patterns, evt) {
21078      return find(match$1(patterns, evt), function (pattern) {
21079        return pattern.action();
21080      });
21081    };
21082    var MatchKeys = {
21083      match: match$1,
21084      action: action,
21085      execute: execute
21086    };
21087
21088    var executeKeydownOverride = function (editor, caret, evt) {
21089      var os = PlatformDetection$1.detect().os;
21090      MatchKeys.execute([
21091        {
21092          keyCode: VK.RIGHT,
21093          action: moveH(editor, true)
21094        },
21095        {
21096          keyCode: VK.LEFT,
21097          action: moveH(editor, false)
21098        },
21099        {
21100          keyCode: VK.UP,
21101          action: moveV(editor, false)
21102        },
21103        {
21104          keyCode: VK.DOWN,
21105          action: moveV(editor, true)
21106        },
21107        {
21108          keyCode: VK.RIGHT,
21109          action: moveH$1(editor, true)
21110        },
21111        {
21112          keyCode: VK.LEFT,
21113          action: moveH$1(editor, false)
21114        },
21115        {
21116          keyCode: VK.UP,
21117          action: moveV$1(editor, false)
21118        },
21119        {
21120          keyCode: VK.DOWN,
21121          action: moveV$1(editor, true)
21122        },
21123        {
21124          keyCode: VK.RIGHT,
21125          action: BoundarySelection.move(editor, caret, true)
21126        },
21127        {
21128          keyCode: VK.LEFT,
21129          action: BoundarySelection.move(editor, caret, false)
21130        },
21131        {
21132          keyCode: VK.RIGHT,
21133          ctrlKey: !os.isOSX(),
21134          altKey: os.isOSX(),
21135          action: BoundarySelection.moveNextWord(editor, caret)
21136        },
21137        {
21138          keyCode: VK.LEFT,
21139          ctrlKey: !os.isOSX(),
21140          altKey: os.isOSX(),
21141          action: BoundarySelection.movePrevWord(editor, caret)
21142        },
21143        {
21144          keyCode: VK.UP,
21145          action: moveV$2(editor, false)
21146        },
21147        {
21148          keyCode: VK.DOWN,
21149          action: moveV$2(editor, true)
21150        }
21151      ], evt).each(function (_) {
21152        evt.preventDefault();
21153      });
21154    };
21155    var setup$7 = function (editor, caret) {
21156      editor.on('keydown', function (evt) {
21157        if (evt.isDefaultPrevented() === false) {
21158          executeKeydownOverride(editor, caret, evt);
21159        }
21160      });
21161    };
21162    var ArrowKeys = { setup: setup$7 };
21163
21164    var isBeforeRoot = function (rootNode) {
21165      return function (elm) {
21166        return eq(rootNode, Element.fromDom(elm.dom().parentNode));
21167      };
21168    };
21169    var getParentBlock$1 = function (rootNode, elm) {
21170      return contains$3(rootNode, elm) ? closest(elm, function (element) {
21171        return isTextBlock(element) || isListItem(element);
21172      }, isBeforeRoot(rootNode)) : Option.none();
21173    };
21174    var placeCaretInEmptyBody = function (editor) {
21175      var body = editor.getBody();
21176      var node = body.firstChild && editor.dom.isBlock(body.firstChild) ? body.firstChild : body;
21177      editor.selection.setCursorLocation(node, 0);
21178    };
21179    var paddEmptyBody = function (editor) {
21180      if (editor.dom.isEmpty(editor.getBody())) {
21181        editor.setContent('');
21182        placeCaretInEmptyBody(editor);
21183      }
21184    };
21185    var willDeleteLastPositionInElement = function (forward, fromPos, elm) {
21186      return liftN([
21187        CaretFinder.firstPositionIn(elm),
21188        CaretFinder.lastPositionIn(elm)
21189      ], function (firstPos, lastPos) {
21190        var normalizedFirstPos = InlineUtils.normalizePosition(true, firstPos);
21191        var normalizedLastPos = InlineUtils.normalizePosition(false, lastPos);
21192        var normalizedFromPos = InlineUtils.normalizePosition(false, fromPos);
21193        if (forward) {
21194          return CaretFinder.nextPosition(elm, normalizedFromPos).map(function (nextPos) {
21195            return nextPos.isEqual(normalizedLastPos) && fromPos.isEqual(normalizedFirstPos);
21196          }).getOr(false);
21197        } else {
21198          return CaretFinder.prevPosition(elm, normalizedFromPos).map(function (prevPos) {
21199            return prevPos.isEqual(normalizedFirstPos) && fromPos.isEqual(normalizedLastPos);
21200          }).getOr(false);
21201        }
21202      }).getOr(true);
21203    };
21204    var DeleteUtils = {
21205      getParentBlock: getParentBlock$1,
21206      paddEmptyBody: paddEmptyBody,
21207      willDeleteLastPositionInElement: willDeleteLastPositionInElement
21208    };
21209
21210    var BlockPosition = Immutable('block', 'position');
21211    var BlockBoundary = Immutable('from', 'to');
21212    var getBlockPosition = function (rootNode, pos) {
21213      var rootElm = Element.fromDom(rootNode);
21214      var containerElm = Element.fromDom(pos.container());
21215      return DeleteUtils.getParentBlock(rootElm, containerElm).map(function (block) {
21216        return BlockPosition(block, pos);
21217      });
21218    };
21219    var isDifferentBlocks = function (blockBoundary) {
21220      return eq(blockBoundary.from().block(), blockBoundary.to().block()) === false;
21221    };
21222    var hasSameParent = function (blockBoundary) {
21223      return parent(blockBoundary.from().block()).bind(function (parent1) {
21224        return parent(blockBoundary.to().block()).filter(function (parent2) {
21225          return eq(parent1, parent2);
21226        });
21227      }).isSome();
21228    };
21229    var isEditable = function (blockBoundary) {
21230      return NodeType.isContentEditableFalse(blockBoundary.from().block()) === false && NodeType.isContentEditableFalse(blockBoundary.to().block()) === false;
21231    };
21232    var skipLastBr = function (rootNode, forward, blockPosition) {
21233      if (NodeType.isBr(blockPosition.position().getNode()) && Empty.isEmpty(blockPosition.block()) === false) {
21234        return CaretFinder.positionIn(false, blockPosition.block().dom()).bind(function (lastPositionInBlock) {
21235          if (lastPositionInBlock.isEqual(blockPosition.position())) {
21236            return CaretFinder.fromPosition(forward, rootNode, lastPositionInBlock).bind(function (to) {
21237              return getBlockPosition(rootNode, to);
21238            });
21239          } else {
21240            return Option.some(blockPosition);
21241          }
21242        }).getOr(blockPosition);
21243      } else {
21244        return blockPosition;
21245      }
21246    };
21247    var readFromRange = function (rootNode, forward, rng) {
21248      var fromBlockPos = getBlockPosition(rootNode, CaretPosition$1.fromRangeStart(rng));
21249      var toBlockPos = fromBlockPos.bind(function (blockPos) {
21250        return CaretFinder.fromPosition(forward, rootNode, blockPos.position()).bind(function (to) {
21251          return getBlockPosition(rootNode, to).map(function (blockPos) {
21252            return skipLastBr(rootNode, forward, blockPos);
21253          });
21254        });
21255      });
21256      return liftN([
21257        fromBlockPos,
21258        toBlockPos
21259      ], BlockBoundary).filter(function (blockBoundary) {
21260        return isDifferentBlocks(blockBoundary) && hasSameParent(blockBoundary) && isEditable(blockBoundary);
21261      });
21262    };
21263    var read$3 = function (rootNode, forward, rng) {
21264      return rng.collapsed ? readFromRange(rootNode, forward, rng) : Option.none();
21265    };
21266    var BlockMergeBoundary = { read: read$3 };
21267
21268    var getChildrenUntilBlockBoundary = function (block) {
21269      var children$1 = children(block);
21270      return findIndex(children$1, isBlock).fold(function () {
21271        return children$1;
21272      }, function (index) {
21273        return children$1.slice(0, index);
21274      });
21275    };
21276    var extractChildren = function (block) {
21277      var children = getChildrenUntilBlockBoundary(block);
21278      each(children, remove$1);
21279      return children;
21280    };
21281    var removeEmptyRoot = function (rootNode, block) {
21282      var parents = Parents.parentsAndSelf(block, rootNode);
21283      return find(parents.reverse(), Empty.isEmpty).each(remove$1);
21284    };
21285    var isEmptyBefore = function (el) {
21286      return filter(prevSiblings(el), function (el) {
21287        return !Empty.isEmpty(el);
21288      }).length === 0;
21289    };
21290    var nestedBlockMerge = function (rootNode, fromBlock, toBlock, insertionPoint) {
21291      if (Empty.isEmpty(toBlock)) {
21292        PaddingBr.fillWithPaddingBr(toBlock);
21293        return CaretFinder.firstPositionIn(toBlock.dom());
21294      }
21295      if (isEmptyBefore(insertionPoint) && Empty.isEmpty(fromBlock)) {
21296        before(insertionPoint, Element.fromTag('br'));
21297      }
21298      var position = CaretFinder.prevPosition(toBlock.dom(), CaretPosition$1.before(insertionPoint.dom()));
21299      each(extractChildren(fromBlock), function (child) {
21300        before(insertionPoint, child);
21301      });
21302      removeEmptyRoot(rootNode, fromBlock);
21303      return position;
21304    };
21305    var sidelongBlockMerge = function (rootNode, fromBlock, toBlock) {
21306      if (Empty.isEmpty(toBlock)) {
21307        remove$1(toBlock);
21308        if (Empty.isEmpty(fromBlock)) {
21309          PaddingBr.fillWithPaddingBr(fromBlock);
21310        }
21311        return CaretFinder.firstPositionIn(fromBlock.dom());
21312      }
21313      var position = CaretFinder.lastPositionIn(toBlock.dom());
21314      each(extractChildren(fromBlock), function (child) {
21315        append(toBlock, child);
21316      });
21317      removeEmptyRoot(rootNode, fromBlock);
21318      return position;
21319    };
21320    var findInsertionPoint = function (toBlock, block) {
21321      var parentsAndSelf = Parents.parentsAndSelf(block, toBlock);
21322      return Option.from(parentsAndSelf[parentsAndSelf.length - 1]);
21323    };
21324    var getInsertionPoint = function (fromBlock, toBlock) {
21325      return contains$3(toBlock, fromBlock) ? findInsertionPoint(toBlock, fromBlock) : Option.none();
21326    };
21327    var trimBr = function (first, block) {
21328      CaretFinder.positionIn(first, block.dom()).map(function (position) {
21329        return position.getNode();
21330      }).map(Element.fromDom).filter(isBr$1).each(remove$1);
21331    };
21332    var mergeBlockInto = function (rootNode, fromBlock, toBlock) {
21333      trimBr(true, fromBlock);
21334      trimBr(false, toBlock);
21335      return getInsertionPoint(fromBlock, toBlock).fold(curry(sidelongBlockMerge, rootNode, fromBlock, toBlock), curry(nestedBlockMerge, rootNode, fromBlock, toBlock));
21336    };
21337    var mergeBlocks = function (rootNode, forward, block1, block2) {
21338      return forward ? mergeBlockInto(rootNode, block2, block1) : mergeBlockInto(rootNode, block1, block2);
21339    };
21340    var MergeBlocks = { mergeBlocks: mergeBlocks };
21341
21342    var backspaceDelete = function (editor, forward) {
21343      var position;
21344      var rootNode = Element.fromDom(editor.getBody());
21345      position = BlockMergeBoundary.read(rootNode.dom(), forward, editor.selection.getRng()).bind(function (blockBoundary) {
21346        return MergeBlocks.mergeBlocks(rootNode, forward, blockBoundary.from().block(), blockBoundary.to().block());
21347      });
21348      position.each(function (pos) {
21349        editor.selection.setRng(pos.toRange());
21350      });
21351      return position.isSome();
21352    };
21353    var BlockBoundaryDelete = { backspaceDelete: backspaceDelete };
21354
21355    var deleteRangeMergeBlocks = function (rootNode, selection) {
21356      var rng = selection.getRng();
21357      return liftN([
21358        DeleteUtils.getParentBlock(rootNode, Element.fromDom(rng.startContainer)),
21359        DeleteUtils.getParentBlock(rootNode, Element.fromDom(rng.endContainer))
21360      ], function (block1, block2) {
21361        if (eq(block1, block2) === false) {
21362          rng.deleteContents();
21363          MergeBlocks.mergeBlocks(rootNode, true, block1, block2).each(function (pos) {
21364            selection.setRng(pos.toRange());
21365          });
21366          return true;
21367        } else {
21368          return false;
21369        }
21370      }).getOr(false);
21371    };
21372    var isRawNodeInTable = function (root, rawNode) {
21373      var node = Element.fromDom(rawNode);
21374      var isRoot = curry(eq, root);
21375      return ancestor(node, isTableCell, isRoot).isSome();
21376    };
21377    var isSelectionInTable = function (root, rng) {
21378      return isRawNodeInTable(root, rng.startContainer) || isRawNodeInTable(root, rng.endContainer);
21379    };
21380    var isEverythingSelected = function (root, rng) {
21381      var noPrevious = CaretFinder.prevPosition(root.dom(), CaretPosition$1.fromRangeStart(rng)).isNone();
21382      var noNext = CaretFinder.nextPosition(root.dom(), CaretPosition$1.fromRangeEnd(rng)).isNone();
21383      return !isSelectionInTable(root, rng) && noPrevious && noNext;
21384    };
21385    var emptyEditor = function (editor) {
21386      editor.setContent('');
21387      editor.selection.setCursorLocation();
21388      return true;
21389    };
21390    var deleteRange = function (editor) {
21391      var rootNode = Element.fromDom(editor.getBody());
21392      var rng = editor.selection.getRng();
21393      return isEverythingSelected(rootNode, rng) ? emptyEditor(editor) : deleteRangeMergeBlocks(rootNode, editor.selection);
21394    };
21395    var backspaceDelete$1 = function (editor, forward) {
21396      return editor.selection.isCollapsed() ? false : deleteRange(editor);
21397    };
21398    var BlockRangeDelete = { backspaceDelete: backspaceDelete$1 };
21399
21400    var isBr$5 = function (pos) {
21401      return getElementFromPosition(pos).exists(isBr$1);
21402    };
21403    var findBr = function (forward, root, pos) {
21404      var parentBlocks = filter(Parents.parentsAndSelf(Element.fromDom(pos.container()), root), isBlock);
21405      var scope = head(parentBlocks).getOr(root);
21406      return CaretFinder.fromPosition(forward, scope.dom(), pos).filter(isBr$5);
21407    };
21408    var isBeforeBr = function (root, pos) {
21409      return getElementFromPosition(pos).exists(isBr$1) || findBr(true, root, pos).isSome();
21410    };
21411    var isAfterBr = function (root, pos) {
21412      return getElementFromPrevPosition(pos).exists(isBr$1) || findBr(false, root, pos).isSome();
21413    };
21414    var findPreviousBr = curry(findBr, false);
21415    var findNextBr = curry(findBr, true);
21416
21417    var isCompoundElement = function (node) {
21418      return isTableCell(Element.fromDom(node)) || isListItem(Element.fromDom(node));
21419    };
21420    var DeleteAction = Adt.generate([
21421      { remove: ['element'] },
21422      { moveToElement: ['element'] },
21423      { moveToPosition: ['position'] }
21424    ]);
21425    var isAtContentEditableBlockCaret = function (forward, from) {
21426      var elm = from.getNode(forward === false);
21427      var caretLocation = forward ? 'after' : 'before';
21428      return NodeType.isElement(elm) && elm.getAttribute('data-mce-caret') === caretLocation;
21429    };
21430    var isDeleteFromCefDifferentBlocks = function (root, forward, from, to) {
21431      var inSameBlock = function (elm) {
21432        return isInline(Element.fromDom(elm)) && !isInSameBlock(from, to, root);
21433      };
21434      return getRelativeCefElm(!forward, from).fold(function () {
21435        return getRelativeCefElm(forward, to).fold(constant(false), inSameBlock);
21436      }, inSameBlock);
21437    };
21438    var deleteEmptyBlockOrMoveToCef = function (root, forward, from, to) {
21439      var toCefElm = to.getNode(forward === false);
21440      return DeleteUtils.getParentBlock(Element.fromDom(root), Element.fromDom(from.getNode())).map(function (blockElm) {
21441        return Empty.isEmpty(blockElm) ? DeleteAction.remove(blockElm.dom()) : DeleteAction.moveToElement(toCefElm);
21442      }).orThunk(function () {
21443        return Option.some(DeleteAction.moveToElement(toCefElm));
21444      });
21445    };
21446    var findCefPosition = function (root, forward, from) {
21447      return CaretFinder.fromPosition(forward, root, from).bind(function (to) {
21448        if (isCompoundElement(to.getNode())) {
21449          return Option.none();
21450        } else if (isDeleteFromCefDifferentBlocks(root, forward, from, to)) {
21451          return Option.none();
21452        } else if (forward && NodeType.isContentEditableFalse(to.getNode())) {
21453          return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
21454        } else if (forward === false && NodeType.isContentEditableFalse(to.getNode(true))) {
21455          return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
21456        } else if (forward && isAfterContentEditableFalse(from)) {
21457          return Option.some(DeleteAction.moveToPosition(to));
21458        } else if (forward === false && isBeforeContentEditableFalse(from)) {
21459          return Option.some(DeleteAction.moveToPosition(to));
21460        } else {
21461          return Option.none();
21462        }
21463      });
21464    };
21465    var getContentEditableBlockAction = function (forward, elm) {
21466      if (forward && NodeType.isContentEditableFalse(elm.nextSibling)) {
21467        return Option.some(DeleteAction.moveToElement(elm.nextSibling));
21468      } else if (forward === false && NodeType.isContentEditableFalse(elm.previousSibling)) {
21469        return Option.some(DeleteAction.moveToElement(elm.previousSibling));
21470      } else {
21471        return Option.none();
21472      }
21473    };
21474    var skipMoveToActionFromInlineCefToContent = function (root, from, deleteAction) {
21475      return deleteAction.fold(function (elm) {
21476        return Option.some(DeleteAction.remove(elm));
21477      }, function (elm) {
21478        return Option.some(DeleteAction.moveToElement(elm));
21479      }, function (to) {
21480        if (isInSameBlock(from, to, root)) {
21481          return Option.none();
21482        } else {
21483          return Option.some(DeleteAction.moveToPosition(to));
21484        }
21485      });
21486    };
21487    var getContentEditableAction = function (root, forward, from) {
21488      if (isAtContentEditableBlockCaret(forward, from)) {
21489        return getContentEditableBlockAction(forward, from.getNode(forward === false)).fold(function () {
21490          return findCefPosition(root, forward, from);
21491        }, Option.some);
21492      } else {
21493        return findCefPosition(root, forward, from).bind(function (deleteAction) {
21494          return skipMoveToActionFromInlineCefToContent(root, from, deleteAction);
21495        });
21496      }
21497    };
21498    var read$4 = function (root, forward, rng) {
21499      var normalizedRange = normalizeRange(forward ? 1 : -1, root, rng);
21500      var from = CaretPosition$1.fromRangeStart(normalizedRange);
21501      var rootElement = Element.fromDom(root);
21502      if (forward === false && isAfterContentEditableFalse(from)) {
21503        return Option.some(DeleteAction.remove(from.getNode(true)));
21504      } else if (forward && isBeforeContentEditableFalse(from)) {
21505        return Option.some(DeleteAction.remove(from.getNode()));
21506      } else if (forward === false && isBeforeContentEditableFalse(from) && isAfterBr(rootElement, from)) {
21507        return findPreviousBr(rootElement, from).map(function (br) {
21508          return DeleteAction.remove(br.getNode());
21509        });
21510      } else if (forward && isAfterContentEditableFalse(from) && isBeforeBr(rootElement, from)) {
21511        return findNextBr(rootElement, from).map(function (br) {
21512          return DeleteAction.remove(br.getNode());
21513        });
21514      } else {
21515        return getContentEditableAction(root, forward, from);
21516      }
21517    };
21518
21519    var deleteElement$1 = function (editor, forward) {
21520      return function (element) {
21521        editor._selectionOverrides.hideFakeCaret();
21522        DeleteElement.deleteElement(editor, forward, Element.fromDom(element));
21523        return true;
21524      };
21525    };
21526    var moveToElement = function (editor, forward) {
21527      return function (element) {
21528        var pos = forward ? CaretPosition$1.before(element) : CaretPosition$1.after(element);
21529        editor.selection.setRng(pos.toRange());
21530        return true;
21531      };
21532    };
21533    var moveToPosition = function (editor) {
21534      return function (pos) {
21535        editor.selection.setRng(pos.toRange());
21536        return true;
21537      };
21538    };
21539    var backspaceDeleteCaret = function (editor, forward) {
21540      var result = read$4(editor.getBody(), forward, editor.selection.getRng()).map(function (deleteAction) {
21541        return deleteAction.fold(deleteElement$1(editor, forward), moveToElement(editor, forward), moveToPosition(editor));
21542      });
21543      return result.getOr(false);
21544    };
21545    var deleteOffscreenSelection = function (rootElement) {
21546      each(descendants$1(rootElement, '.mce-offscreen-selection'), remove$1);
21547    };
21548    var backspaceDeleteRange = function (editor, forward) {
21549      var selectedElement = editor.selection.getNode();
21550      if (NodeType.isContentEditableFalse(selectedElement)) {
21551        deleteOffscreenSelection(Element.fromDom(editor.getBody()));
21552        DeleteElement.deleteElement(editor, forward, Element.fromDom(editor.selection.getNode()));
21553        DeleteUtils.paddEmptyBody(editor);
21554        return true;
21555      } else {
21556        return false;
21557      }
21558    };
21559    var getContentEditableRoot$2 = function (root, node) {
21560      while (node && node !== root) {
21561        if (NodeType.isContentEditableTrue(node) || NodeType.isContentEditableFalse(node)) {
21562          return node;
21563        }
21564        node = node.parentNode;
21565      }
21566      return null;
21567    };
21568    var paddEmptyElement = function (editor) {
21569      var br;
21570      var ceRoot = getContentEditableRoot$2(editor.getBody(), editor.selection.getNode());
21571      if (NodeType.isContentEditableTrue(ceRoot) && editor.dom.isBlock(ceRoot) && editor.dom.isEmpty(ceRoot)) {
21572        br = editor.dom.create('br', { 'data-mce-bogus': '1' });
21573        editor.dom.setHTML(ceRoot, '');
21574        ceRoot.appendChild(br);
21575        editor.selection.setRng(CaretPosition$1.before(br).toRange());
21576      }
21577      return true;
21578    };
21579    var backspaceDelete$2 = function (editor, forward) {
21580      if (editor.selection.isCollapsed()) {
21581        return backspaceDeleteCaret(editor, forward);
21582      } else {
21583        return backspaceDeleteRange(editor, forward);
21584      }
21585    };
21586    var CefDelete = {
21587      backspaceDelete: backspaceDelete$2,
21588      paddEmptyElement: paddEmptyElement
21589    };
21590
21591    var trimEmptyTextNode$1 = function (dom, node) {
21592      if (NodeType.isText(node) && node.data.length === 0) {
21593        dom.remove(node);
21594      }
21595    };
21596    var deleteContentAndShowCaret = function (editor, range, node, direction, forward, peekCaretPosition) {
21597      var caretRange = showCaret(direction, editor, peekCaretPosition.getNode(!forward), forward, true);
21598      if (range.collapsed) {
21599        var deleteRange = range.cloneRange();
21600        if (forward) {
21601          deleteRange.setEnd(caretRange.startContainer, caretRange.startOffset);
21602        } else {
21603          deleteRange.setStart(caretRange.endContainer, caretRange.endOffset);
21604        }
21605        deleteRange.deleteContents();
21606      } else {
21607        range.deleteContents();
21608      }
21609      editor.selection.setRng(caretRange);
21610      trimEmptyTextNode$1(editor.dom, node);
21611      return true;
21612    };
21613    var deleteCefBoundaryText = function (editor, forward) {
21614      var range = editor.selection.getRng();
21615      if (!NodeType.isText(range.commonAncestorContainer)) {
21616        return false;
21617      }
21618      var direction = forward ? HDirection.Forwards : HDirection.Backwards;
21619      var caretWalker = CaretWalker(editor.getBody());
21620      var getNextVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.next);
21621      var getPrevVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.prev);
21622      var getNextPosFn = forward ? getNextVisualCaretPosition : getPrevVisualCaretPosition;
21623      var isBeforeContentEditableFalseFn = forward ? isBeforeContentEditableFalse : isAfterContentEditableFalse;
21624      var caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
21625      var nextCaretPosition = InlineUtils.normalizePosition(forward, getNextPosFn(caretPosition));
21626      if (!nextCaretPosition) {
21627        return false;
21628      } else if (isBeforeContentEditableFalseFn(nextCaretPosition)) {
21629        return deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, nextCaretPosition);
21630      }
21631      var peekCaretPosition = getNextPosFn(nextCaretPosition);
21632      if (peekCaretPosition && isBeforeContentEditableFalseFn(peekCaretPosition)) {
21633        if (isMoveInsideSameBlock(nextCaretPosition, peekCaretPosition)) {
21634          return deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, peekCaretPosition);
21635        }
21636      }
21637      return false;
21638    };
21639    var backspaceDelete$3 = function (editor, forward) {
21640      return deleteCefBoundaryText(editor, forward);
21641    };
21642    var CefBoundaryDelete = { backspaceDelete: backspaceDelete$3 };
21643
21644    var isFeatureEnabled$1 = function (editor) {
21645      return editor.settings.inline_boundaries !== false;
21646    };
21647    var rangeFromPositions = function (from, to) {
21648      var range = domGlobals.document.createRange();
21649      range.setStart(from.container(), from.offset());
21650      range.setEnd(to.container(), to.offset());
21651      return range;
21652    };
21653    var hasOnlyTwoOrLessPositionsLeft = function (elm) {
21654      return liftN([
21655        CaretFinder.firstPositionIn(elm),
21656        CaretFinder.lastPositionIn(elm)
21657      ], function (firstPos, lastPos) {
21658        var normalizedFirstPos = InlineUtils.normalizePosition(true, firstPos);
21659        var normalizedLastPos = InlineUtils.normalizePosition(false, lastPos);
21660        return CaretFinder.nextPosition(elm, normalizedFirstPos).map(function (pos) {
21661          return pos.isEqual(normalizedLastPos);
21662        }).getOr(true);
21663      }).getOr(true);
21664    };
21665    var setCaretLocation = function (editor, caret) {
21666      return function (location) {
21667        return BoundaryCaret.renderCaret(caret, location).map(function (pos) {
21668          BoundarySelection.setCaretPosition(editor, pos);
21669          return true;
21670        }).getOr(false);
21671      };
21672    };
21673    var deleteFromTo = function (editor, caret, from, to) {
21674      var rootNode = editor.getBody();
21675      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
21676      editor.undoManager.ignore(function () {
21677        editor.selection.setRng(rangeFromPositions(from, to));
21678        editor.execCommand('Delete');
21679        BoundaryLocation.readLocation(isInlineTarget, rootNode, CaretPosition$1.fromRangeStart(editor.selection.getRng())).map(BoundaryLocation.inside).map(setCaretLocation(editor, caret));
21680      });
21681      editor.nodeChanged();
21682    };
21683    var rescope$1 = function (rootNode, node) {
21684      var parentBlock = getParentBlock(node, rootNode);
21685      return parentBlock ? parentBlock : rootNode;
21686    };
21687    var backspaceDeleteCollapsed = function (editor, caret, forward, from) {
21688      var rootNode = rescope$1(editor.getBody(), from.container());
21689      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
21690      var fromLocation = BoundaryLocation.readLocation(isInlineTarget, rootNode, from);
21691      return fromLocation.bind(function (location) {
21692        if (forward) {
21693          return location.fold(constant(Option.some(BoundaryLocation.inside(location))), Option.none, constant(Option.some(BoundaryLocation.outside(location))), Option.none);
21694        } else {
21695          return location.fold(Option.none, constant(Option.some(BoundaryLocation.outside(location))), Option.none, constant(Option.some(BoundaryLocation.inside(location))));
21696        }
21697      }).map(setCaretLocation(editor, caret)).getOrThunk(function () {
21698        var toPosition = CaretFinder.navigate(forward, rootNode, from);
21699        var toLocation = toPosition.bind(function (pos) {
21700          return BoundaryLocation.readLocation(isInlineTarget, rootNode, pos);
21701        });
21702        if (fromLocation.isSome() && toLocation.isSome()) {
21703          return InlineUtils.findRootInline(isInlineTarget, rootNode, from).map(function (elm) {
21704            if (hasOnlyTwoOrLessPositionsLeft(elm)) {
21705              DeleteElement.deleteElement(editor, forward, Element.fromDom(elm));
21706              return true;
21707            } else {
21708              return false;
21709            }
21710          }).getOr(false);
21711        } else {
21712          return toLocation.bind(function (_) {
21713            return toPosition.map(function (to) {
21714              if (forward) {
21715                deleteFromTo(editor, caret, from, to);
21716              } else {
21717                deleteFromTo(editor, caret, to, from);
21718              }
21719              return true;
21720            });
21721          }).getOr(false);
21722        }
21723      });
21724    };
21725    var backspaceDelete$4 = function (editor, caret, forward) {
21726      if (editor.selection.isCollapsed() && isFeatureEnabled$1(editor)) {
21727        var from = CaretPosition$1.fromRangeStart(editor.selection.getRng());
21728        return backspaceDeleteCollapsed(editor, caret, forward, from);
21729      }
21730      return false;
21731    };
21732    var BoundaryDelete = { backspaceDelete: backspaceDelete$4 };
21733
21734    var getParentInlines = function (rootElm, startElm) {
21735      var parents = Parents.parentsAndSelf(startElm, rootElm);
21736      return findIndex(parents, isBlock).fold(constant(parents), function (index) {
21737        return parents.slice(0, index);
21738      });
21739    };
21740    var hasOnlyOneChild = function (elm) {
21741      return children(elm).length === 1;
21742    };
21743    var deleteLastPosition = function (forward, editor, target, parentInlines) {
21744      var isFormatElement$1 = curry(isFormatElement, editor);
21745      var formatNodes = map(filter(parentInlines, isFormatElement$1), function (elm) {
21746        return elm.dom();
21747      });
21748      if (formatNodes.length === 0) {
21749        DeleteElement.deleteElement(editor, forward, target);
21750      } else {
21751        var pos = replaceWithCaretFormat(target.dom(), formatNodes);
21752        editor.selection.setRng(pos.toRange());
21753      }
21754    };
21755    var deleteCaret = function (editor, forward) {
21756      var rootElm = Element.fromDom(editor.getBody());
21757      var startElm = Element.fromDom(editor.selection.getStart());
21758      var parentInlines = filter(getParentInlines(rootElm, startElm), hasOnlyOneChild);
21759      return last(parentInlines).map(function (target) {
21760        var fromPos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
21761        if (DeleteUtils.willDeleteLastPositionInElement(forward, fromPos, target.dom()) && !isEmptyCaretFormatElement(target)) {
21762          deleteLastPosition(forward, editor, target, parentInlines);
21763          return true;
21764        } else {
21765          return false;
21766        }
21767      }).getOr(false);
21768    };
21769    var backspaceDelete$5 = function (editor, forward) {
21770      return editor.selection.isCollapsed() ? deleteCaret(editor, forward) : false;
21771    };
21772    var InlineFormatDelete = { backspaceDelete: backspaceDelete$5 };
21773
21774    var tableCellRng = Immutable('start', 'end');
21775    var tableSelection = Immutable('rng', 'table', 'cells');
21776    var deleteAction = Adt.generate([
21777      { removeTable: ['element'] },
21778      { emptyCells: ['cells'] }
21779    ]);
21780    var isRootFromElement = function (root) {
21781      return curry(eq, root);
21782    };
21783    var getClosestCell$1 = function (container, isRoot) {
21784      return closest$1(Element.fromDom(container), 'td,th', isRoot);
21785    };
21786    var getClosestTable = function (cell, isRoot) {
21787      return ancestor$1(cell, 'table', isRoot);
21788    };
21789    var isExpandedCellRng = function (cellRng) {
21790      return eq(cellRng.start(), cellRng.end()) === false;
21791    };
21792    var getTableFromCellRng = function (cellRng, isRoot) {
21793      return getClosestTable(cellRng.start(), isRoot).bind(function (startParentTable) {
21794        return getClosestTable(cellRng.end(), isRoot).bind(function (endParentTable) {
21795          return eq(startParentTable, endParentTable) ? Option.some(startParentTable) : Option.none();
21796        });
21797      });
21798    };
21799    var getTableCells = function (table) {
21800      return descendants$1(table, 'td,th');
21801    };
21802    var getCellRangeFromStartTable = function (cellRng, isRoot) {
21803      return getClosestTable(cellRng.start(), isRoot).bind(function (table) {
21804        return last(getTableCells(table)).map(function (endCell) {
21805          return tableCellRng(cellRng.start(), endCell);
21806        });
21807      });
21808    };
21809    var partialSelection = function (isRoot, rng) {
21810      var startCell = getClosestCell$1(rng.startContainer, isRoot);
21811      var endCell = getClosestCell$1(rng.endContainer, isRoot);
21812      return rng.collapsed ? Option.none() : liftN([
21813        startCell,
21814        endCell
21815      ], tableCellRng).fold(function () {
21816        return startCell.fold(function () {
21817          return endCell.bind(function (endCell) {
21818            return getClosestTable(endCell, isRoot).bind(function (table) {
21819              return head(getTableCells(table)).map(function (startCell) {
21820                return tableCellRng(startCell, endCell);
21821              });
21822            });
21823          });
21824        }, function (startCell) {
21825          return getClosestTable(startCell, isRoot).bind(function (table) {
21826            return last(getTableCells(table)).map(function (endCell) {
21827              return tableCellRng(startCell, endCell);
21828            });
21829          });
21830        });
21831      }, function (cellRng) {
21832        return isWithinSameTable(isRoot, cellRng) ? Option.none() : getCellRangeFromStartTable(cellRng, isRoot);
21833      });
21834    };
21835    var isWithinSameTable = function (isRoot, cellRng) {
21836      return getTableFromCellRng(cellRng, isRoot).isSome();
21837    };
21838    var getCellRng = function (rng, isRoot) {
21839      var startCell = getClosestCell$1(rng.startContainer, isRoot);
21840      var endCell = getClosestCell$1(rng.endContainer, isRoot);
21841      return liftN([
21842        startCell,
21843        endCell
21844      ], tableCellRng).filter(isExpandedCellRng).filter(function (cellRng) {
21845        return isWithinSameTable(isRoot, cellRng);
21846      }).orThunk(function () {
21847        return partialSelection(isRoot, rng);
21848      });
21849    };
21850    var getTableSelectionFromCellRng = function (cellRng, isRoot) {
21851      return getTableFromCellRng(cellRng, isRoot).map(function (table) {
21852        return tableSelection(cellRng, table, getTableCells(table));
21853      });
21854    };
21855    var getTableSelectionFromRng = function (root, rng) {
21856      var isRoot = isRootFromElement(root);
21857      return getCellRng(rng, isRoot).bind(function (cellRng) {
21858        return getTableSelectionFromCellRng(cellRng, isRoot);
21859      });
21860    };
21861    var getCellIndex = function (cells, cell) {
21862      return findIndex(cells, function (x) {
21863        return eq(x, cell);
21864      });
21865    };
21866    var getSelectedCells = function (tableSelection) {
21867      return liftN([
21868        getCellIndex(tableSelection.cells(), tableSelection.rng().start()),
21869        getCellIndex(tableSelection.cells(), tableSelection.rng().end())
21870      ], function (startIndex, endIndex) {
21871        return tableSelection.cells().slice(startIndex, endIndex + 1);
21872      });
21873    };
21874    var getAction = function (tableSelection) {
21875      return getSelectedCells(tableSelection).map(function (selected) {
21876        var cells = tableSelection.cells();
21877        return selected.length === cells.length ? deleteAction.removeTable(tableSelection.table()) : deleteAction.emptyCells(selected);
21878      });
21879    };
21880    var getActionFromCells = function (cells) {
21881      return deleteAction.emptyCells(cells);
21882    };
21883    var getActionFromRange = function (root, rng) {
21884      return getTableSelectionFromRng(root, rng).bind(getAction);
21885    };
21886    var TableDeleteAction = {
21887      getActionFromRange: getActionFromRange,
21888      getActionFromCells: getActionFromCells
21889    };
21890
21891    var emptyCells = function (editor, cells) {
21892      each(cells, PaddingBr.fillWithPaddingBr);
21893      editor.selection.setCursorLocation(cells[0].dom(), 0);
21894      return true;
21895    };
21896    var deleteTableElement = function (editor, table) {
21897      DeleteElement.deleteElement(editor, false, table);
21898      return true;
21899    };
21900    var deleteCellRange = function (editor, rootElm, rng) {
21901      return TableDeleteAction.getActionFromRange(rootElm, rng).map(function (action) {
21902        return action.fold(curry(deleteTableElement, editor), curry(emptyCells, editor));
21903      });
21904    };
21905    var deleteCaptionRange = function (editor, caption) {
21906      return emptyElement(editor, caption);
21907    };
21908    var deleteTableRange = function (editor, rootElm, rng, startElm) {
21909      return getParentCaption(rootElm, startElm).fold(function () {
21910        return deleteCellRange(editor, rootElm, rng);
21911      }, function (caption) {
21912        return deleteCaptionRange(editor, caption);
21913      }).getOr(false);
21914    };
21915    var deleteRange$1 = function (editor, startElm) {
21916      var rootNode = Element.fromDom(editor.getBody());
21917      var rng = editor.selection.getRng();
21918      var selectedCells = TableCellSelection.getCellsFromEditor(editor);
21919      return selectedCells.length !== 0 ? emptyCells(editor, selectedCells) : deleteTableRange(editor, rootNode, rng, startElm);
21920    };
21921    var getParentCell = function (rootElm, elm) {
21922      return find(Parents.parentsAndSelf(elm, rootElm), isTableCell);
21923    };
21924    var getParentCaption = function (rootElm, elm) {
21925      return find(Parents.parentsAndSelf(elm, rootElm), function (elm) {
21926        return name(elm) === 'caption';
21927      });
21928    };
21929    var deleteBetweenCells = function (editor, rootElm, forward, fromCell, from) {
21930      return CaretFinder.navigate(forward, editor.getBody(), from).bind(function (to) {
21931        return getParentCell(rootElm, Element.fromDom(to.getNode())).map(function (toCell) {
21932          return eq(toCell, fromCell) === false;
21933        });
21934      });
21935    };
21936    var emptyElement = function (editor, elm) {
21937      PaddingBr.fillWithPaddingBr(elm);
21938      editor.selection.setCursorLocation(elm.dom(), 0);
21939      return Option.some(true);
21940    };
21941    var isDeleteOfLastCharPos = function (fromCaption, forward, from, to) {
21942      return CaretFinder.firstPositionIn(fromCaption.dom()).bind(function (first) {
21943        return CaretFinder.lastPositionIn(fromCaption.dom()).map(function (last) {
21944          return forward ? from.isEqual(first) && to.isEqual(last) : from.isEqual(last) && to.isEqual(first);
21945        });
21946      }).getOr(true);
21947    };
21948    var emptyCaretCaption = function (editor, elm) {
21949      return emptyElement(editor, elm);
21950    };
21951    var validateCaretCaption = function (rootElm, fromCaption, to) {
21952      return getParentCaption(rootElm, Element.fromDom(to.getNode())).map(function (toCaption) {
21953        return eq(toCaption, fromCaption) === false;
21954      });
21955    };
21956    var deleteCaretInsideCaption = function (editor, rootElm, forward, fromCaption, from) {
21957      return CaretFinder.navigate(forward, editor.getBody(), from).bind(function (to) {
21958        return isDeleteOfLastCharPos(fromCaption, forward, from, to) ? emptyCaretCaption(editor, fromCaption) : validateCaretCaption(rootElm, fromCaption, to);
21959      }).or(Option.some(true));
21960    };
21961    var deleteCaretCells = function (editor, forward, rootElm, startElm) {
21962      var from = CaretPosition$1.fromRangeStart(editor.selection.getRng());
21963      return getParentCell(rootElm, startElm).bind(function (fromCell) {
21964        return Empty.isEmpty(fromCell) ? emptyElement(editor, fromCell) : deleteBetweenCells(editor, rootElm, forward, fromCell, from);
21965      }).getOr(false);
21966    };
21967    var deleteCaretCaption = function (editor, forward, rootElm, fromCaption) {
21968      var from = CaretPosition$1.fromRangeStart(editor.selection.getRng());
21969      return Empty.isEmpty(fromCaption) ? emptyElement(editor, fromCaption) : deleteCaretInsideCaption(editor, rootElm, forward, fromCaption, from);
21970    };
21971    var isNearTable = function (forward, pos) {
21972      return forward ? isBeforeTable(pos) : isAfterTable(pos);
21973    };
21974    var isBeforeOrAfterTable = function (editor, forward) {
21975      var fromPos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
21976      return isNearTable(forward, fromPos) || CaretFinder.fromPosition(forward, editor.getBody(), fromPos).map(function (pos) {
21977        return isNearTable(forward, pos);
21978      }).getOr(false);
21979    };
21980    var deleteCaret$1 = function (editor, forward, startElm) {
21981      var rootElm = Element.fromDom(editor.getBody());
21982      return getParentCaption(rootElm, startElm).fold(function () {
21983        return deleteCaretCells(editor, forward, rootElm, startElm) || isBeforeOrAfterTable(editor, forward);
21984      }, function (fromCaption) {
21985        return deleteCaretCaption(editor, forward, rootElm, fromCaption).getOr(false);
21986      });
21987    };
21988    var backspaceDelete$6 = function (editor, forward) {
21989      var startElm = Element.fromDom(editor.selection.getStart(true));
21990      var cells = TableCellSelection.getCellsFromEditor(editor);
21991      return editor.selection.isCollapsed() && cells.length === 0 ? deleteCaret$1(editor, forward, startElm) : deleteRange$1(editor, startElm);
21992    };
21993    var TableDelete = { backspaceDelete: backspaceDelete$6 };
21994
21995    var deleteCaret$2 = function (editor, forward) {
21996      var fromPos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
21997      return CaretFinder.fromPosition(forward, editor.getBody(), fromPos).filter(function (pos) {
21998        return forward ? isBeforeImageBlock(pos) : isAfterImageBlock(pos);
21999      }).bind(function (pos) {
22000        return Option.from(getChildNodeAtRelativeOffset(forward ? 0 : -1, pos));
22001      }).map(function (elm) {
22002        editor.selection.select(elm);
22003        return true;
22004      }).getOr(false);
22005    };
22006    var backspaceDelete$7 = function (editor, forward) {
22007      return editor.selection.isCollapsed() ? deleteCaret$2(editor, forward) : false;
22008    };
22009    var PageBreakDelete = { backspaceDelete: backspaceDelete$7 };
22010
22011    var executeKeydownOverride$1 = function (editor, caret, evt) {
22012      MatchKeys.execute([
22013        {
22014          keyCode: VK.BACKSPACE,
22015          action: MatchKeys.action(CefDelete.backspaceDelete, editor, false)
22016        },
22017        {
22018          keyCode: VK.DELETE,
22019          action: MatchKeys.action(CefDelete.backspaceDelete, editor, true)
22020        },
22021        {
22022          keyCode: VK.BACKSPACE,
22023          action: MatchKeys.action(CefBoundaryDelete.backspaceDelete, editor, false)
22024        },
22025        {
22026          keyCode: VK.DELETE,
22027          action: MatchKeys.action(CefBoundaryDelete.backspaceDelete, editor, true)
22028        },
22029        {
22030          keyCode: VK.BACKSPACE,
22031          action: MatchKeys.action(BoundaryDelete.backspaceDelete, editor, caret, false)
22032        },
22033        {
22034          keyCode: VK.DELETE,
22035          action: MatchKeys.action(BoundaryDelete.backspaceDelete, editor, caret, true)
22036        },
22037        {
22038          keyCode: VK.BACKSPACE,
22039          action: MatchKeys.action(TableDelete.backspaceDelete, editor, false)
22040        },
22041        {
22042          keyCode: VK.DELETE,
22043          action: MatchKeys.action(TableDelete.backspaceDelete, editor, true)
22044        },
22045        {
22046          keyCode: VK.BACKSPACE,
22047          action: MatchKeys.action(PageBreakDelete.backspaceDelete, editor, false)
22048        },
22049        {
22050          keyCode: VK.DELETE,
22051          action: MatchKeys.action(PageBreakDelete.backspaceDelete, editor, true)
22052        },
22053        {
22054          keyCode: VK.BACKSPACE,
22055          action: MatchKeys.action(BlockRangeDelete.backspaceDelete, editor, false)
22056        },
22057        {
22058          keyCode: VK.DELETE,
22059          action: MatchKeys.action(BlockRangeDelete.backspaceDelete, editor, true)
22060        },
22061        {
22062          keyCode: VK.BACKSPACE,
22063          action: MatchKeys.action(BlockBoundaryDelete.backspaceDelete, editor, false)
22064        },
22065        {
22066          keyCode: VK.DELETE,
22067          action: MatchKeys.action(BlockBoundaryDelete.backspaceDelete, editor, true)
22068        },
22069        {
22070          keyCode: VK.BACKSPACE,
22071          action: MatchKeys.action(InlineFormatDelete.backspaceDelete, editor, false)
22072        },
22073        {
22074          keyCode: VK.DELETE,
22075          action: MatchKeys.action(InlineFormatDelete.backspaceDelete, editor, true)
22076        }
22077      ], evt).each(function (_) {
22078        evt.preventDefault();
22079      });
22080    };
22081    var executeKeyupOverride = function (editor, evt) {
22082      MatchKeys.execute([
22083        {
22084          keyCode: VK.BACKSPACE,
22085          action: MatchKeys.action(CefDelete.paddEmptyElement, editor)
22086        },
22087        {
22088          keyCode: VK.DELETE,
22089          action: MatchKeys.action(CefDelete.paddEmptyElement, editor)
22090        }
22091      ], evt);
22092    };
22093    var setup$8 = function (editor, caret) {
22094      editor.on('keydown', function (evt) {
22095        if (evt.isDefaultPrevented() === false) {
22096          executeKeydownOverride$1(editor, caret, evt);
22097        }
22098      });
22099      editor.on('keyup', function (evt) {
22100        if (evt.isDefaultPrevented() === false) {
22101          executeKeyupOverride(editor, evt);
22102        }
22103      });
22104    };
22105    var DeleteBackspaceKeys = { setup: setup$8 };
22106
22107    var firstNonWhiteSpaceNodeSibling = function (node) {
22108      while (node) {
22109        if (node.nodeType === 1 || node.nodeType === 3 && node.data && /[\r\n\s]/.test(node.data)) {
22110          return node;
22111        }
22112        node = node.nextSibling;
22113      }
22114    };
22115    var moveToCaretPosition = function (editor, root) {
22116      var node, rng, lastNode = root;
22117      var dom = editor.dom;
22118      var moveCaretBeforeOnEnterElementsMap = editor.schema.getMoveCaretBeforeOnEnterElements();
22119      if (!root) {
22120        return;
22121      }
22122      if (/^(LI|DT|DD)$/.test(root.nodeName)) {
22123        var firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
22124        if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) {
22125          root.insertBefore(dom.doc.createTextNode('\xA0'), root.firstChild);
22126        }
22127      }
22128      rng = dom.createRng();
22129      root.normalize();
22130      if (root.hasChildNodes()) {
22131        var walker = new TreeWalker(root, root);
22132        while (node = walker.current()) {
22133          if (NodeType.isText(node)) {
22134            rng.setStart(node, 0);
22135            rng.setEnd(node, 0);
22136            break;
22137          }
22138          if (moveCaretBeforeOnEnterElementsMap[node.nodeName.toLowerCase()]) {
22139            rng.setStartBefore(node);
22140            rng.setEndBefore(node);
22141            break;
22142          }
22143          lastNode = node;
22144          node = walker.next();
22145        }
22146        if (!node) {
22147          rng.setStart(lastNode, 0);
22148          rng.setEnd(lastNode, 0);
22149        }
22150      } else {
22151        if (NodeType.isBr(root)) {
22152          if (root.nextSibling && dom.isBlock(root.nextSibling)) {
22153            rng.setStartBefore(root);
22154            rng.setEndBefore(root);
22155          } else {
22156            rng.setStartAfter(root);
22157            rng.setEndAfter(root);
22158          }
22159        } else {
22160          rng.setStart(root, 0);
22161          rng.setEnd(root, 0);
22162        }
22163      }
22164      editor.selection.setRng(rng);
22165      editor.selection.scrollIntoView(root);
22166    };
22167    var getEditableRoot = function (dom, node) {
22168      var root = dom.getRoot();
22169      var parent, editableRoot;
22170      parent = node;
22171      while (parent !== root && dom.getContentEditable(parent) !== 'false') {
22172        if (dom.getContentEditable(parent) === 'true') {
22173          editableRoot = parent;
22174        }
22175        parent = parent.parentNode;
22176      }
22177      return parent !== root ? editableRoot : root;
22178    };
22179    var getParentBlock$2 = function (editor) {
22180      return Option.from(editor.dom.getParent(editor.selection.getStart(true), editor.dom.isBlock));
22181    };
22182    var getParentBlockName = function (editor) {
22183      return getParentBlock$2(editor).fold(constant(''), function (parentBlock) {
22184        return parentBlock.nodeName.toUpperCase();
22185      });
22186    };
22187    var isListItemParentBlock = function (editor) {
22188      return getParentBlock$2(editor).filter(function (elm) {
22189        return isListItem(Element.fromDom(elm));
22190      }).isSome();
22191    };
22192    var NewLineUtils = {
22193      moveToCaretPosition: moveToCaretPosition,
22194      getEditableRoot: getEditableRoot,
22195      getParentBlock: getParentBlock$2,
22196      getParentBlockName: getParentBlockName,
22197      isListItemParentBlock: isListItemParentBlock
22198    };
22199
22200    var hasFirstChild = function (elm, name) {
22201      return elm.firstChild && elm.firstChild.nodeName === name;
22202    };
22203    var hasParent$1 = function (elm, parentName) {
22204      return elm && elm.parentNode && elm.parentNode.nodeName === parentName;
22205    };
22206    var isListBlock = function (elm) {
22207      return elm && /^(OL|UL|LI)$/.test(elm.nodeName);
22208    };
22209    var isNestedList = function (elm) {
22210      return isListBlock(elm) && isListBlock(elm.parentNode);
22211    };
22212    var getContainerBlock = function (containerBlock) {
22213      var containerBlockParent = containerBlock.parentNode;
22214      if (/^(LI|DT|DD)$/.test(containerBlockParent.nodeName)) {
22215        return containerBlockParent;
22216      }
22217      return containerBlock;
22218    };
22219    var isFirstOrLastLi = function (containerBlock, parentBlock, first) {
22220      var node = containerBlock[first ? 'firstChild' : 'lastChild'];
22221      while (node) {
22222        if (NodeType.isElement(node)) {
22223          break;
22224        }
22225        node = node[first ? 'nextSibling' : 'previousSibling'];
22226      }
22227      return node === parentBlock;
22228    };
22229    var insert = function (editor, createNewBlock, containerBlock, parentBlock, newBlockName) {
22230      var dom = editor.dom;
22231      var rng = editor.selection.getRng();
22232      if (containerBlock === editor.getBody()) {
22233        return;
22234      }
22235      if (isNestedList(containerBlock)) {
22236        newBlockName = 'LI';
22237      }
22238      var newBlock = newBlockName ? createNewBlock(newBlockName) : dom.create('BR');
22239      if (isFirstOrLastLi(containerBlock, parentBlock, true) && isFirstOrLastLi(containerBlock, parentBlock, false)) {
22240        if (hasParent$1(containerBlock, 'LI')) {
22241          dom.insertAfter(newBlock, getContainerBlock(containerBlock));
22242        } else {
22243          dom.replace(newBlock, containerBlock);
22244        }
22245      } else if (isFirstOrLastLi(containerBlock, parentBlock, true)) {
22246        if (hasParent$1(containerBlock, 'LI')) {
22247          dom.insertAfter(newBlock, getContainerBlock(containerBlock));
22248          newBlock.appendChild(dom.doc.createTextNode(' '));
22249          newBlock.appendChild(containerBlock);
22250        } else {
22251          containerBlock.parentNode.insertBefore(newBlock, containerBlock);
22252        }
22253      } else if (isFirstOrLastLi(containerBlock, parentBlock, false)) {
22254        dom.insertAfter(newBlock, getContainerBlock(containerBlock));
22255      } else {
22256        containerBlock = getContainerBlock(containerBlock);
22257        var tmpRng = rng.cloneRange();
22258        tmpRng.setStartAfter(parentBlock);
22259        tmpRng.setEndAfter(containerBlock);
22260        var fragment = tmpRng.extractContents();
22261        if (newBlockName === 'LI' && hasFirstChild(fragment, 'LI')) {
22262          newBlock = fragment.firstChild;
22263          dom.insertAfter(fragment, containerBlock);
22264        } else {
22265          dom.insertAfter(fragment, containerBlock);
22266          dom.insertAfter(newBlock, containerBlock);
22267        }
22268      }
22269      dom.remove(parentBlock);
22270      NewLineUtils.moveToCaretPosition(editor, newBlock);
22271    };
22272    var InsertLi = { insert: insert };
22273
22274    var trimZwsp = function (fragment) {
22275      each(descendants(Element.fromDom(fragment), isText), function (text) {
22276        var rawNode = text.dom();
22277        rawNode.nodeValue = Zwsp.trim(rawNode.nodeValue);
22278      });
22279    };
22280    var isEmptyAnchor = function (dom, elm) {
22281      return elm && elm.nodeName === 'A' && dom.isEmpty(elm);
22282    };
22283    var isTableCell$4 = function (node) {
22284      return node && /^(TD|TH|CAPTION)$/.test(node.nodeName);
22285    };
22286    var emptyBlock = function (elm) {
22287      elm.innerHTML = '<br data-mce-bogus="1">';
22288    };
22289    var containerAndSiblingName = function (container, nodeName) {
22290      return container.nodeName === nodeName || container.previousSibling && container.previousSibling.nodeName === nodeName;
22291    };
22292    var canSplitBlock = function (dom, node) {
22293      return node && dom.isBlock(node) && !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) && !/^(fixed|absolute)/i.test(node.style.position) && dom.getContentEditable(node) !== 'true';
22294    };
22295    var trimInlineElementsOnLeftSideOfBlock = function (dom, nonEmptyElementsMap, block) {
22296      var node = block;
22297      var firstChilds = [];
22298      var i;
22299      if (!node) {
22300        return;
22301      }
22302      while (node = node.firstChild) {
22303        if (dom.isBlock(node)) {
22304          return;
22305        }
22306        if (NodeType.isElement(node) && !nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
22307          firstChilds.push(node);
22308        }
22309      }
22310      i = firstChilds.length;
22311      while (i--) {
22312        node = firstChilds[i];
22313        if (!node.hasChildNodes() || node.firstChild === node.lastChild && node.firstChild.nodeValue === '') {
22314          dom.remove(node);
22315        } else {
22316          if (isEmptyAnchor(dom, node)) {
22317            dom.remove(node);
22318          }
22319        }
22320      }
22321    };
22322    var normalizeZwspOffset = function (start, container, offset) {
22323      if (NodeType.isText(container) === false) {
22324        return offset;
22325      } else if (start) {
22326        return offset === 1 && container.data.charAt(offset - 1) === Zwsp.ZWSP ? 0 : offset;
22327      } else {
22328        return offset === container.data.length - 1 && container.data.charAt(offset) === Zwsp.ZWSP ? container.data.length : offset;
22329      }
22330    };
22331    var includeZwspInRange = function (rng) {
22332      var newRng = rng.cloneRange();
22333      newRng.setStart(rng.startContainer, normalizeZwspOffset(true, rng.startContainer, rng.startOffset));
22334      newRng.setEnd(rng.endContainer, normalizeZwspOffset(false, rng.endContainer, rng.endOffset));
22335      return newRng;
22336    };
22337    var trimLeadingLineBreaks = function (node) {
22338      do {
22339        if (NodeType.isText(node)) {
22340          node.nodeValue = node.nodeValue.replace(/^[\r\n]+/, '');
22341        }
22342        node = node.firstChild;
22343      } while (node);
22344    };
22345    var getEditableRoot$1 = function (dom, node) {
22346      var root = dom.getRoot();
22347      var parent, editableRoot;
22348      parent = node;
22349      while (parent !== root && dom.getContentEditable(parent) !== 'false') {
22350        if (dom.getContentEditable(parent) === 'true') {
22351          editableRoot = parent;
22352        }
22353        parent = parent.parentNode;
22354      }
22355      return parent !== root ? editableRoot : root;
22356    };
22357    var setForcedBlockAttrs = function (editor, node) {
22358      var forcedRootBlockName = Settings.getForcedRootBlock(editor);
22359      if (forcedRootBlockName && forcedRootBlockName.toLowerCase() === node.tagName.toLowerCase()) {
22360        editor.dom.setAttribs(node, Settings.getForcedRootBlockAttrs(editor));
22361      }
22362    };
22363    var wrapSelfAndSiblingsInDefaultBlock = function (editor, newBlockName, rng, container, offset) {
22364      var newBlock, parentBlock, startNode, node, next, rootBlockName;
22365      var blockName = newBlockName || 'P';
22366      var dom = editor.dom, editableRoot = getEditableRoot$1(dom, container);
22367      parentBlock = dom.getParent(container, dom.isBlock);
22368      if (!parentBlock || !canSplitBlock(dom, parentBlock)) {
22369        parentBlock = parentBlock || editableRoot;
22370        if (parentBlock === editor.getBody() || isTableCell$4(parentBlock)) {
22371          rootBlockName = parentBlock.nodeName.toLowerCase();
22372        } else {
22373          rootBlockName = parentBlock.parentNode.nodeName.toLowerCase();
22374        }
22375        if (!parentBlock.hasChildNodes()) {
22376          newBlock = dom.create(blockName);
22377          setForcedBlockAttrs(editor, newBlock);
22378          parentBlock.appendChild(newBlock);
22379          rng.setStart(newBlock, 0);
22380          rng.setEnd(newBlock, 0);
22381          return newBlock;
22382        }
22383        node = container;
22384        while (node.parentNode !== parentBlock) {
22385          node = node.parentNode;
22386        }
22387        while (node && !dom.isBlock(node)) {
22388          startNode = node;
22389          node = node.previousSibling;
22390        }
22391        if (startNode && editor.schema.isValidChild(rootBlockName, blockName.toLowerCase())) {
22392          newBlock = dom.create(blockName);
22393          setForcedBlockAttrs(editor, newBlock);
22394          startNode.parentNode.insertBefore(newBlock, startNode);
22395          node = startNode;
22396          while (node && !dom.isBlock(node)) {
22397            next = node.nextSibling;
22398            newBlock.appendChild(node);
22399            node = next;
22400          }
22401          rng.setStart(container, offset);
22402          rng.setEnd(container, offset);
22403        }
22404      }
22405      return container;
22406    };
22407    var addBrToBlockIfNeeded = function (dom, block) {
22408      var lastChild;
22409      block.normalize();
22410      lastChild = block.lastChild;
22411      if (!lastChild || /^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true))) {
22412        dom.add(block, 'br');
22413      }
22414    };
22415    var insert$1 = function (editor, evt) {
22416      var tmpRng, editableRoot, container, offset, parentBlock, shiftKey;
22417      var newBlock, fragment, containerBlock, parentBlockName, containerBlockName, newBlockName, isAfterLastNodeInContainer;
22418      var dom = editor.dom;
22419      var schema = editor.schema, nonEmptyElementsMap = schema.getNonEmptyElements();
22420      var rng = editor.selection.getRng();
22421      var createNewBlock = function (name) {
22422        var node = container, block, clonedNode, caretNode;
22423        var textInlineElements = schema.getTextInlineElements();
22424        if (name || parentBlockName === 'TABLE' || parentBlockName === 'HR') {
22425          block = dom.create(name || newBlockName);
22426          setForcedBlockAttrs(editor, block);
22427        } else {
22428          block = parentBlock.cloneNode(false);
22429        }
22430        caretNode = block;
22431        if (Settings.shouldKeepStyles(editor) === false) {
22432          dom.setAttrib(block, 'style', null);
22433          dom.setAttrib(block, 'class', null);
22434        } else {
22435          do {
22436            if (textInlineElements[node.nodeName]) {
22437              if (isCaretNode(node) || Bookmarks.isBookmarkNode(node)) {
22438                continue;
22439              }
22440              clonedNode = node.cloneNode(false);
22441              dom.setAttrib(clonedNode, 'id', '');
22442              if (block.hasChildNodes()) {
22443                clonedNode.appendChild(block.firstChild);
22444                block.appendChild(clonedNode);
22445              } else {
22446                caretNode = clonedNode;
22447                block.appendChild(clonedNode);
22448              }
22449            }
22450          } while ((node = node.parentNode) && node !== editableRoot);
22451        }
22452        emptyBlock(caretNode);
22453        return block;
22454      };
22455      var isCaretAtStartOrEndOfBlock = function (start) {
22456        var node, name;
22457        var normalizedOffset = normalizeZwspOffset(start, container, offset);
22458        if (NodeType.isText(container) && (start ? normalizedOffset > 0 : normalizedOffset < container.nodeValue.length)) {
22459          return false;
22460        }
22461        if (container.parentNode === parentBlock && isAfterLastNodeInContainer && !start) {
22462          return true;
22463        }
22464        if (start && NodeType.isElement(container) && container === parentBlock.firstChild) {
22465          return true;
22466        }
22467        if (containerAndSiblingName(container, 'TABLE') || containerAndSiblingName(container, 'HR')) {
22468          return isAfterLastNodeInContainer && !start || !isAfterLastNodeInContainer && start;
22469        }
22470        var walker = new TreeWalker(container, parentBlock);
22471        if (NodeType.isText(container)) {
22472          if (start && normalizedOffset === 0) {
22473            walker.prev();
22474          } else if (!start && normalizedOffset === container.nodeValue.length) {
22475            walker.next();
22476          }
22477        }
22478        while (node = walker.current()) {
22479          if (NodeType.isElement(node)) {
22480            if (!node.getAttribute('data-mce-bogus')) {
22481              name = node.nodeName.toLowerCase();
22482              if (nonEmptyElementsMap[name] && name !== 'br') {
22483                return false;
22484              }
22485            }
22486          } else if (NodeType.isText(node) && !/^[ \t\r\n]*$/.test(node.nodeValue)) {
22487            return false;
22488          }
22489          if (start) {
22490            walker.prev();
22491          } else {
22492            walker.next();
22493          }
22494        }
22495        return true;
22496      };
22497      var insertNewBlockAfter = function () {
22498        if (/^(H[1-6]|PRE|FIGURE)$/.test(parentBlockName) && containerBlockName !== 'HGROUP') {
22499          newBlock = createNewBlock(newBlockName);
22500        } else {
22501          newBlock = createNewBlock();
22502        }
22503        if (Settings.shouldEndContainerOnEmptyBlock(editor) && canSplitBlock(dom, containerBlock) && dom.isEmpty(parentBlock)) {
22504          newBlock = dom.split(containerBlock, parentBlock);
22505        } else {
22506          dom.insertAfter(newBlock, parentBlock);
22507        }
22508        NewLineUtils.moveToCaretPosition(editor, newBlock);
22509      };
22510      NormalizeRange.normalize(dom, rng).each(function (normRng) {
22511        rng.setStart(normRng.startContainer, normRng.startOffset);
22512        rng.setEnd(normRng.endContainer, normRng.endOffset);
22513      });
22514      container = rng.startContainer;
22515      offset = rng.startOffset;
22516      newBlockName = Settings.getForcedRootBlock(editor);
22517      shiftKey = !!(evt && evt.shiftKey);
22518      var ctrlKey = !!(evt && evt.ctrlKey);
22519      if (NodeType.isElement(container) && container.hasChildNodes()) {
22520        isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
22521        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
22522        if (isAfterLastNodeInContainer && NodeType.isText(container)) {
22523          offset = container.nodeValue.length;
22524        } else {
22525          offset = 0;
22526        }
22527      }
22528      editableRoot = getEditableRoot$1(dom, container);
22529      if (!editableRoot) {
22530        return;
22531      }
22532      if (newBlockName && !shiftKey || !newBlockName && shiftKey) {
22533        container = wrapSelfAndSiblingsInDefaultBlock(editor, newBlockName, rng, container, offset);
22534      }
22535      parentBlock = dom.getParent(container, dom.isBlock);
22536      containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
22537      parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : '';
22538      containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
22539      if (containerBlockName === 'LI' && !ctrlKey) {
22540        parentBlock = containerBlock;
22541        containerBlock = containerBlock.parentNode;
22542        parentBlockName = containerBlockName;
22543      }
22544      if (/^(LI|DT|DD)$/.test(parentBlockName)) {
22545        if (dom.isEmpty(parentBlock)) {
22546          InsertLi.insert(editor, createNewBlock, containerBlock, parentBlock, newBlockName);
22547          return;
22548        }
22549      }
22550      if (newBlockName && parentBlock === editor.getBody()) {
22551        return;
22552      }
22553      newBlockName = newBlockName || 'P';
22554      if (isCaretContainerBlock(parentBlock)) {
22555        newBlock = showCaretContainerBlock(parentBlock);
22556        if (dom.isEmpty(parentBlock)) {
22557          emptyBlock(parentBlock);
22558        }
22559        NewLineUtils.moveToCaretPosition(editor, newBlock);
22560      } else if (isCaretAtStartOrEndOfBlock()) {
22561        insertNewBlockAfter();
22562      } else if (isCaretAtStartOrEndOfBlock(true)) {
22563        newBlock = parentBlock.parentNode.insertBefore(createNewBlock(), parentBlock);
22564        NewLineUtils.moveToCaretPosition(editor, containerAndSiblingName(parentBlock, 'HR') ? newBlock : parentBlock);
22565      } else {
22566        tmpRng = includeZwspInRange(rng).cloneRange();
22567        tmpRng.setEndAfter(parentBlock);
22568        fragment = tmpRng.extractContents();
22569        trimZwsp(fragment);
22570        trimLeadingLineBreaks(fragment);
22571        newBlock = fragment.firstChild;
22572        dom.insertAfter(fragment, parentBlock);
22573        trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock);
22574        addBrToBlockIfNeeded(dom, parentBlock);
22575        if (dom.isEmpty(parentBlock)) {
22576          emptyBlock(parentBlock);
22577        }
22578        newBlock.normalize();
22579        if (dom.isEmpty(newBlock)) {
22580          dom.remove(newBlock);
22581          insertNewBlockAfter();
22582        } else {
22583          NewLineUtils.moveToCaretPosition(editor, newBlock);
22584        }
22585      }
22586      dom.setAttrib(newBlock, 'id', '');
22587      editor.fire('NewBlock', { newBlock: newBlock });
22588    };
22589    var InsertBlock = { insert: insert$1 };
22590
22591    var hasRightSideContent = function (schema, container, parentBlock) {
22592      var walker = new TreeWalker(container, parentBlock);
22593      var node;
22594      var nonEmptyElementsMap = schema.getNonEmptyElements();
22595      while (node = walker.next()) {
22596        if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || node.length > 0) {
22597          return true;
22598        }
22599      }
22600    };
22601    var scrollToBr = function (dom, selection, brElm) {
22602      var marker = dom.create('span', {}, '&nbsp;');
22603      brElm.parentNode.insertBefore(marker, brElm);
22604      selection.scrollIntoView(marker);
22605      dom.remove(marker);
22606    };
22607    var moveSelectionToBr = function (dom, selection, brElm, extraBr) {
22608      var rng = dom.createRng();
22609      if (!extraBr) {
22610        rng.setStartAfter(brElm);
22611        rng.setEndAfter(brElm);
22612      } else {
22613        rng.setStartBefore(brElm);
22614        rng.setEndBefore(brElm);
22615      }
22616      selection.setRng(rng);
22617    };
22618    var insertBrAtCaret = function (editor, evt) {
22619      var selection = editor.selection;
22620      var dom = editor.dom;
22621      var rng = selection.getRng();
22622      var brElm;
22623      var extraBr;
22624      NormalizeRange.normalize(dom, rng).each(function (normRng) {
22625        rng.setStart(normRng.startContainer, normRng.startOffset);
22626        rng.setEnd(normRng.endContainer, normRng.endOffset);
22627      });
22628      var offset = rng.startOffset;
22629      var container = rng.startContainer;
22630      if (container.nodeType === 1 && container.hasChildNodes()) {
22631        var isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
22632        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
22633        if (isAfterLastNodeInContainer && container.nodeType === 3) {
22634          offset = container.nodeValue.length;
22635        } else {
22636          offset = 0;
22637        }
22638      }
22639      var parentBlock = dom.getParent(container, dom.isBlock);
22640      var containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
22641      var containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
22642      var isControlKey = !!(evt && evt.ctrlKey);
22643      if (containerBlockName === 'LI' && !isControlKey) {
22644        parentBlock = containerBlock;
22645      }
22646      if (container && container.nodeType === 3 && offset >= container.nodeValue.length) {
22647        if (!hasRightSideContent(editor.schema, container, parentBlock)) {
22648          brElm = dom.create('br');
22649          rng.insertNode(brElm);
22650          rng.setStartAfter(brElm);
22651          rng.setEndAfter(brElm);
22652          extraBr = true;
22653        }
22654      }
22655      brElm = dom.create('br');
22656      rangeInsertNode(dom, rng, brElm);
22657      scrollToBr(dom, selection, brElm);
22658      moveSelectionToBr(dom, selection, brElm, extraBr);
22659      editor.undoManager.add();
22660    };
22661    var insertBrBefore = function (editor, inline) {
22662      var br = Element.fromTag('br');
22663      before(Element.fromDom(inline), br);
22664      editor.undoManager.add();
22665    };
22666    var insertBrAfter = function (editor, inline) {
22667      if (!hasBrAfter(editor.getBody(), inline)) {
22668        after(Element.fromDom(inline), Element.fromTag('br'));
22669      }
22670      var br = Element.fromTag('br');
22671      after(Element.fromDom(inline), br);
22672      scrollToBr(editor.dom, editor.selection, br.dom());
22673      moveSelectionToBr(editor.dom, editor.selection, br.dom(), false);
22674      editor.undoManager.add();
22675    };
22676    var isBeforeBr$1 = function (pos) {
22677      return NodeType.isBr(pos.getNode());
22678    };
22679    var hasBrAfter = function (rootNode, startNode) {
22680      if (isBeforeBr$1(CaretPosition$1.after(startNode))) {
22681        return true;
22682      } else {
22683        return CaretFinder.nextPosition(rootNode, CaretPosition$1.after(startNode)).map(function (pos) {
22684          return NodeType.isBr(pos.getNode());
22685        }).getOr(false);
22686      }
22687    };
22688    var isAnchorLink = function (elm) {
22689      return elm && elm.nodeName === 'A' && 'href' in elm;
22690    };
22691    var isInsideAnchor = function (location) {
22692      return location.fold(constant(false), isAnchorLink, isAnchorLink, constant(false));
22693    };
22694    var readInlineAnchorLocation = function (editor) {
22695      var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
22696      var position = CaretPosition$1.fromRangeStart(editor.selection.getRng());
22697      return BoundaryLocation.readLocation(isInlineTarget, editor.getBody(), position).filter(isInsideAnchor);
22698    };
22699    var insertBrOutsideAnchor = function (editor, location) {
22700      location.fold(noop, curry(insertBrBefore, editor), curry(insertBrAfter, editor), noop);
22701    };
22702    var insert$2 = function (editor, evt) {
22703      var anchorLocation = readInlineAnchorLocation(editor);
22704      if (anchorLocation.isSome()) {
22705        anchorLocation.each(curry(insertBrOutsideAnchor, editor));
22706      } else {
22707        insertBrAtCaret(editor, evt);
22708      }
22709    };
22710    var InsertBr = { insert: insert$2 };
22711
22712    var matchesSelector = function (editor, selector) {
22713      return NewLineUtils.getParentBlock(editor).filter(function (parentBlock) {
22714        return selector.length > 0 && is$1(Element.fromDom(parentBlock), selector);
22715      }).isSome();
22716    };
22717    var shouldInsertBr = function (editor) {
22718      return matchesSelector(editor, Settings.getBrNewLineSelector(editor));
22719    };
22720    var shouldBlockNewLine = function (editor) {
22721      return matchesSelector(editor, Settings.getNoNewLineSelector(editor));
22722    };
22723    var ContextSelectors = {
22724      shouldInsertBr: shouldInsertBr,
22725      shouldBlockNewLine: shouldBlockNewLine
22726    };
22727
22728    var newLineAction = Adt.generate([
22729      { br: [] },
22730      { block: [] },
22731      { none: [] }
22732    ]);
22733    var shouldBlockNewLine$1 = function (editor, shiftKey) {
22734      return ContextSelectors.shouldBlockNewLine(editor);
22735    };
22736    var isBrMode = function (requiredState) {
22737      return function (editor, shiftKey) {
22738        var brMode = Settings.getForcedRootBlock(editor) === '';
22739        return brMode === requiredState;
22740      };
22741    };
22742    var inListBlock = function (requiredState) {
22743      return function (editor, shiftKey) {
22744        return NewLineUtils.isListItemParentBlock(editor) === requiredState;
22745      };
22746    };
22747    var inBlock = function (blockName, requiredState) {
22748      return function (editor, shiftKey) {
22749        var state = NewLineUtils.getParentBlockName(editor) === blockName.toUpperCase();
22750        return state === requiredState;
22751      };
22752    };
22753    var inPreBlock = function (requiredState) {
22754      return inBlock('pre', requiredState);
22755    };
22756    var inSummaryBlock = function () {
22757      return inBlock('summary', true);
22758    };
22759    var shouldPutBrInPre$1 = function (requiredState) {
22760      return function (editor, shiftKey) {
22761        return Settings.shouldPutBrInPre(editor) === requiredState;
22762      };
22763    };
22764    var inBrContext = function (editor, shiftKey) {
22765      return ContextSelectors.shouldInsertBr(editor);
22766    };
22767    var hasShiftKey = function (editor, shiftKey) {
22768      return shiftKey;
22769    };
22770    var canInsertIntoEditableRoot = function (editor) {
22771      var forcedRootBlock = Settings.getForcedRootBlock(editor);
22772      var rootEditable = NewLineUtils.getEditableRoot(editor.dom, editor.selection.getStart());
22773      return rootEditable && editor.schema.isValidChild(rootEditable.nodeName, forcedRootBlock ? forcedRootBlock : 'P');
22774    };
22775    var match$2 = function (predicates, action) {
22776      return function (editor, shiftKey) {
22777        var isMatch = foldl(predicates, function (res, p) {
22778          return res && p(editor, shiftKey);
22779        }, true);
22780        return isMatch ? Option.some(action) : Option.none();
22781      };
22782    };
22783    var getAction$1 = function (editor, evt) {
22784      return LazyEvaluator.evaluateUntil([
22785        match$2([shouldBlockNewLine$1], newLineAction.none()),
22786        match$2([inSummaryBlock()], newLineAction.br()),
22787        match$2([
22788          inPreBlock(true),
22789          shouldPutBrInPre$1(false),
22790          hasShiftKey
22791        ], newLineAction.br()),
22792        match$2([
22793          inPreBlock(true),
22794          shouldPutBrInPre$1(false)
22795        ], newLineAction.block()),
22796        match$2([
22797          inPreBlock(true),
22798          shouldPutBrInPre$1(true),
22799          hasShiftKey
22800        ], newLineAction.block()),
22801        match$2([
22802          inPreBlock(true),
22803          shouldPutBrInPre$1(true)
22804        ], newLineAction.br()),
22805        match$2([
22806          inListBlock(true),
22807          hasShiftKey
22808        ], newLineAction.br()),
22809        match$2([inListBlock(true)], newLineAction.block()),
22810        match$2([
22811          isBrMode(true),
22812          hasShiftKey,
22813          canInsertIntoEditableRoot
22814        ], newLineAction.block()),
22815        match$2([isBrMode(true)], newLineAction.br()),
22816        match$2([inBrContext], newLineAction.br()),
22817        match$2([
22818          isBrMode(false),
22819          hasShiftKey
22820        ], newLineAction.br()),
22821        match$2([canInsertIntoEditableRoot], newLineAction.block())
22822      ], [
22823        editor,
22824        !!(evt && evt.shiftKey)
22825      ]).getOr(newLineAction.none());
22826    };
22827    var NewLineAction = { getAction: getAction$1 };
22828
22829    var insert$3 = function (editor, evt) {
22830      NewLineAction.getAction(editor, evt).fold(function () {
22831        InsertBr.insert(editor, evt);
22832      }, function () {
22833        InsertBlock.insert(editor, evt);
22834      }, noop);
22835    };
22836    var InsertNewLine = { insert: insert$3 };
22837
22838    var endTypingLevel = function (undoManager) {
22839      if (undoManager.typing) {
22840        undoManager.typing = false;
22841        undoManager.add();
22842      }
22843    };
22844    var handleEnterKeyEvent = function (editor, event) {
22845      if (event.isDefaultPrevented()) {
22846        return;
22847      }
22848      event.preventDefault();
22849      endTypingLevel(editor.undoManager);
22850      editor.undoManager.transact(function () {
22851        if (editor.selection.isCollapsed() === false) {
22852          editor.execCommand('Delete');
22853        }
22854        InsertNewLine.insert(editor, event);
22855      });
22856    };
22857    var setup$9 = function (editor) {
22858      editor.on('keydown', function (event) {
22859        if (event.keyCode === VK.ENTER) {
22860          handleEnterKeyEvent(editor, event);
22861        }
22862      });
22863    };
22864    var EnterKey = { setup: setup$9 };
22865
22866    var insertTextAtPosition = function (text, pos) {
22867      var container = pos.container();
22868      var offset = pos.offset();
22869      if (NodeType.isText(container)) {
22870        container.insertData(offset, text);
22871        return Option.some(CaretPosition(container, offset + text.length));
22872      } else {
22873        return getElementFromPosition(pos).map(function (elm) {
22874          var textNode = Element.fromText(text);
22875          if (pos.isAtEnd()) {
22876            after(elm, textNode);
22877          } else {
22878            before(elm, textNode);
22879          }
22880          return CaretPosition(textNode.dom(), text.length);
22881        });
22882      }
22883    };
22884    var insertNbspAtPosition = curry(insertTextAtPosition, '\xA0');
22885    var insertSpaceAtPosition = curry(insertTextAtPosition, ' ');
22886
22887    var navigateIgnoreEmptyTextNodes = function (forward, root, from) {
22888      return CaretFinder.navigateIgnore(forward, root, from, isEmptyText);
22889    };
22890    var isAtBlockBoundary = function (forward, root, pos) {
22891      var parentBlocks = filter(Parents.parentsAndSelf(Element.fromDom(pos.container()), root), isBlock);
22892      return head(parentBlocks).fold(function () {
22893        return navigateIgnoreEmptyTextNodes(forward, root.dom(), pos).forall(function (newPos) {
22894          return isInSameBlock(newPos, pos, root.dom()) === false;
22895        });
22896      }, function (parent) {
22897        return navigateIgnoreEmptyTextNodes(forward, parent.dom(), pos).isNone();
22898      });
22899    };
22900    var isAtStartOfBlock = curry(isAtBlockBoundary, false);
22901    var isAtEndOfBlock = curry(isAtBlockBoundary, true);
22902
22903    var nbsp = '\xA0';
22904    var isInMiddleOfText = function (pos) {
22905      return CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd();
22906    };
22907    var getClosestBlock = function (root, pos) {
22908      var parentBlocks = filter(Parents.parentsAndSelf(Element.fromDom(pos.container()), root), isBlock);
22909      return head(parentBlocks).getOr(root);
22910    };
22911    var hasSpaceBefore = function (root, pos) {
22912      if (isInMiddleOfText(pos)) {
22913        return isAfterSpace(pos);
22914      } else {
22915        return isAfterSpace(pos) || CaretFinder.prevPosition(getClosestBlock(root, pos).dom(), pos).exists(isAfterSpace);
22916      }
22917    };
22918    var hasSpaceAfter = function (root, pos) {
22919      if (isInMiddleOfText(pos)) {
22920        return isBeforeSpace(pos);
22921      } else {
22922        return isBeforeSpace(pos) || CaretFinder.nextPosition(getClosestBlock(root, pos).dom(), pos).exists(isBeforeSpace);
22923      }
22924    };
22925    var isPreValue = function (value) {
22926      return contains([
22927        'pre',
22928        'pre-line',
22929        'pre-wrap'
22930      ], value);
22931    };
22932    var isInPre = function (pos) {
22933      return getElementFromPosition(pos).bind(function (elm) {
22934        return closest(elm, isElement);
22935      }).exists(function (elm) {
22936        return isPreValue(get$2(elm, 'white-space'));
22937      });
22938    };
22939    var isAtBeginningOfBody = function (root, pos) {
22940      return CaretFinder.prevPosition(root.dom(), pos).isNone();
22941    };
22942    var isAtEndOfBody = function (root, pos) {
22943      return CaretFinder.nextPosition(root.dom(), pos).isNone();
22944    };
22945    var isAtLineBoundary = function (root, pos) {
22946      return isAtBeginningOfBody(root, pos) || isAtEndOfBody(root, pos) || isAtStartOfBlock(root, pos) || isAtEndOfBlock(root, pos) || isAfterBr(root, pos) || isBeforeBr(root, pos);
22947    };
22948    var needsToHaveNbsp = function (root, pos) {
22949      if (isInPre(pos)) {
22950        return false;
22951      } else {
22952        return isAtLineBoundary(root, pos) || hasSpaceBefore(root, pos) || hasSpaceAfter(root, pos);
22953      }
22954    };
22955    var needsToBeNbspLeft = function (root, pos) {
22956      if (isInPre(pos)) {
22957        return false;
22958      } else {
22959        return isAtStartOfBlock(root, pos) || isAfterBr(root, pos) || hasSpaceBefore(root, pos);
22960      }
22961    };
22962    var leanRight = function (pos) {
22963      var container = pos.container();
22964      var offset = pos.offset();
22965      if (NodeType.isText(container) && offset < container.data.length) {
22966        return CaretPosition(container, offset + 1);
22967      } else {
22968        return pos;
22969      }
22970    };
22971    var needsToBeNbspRight = function (root, pos) {
22972      var afterPos = leanRight(pos);
22973      if (isInPre(afterPos)) {
22974        return false;
22975      } else {
22976        return isAtEndOfBlock(root, afterPos) || isBeforeBr(root, afterPos) || hasSpaceAfter(root, afterPos);
22977      }
22978    };
22979    var needsToBeNbsp = function (root, pos) {
22980      return needsToBeNbspLeft(root, pos) || needsToBeNbspRight(root, pos);
22981    };
22982    var isNbspAt = function (text, offset) {
22983      return isNbsp(text.charAt(offset));
22984    };
22985    var hasNbsp = function (pos) {
22986      var container = pos.container();
22987      return NodeType.isText(container) && contains$2(container.data, nbsp);
22988    };
22989    var normalizeNbspMiddle = function (text) {
22990      return map(text.split(''), function (chr, i, chars) {
22991        if (isNbsp(chr) && i > 0 && i < chars.length - 1 && isContent(chars[i - 1]) && isContent(chars[i + 1])) {
22992          return ' ';
22993        } else {
22994          return chr;
22995        }
22996      }).join('');
22997    };
22998    var normalizeNbspAtStart = function (root, node) {
22999      var text = node.data;
23000      var firstPos = CaretPosition(node, 0);
23001      if (isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos)) {
23002        node.data = ' ' + text.slice(1);
23003        return true;
23004      } else {
23005        return false;
23006      }
23007    };
23008    var normalizeNbspInMiddleOfTextNode = function (node) {
23009      var text = node.data;
23010      var newText = normalizeNbspMiddle(text);
23011      if (newText !== text) {
23012        node.data = newText;
23013        return true;
23014      } else {
23015        return false;
23016      }
23017    };
23018    var normalizeNbspAtEnd = function (root, node) {
23019      var text = node.data;
23020      var lastPos = CaretPosition(node, text.length - 1);
23021      if (isNbspAt(text, text.length - 1) && !needsToBeNbsp(root, lastPos)) {
23022        node.data = text.slice(0, -1) + ' ';
23023        return true;
23024      } else {
23025        return false;
23026      }
23027    };
23028    var normalizeNbsps = function (root, pos) {
23029      return Option.some(pos).filter(hasNbsp).bind(function (pos) {
23030        var container = pos.container();
23031        var normalized = normalizeNbspAtStart(root, container) || normalizeNbspInMiddleOfTextNode(container) || normalizeNbspAtEnd(root, container);
23032        return normalized ? Option.some(pos) : Option.none();
23033      });
23034    };
23035    var normalizeNbspsInEditor = function (editor) {
23036      var root = Element.fromDom(editor.getBody());
23037      if (editor.selection.isCollapsed()) {
23038        normalizeNbsps(root, CaretPosition.fromRangeStart(editor.selection.getRng())).each(function (pos) {
23039          editor.selection.setRng(pos.toRange());
23040        });
23041      }
23042    };
23043
23044    var locationToCaretPosition = function (root) {
23045      return function (location) {
23046        return location.fold(function (element) {
23047          return CaretFinder.prevPosition(root.dom(), CaretPosition$1.before(element));
23048        }, function (element) {
23049          return CaretFinder.firstPositionIn(element);
23050        }, function (element) {
23051          return CaretFinder.lastPositionIn(element);
23052        }, function (element) {
23053          return CaretFinder.nextPosition(root.dom(), CaretPosition$1.after(element));
23054        });
23055      };
23056    };
23057    var insertInlineBoundarySpaceOrNbsp = function (root, pos) {
23058      return function (checkPos) {
23059        return needsToHaveNbsp(root, checkPos) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
23060      };
23061    };
23062    var setSelection$1 = function (editor) {
23063      return function (pos) {
23064        editor.selection.setRng(pos.toRange());
23065        editor.nodeChanged();
23066        return true;
23067      };
23068    };
23069    var insertSpaceOrNbspAtSelection = function (editor) {
23070      var pos = CaretPosition$1.fromRangeStart(editor.selection.getRng());
23071      var root = Element.fromDom(editor.getBody());
23072      if (editor.selection.isCollapsed()) {
23073        var isInlineTarget = curry(InlineUtils.isInlineTarget, editor);
23074        var caretPosition = CaretPosition$1.fromRangeStart(editor.selection.getRng());
23075        return BoundaryLocation.readLocation(isInlineTarget, editor.getBody(), caretPosition).bind(locationToCaretPosition(root)).bind(insertInlineBoundarySpaceOrNbsp(root, pos)).exists(setSelection$1(editor));
23076      } else {
23077        return false;
23078      }
23079    };
23080
23081    var executeKeydownOverride$2 = function (editor, evt) {
23082      MatchKeys.execute([{
23083          keyCode: VK.SPACEBAR,
23084          action: MatchKeys.action(insertSpaceOrNbspAtSelection, editor)
23085        }], evt).each(function (_) {
23086        evt.preventDefault();
23087      });
23088    };
23089    var setup$a = function (editor) {
23090      editor.on('keydown', function (evt) {
23091        if (evt.isDefaultPrevented() === false) {
23092          executeKeydownOverride$2(editor, evt);
23093        }
23094      });
23095    };
23096    var SpaceKey = { setup: setup$a };
23097
23098    var findBlockCaretContainer = function (editor) {
23099      return descendant(Element.fromDom(editor.getBody()), '*[data-mce-caret]').fold(constant(null), function (elm) {
23100        return elm.dom();
23101      });
23102    };
23103    var removeIeControlRect = function (editor) {
23104      editor.selection.setRng(editor.selection.getRng());
23105    };
23106    var showBlockCaretContainer = function (editor, blockCaretContainer) {
23107      if (blockCaretContainer.hasAttribute('data-mce-caret')) {
23108        showCaretContainerBlock(blockCaretContainer);
23109        removeIeControlRect(editor);
23110        editor.selection.scrollIntoView(blockCaretContainer);
23111      }
23112    };
23113    var handleBlockContainer = function (editor, e) {
23114      var blockCaretContainer = findBlockCaretContainer(editor);
23115      if (!blockCaretContainer) {
23116        return;
23117      }
23118      if (e.type === 'compositionstart') {
23119        e.preventDefault();
23120        e.stopPropagation();
23121        showBlockCaretContainer(editor, blockCaretContainer);
23122        return;
23123      }
23124      if (hasContent(blockCaretContainer)) {
23125        showBlockCaretContainer(editor, blockCaretContainer);
23126        editor.undoManager.add();
23127      }
23128    };
23129    var setup$b = function (editor) {
23130      editor.on('keyup compositionstart', curry(handleBlockContainer, editor));
23131    };
23132    var CaretContainerInput = { setup: setup$b };
23133
23134    var browser$4 = PlatformDetection$1.detect().browser;
23135    var setupIeInput = function (editor) {
23136      var keypressThrotter = first(function () {
23137        if (!editor.composing) {
23138          normalizeNbspsInEditor(editor);
23139        }
23140      }, 0);
23141      if (browser$4.isIE()) {
23142        editor.on('keypress', function (e) {
23143          keypressThrotter.throttle();
23144        });
23145        editor.on('remove', function (e) {
23146          keypressThrotter.cancel();
23147        });
23148      }
23149    };
23150    var setup$c = function (editor) {
23151      setupIeInput(editor);
23152      editor.on('input', function (e) {
23153        if (e.isComposing === false) {
23154          normalizeNbspsInEditor(editor);
23155        }
23156      });
23157    };
23158
23159    var executeKeydownOverride$3 = function (editor, evt) {
23160      MatchKeys.execute([
23161        {
23162          keyCode: VK.END,
23163          action: moveToLineEndPoint(editor, true)
23164        },
23165        {
23166          keyCode: VK.HOME,
23167          action: moveToLineEndPoint(editor, false)
23168        }
23169      ], evt).each(function (_) {
23170        evt.preventDefault();
23171      });
23172    };
23173    var setup$d = function (editor) {
23174      editor.on('keydown', function (evt) {
23175        if (evt.isDefaultPrevented() === false) {
23176          executeKeydownOverride$3(editor, evt);
23177        }
23178      });
23179    };
23180    var HomeEndKeys = { setup: setup$d };
23181
23182    var setup$e = function (editor) {
23183      var caret = BoundarySelection.setupSelectedState(editor);
23184      CaretContainerInput.setup(editor);
23185      ArrowKeys.setup(editor, caret);
23186      DeleteBackspaceKeys.setup(editor, caret);
23187      EnterKey.setup(editor);
23188      SpaceKey.setup(editor);
23189      setup$c(editor);
23190      HomeEndKeys.setup(editor);
23191    };
23192    var KeyboardOverrides = { setup: setup$e };
23193
23194    var Quirks = function (editor) {
23195      var each = Tools.each;
23196      var BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, settings = editor.settings, parser = editor.parser;
23197      var isGecko = Env.gecko, isIE = Env.ie, isWebKit = Env.webkit;
23198      var mceInternalUrlPrefix = 'data:text/mce-internal,';
23199      var mceInternalDataType = isIE ? 'Text' : 'URL';
23200      var setEditorCommandState = function (cmd, state) {
23201        try {
23202          editor.getDoc().execCommand(cmd, false, state);
23203        } catch (ex) {
23204        }
23205      };
23206      var isDefaultPrevented = function (e) {
23207        return e.isDefaultPrevented();
23208      };
23209      var setMceInternalContent = function (e) {
23210        var selectionHtml, internalContent;
23211        if (e.dataTransfer) {
23212          if (editor.selection.isCollapsed() && e.target.tagName === 'IMG') {
23213            selection.select(e.target);
23214          }
23215          selectionHtml = editor.selection.getContent();
23216          if (selectionHtml.length > 0) {
23217            internalContent = mceInternalUrlPrefix + escape(editor.id) + ',' + escape(selectionHtml);
23218            e.dataTransfer.setData(mceInternalDataType, internalContent);
23219          }
23220        }
23221      };
23222      var getMceInternalContent = function (e) {
23223        var internalContent;
23224        if (e.dataTransfer) {
23225          internalContent = e.dataTransfer.getData(mceInternalDataType);
23226          if (internalContent && internalContent.indexOf(mceInternalUrlPrefix) >= 0) {
23227            internalContent = internalContent.substr(mceInternalUrlPrefix.length).split(',');
23228            return {
23229              id: unescape(internalContent[0]),
23230              html: unescape(internalContent[1])
23231            };
23232          }
23233        }
23234        return null;
23235      };
23236      var insertClipboardContents = function (content, internal) {
23237        if (editor.queryCommandSupported('mceInsertClipboardContent')) {
23238          editor.execCommand('mceInsertClipboardContent', false, {
23239            content: content,
23240            internal: internal
23241          });
23242        } else {
23243          editor.execCommand('mceInsertContent', false, content);
23244        }
23245      };
23246      var emptyEditorWhenDeleting = function () {
23247        var serializeRng = function (rng) {
23248          var body = dom.create('body');
23249          var contents = rng.cloneContents();
23250          body.appendChild(contents);
23251          return selection.serializer.serialize(body, { format: 'html' });
23252        };
23253        var allContentsSelected = function (rng) {
23254          var selection = serializeRng(rng);
23255          var allRng = dom.createRng();
23256          allRng.selectNode(editor.getBody());
23257          var allSelection = serializeRng(allRng);
23258          return selection === allSelection;
23259        };
23260        editor.on('keydown', function (e) {
23261          var keyCode = e.keyCode;
23262          var isCollapsed, body;
23263          if (!isDefaultPrevented(e) && (keyCode === DELETE || keyCode === BACKSPACE)) {
23264            isCollapsed = editor.selection.isCollapsed();
23265            body = editor.getBody();
23266            if (isCollapsed && !dom.isEmpty(body)) {
23267              return;
23268            }
23269            if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
23270              return;
23271            }
23272            e.preventDefault();
23273            editor.setContent('');
23274            if (body.firstChild && dom.isBlock(body.firstChild)) {
23275              editor.selection.setCursorLocation(body.firstChild, 0);
23276            } else {
23277              editor.selection.setCursorLocation(body, 0);
23278            }
23279            editor.nodeChanged();
23280          }
23281        });
23282      };
23283      var selectAll = function () {
23284        editor.shortcuts.add('meta+a', null, 'SelectAll');
23285      };
23286      var inputMethodFocus = function () {
23287        if (!editor.inline) {
23288          dom.bind(editor.getDoc(), 'mousedown mouseup', function (e) {
23289            var rng;
23290            if (e.target === editor.getDoc().documentElement) {
23291              rng = selection.getRng();
23292              editor.getBody().focus();
23293              if (e.type === 'mousedown') {
23294                if (isCaretContainer(rng.startContainer)) {
23295                  return;
23296                }
23297                selection.placeCaretAt(e.clientX, e.clientY);
23298              } else {
23299                selection.setRng(rng);
23300              }
23301            }
23302          });
23303        }
23304      };
23305      var removeHrOnBackspace = function () {
23306        editor.on('keydown', function (e) {
23307          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
23308            if (!editor.getBody().getElementsByTagName('hr').length) {
23309              return;
23310            }
23311            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
23312              var node = selection.getNode();
23313              var previousSibling = node.previousSibling;
23314              if (node.nodeName === 'HR') {
23315                dom.remove(node);
23316                e.preventDefault();
23317                return;
23318              }
23319              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'hr') {
23320                dom.remove(previousSibling);
23321                e.preventDefault();
23322              }
23323            }
23324          }
23325        });
23326      };
23327      var focusBody = function () {
23328        if (!domGlobals.Range.prototype.getClientRects) {
23329          editor.on('mousedown', function (e) {
23330            if (!isDefaultPrevented(e) && e.target.nodeName === 'HTML') {
23331              var body_1 = editor.getBody();
23332              body_1.blur();
23333              Delay.setEditorTimeout(editor, function () {
23334                body_1.focus();
23335              });
23336            }
23337          });
23338        }
23339      };
23340      var selectControlElements = function () {
23341        editor.on('click', function (e) {
23342          var target = e.target;
23343          if (/^(IMG|HR)$/.test(target.nodeName) && dom.getContentEditableParent(target) !== 'false') {
23344            e.preventDefault();
23345            editor.selection.select(target);
23346            editor.nodeChanged();
23347          }
23348          if (target.nodeName === 'A' && dom.hasClass(target, 'mce-item-anchor')) {
23349            e.preventDefault();
23350            selection.select(target);
23351          }
23352        });
23353      };
23354      var removeStylesWhenDeletingAcrossBlockElements = function () {
23355        var getAttributeApplyFunction = function () {
23356          var template = dom.getAttribs(selection.getStart().cloneNode(false));
23357          return function () {
23358            var target = selection.getStart();
23359            if (target !== editor.getBody()) {
23360              dom.setAttrib(target, 'style', null);
23361              each(template, function (attr) {
23362                target.setAttributeNode(attr.cloneNode(true));
23363              });
23364            }
23365          };
23366        };
23367        var isSelectionAcrossElements = function () {
23368          return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) !== dom.getParent(selection.getEnd(), dom.isBlock);
23369        };
23370        editor.on('keypress', function (e) {
23371          var applyAttributes;
23372          if (!isDefaultPrevented(e) && (e.keyCode === 8 || e.keyCode === 46) && isSelectionAcrossElements()) {
23373            applyAttributes = getAttributeApplyFunction();
23374            editor.getDoc().execCommand('delete', false, null);
23375            applyAttributes();
23376            e.preventDefault();
23377            return false;
23378          }
23379        });
23380        dom.bind(editor.getDoc(), 'cut', function (e) {
23381          var applyAttributes;
23382          if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
23383            applyAttributes = getAttributeApplyFunction();
23384            Delay.setEditorTimeout(editor, function () {
23385              applyAttributes();
23386            });
23387          }
23388        });
23389      };
23390      var disableBackspaceIntoATable = function () {
23391        editor.on('keydown', function (e) {
23392          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
23393            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
23394              var previousSibling = selection.getNode().previousSibling;
23395              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'table') {
23396                e.preventDefault();
23397                return false;
23398              }
23399            }
23400          }
23401        });
23402      };
23403      var removeBlockQuoteOnBackSpace = function () {
23404        editor.on('keydown', function (e) {
23405          var rng, container, offset, root, parent;
23406          if (isDefaultPrevented(e) || e.keyCode !== VK.BACKSPACE) {
23407            return;
23408          }
23409          rng = selection.getRng();
23410          container = rng.startContainer;
23411          offset = rng.startOffset;
23412          root = dom.getRoot();
23413          parent = container;
23414          if (!rng.collapsed || offset !== 0) {
23415            return;
23416          }
23417          while (parent && parent.parentNode && parent.parentNode.firstChild === parent && parent.parentNode !== root) {
23418            parent = parent.parentNode;
23419          }
23420          if (parent.tagName === 'BLOCKQUOTE') {
23421            editor.formatter.toggle('blockquote', null, parent);
23422            rng = dom.createRng();
23423            rng.setStart(container, 0);
23424            rng.setEnd(container, 0);
23425            selection.setRng(rng);
23426          }
23427        });
23428      };
23429      var setGeckoEditingOptions = function () {
23430        var setOpts = function () {
23431          setEditorCommandState('StyleWithCSS', false);
23432          setEditorCommandState('enableInlineTableEditing', false);
23433          if (!settings.object_resizing) {
23434            setEditorCommandState('enableObjectResizing', false);
23435          }
23436        };
23437        if (!settings.readonly) {
23438          editor.on('BeforeExecCommand mousedown', setOpts);
23439        }
23440      };
23441      var addBrAfterLastLinks = function () {
23442        var fixLinks = function () {
23443          each(dom.select('a'), function (node) {
23444            var parentNode = node.parentNode;
23445            var root = dom.getRoot();
23446            if (parentNode.lastChild === node) {
23447              while (parentNode && !dom.isBlock(parentNode)) {
23448                if (parentNode.parentNode.lastChild !== parentNode || parentNode === root) {
23449                  return;
23450                }
23451                parentNode = parentNode.parentNode;
23452              }
23453              dom.add(parentNode, 'br', { 'data-mce-bogus': 1 });
23454            }
23455          });
23456        };
23457        editor.on('SetContent ExecCommand', function (e) {
23458          if (e.type === 'setcontent' || e.command === 'mceInsertLink') {
23459            fixLinks();
23460          }
23461        });
23462      };
23463      var setDefaultBlockType = function () {
23464        if (settings.forced_root_block) {
23465          editor.on('init', function () {
23466            setEditorCommandState('DefaultParagraphSeparator', Settings.getForcedRootBlock(editor));
23467          });
23468        }
23469      };
23470      var normalizeSelection = function () {
23471        editor.on('keyup focusin mouseup', function (e) {
23472          if (!VK.modifierPressed(e)) {
23473            selection.normalize();
23474          }
23475        }, true);
23476      };
23477      var showBrokenImageIcon = function () {
23478        editor.contentStyles.push('img:-moz-broken {' + '-moz-force-broken-image-icon:1;' + 'min-width:24px;' + 'min-height:24px' + '}');
23479      };
23480      var restoreFocusOnKeyDown = function () {
23481        if (!editor.inline) {
23482          editor.on('keydown', function () {
23483            if (domGlobals.document.activeElement === domGlobals.document.body) {
23484              editor.getWin().focus();
23485            }
23486          });
23487        }
23488      };
23489      var bodyHeight = function () {
23490        if (!editor.inline) {
23491          editor.contentStyles.push('body {min-height: 150px}');
23492          editor.on('click', function (e) {
23493            var rng;
23494            if (e.target.nodeName === 'HTML') {
23495              if (Env.ie > 11) {
23496                editor.getBody().focus();
23497                return;
23498              }
23499              rng = editor.selection.getRng();
23500              editor.getBody().focus();
23501              editor.selection.setRng(rng);
23502              editor.selection.normalize();
23503              editor.nodeChanged();
23504            }
23505          });
23506        }
23507      };
23508      var blockCmdArrowNavigation = function () {
23509        if (Env.mac) {
23510          editor.on('keydown', function (e) {
23511            if (VK.metaKeyPressed(e) && !e.shiftKey && (e.keyCode === 37 || e.keyCode === 39)) {
23512              e.preventDefault();
23513              var selection_1 = editor.selection.getSel();
23514              selection_1.modify('move', e.keyCode === 37 ? 'backward' : 'forward', 'lineboundary');
23515            }
23516          });
23517        }
23518      };
23519      var disableAutoUrlDetect = function () {
23520        setEditorCommandState('AutoUrlDetect', false);
23521      };
23522      var tapLinksAndImages = function () {
23523        editor.on('click', function (e) {
23524          var elm = e.target;
23525          do {
23526            if (elm.tagName === 'A') {
23527              e.preventDefault();
23528              return;
23529            }
23530          } while (elm = elm.parentNode);
23531        });
23532        editor.contentStyles.push('.mce-content-body {-webkit-touch-callout: none}');
23533      };
23534      var blockFormSubmitInsideEditor = function () {
23535        editor.on('init', function () {
23536          editor.dom.bind(editor.getBody(), 'submit', function (e) {
23537            e.preventDefault();
23538          });
23539        });
23540      };
23541      var removeAppleInterchangeBrs = function () {
23542        parser.addNodeFilter('br', function (nodes) {
23543          var i = nodes.length;
23544          while (i--) {
23545            if (nodes[i].attr('class') === 'Apple-interchange-newline') {
23546              nodes[i].remove();
23547            }
23548          }
23549        });
23550      };
23551      var ieInternalDragAndDrop = function () {
23552        editor.on('dragstart', function (e) {
23553          setMceInternalContent(e);
23554        });
23555        editor.on('drop', function (e) {
23556          if (!isDefaultPrevented(e)) {
23557            var internalContent = getMceInternalContent(e);
23558            if (internalContent && internalContent.id !== editor.id) {
23559              e.preventDefault();
23560              var rng = CaretRangeFromPoint.fromPoint(e.x, e.y, editor.getDoc());
23561              selection.setRng(rng);
23562              insertClipboardContents(internalContent.html, true);
23563            }
23564          }
23565        });
23566      };
23567      var refreshContentEditable = function () {
23568      };
23569      var isHidden = function () {
23570        var sel;
23571        if (!isGecko || editor.removed) {
23572          return false;
23573        }
23574        sel = editor.selection.getSel();
23575        return !sel || !sel.rangeCount || sel.rangeCount === 0;
23576      };
23577      removeBlockQuoteOnBackSpace();
23578      emptyEditorWhenDeleting();
23579      if (!Env.windowsPhone) {
23580        normalizeSelection();
23581      }
23582      if (isWebKit) {
23583        inputMethodFocus();
23584        selectControlElements();
23585        setDefaultBlockType();
23586        blockFormSubmitInsideEditor();
23587        disableBackspaceIntoATable();
23588        removeAppleInterchangeBrs();
23589        if (Env.iOS) {
23590          restoreFocusOnKeyDown();
23591          bodyHeight();
23592          tapLinksAndImages();
23593        } else {
23594          selectAll();
23595        }
23596      }
23597      if (Env.ie >= 11) {
23598        bodyHeight();
23599        disableBackspaceIntoATable();
23600      }
23601      if (Env.ie) {
23602        selectAll();
23603        disableAutoUrlDetect();
23604        ieInternalDragAndDrop();
23605      }
23606      if (isGecko) {
23607        removeHrOnBackspace();
23608        focusBody();
23609        removeStylesWhenDeletingAcrossBlockElements();
23610        setGeckoEditingOptions();
23611        addBrAfterLastLinks();
23612        showBrokenImageIcon();
23613        blockCmdArrowNavigation();
23614        disableBackspaceIntoATable();
23615      }
23616      return {
23617        refreshContentEditable: refreshContentEditable,
23618        isHidden: isHidden
23619      };
23620    };
23621
23622    var isTextBlockNode = function (node) {
23623      return NodeType.isElement(node) && isTextBlock(Element.fromDom(node));
23624    };
23625    var normalizeSelection$1 = function (editor) {
23626      var rng = editor.selection.getRng();
23627      var startPos = CaretPosition.fromRangeStart(rng);
23628      var endPos = CaretPosition.fromRangeEnd(rng);
23629      if (CaretPosition.isElementPosition(startPos)) {
23630        var container = startPos.container();
23631        if (isTextBlockNode(container)) {
23632          CaretFinder.firstPositionIn(container).each(function (pos) {
23633            return rng.setStart(pos.container(), pos.offset());
23634          });
23635        }
23636      }
23637      if (CaretPosition.isElementPosition(endPos)) {
23638        var container = startPos.container();
23639        if (isTextBlockNode(container)) {
23640          CaretFinder.lastPositionIn(container).each(function (pos) {
23641            return rng.setEnd(pos.container(), pos.offset());
23642          });
23643        }
23644      }
23645      editor.selection.setRng(RangeNormalizer.normalize(rng));
23646    };
23647    var setup$f = function (editor) {
23648      editor.on('click', function (e) {
23649        if (e.detail >= 3) {
23650          normalizeSelection$1(editor);
23651        }
23652      });
23653    };
23654
23655    var preventSummaryToggle = function (editor) {
23656      editor.on('click', function (e) {
23657        if (editor.dom.getParent(e.target, 'details')) {
23658          e.preventDefault();
23659        }
23660      });
23661    };
23662    var filterDetails = function (editor) {
23663      editor.parser.addNodeFilter('details', function (elms) {
23664        each(elms, function (details) {
23665          details.attr('data-mce-open', details.attr('open'));
23666          details.attr('open', 'open');
23667        });
23668      });
23669      editor.serializer.addNodeFilter('details', function (elms) {
23670        each(elms, function (details) {
23671          var open = details.attr('data-mce-open');
23672          details.attr('open', isString(open) ? open : null);
23673          details.attr('data-mce-open', null);
23674        });
23675      });
23676    };
23677    var setup$g = function (editor) {
23678      preventSummaryToggle(editor);
23679      filterDetails(editor);
23680    };
23681
23682    var DOM$2 = DOMUtils$1.DOM;
23683    var appendStyle = function (editor, text) {
23684      var head = Element.fromDom(editor.getDoc().head);
23685      var tag = Element.fromTag('style');
23686      set(tag, 'type', 'text/css');
23687      append(tag, Element.fromText(text));
23688      append(head, tag);
23689    };
23690    var createParser = function (editor) {
23691      var parser = DomParser(editor.settings, editor.schema);
23692      parser.addAttributeFilter('src,href,style,tabindex', function (nodes, name) {
23693        var i = nodes.length, node;
23694        var dom = editor.dom;
23695        var value, internalName;
23696        while (i--) {
23697          node = nodes[i];
23698          value = node.attr(name);
23699          internalName = 'data-mce-' + name;
23700          if (!node.attr(internalName)) {
23701            if (value.indexOf('data:') === 0 || value.indexOf('blob:') === 0) {
23702              continue;
23703            }
23704            if (name === 'style') {
23705              value = dom.serializeStyle(dom.parseStyle(value), node.name);
23706              if (!value.length) {
23707                value = null;
23708              }
23709              node.attr(internalName, value);
23710              node.attr(name, value);
23711            } else if (name === 'tabindex') {
23712              node.attr(internalName, value);
23713              node.attr(name, null);
23714            } else {
23715              node.attr(internalName, editor.convertURL(value, name, node.name));
23716            }
23717          }
23718        }
23719      });
23720      parser.addNodeFilter('script', function (nodes) {
23721        var i = nodes.length, node, type;
23722        while (i--) {
23723          node = nodes[i];
23724          type = node.attr('type') || 'no/type';
23725          if (type.indexOf('mce-') !== 0) {
23726            node.attr('type', 'mce-' + type);
23727          }
23728        }
23729      });
23730      parser.addNodeFilter('#cdata', function (nodes) {
23731        var i = nodes.length, node;
23732        while (i--) {
23733          node = nodes[i];
23734          node.type = 8;
23735          node.name = '#comment';
23736          node.value = '[CDATA[' + node.value + ']]';
23737        }
23738      });
23739      parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', function (nodes) {
23740        var i = nodes.length, node;
23741        var nonEmptyElements = editor.schema.getNonEmptyElements();
23742        while (i--) {
23743          node = nodes[i];
23744          if (node.isEmpty(nonEmptyElements) && node.getAll('br').length === 0) {
23745            node.append(new Node$1('br', 1)).shortEnded = true;
23746          }
23747        }
23748      });
23749      return parser;
23750    };
23751    var autoFocus = function (editor) {
23752      if (editor.settings.auto_focus) {
23753        Delay.setEditorTimeout(editor, function () {
23754          var focusEditor;
23755          if (editor.settings.auto_focus === true) {
23756            focusEditor = editor;
23757          } else {
23758            focusEditor = editor.editorManager.get(editor.settings.auto_focus);
23759          }
23760          if (!focusEditor.destroyed) {
23761            focusEditor.focus();
23762          }
23763        }, 100);
23764      }
23765    };
23766    var initEditor = function (editor) {
23767      editor.bindPendingEventDelegates();
23768      editor.initialized = true;
23769      editor.fire('init');
23770      editor.focus(true);
23771      editor.nodeChanged({ initial: true });
23772      editor.execCallback('init_instance_callback', editor);
23773      autoFocus(editor);
23774    };
23775    var getStyleSheetLoader = function (editor) {
23776      return editor.inline ? DOM$2.styleSheetLoader : editor.dom.styleSheetLoader;
23777    };
23778    var initContentBody = function (editor, skipWrite) {
23779      var settings = editor.settings;
23780      var targetElm = editor.getElement();
23781      var doc = editor.getDoc(), body, contentCssText;
23782      if (!settings.inline) {
23783        editor.getElement().style.visibility = editor.orgVisibility;
23784      }
23785      if (!skipWrite && !editor.inline) {
23786        doc.open();
23787        doc.write(editor.iframeHTML);
23788        doc.close();
23789      }
23790      if (editor.inline) {
23791        editor.on('remove', function () {
23792          var bodyEl = this.getBody();
23793          DOM$2.removeClass(bodyEl, 'mce-content-body');
23794          DOM$2.removeClass(bodyEl, 'mce-edit-focus');
23795          DOM$2.setAttrib(bodyEl, 'contentEditable', null);
23796        });
23797        DOM$2.addClass(targetElm, 'mce-content-body');
23798        editor.contentDocument = doc = settings.content_document || domGlobals.document;
23799        editor.contentWindow = settings.content_window || domGlobals.window;
23800        editor.bodyElement = targetElm;
23801        editor.contentAreaContainer = targetElm;
23802        settings.content_document = settings.content_window = null;
23803        settings.root_name = targetElm.nodeName.toLowerCase();
23804      }
23805      body = editor.getBody();
23806      body.disabled = true;
23807      editor.readonly = settings.readonly;
23808      if (!editor.readonly) {
23809        if (editor.inline && DOM$2.getStyle(body, 'position', true) === 'static') {
23810          body.style.position = 'relative';
23811        }
23812        body.contentEditable = editor.getParam('content_editable_state', true);
23813      }
23814      body.disabled = false;
23815      editor.editorUpload = EditorUpload(editor);
23816      editor.schema = Schema(settings);
23817      editor.dom = DOMUtils$1(doc, {
23818        keep_values: true,
23819        url_converter: editor.convertURL,
23820        url_converter_scope: editor,
23821        hex_colors: settings.force_hex_style_colors,
23822        update_styles: true,
23823        root_element: editor.inline ? editor.getBody() : null,
23824        collect: function () {
23825          return editor.inline;
23826        },
23827        schema: editor.schema,
23828        contentCssCors: Settings.shouldUseContentCssCors(editor),
23829        onSetAttrib: function (e) {
23830          editor.fire('SetAttrib', e);
23831        }
23832      });
23833      editor.parser = createParser(editor);
23834      editor.serializer = Serializer$1(settings, editor);
23835      editor.selection = Selection(editor.dom, editor.getWin(), editor.serializer, editor);
23836      editor.annotator = Annotator(editor);
23837      editor.formatter = Formatter(editor);
23838      editor.undoManager = UndoManager(editor);
23839      editor._nodeChangeDispatcher = new NodeChange(editor);
23840      editor._selectionOverrides = SelectionOverrides(editor);
23841      setup$g(editor);
23842      setup$f(editor);
23843      KeyboardOverrides.setup(editor);
23844      ForceBlocks.setup(editor);
23845      editor.fire('PreInit');
23846      if (!settings.browser_spellcheck && !settings.gecko_spellcheck) {
23847        doc.body.spellcheck = false;
23848        DOM$2.setAttrib(body, 'spellcheck', 'false');
23849      }
23850      editor.quirks = Quirks(editor);
23851      editor.fire('PostRender');
23852      if (settings.directionality) {
23853        body.dir = settings.directionality;
23854      }
23855      if (settings.protect) {
23856        editor.on('BeforeSetContent', function (e) {
23857          Tools.each(settings.protect, function (pattern) {
23858            e.content = e.content.replace(pattern, function (str) {
23859              return '<!--mce:protected ' + escape(str) + '-->';
23860            });
23861          });
23862        });
23863      }
23864      editor.on('SetContent', function () {
23865        editor.addVisual(editor.getBody());
23866      });
23867      editor.load({
23868        initial: true,
23869        format: 'html'
23870      });
23871      editor.startContent = editor.getContent({ format: 'raw' });
23872      editor.on('compositionstart compositionend', function (e) {
23873        editor.composing = e.type === 'compositionstart';
23874      });
23875      if (editor.contentStyles.length > 0) {
23876        contentCssText = '';
23877        Tools.each(editor.contentStyles, function (style) {
23878          contentCssText += style + '\r\n';
23879        });
23880        editor.dom.addStyle(contentCssText);
23881      }
23882      getStyleSheetLoader(editor).loadAll(editor.contentCSS, function (_) {
23883        initEditor(editor);
23884      }, function (urls) {
23885        initEditor(editor);
23886      });
23887      if (settings.content_style) {
23888        appendStyle(editor, settings.content_style);
23889      }
23890    };
23891    var InitContentBody = { initContentBody: initContentBody };
23892
23893    var DOM$3 = DOMUtils$1.DOM;
23894    var relaxDomain = function (editor, ifr) {
23895      if (domGlobals.document.domain !== domGlobals.window.location.hostname && Env.ie && Env.ie < 12) {
23896        var bodyUuid = Uuid.uuid('mce');
23897        editor[bodyUuid] = function () {
23898          InitContentBody.initContentBody(editor);
23899        };
23900        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);})()';
23901        DOM$3.setAttrib(ifr, 'src', domainRelaxUrl);
23902        return true;
23903      }
23904      return false;
23905    };
23906    var createIframeElement = function (id, title, height, customAttrs) {
23907      var iframe = Element.fromTag('iframe');
23908      setAll(iframe, customAttrs);
23909      setAll(iframe, {
23910        id: id + '_ifr',
23911        frameBorder: '0',
23912        allowTransparency: 'true',
23913        title: title
23914      });
23915      add$3(iframe, 'tox-edit-area__iframe');
23916      return iframe;
23917    };
23918    var getIframeHtml = function (editor) {
23919      var bodyId, bodyClass, iframeHTML;
23920      iframeHTML = Settings.getDocType(editor) + '<html><head>';
23921      if (Settings.getDocumentBaseUrl(editor) !== editor.documentBaseUrl) {
23922        iframeHTML += '<base href="' + editor.documentBaseURI.getURI() + '" />';
23923      }
23924      iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
23925      bodyId = Settings.getBodyId(editor);
23926      bodyClass = Settings.getBodyClass(editor);
23927      if (Settings.getContentSecurityPolicy(editor)) {
23928        iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + Settings.getContentSecurityPolicy(editor) + '" />';
23929      }
23930      iframeHTML += '</head><body id="' + bodyId + '" class="mce-content-body ' + bodyClass + '" data-id="' + editor.id + '"><br></body></html>';
23931      return iframeHTML;
23932    };
23933    var createIframe = function (editor, o) {
23934      var title = editor.editorManager.translate('Rich Text Area. Press ALT
23934-0 for help.');
23935      var ifr = createIframeElement(editor.id, title, o.height, Settings.getIframeAttrs(editor)).dom();
23936      ifr.onload = function () {
23937        ifr.onload = null;
23938        editor.fire('load');
23939      };
23940      var isDomainRelaxed = relaxDomain(editor, ifr);
23941      editor.contentAreaContainer = o.iframeContainer;
23942      editor.iframeElement = ifr;
23943      editor.iframeHTML = getIframeHtml(editor);
23944      DOM$3.add(o.iframeContainer, ifr);
23945      return isDomainRelaxed;
23946    };
23947    var init$1 = function (editor, boxInfo) {
23948      var isDomainRelaxed = createIframe(editor, boxInfo);
23949      if (boxInfo.editorContainer) {
23950        DOM$3.get(boxInfo.editorContainer).style.display = editor.orgDisplay;
23951        editor.hidden = DOM$3.isHidden(boxInfo.editorContainer);
23952      }
23953      editor.getElement().style.display = 'none';
23954      DOM$3.setAttrib(editor.id, 'aria-hidden', 'true');
23955      if (!isDomainRelaxed) {
23956        InitContentBody.initContentBody(editor);
23957      }
23958    };
23959    var InitIframe = { init: init$1 };
23960
23961    var isContentCssSkinName = function (url) {
23962      return /^[a-z0-9\-]+$/i.test(url);
23963    };
23964    var getContentCssUrls = function (editor) {
23965      var contentCss = Settings.getContentCss(editor);
23966      var skinUrl = editor.editorManager.baseURL + '/skins/content';
23967      var suffix = editor.editorManager.suffix;
23968      var contentCssFile = 'content' + suffix + '.css';
23969      var inline = editor.inline === true;
23970      return map(contentCss, function (url) {
23971        if (isContentCssSkinName(url) && !inline) {
23972          return skinUrl + '/' + url + '/' + contentCssFile;
23973        } else {
23974          return editor.documentBaseURI.toAbsolute(url);
23975        }
23976      });
23977    };
23978    var appendContentCssFromSettings = function (editor) {
23979      editor.contentCSS = editor.contentCSS.concat(getContentCssUrls(editor));
23980    };
23981
23982    var DOM$4 = DOMUtils$1.DOM;
23983    var initPlugin = function (editor, initializedPlugins, plugin) {
23984      var Plugin = PluginManager$1.get(plugin);
23985      var pluginUrl = PluginManager$1.urls[plugin] || editor.documentBaseUrl.replace(/\/$/, '');
23986      plugin = Tools.trim(plugin);
23987      if (Plugin && Tools.inArray(initializedPlugins, plugin) === -1) {
23988        Tools.each(PluginManager$1.dependencies(plugin), function (dep) {
23989          initPlugin(editor, initializedPlugins, dep);
23990        });
23991        if (editor.plugins[plugin]) {
23992          return;
23993        }
23994        try {
23995          var pluginInstance = new Plugin(editor, pluginUrl, editor.$);
23996          editor.plugins[plugin] = pluginInstance;
23997          if (pluginInstance.init) {
23998            pluginInstance.init(editor, pluginUrl);
23999            initializedPlugins.push(plugin);
24000          }
24001        } catch (e) {
24002          ErrorReporter.pluginInitError(editor, plugin, e);
24003        }
24004      }
24005    };
24006    var trimLegacyPrefix = function (name) {
24007      return name.replace(/^\-/, '');
24008    };
24009    var initPlugins = function (editor) {
24010      var initializedPlugins = [];
24011      Tools.each(editor.settings.plugins.split(/[ ,]/), function (name) {
24012        initPlugin(editor, initializedPlugins, trimLegacyPrefix(name));
24013      });
24014    };
24015    var initIcons = function (editor) {
24016      var iconPackName = Tools.trim(editor.settings.icons);
24017      var currentIcons = editor.ui.registry.getAll().icons;
24018      var defaultIcons = getAll();
24019      var loadIcons = __assign({}, defaultIcons, IconManager.get(iconPackName).icons);
24020      each$3(loadIcons, function (svgData, icon) {
24021        if (!has(currentIcons, icon)) {
24022          editor.ui.registry.addIcon(icon, svgData);
24023        }
24024      });
24025    };
24026    var initTheme = function (editor) {
24027      var theme = editor.settings.theme;
24028      if (isString(theme)) {
24029        editor.settings.theme = trimLegacyPrefix(theme);
24030        var Theme = ThemeManager.get(theme);
24031        editor.theme = new Theme(editor, ThemeManager.urls[theme]);
24032        if (editor.theme.init) {
24033          editor.theme.init(editor, ThemeManager.urls[theme] || editor.documentBaseUrl.replace(/\/$/, ''), editor.$);
24034        }
24035      } else {
24036        editor.theme = {};
24037      }
24038    };
24039    var renderFromLoadedTheme = function (editor) {
24040      return editor.theme.renderUI();
24041    };
24042    var renderFromThemeFunc = function (editor) {
24043      var elm = editor.getElement();
24044      var theme = editor.settings.theme;
24045      var info = theme(editor, elm);
24046      if (info.editorContainer.nodeType) {
24047        info.editorContainer.id = info.editorContainer.id || editor.id + '_parent';
24048      }
24049      if (info.iframeContainer && info.iframeContainer.nodeType) {
24050        info.iframeContainer.id = info.iframeContainer.id || editor.id + '_iframecontainer';
24051      }
24052      info.height = info.iframeHeight ? info.iframeHeight : elm.offsetHeight;
24053      return info;
24054    };
24055    var createThemeFalseResult = function (element) {
24056      return {
24057        editorContainer: element,
24058        iframeContainer: element
24059      };
24060    };
24061    var renderThemeFalseIframe = function (targetElement) {
24062      var iframeContainer = DOM$4.create('div');
24063      DOM$4.insertAfter(iframeContainer, targetElement);
24064      return createThemeFalseResult(iframeContainer);
24065    };
24066    var renderThemeFalse = function (editor) {
24067      var targetElement = editor.getElement();
24068      return editor.inline ? createThemeFalseResult(null) : renderThemeFalseIframe(targetElement);
24069    };
24070    var renderThemeUi = function (editor) {
24071      var elm = editor.getElement();
24072      editor.orgDisplay = elm.style.display;
24073      if (isString(editor.settings.theme)) {
24074        return renderFromLoadedTheme(editor);
24075      } else if (isFunction(editor.settings.theme)) {
24076        return renderFromThemeFunc(editor);
24077      } else {
24078        return renderThemeFalse(editor);
24079      }
24080    };
24081    var init$2 = function (editor) {
24082      editor.fire('ScriptsLoaded');
24083      initIcons(editor);
24084      initTheme(editor);
24085      initPlugins(editor);
24086      var boxInfo = renderThemeUi(editor);
24087      editor.editorContainer = boxInfo.editorContainer ? boxInfo.editorContainer : null;
24088      appendContentCssFromSettings(editor);
24089      if (editor.inline) {
24090        return InitContentBody.initContentBody(editor);
24091      } else {
24092        return InitIframe.init(editor, boxInfo);
24093      }
24094    };
24095    var Init = { init: init$2 };
24096
24097    var DOM$5 = DOMUtils$1.DOM;
24098    var hasSkipLoadPrefix = function (name) {
24099      return name.charAt(0) === '-';
24100    };
24101    var loadLanguage = function (scriptLoader, editor) {
24102      var languageCode = Settings.getLanguageCode(editor);
24103      var languageUrl = Settings.getLanguageUrl(editor);
24104      if (I18n.hasCode(languageCode) === false && languageCode !== 'en') {
24105        if (languageUrl !== '') {
24106          scriptLoader.add(languageUrl);
24107        } else {
24108          scriptLoader.add(editor.editorManager.baseURL + '/langs/' + languageCode + '.js');
24109        }
24110      }
24111    };
24112    var loadTheme = function (scriptLoader, editor, suffix, callback) {
24113      var settings = editor.settings, theme = settings.theme;
24114      if (isString(theme)) {
24115        if (!hasSkipLoadPrefix(theme) && !ThemeManager.urls.hasOwnProperty(theme)) {
24116          var themeUrl = settings.theme_url;
24117          if (themeUrl) {
24118            ThemeManager.load(theme, editor.documentBaseURI.toAbsolute(themeUrl));
24119          } else {
24120            ThemeManager.load(theme, 'themes/' + theme + '/theme' + suffix + '.js');
24121          }
24122        }
24123        scriptLoader.loadQueue(function () {
24124          ThemeManager.waitFor(theme, callback);
24125        });
24126      } else {
24127        callback();
24128      }
24129    };
24130    var loadIcons = function (editor) {
24131      var iconPackName = Tools.trim(editor.getParam('icons', '', 'string'));
24132      if (iconPackName.length > 0 && !IconManager.has(iconPackName)) {
24133        var urlString = editor.editorManager.baseURL + '/icons/' + iconPackName + '/icons.js';
24134        ScriptLoader.ScriptLoader.add(urlString);
24135      }
24136    };
24137    var loadPlugins = function (settings, suffix) {
24138      if (Tools.isArray(settings.plugins)) {
24139        settings.plugins = settings.plugins.join(' ');
24140      }
24141      Tools.each(settings.external_plugins, function (url, name) {
24142        PluginManager$1.load(name, url);
24143        settings.plugins += ' ' + name;
24144      });
24145      Tools.each(settings.plugins.split(/[ ,]/), function (plugin) {
24146        plugin = Tools.trim(plugin);
24147        if (plugin && !PluginManager$1.urls[plugin]) {
24148          if (hasSkipLoadPrefix(plugin)) {
24149            plugin = plugin.substr(1, plugin.length);
24150            var dependencies = PluginManager$1.dependencies(plugin);
24151            Tools.each(dependencies, function (dep) {
24152              var defaultSettings = {
24153                prefix: 'plugins/',
24154                resource: dep,
24155                suffix: '/plugin' + suffix + '.js'
24156              };
24157              dep = PluginManager$1.createUrl(defaultSettings, dep);
24158              PluginManager$1.load(dep.resource, dep);
24159            });
24160          } else {
24161            PluginManager$1.load(plugin, {
24162              prefix: 'plugins/',
24163              resource: plugin,
24164              suffix: '/plugin' + suffix + '.js'
24165            });
24166          }
24167        }
24168      });
24169    };
24170    var loadScripts = function (editor, suffix) {
24171      var scriptLoader = ScriptLoader.ScriptLoader;
24172      loadTheme(scriptLoader, editor, suffix, function () {
24173        loadLanguage(scriptLoader, editor);
24174        loadIcons(editor);
24175        loadPlugins(editor.settings, suffix);
24176        scriptLoader.loadQueue(function () {
24177          if (!editor.removed) {
24178            Init.init(editor);
24179          }
24180        }, editor, function (urls) {
24181          ErrorReporter.pluginLoadError(editor, urls[0]);
24182          if (!editor.removed) {
24183            Init.init(editor);
24184          }
24185        });
24186      });
24187    };
24188    var render = function (editor) {
24189      var settings = editor.settings, id = editor.id;
24190      I18n.setCode(Settings.getLanguageCode(editor));
24191      var readyHandler = function () {
24192        DOM$5.unbind(domGlobals.window, 'ready', readyHandler);
24193        editor.render();
24194      };
24195      if (!EventUtils.Event.domLoaded) {
24196        DOM$5.bind(domGlobals.window, 'ready', readyHandler);
24197        return;
24198      }
24199      if (!editor.getElement()) {
24200        return;
24201      }
24202      if (!Env.contentEditable) {
24203        return;
24204      }
24205      if (!settings.inline) {
24206        editor.orgVisibility = editor.getElement().style.visibility;
24207        editor.getElement().style.visibility = 'hidden';
24208      } else {
24209        editor.inline = true;
24210      }
24211      var form = editor.getElement().form || DOM$5.getParent(id, 'form');
24212      if (form) {
24213        editor.formElement = form;
24214        if (settings.hidden_input && !/TEXTAREA|INPUT/i.test(editor.getElement().nodeName)) {
24215          DOM$5.insertAfter(DOM$5.create('input', {
24216            type: 'hidden',
24217            name: id
24218          }), id);
24219          editor.hasHiddenInput = true;
24220        }
24221        editor.formEventDelegate = function (e) {
24222          editor.fire(e.type, e);
24223        };
24224        DOM$5.bind(form, 'submit reset', editor.formEventDelegate);
24225        editor.on('reset', function () {
24226          editor.resetContent();
24227        });
24228        if (settings.submit_patch && !form.submit.nodeType && !form.submit.length && !form._mceOldSubmit) {
24229          form._mceOldSubmit = form.submit;
24230          form.submit = function () {
24231            editor.editorManager.triggerSave();
24232            editor.setDirty(false);
24233            return form._mceOldSubmit(form);
24234          };
24235        }
24236      }
24237      editor.windowManager = WindowManager(editor);
24238      editor.notificationManager = NotificationManager(editor);
24239      if (settings.encoding === 'xml') {
24240        editor.on('GetContent', function (e) {
24241          if (e.save) {
24242            e.content = DOM$5.encode(e.content);
24243          }
24244        });
24245      }
24246      if (settings.add_form_submit_trigger) {
24247        editor.on('submit', function () {
24248          if (editor.initialized) {
24249            editor.save();
24250          }
24251        });
24252      }
24253      if (settings.add_unload_trigger) {
24254        editor._beforeUnload = function () {
24255          if (editor.initialized && !editor.destroyed && !editor.isHidden()) {
24256            editor.save({
24257              format: 'raw',
24258              no_events: true,
24259              set_dirty: false
24260            });
24261          }
24262        };
24263        editor.editorManager.on('BeforeUnload', editor._beforeUnload);
24264      }
24265      editor.editorManager.add(editor);
24266      loadScripts(editor, editor.suffix);
24267    };
24268    var Render = { render: render };
24269
24270    var toggleClass = function (elm, cls, state) {
24271      if (has$2(elm, cls) && state === false) {
24272        remove$4(elm, cls);
24273      } else if (state) {
24274        add$3(elm, cls);
24275      }
24276    };
24277    var create$3 = function (editor) {
24278      var activeMode = 'design';
24279      var defaultModes = [
24280        'design',
24281        'readonly'
24282      ];
24283      var availableModes = {
24284        design: {
24285          activate: noop,
24286          deactivate: noop,
24287          editorReadOnly: false
24288        },
24289        readonly: {
24290          activate: noop,
24291          deactivate: noop,
24292          editorReadOnly: true
24293        }
24294      };
24295      var setEditorCommandState = function (cmd, state) {
24296        try {
24297          editor.getDoc().execCommand(cmd, false, state);
24298        } catch (ex) {
24299        }
24300      };
24301      var toggleReadOnly = function (state) {
24302        toggleClass(Element.fromDom(editor.getBody()), 'mce-content-readonly', state);
24303        if (state) {
24304          editor.selection.controlSelection.hideResizeRect();
24305          editor.readonly = true;
24306          editor.getBody().contentEditable = 'false';
24307        } else {
24308          editor.readonly = false;
24309          editor.getBody().contentEditable = 'true';
24310          setEditorCommandState('StyleWithCSS', false);
24311          setEditorCommandState('enableInlineTableEditing', false);
24312          setEditorCommandState('enableObjectResizing', false);
24313          editor.focus();
24314          editor.nodeChanged();
24315        }
24316      };
24317      var switchToMode = function (mode) {
24318        var oldMode = availableModes[activeMode];
24319        var newMode = availableModes[mode];
24320        try {
24321          newMode.activate();
24322        } catch (e) {
24323          domGlobals.console.error('problem while activating editor mode ' + mode + ':', e);
24324          return;
24325        }
24326        oldMode.deactivate();
24327        if (oldMode.editorReadOnly !== newMode.editorReadOnly) {
24328          toggleReadOnly(newMode.editorReadOnly);
24329        }
24330        activeMode = mode;
24331        Events.fireSwitchMode(editor, mode);
24332      };
24333      var set = function (mode) {
24334        if (mode === activeMode) {
24335          return;
24336        } else if (!has(availableModes, mode)) {
24337          throw new Error('Editor mode \'' + mode + '\' is invalid');
24338        }
24339        if (editor.initialized) {
24340          switchToMode(mode);
24341        } else {
24342          editor.on('init', function () {
24343            return switchToMode(mode);
24344          });
24345        }
24346      };
24347      var get = function () {
24348        return activeMode;
24349      };
24350      var isReadOnly = function () {
24351        return editor.readonly === true;
24352      };
24353      var register = function (mode, api) {
24354        if (contains(defaultModes, mode)) {
24355          throw new Error('Cannot override default mode ' + mode);
24356        }
24357        availableModes[mode] = __assign({}, api, {
24358          deactivate: function () {
24359            try {
24360              api.deactivate();
24361            } catch (e) {
24362              domGlobals.console.error('problem while deactivating editor mode ' + mode + ':');
24363              domGlobals.console.error(e);
24364            }
24365          }
24366        });
24367      };
24368      return {
24369        isReadOnly: isReadOnly,
24370        set: set,
24371        get: get,
24372        register: register
24373      };
24374    };
24375
24376    var hasOnlyOneChild$1 = function (node) {
24377      return node.firstChild && node.firstChild === node.lastChild;
24378    };
24379    var isPaddingNode = function (node) {
24380      return node.name === 'br' || node.value === '\xA0';
24381    };
24382    var isPaddedEmptyBlock = function (schema, node) {
24383      var blockElements = schema.getBlockElements();
24384      return blockElements[node.name] && hasOnlyOneChild$1(node) && isPaddingNode(node.firstChild);
24385    };
24386    var isEmptyFragmentElement = function (schema, node) {
24387      var nonEmptyElements = schema.getNonEmptyElements();
24388      return node && (node.isEmpty(nonEmptyElements) || isPaddedEmptyBlock(schema, node));
24389    };
24390    var isListFragment = function (schema, fragment) {
24391      var firstChild = fragment.firstChild;
24392      var lastChild = fragment.lastChild;
24393      if (firstChild && firstChild.name === 'meta') {
24394        firstChild = firstChild.next;
24395      }
24396      if (lastChild && lastChild.attr('id') === 'mce_marker') {
24397        lastChild = lastChild.prev;
24398      }
24399      if (isEmptyFragmentElement(schema, lastChild)) {
24400        lastChild = lastChild.prev;
24401      }
24402      if (!firstChild || firstChild !== lastChild) {
24403        return false;
24404      }
24405      return firstChild.name === 'ul' || firstChild.name === 'ol';
24406    };
24407    var cleanupDomFragment = function (domFragment) {
24408      var firstChild = domFragment.firstChild;
24409      var lastChild = domFragment.lastChild;
24410      if (firstChild && firstChild.nodeName === 'META') {
24411        firstChild.parentNode.removeChild(firstChild);
24412      }
24413      if (lastChild && lastChild.id === 'mce_marker') {
24414        lastChild.parentNode.removeChild(lastChild);
24415      }
24416      return domFragment;
24417    };
24418    var toDomFragment = function (dom, serializer, fragment) {
24419      var html = serializer.serialize(fragment);
24420      var domFragment = dom.createFragment(html);
24421      return cleanupDomFragment(domFragment);
24422    };
24423    var listItems$1 = function (elm) {
24424      return Tools.grep(elm.childNodes, function (child) {
24425        return child.nodeName === 'LI';
24426      });
24427    };
24428    var isPadding = function (node) {
24429      return node.data === '\xA0' || NodeType.isBr(node);
24430    };
24431    var isListItemPadded = function (node) {
24432      return node && node.firstChild && node.firstChild === node.lastChild && isPadding(node.firstChild);
24433    };
24434    var isEmptyOrPadded = function (elm) {
24435      return !elm.firstChild || isListItemPadded(elm);
24436    };
24437    var trimListItems = function (elms) {
24438      return elms.length > 0 && isEmptyOrPadded(elms[elms.length - 1]) ? elms.slice(0, -1) : elms;
24439    };
24440    var getParentLi = function (dom, node) {
24441      var parentBlock = dom.getParent(node, dom.isBlock);
24442      return parentBlock && parentBlock.nodeName === 'LI' ? parentBlock : null;
24443    };
24444    var isParentBlockLi = function (dom, node) {
24445      return !!getParentLi(dom, node);
24446    };
24447    var getSplit = function (parentNode, rng) {
24448      var beforeRng = rng.cloneRange();
24449      var afterRng = rng.cloneRange();
24450      beforeRng.setStartBefore(parentNode);
24451      afterRng.setEndAfter(parentNode);
24452      return [
24453        beforeRng.cloneContents(),
24454        afterRng.cloneContents()
24455      ];
24456    };
24457    var findFirstIn = function (node, rootNode) {
24458      var caretPos = CaretPosition$1.before(node);
24459      var caretWalker = CaretWalker(rootNode);
24460      var newCaretPos = caretWalker.next(caretPos);
24461      return newCaretPos ? newCaretPos.toRange() : null;
24462    };
24463    var findLastOf = function (node, rootNode) {
24464      var caretPos = CaretPosition$1.after(node);
24465      var caretWalker = CaretWalker(rootNode);
24466      var newCaretPos = caretWalker.prev(caretPos);
24467      return newCaretPos ? newCaretPos.toRange() : null;
24468    };
24469    var insertMiddle = function (target, elms, rootNode, rng) {
24470      var parts = getSplit(target, rng);
24471      var parentElm = target.parentNode;
24472      parentElm.insertBefore(parts[0], target);
24473      Tools.each(elms, function (li) {
24474        parentElm.insertBefore(li, target);
24475      });
24476      parentElm.insertBefore(parts[1], target);
24477      parentElm.removeChild(target);
24478      return findLastOf(elms[elms.length - 1], rootNode);
24479    };
24480    var insertBefore$1 = function (target, elms, rootNode) {
24481      var parentElm = target.parentNode;
24482      Tools.each(elms, function (elm) {
24483        parentElm.insertBefore(elm, target);
24484      });
24485      return findFirstIn(target, rootNode);
24486    };
24487    var insertAfter$1 = function (target, elms, rootNode, dom) {
24488      dom.insertAfter(elms.reverse(), target);
24489      return findLastOf(elms[0], rootNode);
24490    };
24491    var insertAtCaret = function (serializer, dom, rng, fragment) {
24492      var domFragment = toDomFragment(dom, serializer, fragment);
24493      var liTarget = getParentLi(dom, rng.startContainer);
24494      var liElms = trimListItems(listItems$1(domFragment.firstChild));
24495      var BEGINNING = 1, END = 2;
24496      var rootNode = dom.getRoot();
24497      var isAt = function (location) {
24498        var caretPos = CaretPosition$1.fromRangeStart(rng);
24499        var caretWalker = CaretWalker(dom.getRoot());
24500        var newPos = location === BEGINNING ? caretWalker.prev(caretPos) : caretWalker.next(caretPos);
24501        return newPos ? getParentLi(dom, newPos.getNode()) !== liTarget : true;
24502      };
24503      if (isAt(BEGINNING)) {
24504        return insertBefore$1(liTarget, liElms, rootNode);
24505      } else if (isAt(END)) {
24506        return insertAfter$1(liTarget, liElms, rootNode, dom);
24507      }
24508      return insertMiddle(liTarget, liElms, rootNode, rng);
24509    };
24510    var InsertList = {
24511      isListFragment: isListFragment,
24512      insertAtCaret: insertAtCaret,
24513      isParentBlockLi: isParentBlockLi,
24514      trimListItems: trimListItems,
24515      listItems: listItems$1
24516    };
24517
24518    var isAfterNbsp = function (container, offset) {
24519      return NodeType.isText(container) && container.nodeValue[offset - 1] === '\xA0';
24520    };
24521    var trimOrPadLeftRight = function (rng, html) {
24522      var container, offset;
24523      container = rng.startContainer;
24524      offset = rng.startOffset;
24525      var hasSiblingText = function (siblingName) {
24526        return container[siblingName] && container[siblingName].nodeType === 3;
24527      };
24528      if (container.nodeType === 3) {
24529        if (offset > 0) {
24530          html = html.replace(/^&nbsp;/, ' ');
24531        } else if (!hasSiblingText('previousSibling')) {
24532          html = html.replace(/^ /, '&nbsp;');
24533        }
24534        if (offset < container.length) {
24535          html = html.replace(/&nbsp;(<br>|)$/, ' ');
24536        } else if (!hasSiblingText('nextSibling')) {
24537          html = html.replace(/(&nbsp;| )(<br>|)$/, '&nbsp;');
24538        }
24539      }
24540      return html;
24541    };
24542    var trimNbspAfterDeleteAndPadValue = function (rng, value) {
24543      var container, offset;
24544      container = rng.startContainer;
24545      offset = rng.startOffset;
24546      if (container.nodeType === 3 && rng.collapsed) {
24547        if (container.data[offset] === '\xA0') {
24548          container.deleteData(offset, 1);
24549          if (!/[\u00a0| ]$/.test(value)) {
24550            value += ' ';
24551          }
24552        } else if (container.data[offset - 1] === '\xA0') {
24553          container.deleteData(offset - 1, 1);
24554          if (!/[\u00a0| ]$/.test(value)) {
24555            value = ' ' + value;
24556          }
24557        }
24558      }
24559      return value;
24560    };
24561
24562    var isTableCell$5 = NodeType.matchNodeNames('td th');
24563    var selectionSetContent = function (editor, content) {
24564      var rng = editor.selection.getRng();
24565      var container = rng.startContainer;
24566      var offset = rng.startOffset;
24567      if (rng.collapsed && isAfterNbsp(container, offset) && NodeType.isText(container)) {
24568        container.insertData(offset - 1, ' ');
24569        container.deleteData(offset, 1);
24570        rng.setStart(container, offset);
24571        rng.setEnd(container, offset);
24572        editor.selection.setRng(rng);
24573      }
24574      editor.selection.setContent(content);
24575    };
24576    var validInsertion = function (editor, value, parentNode) {
24577      if (parentNode.getAttribute('data-mce-bogus') === 'all') {
24578        parentNode.parentNode.insertBefore(editor.dom.createFragment(value), parentNode);
24579      } else {
24580        var node = parentNode.firstChild;
24581        var node2 = parentNode.lastChild;
24582        if (!node || node === node2 && node.nodeName === 'BR') {
24583          editor.dom.setHTML(parentNode, value);
24584        } else {
24585          selectionSetContent(editor, value);
24586        }
24587      }
24588    };
24589    var trimBrsFromTableCell = function (dom, elm) {
24590      Option.from(dom.getParent(elm, 'td,th')).map(Element.fromDom).each(PaddingBr.trimBlockTrailingBr);
24591    };
24592    var reduceInlineTextElements = function (editor, merge) {
24593      var textInlineElements = editor.schema.getTextInlineElements();
24594      var dom = editor.dom;
24595      if (merge) {
24596        var root_1 = editor.getBody(), elementUtils_1 = new ElementUtils(dom);
24597        Tools.each(dom.select('*[data-mce-fragment]'), function (node) {
24598          for (var testNode = node.parentNode; testNode && testNode !== root_1; testNode = testNode.parentNode) {
24599            if (textInlineElements[node.nodeName.toLowerCase()] && elementUtils_1.compare(testNode, node)) {
24600              dom.remove(node, true);
24601            }
24602          }
24603        });
24604      }
24605    };
24606    var markFragmentElements = function (fragment) {
24607      var node = fragment;
24608      while (node = node.walk()) {
24609        if (node.type === 1) {
24610          node.attr('data-mce-fragment', '1');
24611        }
24612      }
24613    };
24614    var umarkFragmentElements = function (elm) {
24615      Tools.each(elm.getElementsByTagName('*'), function (elm) {
24616        elm.removeAttribute('data-mce-fragment');
24617      });
24618    };
24619    var isPartOfFragment = function (node) {
24620      return !!node.getAttribute('data-mce-fragment');
24621    };
24622    var canHaveChildren = function (editor, node) {
24623      return node && !editor.schema.getShortEndedElements()[node.nodeName];
24624    };
24625    var moveSelectionToMarker = function (editor, marker) {
24626      var parentEditableFalseElm, parentBlock, nextRng;
24627      var dom = editor.dom, selection = editor.selection;
24628      var node, node2;
24629      var getContentEditableFalseParent = function (node) {
24630        var root = editor.getBody();
24631        for (; node && node !== root; node = node.parentNode) {
24632          if (editor.dom.getContentEditable(node) === 'false') {
24633            return node;
24634          }
24635        }
24636        return null;
24637      };
24638      if (!marker) {
24639        return;
24640      }
24641      editor.selection.scrollIntoView(marker);
24642      parentEditableFalseElm = getContentEditableFalseParent(marker);
24643      if (parentEditableFalseElm) {
24644        dom.remove(marker);
24645        selection.select(parentEditableFalseElm);
24646        return;
24647      }
24648      var rng = dom.createRng();
24649      node = marker.previousSibling;
24650      if (node && node.nodeType === 3) {
24651        rng.setStart(node, node.nodeValue.length);
24652        if (!Env.ie) {
24653          node2 = marker.nextSibling;
24654          if (node2 && node2.nodeType === 3) {
24655            node.appendData(node2.data);
24656            node2.parentNode.removeChild(node2);
24657          }
24658        }
24659      } else {
24660        rng.setStartBefore(marker);
24661        rng.setEndBefore(marker);
24662      }
24663      var findNextCaretRng = function (rng) {
24664        var caretPos = CaretPosition$1.fromRangeStart(rng);
24665        var caretWalker = CaretWalker(editor.getBody());
24666        caretPos = caretWalker.next(caretPos);
24667        if (caretPos) {
24668          return caretPos.toRange();
24669        }
24670      };
24671      parentBlock = dom.getParent(marker, dom.isBlock);
24672      dom.remove(marker);
24673      if (parentBlock && dom.isEmpty(parentBlock)) {
24674        editor.$(parentBlock).empty();
24675        rng.setStart(parentBlock, 0);
24676        rng.setEnd(parentBlock, 0);
24677        if (!isTableCell$5(parentBlock) && !isPartOfFragment(parentBlock) && (nextRng = findNextCaretRng(rng))) {
24678          rng = nextRng;
24679          dom.remove(parentBlock);
24680        } else {
24681          dom.add(parentBlock, dom.create('br', { 'data-mce-bogus': '1' }));
24682        }
24683      }
24684      selection.setRng(rng);
24685    };
24686    var insertHtmlAtCaret = function (editor, value, details) {
24687      var parser, serializer, parentNode, rootNode, fragment, args;
24688      var marker, rng, node, bookmarkHtml, merge;
24689      var selection = editor.selection, dom = editor.dom;
24690      if (/^ | $/.test(value)) {
24691        value = trimOrPadLeftRight(selection.getRng(), value);
24692      }
24693      parser = editor.parser;
24694      merge = details.merge;
24695      serializer = Serializer({ validate: editor.settings.validate }, editor.schema);
24696      bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;&#x200B;</span>';
24697      args = {
24698        content: value,
24699        format: 'html',
24700        selection: true,
24701        paste: details.paste
24702      };
24703      args = editor.fire('BeforeSetContent', args);
24704      if (args.isDefaultPrevented()) {
24705        editor.fire('SetContent', {
24706          content: args.content,
24707          format: 'html',
24708          selection: true,
24709          paste: details.paste
24710        });
24711        return;
24712      }
24713      value = args.content;
24714      if (value.indexOf('{$caret}') === -1) {
24715        value += '{$caret}';
24716      }
24717      value = value.replace(/\{\$caret\}/, bookmarkHtml);
24718      rng = selection.getRng();
24719      var caretElement = rng.startContainer || (rng.parentElement ? rng.parentElement() : null);
24720      var body = editor.getBody();
24721      if (caretElement === body && selection.isCollapsed()) {
24722        if (dom.isBlock(body.firstChild) && canHaveChildren(editor, body.firstChild) && dom.isEmpty(body.firstChild)) {
24723          rng = dom.createRng();
24724          rng.setStart(body.firstChild, 0);
24725          rng.setEnd(body.firstChild, 0);
24726          selection.setRng(rng);
24727        }
24728      }
24729      if (!selection.isCollapsed()) {
24730        editor.selection.setRng(RangeNormalizer.normalize(editor.selection.getRng()));
24731        editor.getDoc().execCommand('Delete', false, null);
24732        value = trimNbspAfterDeleteAndPadValue(editor.selection.getRng(), value);
24733      }
24734      parentNode = selection.getNode();
24735      var parserArgs = {
24736        context: parentNode.nodeName.toLowerCase(),
24737        data: details.data,
24738        insert: true
24739      };
24740      fragment = parser.parse(value, parserArgs);
24741      if (details.paste === true && InsertList.isListFragment(editor.schema, fragment) && InsertList.isParentBlockLi(dom, parentNode)) {
24742        rng = InsertList.insertAtCaret(serializer, dom, editor.selection.getRng(), fragment);
24743        editor.selection.setRng(rng);
24744        editor.fire('SetContent', args);
24745        return;
24746      }
24747      markFragmentElements(fragment);
24748      node = fragment.lastChild;
24749      if (node.attr('id') === 'mce_marker') {
24750        marker = node;
24751        for (node = node.prev; node; node = node.walk(true)) {
24752          if (node.type === 3 || !dom.isBlock(node.name)) {
24753            if (editor.schema.isValidChild(node.parent.name, 'span')) {
24754              node.parent.insert(marker, node, node.name === 'br');
24755            }
24756            break;
24757          }
24758        }
24759      }
24760      editor._selectionOverrides.showBlockCaretContainer(parentNode);
24761      if (!parserArgs.invalid) {
24762        value = serializer.serialize(fragment);
24763        validInsertion(editor, value, parentNode);
24764      } else {
24765        selectionSetContent(editor, bookmarkHtml);
24766        parentNode = selection.getNode();
24767        rootNode = editor.getBody();
24768        if (parentNode.nodeType === 9) {
24769          parentNode = node = rootNode;
24770        } else {
24771          node = parentNode;
24772        }
24773        while (node !== rootNode) {
24774          parentNode = node;
24775          node = node.parentNode;
24776        }
24777        value = parentNode === rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode);
24778        value = serializer.serialize(parser.parse(value.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i, function () {
24779          return serializer.serialize(fragment);
24780        })));
24781        if (parentNode === rootNode) {
24782          dom.setHTML(rootNode, value);
24783        } else {
24784          dom.setOuterHTML(parentNode, value);
24785        }
24786      }
24787      reduceInlineTextElements(editor, merge);
24788      moveSelectionToMarker(editor, dom.get('mce_marker'));
24789      umarkFragmentElements(editor.getBody());
24790      trimBrsFromTableCell(editor.dom, editor.selection.getStart());
24791      editor.fire('SetContent', args);
24792      editor.addVisual();
24793    };
24794    var processValue = function (value) {
24795      var details;
24796      if (typeof value !== 'string') {
24797        details = Tools.extend({
24798          paste: value.paste,
24799          data: { paste: value.paste }
24800        }, value);
24801        return {
24802          content: value.content,
24803          details: details
24804        };
24805      }
24806      return {
24807        content: value,
24808        details: {}
24809      };
24810    };
24811    var insertAtCaret$1 = function (editor, value) {
24812      var result = processValue(value);
24813      insertHtmlAtCaret(editor, result.content, result.details);
24814    };
24815    var InsertContent = { insertAtCaret: insertAtCaret$1 };
24816
24817    var nativeCommand = function (editor, command) {
24818      editor.getDoc().execCommand(command, false, null);
24819    };
24820    var deleteCommand = function (editor) {
24821      if (CefDelete.backspaceDelete(editor, false)) {
24822        return;
24823      } else if (CefBoundaryDelete.backspaceDelete(editor, false)) {
24824        return;
24825      } else if (BoundaryDelete.backspaceDelete(editor, false)) {
24826        return;
24827      } else if (BlockBoundaryDelete.backspaceDelete(editor, false)) {
24828        return;
24829      } else if (TableDelete.backspaceDelete(editor)) {
24830        return;
24831      } else if (BlockRangeDelete.backspaceDelete(editor, false)) {
24832        return;
24833      } else if (InlineFormatDelete.backspaceDelete(editor, false)) {
24834        return;
24835      } else {
24836        nativeCommand(editor, 'Delete');
24837        DeleteUtils.paddEmptyBody(editor);
24838      }
24839    };
24840    var forwardDeleteCommand = function (editor) {
24841      if (CefDelete.backspaceDelete(editor, true)) {
24842        return;
24843      } else if (CefBoundaryDelete.backspaceDelete(editor, true)) {
24844        return;
24845      } else if (BoundaryDelete.backspaceDelete(editor, true)) {
24846        return;
24847      } else if (BlockBoundaryDelete.backspaceDelete(editor, true)) {
24848        return;
24849      } else if (TableDelete.backspaceDelete(editor)) {
24850        return;
24851      } else if (BlockRangeDelete.backspaceDelete(editor, true)) {
24852        return;
24853      } else if (InlineFormatDelete.backspaceDelete(editor, true)) {
24854        return;
24855      } else {
24856        nativeCommand(editor, 'ForwardDelete');
24857      }
24858    };
24859    var DeleteCommands = {
24860      deleteCommand: deleteCommand,
24861      forwardDeleteCommand: forwardDeleteCommand
24862    };
24863
24864    var getSpecifiedFontProp = function (propName, rootElm, elm) {
24865      var getProperty = function (elm) {
24866        return getRaw(elm, propName);
24867      };
24868      var isRoot = function (elm) {
24869        return eq(Element.fromDom(rootElm), elm);
24870      };
24871      return closest(Element.fromDom(elm), function (elm) {
24872        return getProperty(elm).isSome();
24873      }, isRoot).bind(getProperty);
24874    };
24875    var round$1 = function (number, precision) {
24876      var factor = Math.pow(10, precision);
24877      return Math.round(number * factor) / factor;
24878    };
24879    var toPt = function (fontSize, precision) {
24880      if (/[0-9.]+px$/.test(fontSize)) {
24881        return round$1(parseInt(fontSize, 10) * 72 / 96, precision || 0) + 'pt';
24882      }
24883      return fontSize;
24884    };
24885    var normalizeFontFamily = function (fontFamily) {
24886      return fontFamily.replace(/[\'\"\\]/g, '').replace(/,\s+/g, ',');
24887    };
24888    var getComputedFontProp = function (propName, elm) {
24889      return Option.from(DOMUtils$1.DOM.getStyle(elm, propName, true));
24890    };
24891    var getFontProp = function (propName) {
24892      return function (rootElm, elm) {
24893        return Option.from(elm).map(Element.fromDom).filter(isElement).bind(function (element) {
24894          return getSpecifiedFontProp(propName, rootElm, element.dom()).or(getComputedFontProp(propName, element.dom()));
24895        }).getOr('');
24896      };
24897    };
24898    var FontInfo = {
24899      getFontSize: getFontProp('font-size'),
24900      getFontFamily: compose(normalizeFontFamily, getFontProp('font-family')),
24901      toPt: toPt
24902    };
24903
24904    var findFirstCaretElement = function (editor) {
24905      return CaretFinder.firstPositionIn(editor.getBody()).map(function (caret) {
24906        var container = caret.container();
24907        return NodeType.isText(container) ? container.parentNode : container;
24908      });
24909    };
24910    var isRangeAtStartOfNode = function (rng, root) {
24911      return rng.startContainer === root && rng.startOffset === 0;
24912    };
24913    var getCaretElement = function (editor) {
24914      return Option.from(editor.selection.getRng()).bind(function (rng) {
24915        var root = editor.getBody();
24916        return isRangeAtStartOfNode(rng, root) ? Option.none() : Option.from(editor.selection.getStart(true));
24917      });
24918    };
24919    var fromFontSizeNumber = function (editor, value) {
24920      if (/^[0-9\.]+$/.test(value)) {
24921        var fontSizeNumber = parseInt(value, 10);
24922        if (fontSizeNumber >= 1 && fontSizeNumber <= 7) {
24923          var fontSizes = Settings.getFontStyleValues(editor);
24924          var fontClasses = Settings.getFontSizeClasses(editor);
24925          if (fontClasses) {
24926            return fontClasses[fontSizeNumber - 1] || value;
24927          } else {
24928            return fontSizes[fontSizeNumber - 1] || value;
24929          }
24930        } else {
24931          return value;
24932        }
24933      } else {
24934        return value;
24935      }
24936    };
24937    var fontNameAction = function (editor, value) {
24938      editor.formatter.toggle('fontname', { value: fromFontSizeNumber(editor, value) });
24939      editor.nodeChanged();
24940    };
24941    var fontNameQuery = function (editor) {
24942      return getCaretElement(editor).fold(function () {
24943        return findFirstCaretElement(editor).map(function (caretElement) {
24944          return FontInfo.getFontFamily(editor.getBody(), caretElement);
24945        }).getOr('');
24946      }, function (caretElement) {
24947        return FontInfo.getFontFamily(editor.getBody(), caretElement);
24948      });
24949    };
24950    var fontSizeAction = function (editor, value) {
24951      editor.formatter.toggle('fontsize', { value: fromFontSizeNumber(editor, value) });
24952      editor.nodeChanged();
24953    };
24954    var fontSizeQuery = function (editor) {
24955      return getCaretElement(editor).fold(function () {
24956        return findFirstCaretElement(editor).map(function (caretElement) {
24957          return FontInfo.getFontSize(editor.getBody(), caretElement);
24958        }).getOr('');
24959      }, function (caretElement) {
24960        return FontInfo.getFontSize(editor.getBody(), caretElement);
24961      });
24962    };
24963
24964    var isEditable$1 = function (target) {
24965      return closest(target, function (elm) {
24966        return NodeType.isContentEditableTrue(elm.dom()) || NodeType.isContentEditableFalse(elm.dom());
24967      }).exists(function (elm) {
24968        return NodeType.isContentEditableTrue(elm.dom());
24969      });
24970    };
24971    var parseIndentValue = function (value) {
24972      var number = parseInt(value, 10);
24973      return isNaN(number) ? 0 : number;
24974    };
24975    var getIndentStyleName = function (useMargin, element) {
24976      var indentStyleName = useMargin || isTable$1(element) ? 'margin' : 'padding';
24977      var suffix = get$2(element, 'direction') === 'rtl' ? '-right' : '-left';
24978      return indentStyleName + suffix;
24979    };
24980    var indentElement = function (dom, command, useMargin, value, unit, element) {
24981      var indentStyleName = getIndentStyleName(useMargin, Element.fromDom(element));
24982      if (command === 'outdent') {
24983        var styleValue = Math.max(0, parseIndentValue(element.style[indentStyleName]) - value);
24984        dom.setStyle(element, indentStyleName, styleValue ? styleValue + unit : '');
24985      } else {
24986        var styleValue = parseIndentValue(element.style[indentStyleName]) + value + unit;
24987        dom.setStyle(element, indentStyleName, styleValue);
24988      }
24989    };
24990    var validateBlocks = function (editor, blocks) {
24991      return forall(blocks, function (block) {
24992        var indentStyleName = getIndentStyleName(Settings.shouldIndentUseMargin(editor), block);
24993        var intentValue = getRaw(block, indentStyleName).map(parseIndentValue).getOr(0);
24994        var contentEditable = editor.dom.getContentEditable(block.dom());
24995        return contentEditable !== 'false' && intentValue > 0;
24996      });
24997    };
24998    var canOutdent = function (editor) {
24999      var blocks = getBlocksToIndent(editor);
25000      return editor.readonly !== true && (blocks.length > 1 || validateBlocks(editor, blocks));
25001    };
25002    var isListComponent = function (el) {
25003      return isList(el) || isListItem(el);
25004    };
25005    var parentIsListComponent = function (el) {
25006      return parent(el).map(isListComponent).getOr(false);
25007    };
25008    var getBlocksToIndent = function (editor) {
25009      return filter(map(editor.selection.getSelectedBlocks(), Element.fromDom), function (el) {
25010        return !isListComponent(el) && !parentIsListComponent(el) && isEditable$1(el);
25011      });
25012    };
25013    var handle = function (editor, command) {
25014      var dom = editor.dom, selection = editor.selection, formatter = editor.formatter;
25015      var indentation = Settings.getIndentation(editor);
25016      var indentUnit = /[a-z%]+$/i.exec(indentation)[0];
25017      var indentValue = parseInt(indentation, 10);
25018      var useMargin = Settings.shouldIndentUseMargin(editor);
25019      var forcedRootBlock = Settings.getForcedRootBlock(editor);
25020      if (!editor.queryCommandState('InsertUnorderedList') && !editor.queryCommandState('InsertOrderedList')) {
25021        if (forcedRootBlock === '' && !dom.getParent(selection.getNode(), dom.isBlock)) {
25022          formatter.apply('div');
25023        }
25024      }
25025      each(getBlocksToIndent(editor), function (block) {
25026        indentElement(dom, command, useMargin, indentValue, indentUnit, block.dom());
25027      });
25028    };
25029
25030    var each$g = Tools.each;
25031    var map$3 = Tools.map, inArray$2 = Tools.inArray;
25032    var EditorCommands = function () {
25033      function EditorCommands(editor) {
25034        this.commands = {
25035          state: {},
25036          exec: {},
25037          value: {}
25038        };
25039        this.editor = editor;
25040        this.setupCommands(editor);
25041      }
25042      EditorCommands.prototype.execCommand = function (command, ui, value, args) {
25043        var func, customCommand, state = false;
25044        var self = this;
25045        if (self.editor.removed) {
25046          return;
25047        }
25048        if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(command) && (!args || !args.skip_focus)) {
25049          self.editor.focus();
25050        } else {
25051          SelectionBookmark.restore(self.editor);
25052        }
25053        args = self.editor.fire('BeforeExecCommand', {
25054          command: command,
25055          ui: ui,
25056          value: value
25057        });
25058        if (args.isDefaultPrevented()) {
25059          return false;
25060        }
25061        customCommand = command.toLowerCase();
25062        if (func = self.commands.exec[customCommand]) {
25063          func(customCommand, ui, value);
25064          self.editor.fire('ExecCommand', {
25065            command: command,
25066            ui: ui,
25067            value: value
25068          });
25069          return true;
25070        }
25071        each$g(this.editor.plugins, function (p) {
25072          if (p.execCommand && p.execCommand(command, ui, value)) {
25073            self.editor.fire('ExecCommand', {
25074              command: command,
25075              ui: ui,
25076              value: value
25077            });
25078            state = true;
25079            return false;
25080          }
25081        });
25082        if (state) {
25083          return state;
25084        }
25085        if (self.editor.theme && self.editor.theme.execCommand && self.editor.theme.execCommand(command, ui, value)) {
25086          self.editor.fire('ExecCommand', {
25087            command: command,
25088            ui: ui,
25089            value: value
25090          });
25091          return true;
25092        }
25093        try {
25094          state = self.editor.getDoc().execCommand(command, ui, value);
25095        } catch (ex) {
25096        }
25097        if (state) {
25098          self.editor.fire('ExecCommand', {
25099            command: command,
25100            ui: ui,
25101            value: value
25102          });
25103          return true;
25104        }
25105        return false;
25106      };
25107      EditorCommands.prototype.queryCommandState = function (command) {
25108        var func;
25109        if (this.editor.quirks.isHidden() || this.editor.removed) {
25110          return;
25111        }
25112        command = command.toLowerCase();
25113        if (func = this.commands.state[command]) {
25114          return func(command);
25115        }
25116        try {
25117          return this.editor.getDoc().queryCommandState(command);
25118        } catch (ex) {
25119        }
25120        return false;
25121      };
25122      EditorCommands.prototype.queryCommandValue = function (command) {
25123        var func;
25124        if (this.editor.quirks.isHidden() || this.editor.removed) {
25125          return;
25126        }
25127        command = command.toLowerCase();
25128        if (func = this.commands.value[command]) {
25129          return func(command);
25130        }
25131        try {
25132          return this.editor.getDoc().queryCommandValue(command);
25133        } catch (ex) {
25134        }
25135      };
25136      EditorCommands.prototype.addCommands = function (commandList, type) {
25137        var self = this;
25138        type = type || 'exec';
25139        each$g(commandList, function (callback, command) {
25140          each$g(command.toLowerCase().split(','), function (command) {
25141            self.commands[type][command] = callback;
25142          });
25143        });
25144      };
25145      EditorCommands.prototype.addCommand = function (command, callback, scope) {
25146        var _this = this;
25147        command = command.toLowerCase();
25148        this.commands.exec[command] = function (command, ui, value, args) {
25149          return callback.call(scope || _this.editor, ui, value, args);
25150        };
25151      };
25152      EditorCommands.prototype.queryCommandSupported = function (command) {
25153        command = command.toLowerCase();
25154        if (this.commands.exec[command]) {
25155          return true;
25156        }
25157        try {
25158          return this.editor.getDoc().queryCommandSupported(command);
25159        } catch (ex) {
25160        }
25161        return false;
25162      };
25163      EditorCommands.prototype.addQueryStateHandler = function (command, callback, scope) {
25164        var _this = this;
25165        command = command.toLowerCase();
25166        this.commands.state[command] = function () {
25167          return callback.call(scope || _this.editor);
25168        };
25169      };
25170      EditorCommands.prototype.addQueryValueHandler = function (command, callback, scope) {
25171        var _this = this;
25172        command = command.toLowerCase();
25173        this.commands.value[command] = function () {
25174          return callback.call(scope || _this.editor);
25175        };
25176      };
25177      EditorCommands.prototype.hasCustomCommand = function (command) {
25178        command = command.toLowerCase();
25179        return !!this.commands.exec[command];
25180      };
25181      EditorCommands.prototype.execNativeCommand = function (command, ui, value) {
25182        if (ui === undefined) {
25183          ui = false;
25184        }
25185        if (value === undefined) {
25186          value = null;
25187        }
25188        return this.editor.getDoc().execCommand(command, ui, value);
25189      };
25190      EditorCommands.prototype.isFormatMatch = function (name) {
25191        return this.editor.formatter.match(name);
25192      };
25193      EditorCommands.prototype.toggleFormat = function (name, value) {
25194        this.editor.formatter.toggle(name, value ? { value: value } : undefined);
25195        this.editor.nodeChanged();
25196      };
25197      EditorCommands.prototype.storeSelection = function (type) {
25198        this.selectionBookmark = this.editor.selection.getBookmark(type);
25199      };
25200      EditorCommands.prototype.restoreSelection = function () {
25201        this.editor.selection.moveToBookmark(this.selectionBookmark);
25202      };
25203      EditorCommands.prototype.setupCommands = function (editor) {
25204        var self = this;
25205        this.addCommands({
25206          'mceResetDesignMode,mceBeginUndoLevel': function () {
25207          },
25208          'mceEndUndoLevel,mceAddUndoLevel': function () {
25209            editor.undoManager.add();
25210          },
25211          'Cut,Copy,Paste': function (command) {
25212            var doc = editor.getDoc();
25213            var failed;
25214            try {
25215              self.execNativeCommand(command);
25216            } catch (ex) {
25217              failed = true;
25218            }
25219            if (command === 'paste' && !doc.queryCommandEnabled(command)) {
25220              failed = true;
25221            }
25222            if (failed || !doc.queryCommandSupported(command)) {
25223              var msg = editor.translate('Your browser doesn\'t support direct access to the clipboard. ' + 'Please use the Ctrl+X/C/V keyboard shortcuts instead.');
25224              if (Env.mac) {
25225                msg = msg.replace(/Ctrl\+/g, '\u2318+');
25226              }
25227              editor.notificationManager.open({
25228                text: msg,
25229                type: 'error'
25230              });
25231            }
25232          },
25233          'unlink': function () {
25234            if (editor.selection.isCollapsed()) {
25235              var elm = editor.dom.getParent(editor.selection.getStart(), 'a');
25236              if (elm) {
25237                editor.dom.remove(elm, true);
25238              }
25239              return;
25240            }
25241            editor.formatter.remove('link');
25242          },
25243          'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull,JustifyNone': function (command) {
25244            var align = command.substring(7);
25245            if (align === 'full') {
25246              align = 'justify';
25247            }
25248            each$g('left,center,right,justify'.split(','), function (name) {
25249              if (align !== name) {
25250                editor.formatter.remove('align' + name);
25251              }
25252            });
25253            if (align !== 'none') {
25254              self.toggleFormat('align' + align);
25255            }
25256          },
25257          'InsertUnorderedList,InsertOrderedList': function (command) {
25258            var listElm, listParent;
25259            self.execNativeCommand(command);
25260            listElm = editor.dom.getParent(editor.selection.getNode(), 'ol,ul');
25261            if (listElm) {
25262              listParent = listElm.parentNode;
25263              if (/^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) {
25264                self.storeSelection();
25265                editor.dom.split(listParent, listElm);
25266                self.restoreSelection();
25267              }
25268            }
25269          },
25270          'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': function (command) {
25271            self.toggleFormat(command);
25272          },
25273          'ForeColor,HiliteColor': function (command, ui, value) {
25274            self.toggleFormat(command, value);
25275          },
25276          'FontName': function (command, ui, value) {
25277            fontNameAction(editor, value);
25278          },
25279          'FontSize': function (command, ui, value) {
25280            fontSizeAction(editor, value);
25281          },
25282          'RemoveFormat': function (command) {
25283            editor.formatter.remove(command);
25284          },
25285          'mceBlockQuote': function () {
25286            self.toggleFormat('blockquote');
25287          },
25288          'FormatBlock': function (command, ui, value) {
25289            return self.toggleFormat(value || 'p');
25290          },
25291          'mceCleanup': function () {
25292            var bookmark = editor.selection.getBookmark();
25293            editor.setContent(editor.getContent());
25294            editor.selection.moveToBookmark(bookmark);
25295          },
25296          'mceRemoveNode': function (command, ui, value) {
25297            var node = value || editor.selection.getNode();
25298            if (node !== editor.getBody()) {
25299              self.storeSelection();
25300              editor.dom.remove(node, true);
25301              self.restoreSelection();
25302            }
25303          },
25304          'mceSelectNodeDepth': function (command, ui, value) {
25305            var counter = 0;
25306            editor.dom.getParent(editor.selection.getNode(), function (node) {
25307              if (node.nodeType === 1 && counter++ === value) {
25308                editor.selection.select(node);
25309                return false;
25310              }
25311            }, editor.getBody());
25312          },
25313          'mceSelectNode': function (command, ui, value) {
25314            editor.selection.select(value);
25315          },
25316          'mceInsertContent': function (command, ui, value) {
25317            InsertContent.insertAtCaret(editor, value);
25318          },
25319          'mceInsertRawHTML': function (command, ui, value) {
25320            editor.selection.setContent('tiny_mce_marker');
25321            var content = editor.getContent();
25322            editor.setContent(content.replace(/tiny_mce_marker/g, function () {
25323              return value;
25324            }));
25325          },
25326          'mceInsertNewLine': function (command, ui, value) {
25327            InsertNewLine.insert(editor, value);
25328          },
25329          'mceToggleFormat': function (command, ui, value) {
25330            self.toggleFormat(value);
25331          },
25332          'mceSetContent': function (command, ui, value) {
25333            editor.setContent(value);
25334          },
25335          'Indent,Outdent': function (command) {
25336            handle(editor, command);
25337          },
25338          'mceRepaint': function () {
25339          },
25340          'InsertHorizontalRule': function () {
25341            editor.execCommand('mceInsertContent', false, '<hr />');
25342          },
25343          'mceToggleVisualAid': function () {
25344            editor.hasVisual = !editor.hasVisual;
25345            editor.addVisual();
25346          },
25347          'mceReplaceContent': function (command, ui, value) {
25348            editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, editor.selection.getContent({ format: 'text' })));
25349          },
25350          'mceInsertLink': function (command, ui, value) {
25351            var anchor;
25352            if (typeof value === 'string') {
25353              value = { href: value };
25354            }
25355            anchor = editor.dom.getParent(editor.selection.getNode(), 'a');
25356            value.href = value.href.replace(' ', '%20');
25357            if (!anchor || !value.href) {
25358              editor.formatter.remove('link');
25359            }
25360            if (value.href) {
25361              editor.formatter.apply('link', value, anchor);
25362            }
25363          },
25364          'selectAll': function () {
25365            var editingHost = editor.dom.getParent(editor.selection.getStart(), NodeType.isContentEditableTrue);
25366            if (editingHost) {
25367              var rng = editor.dom.createRng();
25368              rng.selectNodeContents(editingHost);
25369              editor.selection.setRng(rng);
25370            }
25371          },
25372          'delete': function () {
25373            DeleteCommands.deleteCommand(editor);
25374          },
25375          'forwardDelete': function () {
25376            DeleteCommands.forwardDeleteCommand(editor);
25377          },
25378          'mceNewDocument': function () {
25379            editor.setContent('');
25380          },
25381          'InsertLineBreak': function (command, ui, value) {
25382            InsertBr.insert(editor, value);
25383            return true;
25384          }
25385        });
25386        var alignStates = function (name) {
25387          return function () {
25388            var nodes = editor.selection.isCollapsed() ? [editor.dom.getParent(editor.selection.getNode(), editor.dom.isBlock)] : editor.selection.getSelectedBlocks();
25389            var matches = map$3(nodes, function (node) {
25390              return !!editor.formatter.matchNode(node, name);
25391            });
25392            return inArray$2(matches, true) !== -1;
25393          };
25394        };
25395        self.addCommands({
25396          'JustifyLeft': alignStates('alignleft'),
25397          'JustifyCenter': alignStates('aligncenter'),
25398          'JustifyRight': alignStates('alignright'),
25399          'JustifyFull': alignStates('alignjustify'),
25400          'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': function (command) {
25401            return self.isFormatMatch(command);
25402          },
25403          'mceBlockQuote': function () {
25404            return self.isFormatMatch('blockquote');
25405          },
25406          'Outdent': function () {
25407            return canOutdent(editor);
25408          },
25409          'InsertUnorderedList,InsertOrderedList': function (command) {
25410            var list = editor.dom.getParent(editor.selection.getNode(), 'ul,ol');
25411            return list && (command === 'insertunorderedlist' && list.tagName === 'UL' || command === 'insertorderedlist' && list.tagName === 'OL');
25412          }
25413        }, 'state');
25414        self.addCommands({
25415          Undo: function () {
25416            editor.undoManager.undo();
25417          },
25418          Redo: function () {
25419            editor.undoManager.redo();
25420          }
25421        });
25422        self.addQueryValueHandler('FontName', function () {
25423          return fontNameQuery(editor);
25424        }, this);
25425        self.addQueryValueHandler('FontSize', function () {
25426          return fontSizeQuery(editor);
25427        }, this);
25428      };
25429      return EditorCommands;
25430    }();
25431
25432    var nativeEvents = Tools.makeMap('focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange ' + 'mouseout mouseenter mouseleave wheel 
25432keydown keypress keyup input contextmenu dragstart dragend dragover ' + 'draggesture dragdrop drop drag submit ' + 'compositionstart compositionend compositionupdate touchstart touchmove touchend', ' ');
25433    var returnFalse$1 = function () {
25434      return false;
25435    };
25436    var returnTrue$1 = function () {
25437      return true;
25438    };
25439    var EventDispatcher = function () {
25440      function EventDispatcher(settings) {
25441        this.bindings = {};
25442        this.settings = settings || {};
25443        this.scope = this.settings.scope || this;
25444        this.toggleEvent = this.settings.toggleEvent || returnFalse$1;
25445      }
25446      EventDispatcher.isNative = function (name) {
25447        return !!nativeEvents[name.toLowerCase()];
25448      };
25449      EventDispatcher.prototype.fire = function (name, args) {
25450        var handlers, i, l, callback;
25451        name = name.toLowerCase();
25452        args = args || {};
25453        args.type = name;
25454        if (!args.target) {
25455          args.target = this.scope;
25456        }
25457        if (!args.preventDefault) {
25458          args.preventDefault = function () {
25459            args.isDefaultPrevented = returnTrue$1;
25460          };
25461          args.stopPropagation = function () {
25462            args.isPropagationStopped = returnTrue$1;
25463          };
25464          args.stopImmediatePropagation = function () {
25465            args.isImmediatePropagationStopped = returnTrue$1;
25466          };
25467          args.isDefaultPrevented = returnFalse$1;
25468          args.isPropagationStopped = returnFalse$1;
25469          args.isImmediatePropagationStopped = returnFalse$1;
25470        }
25471        if (this.settings.beforeFire) {
25472          this.settings.beforeFire(args);
25473        }
25474        handlers = this.bindings[name];
25475        if (handlers) {
25476          for (i = 0, l = handlers.length; i < l; i++) {
25477            callback = handlers[i];
25478            if (callback.once) {
25479              this.off(name, callback.func);
25480            }
25481            if (args.isImmediatePropagationStopped()) {
25482              args.stopPropagation();
25483              return args;
25484            }
25485            if (callback.func.call(this.scope, args) === false) {
25486              args.preventDefault();
25487              return args;
25488            }
25489          }
25490        }
25491        return args;
25492      };
25493      EventDispatcher.prototype.on = function (name, callback, prepend, extra) {
25494        var handlers, names, i;
25495        if (callback === false) {
25496          callback = returnFalse$1;
25497        }
25498        if (callback) {
25499          var wrappedCallback = { func: callback };
25500          if (extra) {
25501            Tools.extend(wrappedCallback, extra);
25502          }
25503          names = name.toLowerCase().split(' ');
25504          i = names.length;
25505          while (i--) {
25506            name = names[i];
25507            handlers = this.bindings[name];
25508            if (!handlers) {
25509              handlers = this.bindings[name] = [];
25510              this.toggleEvent(name, true);
25511            }
25512            if (prepend) {
25513              handlers.unshift(wrappedCallback);
25514            } else {
25515              handlers.push(wrappedCallback);
25516            }
25517          }
25518        }
25519        return this;
25520      };
25521      EventDispatcher.prototype.off = function (name, callback) {
25522        var i, handlers, bindingName, names, hi;
25523        if (name) {
25524          names = name.toLowerCase().split(' ');
25525          i = names.length;
25526          while (i--) {
25527            name = names[i];
25528            handlers = this.bindings[name];
25529            if (!name) {
25530              for (bindingName in this.bindings) {
25531                this.toggleEvent(bindingName, false);
25532                delete this.bindings[bindingName];
25533              }
25534              return this;
25535            }
25536            if (handlers) {
25537              if (!callback) {
25538                handlers.length = 0;
25539              } else {
25540                hi = handlers.length;
25541                while (hi--) {
25542                  if (handlers[hi].func === callback) {
25543                    handlers = handlers.slice(0, hi).concat(handlers.slice(hi + 1));
25544                    this.bindings[name] = handlers;
25545                  }
25546                }
25547              }
25548              if (!handlers.length) {
25549                this.toggleEvent(name, false);
25550                delete this.bindings[name];
25551              }
25552            }
25553          }
25554        } else {
25555          for (name in this.bindings) {
25556            this.toggleEvent(name, false);
25557          }
25558          this.bindings = {};
25559        }
25560        return this;
25561      };
25562      EventDispatcher.prototype.once = function (name, callback, prepend) {
25563        return this.on(name, callback, prepend, { once: true });
25564      };
25565      EventDispatcher.prototype.has = function (name) {
25566        name = name.toLowerCase();
25567        return !(!this.bindings[name] || this.bindings[name].length === 0);
25568      };
25569      return EventDispatcher;
25570    }();
25571
25572    var getEventDispatcher = function (obj) {
25573      if (!obj._eventDispatcher) {
25574        obj._eventDispatcher = new EventDispatcher({
25575          scope: obj,
25576          toggleEvent: function (name, state) {
25577            if (EventDispatcher.isNative(name) && obj.toggleNativeEvent) {
25578              obj.toggleNativeEvent(name, state);
25579            }
25580          }
25581        });
25582      }
25583      return obj._eventDispatcher;
25584    };
25585    var Observable = {
25586      fire: function (name, args, bubble) {
25587        var self = this;
25588        if (self.removed && name !== 'remove' && name !== 'detach') {
25589          return args;
25590        }
25591        var dispatcherArgs = getEventDispatcher(self).fire(name, args);
25592        if (bubble !== false && self.parent) {
25593          var parent = self.parent();
25594          while (parent && !dispatcherArgs.isPropagationStopped()) {
25595            parent.fire(name, dispatcherArgs, false);
25596            parent = parent.parent();
25597          }
25598        }
25599        return dispatcherArgs;
25600      },
25601      on: function (name, callback, prepend) {
25602        return getEventDispatcher(this).on(name, callback, prepend);
25603      },
25604      off: function (name, callback) {
25605        return getEventDispatcher(this).off(name, callback);
25606      },
25607      once: function (name, callback) {
25608        return getEventDispatcher(this).once(name, callback);
25609      },
25610      hasEventListeners: function (name) {
25611        return getEventDispatcher(this).has(name);
25612      }
25613    };
25614
25615    var DOM$6 = DOMUtils$1.DOM;
25616    var customEventRootDelegates;
25617    var getEventTarget = function (editor, eventName) {
25618      if (eventName === 'selectionchange') {
25619        return editor.getDoc();
25620      }
25621      if (!editor.inline && /^mouse|touch|click|contextmenu|drop|dragover|dragend/.test(eventName)) {
25622        return editor.getDoc().documentElement;
25623      }
25624      if (editor.settings.event_root) {
25625        if (!editor.eventRoot) {
25626          editor.eventRoot = DOM$6.select(editor.settings.event_root)[0];
25627        }
25628        return editor.eventRoot;
25629      }
25630      return editor.getBody();
25631    };
25632    var isListening = function (editor) {
25633      return !editor.hidden && !editor.readonly;
25634    };
25635    var fireEvent = function (editor, eventName, e) {
25636      if (isListening(editor)) {
25637        editor.fire(eventName, e);
25638      } else if (editor.readonly) {
25639        e.preventDefault();
25640      }
25641    };
25642    var bindEventDelegate = function (editor, eventName) {
25643      var eventRootElm, delegate;
25644      if (!editor.delegates) {
25645        editor.delegates = {};
25646      }
25647      if (editor.delegates[eventName] || editor.removed) {
25648        return;
25649      }
25650      eventRootElm = getEventTarget(editor, eventName);
25651      if (editor.settings.event_root) {
25652        if (!customEventRootDelegates) {
25653          customEventRootDelegates = {};
25654          editor.editorManager.on('removeEditor', function () {
25655            var name;
25656            if (!editor.editorManager.activeEditor) {
25657              if (customEventRootDelegates) {
25658                for (name in customEventRootDelegates) {
25659                  editor.dom.unbind(getEventTarget(editor, name));
25660                }
25661                customEventRootDelegates = null;
25662              }
25663            }
25664          });
25665        }
25666        if (customEventRootDelegates[eventName]) {
25667          return;
25668        }
25669        delegate = function (e) {
25670          var target = e.target;
25671          var editors = editor.editorManager.get();
25672          var i = editors.length;
25673          while (i--) {
25674            var body = editors[i].getBody();
25675            if (body === target || DOM$6.isChildOf(target, body)) {
25676              fireEvent(editors[i], eventName, e);
25677            }
25678          }
25679        };
25680        customEventRootDelegates[eventName] = delegate;
25681        DOM$6.bind(eventRootElm, eventName, delegate);
25682      } else {
25683        delegate = function (e) {
25684          fireEvent(editor, eventName, e);
25685        };
25686        DOM$6.bind(eventRootElm, eventName, delegate);
25687        editor.delegates[eventName] = delegate;
25688      }
25689    };
25690    var EditorObservable = __assign({}, Observable, {
25691      bindPendingEventDelegates: function () {
25692        var self = this;
25693        Tools.each(self._pendingNativeEvents, function (name) {
25694          bindEventDelegate(self, name);
25695        });
25696      },
25697      toggleNativeEvent: function (name, state) {
25698        var self = this;
25699        if (name === 'focus' || name === 'blur') {
25700          return;
25701        }
25702        if (state) {
25703          if (self.initialized) {
25704            bindEventDelegate(self, name);
25705          } else {
25706            if (!self._pendingNativeEvents) {
25707              self._pendingNativeEvents = [name];
25708            } else {
25709              self._pendingNativeEvents.push(name);
25710            }
25711          }
25712        } else if (self.initialized) {
25713          self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
25714          delete self.delegates[name];
25715        }
25716      },
25717      unbindAllNativeEvents: function () {
25718        var self = this;
25719        var body = self.getBody();
25720        var dom = self.dom;
25721        var name;
25722        if (self.delegates) {
25723          for (name in self.delegates) {
25724            self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
25725          }
25726          delete self.delegates;
25727        }
25728        if (!self.inline && body && dom) {
25729          body.onload = null;
25730          dom.unbind(self.getWin());
25731          dom.unbind(self.getDoc());
25732        }
25733        if (dom) {
25734          dom.unbind(body);
25735          dom.unbind(self.getContainer());
25736        }
25737      }
25738    });
25739
25740    var each$h = Tools.each, explode$3 = Tools.explode;
25741    var keyCodeLookup = {
25742      f1: 112,
25743      f2: 113,
25744      f3: 114,
25745      f4: 115,
25746      f5: 116,
25747      f6: 117,
25748      f7: 118,
25749      f8: 119,
25750      f9: 120,
25751      f10: 121,
25752      f11: 122,
25753      f12: 123
25754    };
25755    var modifierNames = Tools.makeMap('alt,ctrl,shift,meta,access');
25756    var Shortcuts = function () {
25757      function Shortcuts(editor) {
25758        this.shortcuts = {};
25759        this.pendingPatterns = [];
25760        this.editor = editor;
25761        var self = this;
25762        editor.on('keyup keypress keydown', function (e) {
25763          if ((self.hasModifier(e) || self.isFunctionKey(e)) && !e.isDefaultPrevented()) {
25764            each$h(self.shortcuts, function (shortcut) {
25765              if (self.matchShortcut(e, shortcut)) {
25766                self.pendingPatterns = shortcut.subpatterns.slice(0);
25767                if (e.type === 'keydown') {
25768                  self.executeShortcutAction(shortcut);
25769                }
25770                return true;
25771              }
25772            });
25773            if (self.matchShortcut(e, self.pendingPatterns[0])) {
25774              if (self.pendingPatterns.length === 1) {
25775                if (e.type === 'keydown') {
25776                  self.executeShortcutAction(self.pendingPatterns[0]);
25777                }
25778              }
25779              self.pendingPatterns.shift();
25780            }
25781          }
25782        });
25783      }
25784      Shortcuts.prototype.add = function (pattern, desc, cmdFunc, scope) {
25785        var self = this;
25786        var cmd;
25787        cmd = cmdFunc;
25788        if (typeof cmdFunc === 'string') {
25789          cmdFunc = function () {
25790            self.editor.execCommand(cmd, false, null);
25791          };
25792        } else if (Tools.isArray(cmd)) {
25793          cmdFunc = function () {
25794            self.editor.execCommand(cmd[0], cmd[1], cmd[2]);
25795          };
25796        }
25797        each$h(explode$3(Tools.trim(pattern.toLowerCase())), function (pattern) {
25798          var shortcut = self.createShortcut(pattern, desc, cmdFunc, scope);
25799          self.shortcuts[shortcut.id] = shortcut;
25800        });
25801        return true;
25802      };
25803      Shortcuts.prototype.remove = function (pattern) {
25804        var shortcut = this.createShortcut(pattern);
25805        if (this.shortcuts[shortcut.id]) {
25806          delete this.shortcuts[shortcut.id];
25807          return true;
25808        }
25809        return false;
25810      };
25811      Shortcuts.prototype.parseShortcut = function (pattern) {
25812        var id, key;
25813        var shortcut = {};
25814        each$h(explode$3(pattern, '+'), function (value) {
25815          if (value in modifierNames) {
25816            shortcut[value] = true;
25817          } else {
25818            if (/^[0-9]{2,}$/.test(value)) {
25819              shortcut.keyCode = parseInt(value, 10);
25820            } else {
25821              shortcut.charCode = value.charCodeAt(0);
25822              shortcut.keyCode = keyCodeLookup[value] || value.toUpperCase().charCodeAt(0);
25823            }
25824          }
25825        });
25826        id = [shortcut.keyCode];
25827        for (key in modifierNames) {
25828          if (shortcut[key]) {
25829            id.push(key);
25830          } else {
25831            shortcut[key] = false;
25832          }
25833        }
25834        shortcut.id = id.join(',');
25835        if (shortcut.access) {
25836          shortcut.alt = true;
25837          if (Env.mac) {
25838            shortcut.ctrl = true;
25839          } else {
25840            shortcut.shift = true;
25841          }
25842        }
25843        if (shortcut.meta) {
25844          if (Env.mac) {
25845            shortcut.meta = true;
25846          } else {
25847            shortcut.ctrl = true;
25848            shortcut.meta = false;
25849          }
25850        }
25851        return shortcut;
25852      };
25853      Shortcuts.prototype.createShortcut = function (pattern, desc, cmdFunc, scope) {
25854        var shortcuts;
25855        shortcuts = Tools.map(explode$3(pattern, '>'), this.parseShortcut);
25856        shortcuts[shortcuts.length - 1] = Tools.extend(shortcuts[shortcuts.length - 1], {
25857          func: cmdFunc,
25858          scope: scope || this.editor
25859        });
25860        return Tools.extend(shortcuts[0], {
25861          desc: this.editor.translate(desc),
25862          subpatterns: shortcuts.slice(1)
25863        });
25864      };
25865      Shortcuts.prototype.hasModifier = function (e) {
25866        return e.altKey || e.ctrlKey || e.metaKey;
25867      };
25868      Shortcuts.prototype.isFunctionKey = function (e) {
25869        return e.type === 'keydown' && e.keyCode >= 112 && e.keyCode <= 123;
25870      };
25871      Shortcuts.prototype.matchShortcut = function (e, shortcut) {
25872        if (!shortcut) {
25873          return false;
25874        }
25875        if (shortcut.ctrl !== e.ctrlKey || shortcut.meta !== e.metaKey) {
25876          return false;
25877        }
25878        if (shortcut.alt !== e.altKey || shortcut.shift !== e.shiftKey) {
25879          return false;
25880        }
25881        if (e.keyCode === shortcut.keyCode || e.charCode && e.charCode === shortcut.charCode) {
25882          e.preventDefault();
25883          return true;
25884        }
25885        return false;
25886      };
25887      Shortcuts.prototype.executeShortcutAction = function (shortcut) {
25888        return shortcut.func ? shortcut.func.call(shortcut.scope) : null;
25889      };
25890      return Shortcuts;
25891    }();
25892
25893    var each$i = Tools.each, trim$4 = Tools.trim;
25894    var queryParts = 'source protocol authority userInfo user password host port relative path directory file query anchor'.split(' ');
25895    var DEFAULT_PORTS = {
25896      ftp: 21,
25897      http: 80,
25898      https: 443,
25899      mailto: 25
25900    };
25901    var URI = function () {
25902      function URI(url, settings) {
25903        url = trim$4(url);
25904        this.settings = settings || {};
25905        var baseUri = this.settings.base_uri;
25906        var self = this;
25907        if (/^([\w\-]+):([^\/]{2})/i.test(url) || /^\s*#/.test(url)) {
25908          self.source = url;
25909          return;
25910        }
25911        var isProtocolRelative = url.indexOf('//') === 0;
25912        if (url.indexOf('/') === 0 && !isProtocolRelative) {
25913          url = (baseUri ? baseUri.protocol || 'http' : 'http') + '://mce_host' + url;
25914        }
25915        if (!/^[\w\-]*:?\/\//.test(url)) {
25916          var baseUrl = this.settings.base_uri ? this.settings.base_uri.path : new URI(domGlobals.document.location.href).directory;
25917          if (this.settings.base_uri.protocol == '') {
25918            url = '//mce_host' + self.toAbsPath(baseUrl, url);
25919          } else {
25920            var match = /([^#?]*)([#?]?.*)/.exec(url);
25921            url = (baseUri && baseUri.protocol || 'http') + '://mce_host' + self.toAbsPath(baseUrl, match[1]) + match[2];
25922          }
25923        }
25924        url = url.replace(/@@/g, '(mce_at)');
25925        var urlMatch = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url);
25926        each$i(queryParts, function (v, i) {
25927          var part = urlMatch[i];
25928          if (part) {
25929            part = part.replace(/\(mce_at\)/g, '@@');
25930          }
25931          self[v] = part;
25932        });
25933        if (baseUri) {
25934          if (!self.protocol) {
25935            self.protocol = baseUri.protocol;
25936          }
25937          if (!self.userInfo) {
25938            self.userInfo = baseUri.userInfo;
25939          }
25940          if (!self.port && self.host === 'mce_host') {
25941            self.port = baseUri.port;
25942          }
25943          if (!self.host || self.host === 'mce_host') {
25944            self.host = baseUri.host;
25945          }
25946          self.source = '';
25947        }
25948        if (isProtocolRelative) {
25949          self.protocol = '';
25950        }
25951      }
25952      URI.parseDataUri = function (uri) {
25953        var type;
25954        var uriComponents = decodeURIComponent(uri).split(',');
25955        var matches = /data:([^;]+)/.exec(uriComponents[0]);
25956        if (matches) {
25957          type = matches[1];
25958        }
25959        return {
25960          type: type,
25961          data: uriComponents[1]
25962        };
25963      };
25964      URI.getDocumentBaseUrl = function (loc) {
25965        var baseUrl;
25966        if (loc.protocol.indexOf('http') !== 0 && loc.protocol !== 'file:') {
25967          baseUrl = loc.href;
25968        } else {
25969          baseUrl = loc.protocol + '//' + loc.host + loc.pathname;
25970        }
25971        if (/^[^:]+:\/\/\/?[^\/]+\//.test(baseUrl)) {
25972          baseUrl = baseUrl.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
25973          if (!/[\/\\]$/.test(baseUrl)) {
25974            baseUrl += '/';
25975          }
25976        }
25977        return baseUrl;
25978      };
25979      URI.prototype.setPath = function (path) {
25980        var pathMatch = /^(.*?)\/?(\w+)?$/.exec(path);
25981        this.path = pathMatch[0];
25982        this.directory = pathMatch[1];
25983        this.file = pathMatch[2];
25984        this.source = '';
25985        this.getURI();
25986      };
25987      URI.prototype.toRelative = function (uri) {
25988        var output;
25989        if (uri === './') {
25990          return uri;
25991        }
25992        var relativeUri = new URI(uri, { base_uri: this });
25993        if (relativeUri.host !== 'mce_host' && this.host !== relativeUri.host && relativeUri.host || this.port !== relativeUri.port || this.protocol !== relativeUri.protocol && relativeUri.protocol !== '') {
25994          return relativeUri.getURI();
25995        }
25996        var tu = this.getURI(), uu = relativeUri.getURI();
25997        if (tu === uu || tu.charAt(tu.length - 1) === '/' && tu.substr(0, tu.length - 1) === uu) {
25998          return tu;
25999        }
26000        output = this.toRelPath(this.path, relativeUri.path);
26001        if (relativeUri.query) {
26002          output += '?' + relativeUri.query;
26003        }
26004        if (relativeUri.anchor) {
26005          output += '#' + relativeUri.anchor;
26006        }
26007        return output;
26008      };
26009      URI.prototype.toAbsolute = function (uri, noHost) {
26010        var absoluteUri = new URI(uri, { base_uri: this });
26011        return absoluteUri.getURI(noHost && this.isSameOrigin(absoluteUri));
26012      };
26013      URI.prototype.isSameOrigin = function (uri) {
26014        if (this.host == uri.host && this.protocol == uri.protocol) {
26015          if (this.port == uri.port) {
26016            return true;
26017          }
26018          var defaultPort = DEFAULT_PORTS[this.protocol];
26019          if (defaultPort && (this.port || defaultPort) == (uri.port || defaultPort)) {
26020            return true;
26021          }
26022        }
26023        return false;
26024      };
26025      URI.prototype.toRelPath = function (base, path) {
26026        var items, breakPoint = 0, out = '', i, l;
26027        var normalizedBase = base.substring(0, base.lastIndexOf('/')).split('/');
26028        items = path.split('/');
26029        if (normalizedBase.length >= items.length) {
26030          for (i = 0, l = normalizedBase.length; i < l; i++) {
26031            if (i >= items.length || normalizedBase[i] !== items[i]) {
26032              breakPoint = i + 1;
26033              break;
26034            }
26035          }
26036        }
26037        if (normalizedBase.length < items.length) {
26038          for (i = 0, l = items.length; i < l; i++) {
26039            if (i >= normalizedBase.length || normalizedBase[i] !== items[i]) {
26040              breakPoint = i + 1;
26041              break;
26042            }
26043          }
26044        }
26045        if (breakPoint === 1) {
26046          return path;
26047        }
26048        for (i = 0, l = normalizedBase.length - (breakPoint - 1); i < l; i++) {
26049          out += '../';
26050        }
26051        for (i = breakPoint - 1, l = items.length; i < l; i++) {
26052          if (i !== breakPoint - 1) {
26053            out += '/' + items[i];
26054          } else {
26055            out += items[i];
26056          }
26057        }
26058        return out;
26059      };
26060      URI.prototype.toAbsPath = function (base, path) {
26061        var i, nb = 0, o = [], tr, outPath;
26062        tr = /\/$/.test(path) ? '/' : '';
26063        var normalizedBase = base.split('/');
26064        var normalizedPath = path.split('/');
26065        each$i(normalizedBase, function (k) {
26066          if (k) {
26067            o.push(k);
26068          }
26069        });
26070        normalizedBase = o;
26071        for (i = normalizedPath.length - 1, o = []; i >= 0; i--) {
26072          if (normalizedPath[i].length === 0 || normalizedPath[i] === '.') {
26073            continue;
26074          }
26075          if (normalizedPath[i] === '..') {
26076            nb++;
26077            continue;
26078          }
26079          if (nb > 0) {
26080            nb--;
26081            continue;
26082          }
26083          o.push(normalizedPath[i]);
26084        }
26085        i = normalizedBase.length - nb;
26086        if (i <= 0) {
26087          outPath = o.reverse().join('/');
26088        } else {
26089          outPath = normalizedBase.slice(0, i).join('/') + '/' + o.reverse().join('/');
26090        }
26091        if (outPath.indexOf('/') !== 0) {
26092          outPath = '/' + outPath;
26093        }
26094        if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) {
26095          outPath += tr;
26096        }
26097        return outPath;
26098      };
26099      URI.prototype.getURI = function (noProtoHost) {
26100        if (noProtoHost === void 0) {
26101          noProtoHost = false;
26102        }
26103        var s;
26104        if (!this.source || noProtoHost) {
26105          s = '';
26106          if (!noProtoHost) {
26107            if (this.protocol) {
26108              s += this.protocol + '://';
26109            } else {
26110              s += '//';
26111            }
26112            if (this.userInfo) {
26113              s += this.userInfo + '@';
26114            }
26115            if (this.host) {
26116              s += this.host;
26117            }
26118            if (this.port) {
26119              s += ':' + this.port;
26120            }
26121          }
26122          if (this.path) {
26123            s += this.path;
26124          }
26125          if (this.query) {
26126            s += '?' + this.query;
26127          }
26128          if (this.anchor) {
26129            s += '#' + this.anchor;
26130          }
26131          this.source = s;
26132        }
26133        return this.source;
26134      };
26135      return URI;
26136    }();
26137
26138    var create$4 = function () {
26139      var buttons = {};
26140      var menuItems = {};
26141      var popups = {};
26142      var icons = {};
26143      var contextMenus = {};
26144      var contextToolbars = {};
26145      var sidebars = {};
26146      var add = function (collection, type) {
26147        return function (name, spec) {
26148          return collection[name.toLowerCase()] = merge({ type: type }, spec);
26149        };
26150      };
26151      var addIcon = function (name, svgData) {
26152        return icons[name.toLowerCase()] = svgData;
26153      };
26154      return {
26155        addButton: add(buttons, 'button'),
26156        addToggleButton: add(buttons, 'togglebutton'),
26157        addMenuButton: add(buttons, 'menubutton'),
26158        addSplitButton: add(buttons, 'splitbutton'),
26159        addMenuItem: add(menuItems, 'menuitem'),
26160        addNestedMenuItem: add(menuItems, 'nestedmenuitem'),
26161        addToggleMenuItem: add(menuItems, 'togglemenuitem'),
26162        addAutocompleter: add(popups, 'autocompleter'),
26163        addContextMenu: add(contextMenus, 'contextmenu'),
26164        addContextToolbar: add(contextToolbars, 'contexttoolbar'),
26165        addContextForm: add(contextToolbars, 'contextform'),
26166        addSidebar: add(sidebars, 'sidebar'),
26167        addIcon: addIcon,
26168        getAll: function () {
26169          return {
26170            buttons: buttons,
26171            menuItems: menuItems,
26172            icons: icons,
26173            popups: popups,
26174            contextMenus: contextMenus,
26175            contextToolbars: contextToolbars,
26176            sidebars: sidebars
26177          };
26178        }
26179      };
26180    };
26181
26182    var registry = function () {
26183      var bridge = create$4();
26184      return {
26185        addAutocompleter: bridge.addAutocompleter,
26186        addButton: bridge.addButton,
26187        addContextForm: bridge.addContextForm,
26188        addContextMenu: bridge.addContextMenu,
26189        addContextToolbar: bridge.addContextToolbar,
26190        addIcon: bridge.addIcon,
26191        addMenuButton: bridge.addMenuButton,
26192        addMenuItem: bridge.addMenuItem,
26193        addNestedMenuItem: bridge.addNestedMenuItem,
26194        addSidebar: bridge.addSidebar,
26195        addSplitButton: bridge.addSplitButton,
26196        addToggleButton: bridge.addToggleButton,
26197        addToggleMenuItem: bridge.addToggleMenuItem,
26198        getAll: bridge.getAll
26199      };
26200    };
26201
26202    var DOM$7 = DOMUtils$1.DOM;
26203    var extend$3 = Tools.extend, each$j = Tools.each;
26204    var resolve$4 = Tools.resolve;
26205    var ie$2 = Env.ie;
26206    var Editor = function () {
26207      function Editor(id, settings, editorManager) {
26208        var _this = this;
26209        this.plugins = {};
26210        this.contentCSS = [];
26211        this.contentStyles = [];
26212        this.loadedCSS = {};
26213        this.isNotDirty = false;
26214        this.editorManager = editorManager;
26215        this.documentBaseUrl = editorManager.documentBaseURL;
26216        this.baseUri = editorManager.baseURI;
26217        extend$3(this, EditorObservable);
26218        this.settings = getEditorSettings(this, id, this.documentBaseUrl, editorManager.defaultSettings, settings);
26219        AddOnManager$1.languageLoad = this.settings.language_load;
26220        AddOnManager$1.baseURL = editorManager.baseURL;
26221        this.id = id;
26222        this.setDirty(false);
26223        this.documentBaseURI = new URI(this.settings.document_base_url, { base_uri: this.baseUri });
26224        this.baseURI = this.baseUri;
26225        this.inline = this.settings.inline;
26226        this.suffix = editorManager.suffix;
26227        this.shortcuts = new Shortcuts(this);
26228        this.editorCommands = new EditorCommands(this);
26229        if (this.settings.cache_suffix) {
26230          Env.cacheSuffix = this.settings.cache_suffix.replace(/^[\?\&]+/, '');
26231        }
26232        if (this.settings.override_viewport === false) {
26233          Env.overrideViewPort = false;
26234        }
26235        this.ui = { registry: registry() };
26236        var self = this;
26237        var modeInstance = create$3(self);
26238        this.mode = modeInstance;
26239        this.setMode = modeInstance.set;
26240        editorManager.fire('SetupEditor', { editor: this });
26241        this.execCallback('setup', this);
26242        this.$ = DomQuery.overrideDefaults(function () {
26243          return {
26244            context: _this.inline ? _this.getBody() : _this.getDoc(),
26245            element: _this.getBody()
26246          };
26247        });
26248      }
26249      Editor.prototype.render = function () {
26250        Render.render(this);
26251      };
26252      Editor.prototype.focus = function (skipFocus) {
26253        EditorFocus.focus(this, skipFocus);
26254      };
26255      Editor.prototype.hasFocus = function () {
26256        return EditorFocus.hasFocus(this);
26257      };
26258      Editor.prototype.execCallback = function (name) {
26259        var x = [];
26260        for (var _i = 1; _i < arguments.length; _i++) {
26261          x[_i - 1] = arguments[_i];
26262        }
26263        var self = this;
26264        var callback = self.settings[name], scope;
26265        if (!callback) {
26266          return;
26267        }
26268        if (self.callbackLookup && (scope = self.callbackLookup[name])) {
26269          callback = scope.func;
26270          scope = scope.scope;
26271        }
26272        if (typeof callback === 'string') {
26273          scope = callback.replace(/\.\w+$/, '');
26274          scope = scope ? resolve$4(scope) : 0;
26275          callback = resolve$4(callback);
26276          self.callbackLookup = self.callbackLookup || {};
26277          self.callbackLookup[name] = {
26278            func: callback,
26279            scope: scope
26280          };
26281        }
26282        return callback.apply(scope || self, Array.prototype.slice.call(arguments, 1));
26283      };
26284      Editor.prototype.translate = function (text) {
26285        return I18n.translate(text);
26286      };
26287      Editor.prototype.getParam = function (name, defaultVal, type) {
26288        return getParam(this, name, defaultVal, type);
26289      };
26290      Editor.prototype.nodeChanged = function (args) {
26291        this._nodeChangeDispatcher.nodeChanged(args);
26292      };
26293      Editor.prototype.addCommand = function (name, callback, scope) {
26294        this.editorCommands.addCommand(name, callback, scope);
26295      };
26296      Editor.prototype.addQueryStateHandler = function (name, callback, scope) {
26297        this.editorCommands.addQueryStateHandler(name, callback, scope);
26298      };
26299      Editor.prototype.addQueryValueHandler = function (name, callback, scope) {
26300        this.editorCommands.addQueryValueHandler(name, callback, scope);
26301      };
26302      Editor.prototype.addShortcut = function (pattern, desc, cmdFunc, scope) {
26303        this.shortcuts.add(pattern, desc, cmdFunc, scope);
26304      };
26305      Editor.prototype.execCommand = function (cmd, ui, value, args) {
26306        return this.editorCommands.execCommand(cmd, ui, value, args);
26307      };
26308      Editor.prototype.queryCommandState = function (cmd) {
26309        return this.editorCommands.queryCommandState(cmd);
26310      };
26311      Editor.prototype.queryCommandValue = function (cmd) {
26312        return this.editorCommands.queryCommandValue(cmd);
26313      };
26314      Editor.prototype.queryCommandSupported = function (cmd) {
26315        return this.editorCommands.queryCommandSupported(cmd);
26316      };
26317      Editor.prototype.show = function () {
26318        var self = this;
26319        if (self.hidden) {
26320          self.hidden = false;
26321          if (self.inline) {
26322            self.getBody().contentEditable = 'true';
26323          } else {
26324            DOM$7.show(self.getContainer());
26325            DOM$7.hide(self.id);
26326          }
26327          self.load();
26328          self.fire('show');
26329        }
26330      };
26331      Editor.prototype.hide = function () {
26332        var self = this, doc = self.getDoc();
26333        if (!self.hidden) {
26334          if (ie$2 && doc && !self.inline) {
26335            doc.execCommand('SelectAll');
26336          }
26337          self.save();
26338          if (self.inline) {
26339            self.getBody().contentEditable = 'false';
26340            if (self === self.editorManager.focusedEditor) {
26341              self.editorManager.focusedEditor = null;
26342            }
26343          } else {
26344            DOM$7.hide(self.getContainer());
26345            DOM$7.setStyle(self.id, 'display', self.orgDisplay);
26346          }
26347          self.hidden = true;
26348          self.fire('hide');
26349        }
26350      };
26351      Editor.prototype.isHidden = function () {
26352        return !!this.hidden;
26353      };
26354      Editor.prototype.setProgressState = function (state, time) {
26355        this.fire('ProgressState', {
26356          state: state,
26357          time: time
26358        });
26359      };
26360      Editor.prototype.load = function (args) {
26361        var self = this;
26362        var elm = self.getElement(), html;
26363        if (self.removed) {
26364          return '';
26365        }
26366        if (elm) {
26367          args = args || {};
26368          args.load = true;
26369          var value = elm.value;
26370          html = self.setContent(value !== undefined ? value : elm.innerHTML, args);
26371          args.element = elm;
26372          if (!args.no_events) {
26373            self.fire('LoadContent', args);
26374          }
26375          args.element = elm = null;
26376          return html;
26377        }
26378      };
26379      Editor.prototype.save = function (args) {
26380        var self = this;
26381        var elm = self.getElement(), html, form;
26382        if (!elm || !self.initialized || self.removed) {
26383          return;
26384        }
26385        args = args || {};
26386        args.save = true;
26387        args.element = elm;
26388        html = args.content = self.getContent(args);
26389        if (!args.no_events) {
26390          self.fire('SaveContent', args);
26391        }
26392        if (args.format === 'raw') {
26393          self.fire('RawSaveContent', args);
26394        }
26395        html = args.content;
26396        if (!/TEXTAREA|INPUT/i.test(elm.nodeName)) {
26397          if (args.is_removing || !self.inline) {
26398            elm.innerHTML = html;
26399          }
26400          if (form = DOM$7.getParent(self.id, 'form')) {
26401            each$j(form.elements, function (elm) {
26402              if (elm.name === self.id) {
26403                elm.value = html;
26404                return false;
26405              }
26406            });
26407          }
26408        } else {
26409          elm.value = html;
26410        }
26411        args.element = elm = null;
26412        if (args.set_dirty !== false) {
26413          self.setDirty(false);
26414        }
26415        return html;
26416      };
26417      Editor.prototype.setContent = function (content, args) {
26418        return setContent(this, content, args);
26419      };
26420      Editor.prototype.getContent = function (args) {
26421        return getContent(this, args);
26422      };
26423      Editor.prototype.insertContent = function (content, args) {
26424        if (args) {
26425          content = extend$3({ content: content }, args);
26426        }
26427        this.execCommand('mceInsertContent', false, content);
26428      };
26429      Editor.prototype.resetContent = function (initialContent) {
26430        if (initialContent === undefined) {
26431          setContent(this, this.startContent, { format: 'raw' });
26432        } else {
26433          setContent(this, initialContent);
26434        }
26435        this.undoManager.reset();
26436        this.setDirty(false);
26437        this.nodeChanged();
26438      };
26439      Editor.prototype.isDirty = function () {
26440        return !this.isNotDirty;
26441      };
26442      Editor.prototype.setDirty = function (state) {
26443        var oldState = !this.isNotDirty;
26444        this.isNotDirty = !state;
26445        if (state && state !== oldState) {
26446          this.fire('dirty');
26447        }
26448      };
26449      Editor.prototype.getContainer = function () {
26450        var self = this;
26451        if (!self.container) {
26452          self.container = DOM$7.get(self.editorContainer || self.id + '_parent');
26453        }
26454        return self.container;
26455      };
26456      Editor.prototype.getContentAreaContainer = function () {
26457        return this.contentAreaContainer;
26458      };
26459      Editor.prototype.getElement = function () {
26460        if (!this.targetElm) {
26461          this.targetElm = DOM$7.get(this.id);
26462        }
26463        return this.targetElm;
26464      };
26465      Editor.prototype.getWin = function () {
26466        var self = this;
26467        var elm;
26468        if (!self.contentWindow) {
26469          elm = self.iframeElement;
26470          if (elm) {
26471            self.contentWindow = elm.contentWindow;
26472          }
26473        }
26474        return self.contentWindow;
26475      };
26476      Editor.prototype.getDoc = function () {
26477        var self = this;
26478        var win;
26479        if (!self.contentDocument) {
26480          win = self.getWin();
26481          if (win) {
26482            self.contentDocument = win.document;
26483          }
26484        }
26485        return self.contentDocument;
26486      };
26487      Editor.prototype.getBody = function () {
26488        var doc = this.getDoc();
26489        return this.bodyElement || (doc ? doc.body : null);
26490      };
26491      Editor.prototype.convertURL = function (url, name, elm) {
26492        var self = this, settings = self.settings;
26493        if (settings.urlconverter_callback) {
26494          return self.execCallback('urlconverter_callback', url, elm, true, name);
26495        }
26496        if (!settings.convert_urls || elm && elm.nodeName === 'LINK' || url.indexOf('file:') === 0 || url.length === 0) {
26497          return url;
26498        }
26499        if (settings.relative_urls) {
26500          return self.documentBaseURI.toRelative(url);
26501        }
26502        url = self.documentBaseURI.toAbsolute(url, settings.remove_script_host);
26503        return url;
26504      };
26505      Editor.prototype.addVisual = function (elm) {
26506        var self = this;
26507        var settings = self.settings;
26508        var dom = self.dom;
26509        var cls;
26510        elm = elm || self.getBody();
26511        if (self.hasVisual === undefined) {
26512          self.hasVisual = settings.visual;
26513        }
26514        each$j(dom.select('table,a', elm), function (elm) {
26515          var value;
26516          switch (elm.nodeName) {
26517          case 'TABLE':
26518            cls = settings.visual_table_class || 'mce-item-table';
26519            value = dom.getAttrib(elm, 'border');
26520            if ((!value || value === '0') && self.hasVisual) {
26521              dom.addClass(elm, cls);
26522            } else {
26523              dom.removeClass(elm, cls);
26524            }
26525            return;
26526          case 'A':
26527            if (!dom.getAttrib(elm, 'href')) {
26528              value = dom.getAttrib(elm, 'name') || elm.id;
26529              cls = settings.visual_anchor_class || 'mce-item-anchor';
26530              if (value && self.hasVisual) {
26531                dom.addClass(elm, cls);
26532              } else {
26533                dom.removeClass(elm, cls);
26534              }
26535            }
26536            return;
26537          }
26538        });
26539        self.fire('VisualAid', {
26540          element: elm,
26541          hasVisual: self.hasVisual
26542        });
26543      };
26544      Editor.prototype.remove = function () {
26545        remove$6(this);
26546      };
26547      Editor.prototype.destroy = function (automatic) {
26548        destroy(this, automatic);
26549      };
26550      Editor.prototype.uploadImages = function (callback) {
26551        return this.editorUpload.uploadImages(callback);
26552      };
26553      Editor.prototype._scanForImages = function () {
26554        return this.editorUpload.scanForImages();
26555      };
26556      Editor.prototype.addButton = function () {
26557        throw new Error('editor.addButton has been removed in tinymce 5x, use editor.ui.registry.addButton or editor.ui.registry.addToggleButton or editor.ui.registry.addSplitButton instead');
26558      };
26559      Editor.prototype.addSidebar = function () {
26560        throw new Error('editor.addSidebar has been removed in tinymce 5x, use editor.ui.registry.addSidebar instead');
26561      };
26562      Editor.prototype.addMenuItem = function () {
26563        throw new Error('editor.addMenuItem has been removed in tinymce 5x, use editor.ui.registry.addMenuItem instead');
26564      };
26565      Editor.prototype.addContextToolbar = function () {
26566        throw new Error('editor.addContextToolbar has been removed in tinymce 5x, use editor.ui.registry.addContextToolbar instead');
26567      };
26568      return Editor;
26569    }();
26570
26571    var isEditorUIElement = function (elm) {
26572      return elm.className.toString().indexOf('tox-') !== -1 || elm.className.toString().indexOf('mce-') !== -1;
26573    };
26574    var FocusManager = { isEditorUIElement: isEditorUIElement };
26575
26576    var isManualNodeChange = function (e) {
26577      return e.type === 'nodechange' && e.selectionChange;
26578    };
26579    var registerPageMouseUp = function (editor, throttledStore) {
26580      var mouseUpPage = function () {
26581        throttledStore.throttle();
26582      };
26583      DOMUtils$1.DOM.bind(domGlobals.document, 'mouseup', mouseUpPage);
26584      editor.on('remove', function () {
26585        DOMUtils$1.DOM.unbind(domGlobals.document, 'mouseup', mouseUpPage);
26586      });
26587    };
26588    var registerFocusOut = function (editor) {
26589      editor.on('focusout', function () {
26590        SelectionBookmark.store(editor);
26591      });
26592    };
26593    var registerMouseUp = function (editor, throttledStore) {
26594      editor.on('mouseup touchend', function (e) {
26595        throttledStore.throttle();
26596      });
26597    };
26598    var registerEditorEvents = function (editor, throttledStore) {
26599      var browser = PlatformDetection$1.detect().browser;
26600      if (browser.isIE()) {
26601        registerFocusOut(editor);
26602      } else {
26603        registerMouseUp(editor, throttledStore);
26604      }
26605      editor.on('keyup NodeChange', function (e) {
26606        if (!isManualNodeChange(e)) {
26607          SelectionBookmark.store(editor);
26608        }
26609      });
26610    };
26611    var register$3 = function (editor) {
26612      var throttledStore = first(function () {
26613        SelectionBookmark.store(editor);
26614      }, 0);
26615      if (editor.inline) {
26616        registerPageMouseUp(editor, throttledStore);
26617      }
26618      editor.on('init', function () {
26619        registerEditorEvents(editor, throttledStore);
26620      });
26621      editor.on('remove', function () {
26622        throttledStore.cancel();
26623      });
26624    };
26625    var SelectionRestore = { register: register$3 };
26626
26627    var documentFocusInHandler;
26628    var DOM$8 = DOMUtils$1.DOM;
26629    var isEditorUIElement$1 = function (elm) {
26630      return FocusManager.isEditorUIElement(elm);
26631    };
26632    var isUIElement = function (editor, elm) {
26633      var customSelector = editor ? editor.settings.custom_ui_selector : '';
26634      var parent = DOM$8.getParent(elm, function (elm) {
26635        return isEditorUIElement$1(elm) || (customSelector ? editor.dom.is(elm, customSelector) : false);
26636      });
26637      return parent !== null;
26638    };
26639    var getActiveElement = function () {
26640      try {
26641        return domGlobals.document.activeElement;
26642      } catch (ex) {
26643        return domGlobals.document.body;
26644      }
26645    };
26646    var registerEvents = function (editorManager, e) {
26647      var editor = e.editor;
26648      SelectionRestore.register(editor);
26649      editor.on('focusin', function () {
26650        var self = this;
26651        var focusedEditor = editorManager.focusedEditor;
26652        if (focusedEditor !== self) {
26653          if (focusedEditor) {
26654            focusedEditor.fire('blur', { focusedEditor: self });
26655          }
26656          editorManager.setActive(self);
26657          editorManager.focusedEditor = self;
26658          self.fire('focus', { blurredEditor: focusedEditor });
26659          self.focus(true);
26660        }
26661      });
26662      editor.on('focusout', function () {
26663        var self = this;
26664        Delay.setEditorTimeout(self, function () {
26665          var focusedEditor = editorManager.focusedEditor;
26666          if (!isUIElement(self, getActiveElement()) && focusedEditor === self) {
26667            self.fire('blur', { focusedEditor: null });
26668            editorManager.focusedEditor = null;
26669          }
26670        });
26671      });
26672      if (!documentFocusInHandler) {
26673        documentFocusInHandler = function (e) {
26674          var activeEditor = editorManager.activeEditor;
26675          var target;
26676          target = e.target;
26677          if (activeEditor && target.ownerDocument === domGlobals.document) {
26678            if (target !== domGlobals.document.body && !isUIElement(activeEditor, target) && editorManager.focusedEditor === activeEditor) {
26679              activeEditor.fire('blur', { focusedEditor: null });
26680              editorManager.focusedEditor = null;
26681            }
26682          }
26683        };
26684        DOM$8.bind(domGlobals.document, 'focusin', documentFocusInHandler);
26685      }
26686    };
26687    var unregisterDocumentEvents = function (editorManager, e) {
26688      if (editorManager.focusedEditor === e.editor) {
26689        editorManager.focusedEditor = null;
26690      }
26691      if (!editorManager.activeEditor) {
26692        DOM$8.unbind(domGlobals.document, 'focusin', documentFocusInHandler);
26693        documentFocusInHandler = null;
26694      }
26695    };
26696    var setup$h = function (editorManager) {
26697      editorManager.on('AddEditor', curry(registerEvents, editorManager));
26698      editorManager.on('RemoveEditor', curry(unregisterDocumentEvents, editorManager));
26699    };
26700    var FocusController = {
26701      setup: setup$h,
26702      isEditorUIElement: isEditorUIElement$1,
26703      isUIElement: isUIElement
26704    };
26705
26706    var DOM$9 = DOMUtils$1.DOM;
26707    var explode$4 = Tools.explode, each$k = Tools.each, extend$4 = Tools.extend;
26708    var instanceCounter = 0, beforeUnloadDelegate, boundGlobalEvents = false;
26709    var legacyEditors = [];
26710    var editors = [];
26711    var isValidLegacyKey = function (id) {
26712      return id !== 'length';
26713    };
26714    var globalEventDelegate = function (e) {
26715      var type = e.type;
26716      each$k(EditorManager.get(), function (editor) {
26717        switch (type) {
26718        case 'scroll':
26719          editor.fire('ScrollWindow', e);
26720          break;
26721        case 'resize':
26722          editor.fire('ResizeWindow', e);
26723          break;
26724        }
26725      });
26726    };
26727    var toggleGlobalEvents = function (state) {
26728      if (state !== boundGlobalEvents) {
26729        if (state) {
26730          DomQuery(window).on('resize scroll', globalEventDelegate);
26731        } else {
26732          DomQuery(window).off('resize scroll', globalEventDelegate);
26733        }
26734        boundGlobalEvents = state;
26735      }
26736    };
26737    var removeEditorFromList = function (targetEditor) {
26738      var oldEditors = editors;
26739      delete legacyEditors[targetEditor.id];
26740      for (var i = 0; i < legacyEditors.length; i++) {
26741        if (legacyEditors[i] === targetEditor) {
26742          legacyEditors.splice(i, 1);
26743          break;
26744        }
26745      }
26746      editors = filter(editors, function (editor) {
26747        return targetEditor !== editor;
26748      });
26749      if (EditorManager.activeEditor === targetEditor) {
26750        EditorManager.activeEditor = editors.length > 0 ? editors[0] : null;
26751      }
26752      if (EditorManager.focusedEditor === targetEditor) {
26753        EditorManager.focusedEditor = null;
26754      }
26755      return oldEditors.length !== editors.length;
26756    };
26757    var purgeDestroyedEditor = function (editor) {
26758      if (editor && editor.initialized && !(editor.getContainer() || editor.getBody()).parentNode) {
26759        removeEditorFromList(editor);
26760        editor.unbindAllNativeEvents();
26761        editor.destroy(true);
26762        editor.removed = true;
26763        editor = null;
26764      }
26765      return editor;
26766    };
26767    var EditorManager = __assign({}, Observable, {
26768      _beforeUnloadHandler: null,
26769      baseURI: null,
26770      baseURL: null,
26771      defaultSettings: {},
26772      documentBaseURL: null,
26773      suffix: null,
26774      $: DomQuery,
26775      majorVersion: '5',
26776      minorVersion: '0.4',
26777      releaseDate: '2019-04-23',
26778      editors: legacyEditors,
26779      i18n: I18n,
26780      activeEditor: null,
26781      focusedEditor: null,
26782      settings: {},
26783      setup: function () {
26784        var self = this;
26785        var baseURL, documentBaseURL, suffix = '', preInit, src;
26786        documentBaseURL = URI.getDocumentBaseUrl(domGlobals.document.location);
26787        if (/^[^:]+:\/\/\/?[^\/]+\//.test(documentBaseURL)) {
26788          documentBaseURL = documentBaseURL.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
26789          if (!/[\/\\]$/.test(documentBaseURL)) {
26790            documentBaseURL += '/';
26791          }
26792        }
26793        preInit = window.tinymce || window.tinyMCEPreInit;
26794        if (preInit) {
26795          baseURL = preInit.base || preInit.baseURL;
26796          suffix = preInit.suffix;
26797        } else {
26798          var scripts = domGlobals.document.getElementsByTagName('script');
26799          for (var i = 0; i < scripts.length; i++) {
26800            src = scripts[i].src;
26801            var srcScript = src.substring(src.lastIndexOf('/'));
26802            if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
26803              if (srcScript.indexOf('.min') !== -1) {
26804                suffix = '.min';
26805              }
26806              baseURL = src.substring(0, src.lastIndexOf('/'));
26807              break;
26808            }
26809          }
26810          if (!baseURL && domGlobals.document.currentScript) {
26811            src = domGlobals.document.currentScript.src;
26812            if (src.indexOf('.min') !== -1) {
26813              suffix = '.min';
26814            }
26815            baseURL = src.substring(0, src.lastIndexOf('/'));
26816          }
26817        }
26818        self.baseURL = new URI(documentBaseURL).toAbsolute(baseURL);
26819        self.documentBaseURL = documentBaseURL;
26820        self.baseURI = new URI(self.baseURL);
26821        self.suffix = suffix;
26822        FocusController.setup(self);
26823      },
26824      overrideDefaults: function (defaultSettings) {
26825        var baseUrl, suffix;
26826        baseUrl = defaultSettings.base_url;
26827        if (baseUrl) {
26828          this.baseURL = new URI(this.documentBaseURL).toAbsolute(baseUrl.replace(/\/+$/, ''));
26829          this.baseURI = new URI(this.baseURL);
26830        }
26831        suffix = defaultSettings.suffix;
26832        if (defaultSettings.suffix) {
26833          this.suffix = suffix;
26834        }
26835        this.defaultSettings = defaultSettings;
26836        var pluginBaseUrls = defaultSettings.plugin_base_urls;
26837        for (var name in pluginBaseUrls) {
26838          AddOnManager$1.PluginManager.urls[name] = pluginBaseUrls[name];
26839        }
26840      },
26841      init: function (settings) {
26842        var self = this;
26843        var result, invalidInlineTargets;
26844        invalidInlineTargets = Tools.makeMap('area base basefont br col frame hr img input isindex link meta param embed source wbr track ' + 'colgroup option table tbody tfoot thead tr th td script noscript style textarea video audio iframe object menu', ' ');
26845        var isInvalidInlineTarget = function (settings, elm) {
26846          return settings.inline && elm.tagName.toLowerCase() in invali
26846dInlineTargets;
26847        };
26848        var createId = function (elm) {
26849          var id = elm.id;
26850          if (!id) {
26851            id = elm.name;
26852            if (id && !DOM$9.get(id)) {
26853              id = elm.name;
26854            } else {
26855              id = DOM$9.uniqueId();
26856            }
26857            elm.setAttribute('id', id);
26858          }
26859          return id;
26860        };
26861        var execCallback = function (name) {
26862          var callback = settings[name];
26863          if (!callback) {
26864            return;
26865          }
26866          return callback.apply(self, Array.prototype.slice.call(arguments, 2));
26867        };
26868        var hasClass = function (elm, className) {
26869          return className.constructor === RegExp ? className.test(elm.className) : DOM$9.hasClass(elm, className);
26870        };
26871        var findTargets = function (settings) {
26872          var l, targets = [];
26873          if (Env.ie && Env.ie < 11) {
26874            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/');
26875            return [];
26876          }
26877          if (settings.types) {
26878            each$k(settings.types, function (type) {
26879              targets = targets.concat(DOM$9.select(type.selector));
26880            });
26881            return targets;
26882          } else if (settings.selector) {
26883            return DOM$9.select(settings.selector);
26884          } else if (settings.target) {
26885            return [settings.target];
26886          }
26887          switch (settings.mode) {
26888          case 'exact':
26889            l = settings.elements || '';
26890            if (l.length > 0) {
26891              each$k(explode$4(l), function (id) {
26892                var elm;
26893                if (elm = DOM$9.get(id)) {
26894                  targets.push(elm);
26895                } else {
26896                  each$k(domGlobals.document.forms, function (f) {
26897                    each$k(f.elements, function (e) {
26898                      if (e.name === id) {
26899                        id = 'mce_editor_' + instanceCounter++;
26900                        DOM$9.setAttrib(e, 'id', id);
26901                        targets.push(e);
26902                      }
26903                    });
26904                  });
26905                }
26906              });
26907            }
26908            break;
26909          case 'textareas':
26910          case 'specific_textareas':
26911            each$k(DOM$9.select('textarea'), function (elm) {
26912              if (settings.editor_deselector && hasClass(elm, settings.editor_deselector)) {
26913                return;
26914              }
26915              if (!settings.editor_selector || hasClass(elm, settings.editor_selector)) {
26916                targets.push(elm);
26917              }
26918            });
26919            break;
26920          }
26921          return targets;
26922        };
26923        var provideResults = function (editors) {
26924          result = editors;
26925        };
26926        var initEditors = function () {
26927          var initCount = 0;
26928          var editors = [];
26929          var targets;
26930          var createEditor = function (id, settings, targetElm) {
26931            var editor = new Editor(id, settings, self);
26932            editors.push(editor);
26933            editor.on('init', function () {
26934              if (++initCount === targets.length) {
26935                provideResults(editors);
26936              }
26937            });
26938            editor.targetElm = editor.targetElm || targetElm;
26939            editor.render();
26940          };
26941          DOM$9.unbind(window, 'ready', initEditors);
26942          execCallback('onpageload');
26943          targets = DomQuery.unique(findTargets(settings));
26944          if (settings.types) {
26945            each$k(settings.types, function (type) {
26946              Tools.each(targets, function (elm) {
26947                if (DOM$9.is(elm, type.selector)) {
26948                  createEditor(createId(elm), extend$4({}, settings, type), elm);
26949                  return false;
26950                }
26951                return true;
26952              });
26953            });
26954            return;
26955          }
26956          Tools.each(targets, function (elm) {
26957            purgeDestroyedEditor(self.get(elm.id));
26958          });
26959          targets = Tools.grep(targets, function (elm) {
26960            return !self.get(elm.id);
26961          });
26962          if (targets.length === 0) {
26963            provideResults([]);
26964          } else {
26965            each$k(targets, function (elm) {
26966              if (isInvalidInlineTarget(settings, elm)) {
26967                ErrorReporter.initError('Could not initialize inline editor on invalid inline target element', elm);
26968              } else {
26969                createEditor(createId(elm), settings, elm);
26970              }
26971            });
26972          }
26973        };
26974        self.settings = settings;
26975        DOM$9.bind(window, 'ready', initEditors);
26976        return new promiseObj(function (resolve) {
26977          if (result) {
26978            resolve(result);
26979          } else {
26980            provideResults = function (editors) {
26981              resolve(editors);
26982            };
26983          }
26984        });
26985      },
26986      get: function (id) {
26987        if (arguments.length === 0) {
26988          return editors.slice(0);
26989        } else if (isString(id)) {
26990          return find(editors, function (editor) {
26991            return editor.id === id;
26992          }).getOr(null);
26993        } else if (isNumber(id)) {
26994          return editors[id] ? editors[id] : null;
26995        } else {
26996          return null;
26997        }
26998      },
26999      add: function (editor) {
27000        var self = this;
27001        var existingEditor;
27002        existingEditor = legacyEditors[editor.id];
27003        if (existingEditor === editor) {
27004          return editor;
27005        }
27006        if (self.get(editor.id) === null) {
27007          if (isValidLegacyKey(editor.id)) {
27008            legacyEditors[editor.id] = editor;
27009          }
27010          legacyEditors.push(editor);
27011          editors.push(editor);
27012        }
27013        toggleGlobalEvents(true);
27014        self.activeEditor = editor;
27015        self.fire('AddEditor', { editor: editor });
27016        if (!beforeUnloadDelegate) {
27017          beforeUnloadDelegate = function () {
27018            self.fire('BeforeUnload');
27019          };
27020          DOM$9.bind(window, 'beforeunload', beforeUnloadDelegate);
27021        }
27022        return editor;
27023      },
27024      createEditor: function (id, settings) {
27025        return this.add(new Editor(id, settings, this));
27026      },
27027      remove: function (selector) {
27028        var self = this;
27029        var i, editor;
27030        if (!selector) {
27031          for (i = editors.length - 1; i >= 0; i--) {
27032            self.remove(editors[i]);
27033          }
27034          return;
27035        }
27036        if (isString(selector)) {
27037          each$k(DOM$9.select(selector), function (elm) {
27038            editor = self.get(elm.id);
27039            if (editor) {
27040              self.remove(editor);
27041            }
27042          });
27043          return;
27044        }
27045        editor = selector;
27046        if (isNull(self.get(editor.id))) {
27047          return null;
27048        }
27049        if (removeEditorFromList(editor)) {
27050          self.fire('RemoveEditor', { editor: editor });
27051        }
27052        if (editors.length === 0) {
27053          DOM$9.unbind(window, 'beforeunload', beforeUnloadDelegate);
27054        }
27055        editor.remove();
27056        toggleGlobalEvents(editors.length > 0);
27057        return editor;
27058      },
27059      execCommand: function (cmd, ui, value) {
27060        var self = this, editor = self.get(value);
27061        switch (cmd) {
27062        case 'mceAddEditor':
27063          if (!self.get(value)) {
27064            new Editor(value, self.settings, self).render();
27065          }
27066          return true;
27067        case 'mceRemoveEditor':
27068          if (editor) {
27069            editor.remove();
27070          }
27071          return true;
27072        case 'mceToggleEditor':
27073          if (!editor) {
27074            self.execCommand('mceAddEditor', 0, value);
27075            return true;
27076          }
27077          if (editor.isHidden()) {
27078            editor.show();
27079          } else {
27080            editor.hide();
27081          }
27082          return true;
27083        }
27084        if (self.activeEditor) {
27085          return self.activeEditor.execCommand(cmd, ui, value);
27086        }
27087        return false;
27088      },
27089      triggerSave: function () {
27090        each$k(editors, function (editor) {
27091          editor.save();
27092        });
27093      },
27094      addI18n: function (code, items) {
27095        I18n.add(code, items);
27096      },
27097      translate: function (text) {
27098        return I18n.translate(text);
27099      },
27100      setActive: function (editor) {
27101        var activeEditor = this.activeEditor;
27102        if (this.activeEditor !== editor) {
27103          if (activeEditor) {
27104            activeEditor.fire('deactivate', { relatedTarget: editor });
27105          }
27106          editor.fire('activate', { relatedTarget: activeEditor });
27107        }
27108        this.activeEditor = editor;
27109      }
27110    });
27111    EditorManager.setup();
27112
27113    function RangeUtils(dom) {
27114      var walk = function (rng, callback) {
27115        return RangeWalk.walk(dom, rng, callback);
27116      };
27117      var split = split$1;
27118      var normalize = function (rng) {
27119        return NormalizeRange.normalize(dom, rng).fold(constant(false), function (normalizedRng) {
27120          rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset);
27121          rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset);
27122          return true;
27123        });
27124      };
27125      return {
27126        walk: walk,
27127        split: split,
27128        normalize: normalize
27129      };
27130    }
27131    (function (RangeUtils) {
27132      RangeUtils.compareRanges = RangeCompare.isEq;
27133      RangeUtils.getCaretRangeFromPoint = CaretRangeFromPoint.fromPoint;
27134      RangeUtils.getSelectedNode = getSelectedNode;
27135      RangeUtils.getNode = getNode;
27136    }(RangeUtils || (RangeUtils = {})));
27137    var RangeUtils$1 = RangeUtils;
27138
27139    var min = Math.min, max = Math.max, round$2 = Math.round;
27140    var relativePosition = function (rect, targetRect, rel) {
27141      var x, y, w, h, targetW, targetH;
27142      x = targetRect.x;
27143      y = targetRect.y;
27144      w = rect.w;
27145      h = rect.h;
27146      targetW = targetRect.w;
27147      targetH = targetRect.h;
27148      rel = (rel || '').split('');
27149      if (rel[0] === 'b') {
27150        y += targetH;
27151      }
27152      if (rel[1] === 'r') {
27153        x += targetW;
27154      }
27155      if (rel[0] === 'c') {
27156        y += round$2(targetH / 2);
27157      }
27158      if (rel[1] === 'c') {
27159        x += round$2(targetW / 2);
27160      }
27161      if (rel[3] === 'b') {
27162        y -= h;
27163      }
27164      if (rel[4] === 'r') {
27165        x -= w;
27166      }
27167      if (rel[3] === 'c') {
27168        y -= round$2(h / 2);
27169      }
27170      if (rel[4] === 'c') {
27171        x -= round$2(w / 2);
27172      }
27173      return create$5(x, y, w, h);
27174    };
27175    var findBestRelativePosition = function (rect, targetRect, constrainRect, rels) {
27176      var pos, i;
27177      for (i = 0; i < rels.length; i++) {
27178        pos = relativePosition(rect, targetRect, rels[i]);
27179        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) {
27180          return rels[i];
27181        }
27182      }
27183      return null;
27184    };
27185    var inflate = function (rect, w, h) {
27186      return create$5(rect.x - w, rect.y - h, rect.w + w * 2, rect.h + h * 2);
27187    };
27188    var intersect = function (rect, cropRect) {
27189      var x1, y1, x2, y2;
27190      x1 = max(rect.x, cropRect.x);
27191      y1 = max(rect.y, cropRect.y);
27192      x2 = min(rect.x + rect.w, cropRect.x + cropRect.w);
27193      y2 = min(rect.y + rect.h, cropRect.y + cropRect.h);
27194      if (x2 - x1 < 0 || y2 - y1 < 0) {
27195        return null;
27196      }
27197      return create$5(x1, y1, x2 - x1, y2 - y1);
27198    };
27199    var clamp$1 = function (rect, clampRect, fixedSize) {
27200      var underflowX1, underflowY1, overflowX2, overflowY2, x1, y1, x2, y2, cx2, cy2;
27201      x1 = rect.x;
27202      y1 = rect.y;
27203      x2 = rect.x + rect.w;
27204      y2 = rect.y + rect.h;
27205      cx2 = clampRect.x + clampRect.w;
27206      cy2 = clampRect.y + clampRect.h;
27207      underflowX1 = max(0, clampRect.x - x1);
27208      underflowY1 = max(0, clampRect.y - y1);
27209      overflowX2 = max(0, x2 - cx2);
27210      overflowY2 = max(0, y2 - cy2);
27211      x1 += underflowX1;
27212      y1 += underflowY1;
27213      if (fixedSize) {
27214        x2 += underflowX1;
27215        y2 += underflowY1;
27216        x1 -= overflowX2;
27217        y1 -= overflowY2;
27218      }
27219      x2 -= overflowX2;
27220      y2 -= overflowY2;
27221      return create$5(x1, y1, x2 - x1, y2 - y1);
27222    };
27223    var create$5 = function (x, y, w, h) {
27224      return {
27225        x: x,
27226        y: y,
27227        w: w,
27228        h: h
27229      };
27230    };
27231    var fromClientRect = function (clientRect) {
27232      return create$5(clientRect.left, clientRect.top, clientRect.width, clientRect.height);
27233    };
27234    var Rect = {
27235      inflate: inflate,
27236      relativePosition: relativePosition,
27237      findBestRelativePosition: findBestRelativePosition,
27238      intersect: intersect,
27239      clamp: clamp$1,
27240      create: create$5,
27241      fromClientRect: fromClientRect
27242    };
27243
27244    var each$l = Tools.each, extend$5 = Tools.extend;
27245    var extendClass, initializing;
27246    var Class = function () {
27247    };
27248    Class.extend = extendClass = function (prop) {
27249      var self = this;
27250      var _super = self.prototype;
27251      var prototype, name, member;
27252      var Class = function () {
27253        var i, mixins, mixin;
27254        var self = this;
27255        if (!initializing) {
27256          if (self.init) {
27257            self.init.apply(self, arguments);
27258          }
27259          mixins = self.Mixins;
27260          if (mixins) {
27261            i = mixins.length;
27262            while (i--) {
27263              mixin = mixins[i];
27264              if (mixin.init) {
27265                mixin.init.apply(self, arguments);
27266              }
27267            }
27268          }
27269        }
27270      };
27271      var dummy = function () {
27272        return this;
27273      };
27274      var createMethod = function (name, fn) {
27275        return function () {
27276          var self = this;
27277          var tmp = self._super;
27278          var ret;
27279          self._super = _super[name];
27280          ret = fn.apply(self, arguments);
27281          self._super = tmp;
27282          return ret;
27283        };
27284      };
27285      initializing = true;
27286      prototype = new self();
27287      initializing = false;
27288      if (prop.Mixins) {
27289        each$l(prop.Mixins, function (mixin) {
27290          for (var name_1 in mixin) {
27291            if (name_1 !== 'init') {
27292              prop[name_1] = mixin[name_1];
27293            }
27294          }
27295        });
27296        if (_super.Mixins) {
27297          prop.Mixins = _super.Mixins.concat(prop.Mixins);
27298        }
27299      }
27300      if (prop.Methods) {
27301        each$l(prop.Methods.split(','), function (name) {
27302          prop[name] = dummy;
27303        });
27304      }
27305      if (prop.Properties) {
27306        each$l(prop.Properties.split(','), function (name) {
27307          var fieldName = '_' + name;
27308          prop[name] = function (value) {
27309            var self = this;
27310            if (value !== undefined) {
27311              self[fieldName] = value;
27312              return self;
27313            }
27314            return self[fieldName];
27315          };
27316        });
27317      }
27318      if (prop.Statics) {
27319        each$l(prop.Statics, function (func, name) {
27320          Class[name] = func;
27321        });
27322      }
27323      if (prop.Defaults && _super.Defaults) {
27324        prop.Defaults = extend$5({}, _super.Defaults, prop.Defaults);
27325      }
27326      for (name in prop) {
27327        member = prop[name];
27328        if (typeof member === 'function' && _super[name]) {
27329          prototype[name] = createMethod(name, member);
27330        } else {
27331          prototype[name] = member;
27332        }
27333      }
27334      Class.prototype = prototype;
27335      Class.constructor = Class;
27336      Class.extend = extendClass;
27337      return Class;
27338    };
27339
27340    var min$1 = Math.min, max$1 = Math.max, round$3 = Math.round;
27341    var Color = function (value) {
27342      var self = {};
27343      var r = 0, g = 0, b = 0;
27344      var rgb2hsv = function (r, g, b) {
27345        var h, s, v, d, minRGB, maxRGB;
27346        h = 0;
27347        s = 0;
27348        v = 0;
27349        r = r / 255;
27350        g = g / 255;
27351        b = b / 255;
27352        minRGB = min$1(r, min$1(g, b));
27353        maxRGB = max$1(r, max$1(g, b));
27354        if (minRGB === maxRGB) {
27355          v = minRGB;
27356          return {
27357            h: 0,
27358            s: 0,
27359            v: v * 100
27360          };
27361        }
27362        d = r === minRGB ? g - b : b === minRGB ? r - g : b - r;
27363        h = r === minRGB ? 3 : b === minRGB ? 1 : 5;
27364        h = 60 * (h - d / (maxRGB - minRGB));
27365        s = (maxRGB - minRGB) / maxRGB;
27366        v = maxRGB;
27367        return {
27368          h: round$3(h),
27369          s: round$3(s * 100),
27370          v: round$3(v * 100)
27371        };
27372      };
27373      var hsvToRgb = function (hue, saturation, brightness) {
27374        var side, chroma, x, match;
27375        hue = (parseInt(hue, 10) || 0) % 360;
27376        saturation = parseInt(saturation, 10) / 100;
27377        brightness = parseInt(brightness, 10) / 100;
27378        saturation = max$1(0, min$1(saturation, 1));
27379        brightness = max$1(0, min$1(brightness, 1));
27380        if (saturation === 0) {
27381          r = g = b = round$3(255 * brightness);
27382          return;
27383        }
27384        side = hue / 60;
27385        chroma = brightness * saturation;
27386        x = chroma * (1 - Math.abs(side % 2 - 1));
27387        match = brightness - chroma;
27388        switch (Math.floor(side)) {
27389        case 0:
27390          r = chroma;
27391          g = x;
27392          b = 0;
27393          break;
27394        case 1:
27395          r = x;
27396          g = chroma;
27397          b = 0;
27398          break;
27399        case 2:
27400          r = 0;
27401          g = chroma;
27402          b = x;
27403          break;
27404        case 3:
27405          r = 0;
27406          g = x;
27407          b = chroma;
27408          break;
27409        case 4:
27410          r = x;
27411          g = 0;
27412          b = chroma;
27413          break;
27414        case 5:
27415          r = chroma;
27416          g = 0;
27417          b = x;
27418          break;
27419        default:
27420          r = g = b = 0;
27421        }
27422        r = round$3(255 * (r + match));
27423        g = round$3(255 * (g + match));
27424        b = round$3(255 * (b + match));
27425      };
27426      var toHex = function () {
27427        var hex = function (val) {
27428          val = parseInt(val, 10).toString(16);
27429          return val.length > 1 ? val : '0' + val;
27430        };
27431        return '#' + hex(r) + hex(g) + hex(b);
27432      };
27433      var toRgb = function () {
27434        return {
27435          r: r,
27436          g: g,
27437          b: b
27438        };
27439      };
27440      var toHsv = function () {
27441        return rgb2hsv(r, g, b);
27442      };
27443      var parse = function (value) {
27444        var matches;
27445        if (typeof value === 'object') {
27446          if ('r' in value) {
27447            r = value.r;
27448            g = value.g;
27449            b = value.b;
27450          } else if ('v' in value) {
27451            hsvToRgb(value.h, value.s, value.v);
27452          }
27453        } else {
27454          if (matches = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(value)) {
27455            r = parseInt(matches[1], 10);
27456            g = parseInt(matches[2], 10);
27457            b = parseInt(matches[3], 10);
27458          } else if (matches = /#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(value)) {
27459            r = parseInt(matches[1], 16);
27460            g = parseInt(matches[2], 16);
27461            b = parseInt(matches[3], 16);
27462          } else if (matches = /#([0-F])([0-F])([0-F])/gi.exec(value)) {
27463            r = parseInt(matches[1] + matches[1], 16);
27464            g = parseInt(matches[2] + matches[2], 16);
27465            b = parseInt(matches[3] + matches[3], 16);
27466          }
27467        }
27468        r = r < 0 ? 0 : r >
27468 255 ? 255 : r;
27469        g = g < 0 ? 0 : g > 255 ? 255 : g;
27470        b = b < 0 ? 0 : b > 255 ? 255 : b;
27471        return self;
27472      };
27473      if (value) {
27474        parse(value);
27475      }
27476      self.toRgb = toRgb;
27477      self.toHsv = toHsv;
27478      self.toHex = toHex;
27479      self.parse = parse;
27480      return self;
27481    };
27482
27483    var serialize = function (obj) {
27484      var data = JSON.stringify(obj);
27485      if (!isString(data)) {
27486        return data;
27487      }
27488      return data.replace(/[\u0080-\uFFFF]/g, function (match) {
27489        var hexCode = match.charCodeAt(0).toString(16);
27490        return '\\u' + '0000'.substring(hexCode.length) + hexCode;
27491      });
27492    };
27493    var JSONUtils = {
27494      serialize: serialize,
27495      parse: function (text) {
27496        try {
27497          return JSON.parse(text);
27498        } catch (ex) {
27499        }
27500      }
27501    };
27502
27503    var JSONP = {
27504      callbacks: {},
27505      count: 0,
27506      send: function (settings) {
27507        var self = this, dom = DOMUtils$1.DOM, count = settings.count !== undefined ? settings.count : self.count;
27508        var id = 'tinymce_jsonp_' + count;
27509        self.callbacks[count] = function (json) {
27510          dom.remove(id);
27511          delete self.callbacks[count];
27512          settings.callback(json);
27513        };
27514        dom.add(dom.doc.body, 'script', {
27515          id: id,
27516          src: settings.url,
27517          type: 'text/javascript'
27518        });
27519        self.count++;
27520      }
27521    };
27522
27523    var XHR = __assign({}, Observable, {
27524      send: function (settings) {
27525        var xhr, count = 0;
27526        var ready = function () {
27527          if (!settings.async || xhr.readyState === 4 || count++ > 10000) {
27528            if (settings.success && count < 10000 && xhr.status === 200) {
27529              settings.success.call(settings.success_scope, '' + xhr.responseText, xhr, settings);
27530            } else if (settings.error) {
27531              settings.error.call(settings.error_scope, count > 10000 ? 'TIMED_OUT' : 'GENERAL', xhr, settings);
27532            }
27533            xhr = null;
27534          } else {
27535            Delay.setTimeout(ready, 10);
27536          }
27537        };
27538        settings.scope = settings.scope || this;
27539        settings.success_scope = settings.success_scope || settings.scope;
27540        settings.error_scope = settings.error_scope || settings.scope;
27541        settings.async = settings.async !== false;
27542        settings.data = settings.data || '';
27543        XHR.fire('beforeInitialize', { settings: settings });
27544        xhr = XMLHttpRequest();
27545        if (xhr) {
27546          if (xhr.overrideMimeType) {
27547            xhr.overrideMimeType(settings.content_type);
27548          }
27549          xhr.open(settings.type || (settings.data ? 'POST' : 'GET'), settings.url, settings.async);
27550          if (settings.crossDomain) {
27551            xhr.withCredentials = true;
27552          }
27553          if (settings.content_type) {
27554            xhr.setRequestHeader('Content-Type', settings.content_type);
27555          }
27556          if (settings.requestheaders) {
27557            Tools.each(settings.requestheaders, function (header) {
27558              xhr.setRequestHeader(header.key, header.value);
27559            });
27560          }
27561          xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
27562          xhr = XHR.fire('beforeSend', {
27563            xhr: xhr,
27564            settings: settings
27565          }).xhr;
27566          xhr.send(settings.data);
27567          if (!settings.async) {
27568            return ready();
27569          }
27570          Delay.setTimeout(ready, 10);
27571        }
27572      }
27573    });
27574
27575    var extend$6 = Tools.extend;
27576    var JSONRequest = function () {
27577      function JSONRequest(settings) {
27578        this.settings = extend$6({}, settings);
27579        this.count = 0;
27580      }
27581      JSONRequest.sendRPC = function (o) {
27582        return new JSONRequest().send(o);
27583      };
27584      JSONRequest.prototype.send = function (args) {
27585        var ecb = args.error, scb = args.success;
27586        var xhrArgs = extend$6(this.settings, args);
27587        xhrArgs.success = function (c, x) {
27588          c = JSONUtils.parse(c);
27589          if (typeof c === 'undefined') {
27590            c = { error: 'JSON Parse error.' };
27591          }
27592          if (c.error) {
27593            ecb.call(xhrArgs.error_scope || xhrArgs.scope, c.error, x);
27594          } else {
27595            scb.call(xhrArgs.success_scope || xhrArgs.scope, c.result);
27596          }
27597        };
27598        xhrArgs.error = function (ty, x) {
27599          if (ecb) {
27600            ecb.call(xhrArgs.error_scope || xhrArgs.scope, ty, x);
27601          }
27602        };
27603        xhrArgs.data = JSONUtils.serialize({
27604          id: args.id || 'c' + this.count++,
27605          method: args.method,
27606          params: args.params
27607        });
27608        xhrArgs.content_type = 'application/json';
27609        XHR.send(xhrArgs);
27610      };
27611      return JSONRequest;
27612    }();
27613
27614    var create$6 = function () {
27615      return function () {
27616        var data = {};
27617        var keys = [];
27618        var storage = {
27619          getItem: function (key) {
27620            var item = data[key];
27621            return item ? item : null;
27622          },
27623          setItem: function (key, value) {
27624            keys.push(key);
27625            data[key] = String(value);
27626          },
27627          key: function (index) {
27628            return keys[index];
27629          },
27630          removeItem: function (key) {
27631            keys = keys.filter(function (k) {
27632              return k === key;
27633            });
27634            delete data[key];
27635          },
27636          clear: function () {
27637            keys = [];
27638            data = {};
27639          },
27640          length: 0
27641        };
27642        Object.defineProperty(storage, 'length', {
27643          get: function () {
27644            return keys.length;
27645          },
27646          configurable: false,
27647          enumerable: false
27648        });
27649        return storage;
27650      }();
27651    };
27652
27653    var localStorage;
27654    try {
27655      localStorage = domGlobals.window.localStorage;
27656    } catch (e) {
27657      localStorage = create$6();
27658    }
27659    var LocalStorage = localStorage;
27660
27661    var publicApi = {
27662      geom: { Rect: Rect },
27663      util: {
27664        Promise: promiseObj,
27665        Delay: Delay,
27666        Tools: Tools,
27667        VK: VK,
27668        URI: URI,
27669        Class: Class,
27670        EventDispatcher: EventDispatcher,
27671        Observable: Observable,
27672        I18n: I18n,
27673        XHR: XHR,
27674        JSON: JSONUtils,
27675        JSONRequest: JSONRequest,
27676        JSONP: JSONP,
27677        LocalStorage: LocalStorage,
27678        Color: Color
27679      },
27680      dom: {
27681        EventUtils: EventUtils,
27682        Sizzle: Sizzle,
27683        DomQuery: DomQuery,
27684        TreeWalker: TreeWalker,
27685        DOMUtils: DOMUtils$1,
27686        ScriptLoader: ScriptLoader,
27687        RangeUtils: RangeUtils$1,
27688        Serializer: Serializer$1,
27689        ControlSelection: ControlSelection,
27690        BookmarkManager: BookmarkManager$1,
27691        Selection: Selection,
27692        Event: EventUtils.Event
27693      },
27694      html: {
27695        Styles: Styles,
27696        Entities: Entities,
27697        Node: Node$1,
27698        Schema: Schema,
27699        SaxParser: SaxParser$1,
27700        DomParser: DomParser,
27701        Writer: Writer,
27702        Serializer: Serializer
27703      },
27704      Env: Env,
27705      AddOnManager: AddOnManager$1,
27706      Annotator: Annotator,
27707      Formatter: Formatter,
27708      UndoManager: UndoManager,
27709      EditorCommands: EditorCommands,
27710      WindowManager: WindowManager,
27711      NotificationManager: NotificationManager,
27712      EditorObservable: EditorObservable,
27713      Shortcuts: Shortcuts,
27714      Editor: Editor,
27715      FocusManager: FocusManager,
27716      EditorManager: EditorManager,
27717      DOM: DOMUtils$1.DOM,
27718      ScriptLoader: ScriptLoader.ScriptLoader,
27719      PluginManager: AddOnManager$1.PluginManager,
27720      ThemeManager: AddOnManager$1.ThemeManager,
27721      IconManager: IconManager,
27722      trim: Tools.trim,
27723      isArray: Tools.isArray,
27724      is: Tools.is,
27725      toArray: Tools.toArray,
27726      makeMap: Tools.makeMap,
27727      each: Tools.each,
27728      map: Tools.map,
27729      grep: Tools.grep,
27730      inArray: Tools.inArray,
27731      extend: Tools.extend,
27732      create: Tools.create,
27733      walk: Tools.walk,
27734      createNS: Tools.createNS,
27735      resolve: Tools.resolve,
27736      explode: Tools.explode,
27737      _addCacheSuffix: Tools._addCacheSuffix,
27738      isOpera: Env.opera,
27739      isWebKit: Env.webkit,
27740      isIE: Env.ie,
27741      isGecko: Env.gecko,
27742      isMac: Env.mac
27743    };
27744    var tinymce = Tools.extend(EditorManager, publicApi);
27745
27746    var exportToModuleLoaders = function (tinymce) {
27747      if (typeof module === 'object') {
27748        try {
27749          module.exports = tinymce;
27750        } catch (_) {
27751        }
27752      }
27753    };
27754    var exportToWindowGlobal = function (tinymce) {
27755      window.tinymce = tinymce;
27756      window.tinyMCE = tinymce;
27757    };
27758    exportToWindowGlobal(tinymce);
27759    exportToModuleLoaders(tinymce);
27760
27761}(window));
27762})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.