PageSourceSearch

https://static.shopmaker.com/assets/tinymce-0b1840b7cec0f237ed6b30…e37b955e6f6f8a65a33e1d236a1b007d4635a968.js

js shopmaker.com collected 2026-09-29 23:29:25 UTC 1,143,029 bytes, 30,656 lines download raw bytes

1window.TinyMCERails = {
2  configuration: {
3    default: {}
4  },
5
6  initialize: function(config, options) {
7    if (typeof tinyMCE != 'undefined') {
8      // Merge the custom options with the given configuration
9      var configuration = TinyMCERails.configuration[config || 'default'];
10      configuration = TinyMCERails._merge(configuration, options);
11
12      tinymce.init(configuration);
13    } else {
14      // Wait until TinyMCE is loaded
15      setTimeout(function() {
16        TinyMCERails.initialize(config, options);
17      }, 50);
18    }
19  },
20
21  setupTurbolinks: function() {
22    // Remove all TinyMCE instances before rendering
23    document.addEventListener('turbolinks:before-render', function() {
24      tinymce.remove();
25    });
26  },
27
28  _merge: function() {
29    var result = {};
30
31    for (var i = 0; i < arguments.length; ++i) {
32      var source = arguments[i];
33
34      for (var key in source) {
35        if (Object.prototype.hasOwnProperty.call(source, key)) {
36          if (Object.prototype.toString.call(source[key]) === '[object Object]') {
37            result[key] = TinyMCERails._merge(result[key], source[key]);
38          } else {
39            result[key] = source[key];
40          }
41        }
42      }
43    }
44
45    return result;
46  }
47};
48
49if (typeof Turbolinks != 'undefined' && Turbolinks.supported) {
50  TinyMCERails.setupTurbolinks();
51};
52window.tinymce = window.tinymce || {
53  base:   'https://static.shopmaker.com/assets/tinymce',
54  suffix: ''
55};
56/**
57 * TinyMCE version 6.4.2 (2023-04-26)
58 */
59
60(function () {
61    'use strict';
62
63    var typeOf$1 = function (x) {
64      if (x === null) {
65        return 'null';
66      }
67      if (x === undefined) {
68        return 'undefined';
69      }
70      var t = typeof x;
71      if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
72        return 'array';
73      }
74      if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
75        return 'string';
76      }
77      return t;
78    };
79    var isEquatableType = function (x) {
80      return [
81        'undefined',
82        'boolean',
83        'number',
84        'string',
85        'function',
86        'xml',
87        'null'
88      ].indexOf(x) !== -1;
89    };
90
91    var sort$1 = function (xs, compareFn) {
92      var clone = Array.prototype.slice.call(xs);
93      return clone.sort(compareFn);
94    };
95
96    var contramap = function (eqa, f) {
97      return eq$2(function (x, y) {
98        return eqa.eq(f(x), f(y));
99      });
100    };
101    var eq$2 = function (f) {
102      return { eq: f };
103    };
104    var tripleEq = eq$2(function (x, y) {
105      return x === y;
106    });
107    var eqString = tripleEq;
108    var eqArray = function (eqa) {
109      return eq$2(function (x, y) {
110        if (x.length !== y.length) {
111          return false;
112        }
113        var len = x.length;
114        for (var i = 0; i < len; i++) {
115          if (!eqa.eq(x[i], y[i])) {
116            return false;
117          }
118        }
119        return true;
120      });
121    };
122    var eqSortedArray = function (eqa, compareFn) {
123      return contramap(eqArray(eqa), function (xs) {
124        return sort$1(xs, compareFn);
125      });
126    };
127    var eqRecord = function (eqa) {
128      return eq$2(function (x, y) {
129        var kx = Object.keys(x);
130        var ky = Object.keys(y);
131        if (!eqSortedArray(eqString).eq(kx, ky)) {
132          return false;
133        }
134        var len = kx.length;
135        for (var i = 0; i < len; i++) {
136          var q = kx[i];
137          if (!eqa.eq(x[q], y[q])) {
138            return false;
139          }
140        }
141        return true;
142      });
143    };
144    var eqAny = eq$2(function (x, y) {
145      if (x === y) {
146        return true;
147      }
148      var tx = typeOf$1(x);
149      var ty = typeOf$1(y);
150      if (tx !== ty) {
151        return false;
152      }
153      if (isEquatableType(tx)) {
154        return x === y;
155      } else if (tx === 'array') {
156        return eqArray(eqAny).eq(x, y);
157      } else if (tx === 'object') {
158        return eqRecord(eqAny).eq(x, y);
159      }
160      return false;
161    });
162
163    const getPrototypeOf$2 = Object.getPrototypeOf;
164    const hasProto = (v, constructor, predicate) => {
165      var _a;
166      if (predicate(v, constructor.prototype)) {
167        return true;
168      } else {
169        return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
170      }
171    };
172    const typeOf = x => {
173      const t = typeof x;
174      if (x === null) {
175        return 'null';
vendor: 24,812 bytes, lines 176-1049
176      } else if (t === 'object' && Array.isArray(x)) {
177        return 'array';
178      } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
179        return 'string';
180      } else {
181        return t;
182      }
183    };
184    const isType$1 = type => value => typeOf(value) === type;
185    const isSimpleType = type => value => typeof value === type;
186    const eq$1 = t => a => t === a;
187    const is$4 = (value, constructor) => isObject(value) && hasProto(value, constructor, (o, proto) => getPrototypeOf$2(o) === proto);
188    const isString = isType$1('string');
189    const isObject = isType$1('object');
190    const isPlainObject = value => is$4(value, Object);
191    const isArray$1 = isType$1('array');
192    const isNull = eq$1(null);
193    const isBoolean = isSimpleType('boolean');
194    const isUndefined = eq$1(undefined);
195    const isNullable = a => a === null || a === undefined;
196    const isNonNullable = a => !isNullable(a);
197    const isFunction = isSimpleType('function');
198    const isNumber = isSimpleType('number');
199    const isArrayOf = (value, pred) => {
200      if (isArray$1(value)) {
201        for (let i = 0, len = value.length; i < len; ++i) {
202          if (!pred(value[i])) {
203            return false;
204          }
205        }
206        return true;
207      }
208      return false;
209    };
210
211    const noop = () => {
212    };
213    const compose = (fa, fb) => {
214      return (...args) => {
215        return fa(fb.apply(null, args));
216      };
217    };
218    const compose1 = (fbc, fab) => a => fbc(fab(a));
219    const constant = value => {
220      return () => {
221        return value;
222      };
223    };
224    const identity = x => {
225      return x;
226    };
227    const tripleEquals = (a, b) => {
228      return a === b;
229    };
230    function curry(fn, ...initialArgs) {
231      return (...restArgs) => {
232        const all = initialArgs.concat(restArgs);
233        return fn.apply(null, all);
234      };
235    }
236    const not = f => t => !f(t);
237    const die = msg => {
238      return () => {
239        throw new Error(msg);
240      };
241    };
242    const apply$1 = f => {
243      return f();
244    };
245    const call = f => {
246      f();
247    };
248    const never = constant(false);
249    const always = constant(true);
250
251    class Optional {
252      constructor(tag, value) {
253        this.tag = tag;
254        this.value = value;
255      }
256      static some(value) {
257        return new Optional(true, value);
258      }
259      static none() {
260        return Optional.singletonNone;
261      }
262      fold(onNone, onSome) {
263        if (this.tag) {
264          return onSome(this.value);
265        } else {
266          return onNone();
267        }
268      }
269      isSome() {
270        return this.tag;
271      }
272      isNone() {
273        return !this.tag;
274      }
275      map(mapper) {
276        if (this.tag) {
277          return Optional.some(mapper(this.value));
278        } else {
279          return Optional.none();
280        }
281      }
282      bind(binder) {
283        if (this.tag) {
284          return binder(this.value);
285        } else {
286          return Optional.none();
287        }
288      }
289      exists(predicate) {
290        return this.tag && predicate(this.value);
291      }
292      forall(predicate) {
293        return !this.tag || predicate(this.value);
294      }
295      filter(predicate) {
296        if (!this.tag || predicate(this.value)) {
297          return this;
298        } else {
299          return Optional.none();
300        }
301      }
302      getOr(replacement) {
303        return this.tag ? this.value : replacement;
304      }
305      or(replacement) {
306        return this.tag ? this : replacement;
307      }
308      getOrThunk(thunk) {
309        return this.tag ? this.value : thunk();
310      }
311      orThunk(thunk) {
312        return this.tag ? this : thunk();
313      }
314      getOrDie(message) {
315        if (!this.tag) {
316          throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
317        } else {
318          return this.value;
319        }
320      }
321      static from(value) {
322        return isNonNullable(value) ? Optional.some(value) : Optional.none();
323      }
324      getOrNull() {
325        return this.tag ? this.value : null;
326      }
327      getOrUndefined() {
328        return this.value;
329      }
330      each(worker) {
331        if (this.tag) {
332          worker(this.value);
333        }
334      }
335      toArray() {
336        return this.tag ? [this.value] : [];
337      }
338      toString() {
339        return this.tag ? `some(${ this.value })` : 'none()';
340      }
341    }
342    Optional.singletonNone = new Optional(false);
343
344    const nativeSlice = Array.prototype.slice;
345    const nativeIndexOf = Array.prototype.indexOf;
346    const nativePush = Array.prototype.push;
347    const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
348    const indexOf$1 = (xs, x) => {
349      const r = rawIndexOf(xs, x);
350      return r === -1 ? Optional.none() : Optional.some(r);
351    };
352    const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
353    const exists = (xs, pred) => {
354      for (let i = 0, len = xs.length; i < len; i++) {
355        const x = xs[i];
356        if (pred(x, i)) {
357          return true;
358        }
359      }
360      return false;
361    };
362    const map$3 = (xs, f) => {
363      const len = xs.length;
364      const r = new Array(len);
365      for (let i = 0; i < len; i++) {
366        const x = xs[i];
367        r[i] = f(x, i);
368      }
369      return r;
370    };
371    const each$e = (xs, f) => {
372      for (let i = 0, len = xs.length; i < len; i++) {
373        const x = xs[i];
374        f(x, i);
375      }
376    };
377    const eachr = (xs, f) => {
378      for (let i = xs.length - 1; i >= 0; i--) {
379        const x = xs[i];
380        f(x, i);
381      }
382    };
383    const partition$2 = (xs, pred) => {
384      const pass = [];
385      const fail = [];
386      for (let i = 0, len = xs.length; i < len; i++) {
387        const x = xs[i];
388        const arr = pred(x, i) ? pass : fail;
389        arr.push(x);
390      }
391      return {
392        pass,
393        fail
394      };
395    };
396    const filter$5 = (xs, pred) => {
397      const r = [];
398      for (let i = 0, len = xs.length; i < len; i++) {
399        const x = xs[i];
400        if (pred(x, i)) {
401          r.push(x);
402        }
403      }
404      return r;
405    };
406    const foldr = (xs, f, acc) => {
407      eachr(xs, (x, i) => {
408        acc = f(acc, x, i);
409      });
410      return acc;
411    };
412    const foldl = (xs, f, acc) => {
413      each$e(xs, (x, i) => {
414        acc = f(acc, x, i);
415      });
416      return acc;
417    };
418    const findUntil$1 = (xs, pred, until) => {
419      for (let i = 0, len = xs.length; i < len; i++) {
420        const x = xs[i];
421        if (pred(x, i)) {
422          return Optional.some(x);
423        } else if (until(x, i)) {
424          break;
425        }
426      }
427      return Optional.none();
428    };
429    const find$2 = (xs, pred) => {
430      return findUntil$1(xs, pred, never);
431    };
432    const findIndex$2 = (xs, pred) => {
433      for (let i = 0, len = xs.length; i < len; i++) {
434        const x = xs[i];
435        if (pred(x, i)) {
436          return Optional.some(i);
437        }
438      }
439      return Optional.none();
440    };
441    const flatten = xs => {
442      const r = [];
443      for (let i = 0, len = xs.length; i < len; ++i) {
444        if (!isArray$1(xs[i])) {
445          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
446        }
447        nativePush.apply(r, xs[i]);
448      }
449      return r;
450    };
451    const bind$3 = (xs, f) => flatten(map$3(xs, f));
452    const forall = (xs, pred) => {
453      for (let i = 0, len = xs.length; i < len; ++i) {
454        const x = xs[i];
455        if (pred(x, i) !== true) {
456          return false;
457        }
458      }
459      return true;
460    };
461    const reverse = xs => {
462      const r = nativeSlice.call(xs, 0);
463      r.reverse();
464      return r;
465    };
466    const difference = (a1, a2) => filter$5(a1, x => !contains$2(a2, x));
467    const mapToObject = (xs, f) => {
468      const r = {};
469      for (let i = 0, len = xs.length; i < len; i++) {
470        const x = xs[i];
471        r[String(x)] = f(x, i);
472      }
473      return r;
474    };
475    const sort = (xs, comparator) => {
476      const copy = nativeSlice.call(xs, 0);
477      copy.sort(comparator);
478      return copy;
479    };
480    const get$b = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
481    const head = xs => get$b(xs, 0);
482    const last$3 = xs => get$b(xs, xs.length - 1);
483    const from = isFunction(Array.from) ? Array.from : x => nativeSlice.call(x);
484    const findMap = (arr, f) => {
485      for (let i = 0; i < arr.length; i++) {
486        const r = f(arr[i], i);
487        if (r.isSome()) {
488          return r;
489        }
490      }
491      return Optional.none();
492    };
493    const unique$1 = (xs, comparator) => {
494      const r = [];
495      const isDuplicated = isFunction(comparator) ? x => exists(r, i => comparator(i, x)) : x => contains$2(r, x);
496      for (let i = 0, len = xs.length; i < len; i++) {
497        const x = xs[i];
498        if (!isDuplicated(x)) {
499          r.push(x);
500        }
501      }
502      return r;
503    };
504
505    const keys = Object.keys;
506    const hasOwnProperty$2 = Object.hasOwnProperty;
507    const each$d = (obj, f) => {
508      const props = keys(obj);
509      for (let k = 0, len = props.length; k < len; k++) {
510        const i = props[k];
511        const x = obj[i];
512        f(x, i);
513      }
514    };
515    const map$2 = (obj, f) => {
516      return tupleMap(obj, (x, i) => ({
517        k: i,
518        v: f(x, i)
519      }));
520    };
521    const tupleMap = (obj, f) => {
522      const r = {};
523      each$d(obj, (x, i) => {
524        const tuple = f(x, i);
525        r[tuple.k] = tuple.v;
526      });
527      return r;
528    };
529    const objAcc = r => (x, i) => {
530      r[i] = x;
531    };
532    const internalFilter = (obj, pred, onTrue, onFalse) => {
533      each$d(obj, (x, i) => {
534        (pred(x, i) ? onTrue : onFalse)(x, i);
535      });
536    };
537    const bifilter = (obj, pred) => {
538      const t = {};
539      const f = {};
540      internalFilter(obj, pred, objAcc(t), objAcc(f));
541      return {
542        t,
543        f
544      };
545    };
546    const filter$4 = (obj, pred) => {
547      const t = {};
548      internalFilter(obj, pred, objAcc(t), noop);
549      return t;
550    };
551    const mapToArray = (obj, f) => {
552      const r = [];
553      each$d(obj, (value, name) => {
554        r.push(f(value, name));
555      });
556      return r;
557    };
558    const values = obj => {
559      return mapToArray(obj, identity);
560    };
561    const get$a = (obj, key) => {
562      return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
563    };
564    const has$2 = (obj, key) => hasOwnProperty$2.call(obj, key);
565    const hasNonNullableKey = (obj, key) => has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
566    const equal$1 = (a1, a2, eq = eqAny) => eqRecord(eq).eq(a1, a2);
567
568    const stringArray = a => {
569      const all = {};
570      each$e(a, key => {
571        all[key] = {};
572      });
573      return keys(all);
574    };
575
576    const isArrayLike = o => o.length !== undefined;
577    const isArray = Array.isArray;
578    const toArray$1 = obj => {
579      if (!isArray(obj)) {
580        const array = [];
581        for (let i = 0, l = obj.length; i < l; i++) {
582          array[i] = obj[i];
583        }
584        return array;
585      } else {
586        return obj;
587      }
588    };
589    const each$c = (o, cb, s) => {
590      if (!o) {
591        return false;
592      }
593      s = s || o;
594      if (isArrayLike(o)) {
595        for (let n = 0, l = o.length; n < l; n++) {
596          if (cb.call(s, o[n], n, o) === false) {
597            return false;
598          }
599        }
600      } else {
601        for (const n in o) {
602          if (has$2(o, n)) {
603            if (cb.call(s, o[n], n, o) === false) {
604              return false;
605            }
606          }
607        }
608      }
609      return true;
610    };
611    const map$1 = (array, callback) => {
612      const out = [];
613      each$c(array, (item, index) => {
614        out.push(callback(item, index, array));
615      });
616      return out;
617    };
618    const filter$3 = (a, f) => {
619      const o = [];
620      each$c(a, (v, index) => {
621        if (!f || f(v, index, a)) {
622          o.push(v);
623        }
624      });
625      return o;
626    };
627    const indexOf = (a, v) => {
628      if (a) {
629        for (let i = 0, l = a.length; i < l; i++) {
630          if (a[i] === v) {
631            return i;
632          }
633        }
634      }
635      return -1;
636    };
637    const reduce = (collection, iteratee, accumulator, thisArg) => {
638      let acc = isUndefined(accumulator) ? collection[0] : accumulator;
639      for (let i = 0; i < collection.length; i++) {
640        acc = iteratee.call(thisArg, acc, collection[i], i);
641      }
642      return acc;
643    };
644    const findIndex$1 = (array, predicate, thisArg) => {
645      for (let i = 0, l = array.length; i < l; i++) {
646        if (predicate.call(thisArg, array[i], i, array)) {
647          return i;
648        }
649      }
650      return -1;
651    };
652    const last$2 = collection => collection[collection.length - 1];
653
654    const cached = f => {
655      let called = false;
656      let r;
657      return (...args) => {
658        if (!called) {
659          called = true;
660          r = f.apply(null, args);
661        }
662        return r;
663      };
664    };
665
666    const DeviceType = (os, browser, userAgent, mediaMatch) => {
667      const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
668      const isiPhone = os.isiOS() && !isiPad;
669      const isMobile = os.isiOS() || os.isAndroid();
670      const isTouch = isMobile || mediaMatch('(pointer:coarse)');
671      const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
672      const isPhone = isiPhone || isMobile && !isTablet;
673      const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
674      const isDesktop = !isPhone && !isTablet && !iOSwebview;
675      return {
676        isiPad: constant(isiPad),
677        isiPhone: constant(isiPhone),
678        isTablet: constant(isTablet),
679        isPhone: constant(isPhone),
680        isTouch: constant(isTouch),
681        isAndroid: os.isAndroid,
682        isiOS: os.isiOS,
683        isWebView: constant(iOSwebview),
684        isDesktop: constant(isDesktop)
685      };
686    };
687
688    const firstMatch = (regexes, s) => {
689      for (let i = 0; i < regexes.length; i++) {
690        const x = regexes[i];
691        if (x.test(s)) {
692          return x;
693        }
694      }
695      return undefined;
696    };
697    const find$1 = (regexes, agent) => {
698      const r = firstMatch(regexes, agent);
699      if (!r) {
700        return {
701          major: 0,
702          minor: 0
703        };
704      }
705      const group = i => {
706        return Number(agent.replace(r, '$' + i));
707      };
708      return nu$3(group(1), group(2));
709    };
710    const detect$5 = (versionRegexes, agent) => {
711      const cleanedAgent = String(agent).toLowerCase();
712      if (versionRegexes.length === 0) {
713        return unknown$2();
714      }
715      return find$1(versionRegexes, cleanedAgent);
716    };
717    const unknown$2 = () => {
718      return nu$3(0, 0);
719    };
720    const nu$3 = (major, minor) => {
721      return {
722        major,
723        minor
724      };
725    };
726    const Version = {
727      nu: nu$3,
728      detect: detect$5,
729      unknown: unknown$2
730    };
731
732    const detectBrowser$1 = (browsers, userAgentData) => {
733      return findMap(userAgentData.brands, uaBrand => {
734        const lcBrand = uaBrand.brand.toLowerCase();
735        return find$2(browsers, browser => {
736          var _a;
737          return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
738        }).map(info => ({
739          current: info.name,
740          version: Version.nu(parseInt(uaBrand.version, 10), 0)
741        }));
742      });
743    };
744
745    const detect$4 = (candidates, userAgent) => {
746      const agent = String(userAgent).toLowerCase();
747      return find$2(candidates, candidate => {
748        return candidate.search(agent);
749      });
750    };
751    const detectBrowser = (browsers, userAgent) => {
752      return detect$4(browsers, userAgent).map(browser => {
753        const version = Version.detect(browser.versionRegexes, userAgent);
754        return {
755          current: browser.name,
756          version
757        };
758      });
759    };
760    const detectOs = (oses, userAgent) => {
761      return detect$4(oses, userAgent).map(os => {
762        const version = Version.detect(os.versionRegexes, userAgent);
763        return {
764          current: os.name,
765          version
766        };
767      });
768    };
769
770    const removeFromStart = (str, numChars) => {
771      return str.substring(numChars);
772    };
773
774    const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
775    const removeLeading = (str, prefix) => {
776      return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str;
777    };
778    const contains$1 = (str, substr, start = 0, end) => {
779      const idx = str.indexOf(substr, start);
780      if (idx !== -1) {
781        return isUndefined(end) ? true : idx + substr.length <= end;
782      } else {
783        return false;
784      }
785    };
786    const startsWith = (str, prefix) => {
787      return checkRange(str, prefix, 0);
788    };
789    const endsWith = (str, suffix) => {
790      return checkRange(str, suffix, str.length - suffix.length);
791    };
792    const blank = r => s => s.replace(r, '');
793    const trim$3 = blank(/^\s+|\s+$/g);
794    const lTrim = blank(/^\s+/g);
795    const rTrim = blank(/\s+$/g);
796    const isNotEmpty = s => s.length > 0;
797    const isEmpty$3 = s => !isNotEmpty(s);
798    const repeat = (s, count) => count <= 0 ? '' : new Array(count + 1).join(s);
799    const toInt = (value, radix = 10) => {
800      const num = parseInt(value, radix);
801      return isNaN(num) ? Optional.none() : Optional.some(num);
802    };
803
804    const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
805    const checkContains = target => {
806      return uastring => {
807        return contains$1(uastring, target);
808      };
809    };
810    const browsers = [
811      {
812        name: 'Edge',
813        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
814        search: uastring => {
815          return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit');
816        }
817      },
818      {
819        name: 'Chromium',
820        brand: 'Chromium',
821        versionRegexes: [
822          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
823          normalVersionRegex
824        ],
825        search: uastring => {
826          return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe');
827        }
828      },
829      {
830        name: 'IE',
831        versionRegexes: [
832          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
833          /.*?rv:([0-9]+)\.([0-9]+).*/
834        ],
835        search: uastring => {
836          return contains$1(uastring, 'msie') || contains$1(uastring, 'trident');
837        }
838      },
839      {
840        name: 'Opera',
841        versionRegexes: [
842          normalVersionRegex,
843          /.*?opera\/([0-9]+)\.([0-9]+).*/
844        ],
845        search: checkContains('opera')
846      },
847      {
848        name: 'Firefox',
849        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
850        search: checkContains('firefox')
851      },
852      {
853        name: 'Safari',
854        versionRegexes: [
855          normalVersionRegex,
856          /.*?cpu os ([0-9]+)_([0-9]+).*/
857        ],
858        search: uastring => {
859          return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit');
860        }
861      }
862    ];
863    const oses = [
864      {
865        name: 'Windows',
866        search: checkContains('win'),
867        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
868      },
869      {
870        name: 'iOS',
871        search: uastring => {
872          return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad');
873        },
874        versionRegexes: [
875          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
876          /.*cpu os ([0-9]+)_([0-9]+).*/,
877          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
878        ]
879      },
880      {
881        name: 'Android',
882        search: checkContains('android'),
883        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
884      },
885      {
886        name: 'macOS',
887        search: checkContains('mac os x'),
888        versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
889      },
890      {
891        name: 'Linux',
892        search: checkContains('linux'),
893        versionRegexes: []
894      },
895      {
896        name: 'Solaris',
897        search: checkContains('sunos'),
898        versionRegexes: []
899      },
900      {
901        name: 'FreeBSD',
902        search: checkContains('freebsd'),
903        versionRegexes: []
904      },
905      {
906        name: 'ChromeOS',
907        search: checkContains('cros'),
908        versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
909      }
910    ];
911    const PlatformInfo = {
912      browsers: constant(browsers),
913      oses: constant(oses)
914    };
915
916    const edge = 'Edge';
917    const chromium = 'Chromium';
918    const ie = 'IE';
919    const opera = 'Opera';
920    const firefox = 'Firefox';
921    const safari = 'Safari';
922    const unknown$1 = () => {
923      return nu$2({
924        current: undefined,
925        version: Version.unknown()
926      });
927    };
928    const nu$2 = info => {
929      const current = info.current;
930      const version = info.version;
931      const isBrowser = name => () => current === name;
932      return {
933        current,
934        version,
935        isEdge: isBrowser(edge),
936        isChromium: isBrowser(chromium),
937        isIE: isBrowser(ie),
938        isOpera: isBrowser(opera),
939        isFirefox: isBrowser(firefox),
940        isSafari: isBrowser(safari)
941      };
942    };
943    const Browser = {
944      unknown: unknown$1,
945      nu: nu$2,
946      edge: constant(edge),
947      chromium: constant(chromium),
948      ie: constant(ie),
949      opera: constant(opera),
950      firefox: constant(firefox),
951      safari: constant(safari)
952    };
953
954    const windows = 'Windows';
955    const ios = 'iOS';
956    const android = 'Android';
957    const linux = 'Linux';
958    const macos = 'macOS';
959    const solaris = 'Solaris';
960    const freebsd = 'FreeBSD';
961    const chromeos = 'ChromeOS';
962    const unknown = () => {
963      return nu$1({
964        current: undefined,
965        version: Version.unknown()
966      });
967    };
968    const nu$1 = info => {
969      const current = info.current;
970      const version = info.version;
971      const isOS = name => () => current === name;
972      return {
973        current,
974        version,
975        isWindows: isOS(windows),
976        isiOS: isOS(ios),
977        isAndroid: isOS(android),
978        isMacOS: isOS(macos),
979        isLinux: isOS(linux),
980        isSolaris: isOS(solaris),
981        isFreeBSD: isOS(freebsd),
982        isChromeOS: isOS(chromeos)
983      };
984    };
985    const OperatingSystem = {
986      unknown,
987      nu: nu$1,
988      windows: constant(windows),
989      ios: constant(ios),
990      android: constant(android),
991      linux: constant(linux),
992      macos: constant(macos),
993      solaris: constant(solaris),
994      freebsd: constant(freebsd),
995      chromeos: constant(chromeos)
996    };
997
998    const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => {
999      const browsers = PlatformInfo.browsers();
1000      const oses = PlatformInfo.oses();
1001      const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
1002      const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
1003      const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
1004      return {
1005        browser,
1006        os,
1007        deviceType
1008      };
1009    };
1010    const PlatformDetection = { detect: detect$3 };
1011
1012    const mediaMatch = query => window.matchMedia(query).matches;
1013    let platform$2 = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
1014    const detect$2 = () => platform$2();
1015
1016    const userAgent = navigator.userAgent;
1017    const platform$1 = detect$2();
1018    const browser$1 = platform$1.browser;
1019    const os = platform$1.os;
1020    const deviceType = platform$1.deviceType;
1021    const windowsPhone = userAgent.indexOf('Windows Phone') !== -1;
1022    const Env = {
1023      transparentSrc: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
1024      documentMode: browser$1.isIE() ? document.documentMode || 7 : 10,
1025      cacheSuffix: null,
1026      container: null,
1027      canHaveCSP: !browser$1.isIE(),
1028      windowsPhone,
1029      browser: {
1030        current: browser$1.current,
1031        version: browser$1.version,
1032        isChromium: browser$1.isChromium,
1033        isEdge: browser$1.isEdge,
1034        isFirefox: browser$1.isFirefox,
1035        isIE: browser$1.isIE,
1036        isOpera: browser$1.isOpera,
1037        isSafari: browser$1.isSafari
1038      },
1039      os: {
1040        current: os.current,
1041        version: os.version,
1042        isAndroid: os.isAndroid,
1043        isChromeOS: os.isChromeOS,
1044        isFreeBSD: os.isFreeBSD,
1045        isiOS: os.isiOS,
1046        isLinux: os.isLinux,
1047        isMacOS: os.isMacOS,
1048        isSolaris: os.isSolaris,
1049        isWindows: os
vendor: 6,264 bytes, lines 1049-1253
1049.isWindows
1050      },
1051      deviceType: {
1052        isDesktop: deviceType.isDesktop,
1053        isiPad: deviceType.isiPad,
1054        isiPhone: deviceType.isiPhone,
1055        isPhone: deviceType.isPhone,
1056        isTablet: deviceType.isTablet,
1057        isTouch: deviceType.isTouch,
1058        isWebView: deviceType.isWebView
1059      }
1060    };
1061
1062    const whiteSpaceRegExp$1 = /^\s*|\s*$/g;
1063    const trim$2 = str => {
1064      return isNullable(str) ? '' : ('' + str).replace(whiteSpaceRegExp$1, '');
1065    };
1066    const is$3 = (obj, type) => {
1067      if (!type) {
1068        return obj !== undefined;
1069      }
1070      if (type === 'array' && isArray(obj)) {
1071        return true;
1072      }
1073      return typeof obj === type;
1074    };
1075    const makeMap$4 = (items, delim, map = {}) => {
1076      const resolvedItems = isString(items) ? items.split(delim || ',') : items || [];
1077      let i = resolvedItems.length;
1078      while (i--) {
1079        map[resolvedItems[i]] = {};
1080      }
1081      return map;
1082    };
1083    const hasOwnProperty$1 = has$2;
1084    const extend$3 = (obj, ...exts) => {
1085      for (let i = 0; i < exts.length; i++) {
1086        const ext = exts[i];
1087        for (const name in ext) {
1088          if (has$2(ext, name)) {
1089            const value = ext[name];
1090            if (value !== undefined) {
1091              obj[name] = value;
1092            }
1093          }
1094        }
1095      }
1096      return obj;
1097    };
1098    const walk$4 = function (o, f, n, s) {
1099      s = s || this;
1100      if (o) {
1101        if (n) {
1102          o = o[n];
1103        }
1104        each$c(o, (o, i) => {
1105          if (f.call(s, o, i, n) === false) {
1106            return false;
1107          } else {
1108            walk$4(o, f, n, s);
1109            return true;
1110          }
1111        });
1112      }
1113    };
1114    const resolve$3 = (n, o = window) => {
1115      const path = n.split('.');
1116      for (let i = 0, l = path.length; i < l; i++) {
1117        o = o[path[i]];
1118        if (!o) {
1119          break;
1120        }
1121      }
1122      return o;
1123    };
1124    const explode$3 = (s, d) => {
1125      if (isArray$1(s)) {
1126        return s;
1127      } else if (s === '') {
1128        return [];
1129      } else {
1130        return map$1(s.split(d || ','), trim$2);
1131      }
1132    };
1133    const _addCacheSuffix = url => {
1134      const cacheSuffix = Env.cacheSuffix;
1135      if (cacheSuffix) {
1136        url += (url.indexOf('?') === -1 ? '?' : '&') + cacheSuffix;
1137      }
1138      return url;
1139    };
1140    const Tools = {
1141      trim: trim$2,
1142      isArray: isArray,
1143      is: is$3,
1144      toArray: toArray$1,
1145      makeMap: makeMap$4,
1146      each: each$c,
1147      map: map$1,
1148      grep: filter$3,
1149      inArray: indexOf,
1150      hasOwn: hasOwnProperty$1,
1151      extend: extend$3,
1152      walk: walk$4,
1153      resolve: resolve$3,
1154      explode: explode$3,
1155      _addCacheSuffix
1156    };
1157
1158    const is$2 = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
1159    const cat = arr => {
1160      const r = [];
1161      const push = x => {
1162        r.push(x);
1163      };
1164      for (let i = 0; i < arr.length; i++) {
1165        arr[i].each(push);
1166      }
1167      return r;
1168    };
1169    const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
1170    const lift3 = (oa, ob, oc, f) => oa.isSome() && ob.isSome() && oc.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie())) : Optional.none();
1171    const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
1172
1173    const Global = typeof window !== 'undefined' ? window : Function('return this;')();
1174
1175    const path = (parts, scope) => {
1176      let o = scope !== undefined && scope !== null ? scope : Global;
1177      for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
1178        o = o[parts[i]];
1179      }
1180      return o;
1181    };
1182    const resolve$2 = (p, scope) => {
1183      const parts = p.split('.');
1184      return path(parts, scope);
1185    };
1186
1187    const unsafe = (name, scope) => {
1188      return resolve$2(name, scope);
1189    };
1190    const getOrDie = (name, scope) => {
1191      const actual = unsafe(name, scope);
1192      if (actual === undefined || actual === null) {
1193        throw new Error(name + ' not available on this browser');
1194      }
1195      return actual;
1196    };
1197
1198    const getPrototypeOf$1 = Object.getPrototypeOf;
1199    const sandHTMLElement = scope => {
1200      return getOrDie('HTMLElement', scope);
1201    };
1202    const isPrototypeOf = x => {
1203      const scope = resolve$2('ownerDocument.defaultView', x);
1204      return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf$1(x).constructor.name));
1205    };
1206
1207    const COMMENT = 8;
1208    const DOCUMENT = 9;
1209    const DOCUMENT_FRAGMENT = 11;
1210    const ELEMENT = 1;
1211    const TEXT = 3;
1212
1213    const name = element => {
1214      const r = element.dom.nodeName;
1215      return r.toLowerCase();
1216    };
1217    const type$1 = element => element.dom.nodeType;
1218    const isType = t => element => type$1(element) === t;
1219    const isComment$1 = element => type$1(element) === COMMENT || name(element) === '#comment';
1220    const isHTMLElement = element => isElement$7(element) && isPrototypeOf(element.dom);
1221    const isElement$7 = isType(ELEMENT);
1222    const isText$b = isType(TEXT);
1223    const isDocument$2 = isType(DOCUMENT);
1224    const isDocumentFragment$1 = isType(DOCUMENT_FRAGMENT);
1225    const isTag = tag => e => isElement$7(e) && name(e) === tag;
1226
1227    const rawSet = (dom, key, value) => {
1228      if (isString(value) || isBoolean(value) || isNumber(value)) {
1229        dom.setAttribute(key, value + '');
1230      } else {
1231        console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
1232        throw new Error('Attribute value was not simple');
1233      }
1234    };
1235    const set$3 = (element, key, value) => {
1236      rawSet(element.dom, key, value);
1237    };
1238    const setAll$1 = (element, attrs) => {
1239      const dom = element.dom;
1240      each$d(attrs, (v, k) => {
1241        rawSet(dom, k, v);
1242      });
1243    };
1244    const get$9 = (element, key) => {
1245      const v = element.dom.getAttribute(key);
1246      return v === null ? undefined : v;
1247    };
1248    const getOpt = (element, key) => Optional.from(get$9(element, key));
1249    const has$1 = (element, key) => {
1250      const dom = element.dom;
1251      return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
1252    };
1253    const remove$
vendor: 15,634 bytes, lines 1253-1688
1253b = (element, key) => {
1254      element.dom.removeAttribute(key);
1255    };
1256    const hasNone = element => {
1257      const attrs = element.dom.attributes;
1258      return attrs === undefined || attrs === null || attrs.length === 0;
1259    };
1260    const clone$4 = element => foldl(element.dom.attributes, (acc, attr) => {
1261      acc[attr.name] = attr.value;
1262      return acc;
1263    }, {});
1264
1265    const read$4 = (element, attr) => {
1266      const value = get$9(element, attr);
1267      return value === undefined || value === '' ? [] : value.split(' ');
1268    };
1269    const add$4 = (element, attr, id) => {
1270      const old = read$4(element, attr);
1271      const nu = old.concat([id]);
1272      set$3(element, attr, nu.join(' '));
1273      return true;
1274    };
1275    const remove$a = (element, attr, id) => {
1276      const nu = filter$5(read$4(element, attr), v => v !== id);
1277      if (nu.length > 0) {
1278        set$3(element, attr, nu.join(' '));
1279      } else {
1280        remove$b(element, attr);
1281      }
1282      return false;
1283    };
1284
1285    const supports = element => element.dom.classList !== undefined;
1286    const get$8 = element => read$4(element, 'class');
1287    const add$3 = (element, clazz) => add$4(element, 'class', clazz);
1288    const remove$9 = (element, clazz) => remove$a(element, 'class', clazz);
1289    const toggle$2 = (element, clazz) => {
1290      if (contains$2(get$8(element), clazz)) {
1291        return remove$9(element, clazz);
1292      } else {
1293        return add$3(element, clazz);
1294      }
1295    };
1296
1297    const add$2 = (element, clazz) => {
1298      if (supports(element)) {
1299        element.dom.classList.add(clazz);
1300      } else {
1301        add$3(element, clazz);
1302      }
1303    };
1304    const cleanClass = element => {
1305      const classList = supports(element) ? element.dom.classList : get$8(element);
1306      if (classList.length === 0) {
1307        remove$b(element, 'class');
1308      }
1309    };
1310    const remove$8 = (element, clazz) => {
1311      if (supports(element)) {
1312        const classList = element.dom.classList;
1313        classList.remove(clazz);
1314      } else {
1315        remove$9(element, clazz);
1316      }
1317      cleanClass(element);
1318    };
1319    const toggle$1 = (element, clazz) => {
1320      const result = supports(element) ? element.dom.classList.toggle(clazz) : toggle$2(element, clazz);
1321      cleanClass(element);
1322      return result;
1323    };
1324    const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
1325
1326    const fromHtml$1 = (html, scope) => {
1327      const doc = scope || document;
1328      const div = doc.createElement('div');
1329      div.innerHTML = html;
1330      if (!div.hasChildNodes() || div.childNodes.length > 1) {
1331        const message = 'HTML does not have a single root node';
1332        console.error(message, html);
1333        throw new Error(message);
1334      }
1335      return fromDom$2(div.childNodes[0]);
1336    };
1337    const fromTag = (tag, scope) => {
1338      const doc = scope || document;
1339      const node = doc.createElement(tag);
1340      return fromDom$2(node);
1341    };
1342    const fromText = (text, scope) => {
1343      const doc = scope || document;
1344      const node = doc.createTextNode(text);
1345      return fromDom$2(node);
1346    };
1347    const fromDom$2 = node => {
1348      if (node === null || node === undefined) {
1349        throw new Error('Node cannot be null or undefined');
1350      }
1351      return { dom: node };
1352    };
1353    const fromPoint$2 = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$2);
1354    const SugarElement = {
1355      fromHtml: fromHtml$1,
1356      fromTag,
1357      fromText,
1358      fromDom: fromDom$2,
1359      fromPoint: fromPoint$2
1360    };
1361
1362    const toArray = (target, f) => {
1363      const r = [];
1364      const recurse = e => {
1365        r.push(e);
1366        return f(e);
1367      };
1368      let cur = f(target);
1369      do {
1370        cur = cur.bind(recurse);
1371      } while (cur.isSome());
1372      return r;
1373    };
1374
1375    const is$1 = (element, selector) => {
1376      const dom = element.dom;
1377      if (dom.nodeType !== ELEMENT) {
1378        return false;
1379      } else {
1380        const elem = dom;
1381        if (elem.matches !== undefined) {
1382          return elem.matches(selector);
1383        } else if (elem.msMatchesSelector !== undefined) {
1384          return elem.msMatchesSelector(selector);
1385        } else if (elem.webkitMatchesSelector !== undefined) {
1386          return elem.webkitMatchesSelector(selector);
1387        } else if (elem.mozMatchesSelector !== undefined) {
1388          return elem.mozMatchesSelector(selector);
1389        } else {
1390          throw new Error('Browser lacks native selectors');
1391        }
1392      }
1393    };
1394    const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
1395    const all = (selector, scope) => {
1396      const base = scope === undefined ? document : scope.dom;
1397      return bypassSelector(base) ? [] : map$3(base.querySelectorAll(selector), SugarElement.fromDom);
1398    };
1399    const one = (selector, scope) => {
1400      const base = scope === undefined ? document : scope.dom;
1401      return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
1402    };
1403
1404    const eq = (e1, e2) => e1.dom === e2.dom;
1405    const contains = (e1, e2) => {
1406      const d1 = e1.dom;
1407      const d2 = e2.dom;
1408      return d1 === d2 ? false : d1.contains(d2);
1409    };
1410
1411    const owner$1 = element => SugarElement.fromDom(element.dom.ownerDocument);
1412    const documentOrOwner = dos => isDocument$2(dos) ? dos : owner$1(dos);
1413    const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
1414    const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
1415    const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
1416    const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
1417    const parents$1 = (element, isRoot) => {
1418      const stop = isFunction(isRoot) ? isRoot : never;
1419      let dom = element.dom;
1420      const ret = [];
1421      while (dom.parentNode !== null && dom.parentNode !== undefined) {
1422        const rawParent = dom.parentNode;
1423        const p = SugarElement.fromDom(rawParent);
1424        ret.push(p);
1425        if (stop(p) === true) {
1426          break;
1427        } else {
1428          dom = rawParent;
1429        }
1430      }
1431      return ret;
1432    };
1433    const siblings = element => {
1434      const filterSelf = elements => filter$5(elements, x => !eq(element, x));
1435      return parent(element).map(children$1).map(filterSelf).getOr([]);
1436    };
1437    const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
1438    const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
1439    const prevSiblings = element => reverse(toArray(element, prevSibling));
1440    const nextSiblings = element => toArray(element, nextSibling);
1441    const children$1 = element => map$3(element.dom.childNodes, SugarElement.fromDom);
1442    const child$1 = (element, index) => {
1443      const cs = element.dom.childNodes;
1444      return Optional.from(cs[index]).map(SugarElement.fromDom);
1445    };
1446    const firstChild = element => child$1(element, 0);
1447    const lastChild = element => child$1(element, element.dom.childNodes.length - 1);
1448    const childNodesCount = element => element.dom.childNodes.length;
1449
1450    const getHead = doc => {
1451      const b = doc.dom.head;
1452      if (b === null || b === undefined) {
1453        throw new Error('Head is not available yet');
1454      }
1455      return SugarElement.fromDom(b);
1456    };
1457
1458    const isShadowRoot = dos => isDocumentFragment$1(dos) && isNonNullable(dos.dom.host);
1459    const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
1460    const isSupported$1 = constant(supported);
1461    const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
1462    const getStyleContainer = dos => isShadowRoot(dos) ? dos : getHead(documentOrOwner(dos));
1463    const getContentContainer = dos => isShadowRoot(dos) ? dos : SugarElement.fromDom(documentOrOwner(dos).dom.body);
1464    const getShadowRoot = e => {
1465      const r = getRootNode(e);
1466      return isShadowRoot(r) ? Optional.some(r) : Optional.none();
1467    };
1468    const getShadowHost = e => SugarElement.fromDom(e.dom.host);
1469    const getOriginalEventTarget = event => {
1470      if (isSupported$1() && isNonNullable(event.target)) {
1471        const el = SugarElement.fromDom(event.target);
1472        if (isElement$7(el) && isOpenShadowHost(el)) {
1473          if (event.composed && event.composedPath) {
1474            const composedPath = event.composedPath();
1475            if (composedPath) {
1476              return head(composedPath);
1477            }
1478          }
1479        }
1480      }
1481      return Optional.from(event.target);
1482    };
1483    const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
1484
1485    const inBody = element => {
1486      const dom = isText$b(element) ? element.dom.parentNode : element.dom;
1487      if (dom === undefined || dom === null || dom.ownerDocument === null) {
1488        return false;
1489      }
1490      const doc = dom.ownerDocument;
1491      return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
1492    };
1493
1494    var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
1495      if (is(scope, a)) {
1496        return Optional.some(scope);
1497      } else if (isFunction(isRoot) && isRoot(scope)) {
1498        return Optional.none();
1499      } else {
1500        return ancestor(scope, a, isRoot);
1501      }
1502    };
1503
1504    const ancestor$4 = (scope, predicate, isRoot) => {
1505      let element = scope.dom;
1506      const stop = isFunction(isRoot) ? isRoot : never;
1507      while (element.parentNode) {
1508        element = element.parentNode;
1509        const el = SugarElement.fromDom(element);
1510        if (predicate(el)) {
1511          return Optional.some(el);
1512        } else if (stop(el)) {
1513          break;
1514        }
1515      }
1516      return Optional.none();
1517    };
1518    const closest$4 = (scope, predicate, isRoot) => {
1519      const is = (s, test) => test(s);
1520      return ClosestOrAncestor(is, ancestor$4, scope, predicate, isRoot);
1521    };
1522    const sibling$1 = (scope, predicate) => {
1523      const element = scope.dom;
1524      if (!element.parentNode) {
1525        return Optional.none();
1526      }
1527      return child(SugarElement.fromDom(element.parentNode), x => !eq(scope, x) && predicate(x));
1528    };
1529    const child = (scope, predicate) => {
1530      const pred = node => predicate(SugarElement.fromDom(node));
1531      const result = find$2(scope.dom.childNodes, pred);
1532      return result.map(SugarElement.fromDom);
1533    };
1534    const descendant$1 = (scope, predicate) => {
1535      const descend = node => {
1536        for (let i = 0; i < node.childNodes.length; i++) {
1537          const child = SugarElement.fromDom(node.childNodes[i]);
1538          if (predicate(child)) {
1539            return Optional.some(child);
1540          }
1541          const res = descend(node.childNodes[i]);
1542          if (res.isSome()) {
1543            return res;
1544          }
1545        }
1546        return Optional.none();
1547      };
1548      return descend(scope.dom);
1549    };
1550
1551    const ancestor$3 = (scope, selector, isRoot) => ancestor$4(scope, e => is$1(e, selector), isRoot);
1552    const descendant = (scope, selector) => one(selector, scope);
1553    const closest$3 = (scope, selector, isRoot) => {
1554      const is = (element, selector) => is$1(element, selector);
1555      return ClosestOrAncestor(is, ancestor$3, scope, selector, isRoot);
1556    };
1557
1558    const closest$2 = target => closest$3(target, '[contenteditable]');
1559    const isEditable$3 = (element, assumeEditable = false) => {
1560      if (inBody(element)) {
1561        return element.dom.isContentEditable;
1562      } else {
1563        return closest$2(element).fold(constant(assumeEditable), editable => getRaw$1(editable) === 'true');
1564      }
1565    };
1566    const getRaw$1 = element => element.dom.contentEditable;
1567
1568    const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
1569
1570    const internalSet = (dom, property, value) => {
1571      if (!isString(value)) {
1572        console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
1573        throw new Error('CSS value must be a string: ' + value);
1574      }
1575      if (isSupported(dom)) {
1576        dom.style.setProperty(property, value);
1577      }
1578    };
1579    const internalRemove = (dom, property) => {
1580      if (isSupported(dom)) {
1581        dom.style.removeProperty(property);
1582      }
1583    };
1584    const set$2 = (element, property, value) => {
1585      const dom = element.dom;
1586      internalSet(dom, property, value);
1587    };
1588    const setAll = (element, css) => {
1589      const dom = element.dom;
1590      each$d(css, (v, k) => {
1591        internalSet(dom, k, v);
1592      });
1593    };
1594    const get$7 = (element, property) => {
1595      const dom = element.dom;
1596      const styles = window.getComputedStyle(dom);
1597      const r = styles.getPropertyValue(property);
1598      return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
1599    };
1600    const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : '';
1601    const getRaw = (element, property) => {
1602      const dom = element.dom;
1603      const raw = getUnsafeProperty(dom, property);
1604      return Optional.from(raw).filter(r => r.length > 0);
1605    };
1606    const getAllRaw = element => {
1607      const css = {};
1608      const dom = element.dom;
1609      if (isSupported(dom)) {
1610        for (let i = 0; i < dom.style.length; i++) {
1611          const ruleName = dom.style.item(i);
1612          css[ruleName] = dom.style[ruleName];
1613        }
1614      }
1615      return css;
1616    };
1617    const remove$7 = (element, property) => {
1618      const dom = element.dom;
1619      internalRemove(dom, property);
1620      if (is$2(getOpt(element, 'style').map(trim$3), '')) {
1621        remove$b(element, 'style');
1622      }
1623    };
1624    const reflow = e => e.dom.offsetWidth;
1625
1626    const before$3 = (marker, element) => {
1627      const parent$1 = parent(marker);
1628      parent$1.each(v => {
1629        v.dom.insertBefore(element.dom, marker.dom);
1630      });
1631    };
1632    const after$4 = (marker, element) => {
1633      const sibling = nextSibling(marker);
1634      sibling.fold(() => {
1635        const parent$1 = parent(marker);
1636        parent$1.each(v => {
1637          append$1(v, element);
1638        });
1639      }, v => {
1640        before$3(v, element);
1641      });
1642    };
1643    const prepend = (parent, element) => {
1644      const firstChild$1 = firstChild(parent);
1645      firstChild$1.fold(() => {
1646        append$1(parent, element);
1647      }, v => {
1648        parent.dom.insertBefore(element.dom, v.dom);
1649      });
1650    };
1651    const append$1 = (parent, element) => {
1652      parent.dom.appendChild(element.dom);
1653    };
1654    const wrap$2 = (element, wrapper) => {
1655      before$3(element, wrapper);
1656      append$1(wrapper, element);
1657    };
1658
1659    const after$3 = (marker, elements) => {
1660      each$e(elements, (x, i) => {
1661        const e = i === 0 ? marker : elements[i - 1];
1662        after$4(e, x);
1663      });
1664    };
1665    const append = (parent, elements) => {
1666      each$e(elements, x => {
1667        append$1(parent, x);
1668      });
1669    };
1670
1671    const empty = element => {
1672      element.dom.textContent = '';
1673      each$e(children$1(element), rogue => {
1674        remove$6(rogue);
1675      });
1676    };
1677    const remove$6 = element => {
1678      const dom = element.dom;
1679      if (dom.parentNode !== null) {
1680        dom.parentNode.removeChild(dom);
1681      }
1682    };
1683    const unwrap = wrapper => {
1684      const children = children$1(wrapper);
1685      if (children.length > 0) {
1686        after$3(wrapper, children);
1687      }
1688      remove$6
vendor: 11,043 bytes, lines 1688-2017
1688(wrapper);
1689    };
1690
1691    const fromHtml = (html, scope) => {
1692      const doc = scope || document;
1693      const div = doc.createElement('div');
1694      div.innerHTML = html;
1695      return children$1(SugarElement.fromDom(div));
1696    };
1697    const fromDom$1 = nodes => map$3(nodes, SugarElement.fromDom);
1698
1699    const get$6 = element => element.dom.innerHTML;
1700    const set$1 = (element, content) => {
1701      const owner = owner$1(element);
1702      const docDom = owner.dom;
1703      const fragment = SugarElement.fromDom(docDom.createDocumentFragment());
1704      const contentElements = fromHtml(content, docDom);
1705      append(fragment, contentElements);
1706      empty(element);
1707      append$1(element, fragment);
1708    };
1709    const getOuter = element => {
1710      const container = SugarElement.fromTag('div');
1711      const clone = SugarElement.fromDom(element.dom.cloneNode(true));
1712      append$1(container, clone);
1713      return get$6(container);
1714    };
1715
1716    const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
1717      target,
1718      x,
1719      y,
1720      stop,
1721      prevent,
1722      kill,
1723      raw
1724    });
1725    const fromRawEvent = rawEvent => {
1726      const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
1727      const stop = () => rawEvent.stopPropagation();
1728      const prevent = () => rawEvent.preventDefault();
1729      const kill = compose(prevent, stop);
1730      return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
1731    };
1732    const handle$1 = (filter, handler) => rawEvent => {
1733      if (filter(rawEvent)) {
1734        handler(fromRawEvent(rawEvent));
1735      }
1736    };
1737    const binder = (element, event, filter, handler, useCapture) => {
1738      const wrapped = handle$1(filter, handler);
1739      element.dom.addEventListener(event, wrapped, useCapture);
1740      return { unbind: curry(unbind, element, event, wrapped, useCapture) };
1741    };
1742    const bind$2 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
1743    const unbind = (element, event, handler, useCapture) => {
1744      element.dom.removeEventListener(event, handler, useCapture);
1745    };
1746
1747    const r = (left, top) => {
1748      const translate = (x, y) => r(left + x, top + y);
1749      return {
1750        left,
1751        top,
1752        translate
1753      };
1754    };
1755    const SugarPosition = r;
1756
1757    const boxPosition = dom => {
1758      const box = dom.getBoundingClientRect();
1759      return SugarPosition(box.left, box.top);
1760    };
1761    const firstDefinedOrZero = (a, b) => {
1762      if (a !== undefined) {
1763        return a;
1764      } else {
1765        return b !== undefined ? b : 0;
1766      }
1767    };
1768    const absolute = element => {
1769      const doc = element.dom.ownerDocument;
1770      const body = doc.body;
1771      const win = doc.defaultView;
1772      const html = doc.documentElement;
1773      if (body === element.dom) {
1774        return SugarPosition(body.offsetLeft, body.offsetTop);
1775      }
1776      const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop);
1777      const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft);
1778      const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
1779      const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
1780      return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
1781    };
1782    const viewport = element => {
1783      const dom = element.dom;
1784      const doc = dom.ownerDocument;
1785      const body = doc.body;
1786      if (body === dom) {
1787        return SugarPosition(body.offsetLeft, body.offsetTop);
1788      }
1789      if (!inBody(element)) {
1790        return SugarPosition(0, 0);
1791      }
1792      return boxPosition(dom);
1793    };
1794
1795    const get$5 = _DOC => {
1796      const doc = _DOC !== undefined ? _DOC.dom : document;
1797      const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
1798      const y = doc.body.scrollTop || doc.documentElement.scrollTop;
1799      return SugarPosition(x, y);
1800    };
1801    const intoView = (element, alignToTop) => {
1802      const isSafari = detect$2().browser.isSafari();
1803      if (isSafari && isFunction(element.dom.scrollIntoViewIfNeeded)) {
1804        element.dom.scrollIntoViewIfNeeded(false);
1805      } else {
1806        element.dom.scrollIntoView(alignToTop);
1807      }
1808    };
1809
1810    const get$4 = _win => {
1811      const win = _win === undefined ? window : _win;
1812      if (detect$2().browser.isFirefox()) {
1813        return Optional.none();
1814      } else {
1815        return Optional.from(win.visualViewport);
1816      }
1817    };
1818    const bounds = (x, y, width, height) => ({
1819      x,
1820      y,
1821      width,
1822      height,
1823      right: x + width,
1824      bottom: y + height
1825    });
1826    const getBounds = _win => {
1827      const win = _win === undefined ? window : _win;
1828      const doc = win.document;
1829      const scroll = get$5(SugarElement.fromDom(doc));
1830      return get$4(win).fold(() => {
1831        const html = win.document.documentElement;
1832        const width = html.clientWidth;
1833        const height = html.clientHeight;
1834        return bounds(scroll.left, scroll.top, width, height);
1835      }, visualViewport => bounds(Math.max(visualViewport.pageLeft, scroll.left), Math.max(visualViewport.pageTop, scroll.top), visualViewport.width, visualViewport.height));
1836    };
1837
1838    const children = (scope, predicate) => filter$5(children$1(scope), predicate);
1839    const descendants$1 = (scope, predicate) => {
1840      let result = [];
1841      each$e(children$1(scope), x => {
1842        if (predicate(x)) {
1843          result = result.concat([x]);
1844        }
1845        result = result.concat(descendants$1(x, predicate));
1846      });
1847      return result;
1848    };
1849
1850    const descendants = (scope, selector) => all(selector, scope);
1851
1852    const ancestor$2 = (scope, selector, isRoot) => ancestor$3(scope, selector, isRoot).isSome();
1853
1854    class DomTreeWalker {
1855      constructor(startNode, rootNode) {
1856        this.node = startNode;
1857        this.rootNode = rootNode;
1858        this.current = this.current.bind(this);
1859        this.next = this.next.bind(this);
1860        this.prev = this.prev.bind(this);
1861        this.prev2 = this.prev2.bind(this);
1862      }
1863      current() {
1864        return this.node;
1865      }
1866      next(shallow) {
1867        this.node = this.findSibling(this.node, 'firstChild', 'nextSibling', shallow);
1868        return this.node;
1869      }
1870      prev(shallow) {
1871        this.node = this.findSibling(this.node, 'lastChild', 'previousSibling', shallow);
1872        return this.node;
1873      }
1874      prev2(shallow) {
1875        this.node = this.findPreviousNode(this.node, shallow);
1876        return this.node;
1877      }
1878      findSibling(node, startName, siblingName, shallow) {
1879        if (node) {
1880          if (!shallow && node[startName]) {
1881            return node[startName];
1882          }
1883          if (node !== this.rootNode) {
1884            let sibling = node[siblingName];
1885            if (sibling) {
1886              return sibling;
1887            }
1888            for (let parent = node.parentNode; parent && parent !== this.rootNode; parent = parent.parentNode) {
1889              sibling = parent[siblingName];
1890              if (sibling) {
1891                return sibling;
1892              }
1893            }
1894          }
1895        }
1896        return undefined;
1897      }
1898      findPreviousNode(node, shallow) {
1899        if (node) {
1900          const sibling = node.previousSibling;
1901          if (this.rootNode && sibling === this.rootNode) {
1902            return;
1903          }
1904          if (sibling) {
1905            if (!shallow) {
1906              for (let child = sibling.lastChild; child; child = child.lastChild) {
1907                if (!child.lastChild) {
1908                  return child;
1909                }
1910              }
1911            }
1912            return sibling;
1913          }
1914          const parent = node.parentNode;
1915          if (parent && parent !== this.rootNode) {
1916            return parent;
1917          }
1918        }
1919        return undefined;
1920      }
1921    }
1922
1923    const isNodeType = type => {
1924      return node => {
1925        return !!node && node.nodeType === type;
1926      };
1927    };
1928    const isRestrictedNode = node => !!node && !Object.getPrototypeOf(node);
1929    const isElement$6 = isNodeType(1);
1930    const matchNodeName = name => {
1931      const lowerCasedName = name.toLowerCase();
1932      return node => isNonNullable(node) && node.nodeName.toLowerCase() === lowerCasedName;
1933    };
1934    const matchNodeNames = names => {
1935      const lowerCasedNames = names.map(s => s.toLowerCase());
1936      return node => {
1937        if (node && node.nodeName) {
1938          const nodeName = node.nodeName.toLowerCase();
1939          return contains$2(lowerCasedNames, nodeName);
1940        }
1941        return false;
1942      };
1943    };
1944    const matchStyleValues = (name, values) => {
1945      const items = values.toLowerCase().split(' ');
1946      return node => {
1947        if (isElement$6(node)) {
1948          const win = node.ownerDocument.defaultView;
1949          if (win) {
1950            for (let i = 0; i < items.length; i++) {
1951              const computed = win.getComputedStyle(node, null);
1952              const cssValue = computed ? computed.getPropertyValue(name) : null;
1953              if (cssValue === items[i]) {
1954                return true;
1955              }
1956            }
1957          }
1958        }
1959        return false;
1960      };
1961    };
1962    const hasAttribute = attrName => {
1963      return node => {
1964        return isElement$6(node) && node.hasAttribute(attrName);
1965      };
1966    };
1967    const hasAttributeValue = (attrName, attrValue) => {
1968      return node => {
1969        return isElement$6(node) && node.getAttribute(attrName) === attrValue;
1970      };
1971    };
1972    const isBogus$2 = node => isElement$6(node) && node.hasAttribute('data-mce-bogus');
1973    const isBogusAll$1 = node => isElement$6(node) && node.getAttribute('data-mce-bogus') === 'all';
1974    const isTable$2 = node => isElement$6(node) && node.tagName === 'TABLE';
1975    const hasContentEditableState = value => {
1976      return node => {
1977        if (isElement$6(node)) {
1978          if (node.contentEditable === value) {
1979            return true;
1980          }
1981          if (node.getAttribute('data-mce-contenteditable') === value) {
1982            return true;
1983          }
1984        }
1985        return false;
1986      };
1987    };
1988    const isTextareaOrInput = matchNodeNames([
1989      'textarea',
1990      'input'
1991    ]);
1992    const isText$a = isNodeType(3);
1993    const isCData = isNodeType(4);
1994    const isPi = isNodeType(7);
1995    const isComment = isNodeType(8);
1996    const isDocument$1 = isNodeType(9);
1997    const isDocumentFragment = isNodeType(11);
1998    const isBr$6 = matchNodeName('br');
1999    const isImg = matchNodeName('img');
2000    const isContentEditableTrue$3 = hasContentEditableState('true');
2001    const isContentEditableFalse$b = hasContentEditableState('false');
2002    const isTableCell$3 = matchNodeNames([
2003      'td',
2004      'th'
2005    ]);
2006    const isTableCellOrCaption = matchNodeNames([
2007      'td',
2008      'th',
2009      'caption'
2010    ]);
2011    const isMedia$2 = matchNodeNames([
2012      'video',
2013      'audio',
2014      'object',
2015      'embed'
2016    ]);
2017    const isListItem$2 = matchNodeName('li');
vendor: 4,970 bytes, lines 2018-2227
2018
2019    const zeroWidth = '\uFEFF';
2020    const nbsp = '\xA0';
2021    const isZwsp$1 = char => char === zeroWidth;
2022    const removeZwsp = s => s.replace(/\uFEFF/g, '');
2023
2024    const NodeValue = (is, name) => {
2025      const get = element => {
2026        if (!is(element)) {
2027          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
2028        }
2029        return getOption(element).getOr('');
2030      };
2031      const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
2032      const set = (element, value) => {
2033        if (!is(element)) {
2034          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
2035        }
2036        element.dom.nodeValue = value;
2037      };
2038      return {
2039        get,
2040        getOption,
2041        set
2042      };
2043    };
2044
2045    const api$1 = NodeValue(isText$b, 'text');
2046    const get$3 = element => api$1.get(element);
2047    const getOption = element => api$1.getOption(element);
2048    const set = (element, value) => api$1.set(element, value);
2049
2050    const blocks = [
2051      'article',
2052      'aside',
2053      'details',
2054      'div',
2055      'dt',
2056      'figcaption',
2057      'footer',
2058      'form',
2059      'fieldset',
2060      'header',
2061      'hgroup',
2062      'html',
2063      'main',
2064      'nav',
2065      'section',
2066      'summary',
2067      'body',
2068      'p',
2069      'dl',
2070      'multicol',
2071      'dd',
2072      'figure',
2073      'address',
2074      'center',
2075      'blockquote',
2076      'h1',
2077      'h2',
2078      'h3',
2079      'h4',
2080      'h5',
2081      'h6',
2082      'listing',
2083      'xmp',
2084      'pre',
2085      'plaintext',
2086      'menu',
2087      'dir',
2088      'ul',
2089      'ol',
2090      'li',
2091      'hr',
2092      'table',
2093      'tbody',
2094      'thead',
2095      'tfoot',
2096      'th',
2097      'tr',
2098      'td',
2099      'caption'
2100    ];
2101    const tableCells = [
2102      'td',
2103      'th'
2104    ];
2105    const tableSections = [
2106      'thead',
2107      'tbody',
2108      'tfoot'
2109    ];
2110    const textBlocks = [
2111      'h1',
2112      'h2',
2113      'h3',
2114      'h4',
2115      'h5',
2116      'h6',
2117      'p',
2118      'div',
2119      'address',
2120      'pre',
2121      'form',
2122      'blockquote',
2123      'center',
2124      'dir',
2125      'fieldset',
2126      'header',
2127      'footer',
2128      'article',
2129      'section',
2130      'hgroup',
2131      'aside',
2132      'nav',
2133      'figure'
2134    ];
2135    const headings = [
2136      'h1',
2137      'h2',
2138      'h3',
2139      'h4',
2140      'h5',
2141      'h6'
2142    ];
2143    const listItems$1 = [
2144      'li',
2145      'dd',
2146      'dt'
2147    ];
2148    const lists = [
2149      'ul',
2150      'ol',
2151      'dl'
2152    ];
2153    const wsElements = [
2154      'pre',
2155      'script',
2156      'textarea',
2157      'style'
2158    ];
2159    const wrapBlockElements = ['pre'].concat(headings);
2160    const lazyLookup = items => {
2161      let lookup;
2162      return node => {
2163        lookup = lookup ? lookup : mapToObject(items, always);
2164        return has$2(lookup, name(node));
2165      };
2166    };
2167    const isBlock$2 = lazyLookup(blocks);
2168    const isTable$1 = node => name(node) === 'table';
2169    const isInline$1 = node => isElement$7(node) && !isBlock$2(node);
2170    const isBr$5 = node => isElement$7(node) && name(node) === 'br';
2171    const isTextBlock$2 = lazyLookup(textBlocks);
2172    const isList = lazyLookup(lists);
2173    const isListItem$1 = lazyLookup(listItems$1);
2174    const isTableSection = lazyLookup(tableSections);
2175    const isTableCell$2 = lazyLookup(tableCells);
2176    const isWsPreserveElement = lazyLookup(wsElements);
2177    const isWrapBlockElement = lazyLookup(wrapBlockElements);
2178    const isWrapElement = node => isWrapBlockElement(node) || isInline$1(node);
2179
2180    const getLastChildren$1 = elm => {
2181      const children = [];
2182      let rawNode = elm.dom;
2183      while (rawNode) {
2184        children.push(SugarElement.fromDom(rawNode));
2185        rawNode = rawNode.lastChild;
2186      }
2187      return children;
2188    };
2189    const removeTrailingBr = elm => {
2190      const allBrs = descendants(elm, 'br');
2191      const brs = filter$5(getLastChildren$1(elm).slice(-1), isBr$5);
2192      if (allBrs.length === brs.length) {
2193        each$e(brs, remove$6);
2194      }
2195    };
2196    const createPaddingBr = () => {
2197      const br = SugarElement.fromTag('br');
2198      set$3(br, 'data-mce-bogus', '1');
2199      return br;
2200    };
2201    const fillWithPaddingBr = elm => {
2202      empty(elm);
2203      append$1(elm, createPaddingBr());
2204    };
2205    const trimBlockTrailingBr = elm => {
2206      lastChild(elm).each(lastChild => {
2207        prevSibling(lastChild).each(lastChildPrevSibling => {
2208          if (isBlock$2(elm) && isBr$5(lastChild) && isBlock$2(lastChildPrevSibling)) {
2209            remove$6(lastChild);
2210          }
2211        });
2212      });
2213    };
2214
2215    const ZWSP$1 = zeroWidth;
2216    const isZwsp = isZwsp$1;
2217    const trim$1 = removeZwsp;
2218
2219    const isElement$5 = isElement$6;
2220    const isText$9 = isText$a;
2221    const isCaretContainerBlock$1 = node => {
2222      if (isText$9(node)) {
2223        node = node.parentNode;
2224      }
2225      return isElement$5(node) && node.hasAttribute('data-mce-caret');
2226    };
2227    const isCaretContainerInline = node => isText$9(node) && isZwsp
vendor: 14,737 bytes, lines 2227-2572
2227(node.data);
2228    const isCaretContainer$2 = node => isCaretContainerBlock$1(node) || isCaretContainerInline(node);
2229    const hasContent = node => node.firstChild !== node.lastChild || !isBr$6(node.firstChild);
2230    const insertInline$1 = (node, before) => {
2231      var _a;
2232      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
2233      const textNode = doc.createTextNode(ZWSP$1);
2234      const parentNode = node.parentNode;
2235      if (!before) {
2236        const sibling = node.nextSibling;
2237        if (isText$9(sibling)) {
2238          if (isCaretContainer$2(sibling)) {
2239            return sibling;
2240          }
2241          if (startsWithCaretContainer$1(sibling)) {
2242            sibling.splitText(1);
2243            return sibling;
2244          }
2245        }
2246        if (node.nextSibling) {
2247          parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(textNode, node.nextSibling);
2248        } else {
2249          parentNode === null || parentNode === void 0 ? void 0 : parentNode.appendChild(textNode);
2250        }
2251      } else {
2252        const sibling = node.previousSibling;
2253        if (isText$9(sibling)) {
2254          if (isCaretContainer$2(sibling)) {
2255            return sibling;
2256          }
2257          if (endsWithCaretContainer$1(sibling)) {
2258            return sibling.splitText(sibling.data.length - 1);
2259          }
2260        }
2261        parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(textNode, node);
2262      }
2263      return textNode;
2264    };
2265    const isBeforeInline = pos => {
2266      const container = pos.container();
2267      if (!isText$a(container)) {
2268        return false;
2269      }
2270      return container.data.charAt(pos.offset()) === ZWSP$1 || pos.isAtStart() && isCaretContainerInline(container.previousSibling);
2271    };
2272    const isAfterInline = pos => {
2273      const container = pos.container();
2274      if (!isText$a(container)) {
2275        return false;
2276      }
2277      return container.data.charAt(pos.offset() - 1) === ZWSP$1 || pos.isAtEnd() && isCaretContainerInline(container.nextSibling);
2278    };
2279    const insertBlock = (blockName, node, before) => {
2280      var _a;
2281      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
2282      const blockNode = doc.createElement(blockName);
2283      blockNode.setAttribute('data-mce-caret', before ? 'before' : 'after');
2284      blockNode.setAttribute('data-mce-bogus', 'all');
2285      blockNode.appendChild(createPaddingBr().dom);
2286      const parentNode = node.parentNode;
2287      if (!before) {
2288        if (node.nextSibling) {
2289          parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(blockNode, node.nextSibling);
2290        } else {
2291          parentNode === null || parentNode === void 0 ? void 0 : parentNode.appendChild(blockNode);
2292        }
2293      } else {
2294        parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(blockNode, node);
2295      }
2296      return blockNode;
2297    };
2298    const startsWithCaretContainer$1 = node => isText$9(node) && node.data[0] === ZWSP$1;
2299    const endsWithCaretContainer$1 = node => isText$9(node) && node.data[node.data.length - 1] === ZWSP$1;
2300    const trimBogusBr = elm => {
2301      var _a;
2302      const brs = elm.getElementsByTagName('br');
2303      const lastBr = brs[brs.length - 1];
2304      if (isBogus$2(lastBr)) {
2305        (_a = lastBr.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(lastBr);
2306      }
2307    };
2308    const showCaretContainerBlock = caretContainer => {
2309      if (caretContainer && caretContainer.hasAttribute('data-mce-caret')) {
2310        trimBogusBr(caretContainer);
2311        caretContainer.removeAttribute('data-mce-caret');
2312        caretContainer.removeAttribute('data-mce-bogus');
2313        caretContainer.removeAttribute('style');
2314        caretContainer.removeAttribute('data-mce-style');
2315        caretContainer.removeAttribute('_moz_abspos');
2316        return caretContainer;
2317      }
2318      return null;
2319    };
2320    const isRangeInCaretContainerBlock = range => isCaretContainerBlock$1(range.startContainer);
2321
2322    const isContentEditableTrue$2 = isContentEditableTrue$3;
2323    const isContentEditableFalse$a = isContentEditableFalse$b;
2324    const isBr$4 = isBr$6;
2325    const isText$8 = isText$a;
2326    const isInvalidTextElement = matchNodeNames([
2327      'script',
2328      'style',
2329      'textarea'
2330    ]);
2331    const isAtomicInline = matchNodeNames([
2332      'img',
2333      'input',
2334      'textarea',
2335      'hr',
2336      'iframe',
2337      'video',
2338      'audio',
2339      'object',
2340      'embed'
2341    ]);
2342    const isTable = matchNodeNames(['table']);
2343    const isCaretContainer$1 = isCaretContainer$2;
2344    const isCaretCandidate$3 = node => {
2345      if (isCaretContainer$1(node)) {
2346        return false;
2347      }
2348      if (isText$8(node)) {
2349        return !isInvalidTextElement(node.parentNode);
2350      }
2351      return isAtomicInline(node) || isBr$4(node) || isTable(node) || isNonUiContentEditableFalse(node);
2352    };
2353    const isUnselectable = node => isElement$6(node) && node.getAttribute('unselectable') === 'true';
2354    const isNonUiContentEditableFalse = node => !isUnselectable(node) && isContentEditableFalse$a(node);
2355    const isInEditable = (node, root) => {
2356      for (let tempNode = node.parentNode; tempNode && tempNode !== root; tempNode = tempNode.parentNode) {
2357        if (isNonUiContentEditableFalse(tempNode)) {
2358          return false;
2359        }
2360        if (isContentEditableTrue$2(tempNode)) {
2361          return true;
2362        }
2363      }
2364      return true;
2365    };
2366    const isAtomicContentEditableFalse = node => {
2367      if (!isNonUiContentEditableFalse(node)) {
2368        return false;
2369      }
2370      return !foldl(from(node.getElementsByTagName('*')), (result, elm) => {
2371        return result || isContentEditableTrue$2(elm);
2372      }, false);
2373    };
2374    const isAtomic$1 = node => isAtomicInline(node) || isAtomicContentEditableFalse(node);
2375    const isEditableCaretCandidate$1 = (node, root) => isCaretCandidate$3(node) && isInEditable(node, root);
2376
2377    const whiteSpaceRegExp = /^[ \t\r\n]*$/;
2378    const isWhitespaceText = text => whiteSpaceRegExp.test(text);
2379    const isCollapsibleWhitespace$1 = c => ' \f\t\x0B'.indexOf(c) !== -1;
2380    const isNewLineChar = c => c === '\n' || c === '\r';
2381    const isNewline = (text, idx) => idx < text.length && idx >= 0 ? isNewLineChar(text[idx]) : false;
2382    const normalize$4 = (text, tabSpaces = 4, isStartOfContent = true, isEndOfContent = true) => {
2383      const tabSpace = repeat(' ', tabSpaces);
2384      const normalizedText = text.replace(/\t/g, tabSpace);
2385      const result = foldl(normalizedText, (acc, c) => {
2386        if (isCollapsibleWhitespace$1(c) || c === nbsp) {
2387          if (acc.pcIsSpace || acc.str === '' && isStartOfContent || acc.str.length === normalizedText.length - 1 && isEndOfContent || isNewline(normalizedText, acc.str.length + 1)) {
2388            return {
2389              pcIsSpace: false,
2390              str: acc.str + nbsp
2391            };
2392          } else {
2393            return {
2394              pcIsSpace: true,
2395              str: acc.str + ' '
2396            };
2397          }
2398        } else {
2399          return {
2400            pcIsSpace: isNewLineChar(c),
2401            str: acc.str + c
2402          };
2403        }
2404      }, {
2405        pcIsSpace: false,
2406        str: ''
2407      });
2408      return result.str;
2409    };
2410
2411    const hasWhitespacePreserveParent = (node, rootNode) => {
2412      const rootElement = SugarElement.fromDom(rootNode);
2413      const startNode = SugarElement.fromDom(node);
2414      return ancestor$2(startNode, 'pre,code', curry(eq, rootElement));
2415    };
2416    const isWhitespace$1 = (node, rootNode) => {
2417      return isText$a(node) && isWhitespaceText(node.data) && !hasWhitespacePreserveParent(node, rootNode);
2418    };
2419    const isNamedAnchor = node => {
2420      return isElement$6(node) && node.nodeName === 'A' && !node.hasAttribute('href') && (node.hasAttribute('name') || node.hasAttribute('id'));
2421    };
2422    const isContent$1 = (node, rootNode) => {
2423      return isCaretCandidate$3(node) && !isWhitespace$1(node, rootNode) || isNamedAnchor(node) || isBookmark(node);
2424    };
2425    const isBookmark = hasAttribute('data-mce-bookmark');
2426    const isBogus$1 = hasAttribute('data-mce-bogus');
2427    const isBogusAll = hasAttributeValue('data-mce-bogus', 'all');
2428    const isEmptyNode = (targetNode, skipBogus) => {
2429      let brCount = 0;
2430      if (isContent$1(targetNode, targetNode)) {
2431        return false;
2432      } else {
2433        let node = targetNode.firstChild;
2434        if (!node) {
2435          return true;
2436        }
2437        const walker = new DomTreeWalker(node, targetNode);
2438        do {
2439          if (skipBogus) {
2440            if (isBogusAll(node)) {
2441              node = walker.next(true);
2442              continue;
2443            }
2444            if (isBogus$1(node)) {
2445              node = walker.next();
2446              continue;
2447            }
2448          }
2449          if (isBr$6(node)) {
2450            brCount++;
2451            node = walker.next();
2452            continue;
2453          }
2454          if (isContent$1(node, targetNode)) {
2455            return false;
2456          }
2457          node = walker.next();
2458        } while (node);
2459        return brCount <= 1;
2460      }
2461    };
2462    const isEmpty$2 = (elm, skipBogus = true) => isEmptyNode(elm.dom, skipBogus);
2463
2464    const transparentBlockAttr = 'data-mce-block';
2465    const elementNames = map => filter$5(keys(map), key => !/[A-Z]/.test(key));
2466    const makeSelectorFromSchemaMap = map => elementNames(map).join(',');
2467    const updateTransparent = (blocksSelector, transparent) => {
2468      if (isNonNullable(transparent.querySelector(blocksSelector))) {
2469        transparent.setAttribute(transparentBlockAttr, 'true');
2470        if (transparent.getAttribute('data-mce-selected') === 'inline-boundary') {
2471          transparent.removeAttribute('data-mce-selected');
2472        }
2473        return true;
2474      } else {
2475        transparent.removeAttribute(transparentBlockAttr);
2476        return false;
2477      }
2478    };
2479    const updateBlockStateOnChildren = (schema, scope) => {
2480      const transparentSelector = makeSelectorFromSchemaMap(schema.getTransparentElements());
2481      const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements());
2482      return filter$5(scope.querySelectorAll(transparentSelector), transparent => updateTransparent(blocksSelector, transparent));
2483    };
2484    const trimEdge = (el, leftSide) => {
2485      var _a;
2486      const childPropertyName = leftSide ? 'lastChild' : 'firstChild';
2487      for (let child = el[childPropertyName]; child; child = child[childPropertyName]) {
2488        if (isEmpty$2(SugarElement.fromDom(child))) {
2489          (_a = child.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(child);
2490          return;
2491        }
2492      }
2493    };
2494    const split$2 = (parentElm, splitElm) => {
2495      const range = document.createRange();
2496      const parentNode = parentElm.parentNode;
2497      if (parentNode) {
2498        range.setStartBefore(parentElm);
2499        range.setEndBefore(splitElm);
2500        const beforeFragment = range.extractContents();
2501        trimEdge(beforeFragment, true);
2502        range.setStartAfter(splitElm);
2503        range.setEndAfter(parentElm);
2504        const afterFragment = range.extractContents();
2505        trimEdge(afterFragment, false);
2506        if (!isEmpty$2(SugarElement.fromDom(beforeFragment))) {
2507          parentNode.insertBefore(beforeFragment, parentElm);
2508        }
2509        if (!isEmpty$2(SugarElement.fromDom(splitElm))) {
2510          parentNode.insertBefore(splitElm, parentElm);
2511        }
2512        if (!isEmpty$2(SugarElement.fromDom(afterFragment))) {
2513          parentNode.insertBefore(afterFragment, parentElm);
2514        }
2515        parentNode.removeChild(parentElm);
2516      }
2517    };
2518    const splitInvalidChildren = (schema, scope, transparentBlocks) => {
2519      const blocksElements = schema.getBlockElements();
2520      const rootNode = SugarElement.fromDom(scope);
2521      const isBlock = el => name(el) in blocksElements;
2522      const isRoot = el => eq(el, rootNode);
2523      each$e(fromDom$1(transparentBlocks), transparentBlock => {
2524        ancestor$4(transparentBlock, isBlock, isRoot).each(parentBlock => {
2525          const invalidChildren = children(transparentBlock, el => isBlock(el) && !schema.isValidChild(name(parentBlock), name(el)));
2526          if (invalidChildren.length > 0) {
2527            const stateScope = parentElement(parentBlock);
2528            each$e(invalidChildren, child => {
2529              ancestor$4(child, isBlock, isRoot).each(parentBlock => {
2530                split$2(parentBlock.dom, child.dom);
2531              });
2532            });
2533            stateScope.each(scope => updateBlockStateOnChildren(schema, scope.dom));
2534          }
2535        });
2536      });
2537    };
2538    const unwrapInvalidChildren = (schema, scope, transparentBlocks) => {
2539      each$e([
2540        ...transparentBlocks,
2541        ...isTransparentBlock(schema, scope) ? [scope] : []
2542      ], block => each$e(descendants(SugarElement.fromDom(block), block.nodeName.toLowerCase()), elm => {
2543        if (isTransparentInline(schema, elm.dom)) {
2544          unwrap(elm);
2545        }
2546      }));
2547    };
2548    const updateChildren = (schema, scope) => {
2549      const transparentBlocks = updateBlockStateOnChildren(schema, scope);
2550      splitInvalidChildren(schema, scope, transparentBlocks);
2551      unwrapInvalidChildren(schema, scope, transparentBlocks);
2552    };
2553    const updateElement = (schema, target) => {
2554      if (isTransparentElement(schema, target)) {
2555        const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements());
2556        updateTransparent(blocksSelector, target);
2557      }
2558    };
2559    const updateCaret = (schema, root, caretParent) => {
2560      const isRoot = el => eq(el, SugarElement.fromDom(root));
2561      const parents = parents$1(SugarElement.fromDom(caretParent), isRoot);
2562      get$b(parents, parents.length - 2).filter(isElement$7).fold(() => updateChildren(schema, root), scope => updateChildren(schema, scope.dom));
2563    };
2564    const hasBlockAttr = el => el.hasAttribute(transparentBlockAttr);
2565    const isTransparentElementName = (schema, name) => has$2(schema.getTransparentElements(), name);
2566    const isTransparentElement = (schema, node) => isElement$6(node) && isTransparentElementName(schema, node.nodeName);
2567    const isTransparentBlock = (schema, node) => isTransparentElement(schema, node) && hasBlockAttr(node);
2568    const isTransparentInline = (schema, node) => isTransparentElement(schema, node) && !hasBlockAttr(node);
2569    const isTransparentAstBlock = (schema, node) => node.type === 1 && isTransparentElementName(schema, node.name) && isString(node.attr(transparentBlockAttr));
2570    const isTransparentAstInline = (schema, node) => node.type === 1 && isTransparentElementName(schema, node.name) && isUndefined(node.attr(transparentBlockAttr));
2571
2572    const browser
vendor: 2,903 bytes, lines 2572-2642
2572 = detect$2().browser;
2573    const firstElement = nodes => find$2(nodes, isElement$7);
2574    const getTableCaptionDeltaY = elm => {
2575      if (browser.isFirefox() && name(elm) === 'table') {
2576        return firstElement(children$1(elm)).filter(elm => {
2577          return name(elm) === 'caption';
2578        }).bind(caption => {
2579          return firstElement(nextSiblings(caption)).map(body => {
2580            const bodyTop = body.dom.offsetTop;
2581            const captionTop = caption.dom.offsetTop;
2582            const captionHeight = caption.dom.offsetHeight;
2583            return bodyTop <= captionTop ? -captionHeight : 0;
2584          });
2585        }).getOr(0);
2586      } else {
2587        return 0;
2588      }
2589    };
2590    const hasChild = (elm, child) => elm.children && contains$2(elm.children, child);
2591    const getPos = (body, elm, rootElm) => {
2592      let x = 0, y = 0;
2593      const doc = body.ownerDocument;
2594      rootElm = rootElm ? rootElm : body;
2595      if (elm) {
2596        if (rootElm === body && elm.getBoundingClientRect && get$7(SugarElement.fromDom(body), 'position') === 'static') {
2597          const pos = elm.getBoundingClientRect();
2598          x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - doc.documentElement.clientLeft;
2599          y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - doc.documentElement.clientTop;
2600          return {
2601            x,
2602            y
2603          };
2604        }
2605        let offsetParent = elm;
2606        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType && !hasChild(offsetParent, rootElm)) {
2607          const castOffsetParent = offsetParent;
2608          x += castOffsetParent.offsetLeft || 0;
2609          y += castOffsetParent.offsetTop || 0;
2610          offsetParent = castOffsetParent.offsetParent;
2611        }
2612        offsetParent = elm.parentNode;
2613        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType && !hasChild(offsetParent, rootElm)) {
2614          x -= offsetParent.scrollLeft || 0;
2615          y -= offsetParent.scrollTop || 0;
2616          offsetParent = offsetParent.parentNode;
2617        }
2618        y += getTableCaptionDeltaY(SugarElement.fromDom(elm));
2619      }
2620      return {
2621        x,
2622        y
2623      };
2624    };
2625
2626    const StyleSheetLoader = (documentOrShadowRoot, settings = {}) => {
2627      let idCount = 0;
2628      const loadedStates = {};
2629      const edos = SugarElement.fromDom(documentOrShadowRoot);
2630      const doc = documentOrOwner(edos);
2631      const _setReferrerPolicy = referrerPolicy => {
2632        settings.referrerPolicy = referrerPolicy;
2633      };
2634      const _setContentCssCors = contentCssCors => {
2635        settings.contentCssCors = contentCssCors;
2636      };
2637      const addStyle = element => {
2638        append$1(getStyleContainer(edos), element);
2639      };
2640      const removeStyle = id => {
2641        const styleContainer = getStyleContainer(edos);
2642        descendant(styleContainer, '#' + id).each(remove$6
vendor: 16,522 bytes, lines 2642-3031
2642);
2643      };
2644      const getOrCreateState = url => get$a(loadedStates, url).getOrThunk(() => ({
2645        id: 'mce-u' + idCount++,
2646        passed: [],
2647        failed: [],
2648        count: 0
2649      }));
2650      const load = url => new Promise((success, failure) => {
2651        let link;
2652        const urlWithSuffix = Tools._addCacheSuffix(url);
2653        const state = getOrCreateState(urlWithSuffix);
2654        loadedStates[urlWithSuffix] = state;
2655        state.count++;
2656        const resolve = (callbacks, status) => {
2657          each$e(callbacks, call);
2658          state.status = status;
2659          state.passed = [];
2660          state.failed = [];
2661          if (link) {
2662            link.onload = null;
2663            link.onerror = null;
2664            link = null;
2665          }
2666        };
2667        const passed = () => resolve(state.passed, 2);
2668        const failed = () => resolve(state.failed, 3);
2669        if (success) {
2670          state.passed.push(success);
2671        }
2672        if (failure) {
2673          state.failed.push(failure);
2674        }
2675        if (state.status === 1) {
2676          return;
2677        }
2678        if (state.status === 2) {
2679          passed();
2680          return;
2681        }
2682        if (state.status === 3) {
2683          failed();
2684          return;
2685        }
2686        state.status = 1;
2687        const linkElem = SugarElement.fromTag('link', doc.dom);
2688        setAll$1(linkElem, {
2689          rel: 'stylesheet',
2690          type: 'text/css',
2691          id: state.id
2692        });
2693        if (settings.contentCssCors) {
2694          set$3(linkElem, 'crossOrigin', 'anonymous');
2695        }
2696        if (settings.referrerPolicy) {
2697          set$3(linkElem, 'referrerpolicy', settings.referrerPolicy);
2698        }
2699        link = linkElem.dom;
2700        link.onload = passed;
2701        link.onerror = failed;
2702        addStyle(linkElem);
2703        set$3(linkElem, 'href', urlWithSuffix);
2704      });
2705      const loadAll = urls => {
2706        const loadedUrls = Promise.allSettled(map$3(urls, url => load(url).then(constant(url))));
2707        return loadedUrls.then(results => {
2708          const parts = partition$2(results, r => r.status === 'fulfilled');
2709          if (parts.fail.length > 0) {
2710            return Promise.reject(map$3(parts.fail, result => result.reason));
2711          } else {
2712            return map$3(parts.pass, result => result.value);
2713          }
2714        });
2715      };
2716      const unload = url => {
2717        const urlWithSuffix = Tools._addCacheSuffix(url);
2718        get$a(loadedStates, urlWithSuffix).each(state => {
2719          const count = --state.count;
2720          if (count === 0) {
2721            delete loadedStates[urlWithSuffix];
2722            removeStyle(state.id);
2723          }
2724        });
2725      };
2726      const unloadAll = urls => {
2727        each$e(urls, url => {
2728          unload(url);
2729        });
2730      };
2731      return {
2732        load,
2733        loadAll,
2734        unload,
2735        unloadAll,
2736        _setReferrerPolicy,
2737        _setContentCssCors
2738      };
2739    };
2740
2741    const create$d = () => {
2742      const map = new WeakMap();
2743      const forElement = (referenceElement, settings) => {
2744        const root = getRootNode(referenceElement);
2745        const rootDom = root.dom;
2746        return Optional.from(map.get(rootDom)).getOrThunk(() => {
2747          const sl = StyleSheetLoader(rootDom, settings);
2748          map.set(rootDom, sl);
2749          return sl;
2750        });
2751      };
2752      return { forElement };
2753    };
2754    const instance = create$d();
2755
2756    const isSpan = node => node.nodeName.toLowerCase() === 'span';
2757    const isInlineContent = (node, root) => isNonNullable(node) && (isContent$1(node, root) || isInline$1(SugarElement.fromDom(node)));
2758    const surroundedByInlineContent = (node, root) => {
2759      const prev = new DomTreeWalker(node, root).prev(false);
2760      const next = new DomTreeWalker(node, root).next(false);
2761      const prevIsInline = isUndefined(prev) || isInlineContent(prev, root);
2762      const nextIsInline = isUndefined(next) || isInlineContent(next, root);
2763      return prevIsInline && nextIsInline;
2764    };
2765    const isBookmarkNode$2 = node => isSpan(node) && node.getAttribute('data-mce-type') === 'bookmark';
2766    const isKeepTextNode = (node, root) => isText$a(node) && node.data.length > 0 && surroundedByInlineContent(node, root);
2767    const isKeepElement = node => isElement$6(node) ? node.childNodes.length > 0 : false;
2768    const isDocument = node => isDocumentFragment(node) || isDocument$1(node);
2769    const trimNode = (dom, node, root) => {
2770      var _a;
2771      const rootNode = root || node;
2772      if (isElement$6(node) && isBookmarkNode$2(node)) {
2773        return node;
2774      }
2775      const children = node.childNodes;
2776      for (let i = children.length - 1; i >= 0; i--) {
2777        trimNode(dom, children[i], rootNode);
2778      }
2779      if (isElement$6(node)) {
2780        const currentChildren = node.childNodes;
2781        if (currentChildren.length === 1 && isBookmarkNode$2(currentChildren[0])) {
2782          (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(currentChildren[0], node);
2783        }
2784      }
2785      if (!isDocument(node) && !isContent$1(node, rootNode) && !isKeepElement(node) && !isKeepTextNode(node, rootNode)) {
2786        dom.remove(node);
2787      }
2788      return node;
2789    };
2790
2791    const makeMap$3 = Tools.makeMap;
2792    const attrsCharsRegExp = /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
2793    const textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
2794    const rawCharsRegExp = /[<>&\"\']/g;
2795    const entityRegExp = /&#([a-z0-9]+);?|&([a-z0-9]+);/gi;
2796    const asciiMap = {
2797      128: '\u20AC',
2798      130: '\u201A',
2799      131: '\u0192',
2800      132: '\u201E',
2801      133: '\u2026',
2802      134: '\u2020',
2803      135: '\u2021',
2804      136: '\u02c6',
2805      137: '\u2030',
2806      138: '\u0160',
2807      139: '\u2039',
2808      140: '\u0152',
2809      142: '\u017d',
2810      145: '\u2018',
2811      146: '\u2019',
2812      147: '\u201C',
2813      148: '\u201D',
2814      149: '\u2022',
2815      150: '\u2013',
2816      151: '\u2014',
2817      152: '\u02DC',
2818      153: '\u2122',
2819      154: '\u0161',
2820      155: '\u203A',
2821      156: '\u0153',
2822      158: '\u017e',
2823      159: '\u0178'
2824    };
2825    const baseEntities = {
2826      '"': '&quot;',
2827      '\'': '&#39;',
2828      '<': '&lt;',
2829      '>': '&gt;',
2830      '&': '&amp;',
2831      '`': '&#96;'
2832    };
2833    const reverseEntities = {
2834      '&lt;': '<',
2835      '&gt;': '>',
2836      '&amp;': '&',
2837      '&quot;': '"',
2838      '&apos;': `'`
2839    };
2840    const nativeDecode = text => {
2841      const elm = SugarElement.fromTag('div').dom;
2842      elm.innerHTML = text;
2843      return elm.textContent || elm.innerText || text;
2844    };
2845    const buildEntitiesLookup = (items, radix) => {
2846      const lookup = {};
2847      if (items) {
2848        const itemList = items.split(',');
2849        radix = radix || 10;
2850        for (let i = 0; i < itemList.length; i += 2) {
2851          const chr = String.fromCharCode(parseInt(itemList[i], radix));
2852          if (!baseEntities[chr]) {
2853            const entity = '&' + itemList[i + 1] + ';';
2854            lookup[chr] = entity;
2855            lookup[entity] = chr;
2856          }
2857        }
2858        return lookup;
2859      } else {
2860        return undefined;
2861      }
2862    };
2863    const namedEntities = buildEntitiesLookup('50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' + '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' + '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' + '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' + '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' + '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' + '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' + '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' + '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' + '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' + 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' + 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' + 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' + 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' + 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' + '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' + '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' + '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' + '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' + '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' + 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' + 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' + 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' + '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' + '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32);
2864    const encodeRaw = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2865      return baseEntities[chr] || chr;
2866    });
2867    const encodeAllRaw = text => ('' + text).replace(rawCharsRegExp, chr => {
2868      return baseEntities[chr] || chr;
2869    });
2870    const encodeNumeric = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2871      if (chr.length > 1) {
2872        return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
2873      }
2874      return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
2875    });
2876    const encodeNamed = (text, attr, entities) => {
2877      const resolveEntities = entities || namedEntities;
2878      return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2879        return baseEntities[chr] || resolveEntities[chr] || chr;
2880      });
2881    };
2882    const getEncodeFunc = (name, entities) => {
2883      const entitiesMap = buildEntitiesLookup(entities) || namedEntities;
2884      const encodeNamedAndNumeric = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2885        if (baseEntities[chr] !== undefined) {
2886          return baseEntities[chr];
2887        }
2888        if (entitiesMap[chr] !== undefined) {
2889          return entitiesMap[chr];
2890        }
2891        if (chr.length > 1) {
2892          return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
2893        }
2894        return '&#' + chr.charCodeAt(0) + ';';
2895      });
2896      const encodeCustomNamed = (text, attr) => {
2897        return encodeNamed(text, attr, entitiesMap);
2898      };
2899      const nameMap = makeMap$3(name.replace(/\+/g, ','));
2900      if (nameMap.named && nameMap.numeric) {
2901        return encodeNamedAndNumeric;
2902      }
2903      if (nameMap.named) {
2904        if (entities) {
2905          return encodeCustomNamed;
2906        }
2907        return encodeNamed;
2908      }
2909      if (nameMap.numeric) {
2910        return encodeNumeric;
2911      }
2912      return encodeRaw;
2913    };
2914    const decode = text => text.replace(entityRegExp, (all, numeric) => {
2915      if (numeric) {
2916        if (numeric.charAt(0).toLowerCase() === 'x') {
2917          numeric = parseInt(numeric.substr(1), 16);
2918        } else {
2919          numeric = parseInt(numeric, 10);
2920        }
2921        if (numeric > 65535) {
2922          numeric -= 65536;
2923          return String.fromCharCode(55296 + (numeric >> 10), 56320 + (numeric & 1023));
2924        }
2925        return asciiMap[numeric] || String.fromCharCode(numeric);
2926      }
2927      return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
2928    });
2929    const Entities = {
2930      encodeRaw,
2931      encodeAllRaw,
2932      encodeNumeric,
2933      encodeNamed,
2934      getEncodeFunc,
2935      decode
2936    };
2937
2938    const lookupCache = {};
2939    const mapCache = {};
2940    const dummyObj = {};
2941    const makeMap$2 = Tools.makeMap, each$b = Tools.each, extend$2 = Tools.extend, explode$2 = Tools.explode, inArray = Tools.inArray;
2942    const split$1 = (items, delim) => {
2943      items = Tools.trim(items);
2944      return items ? items.split(delim || ' ') : [];
2945    };
2946    const createMap = (defaultValue, extendWith = {}) => {
2947      const value = makeMap$2(defaultValue, ' ', makeMap$2(defaultValue.toUpperCase(), ' '));
2948      return extend$2(value, extendWith);
2949    };
2950    const getTextRootBlockElements = schema => createMap('td th li dt dd figcaption caption details summary', schema.getTextBlockElements());
2951    const compileSchema = type => {
2952      const schema = {};
2953      let globalAttributes, blockContent;
2954      let phrasingContent, flowContent;
2955      const add = (name, attributes = '', children = '') => {
2956        const childNames = split$1(children);
2957        const names = split$1(name);
2958        let ni = names.length;
2959        while (ni--) {
2960          const attributesOrder = split$1([
2961            globalAttributes,
2962            attributes
2963          ].join(' '));
2964          schema[names[ni]] = {
2965            attributes: mapToObject(attributesOrder, () => ({})),
2966            attributesOrder,
2967            children: mapToObject(childNames, constant(dummyObj))
2968          };
2969        }
2970      };
2971      const addAttrs = (name, attributes) => {
2972        const names = split$1(name);
2973        const attrs = split$1(attributes);
2974        let ni = names.length;
2975        while (ni--) {
2976          const schemaItem = schema[names[ni]];
2977          for (let i = 0, l = attrs.length; i < l; i++) {
2978            schemaItem.attributes[attrs[i]] = {};
2979            schemaItem.attributesOrder.push(attrs[i]);
2980          }
2981        }
2982      };
2983      if (lookupCache[type]) {
2984        return lookupCache[type];
2985      }
2986      globalAttributes = 'id accesskey class dir lang style tabindex title role';
2987      blockContent = 'address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul';
2988      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';
2989      if (type !== 'html4') {
2990        const transparentContent = 'a ins del canvas map';
2991        globalAttributes += ' contenteditable contextmenu draggable dropzone ' + 'hidden spellcheck translate';
2992        blockContent += ' article aside details dialog figure main header footer hgroup section nav ' + transparentContent;
2993        phrasingContent += ' audio canvas command datalist mark meter output picture ' + 'progress time wbr video ruby bdi keygen';
2994      }
2995      if (type !== 'html5-strict') {
2996        globalAttributes += ' xml:lang';
2997        const html4PhrasingContent = 'acronym applet basefont big font strike tt';
2998        phrasingContent = [
2999          phrasingContent,
3000          html4PhrasingContent
3001        ].join(' ');
3002        each$b(split$1(html4PhrasingContent), name => {
3003          add(name, '', phrasingContent);
3004        });
3005        const html4BlockContent = 'center dir isindex noframes';
3006        blockContent = [
3007          blockContent,
3008          html4BlockContent
3009        ].join(' ');
3010        flowContent = [
3011          blockContent,
3012          phrasingContent
3013        ].join(' ');
3014        each$b(split$1(html4BlockContent), name => {
3015          add(name, '', flowContent);
3016        });
3017      }
3018      flowContent = flowContent || [
3019        blockContent,
3020        phrasingContent
3021      ].join(' ');
3022      add('html', 'manifest', 'head body');
3023      add('head', '', 'base command link meta noscript script style title');
3024      add('title hr noscript br');
3025      add('base', 'href target');
3026      add('link', 'href rel media hreflang type sizes hreflang');
3027      add('meta', 'name http-equiv content charset');
3028      add('style', 'media type scoped');
3029      add('script', 'src async defer type charset');
3030      add('body', 'onafterprint onbeforeprint onbeforeunload onblur onerror onfocus ' + 'onhashchange onload onmessage onoffline ononline onpagehide onpageshow ' + 'onpopstate onresize onscroll onstorage onunload', flowContent);
3031      add('
3031address dt dd div caption', '', flowContent);
3032      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);
3033      add('blockquote', 'cite', flowContent);
3034      add('ol', 'reversed start type', 'li');
3035      add('ul', '', 'li');
3036      add('li', 'value', flowContent);
3037      add('dl', '', 'dt dd');
3038      add('a', 'href target rel media hreflang type',
vendor: 19,399 bytes, lines 3038-3466
3038 flowContent);
3039      add('q', 'cite', phrasingContent);
3040      add('ins del', 'cite datetime', flowContent);
3041      add('img', 'src sizes srcset alt usemap ismap width height');
3042      add('iframe', 'src name width height', flowContent);
3043      add('embed', 'src type width height');
3044      add('object', 'data type typemustmatch name usemap form width height', [
3045        flowContent,
3046        'param'
3047      ].join(' '));
3048      add('param', 'name value');
3049      add('map', 'name', [
3050        flowContent,
3051        'area'
3052      ].join(' '));
3053      add('area', 'alt coords shape href target rel media hreflang type');
3054      add('table', 'border', 'caption colgroup thead tfoot tbody tr' + (type === 'html4' ? ' col' : ''));
3055      add('colgroup', 'span', 'col');
3056      add('col', 'span');
3057      add('tbody thead tfoot', '', 'tr');
3058      add('tr', '', 'td th');
3059      add('td', 'colspan rowspan headers', flowContent);
3060      add('th', 'colspan rowspan headers scope abbr', flowContent);
3061      add('form', 'accept-charset action autocomplete enctype method name novalidate target', flowContent);
3062      add('fieldset', 'disabled form name', [
3063        flowContent,
3064        'legend'
3065      ].join(' '));
3066      add('label', 'form for', phrasingContent);
3067      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');
3068      add('button', 'disabled form formaction formenctype formmethod formnovalidate formtarget name type value', type === 'html4' ? flowContent : phrasingContent);
3069      add('select', 'disabled form multiple name required size', 'option optgroup');
3070      add('optgroup', 'disabled label', 'option');
3071      add('option', 'disabled label selected value');
3072      add('textarea', 'cols dirname disabled form maxlength name readonly required rows wrap');
3073      add('menu', 'type label', [
3074        flowContent,
3075        'li'
3076      ].join(' '));
3077      add('noscript', '', flowContent);
3078      if (type !== 'html4') {
3079        add('wbr');
3080        add('ruby', '', [
3081          phrasingContent,
3082          'rt rp'
3083        ].join(' '));
3084        add('figcaption', '', flowContent);
3085        add('mark rt rp summary bdi', '', phrasingContent);
3086        add('canvas', 'width height', flowContent);
3087        add('video', 'src crossorigin poster preload autoplay mediagroup loop ' + 'muted controls width height buffered', [
3088          flowContent,
3089          'track source'
3090        ].join(' '));
3091        add('audio', 'src crossorigin preload autoplay mediagroup loop muted controls ' + 'buffered volume', [
3092          flowContent,
3093          'track source'
3094        ].join(' '));
3095        add('picture', '', 'img source');
3096        add('source', 'src srcset type media sizes');
3097        add('track', 'kind src srclang label default');
3098        add('datalist', '', [
3099          phrasingContent,
3100          'option'
3101        ].join(' '));
3102        add('article section nav aside main header footer', '', flowContent);
3103        add('hgroup', '', 'h1 h2 h3 h4 h5 h6');
3104        add('figure', '', [
3105          flowContent,
3106          'figcaption'
3107        ].join(' '));
3108        add('time', 'datetime', phrasingContent);
3109        add('dialog', 'open', flowContent);
3110        add('command', 'type label icon disabled checked radiogroup command');
3111        add('output', 'for form name', phrasingContent);
3112        add('progress', 'value max', phrasingContent);
3113        add('meter', 'value min max low high optimum', phrasingContent);
3114        add('details', 'open', [
3115          flowContent,
3116          'summary'
3117        ].join(' '));
3118        add('keygen', 'autofocus challenge disabled form keytype name');
3119      }
3120      if (type !== 'html5-strict') {
3121        addAttrs('script', 'language xml:space');
3122        addAttrs('style', 'xml:space');
3123        addAttrs('object', 'declare classid code codebase codetype archive standby align border hspace vspace');
3124        addAttrs('embed', 'align name hspace vspace');
3125        addAttrs('param', 'valuetype type');
3126        addAttrs('a', 'charset name rev shape coords');
3127        addAttrs('br', 'clear');
3128        addAttrs('applet', 'codebase archive code object alt name width height align hspace vspace');
3129        addAttrs('img', 'name longdesc align border hspace vspace');
3130        addAttrs('iframe', 'longdesc frameborder marginwidth marginheight scrolling align');
3131        addAttrs('font basefont', 'size color face');
3132        addAttrs('input', 'usemap align');
3133        addAttrs('select');
3134        addAttrs('textarea');
3135        addAttrs('h1 h2 h3 h4 h5 h6 div p legend caption', 'align');
3136        addAttrs('ul', 'type compact');
3137        addAttrs('li', 'type');
3138        addAttrs('ol dl menu dir', 'compact');
3139        addAttrs('pre', 'width xml:space');
3140        addAttrs('hr', 'align noshade size width');
3141        addAttrs('isindex', 'prompt');
3142        addAttrs('table', 'summary width frame rules cellspacing cellpadding align bgcolor');
3143        addAttrs('col', 'width align char charoff valign');
3144        addAttrs('colgroup', 'width align char charoff valign');
3145        addAttrs('thead', 'align char charoff valign');
3146        addAttrs('tr', 'align char charoff valign bgcolor');
3147        addAttrs('th', 'axis align char charoff valign nowrap bgcolor width height');
3148        addAttrs('form', 'accept');
3149        addAttrs('td', 'abbr axis scope align char charoff valign nowrap bgcolor width height');
3150        addAttrs('tfoot', 'align char charoff valign');
3151        addAttrs('tbody', 'align char charoff valign');
3152        addAttrs('area', 'nohref');
3153        addAttrs('body', 'background bgcolor text link vlink alink');
3154      }
3155      if (type !== 'html4') {
3156        addAttrs('input button select textarea', 'autofocus');
3157        addAttrs('input textarea', 'placeholder');
3158        addAttrs('a', 'download');
3159        addAttrs('link script img', 'crossorigin');
3160        addAttrs('img', 'loading');
3161        addAttrs('iframe', 'sandbox seamless allow allowfullscreen loading');
3162      }
3163      if (type !== 'html4') {
3164        each$e([
3165          schema.video,
3166          schema.audio
3167        ], item => {
3168          delete item.children.audio;
3169          delete item.children.video;
3170        });
3171      }
3172      each$b(split$1('a form meter progress dfn'), name => {
3173        if (schema[name]) {
3174          delete schema[name].children[name];
3175        }
3176      });
3177      delete schema.caption.children.table;
3178      delete schema.script;
3179      lookupCache[type] = schema;
3180      return schema;
3181    };
3182    const compileElementMap = (value, mode) => {
3183      if (value) {
3184        const styles = {};
3185        if (isString(value)) {
3186          value = { '*': value };
3187        }
3188        each$b(value, (value, key) => {
3189          styles[key] = styles[key.toUpperCase()] = mode === 'map' ? makeMap$2(value, /[, ]/) : explode$2(value, /[, ]/);
3190        });
3191        return styles;
3192      } else {
3193        return undefined;
3194      }
3195    };
3196    const Schema = (settings = {}) => {
3197      var _a;
3198      const elements = {};
3199      const children = {};
3200      let patternElements = [];
3201      const customElementsMap = {};
3202      const specialElements = {};
3203      const createLookupTable = (option, defaultValue, extendWith) => {
3204        const value = settings[option];
3205        if (!value) {
3206          let newValue = mapCache[option];
3207          if (!newValue) {
3208            newValue = createMap(defaultValue, extendWith);
3209            mapCache[option] = newValue;
3210          }
3211          return newValue;
3212        } else {
3213          return makeMap$2(value, /[, ]/, makeMap$2(value.toUpperCase(), /[, ]/));
3214        }
3215      };
3216      const schemaType = (_a = settings.schema) !== null && _a !== void 0 ? _a : 'html5';
3217      const schemaItems = compileSchema(schemaType);
3218      if (settings.verify_html === false) {
3219        settings.valid_elements = '*[*]';
3220      }
3221      const validStyles = compileElementMap(settings.valid_styles);
3222      const invalidStyles = compileElementMap(settings.invalid_styles, 'map');
3223      const validClasses = compileElementMap(settings.valid_classes, 'map');
3224      const whitespaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea video audio iframe object code');
3225      const selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
3226      const voidElementsMap = createLookupTable('void_elements', 'area base basefont br col frame hr img input isindex link ' + 'meta param embed source wbr track');
3227      const boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' + 'noshade nowrap readonly selected autoplay loop controls allowfullscreen');
3228      const nonEmptyOrMoveCaretBeforeOnEnter = 'td th iframe video audio object script code';
3229      const nonEmptyElementsMap = createLookupTable('non_empty_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' pre', voidElementsMap);
3230      const moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' table', voidElementsMap);
3231      const 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');
3232      const 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);
3233      const textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font s strike u var cite ' + 'dfn code mark q sup sub samp');
3234      const transparentElementsMap = createLookupTable('transparent_elements', 'a ins del canvas map');
3235      each$b('script noscript iframe noframes noembed title style textarea xmp plaintext'.split(' '), name => {
3236        specialElements[name] = new RegExp('</' + name + '[^>]*>', 'gi');
3237      });
3238      const patternToRegExp = str => new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$');
3239      const addValidElements = validElements => {
3240        const elementRuleRegExp = /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)])?$/;
3241        const attrRuleRegExp = /^([!\-])?(\w+[\\:]:\w+|[^=~<]+)?(?:([=~<])(.*))?$/;
3242        const hasPatternsRegExp = /[*?+]/;
3243        if (validElements) {
3244          const validElementsArr = split$1(validElements, ',');
3245          let globalAttributes;
3246          let globalAttributesOrder;
3247          if (elements['@']) {
3248            globalAttributes = elements['@'].attributes;
3249            globalAttributesOrder = elements['@'].attributesOrder;
3250          }
3251          for (let ei = 0, el = validElementsArr.length; ei < el; ei++) {
3252            let matches = elementRuleRegExp.exec(validElementsArr[ei]);
3253            if (matches) {
3254              const prefix = matches[1];
3255              const elementName = matches[2];
3256              const outputName = matches[3];
3257              const attrData = matches[5];
3258              const attributes = {};
3259              const attributesOrder = [];
3260              const element = {
3261                attributes,
3262                attributesOrder
3263              };
3264              if (prefix === '#') {
3265                element.paddEmpty = true;
3266              }
3267              if (prefix === '-') {
3268                element.removeEmpty = true;
3269              }
3270              if (matches[4] === '!') {
3271                element.removeEmptyAttrs = true;
3272              }
3273              if (globalAttributes) {
3274                each$d(globalAttributes, (value, key) => {
3275                  attributes[key] = value;
3276                });
3277                if (globalAttributesOrder) {
3278                  attributesOrder.push(...globalAttributesOrder);
3279                }
3280              }
3281              if (attrData) {
3282                const attrDatas = split$1(attrData, '|');
3283                for (let ai = 0, al = attrDatas.length; ai < al; ai++) {
3284                  matches = attrRuleRegExp.exec(attrDatas[ai]);
3285                  if (matches) {
3286                    const attr = {};
3287                    const attrType = matches[1];
3288                    const attrName = matches[2].replace(/[\\:]:/g, ':');
3289                    const attrPrefix = matches[3];
3290                    const value = matches[4];
3291                    if (attrType === '!') {
3292                      element.attributesRequired = element.attributesRequired || [];
3293                      element.attributesRequired.push(attrName);
3294                      attr.required = true;
3295                    }
3296                    if (attrType === '-') {
3297                      delete attributes[attrName];
3298                      attributesOrder.splice(inArray(attributesOrder, attrName), 1);
3299                      continue;
3300                    }
3301                    if (attrPrefix) {
3302                      if (attrPrefix === '=') {
3303                        element.attributesDefault = element.attributesDefault || [];
3304                        element.attributesDefault.push({
3305                          name: attrName,
3306                          value
3307                        });
3308                        attr.defaultValue = value;
3309                      }
3310                      if (attrPrefix === '~') {
3311                        element.attributesForced = element.attributesForced || [];
3312                        element.attributesForced.push({
3313                          name: attrName,
3314                          value
3315                        });
3316                        attr.forcedValue = value;
3317                      }
3318                      if (attrPrefix === '<') {
3319                        attr.validValues = makeMap$2(value, '?');
3320                      }
3321                    }
3322                    if (hasPatternsRegExp.test(attrName)) {
3323                      const attrPattern = attr;
3324                      element.attributePatterns = element.attributePatterns || [];
3325                      attrPattern.pattern = patternToRegExp(attrName);
3326                      element.attributePatterns.push(attrPattern);
3327                    } else {
3328                      if (!attributes[attrName]) {
3329                        attributesOrder.push(attrName);
3330                      }
3331                      attributes[attrName] = attr;
3332                    }
3333                  }
3334                }
3335              }
3336              if (!globalAttributes && elementName === '@') {
3337                globalAttributes = attributes;
3338                globalAttributesOrder = attributesOrder;
3339              }
3340              if (outputName) {
3341                element.outputName = elementName;
3342                elements[outputName] = element;
3343              }
3344              if (hasPatternsRegExp.test(elementName)) {
3345                const patternElement = element;
3346                patternElement.pattern = patternToRegExp(elementName);
3347                patternElements.push(patternElement);
3348              } else {
3349                elements[elementName] = element;
3350              }
3351            }
3352          }
3353        }
3354      };
3355      const setValidElements = validElements => {
3356        patternElements = [];
3357        each$e(keys(elements), name => {
3358          delete elements[name];
3359        });
3360        addValidElements(validElements);
3361        each$b(schemaItems, (element, name) => {
3362          children[name] = element.children;
3363        });
3364      };
3365      const addCustomElements = customElements => {
3366        const customElementRegExp = /^(~)?(.+)$/;
3367        if (customElements) {
3368          delete mapCache.text_block_elements;
3369          delete mapCache.block_elements;
3370          each$b(split$1(customElements, ','), rule => {
3371            const matches = customElementRegExp.exec(rule);
3372            if (matches) {
3373              const inline = matches[1] === '~';
3374              const cloneName = inline ? 'span' : 'div';
3375              const name = matches[2];
3376              children[name] = children[cloneName];
3377              customElementsMap[name] = cloneName;
3378              nonEmptyElementsMap[name.toUpperCase()] = {};
3379              nonEmptyElementsMap[name] = {};
3380              if (!inline) {
3381                blockElementsMap[name.toUpperCase()] = {};
3382                blockElementsMap[name] = {};
3383              }
3384              if (!elements[name]) {
3385                let customRule = elements[cloneName];
3386                customRule = extend$2({}, customRule);
3387                delete customRule.removeEmptyAttrs;
3388                delete customRule.removeEmpty;
3389                elements[name] = customRule;
3390              }
3391              each$b(children, (element, elmName) => {
3392                if (element[cloneName]) {
3393                  children[elmName] = element = extend$2({}, children[elmName]);
3394                  element[name] = element[cloneName];
3395                }
3396              });
3397            }
3398          });
3399        }
3400      };
3401      const addValidChildren = validChildren => {
3402        const childRuleRegExp = /^([+\-]?)([A-Za-z0-9_\-.\u00b7\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u037d\u037f-\u1fff\u200c-\u200d\u203f-\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]+)\[([^\]]+)]$/;
3403        delete lookupCache[schemaType];
3404        if (validChildren) {
3405          each$b(split$1(validChildren, ','), rule => {
3406            const matches = childRuleRegExp.exec(rule);
3407            if (matches) {
3408              const prefix = matches[1];
3409              let parent;
3410              if (prefix) {
3411                parent = children[matches[2]];
3412              } else {
3413                parent = children[matches[2]] = { '#comment': {} };
3414              }
3415              parent = children[matches[2]];
3416              each$b(split$1(matches[3], '|'), child => {
3417                if (prefix === '-') {
3418                  delete parent[child];
3419                } else {
3420                  parent[child] = {};
3421                }
3422              });
3423            }
3424          });
3425        }
3426      };
3427      const getElementRule = name => {
3428        const element = elements[name];
3429        if (element) {
3430          return element;
3431        }
3432        let i = patternElements.length;
3433        while (i--) {
3434          const patternElement = patternElements[i];
3435          if (patternElement.pattern.test(name)) {
3436            return patternElement;
3437          }
3438        }
3439        return undefined;
3440      };
3441      if (!settings.valid_elements) {
3442        each$b(schemaItems, (element, name) => {
3443          elements[name] = {
3444            attributes: element.attributes,
3445            attributesOrder: element.attributesOrder
3446          };
3447          children[name] = element.children;
3448        });
3449        each$b(split$1('strong/b em/i'), item => {
3450          const items = split$1(item, '/');
3451          elements[items[1]].outputName = items[0];
3452        });
3453        each$b(textInlineElementsMap, (_val, name) => {
3454          if (elements[name]) {
3455            if (settings.padd_empty_block_inline_children) {
3456              elements[name].paddInEmptyBlock = true;
3457            }
3458            elements[name].removeEmpty = true;
3459          }
3460        });
3461        each$b(split$1('ol ul blockquote a table tbody'), name => {
3462          if (elements[name]) {
3463            elements[name].removeEmpty = true;
3464          }
3465        });
3466        each$b(split$1('p h1 h2 h3 h4 h5 h6 th td pre div address caption li
3466'), name => {
3467          elements[name].paddEmpty = true;
vendor: 23,235 bytes, lines 3467-4113
3467
3468        });
3469        each$b(split$1('span'), name => {
3470          elements[name].removeEmptyAttrs = true;
3471        });
3472      } else {
3473        setValidElements(settings.valid_elements);
3474      }
3475      addCustomElements(settings.custom_elements);
3476      addValidChildren(settings.valid_children);
3477      addValidElements(settings.extended_valid_elements);
3478      addValidChildren('+ol[ul|ol],+ul[ul|ol]');
3479      each$b({
3480        dd: 'dl',
3481        dt: 'dl',
3482        li: 'ul ol',
3483        td: 'tr',
3484        th: 'tr',
3485        tr: 'tbody thead tfoot',
3486        tbody: 'table',
3487        thead: 'table',
3488        tfoot: 'table',
3489        legend: 'fieldset',
3490        area: 'map',
3491        param: 'video audio object'
3492      }, (parents, item) => {
3493        if (elements[item]) {
3494          elements[item].parentsRequired = split$1(parents);
3495        }
3496      });
3497      if (settings.invalid_elements) {
3498        each$b(explode$2(settings.invalid_elements), item => {
3499          if (elements[item]) {
3500            delete elements[item];
3501          }
3502        });
3503      }
3504      if (!getElementRule('span')) {
3505        addValidElements('span[!data-mce-type|*]');
3506      }
3507      const getValidStyles = constant(validStyles);
3508      const getInvalidStyles = constant(invalidStyles);
3509      const getValidClasses = constant(validClasses);
3510      const getBoolAttrs = constant(boolAttrMap);
3511      const getBlockElements = constant(blockElementsMap);
3512      const getTextBlockElements = constant(textBlockElementsMap);
3513      const getTextInlineElements = constant(textInlineElementsMap);
3514      const getVoidElements = constant(Object.seal(voidElementsMap));
3515      const getSelfClosingElements = constant(selfClosingElementsMap);
3516      const getNonEmptyElements = constant(nonEmptyElementsMap);
3517      const getMoveCaretBeforeOnEnterElements = constant(moveCaretBeforeOnEnterElementsMap);
3518      const getWhitespaceElements = constant(whitespaceElementsMap);
3519      const getTransparentElements = constant(transparentElementsMap);
3520      const getSpecialElements = constant(Object.seal(specialElements));
3521      const isValidChild = (name, child) => {
3522        const parent = children[name.toLowerCase()];
3523        return !!(parent && parent[child.toLowerCase()]);
3524      };
3525      const isValid = (name, attr) => {
3526        const rule = getElementRule(name);
3527        if (rule) {
3528          if (attr) {
3529            if (rule.attributes[attr]) {
3530              return true;
3531            }
3532            const attrPatterns = rule.attributePatterns;
3533            if (attrPatterns) {
3534              let i = attrPatterns.length;
3535              while (i--) {
3536                if (attrPatterns[i].pattern.test(attr)) {
3537                  return true;
3538                }
3539              }
3540            }
3541          } else {
3542            return true;
3543          }
3544        }
3545        return false;
3546      };
3547      const getCustomElements = constant(customElementsMap);
3548      return {
3549        type: schemaType,
3550        children,
3551        elements,
3552        getValidStyles,
3553        getValidClasses,
3554        getBlockElements,
3555        getInvalidStyles,
3556        getVoidElements,
3557        getTextBlockElements,
3558        getTextInlineElements,
3559        getBoolAttrs,
3560        getElementRule,
3561        getSelfClosingElements,
3562        getNonEmptyElements,
3563        getMoveCaretBeforeOnEnterElements,
3564        getWhitespaceElements,
3565        getTransparentElements,
3566        getSpecialElements,
3567        isValidChild,
3568        isValid,
3569        getCustomElements,
3570        addValidElements,
3571        setValidElements,
3572        addCustomElements,
3573        addValidChildren
3574      };
3575    };
3576
3577    const Styles = (settings = {}, schema) => {
3578      const urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi;
3579      const styleRegExp = /\s*([^:]+):\s*([^;]+);?/g;
3580      const trimRightRegExp = /\s+$/;
3581      const encodingLookup = {};
3582      let validStyles;
3583      let invalidStyles;
3584      const invisibleChar = zeroWidth;
3585      if (schema) {
3586        validStyles = schema.getValidStyles();
3587        invalidStyles = schema.getInvalidStyles();
3588      }
3589      const encodingItems = (`\\" \\' \\; \\: ; : ` + invisibleChar).split(' ');
3590      for (let i = 0; i < encodingItems.length; i++) {
3591        encodingLookup[encodingItems[i]] = invisibleChar + i;
3592        encodingLookup[invisibleChar + i] = encodingItems[i];
3593      }
3594      const self = {
3595        parse: css => {
3596          const styles = {};
3597          let isEncoded = false;
3598          const urlConverter = settings.url_converter;
3599          const urlConverterScope = settings.url_converter_scope || self;
3600          const compress = (prefix, suffix, noJoin) => {
3601            const top = styles[prefix + '-top' + suffix];
3602            if (!top) {
3603              return;
3604            }
3605            const right = styles[prefix + '-right' + suffix];
3606            if (!right) {
3607              return;
3608            }
3609            const bottom = styles[prefix + '-bottom' + suffix];
3610            if (!bottom) {
3611              return;
3612            }
3613            const left = styles[prefix + '-left' + suffix];
3614            if (!left) {
3615              return;
3616            }
3617            const box = [
3618              top,
3619              right,
3620              bottom,
3621              left
3622            ];
3623            let i = box.length - 1;
3624            while (i--) {
3625              if (box[i] !== box[i + 1]) {
3626                break;
3627              }
3628            }
3629            if (i > -1 && noJoin) {
3630              return;
3631            }
3632            styles[prefix + suffix] = i === -1 ? box[0] : box.join(' ');
3633            delete styles[prefix + '-top' + suffix];
3634            delete styles[prefix + '-right' + suffix];
3635            delete styles[prefix + '-bottom' + suffix];
3636            delete styles[prefix + '-left' + suffix];
3637          };
3638          const canCompress = key => {
3639            const value = styles[key];
3640            if (!value) {
3641              return;
3642            }
3643            const values = value.split(' ');
3644            let i = values.length;
3645            while (i--) {
3646              if (values[i] !== values[0]) {
3647                return false;
3648              }
3649            }
3650            styles[key] = values[0];
3651            return true;
3652          };
3653          const compress2 = (target, a, b, c) => {
3654            if (!canCompress(a)) {
3655              return;
3656            }
3657            if (!canCompress(b)) {
3658              return;
3659            }
3660            if (!canCompress(c)) {
3661              return;
3662            }
3663            styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c];
3664            delete styles[a];
3665            delete styles[b];
3666            delete styles[c];
3667          };
3668          const encode = str => {
3669            isEncoded = true;
3670            return encodingLookup[str];
3671          };
3672          const decode = (str, keepSlashes) => {
3673            if (isEncoded) {
3674              str = str.replace(/\uFEFF[0-9]/g, str => {
3675                return encodingLookup[str];
3676              });
3677            }
3678            if (!keepSlashes) {
3679              str = str.replace(/\\([\'\";:])/g, '$1');
3680            }
3681            return str;
3682          };
3683          const decodeSingleHexSequence = escSeq => {
3684            return String.fromCharCode(parseInt(escSeq.slice(1), 16));
3685          };
3686          const decodeHexSequences = value => {
3687            return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence);
3688          };
3689          const processUrl = (match, url, url2, url3, str, str2) => {
3690            str = str || str2;
3691            if (str) {
3692              str = decode(str);
3693              return `'` + str.replace(/\'/g, `\\'`) + `'`;
3694            }
3695            url = decode(url || url2 || url3 || '');
3696            if (!settings.allow_script_urls) {
3697              const scriptUrl = url.replace(/[\s\r\n]+/g, '');
3698              if (/(java|vb)script:/i.test(scriptUrl)) {
3699                return '';
3700              }
3701              if (!settings.allow_svg_data_urls && /^data:image\/svg/i.test(scriptUrl)) {
3702                return '';
3703              }
3704            }
3705            if (urlConverter) {
3706              url = urlConverter.call(urlConverterScope, url, 'style');
3707            }
3708            return `url('` + url.replace(/\'/g, `\\'`) + `')`;
3709          };
3710          if (css) {
3711            css = css.replace(/[\u0000-\u001F]/g, '');
3712            css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, str => {
3713              return str.replace(/[;:]/g, encode);
3714            });
3715            let matches;
3716            while (matches = styleRegExp.exec(css)) {
3717              styleRegExp.lastIndex = matches.index + matches[0].length;
3718              let name = matches[1].replace(trimRightRegExp, '').toLowerCase();
3719              let value = matches[2].replace(trimRightRegExp, '');
3720              if (name && value) {
3721                name = decodeHexSequences(name);
3722                value = decodeHexSequences(value);
3723                if (name.indexOf(invisibleChar) !== -1 || name.indexOf('"') !== -1) {
3724                  continue;
3725                }
3726                if (!settings.allow_script_urls && (name === 'behavior' || /expression\s*\(|\/\*|\*\//.test(value))) {
3727                  continue;
3728                }
3729                if (name === 'font-weight' && value === '700') {
3730                  value = 'bold';
3731                } else if (name === 'color' || name === 'background-color') {
3732                  value = value.toLowerCase();
3733                }
3734                value = value.replace(urlOrStrRegExp, processUrl);
3735                styles[name] = isEncoded ? decode(value, true) : value;
3736              }
3737            }
3738            compress('border', '', true);
3739            compress('border', '-width');
3740            compress('border', '-color');
3741            compress('border', '-style');
3742            compress('padding', '');
3743            compress('margin', '');
3744            compress2('border', 'border-width', 'border-style', 'border-color');
3745            if (styles.border === 'medium none') {
3746              delete styles.border;
3747            }
3748            if (styles['border-image'] === 'none') {
3749              delete styles['border-image'];
3750            }
3751          }
3752          return styles;
3753        },
3754        serialize: (styles, elementName) => {
3755          let css = '';
3756          const serializeStyles = (elemName, validStyleList) => {
3757            const styleList = validStyleList[elemName];
3758            if (styleList) {
3759              for (let i = 0, l = styleList.length; i < l; i++) {
3760                const name = styleList[i];
3761                const value = styles[name];
3762                if (value) {
3763                  css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
3764                }
3765              }
3766            }
3767          };
3768          const isValid = (name, elemName) => {
3769            if (!invalidStyles || !elemName) {
3770              return true;
3771            }
3772            let styleMap = invalidStyles['*'];
3773            if (styleMap && styleMap[name]) {
3774              return false;
3775            }
3776            styleMap = invalidStyles[elemName];
3777            return !(styleMap && styleMap[name]);
3778          };
3779          if (elementName && validStyles) {
3780            serializeStyles('*', validStyles);
3781            serializeStyles(elementName, validStyles);
3782          } else {
3783            each$d(styles, (value, name) => {
3784              if (value && isValid(name, elementName)) {
3785                css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
3786              }
3787            });
3788          }
3789          return css;
3790        }
3791      };
3792      return self;
3793    };
3794
3795    const deprecated = {
3796      keyLocation: true,
3797      layerX: true,
3798      layerY: true,
3799      returnValue: true,
3800      webkitMovementX: true,
3801      webkitMovementY: true,
3802      keyIdentifier: true,
3803      mozPressure: true
3804    };
3805    const isNativeEvent = event => event instanceof Event || isFunction(event.initEvent);
3806    const hasIsDefaultPrevented = event => event.isDefaultPrevented === always || event.isDefaultPrevented === never;
3807    const needsNormalizing = event => isNullable(event.preventDefault) || isNativeEvent(event);
3808    const clone$3 = (originalEvent, data) => {
3809      const event = data !== null && data !== void 0 ? data : {};
3810      for (const name in originalEvent) {
3811        if (!has$2(deprecated, name)) {
3812          event[name] = originalEvent[name];
3813        }
3814      }
3815      if (isNonNullable(originalEvent.composedPath)) {
3816        event.composedPath = () => originalEvent.composedPath();
3817      }
3818      return event;
3819    };
3820    const normalize$3 = (type, originalEvent, fallbackTarget, data) => {
3821      var _a;
3822      const event = clone$3(originalEvent, data);
3823      event.type = type;
3824      if (isNullable(event.target)) {
3825        event.target = (_a = event.srcElement) !== null && _a !== void 0 ? _a : fallbackTarget;
3826      }
3827      if (needsNormalizing(originalEvent)) {
3828        event.preventDefault = () => {
3829          event.defaultPrevented = true;
3830          event.isDefaultPrevented = always;
3831          if (isFunction(originalEvent.preventDefault)) {
3832            originalEvent.preventDefault();
3833          }
3834        };
3835        event.stopPropagation = () => {
3836          event.cancelBubble = true;
3837          event.isPropagationStopped = always;
3838          if (isFunction(originalEvent.stopPropagation)) {
3839            originalEvent.stopPropagation();
3840          }
3841        };
3842        event.stopImmediatePropagation = () => {
3843          event.isImmediatePropagationStopped = always;
3844          event.stopPropagation();
3845        };
3846        if (!hasIsDefaultPrevented(event)) {
3847          event.isDefaultPrevented = event.defaultPrevented === true ? always : never;
3848          event.isPropagationStopped = event.cancelBubble === true ? always : never;
3849          event.isImmediatePropagationStopped = never;
3850        }
3851      }
3852      return event;
3853    };
3854
3855    const eventExpandoPrefix = 'mce-data-';
3856    const mouseEventRe = /^(?:mouse|contextmenu)|click/;
3857    const addEvent = (target, name, callback, capture) => {
3858      target.addEventListener(name, callback, capture || false);
3859    };
3860    const removeEvent = (target, name, callback, capture) => {
3861      target.removeEventListener(name, callback, capture || false);
3862    };
3863    const isMouseEvent = event => isNonNullable(event) && mouseEventRe.test(event.type);
3864    const fix = (originalEvent, data) => {
3865      const event = normalize$3(originalEvent.type, originalEvent, document, data);
3866      if (isMouseEvent(originalEvent) && isUndefined(originalEvent.pageX) && !isUndefined(originalEvent.clientX)) {
3867        const eventDoc = event.target.ownerDocument || document;
3868        const doc = eventDoc.documentElement;
3869        const body = eventDoc.body;
3870        const mouseEvent = event;
3871        mouseEvent.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
3872        mouseEvent.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
3873      }
3874      return event;
3875    };
3876    const bindOnReady = (win, callback, eventUtils) => {
3877      const doc = win.document, event = { type: 'ready' };
3878      if (eventUtils.domLoaded) {
3879        callback(event);
3880        return;
3881      }
3882      const isDocReady = () => {
3883        return doc.readyState === 'complete' || doc.readyState === 'interactive' && doc.body;
3884      };
3885      const readyHandler = () => {
3886        removeEvent(win, 'DOMContentLoaded', readyHandler);
3887        removeEvent(win, 'load', readyHandler);
3888        if (!eventUtils.domLoaded) {
3889          eventUtils.domLoaded = true;
3890          callback(event);
3891        }
3892        win = null;
3893      };
3894      if (isDocReady()) {
3895        readyHandler();
3896      } else {
3897        addEvent(win, 'DOMContentLoaded', readyHandler);
3898      }
3899      if (!eventUtils.domLoaded) {
3900        addEvent(win, 'load', readyHandler);
3901      }
3902    };
3903    class EventUtils {
3904      constructor() {
3905        this.domLoaded = false;
3906        this.events = {};
3907        this.count = 1;
3908        this.expando = eventExpandoPrefix + (+new Date()).toString(32);
3909        this.hasFocusIn = 'onfocusin' in document.documentElement;
3910        this.count = 1;
3911      }
3912      bind(target, names, callback, scope) {
3913        const self = this;
3914        let callbackList;
3915        const win = window;
3916        const defaultNativeHandler = evt => {
3917          self.executeHandlers(fix(evt || win.event), id);
3918        };
3919        if (!target || isText$a(target) || isComment(target)) {
3920          return callback;
3921        }
3922        let id;
3923        if (!target[self.expando]) {
3924          id = self.count++;
3925          target[self.expando] = id;
3926          self.events[id] = {};
3927        } else {
3928          id = target[self.expando];
3929        }
3930        scope = scope || target;
3931        const namesList = names.split(' ');
3932        let i = namesList.length;
3933        while (i--) {
3934          let name = namesList[i];
3935          let nativeHandler = defaultNativeHandler;
3936          let capture = false;
3937          let fakeName = false;
3938          if (name === 'DOMContentLoaded') {
3939            name = 'ready';
3940          }
3941          if (self.domLoaded && name === 'ready' && target.readyState === 'complete') {
3942            callback.call(scope, fix({ type: name }));
3943            continue;
3944          }
3945          if (!self.hasFocusIn && (name === 'focusin' || name === 'focusout')) {
3946            capture = true;
3947            fakeName = name === 'focusin' ? 'focus' : 'blur';
3948            nativeHandler = evt => {
3949              const event = fix(evt || win.event);
3950              event.type = event.type === 'focus' ? 'focusin' : 'focusout';
3951              self.executeHandlers(event, id);
3952            };
3953          }
3954          callbackList = self.events[id][name];
3955          if (!callbackList) {
3956            self.events[id][name] = callbackList = [{
3957                func: callback,
3958                scope
3959              }];
3960            callbackList.fakeName = fakeName;
3961            callbackList.capture = capture;
3962            callbackList.nativeHandler = nativeHandler;
3963            if (name === 'ready') {
3964              bindOnReady(target, nativeHandler, self);
3965            } else {
3966              addEvent(target, fakeName || name, nativeHandler, capture);
3967            }
3968          } else {
3969            if (name === 'ready' && self.domLoaded) {
3970              callback(fix({ type: name }));
3971            } else {
3972              callbackList.push({
3973                func: callback,
3974                scope
3975              });
3976            }
3977          }
3978        }
3979        target = callbackList = null;
3980        return callback;
3981      }
3982      unbind(target, names, callback) {
3983        if (!target || isText$a(target) || isComment(target)) {
3984          return this;
3985        }
3986        const id = target[this.expando];
3987        if (id) {
3988          let eventMap = this.events[id];
3989          if (names) {
3990            const namesList = names.split(' ');
3991            let i = namesList.length;
3992            while (i--) {
3993              const name = namesList[i];
3994              const callbackList = eventMap[name];
3995              if (callbackList) {
3996                if (callback) {
3997                  let ci = callbackList.length;
3998                  while (ci--) {
3999                    if (callbackList[ci].func === callback) {
4000                      const nativeHandler = callbackList.nativeHandler;
4001                      const fakeName = callbackList.fakeName, capture = callbackList.capture;
4002                      const newCallbackList = callbackList.slice(0, ci).concat(callbackList.slice(ci + 1));
4003                      newCallbackList.nativeHandler = nativeHandler;
4004                      newCallbackList.fakeName = fakeName;
4005                      newCallbackList.capture = capture;
4006                      eventMap[name] = newCallbackList;
4007                    }
4008                  }
4009                }
4010                if (!callback || callbackList.length === 0) {
4011                  delete eventMap[name];
4012                  removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
4013                }
4014              }
4015            }
4016          } else {
4017            each$d(eventMap, (callbackList, name) => {
4018              removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
4019            });
4020            eventMap = {};
4021          }
4022          for (const name in eventMap) {
4023            if (has$2(eventMap, name)) {
4024              return this;
4025            }
4026          }
4027          delete this.events[id];
4028          try {
4029            delete target[this.expando];
4030          } catch (ex) {
4031            target[this.expando] = null;
4032          }
4033        }
4034        return this;
4035      }
4036      fire(target, name, args) {
4037        return this.dispatch(target, name, args);
4038      }
4039      dispatch(target, name, args) {
4040        if (!target || isText$a(target) || isComment(target)) {
4041          return this;
4042        }
4043        const event = fix({
4044          type: name,
4045          target
4046        }, args);
4047        do {
4048          const id = target[this.expando];
4049          if (id) {
4050            this.executeHandlers(event, id);
4051          }
4052          target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow;
4053        } while (target && !event.isPropagationStopped());
4054        return this;
4055      }
4056      clean(target) {
4057        if (!target || isText$a(target) || isComment(target)) {
4058          return this;
4059        }
4060        if (target[this.expando]) {
4061          this.unbind(target);
4062        }
4063        if (!target.getElementsByTagName) {
4064          target = target.document;
4065        }
4066        if (target && target.getElementsByTagName) {
4067          this.unbind(target);
4068          const children = target.getElementsByTagName('*');
4069          let i = children.length;
4070          while (i--) {
4071            target = children[i];
4072            if (target[this.expando]) {
4073              this.unbind(target);
4074            }
4075          }
4076        }
4077        return this;
4078      }
4079      destroy() {
4080        this.events = {};
4081      }
4082      cancel(e) {
4083        if (e) {
4084          e.preventDefault();
4085          e.stopImmediatePropagation();
4086        }
4087        return false;
4088      }
4089      executeHandlers(evt, id) {
4090        const container = this.events[id];
4091        const callbackList = container && container[evt.type];
4092        if (callbackList) {
4093          for (let i = 0, l = callbackList.length; i < l; i++) {
4094            const callback = callbackList[i];
4095            if (callback && callback.func.call(callback.scope, evt) === false) {
4096              evt.preventDefault();
4097            }
4098            if (evt.isImmediatePropagationStopped()) {
4099              return;
4100            }
4101          }
4102        }
4103      }
4104    }
4105    EventUtils.Event = new EventUtils();
4106
4107    const each$a = Tools.each;
4108    const grep = Tools.grep;
4109    const internalStyleName = 'data-mce-style';
4110    const numericalCssMap = Tools.makeMap('fill-opacity font-weight line-height opacity orphans widows z-index zoom', ' ');
4111    const legacySetAttribute = (elm, name, value) => {
4112      if (isNullable(value) || value === '') {
4113        remove$
vendor: 24,236 bytes, lines 4113-4804
4113b(elm, name);
4114      } else {
4115        set$3(elm, name, value);
4116      }
4117    };
4118    const camelCaseToHyphens = name => name.replace(/[A-Z]/g, v => '-' + v.toLowerCase());
4119    const findNodeIndex = (node, normalized) => {
4120      let idx = 0;
4121      if (node) {
4122        for (let lastNodeType = node.nodeType, tempNode = node.previousSibling; tempNode; tempNode = tempNode.previousSibling) {
4123          const nodeType = tempNode.nodeType;
4124          if (normalized && isText$a(tempNode)) {
4125            if (nodeType === lastNodeType || !tempNode.data.length) {
4126              continue;
4127            }
4128          }
4129          idx++;
4130          lastNodeType = nodeType;
4131        }
4132      }
4133      return idx;
4134    };
4135    const updateInternalStyleAttr = (styles, elm) => {
4136      const rawValue = get$9(elm, 'style');
4137      const value = styles.serialize(styles.parse(rawValue), name(elm));
4138      legacySetAttribute(elm, internalStyleName, value);
4139    };
4140    const convertStyleToString = (cssValue, cssName) => {
4141      if (isNumber(cssValue)) {
4142        return has$2(numericalCssMap, cssName) ? cssValue + '' : cssValue + 'px';
4143      } else {
4144        return cssValue;
4145      }
4146    };
4147    const applyStyle$1 = ($elm, cssName, cssValue) => {
4148      const normalizedName = camelCaseToHyphens(cssName);
4149      if (isNullable(cssValue) || cssValue === '') {
4150        remove$7($elm, normalizedName);
4151      } else {
4152        set$2($elm, normalizedName, convertStyleToString(cssValue, normalizedName));
4153      }
4154    };
4155    const setupAttrHooks = (styles, settings, getContext) => {
4156      const keepValues = settings.keep_values;
4157      const keepUrlHook = {
4158        set: (elm, value, name) => {
4159          const sugarElm = SugarElement.fromDom(elm);
4160          if (isFunction(settings.url_converter) && isNonNullable(value)) {
4161            value = settings.url_converter.call(settings.url_converter_scope || getContext(), String(value), name, elm);
4162          }
4163          const internalName = 'data-mce-' + name;
4164          legacySetAttribute(sugarElm, internalName, value);
4165          legacySetAttribute(sugarElm, name, value);
4166        },
4167        get: (elm, name) => {
4168          const sugarElm = SugarElement.fromDom(elm);
4169          return get$9(sugarElm, 'data-mce-' + name) || get$9(sugarElm, name);
4170        }
4171      };
4172      const attrHooks = {
4173        style: {
4174          set: (elm, value) => {
4175            const sugarElm = SugarElement.fromDom(elm);
4176            if (keepValues) {
4177              legacySetAttribute(sugarElm, internalStyleName, value);
4178            }
4179            remove$b(sugarElm, 'style');
4180            if (isString(value)) {
4181              setAll(sugarElm, styles.parse(value));
4182            }
4183          },
4184          get: elm => {
4185            const sugarElm = SugarElement.fromDom(elm);
4186            const value = get$9(sugarElm, internalStyleName) || get$9(sugarElm, 'style');
4187            return styles.serialize(styles.parse(value), name(sugarElm));
4188          }
4189        }
4190      };
4191      if (keepValues) {
4192        attrHooks.href = attrHooks.src = keepUrlHook;
4193      }
4194      return attrHooks;
4195    };
4196    const DOMUtils = (doc, settings = {}) => {
4197      const addedStyles = {};
4198      const win = window;
4199      const files = {};
4200      let counter = 0;
4201      const stdMode = true;
4202      const boxModel = true;
4203      const styleSheetLoader = instance.forElement(SugarElement.fromDom(doc), {
4204        contentCssCors: settings.contentCssCors,
4205        referrerPolicy: settings.referrerPolicy
4206      });
4207      const boundEvents = [];
4208      const schema = settings.schema ? settings.schema : Schema({});
4209      const styles = Styles({
4210        url_converter: settings.url_converter,
4211        url_converter_scope: settings.url_converter_scope
4212      }, settings.schema);
4213      const events = settings.ownEvents ? new EventUtils() : EventUtils.Event;
4214      const blockElementsMap = schema.getBlockElements();
4215      const isBlock = node => {
4216        if (isString(node)) {
4217          return has$2(blockElementsMap, node);
4218        } else {
4219          return isElement$6(node) && (has$2(blockElementsMap, node.nodeName) || isTransparentBlock(schema, node));
4220        }
4221      };
4222      const get = elm => elm && doc && isString(elm) ? doc.getElementById(elm) : elm;
4223      const _get = elm => {
4224        const value = get(elm);
4225        return isNonNullable(value) ? SugarElement.fromDom(value) : null;
4226      };
4227      const getAttrib = (elm, name, defaultVal = '') => {
4228        let value;
4229        const $elm = _get(elm);
4230        if (isNonNullable($elm) && isElement$7($elm)) {
4231          const hook = attrHooks[name];
4232          if (hook && hook.get) {
4233            value = hook.get($elm.dom, name);
4234          } else {
4235            value = get$9($elm, name);
4236          }
4237        }
4238        return isNonNullable(value) ? value : defaultVal;
4239      };
4240      const getAttribs = elm => {
4241        const node = get(elm);
4242        return isNullable(node) ? [] : node.attributes;
4243      };
4244      const setAttrib = (elm, name, value) => {
4245        run(elm, e => {
4246          if (isElement$6(e)) {
4247            const $elm = SugarElement.fromDom(e);
4248            const val = value === '' ? null : value;
4249            const originalValue = get$9($elm, name);
4250            const hook = attrHooks[name];
4251            if (hook && hook.set) {
4252              hook.set($elm.dom, val, name);
4253            } else {
4254              legacySetAttribute($elm, name, val);
4255            }
4256            if (originalValue !== val && settings.onSetAttrib) {
4257              settings.onSetAttrib({
4258                attrElm: $elm.dom,
4259                attrName: name,
4260                attrValue: val
4261              });
4262            }
4263          }
4264        });
4265      };
4266      const clone = (node, deep) => {
4267        return node.cloneNode(deep);
4268      };
4269      const getRoot = () => settings.root_element || doc.body;
4270      const getViewPort = argWin => {
4271        const vp = getBounds(argWin);
4272        return {
4273          x: vp.x,
4274          y: vp.y,
4275          w: vp.width,
4276          h: vp.height
4277        };
4278      };
4279      const getPos$1 = (elm, rootElm) => getPos(doc.body, get(elm), rootElm);
4280      const setStyle = (elm, name, value) => {
4281        run(elm, e => {
4282          const $elm = SugarElement.fromDom(e);
4283          applyStyle$1($elm, name, value);
4284          if (settings.update_styles) {
4285            updateInternalStyleAttr(styles, $elm);
4286          }
4287        });
4288      };
4289      const setStyles = (elm, stylesArg) => {
4290        run(elm, e => {
4291          const $elm = SugarElement.fromDom(e);
4292          each$d(stylesArg, (v, n) => {
4293            applyStyle$1($elm, n, v);
4294          });
4295          if (settings.update_styles) {
4296            updateInternalStyleAttr(styles, $elm);
4297          }
4298        });
4299      };
4300      const getStyle = (elm, name, computed) => {
4301        const $elm = get(elm);
4302        if (isNullable($elm) || !isElement$6($elm)) {
4303          return undefined;
4304        }
4305        if (computed) {
4306          return get$7(SugarElement.fromDom($elm), camelCaseToHyphens(name));
4307        } else {
4308          name = name.replace(/-(\D)/g, (a, b) => b.toUpperCase());
4309          if (name === 'float') {
4310            name = 'cssFloat';
4311          }
4312          return $elm.style ? $elm.style[name] : undefined;
4313        }
4314      };
4315      const getSize = elm => {
4316        const $elm = get(elm);
4317        if (!$elm) {
4318          return {
4319            w: 0,
4320            h: 0
4321          };
4322        }
4323        let w = getStyle($elm, 'width');
4324        let h = getStyle($elm, 'height');
4325        if (!w || w.indexOf('px') === -1) {
4326          w = '0';
4327        }
4328        if (!h || h.indexOf('px') === -1) {
4329          h = '0';
4330        }
4331        return {
4332          w: parseInt(w, 10) || $elm.offsetWidth || $elm.clientWidth,
4333          h: parseInt(h, 10) || $elm.offsetHeight || $elm.clientHeight
4334        };
4335      };
4336      const getRect = elm => {
4337        const $elm = get(elm);
4338        const pos = getPos$1($elm);
4339        const size = getSize($elm);
4340        return {
4341          x: pos.x,
4342          y: pos.y,
4343          w: size.w,
4344          h: size.h
4345        };
4346      };
4347      const is = (elm, selector) => {
4348        if (!elm) {
4349          return false;
4350        }
4351        const elms = isArray$1(elm) ? elm : [elm];
4352        return exists(elms, e => {
4353          return is$1(SugarElement.fromDom(e), selector);
4354        });
4355      };
4356      const getParents = (elm, selector, root, collect) => {
4357        const result = [];
4358        let node = get(elm);
4359        collect = collect === undefined;
4360        const resolvedRoot = root || (getRoot().nodeName !== 'BODY' ? getRoot().parentNode : null);
4361        if (isString(selector)) {
4362          if (selector === '*') {
4363            selector = isElement$6;
4364          } else {
4365            const selectorVal = selector;
4366            selector = node => is(node, selectorVal);
4367          }
4368        }
4369        while (node) {
4370          if (node === resolvedRoot || isNullable(node.nodeType) || isDocument$1(node) || isDocumentFragment(node)) {
4371            break;
4372          }
4373          if (!selector || selector(node)) {
4374            if (collect) {
4375              result.push(node);
4376            } else {
4377              return [node];
4378            }
4379          }
4380          node = node.parentNode;
4381        }
4382        return collect ? result : null;
4383      };
4384      const getParent = (node, selector, root) => {
4385        const parents = getParents(node, selector, root, false);
4386        return parents && parents.length > 0 ? parents[0] : null;
4387      };
4388      const _findSib = (node, selector, name) => {
4389        let func = selector;
4390        if (node) {
4391          if (isString(selector)) {
4392            func = node => {
4393              return is(node, selector);
4394            };
4395          }
4396          for (let tempNode = node[name]; tempNode; tempNode = tempNode[name]) {
4397            if (isFunction(func) && func(tempNode)) {
4398              return tempNode;
4399            }
4400          }
4401        }
4402        return null;
4403      };
4404      const getNext = (node, selector) => _findSib(node, selector, 'nextSibling');
4405      const getPrev = (node, selector) => _findSib(node, selector, 'previousSibling');
4406      const isParentNode = node => isFunction(node.querySelectorAll);
4407      const select = (selector, scope) => {
4408        var _a, _b;
4409        const elm = (_b = (_a = get(scope)) !== null && _a !== void 0 ? _a : settings.root_element) !== null && _b !== void 0 ? _b : doc;
4410        return isParentNode(elm) ? from(elm.querySelectorAll(selector)) : [];
4411      };
4412      const run = function (elm, func, scope) {
4413        const context = scope !== null && scope !== void 0 ? scope : this;
4414        if (isArray$1(elm)) {
4415          const result = [];
4416          each$a(elm, (e, i) => {
4417            const node = get(e);
4418            if (node) {
4419              result.push(func.call(context, node, i));
4420            }
4421          });
4422          return result;
4423        } else {
4424          const node = get(elm);
4425          return !node ? false : func.call(context, node);
4426        }
4427      };
4428      const setAttribs = (elm, attrs) => {
4429        run(elm, $elm => {
4430          each$d(attrs, (value, name) => {
4431            setAttrib($elm, name, value);
4432          });
4433        });
4434      };
4435      const setHTML = (elm, html) => {
4436        run(elm, e => {
4437          const $elm = SugarElement.fromDom(e);
4438          set$1($elm, html);
4439        });
4440      };
4441      const add = (parentElm, name, attrs, html, create) => run(parentElm, parentElm => {
4442        const newElm = isString(name) ? doc.createElement(name) : name;
4443        if (isNonNullable(attrs)) {
4444          setAttribs(newElm, attrs);
4445        }
4446        if (html) {
4447          if (!isString(html) && html.nodeType) {
4448            newElm.appendChild(html);
4449          } else if (isString(html)) {
4450            setHTML(newElm, html);
4451          }
4452        }
4453        return !create ? parentElm.appendChild(newElm) : newElm;
4454      });
4455      const create = (name, attrs, html) => add(doc.createElement(name), name, attrs, html, true);
4456      const decode = Entities.decode;
4457      const encode = Entities.encodeAllRaw;
4458      const createHTML = (name, attrs, html = '') => {
4459        let outHtml = '<' + name;
4460        for (const key in attrs) {
4461          if (hasNonNullableKey(attrs, key)) {
4462            outHtml += ' ' + key + '="' + encode(attrs[key]) + '"';
4463          }
4464        }
4465        if (isEmpty$3(html) && has$2(schema.getVoidElements(), name)) {
4466          return outHtml + ' />';
4467        } else {
4468          return outHtml + '>' + html + '</' + name + '>';
4469        }
4470      };
4471      const createFragment = html => {
4472        const container = doc.createElement('div');
4473        const frag = doc.createDocumentFragment();
4474        frag.appendChild(container);
4475        if (html) {
4476          container.innerHTML = html;
4477        }
4478        let node;
4479        while (node = container.firstChild) {
4480          frag.appendChild(node);
4481        }
4482        frag.removeChild(container);
4483        return frag;
4484      };
4485      const remove = (node, keepChildren) => {
4486        return run(node, n => {
4487          const $node = SugarElement.fromDom(n);
4488          if (keepChildren) {
4489            each$e(children$1($node), child => {
4490              if (isText$b(child) && child.dom.length === 0) {
4491                remove$6(child);
4492              } else {
4493                before$3($node, child);
4494              }
4495            });
4496          }
4497          remove$6($node);
4498          return $node.dom;
4499        });
4500      };
4501      const removeAllAttribs = e => run(e, e => {
4502        const attrs = e.attributes;
4503        for (let i = attrs.length - 1; i >= 0; i--) {
4504          e.removeAttributeNode(attrs.item(i));
4505        }
4506      });
4507      const parseStyle = cssText => styles.parse(cssText);
4508      const serializeStyle = (stylesArg, name) => styles.serialize(stylesArg, name);
4509      const addStyle = cssText => {
4510        if (self !== DOMUtils.DOM && doc === document) {
4511          if (addedStyles[cssText]) {
4512            return;
4513          }
4514          addedStyles[cssText] = true;
4515        }
4516        let styleElm = doc.getElementById('mceDefaultStyles');
4517        if (!styleElm) {
4518          styleElm = doc.createElement('style');
4519          styleElm.id = 'mceDefaultStyles';
4520          styleElm.type = 'text/css';
4521          const head = doc.head;
4522          if (head.firstChild) {
4523            head.insertBefore(styleElm, head.firstChild);
4524          } else {
4525            head.appendChild(styleElm);
4526          }
4527        }
4528        if (styleElm.styleSheet) {
4529          styleElm.styleSheet.cssText += cssText;
4530        } else {
4531          styleElm.appendChild(doc.createTextNode(cssText));
4532        }
4533      };
4534      const loadCSS = urls => {
4535        if (!urls) {
4536          urls = '';
4537        }
4538        each$e(urls.split(','), url => {
4539          files[url] = true;
4540          styleSheetLoader.load(url).catch(noop);
4541        });
4542      };
4543      const toggleClass = (elm, cls, state) => {
4544        run(elm, e => {
4545          if (isElement$6(e)) {
4546            const $elm = SugarElement.fromDom(e);
4547            const classes = cls.split(' ');
4548            each$e(classes, c => {
4549              if (isNonNullable(state)) {
4550                const fn = state ? add$2 : remove$8;
4551                fn($elm, c);
4552              } else {
4553                toggle$1($elm, c);
4554              }
4555            });
4556          }
4557        });
4558      };
4559      const addClass = (elm, cls) => {
4560        toggleClass(elm, cls, true);
4561      };
4562      const removeClass = (elm, cls) => {
4563        toggleClass(elm, cls, false);
4564      };
4565      const hasClass = (elm, cls) => {
4566        const $elm = _get(elm);
4567        const classes = cls.split(' ');
4568        return isNonNullable($elm) && forall(classes, c => has($elm, c));
4569      };
4570      const show = elm => {
4571        run(elm, e => remove$7(SugarElement.fromDom(e), 'display'));
4572      };
4573      const hide = elm => {
4574        run(elm, e => set$2(SugarElement.fromDom(e), 'display', 'none'));
4575      };
4576      const isHidden = elm => {
4577        const $elm = _get(elm);
4578        return isNonNullable($elm) && is$2(getRaw($elm, 'display'), 'none');
4579      };
4580      const uniqueId = prefix => (!prefix ? 'mce_' : prefix) + counter++;
4581      const getOuterHTML = elm => {
4582        const $elm = _get(elm);
4583        if (isNonNullable($elm)) {
4584          return isElement$6($elm.dom) ? $elm.dom.outerHTML : getOuter($elm);
4585        } else {
4586          return '';
4587        }
4588      };
4589      const setOuterHTML = (elm, html) => {
4590        run(elm, $elm => {
4591          if (isElement$6($elm)) {
4592            $elm.outerHTML = html;
4593          }
4594        });
4595      };
4596      const insertAfter = (node, reference) => {
4597        const referenceNode = get(reference);
4598        return run(node, node => {
4599          const parent = referenceNode === null || referenceNode === void 0 ? void 0 : referenceNode.parentNode;
4600          const nextSibling = referenceNode === null || referenceNode === void 0 ? void 0 : referenceNode.nextSibling;
4601          if (parent) {
4602            if (nextSibling) {
4603              parent.insertBefore(node, nextSibling);
4604            } else {
4605              parent.appendChild(node);
4606            }
4607          }
4608          return node;
4609        });
4610      };
4611      const replace = (newElm, oldElm, keepChildren) => run(oldElm, elm => {
4612        var _a;
4613        const replacee = isArray$1(oldElm) ? newElm.cloneNode(true) : newElm;
4614        if (keepChildren) {
4615          each$a(grep(elm.childNodes), node => {
4616            replacee.appendChild(node);
4617          });
4618        }
4619        (_a = elm.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(replacee, elm);
4620        return elm;
4621      });
4622      const rename = (elm, name) => {
4623        if (elm.nodeName !== name.toUpperCase()) {
4624          const newElm = create(name);
4625          each$a(getAttribs(elm), attrNode => {
4626            setAttrib(newElm, attrNode.nodeName, getAttrib(elm, attrNode.nodeName));
4627          });
4628          replace(newElm, elm, true);
4629          return newElm;
4630        } else {
4631          return elm;
4632        }
4633      };
4634      const findCommonAncestor = (a, b) => {
4635        let ps = a;
4636        while (ps) {
4637          let pe = b;
4638          while (pe && ps !== pe) {
4639            pe = pe.parentNode;
4640          }
4641          if (ps === pe) {
4642            break;
4643          }
4644          ps = ps.parentNode;
4645        }
4646        if (!ps && a.ownerDocument) {
4647          return a.ownerDocument.documentElement;
4648        } else {
4649          return ps;
4650        }
4651      };
4652      const isNonEmptyElement = node => {
4653        if (isElement$6(node)) {
4654          const isNamedAnchor = node.nodeName.toLowerCase() === 'a' && !getAttrib(node, 'href') && getAttrib(node, 'id');
4655          if (getAttrib(node, 'name') || getAttrib(node, 'data-mce-bookmark') || isNamedAnchor) {
4656            return true;
4657          }
4658        }
4659        return false;
4660      };
4661      const isEmpty = (node, elements) => {
4662        let brCount = 0;
4663        if (isNonEmptyElement(node)) {
4664          return false;
4665        }
4666        const firstChild = node.firstChild;
4667        if (firstChild) {
4668          const walker = new DomTreeWalker(firstChild, node);
4669          const whitespaceElements = schema ? schema.getWhitespaceElements() : {};
4670          const nonEmptyElements = elements || (schema ? schema.getNonEmptyElements() : null);
4671          let tempNode = firstChild;
4672          do {
4673            if (isElement$6(tempNode)) {
4674              const bogusVal = tempNode.getAttribute('data-mce-bogus');
4675              if (bogusVal) {
4676                tempNode = walker.next(bogusVal === 'all');
4677                continue;
4678              }
4679              const name = tempNode.nodeName.toLowerCase();
4680              if (nonEmptyElements && nonEmptyElements[name]) {
4681                if (name === 'br') {
4682                  brCount++;
4683                  tempNode = walker.next();
4684                  continue;
4685                }
4686                return false;
4687              }
4688              if (isNonEmptyElement(tempNode)) {
4689                return false;
4690              }
4691            }
4692            if (isComment(tempNode)) {
4693              return false;
4694            }
4695            if (isText$a(tempNode) && !isWhitespaceText(tempNode.data)) {
4696              return false;
4697            }
4698            if (isText$a(tempNode) && tempNode.parentNode && whitespaceElements[tempNode.parentNode.nodeName] && isWhitespaceText(tempNode.data)) {
4699              return false;
4700            }
4701            tempNode = walker.next();
4702          } while (tempNode);
4703        }
4704        return brCount <= 1;
4705      };
4706      const createRng = () => doc.createRange();
4707      const split = (parentElm, splitElm, replacementElm) => {
4708        let range = createRng();
4709        let beforeFragment;
4710        let afterFragment;
4711        if (parentElm && splitElm && parentElm.parentNode && splitElm.parentNode) {
4712          const parentNode = parentElm.parentNode;
4713          range.setStart(parentNode, findNodeIndex(parentElm));
4714          range.setEnd(splitElm.parentNode, findNodeIndex(splitElm));
4715          beforeFragment = range.extractContents();
4716          range = createRng();
4717          range.setStart(splitElm.parentNode, findNodeIndex(splitElm) + 1);
4718          range.setEnd(parentNode, findNodeIndex(parentElm) + 1);
4719          afterFragment = range.extractContents();
4720          parentNode.insertBefore(trimNode(self, beforeFragment), parentElm);
4721          if (replacementElm) {
4722            parentNode.insertBefore(replacementElm, parentElm);
4723          } else {
4724            parentNode.insertBefore(splitElm, parentElm);
4725          }
4726          parentNode.insertBefore(trimNode(self, afterFragment), parentElm);
4727          remove(parentElm);
4728          return replacementElm || splitElm;
4729        } else {
4730          return undefined;
4731        }
4732      };
4733      const bind = (target, name, func, scope) => {
4734        if (isArray$1(target)) {
4735          let i = target.length;
4736          const rv = [];
4737          while (i--) {
4738            rv[i] = bind(target[i], name, func, scope);
4739          }
4740          return rv;
4741        } else {
4742          if (settings.collect && (target === doc || target === win)) {
4743            boundEvents.push([
4744              target,
4745              name,
4746              func,
4747              scope
4748            ]);
4749          }
4750          return events.bind(target, name, func, scope || self);
4751        }
4752      };
4753      const unbind = (target, name, func) => {
4754        if (isArray$1(target)) {
4755          let i = target.length;
4756          const rv = [];
4757          while (i--) {
4758            rv[i] = unbind(target[i], name, func);
4759          }
4760          return rv;
4761        } else {
4762          if (boundEvents.length > 0 && (target === doc || target === win)) {
4763            let i = boundEvents.length;
4764            while (i--) {
4765              const [boundTarget, boundName, boundFunc] = boundEvents[i];
4766              if (target === boundTarget && (!name || name === boundName) && (!func || func === boundFunc)) {
4767                events.unbind(boundTarget, boundName, boundFunc);
4768              }
4769            }
4770          }
4771          return events.unbind(target, name, func);
4772        }
4773      };
4774      const dispatch = (target, name, evt) => events.dispatch(target, name, evt);
4775      const fire = (target, name, evt) => events.dispatch(target, name, evt);
4776      const getContentEditable = node => {
4777        if (node && isElement$6(node)) {
4778          const contentEditable = node.getAttribute('data-mce-contenteditable');
4779          if (contentEditable && contentEditable !== 'inherit') {
4780            return contentEditable;
4781          }
4782          return node.contentEditable !== 'inherit' ? node.contentEditable : null;
4783        } else {
4784          return null;
4785        }
4786      };
4787      const getContentEditableParent = node => {
4788        const root = getRoot();
4789        let state = null;
4790        for (let tempNode = node; tempNode && tempNode !== root; tempNode = tempNode.parentNode) {
4791          state = getContentEditable(tempNode);
4792          if (state !== null) {
4793            break;
4794          }
4795        }
4796        return state;
4797      };
4798      const isEditable = node => {
4799        if (isNonNullable(node)) {
4800          const scope = isElement$6(node) ? node : node.parentElement;
4801          const isRootEditable = getContentEditable(getRoot()) === 'true';
4802          return isNonNullable(scope) && isEditable$3(SugarElement.fromDom(scope), isRootEditable);
4803        } else {
4804          return false;
vendor: 6,561 bytes, lines 4805-5035
4805        }
4806      };
4807      const destroy = () => {
4808        if (boundEvents.length > 0) {
4809          let i = boundEvents.length;
4810          while (i--) {
4811            const [boundTarget, boundName, boundFunc] = boundEvents[i];
4812            events.unbind(boundTarget, boundName, boundFunc);
4813          }
4814        }
4815        each$d(files, (_, url) => {
4816          styleSheetLoader.unload(url);
4817          delete files[url];
4818        });
4819      };
4820      const isChildOf = (node, parent) => {
4821        return node === parent || parent.contains(node);
4822      };
4823      const dumpRng = r => 'startContainer: ' + r.startContainer.nodeName + ', startOffset: ' + r.startOffset + ', endContainer: ' + r.endContainer.nodeName + ', endOffset: ' + r.endOffset;
4824      const self = {
4825        doc,
4826        settings,
4827        win,
4828        files,
4829        stdMode,
4830        boxModel,
4831        styleSheetLoader,
4832        boundEvents,
4833        styles,
4834        schema,
4835        events,
4836        isBlock: isBlock,
4837        root: null,
4838        clone,
4839        getRoot,
4840        getViewPort,
4841        getRect,
4842        getSize,
4843        getParent,
4844        getParents: getParents,
4845        get,
4846        getNext,
4847        getPrev,
4848        select,
4849        is,
4850        add,
4851        create,
4852        createHTML,
4853        createFragment,
4854        remove,
4855        setStyle,
4856        getStyle: getStyle,
4857        setStyles,
4858        removeAllAttribs,
4859        setAttrib,
4860        setAttribs,
4861        getAttrib,
4862        getPos: getPos$1,
4863        parseStyle,
4864        serializeStyle,
4865        addStyle,
4866        loadCSS,
4867        addClass,
4868        removeClass,
4869        hasClass,
4870        toggleClass,
4871        show,
4872        hide,
4873        isHidden,
4874        uniqueId,
4875        setHTML,
4876        getOuterHTML,
4877        setOuterHTML,
4878        decode,
4879        encode,
4880        insertAfter,
4881        replace,
4882        rename,
4883        findCommonAncestor,
4884        run,
4885        getAttribs,
4886        isEmpty,
4887        createRng,
4888        nodeIndex: findNodeIndex,
4889        split,
4890        bind: bind,
4891        unbind: unbind,
4892        fire,
4893        dispatch,
4894        getContentEditable,
4895        getContentEditableParent,
4896        isEditable,
4897        destroy,
4898        isChildOf,
4899        dumpRng
4900      };
4901      const attrHooks = setupAttrHooks(styles, settings, constant(self));
4902      return self;
4903    };
4904    DOMUtils.DOM = DOMUtils(document);
4905    DOMUtils.nodeIndex = findNodeIndex;
4906
4907    const DOM$b = DOMUtils.DOM;
4908    const QUEUED = 0;
4909    const LOADING = 1;
4910    const LOADED = 2;
4911    const FAILED = 3;
4912    class ScriptLoader {
4913      constructor(settings = {}) {
4914        this.states = {};
4915        this.queue = [];
4916        this.scriptLoadedCallbacks = {};
4917        this.queueLoadedCallbacks = [];
4918        this.loading = false;
4919        this.settings = settings;
4920      }
4921      _setReferrerPolicy(referrerPolicy) {
4922        this.settings.referrerPolicy = referrerPolicy;
4923      }
4924      loadScript(url) {
4925        return new Promise((resolve, reject) => {
4926          const dom = DOM$b;
4927          let elm;
4928          const cleanup = () => {
4929            dom.remove(id);
4930            if (elm) {
4931              elm.onerror = elm.onload = elm = null;
4932            }
4933          };
4934          const done = () => {
4935            cleanup();
4936            resolve();
4937          };
4938          const error = () => {
4939            cleanup();
4940            reject('Failed to load script: ' + url);
4941          };
4942          const id = dom.uniqueId();
4943          elm = document.createElement('script');
4944          elm.id = id;
4945          elm.type = 'text/javascript';
4946          elm.src = Tools._addCacheSuffix(url);
4947          if (this.settings.referrerPolicy) {
4948            dom.setAttrib(elm, 'referrerpolicy', this.settings.referrerPolicy);
4949          }
4950          elm.onload = done;
4951          elm.onerror = error;
4952          (document.getElementsByTagName('head')[0] || document.body).appendChild(elm);
4953        });
4954      }
4955      isDone(url) {
4956        return this.states[url] === LOADED;
4957      }
4958      markDone(url) {
4959        this.states[url] = LOADED;
4960      }
4961      add(url) {
4962        const self = this;
4963        self.queue.push(url);
4964        const state = self.states[url];
4965        if (state === undefined) {
4966          self.states[url] = QUEUED;
4967        }
4968        return new Promise((resolve, reject) => {
4969          if (!self.scriptLoadedCallbacks[url]) {
4970            self.scriptLoadedCallbacks[url] = [];
4971          }
4972          self.scriptLoadedCallbacks[url].push({
4973            resolve,
4974            reject
4975          });
4976        });
4977      }
4978      load(url) {
4979        return this.add(url);
4980      }
4981      remove(url) {
4982        delete this.states[url];
4983        delete this.scriptLoadedCallbacks[url];
4984      }
4985      loadQueue() {
4986        const queue = this.queue;
4987        this.queue = [];
4988        return this.loadScripts(queue);
4989      }
4990      loadScripts(scripts) {
4991        const self = this;
4992        const execCallbacks = (name, url) => {
4993          get$a(self.scriptLoadedCallbacks, url).each(callbacks => {
4994            each$e(callbacks, callback => callback[name](url));
4995          });
4996          delete self.scriptLoadedCallbacks[url];
4997        };
4998        const processResults = results => {
4999          const failures = filter$5(results, result => result.status === 'rejected');
5000          if (failures.length > 0) {
5001            return Promise.reject(bind$3(failures, ({reason}) => isArray$1(reason) ? reason : [reason]));
5002          } else {
5003            return Promise.resolve();
5004          }
5005        };
5006        const load = urls => Promise.allSettled(map$3(urls, url => {
5007          if (self.states[url] === LOADED) {
5008            execCallbacks('resolve', url);
5009            return Promise.resolve();
5010          } else if (self.states[url] === FAILED) {
5011            execCallbacks('reject', url);
5012            return Promise.reject(url);
5013          } else {
5014            self.states[url] = LOADING;
5015            return self.loadScript(url).then(() => {
5016              self.states[url] = LOADED;
5017              execCallbacks('resolve', url);
5018              const queue = self.queue;
5019              if (queue.length > 0) {
5020                self.queue = [];
5021                return load(queue).then(processResults);
5022              } else {
5023                return Promise.resolve();
5024              }
5025            }, () => {
5026              self.states[url] = FAILED;
5027              execCallbacks('reject', url);
5028              return Promise.reject(url);
5029            });
5030          }
5031        }));
5032        const processQueue = urls => {
5033          self.loading = true;
5034          return load(urls).then(results => {
5035            self.loading = false;
vendor: 4,081 bytes, lines 5036-5157
5036            const nextQueuedItem = self.queueLoadedCallbacks.shift();
5037            Optional.from(nextQueuedItem).each(call);
5038            return processResults(results);
5039          });
5040        };
5041        const uniqueScripts = stringArray(scripts);
5042        if (self.loading) {
5043          return new Promise((resolve, reject) => {
5044            self.queueLoadedCallbacks.push(() => processQueue(uniqueScripts).then(resolve, reject));
5045          });
5046        } else {
5047          return processQueue(uniqueScripts);
5048        }
5049      }
5050    }
5051    ScriptLoader.ScriptLoader = new ScriptLoader();
5052
5053    const Cell = initial => {
5054      let value = initial;
5055      const get = () => {
5056        return value;
5057      };
5058      const set = v => {
5059        value = v;
5060      };
5061      return {
5062        get,
5063        set
5064      };
5065    };
5066
5067    const isRaw = str => isObject(str) && has$2(str, 'raw');
5068    const isTokenised = str => isArray$1(str) && str.length > 1;
5069    const data = {};
5070    const currentCode = Cell('en');
5071    const getLanguageData = () => get$a(data, currentCode.get());
5072    const getData$1 = () => map$2(data, value => ({ ...value }));
5073    const setCode = newCode => {
5074      if (newCode) {
5075        currentCode.set(newCode);
5076      }
5077    };
5078    const getCode = () => currentCode.get();
5079    const add$1 = (code, items) => {
5080      let langData = data[code];
5081      if (!langData) {
5082        data[code] = langData = {};
5083      }
5084      each$d(items, (translation, name) => {
5085        langData[name.toLowerCase()] = translation;
5086      });
5087    };
5088    const translate = text => {
5089      const langData = getLanguageData().getOr({});
5090      const toString = obj => {
5091        if (isFunction(obj)) {
5092          return Object.prototype.toString.call(obj);
5093        }
5094        return !isEmpty(obj) ? '' + obj : '';
5095      };
5096      const isEmpty = text => text === '' || text === null || text === undefined;
5097      const getLangData = text => {
5098        const textstr = toString(text);
5099        return get$a(langData, textstr.toLowerCase()).map(toString).getOr(textstr);
5100      };
5101      const removeContext = str => str.replace(/{context:\w+}$/, '');
5102      if (isEmpty(text)) {
5103        return '';
5104      }
5105      if (isRaw(text)) {
5106        return toString(text.raw);
5107      }
5108      if (isTokenised(text)) {
5109        const values = text.slice(1);
5110        const substitued = getLangData(text[0]).replace(/\{([0-9]+)\}/g, ($1, $2) => has$2(values, $2) ? toString(values[$2]) : $1);
5111        return removeContext(substitued);
5112      }
5113      return removeContext(getLangData(text));
5114    };
5115    const isRtl$1 = () => getLanguageData().bind(items => get$a(items, '_dir')).exists(dir => dir === 'rtl');
5116    const hasCode = code => has$2(data, code);
5117    const I18n = {
5118      getData: getData$1,
5119      setCode,
5120      getCode,
5121      add: add$1,
5122      translate,
5123      isRtl: isRtl$1,
5124      hasCode
5125    };
5126
5127    const AddOnManager = () => {
5128      const items = [];
5129      const urls = {};
5130      const lookup = {};
5131      const _listeners = [];
5132      const runListeners = (name, state) => {
5133        const matchedListeners = filter$5(_listeners, listener => listener.name === name && listener.state === state);
5134        each$e(matchedListeners, listener => listener.resolve());
5135      };
5136      const isLoaded = name => has$2(urls, name);
5137      const isAdded = name => has$2(lookup, name);
5138      const get = name => {
5139        if (lookup[name]) {
5140          return lookup[name].instance;
5141        }
5142        return undefined;
5143      };
5144      const loadLanguagePack = (name, languages) => {
5145        const language = I18n.getCode();
5146        const wrappedLanguages = ',' + (languages || '') + ',';
5147        if (!language || languages && wrappedLanguages.indexOf(',' + language + ',') === -1) {
5148          return;
5149        }
5150        ScriptLoader.ScriptLoader.add(urls[name] + '/langs/' + language + '.js');
5151      };
5152      const requireLangPack = (name, languages) => {
5153        if (AddOnManager.languageLoad !== false) {
5154          if (isLoaded(name)) {
5155            loadLanguagePack(name, languages);
5156          } else {
5157            waitFor(name, 'loaded').then(() =>
vendor: 12,355 bytes, lines 5157-5541
5157 loadLanguagePack(name, languages));
5158          }
5159        }
5160      };
5161      const add = (id, addOn) => {
5162        items.push(addOn);
5163        lookup[id] = { instance: addOn };
5164        runListeners(id, 'added');
5165        return addOn;
5166      };
5167      const remove = name => {
5168        delete urls[name];
5169        delete lookup[name];
5170      };
5171      const createUrl = (baseUrl, dep) => {
5172        if (isString(dep)) {
5173          return isString(baseUrl) ? {
5174            prefix: '',
5175            resource: dep,
5176            suffix: ''
5177          } : {
5178            prefix: baseUrl.prefix,
5179            resource: dep,
5180            suffix: baseUrl.suffix
5181          };
5182        } else {
5183          return dep;
5184        }
5185      };
5186      const load = (name, addOnUrl) => {
5187        if (urls[name]) {
5188          return Promise.resolve();
5189        }
5190        let urlString = isString(addOnUrl) ? addOnUrl : addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
5191        if (urlString.indexOf('/') !== 0 && urlString.indexOf('://') === -1) {
5192          urlString = AddOnManager.baseURL + '/' + urlString;
5193        }
5194        urls[name] = urlString.substring(0, urlString.lastIndexOf('/'));
5195        const done = () => {
5196          runListeners(name, 'loaded');
5197          return Promise.resolve();
5198        };
5199        if (lookup[name]) {
5200          return done();
5201        } else {
5202          return ScriptLoader.ScriptLoader.add(urlString).then(done);
5203        }
5204      };
5205      const waitFor = (name, state = 'added') => {
5206        if (state === 'added' && isAdded(name)) {
5207          return Promise.resolve();
5208        } else if (state === 'loaded' && isLoaded(name)) {
5209          return Promise.resolve();
5210        } else {
5211          return new Promise(resolve => {
5212            _listeners.push({
5213              name,
5214              state,
5215              resolve
5216            });
5217          });
5218        }
5219      };
5220      return {
5221        items,
5222        urls,
5223        lookup,
5224        get,
5225        requireLangPack,
5226        add,
5227        remove,
5228        createUrl,
5229        load,
5230        waitFor
5231      };
5232    };
5233    AddOnManager.languageLoad = true;
5234    AddOnManager.baseURL = '';
5235    AddOnManager.PluginManager = AddOnManager();
5236    AddOnManager.ThemeManager = AddOnManager();
5237    AddOnManager.ModelManager = AddOnManager();
5238
5239    const singleton = doRevoke => {
5240      const subject = Cell(Optional.none());
5241      const revoke = () => subject.get().each(doRevoke);
5242      const clear = () => {
5243        revoke();
5244        subject.set(Optional.none());
5245      };
5246      const isSet = () => subject.get().isSome();
5247      const get = () => subject.get();
5248      const set = s => {
5249        revoke();
5250        subject.set(Optional.some(s));
5251      };
5252      return {
5253        clear,
5254        isSet,
5255        get,
5256        set
5257      };
5258    };
5259    const repeatable = delay => {
5260      const intervalId = Cell(Optional.none());
5261      const revoke = () => intervalId.get().each(id => clearInterval(id));
5262      const clear = () => {
5263        revoke();
5264        intervalId.set(Optional.none());
5265      };
5266      const isSet = () => intervalId.get().isSome();
5267      const get = () => intervalId.get();
5268      const set = functionToRepeat => {
5269        revoke();
5270        intervalId.set(Optional.some(setInterval(functionToRepeat, delay)));
5271      };
5272      return {
5273        clear,
5274        isSet,
5275        get,
5276        set
5277      };
5278    };
5279    const value$2 = () => {
5280      const subject = singleton(noop);
5281      const on = f => subject.get().each(f);
5282      return {
5283        ...subject,
5284        on
5285      };
5286    };
5287
5288    const first$1 = (fn, rate) => {
5289      let timer = null;
5290      const cancel = () => {
5291        if (!isNull(timer)) {
5292          clearTimeout(timer);
5293          timer = null;
5294        }
5295      };
5296      const throttle = (...args) => {
5297        if (isNull(timer)) {
5298          timer = setTimeout(() => {
5299            timer = null;
5300            fn.apply(null, args);
5301          }, rate);
5302        }
5303      };
5304      return {
5305        cancel,
5306        throttle
5307      };
5308    };
5309    const last$1 = (fn, rate) => {
5310      let timer = null;
5311      const cancel = () => {
5312        if (!isNull(timer)) {
5313          clearTimeout(timer);
5314          timer = null;
5315        }
5316      };
5317      const throttle = (...args) => {
5318        cancel();
5319        timer = setTimeout(() => {
5320          timer = null;
5321          fn.apply(null, args);
5322        }, rate);
5323      };
5324      return {
5325        cancel,
5326        throttle
5327      };
5328    };
5329
5330    const annotation = constant('mce-annotation');
5331    const dataAnnotation = constant('data-mce-annotation');
5332    const dataAnnotationId = constant('data-mce-annotation-uid');
5333    const dataAnnotationActive = constant('data-mce-annotation-active');
5334    const dataAnnotationClasses = constant('data-mce-annotation-classes');
5335    const dataAnnotationAttributes = constant('data-mce-annotation-attrs');
5336
5337    const isRoot$1 = root => node => eq(node, root);
5338    const identify = (editor, annotationName) => {
5339      const rng = editor.selection.getRng();
5340      const start = SugarElement.fromDom(rng.startContainer);
5341      const root = SugarElement.fromDom(editor.getBody());
5342      const selector = annotationName.fold(() => '.' + annotation(), an => `[${ dataAnnotation() }="${ an }"]`);
5343      const newStart = child$1(start, rng.startOffset).getOr(start);
5344      const closest = closest$3(newStart, selector, isRoot$1(root));
5345      return closest.bind(c => getOpt(c, `${ dataAnnotationId() }`).bind(uid => getOpt(c, `${ dataAnnotation() }`).map(name => {
5346        const elements = findMarkers(editor, uid);
5347        return {
5348          uid,
5349          name,
5350          elements
5351        };
5352      })));
5353    };
5354    const isAnnotation = elem => isElement$7(elem) && has(elem, annotation());
5355    const isBogusElement = (elem, root) => has$1(elem, 'data-mce-bogus') || ancestor$2(elem, '[data-mce-bogus="all"]', isRoot$1(root));
5356    const findMarkers = (editor, uid) => {
5357      const body = SugarElement.fromDom(editor.getBody());
5358      const descendants$1 = descendants(body, `[${ dataAnnotationId() }="${ uid }"]`);
5359      return filter$5(descendants$1, descendant => !isBogusElement(descendant, body));
5360    };
5361    const findAll = (editor, name) => {
5362      const body = SugarElement.fromDom(editor.getBody());
5363      const markers = descendants(body, `[${ dataAnnotation() }="${ name }"]`);
5364      const directory = {};
5365      each$e(markers, m => {
5366        if (!isBogusElement(m, body)) {
5367          const uid = get$9(m, dataAnnotationId());
5368          const nodesAlready = get$a(directory, uid).getOr([]);
5369          directory[uid] = nodesAlready.concat([m]);
5370        }
5371      });
5372      return directory;
5373    };
5374
5375    const setup$x = (editor, registry) => {
5376      const changeCallbacks = Cell({});
5377      const initData = () => ({
5378        listeners: [],
5379        previous: value$2()
5380      });
5381      const withCallbacks = (name, f) => {
5382        updateCallbacks(name, data => {
5383          f(data);
5384          return data;
5385        });
5386      };
5387      const updateCallbacks = (name, f) => {
5388        const callbackMap = changeCallbacks.get();
5389        const data = get$a(callbackMap, name).getOrThunk(initData);
5390        const outputData = f(data);
5391        callbackMap[name] = outputData;
5392        changeCallbacks.set(callbackMap);
5393      };
5394      const fireCallbacks = (name, uid, elements) => {
5395        withCallbacks(name, data => {
5396          each$e(data.listeners, f => f(true, name, {
5397            uid,
5398            nodes: map$3(elements, elem => elem.dom)
5399          }));
5400        });
5401      };
5402      const fireNoAnnotation = name => {
5403        withCallbacks(name, data => {
5404          each$e(data.listeners, f => f(false, name));
5405        });
5406      };
5407      const toggleActiveAttr = (uid, state) => {
5408        each$e(findMarkers(editor, uid), elem => {
5409          if (state) {
5410            set$3(elem, dataAnnotationActive(), 'true');
5411          } else {
5412            remove$b(elem, dataAnnotationActive());
5413          }
5414        });
5415      };
5416      const onNodeChange = last$1(() => {
5417        const annotations = sort(registry.getNames());
5418        each$e(annotations, name => {
5419          updateCallbacks(name, data => {
5420            const prev = data.previous.get();
5421            identify(editor, Optional.some(name)).fold(() => {
5422              prev.each(uid => {
5423                fireNoAnnotation(name);
5424                data.previous.clear();
5425                toggleActiveAttr(uid, false);
5426              });
5427            }, ({uid, name, elements}) => {
5428              if (!is$2(prev, uid)) {
5429                prev.each(uid => toggleActiveAttr(uid, false));
5430                fireCallbacks(name, uid, elements);
5431                data.previous.set(uid);
5432                toggleActiveAttr(uid, true);
5433              }
5434            });
5435            return {
5436              previous: data.previous,
5437              listeners: data.listeners
5438            };
5439          });
5440        });
5441      }, 30);
5442      editor.on('remove', () => {
5443        onNodeChange.cancel();
5444      });
5445      editor.on('NodeChange', () => {
5446        onNodeChange.throttle();
5447      });
5448      const addListener = (name, f) => {
5449        updateCallbacks(name, data => ({
5450          previous: data.previous,
5451          listeners: data.listeners.concat([f])
5452        }));
5453      };
5454      return { addListener };
5455    };
5456
5457    const setup$w = (editor, registry) => {
5458      const dataAnnotation$1 = dataAnnotation();
5459      const identifyParserNode = node => Optional.from(node.attr(dataAnnotation$1)).bind(registry.lookup);
5460      const removeDirectAnnotation = node => {
5461        var _a, _b;
5462        node.attr(dataAnnotationId(), null);
5463        node.attr(dataAnnotation(), null);
5464        node.attr(dataAnnotationActive(), null);
5465        const customAttrNames = Optional.from(node.attr(dataAnnotationAttributes())).map(names => names.split(',')).getOr([]);
5466        const customClasses = Optional.from(node.attr(dataAnnotationClasses())).map(names => names.split(',')).getOr([]);
5467        each$e(customAttrNames, name => node.attr(name, null));
5468        const classList = (_b = (_a = node.attr('class')) === null || _a === void 0 ? void 0 : _a.split(' ')) !== null && _b !== void 0 ? _b : [];
5469        const newClassList = difference(classList, [annotation()].concat(customClasses));
5470        node.attr('class', newClassList.length > 0 ? newClassList.join(' ') : null);
5471        node.attr(dataAnnotationClasses(), null);
5472        node.attr(dataAnnotationAttributes(), null);
5473      };
5474      editor.serializer.addTempAttr(dataAnnotationActive());
5475      editor.serializer.addAttributeFilter(dataAnnotation$1, nodes => {
5476        for (const node of nodes) {
5477          identifyParserNode(node).each(settings => {
5478            if (settings.persistent === false) {
5479              if (node.name === 'span') {
5480                node.unwrap();
5481              } else {
5482                removeDirectAnnotation(node);
5483              }
5484            }
5485          });
5486        }
5487      });
5488    };
5489
5490    const create$c = () => {
5491      const annotations = {};
5492      const register = (name, settings) => {
5493        annotations[name] = {
5494          name,
5495          settings
5496        };
5497      };
5498      const lookup = name => get$a(annotations, name).map(a => a.settings);
5499      const getNames = () => keys(annotations);
5500      return {
5501        register,
5502        lookup,
5503        getNames
5504      };
5505    };
5506
5507    let unique = 0;
5508    const generate$1 = prefix => {
5509      const date = new Date();
5510      const time = date.getTime();
5511      const random = Math.floor(Math.random() * 1000000000);
5512      unique++;
5513      return prefix + '_' + random + unique + String(time);
5514    };
5515
5516    const add = (element, classes) => {
5517      each$e(classes, x => {
5518        add$2(element, x);
5519      });
5520    };
5521    const remove$5 = (element, classes) => {
5522      each$e(classes, x => {
5523        remove$8(element, x);
5524      });
5525    };
5526
5527    const clone$2 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
5528    const shallow$1 = original => clone$2(original, false);
5529    const deep$1 = original => clone$2(original, true);
5530    const shallowAs = (original, tag) => {
5531      const nu = SugarElement.fromTag(tag);
5532      const attributes = clone$4(original);
5533      setAll$1(nu, attributes);
5534      return nu;
5535    };
5536    const mutate = (original, tag) => {
5537      const nu = shallowAs(original, tag);
5538      after$4(original, nu);
5539      const children = children$1(original);
5540      append(nu, children);
5541      remove$6
vendor: 45,163 bytes, lines 5541-6802
5541(original);
5542      return nu;
5543    };
5544
5545    const TextWalker = (startNode, rootNode, isBoundary = never) => {
5546      const walker = new DomTreeWalker(startNode, rootNode);
5547      const walk = direction => {
5548        let next;
5549        do {
5550          next = walker[direction]();
5551        } while (next && !isText$a(next) && !isBoundary(next));
5552        return Optional.from(next).filter(isText$a);
5553      };
5554      return {
5555        current: () => Optional.from(walker.current()).filter(isText$a),
5556        next: () => walk('next'),
5557        prev: () => walk('prev'),
5558        prev2: () => walk('prev2')
5559      };
5560    };
5561
5562    const TextSeeker = (dom, isBoundary) => {
5563      const isBlockBoundary = isBoundary ? isBoundary : node => dom.isBlock(node) || isBr$6(node) || isContentEditableFalse$b(node);
5564      const walk = (node, offset, walker, process) => {
5565        if (isText$a(node)) {
5566          const newOffset = process(node, offset, node.data);
5567          if (newOffset !== -1) {
5568            return Optional.some({
5569              container: node,
5570              offset: newOffset
5571            });
5572          }
5573        }
5574        return walker().bind(next => walk(next.container, next.offset, walker, process));
5575      };
5576      const backwards = (node, offset, process, root) => {
5577        const walker = TextWalker(node, root !== null && root !== void 0 ? root : dom.getRoot(), isBlockBoundary);
5578        return walk(node, offset, () => walker.prev().map(prev => ({
5579          container: prev,
5580          offset: prev.length
5581        })), process).getOrNull();
5582      };
5583      const forwards = (node, offset, process, root) => {
5584        const walker = TextWalker(node, root !== null && root !== void 0 ? root : dom.getRoot(), isBlockBoundary);
5585        return walk(node, offset, () => walker.next().map(next => ({
5586          container: next,
5587          offset: 0
5588        })), process).getOrNull();
5589      };
5590      return {
5591        backwards,
5592        forwards
5593      };
5594    };
5595
5596    const round$2 = Math.round;
5597    const clone$1 = rect => {
5598      if (!rect) {
5599        return {
5600          left: 0,
5601          top: 0,
5602          bottom: 0,
5603          right: 0,
5604          width: 0,
5605          height: 0
5606        };
5607      }
5608      return {
5609        left: round$2(rect.left),
5610        top: round$2(rect.top),
5611        bottom: round$2(rect.bottom),
5612        right: round$2(rect.right),
5613        width: round$2(rect.width),
5614        height: round$2(rect.height)
5615      };
5616    };
5617    const collapse = (rect, toStart) => {
5618      rect = clone$1(rect);
5619      if (toStart) {
5620        rect.right = rect.left;
5621      } else {
5622        rect.left = rect.left + rect.width;
5623        rect.right = rect.left;
5624      }
5625      rect.width = 0;
5626      return rect;
5627    };
5628    const isEqual = (rect1, rect2) => rect1.left === rect2.left && rect1.top === rect2.top && rect1.bottom === rect2.bottom && rect1.right === rect2.right;
5629    const isValidOverflow = (overflowY, rect1, rect2) => overflowY >= 0 && overflowY <= Math.min(rect1.height, rect2.height) / 2;
5630    const isAbove$1 = (rect1, rect2) => {
5631      const halfHeight = Math.min(rect2.height / 2, rect1.height / 2);
5632      if (rect1.bottom - halfHeight < rect2.top) {
5633        return true;
5634      }
5635      if (rect1.top > rect2.bottom) {
5636        return false;
5637      }
5638      return isValidOverflow(rect2.top - rect1.bottom, rect1, rect2);
5639    };
5640    const isBelow$1 = (rect1, rect2) => {
5641      if (rect1.top > rect2.bottom) {
5642        return true;
5643      }
5644      if (rect1.bottom < rect2.top) {
5645        return false;
5646      }
5647      return isValidOverflow(rect2.bottom - rect1.top, rect1, rect2);
5648    };
5649    const containsXY = (rect, clientX, clientY) => clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
5650    const boundingClientRectFromRects = rects => {
5651      return foldl(rects, (acc, rect) => {
5652        return acc.fold(() => Optional.some(rect), prevRect => {
5653          const left = Math.min(rect.left, prevRect.left);
5654          const top = Math.min(rect.top, prevRect.top);
5655          const right = Math.max(rect.right, prevRect.right);
5656          const bottom = Math.max(rect.bottom, prevRect.bottom);
5657          return Optional.some({
5658            top,
5659            right,
5660            bottom,
5661            left,
5662            width: right - left,
5663            height: bottom - top
5664          });
5665        });
5666      }, Optional.none());
5667    };
5668    const distanceToRectEdgeFromXY = (rect, x, y) => {
5669      const cx = Math.max(Math.min(x, rect.left + rect.width), rect.left);
5670      const cy = Math.max(Math.min(y, rect.top + rect.height), rect.top);
5671      return Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
5672    };
5673    const overlapY = (r1, r2) => Math.max(0, Math.min(r1.bottom, r2.bottom) - Math.max(r1.top, r2.top));
5674
5675    const clamp$2 = (value, min, max) => Math.min(Math.max(value, min), max);
5676
5677    const getSelectedNode = range => {
5678      const startContainer = range.startContainer, startOffset = range.startOffset;
5679      if (startContainer === range.endContainer && startContainer.hasChildNodes() && range.endOffset === startOffset + 1) {
5680        return startContainer.childNodes[startOffset];
5681      }
5682      return null;
5683    };
5684    const getNode$1 = (container, offset) => {
5685      if (isElement$6(container) && container.hasChildNodes()) {
5686        const childNodes = container.childNodes;
5687        const safeOffset = clamp$2(offset, 0, childNodes.length - 1);
5688        return childNodes[safeOffset];
5689      } else {
5690        return container;
5691      }
5692    };
5693    const getNodeUnsafe = (container, offset) => {
5694      if (offset < 0 && isElement$6(container) && container.hasChildNodes()) {
5695        return undefined;
5696      } else {
5697        return getNode$1(container, offset);
5698      }
5699    };
5700
5701    const extendingChars = new RegExp('[\u0300-\u036f\u0483-\u0487\u0488-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a' + '\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0' + '\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0902\u093a\u093c' + '\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2-\u09e3' + '\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc' + '\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57' + '\u0b62-\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c00\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56' + '\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d01\u0d3e\u0d41-\u0d44' + '\u0d4d\u0d57\u0d62-\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9' + '\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97' + '\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074' + '\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5' + '\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18' + '\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1ABE\u1b00-\u1b03\u1b34' + '\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9' + '\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9' + '\u1dc0-\u1df5\u1dfc-\u1dff\u200c-\u200d\u20d0-\u20dc\u20DD-\u20E0\u20e1\u20E2-\u20E4\u20e5-\u20f0\u2cef-\u2cf1' + '\u2d7f\u2de0-\u2dff\u302a-\u302d\u302e-\u302f\u3099-\u309a\ua66f\uA670-\uA672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1' + '\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc' + '\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1' + '\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f]');
5702    const isExtendingChar = ch => isString(ch) && ch.charCodeAt(0) >= 768 && extendingChars.test(ch);
5703
5704    const or = (...args) => {
5705      return x => {
5706        for (let i = 0; i < args.length; i++) {
5707          if (args[i](x)) {
5708            return true;
5709          }
5710        }
5711        return false;
5712      };
5713    };
5714    const and = (...args) => {
5715      return x => {
5716        for (let i = 0; i < args.length; i++) {
5717          if (!args[i](x)) {
5718            return false;
5719          }
5720        }
5721        return true;
5722      };
5723    };
5724
5725    const isElement$4 = isElement$6;
5726    const isCaretCandidate$2 = isCaretCandidate$3;
5727    const isBlock$1 = matchStyleValues('display', 'block table');
5728    const isFloated = matchStyleValues('float', 'left right');
5729    const isValidElementCaretCandidate = and(isElement$4, isCaretCandidate$2, not(isFloated));
5730    const isNotPre = not(matchStyleValues('white-space', 'pre pre-line pre-wrap'));
5731    const isText$7 = isText$a;
5732    const isBr$3 = isBr$6;
5733    const nodeIndex$1 = DOMUtils.nodeIndex;
5734    const resolveIndex$1 = getNodeUnsafe;
5735    const createRange$1 = doc => doc ? doc.createRange() : DOMUtils.DOM.createRng();
5736    const isWhiteSpace$1 = chr => isString(chr) && /[\r\n\t ]/.test(chr);
5737    const isRange = rng => !!rng.setStart && !!rng.setEnd;
5738    const isHiddenWhiteSpaceRange = range => {
5739      const container = range.startContainer;
5740      const offset = range.startOffset;
5741      if (isWhiteSpace$1(range.toString()) && isNotPre(container.parentNode) && isText$a(container)) {
5742        const text = container.data;
5743        if (isWhiteSpace$1(text[offset - 1]) || isWhiteSpace$1(text[offset + 1])) {
5744          return true;
5745        }
5746      }
5747      return false;
5748    };
5749    const getBrClientRect = brNode => {
5750      const doc = brNode.ownerDocument;
5751      const rng = createRange$1(doc);
5752      const nbsp$1 = doc.createTextNode(nbsp);
5753      const parentNode = brNode.parentNode;
5754      parentNode.insertBefore(nbsp$1, brNode);
5755      rng.setStart(nbsp$1, 0);
5756      rng.setEnd(nbsp$1, 1);
5757      const clientRect = clone$1(rng.getBoundingClientRect());
5758      parentNode.removeChild(nbsp$1);
5759      return clientRect;
5760    };
5761    const getBoundingClientRectWebKitText = rng => {
5762      const sc = rng.startContainer;
5763      const ec = rng.endContainer;
5764      const so = rng.startOffset;
5765      const eo = rng.endOffset;
5766      if (sc === ec && isText$a(ec) && so === 0 && eo === 1) {
5767        const newRng = rng.cloneRange();
5768        newRng.setEndAfter(ec);
5769        return getBoundingClientRect$1(newRng);
5770      } else {
5771        return null;
5772      }
5773    };
5774    const isZeroRect = r => r.left === 0 && r.right === 0 && r.top === 0 && r.bottom === 0;
5775    const getBoundingClientRect$1 = item => {
5776      var _a;
5777      let clientRect;
5778      const clientRects = item.getClientRects();
5779      if (clientRects.length > 0) {
5780        clientRect = clone$1(clientRects[0]);
5781      } else {
5782        clientRect = clone$1(item.getBoundingClientRect());
5783      }
5784      if (!isRange(item) && isBr$3(item) && isZeroRect(clientRect)) {
5785        return getBrClientRect(item);
5786      }
5787      if (isZeroRect(clientRect) && isRange(item)) {
5788        return (_a = getBoundingClientRectWebKitText(item)) !== null && _a !== void 0 ? _a : clientRect;
5789      }
5790      return clientRect;
5791    };
5792    const collapseAndInflateWidth = (clientRect, toStart) => {
5793      const newClientRect = collapse(clientRect, toStart);
5794      newClientRect.width = 1;
5795      newClientRect.right = newClientRect.left + 1;
5796      return newClientRect;
5797    };
5798    const getCaretPositionClientRects = caretPosition => {
5799      const clientRects = [];
5800      const addUniqueAndValidRect = clientRect => {
5801        if (clientRect.height === 0) {
5802          return;
5803        }
5804        if (clientRects.length > 0) {
5805          if (isEqual(clientRect, clientRects[clientRects.length - 1])) {
5806            return;
5807          }
5808        }
5809        clientRects.push(clientRect);
5810      };
5811      const addCharacterOffset = (container, offset) => {
5812        const range = createRange$1(container.ownerDocument);
5813        if (offset < container.data.length) {
5814          if (isExtendingChar(container.data[offset])) {
5815            return;
5816          }
5817          if (isExtendingChar(container.data[offset - 1])) {
5818            range.setStart(container, offset);
5819            range.setEnd(container, offset + 1);
5820            if (!isHiddenWhiteSpaceRange(range)) {
5821              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), false));
5822              return;
5823            }
5824          }
5825        }
5826        if (offset > 0) {
5827          range.setStart(container, offset - 1);
5828          range.setEnd(container, offset);
5829          if (!isHiddenWhiteSpaceRange(range)) {
5830            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), false));
5831          }
5832        }
5833        if (offset < container.data.length) {
5834          range.setStart(container, offset);
5835          range.setEnd(container, offset + 1);
5836          if (!isHiddenWhiteSpaceRange(range)) {
5837            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), true));
5838          }
5839        }
5840      };
5841      const container = caretPosition.container();
5842      const offset = caretPosition.offset();
5843      if (isText$7(container)) {
5844        addCharacterOffset(container, offset);
5845        return clientRects;
5846      }
5847      if (isElement$4(container)) {
5848        if (caretPosition.isAtEnd()) {
5849          const node = resolveIndex$1(container, offset);
5850          if (isText$7(node)) {
5851            addCharacterOffset(node, node.data.length);
5852          }
5853          if (isValidElementCaretCandidate(node) && !isBr$3(node)) {
5854            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), false));
5855          }
5856        } else {
5857          const node = resolveIndex$1(container, offset);
5858          if (isText$7(node)) {
5859            addCharacterOffset(node, 0);
5860          }
5861          if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) {
5862            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), false));
5863            return clientRects;
5864          }
5865          const beforeNode = resolveIndex$1(caretPosition.container(), caretPosition.offset() - 1);
5866          if (isValidElementCaretCandidate(beforeNode) && !isBr$3(beforeNode)) {
5867            if (isBlock$1(beforeNode) || isBlock$1(node) || !isValidElementCaretCandidate(node)) {
5868              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(beforeNode), false));
5869            }
5870          }
5871          if (isValidElementCaretCandidate(node)) {
5872            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), true));
5873          }
5874        }
5875      }
5876      return clientRects;
5877    };
5878    const CaretPosition = (container, offset, clientRects) => {
5879      const isAtStart = () => {
5880        if (isText$7(container)) {
5881          return offset === 0;
5882        }
5883        return offset === 0;
5884      };
5885      const isAtEnd = () => {
5886        if (isText$7(container)) {
5887          return offset >= container.data.length;
5888        }
5889        return offset >= container.childNodes.length;
5890      };
5891      const toRange = () => {
5892        const range = createRange$1(container.ownerDocument);
5893        range.setStart(container, offset);
5894        range.setEnd(container, offset);
5895        return range;
5896      };
5897      const getClientRects = () => {
5898        if (!clientRects) {
5899          clientRects = getCaretPositionClientRects(CaretPosition(container, offset));
5900        }
5901        return clientRects;
5902      };
5903      const isVisible = () => getClientRects().length > 0;
5904      const isEqual = caretPosition => caretPosition && container === caretPosition.container() && offset === caretPosition.offset();
5905      const getNode = before => resolveIndex$1(container, before ? offset - 1 : offset);
5906      return {
5907        container: constant(container),
5908        offset: constant(offset),
5909        toRange,
5910        getClientRects,
5911        isVisible,
5912        isAtStart,
5913        isAtEnd,
5914        isEqual,
5915        getNode
5916      };
5917    };
5918    CaretPosition.fromRangeStart = range => CaretPosition(range.startContainer, range.startOffset);
5919    CaretPosition.fromRangeEnd = range => CaretPosition(range.endContainer, range.endOffset);
5920    CaretPosition.after = node => CaretPosition(node.parentNode, nodeIndex$1(node) + 1);
5921    CaretPosition.before = node => CaretPosition(node.parentNode, nodeIndex$1(node));
5922    CaretPosition.isAbove = (pos1, pos2) => lift2(head(pos2.getClientRects()), last$3(pos1.getClientRects()), isAbove$1).getOr(false);
5923    CaretPosition.isBelow = (pos1, pos2) => lift2(last$3(pos2.getClientRects()), head(pos1.getClientRects()), isBelow$1).getOr(false);
5924    CaretPosition.isAtStart = pos => pos ? pos.isAtStart() : false;
5925    CaretPosition.isAtEnd = pos => pos ? pos.isAtEnd() : false;
5926    CaretPosition.isTextPosition = pos => pos ? isText$a(pos.container()) : false;
5927    CaretPosition.isElementPosition = pos => !CaretPosition.isTextPosition(pos);
5928
5929    const trimEmptyTextNode$1 = (dom, node) => {
5930      if (isText$a(node) && node.data.length === 0) {
5931        dom.remove(node);
5932      }
5933    };
5934    const insertNode = (dom, rng, node) => {
5935      rng.insertNode(node);
5936      trimEmptyTextNode$1(dom, node.previousSibling);
5937      trimEmptyTextNode$1(dom, node.nextSibling);
5938    };
5939    const insertFragment = (dom, rng, frag) => {
5940      const firstChild = Optional.from(frag.firstChild);
5941      const lastChild = Optional.from(frag.lastChild);
5942      rng.insertNode(frag);
5943      firstChild.each(child => trimEmptyTextNode$1(dom, child.previousSibling));
5944      lastChild.each(child => trimEmptyTextNode$1(dom, child.nextSibling));
5945    };
5946    const rangeInsertNode = (dom, rng, node) => {
5947      if (isDocumentFragment(node)) {
5948        insertFragment(dom, rng, node);
5949      } else {
5950        insertNode(dom, rng, node);
5951      }
5952    };
5953
5954    const isText$6 = isText$a;
5955    const isBogus = isBogus$2;
5956    const nodeIndex = DOMUtils.nodeIndex;
5957    const normalizedParent = node => {
5958      const parentNode = node.parentNode;
5959      if (isBogus(parentNode)) {
5960        return normalizedParent(parentNode);
5961      }
5962      return parentNode;
5963    };
5964    const getChildNodes = node => {
5965      if (!node) {
5966        return [];
5967      }
5968      return reduce(node.childNodes, (result, node) => {
5969        if (isBogus(node) && node.nodeName !== 'BR') {
5970          result = result.concat(getChildNodes(node));
5971        } else {
5972          result.push(node);
5973        }
5974        return result;
5975      }, []);
5976    };
5977    const normalizedTextOffset = (node, offset) => {
5978      let tempNode = node;
5979      while (tempNode = tempNode.previousSibling) {
5980        if (!isText$6(tempNode)) {
5981          break;
5982        }
5983        offset += tempNode.data.length;
5984      }
5985      return offset;
5986    };
5987    const equal = a => b => a === b;
5988    const normalizedNodeIndex = node => {
5989      let nodes, index;
5990      nodes = getChildNodes(normalizedParent(node));
5991      index = findIndex$1(nodes, equal(node), node);
5992      nodes = nodes.slice(0, index + 1);
5993      const numTextFragments = reduce(nodes, (result, node, i) => {
5994        if (isText$6(node) && isText$6(nodes[i - 1])) {
5995          result++;
5996        }
5997        return result;
5998      }, 0);
5999      nodes = filter$3(nodes, matchNodeNames([node.nodeName]));
6000      index = findIndex$1(nodes, equal(node), node);
6001      return index - numTextFragments;
6002    };
6003    const createPathItem = node => {
6004      const name = isText$6(node) ? 'text()' : node.nodeName.toLowerCase();
6005      return name + '[' + normalizedNodeIndex(node) + ']';
6006    };
6007    const parentsUntil$1 = (root, node, predicate) => {
6008      const parents = [];
6009      for (let tempNode = node.parentNode; tempNode && tempNode !== root; tempNode = tempNode.parentNode) {
6010        if (predicate && predicate(tempNode)) {
6011          break;
6012        }
6013        parents.push(tempNode);
6014      }
6015      return parents;
6016    };
6017    const create$b = (root, caretPosition) => {
6018      let path = [];
6019      let container = caretPosition.container();
6020      let offset = caretPosition.offset();
6021      let outputOffset;
6022      if (isText$6(container)) {
6023        outputOffset = normalizedTextOffset(container, offset);
6024      } else {
6025        const childNodes = container.childNodes;
6026        if (offset >= childNodes.length) {
6027          outputOffset = 'after';
6028          offset = childNodes.length - 1;
6029        } else {
6030          outputOffset = 'before';
6031        }
6032        container = childNodes[offset];
6033      }
6034      path.push(createPathItem(container));
6035      let parents = parentsUntil$1(root, container);
6036      parents = filter$3(parents, not(isBogus$2));
6037      path = path.concat(map$1(parents, node => {
6038        return createPathItem(node);
6039      }));
6040      return path.reverse().join('/') + ',' + outputOffset;
6041    };
6042    const resolvePathItem = (node, name, index) => {
6043      let nodes = getChildNodes(node);
6044      nodes = filter$3(nodes, (node, index) => {
6045        return !isText$6(node) || !isText$6(nodes[index - 1]);
6046      });
6047      nodes = filter$3(nodes, matchNodeNames([name]));
6048      return nodes[index];
6049    };
6050    const findTextPosition = (container, offset) => {
6051      let node = container;
6052      let targetOffset = 0;
6053      while (isText$6(node)) {
6054        const dataLen = node.data.length;
6055        if (offset >= targetOffset && offset <= targetOffset + dataLen) {
6056          container = node;
6057          offset = offset - targetOffset;
6058          break;
6059        }
6060        if (!isText$6(node.nextSibling)) {
6061          container = node;
6062          offset = dataLen;
6063          break;
6064        }
6065        targetOffset += dataLen;
6066        node = node.nextSibling;
6067      }
6068      if (isText$6(container) && offset > container.data.length) {
6069        offset = container.data.length;
6070      }
6071      return CaretPosition(container, offset);
6072    };
6073    const resolve$1 = (root, path) => {
6074      if (!path) {
6075        return null;
6076      }
6077      const parts = path.split(',');
6078      const paths = parts[0].split('/');
6079      const offset = parts.length > 1 ? parts[1] : 'before';
6080      const container = reduce(paths, (result, value) => {
6081        const match = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value);
6082        if (!match) {
6083          return null;
6084        }
6085        if (match[1] === 'text()') {
6086          match[1] = '#text';
6087        }
6088        return resolvePathItem(result, match[1], parseInt(match[2], 10));
6089      }, root);
6090      if (!container) {
6091        return null;
6092      }
6093      if (!isText$6(container) && container.parentNode) {
6094        let nodeOffset;
6095        if (offset === 'after') {
6096          nodeOffset = nodeIndex(container) + 1;
6097        } else {
6098          nodeOffset = nodeIndex(container);
6099        }
6100        return CaretPosition(container.parentNode, nodeOffset);
6101      }
6102      return findTextPosition(container, parseInt(offset, 10));
6103    };
6104
6105    const isContentEditableFalse$9 = isContentEditableFalse$b;
6106    const getNormalizedTextOffset$1 = (trim, container, offset) => {
6107      let trimmedOffset = trim(container.data.slice(0, offset)).length;
6108      for (let node = container.previousSibling; node && isText$a(node); node = node.previousSibling) {
6109        trimmedOffset += trim(node.data).length;
6110      }
6111      return trimmedOffset;
6112    };
6113    const getPoint = (dom, trim, normalized, rng, start) => {
6114      const container = start ? rng.startContainer : rng.endContainer;
6115      let offset = start ? rng.startOffset : rng.endOffset;
6116      const point = [];
6117      const root = dom.getRoot();
6118      if (isText$a(container)) {
6119        point.push(normalized ? getNormalizedTextOffset$1(trim, container, offset) : offset);
6120      } else {
6121        let after = 0;
6122        const childNodes = container.childNodes;
6123        if (offset >= childNodes.length && childNodes.length) {
6124          after = 1;
6125          offset = Math.max(0, childNodes.length - 1);
6126        }
6127        point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
6128      }
6129      for (let node = container; node && node !== root; node = node.parentNode) {
6130        point.push(dom.nodeIndex(node, normalized));
6131      }
6132      return point;
6133    };
6134    const getLocation = (trim, selection, normalized, rng) => {
6135      const dom = selection.dom;
6136      const start = getPoint(dom, trim, normalized, rng, true);
6137      const forward = selection.isForward();
6138      const fakeCaret = isRangeInCaretContainerBlock(rng) ? { isFakeCaret: true } : {};
6139      if (!selection.isCollapsed()) {
6140        const end = getPoint(dom, trim, normalized, rng, false);
6141        return {
6142          start,
6143          end,
6144          forward,
6145          ...fakeCaret
6146        };
6147      } else {
6148        return {
6149          start,
6150          forward,
6151          ...fakeCaret
6152        };
6153      }
6154    };
6155    const findIndex = (dom, name, element) => {
6156      let count = 0;
6157      Tools.each(dom.select(name), node => {
6158        if (node.getAttribute('data-mce-bogus') === 'all') {
6159          return;
6160        } else if (node === element) {
6161          return false;
6162        } else {
6163          count++;
6164          return;
6165        }
6166      });
6167      return count;
6168    };
6169    const moveEndPoint$1 = (rng, start) => {
6170      let container = start ? rng.startContainer : rng.endContainer;
6171      let offset = start ? rng.startOffset : rng.endOffset;
6172      if (isElement$6(container) && container.nodeName === 'TR') {
6173        const childNodes = container.childNodes;
6174        container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
6175        if (container) {
6176          offset = start ? 0 : container.childNodes.length;
6177          if (start) {
6178            rng.setStart(container, offset);
6179          } else {
6180            rng.setEnd(container, offset);
6181          }
6182        }
6183      }
6184    };
6185    const normalizeTableCellSelection = rng => {
6186      moveEndPoint$1(rng, true);
6187      moveEndPoint$1(rng, false);
6188      return rng;
6189    };
6190    const findSibling = (node, offset) => {
6191      if (isElement$6(node)) {
6192        node = getNode$1(node, offset);
6193        if (isContentEditableFalse$9(node)) {
6194          return node;
6195        }
6196      }
6197      if (isCaretContainer$2(node)) {
6198        if (isText$a(node) && isCaretContainerBlock$1(node)) {
6199          node = node.parentNode;
6200        }
6201        let sibling = node.previousSibling;
6202        if (isContentEditableFalse$9(sibling)) {
6203          return sibling;
6204        }
6205        sibling = node.nextSibling;
6206        if (isContentEditableFalse$9(sibling)) {
6207          return sibling;
6208        }
6209      }
6210      return undefined;
6211    };
6212    const findAdjacentContentEditableFalseElm = rng => {
6213      return findSibling(rng.startContainer, rng.startOffset) || findSibling(rng.endContainer, rng.endOffset);
6214    };
6215    const getOffsetBookmark = (trim, normalized, selection) => {
6216      const element = selection.getNode();
6217      const rng = selection.getRng();
6218      if (element.nodeName === 'IMG' || isContentEditableFalse$9(element)) {
6219        const name = element.nodeName;
6220        return {
6221          name,
6222          index: findIndex(selection.dom, name, element)
6223        };
6224      }
6225      const sibling = findAdjacentContentEditableFalseElm(rng);
6226      if (sibling) {
6227        const name = sibling.tagName;
6228        return {
6229          name,
6230          index: findIndex(selection.dom, name, sibling)
6231        };
6232      }
6233      return getLocation(trim, selection, normalized, rng);
6234    };
6235    const getCaretBookmark = selection => {
6236      const rng = selection.getRng();
6237      return {
6238        start: create$b(selection.dom.getRoot(), CaretPosition.fromRangeStart(rng)),
6239        end: create$b(selection.dom.getRoot(), CaretPosition.fromRangeEnd(rng)),
6240        forward: selection.isForward()
6241      };
6242    };
6243    const getRangeBookmark = selection => {
6244      return {
6245        rng: selection.getRng(),
6246        forward: selection.isForward()
6247      };
6248    };
6249    const createBookmarkSpan = (dom, id, filled) => {
6250      const args = {
6251        'data-mce-type': 'bookmark',
6252        id,
6253        'style': 'overflow:hidden;line-height:0px'
6254      };
6255      return filled ? dom.create('span', args, '&#xFEFF;') : dom.create('span', args);
6256    };
6257    const getPersistentBookmark = (selection, filled) => {
6258      const dom = selection.dom;
6259      let rng = selection.getRng();
6260      const id = dom.uniqueId();
6261      const collapsed = selection.isCollapsed();
6262      const element = selection.getNode();
6263      const name = element.nodeName;
6264      const forward = selection.isForward();
6265      if (name === 'IMG') {
6266        return {
6267          name,
6268          index: findIndex(dom, name, element)
6269        };
6270      }
6271      const rng2 = normalizeTableCellSelection(rng.cloneRange());
6272      if (!collapsed) {
6273        rng2.collapse(false);
6274        const endBookmarkNode = createBookmarkSpan(dom, id + '_end', filled);
6275        rangeInsertNode(dom, rng2, endBookmarkNode);
6276      }
6277      rng = normalizeTableCellSelection(rng);
6278      rng.collapse(true);
6279      const startBookmarkNode = createBookmarkSpan(dom, id + '_start', filled);
6280      rangeInsertNode(dom, rng, startBookmarkNode);
6281      selection.moveToBookmark({
6282        id,
6283        keep: true,
6284        forward
6285      });
6286      return {
6287        id,
6288        forward
6289      };
6290    };
6291    const getBookmark$2 = (selection, type, normalized = false) => {
6292      if (type === 2) {
6293        return getOffsetBookmark(trim$1, normalized, selection);
6294      } else if (type === 3) {
6295        return getCaretBookmark(selection);
6296      } else if (type) {
6297        return getRangeBookmark(selection);
6298      } else {
6299        return getPersistentBookmark(selection, false);
6300      }
6301    };
6302    const getUndoBookmark = curry(getOffsetBookmark, identity, true);
6303
6304    const value$1 = value => {
6305      const applyHelper = fn => fn(value);
6306      const constHelper = constant(value);
6307      const outputHelper = () => output;
6308      const output = {
6309        tag: true,
6310        inner: value,
6311        fold: (_onError, onValue) => onValue(value),
6312        isValue: always,
6313        isError: never,
6314        map: mapper => Result.value(mapper(value)),
6315        mapError: outputHelper,
6316        bind: applyHelper,
6317        exists: applyHelper,
6318        forall: applyHelper,
6319        getOr: constHelper,
6320        or: outputHelper,
6321        getOrThunk: constHelper,
6322        orThunk: outputHelper,
6323        getOrDie: constHelper,
6324        each: fn => {
6325          fn(value);
6326        },
6327        toOptional: () => Optional.some(value)
6328      };
6329      return output;
6330    };
6331    const error = error => {
6332      const outputHelper = () => output;
6333      const output = {
6334        tag: false,
6335        inner: error,
6336        fold: (onError, _onValue) => onError(error),
6337        isValue: never,
6338        isError: always,
6339        map: outputHelper,
6340        mapError: mapper => Result.error(mapper(error)),
6341        bind: outputHelper,
6342        exists: never,
6343        forall: always,
6344        getOr: identity,
6345        or: identity,
6346        getOrThunk: apply$1,
6347        orThunk: apply$1,
6348        getOrDie: die(String(error)),
6349        each: noop,
6350        toOptional: Optional.none
6351      };
6352      return output;
6353    };
6354    const fromOption = (optional, err) => optional.fold(() => error(err), value$1);
6355    const Result = {
6356      value: value$1,
6357      error,
6358      fromOption
6359    };
6360
6361    const generate = cases => {
6362      if (!isArray$1(cases)) {
6363        throw new Error('cases must be an array');
6364      }
6365      if (cases.length === 0) {
6366        throw new Error('there must be at least one case');
6367      }
6368      const constructors = [];
6369      const adt = {};
6370      each$e(cases, (acase, count) => {
6371        const keys$1 = keys(acase);
6372        if (keys$1.length !== 1) {
6373          throw new Error('one and only one name per case');
6374        }
6375        const key = keys$1[0];
6376        const value = acase[key];
6377        if (adt[key] !== undefined) {
6378          throw new Error('duplicate key detected:' + key);
6379        } else if (key === 'cata') {
6380          throw new Error('cannot have a case named cata (sorry)');
6381        } else if (!isArray$1(value)) {
6382          throw new Error('case arguments must be an array');
6383        }
6384        constructors.push(key);
6385        adt[key] = (...args) => {
6386          const argLength = args.length;
6387          if (argLength !== value.length) {
6388            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
6389          }
6390          const match = branches => {
6391            const branchKeys = keys(branches);
6392            if (constructors.length !== branchKeys.length) {
6393              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
6394            }
6395            const allReqd = forall(constructors, reqKey => {
6396              return contains$2(branchKeys, reqKey);
6397            });
6398            if (!allReqd) {
6399              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
6400            }
6401            return branches[key].apply(null, args);
6402          };
6403          return {
6404            fold: (...foldArgs) => {
6405              if (foldArgs.length !== cases.length) {
6406                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
6407              }
6408              const target = foldArgs[count];
6409              return target.apply(null, args);
6410            },
6411            match,
6412            log: label => {
6413              console.log(label, {
6414                constructors,
6415                constructor: key,
6416                params: args
6417              });
6418            }
6419          };
6420        };
6421      });
6422      return adt;
6423    };
6424    const Adt = { generate };
6425
6426    Adt.generate([
6427      {
6428        bothErrors: [
6429          'error1',
6430          'error2'
6431        ]
6432      },
6433      {
6434        firstError: [
6435          'error1',
6436          'value2'
6437        ]
6438      },
6439      {
6440        secondError: [
6441          'value1',
6442          'error2'
6443        ]
6444      },
6445      {
6446        bothValues: [
6447          'value1',
6448          'value2'
6449        ]
6450      }
6451    ]);
6452    const partition$1 = results => {
6453      const errors = [];
6454      const values = [];
6455      each$e(results, result => {
6456        result.fold(err => {
6457          errors.push(err);
6458        }, value => {
6459          values.push(value);
6460        });
6461      });
6462      return {
6463        errors,
6464        values
6465      };
6466    };
6467
6468    const isInlinePattern = pattern => pattern.type === 'inline-command' || pattern.type === 'inline-format';
6469    const isBlockPattern = pattern => pattern.type === 'block-command' || pattern.type === 'block-format';
6470    const normalizePattern = pattern => {
6471      const err = message => Result.error({
6472        message,
6473        pattern
6474      });
6475      const formatOrCmd = (name, onFormat, onCommand) => {
6476        if (pattern.format !== undefined) {
6477          let formats;
6478          if (isArray$1(pattern.format)) {
6479            if (!forall(pattern.format, isString)) {
6480              return err(name + ' pattern has non-string items in the `format` array');
6481            }
6482            formats = pattern.format;
6483          } else if (isString(pattern.format)) {
6484            formats = [pattern.format];
6485          } else {
6486            return err(name + ' pattern has non-string `format` parameter');
6487          }
6488          return Result.value(onFormat(formats));
6489        } else if (pattern.cmd !== undefined) {
6490          if (!isString(pattern.cmd)) {
6491            return err(name + ' pattern has non-string `cmd` parameter');
6492          }
6493          return Result.value(onCommand(pattern.cmd, pattern.value));
6494        } else {
6495          return err(name + ' pattern is missing both `format` and `cmd` parameters');
6496        }
6497      };
6498      if (!isObject(pattern)) {
6499        return err('Raw pattern is not an object');
6500      }
6501      if (!isString(pattern.start)) {
6502        return err('Raw pattern is missing `start` parameter');
6503      }
6504      if (pattern.end !== undefined) {
6505        if (!isString(pattern.end)) {
6506          return err('Inline pattern has non-string `end` parameter');
6507        }
6508        if (pattern.start.length === 0 && pattern.end.length === 0) {
6509          return err('Inline pattern has empty `start` and `end` parameters');
6510        }
6511        let start = pattern.start;
6512        let end = pattern.end;
6513        if (end.length === 0) {
6514          end = start;
6515          start = '';
6516        }
6517        return formatOrCmd('Inline', format => ({
6518          type: 'inline-format',
6519          start,
6520          end,
6521          format
6522        }), (cmd, value) => ({
6523          type: 'inline-command',
6524          start,
6525          end,
6526          cmd,
6527          value
6528        }));
6529      } else if (pattern.replacement !== undefined) {
6530        if (!isString(pattern.replacement)) {
6531          return err('Replacement pattern has non-string `replacement` parameter');
6532        }
6533        if (pattern.start.length === 0) {
6534          return err('Replacement pattern has empty `start` parameter');
6535        }
6536        return Result.value({
6537          type: 'inline-command',
6538          start: '',
6539          end: pattern.start,
6540          cmd: 'mceInsertContent',
6541          value: pattern.replacement
6542        });
6543      } else {
6544        if (pattern.start.length === 0) {
6545          return err('Block pattern has empty `start` parameter');
6546        }
6547        return formatOrCmd('Block', formats => ({
6548          type: 'block-format',
6549          start: pattern.start,
6550          format: formats[0]
6551        }), (command, commandValue) => ({
6552          type: 'block-command',
6553          start: pattern.start,
6554          cmd: command,
6555          value: commandValue
6556        }));
6557      }
6558    };
6559    const getBlockPatterns = patterns => filter$5(patterns, isBlockPattern);
6560    const getInlinePatterns = patterns => filter$5(patterns, isInlinePattern);
6561    const createPatternSet = (patterns, dynamicPatternsLookup) => ({
6562      inlinePatterns: getInlinePatterns(patterns),
6563      blockPatterns: getBlockPatterns(patterns),
6564      dynamicPatternsLookup
6565    });
6566    const fromRawPatterns = patterns => {
6567      const normalized = partition$1(map$3(patterns, normalizePattern));
6568      each$e(normalized.errors, err => console.error(err.message, err.pattern));
6569      return normalized.values;
6570    };
6571    const fromRawPatternsLookup = lookupFn => {
6572      return ctx => {
6573        const rawPatterns = lookupFn(ctx);
6574        return fromRawPatterns(rawPatterns);
6575      };
6576    };
6577
6578    const deviceDetection$1 = detect$2().deviceType;
6579    const isTouch = deviceDetection$1.isTouch();
6580    const DOM$a = DOMUtils.DOM;
6581    const getHash = value => {
6582      const items = value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(',');
6583      return foldl(items, (output, item) => {
6584        const arr = item.split('=');
6585        const key = arr[0];
6586        const val = arr.length > 1 ? arr[1] : key;
6587        output[trim$3(key)] = trim$3(val);
6588        return output;
6589      }, {});
6590    };
6591    const isRegExp = x => is$4(x, RegExp);
6592    const option = name => editor => editor.options.get(name);
6593    const stringOrObjectProcessor = value => isString(value) || isObject(value);
6594    const bodyOptionProcessor = (editor, defaultValue = '') => value => {
6595      const valid = isString(value);
6596      if (valid) {
6597        if (value.indexOf('=') !== -1) {
6598          const bodyObj = getHash(value);
6599          return {
6600            value: get$a(bodyObj, editor.id).getOr(defaultValue),
6601            valid
6602          };
6603        } else {
6604          return {
6605            value,
6606            valid
6607          };
6608        }
6609      } else {
6610        return {
6611          valid: false,
6612          message: 'Must be a string.'
6613        };
6614      }
6615    };
6616    const register$7 = editor => {
6617      const registerOption = editor.options.register;
6618      registerOption('id', {
6619        processor: 'string',
6620        default: editor.id
6621      });
6622      registerOption('selector', { processor: 'string' });
6623      registerOption('target', { processor: 'object' });
6624      registerOption('suffix', { processor: 'string' });
6625      registerOption('cache_suffix', { processor: 'string' });
6626      registerOption('base_url', { processor: 'string' });
6627      registerOption('referrer_policy', {
6628        processor: 'string',
6629        default: ''
6630      });
6631      registerOption('language_load', {
6632        processor: 'boolean',
6633        default: true
6634      });
6635      registerOption('inline', {
6636        processor: 'boolean',
6637        default: false
6638      });
6639      registerOption('iframe_attrs', {
6640        processor: 'object',
6641        default: {}
6642      });
6643      registerOption('doctype', {
6644        processor: 'string',
6645        default: '<!DOCTYPE html>'
6646      });
6647      registerOption('document_base_url', {
6648        processor: 'string',
6649        default: editor.documentBaseUrl
6650      });
6651      registerOption('body_id', {
6652        processor: bodyOptionProcessor(editor, 'tinymce'),
6653        default: 'tinymce'
6654      });
6655      registerOption('body_class', {
6656        processor: bodyOptionProcessor(editor),
6657        default: ''
6658      });
6659      registerOption('content_security_policy', {
6660        processor: 'string',
6661        default: ''
6662      });
6663      registerOption('br_in_pre', {
6664        processor: 'boolean',
6665        default: true
6666      });
6667      registerOption('forced_root_block', {
6668        processor: value => {
6669          const valid = isString(value) && isNotEmpty(value);
6670          if (valid) {
6671            return {
6672              value,
6673              valid
6674            };
6675          } else {
6676            return {
6677              valid: false,
6678              message: 'Must be a non-empty string.'
6679            };
6680          }
6681        },
6682        default: 'p'
6683      });
6684      registerOption('forced_root_block_attrs', {
6685        processor: 'object',
6686        default: {}
6687      });
6688      registerOption('newline_behavior', {
6689        processor: value => {
6690          const valid = contains$2([
6691            'block',
6692            'linebreak',
6693            'invert',
6694            'default'
6695          ], value);
6696          return valid ? {
6697            value,
6698            valid
6699          } : {
6700            valid: false,
6701            message: 'Must be one of: block, linebreak, invert or default.'
6702          };
6703        },
6704        default: 'default'
6705      });
6706      registerOption('br_newline_selector', {
6707        processor: 'string',
6708        default: '.mce-toc h2,figcaption,caption'
6709      });
6710      registerOption('no_newline_selector', {
6711        processor: 'string',
6712        default: ''
6713      });
6714      registerOption('keep_styles', {
6715        processor: 'boolean',
6716        default: true
6717      });
6718      registerOption('end_container_on_empty_block', {
6719        processor: value => {
6720          if (isBoolean(value)) {
6721            return {
6722              valid: true,
6723              value
6724            };
6725          } else if (isString(value)) {
6726            return {
6727              valid: true,
6728              value
6729            };
6730          } else {
6731            return {
6732              valid: false,
6733              message: 'Must be boolean or a string'
6734            };
6735          }
6736        },
6737        default: 'blockquote'
6738      });
6739      registerOption('font_size_style_values', {
6740        processor: 'string',
6741        default: 'xx-small,x-small,small,medium,large,x-large,xx-large'
6742      });
6743      registerOption('font_size_legacy_values', {
6744        processor: 'string',
6745        default: 'xx-small,small,medium,large,x-large,xx-large,300%'
6746      });
6747      registerOption('font_size_classes', {
6748        processor: 'string',
6749        default: ''
6750      });
6751      registerOption('automatic_uploads', {
6752        processor: 'boolean',
6753        default: true
6754      });
6755      registerOption('images_reuse_filename', {
6756        processor: 'boolean',
6757        default: false
6758      });
6759      registerOption('images_replace_blob_uris', {
6760        processor: 'boolean',
6761        default: true
6762      });
6763      registerOption('icons', {
6764        processor: 'string',
6765        default: ''
6766      });
6767      registerOption('icons_url', {
6768        processor: 'string',
6769        default: ''
6770      });
6771      registerOption('images_upload_url', {
6772        processor: 'string',
6773        default: ''
6774      });
6775      registerOption('images_upload_base_path', {
6776        processor: 'string',
6777        default: ''
6778      });
6779      registerOption('images_upload_credentials', {
6780        processor: 'boolean',
6781        default: false
6782      });
6783      registerOption('images_upload_handler', { processor: 'function' });
6784      registerOption('language', {
6785        processor: 'string',
6786        default: 'en'
6787      });
6788      registerOption('language_url', {
6789        processor: 'string',
6790        default: ''
6791      });
6792      registerOption('entity_encoding', {
6793        processor: 'string',
6794        default: 'named'
6795      });
6796      registerOption('indent', {
6797        processor: 'boolean',
6798        default: true
6799      });
6800      registerOption('indent_before', {
6801        processor: 'string',
6802        default: '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,
6802summary,article,hgroup,aside,f
vendor: 18,894 bytes, lines 6802-7354
6802igure,figcaption,option,optgroup,datalist'
6803      });
6804      registerOption('indent_after', {
6805        processor: 'string',
6806        default: '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'
6807      });
6808      registerOption('indent_use_margin', {
6809        processor: 'boolean',
6810        default: false
6811      });
6812      registerOption('indentation', {
6813        processor: 'string',
6814        default: '40px'
6815      });
6816      registerOption('content_css', {
6817        processor: value => {
6818          const valid = value === false || isString(value) || isArrayOf(value, isString);
6819          if (valid) {
6820            if (isString(value)) {
6821              return {
6822                value: map$3(value.split(','), trim$3),
6823                valid
6824              };
6825            } else if (isArray$1(value)) {
6826              return {
6827                value,
6828                valid
6829              };
6830            } else if (value === false) {
6831              return {
6832                value: [],
6833                valid
6834              };
6835            } else {
6836              return {
6837                value,
6838                valid
6839              };
6840            }
6841          } else {
6842            return {
6843              valid: false,
6844              message: 'Must be false, a string or an array of strings.'
6845            };
6846          }
6847        },
6848        default: isInline(editor) ? [] : ['default']
6849      });
6850      registerOption('content_style', { processor: 'string' });
6851      registerOption('content_css_cors', {
6852        processor: 'boolean',
6853        default: false
6854      });
6855      registerOption('font_css', {
6856        processor: value => {
6857          const valid = isString(value) || isArrayOf(value, isString);
6858          if (valid) {
6859            const newValue = isArray$1(value) ? value : map$3(value.split(','), trim$3);
6860            return {
6861              value: newValue,
6862              valid
6863            };
6864          } else {
6865            return {
6866              valid: false,
6867              message: 'Must be a string or an array of strings.'
6868            };
6869          }
6870        },
6871        default: []
6872      });
6873      registerOption('inline_boundaries', {
6874        processor: 'boolean',
6875        default: true
6876      });
6877      registerOption('inline_boundaries_selector', {
6878        processor: 'string',
6879        default: 'a[href],code,span.mce-annotation'
6880      });
6881      registerOption('object_resizing', {
6882        processor: value => {
6883          const valid = isBoolean(value) || isString(value);
6884          if (valid) {
6885            if (value === false || deviceDetection$1.isiPhone() || deviceDetection$1.isiPad()) {
6886              return {
6887                value: '',
6888                valid
6889              };
6890            } else {
6891              return {
6892                value: value === true ? 'table,img,figure.image,div,video,iframe' : value,
6893                valid
6894              };
6895            }
6896          } else {
6897            return {
6898              valid: false,
6899              message: 'Must be boolean or a string'
6900            };
6901          }
6902        },
6903        default: !isTouch
6904      });
6905      registerOption('resize_img_proportional', {
6906        processor: 'boolean',
6907        default: true
6908      });
6909      registerOption('event_root', { processor: 'object' });
6910      registerOption('service_message', { processor: 'string' });
6911      registerOption('theme', {
6912        processor: value => value === false || isString(value) || isFunction(value),
6913        default: 'silver'
6914      });
6915      registerOption('theme_url', { processor: 'string' });
6916      registerOption('formats', { processor: 'object' });
6917      registerOption('format_empty_lines', {
6918        processor: 'boolean',
6919        default: false
6920      });
6921      registerOption('format_noneditable_selector', {
6922        processor: 'string',
6923        default: ''
6924      });
6925      registerOption('preview_styles', {
6926        processor: value => {
6927          const valid = value === false || isString(value);
6928          if (valid) {
6929            return {
6930              value: value === false ? '' : value,
6931              valid
6932            };
6933          } else {
6934            return {
6935              valid: false,
6936              message: 'Must be false or a string'
6937            };
6938          }
6939        },
6940        default: 'font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow'
6941      });
6942      registerOption('custom_ui_selector', {
6943        processor: 'string',
6944        default: ''
6945      });
6946      registerOption('hidden_input', {
6947        processor: 'boolean',
6948        default: true
6949      });
6950      registerOption('submit_patch', {
6951        processor: 'boolean',
6952        default: true
6953      });
6954      registerOption('encoding', { processor: 'string' });
6955      registerOption('add_form_submit_trigger', {
6956        processor: 'boolean',
6957        default: true
6958      });
6959      registerOption('add_unload_trigger', {
6960        processor: 'boolean',
6961        default: true
6962      });
6963      registerOption('custom_undo_redo_levels', {
6964        processor: 'number',
6965        default: 0
6966      });
6967      registerOption('disable_nodechange', {
6968        processor: 'boolean',
6969        default: false
6970      });
6971      registerOption('readonly', {
6972        processor: 'boolean',
6973        default: false
6974      });
6975      registerOption('plugins', {
6976        processor: 'string[]',
6977        default: []
6978      });
6979      registerOption('external_plugins', { processor: 'object' });
6980      registerOption('forced_plugins', { processor: 'string[]' });
6981      registerOption('model', {
6982        processor: 'string',
6983        default: editor.hasPlugin('rtc') ? 'plugin' : 'dom'
6984      });
6985      registerOption('model_url', { processor: 'string' });
6986      registerOption('block_unsupported_drop', {
6987        processor: 'boolean',
6988        default: true
6989      });
6990      registerOption('visual', {
6991        processor: 'boolean',
6992        default: true
6993      });
6994      registerOption('visual_table_class', {
6995        processor: 'string',
6996        default: 'mce-item-table'
6997      });
6998      registerOption('visual_anchor_class', {
6999        processor: 'string',
7000        default: 'mce-item-anchor'
7001      });
7002      registerOption('iframe_aria_text', {
7003        processor: 'string',
7004        default: 'Rich Text Area. Press ALT-0 for help.'
7005      });
7006      registerOption('setup', { processor: 'function' });
7007      registerOption('init_instance_callback', { processor: 'function' });
7008      registerOption('url_converter', {
7009        processor: 'function',
7010        default: editor.convertURL
7011      });
7012      registerOption('url_converter_scope', {
7013        processor: 'object',
7014        default: editor
7015      });
7016      registerOption('urlconverter_callback', { processor: 'function' });
7017      registerOption('allow_conditional_comments', {
7018        processor: 'boolean',
7019        default: false
7020      });
7021      registerOption('allow_html_data_urls', {
7022        processor: 'boolean',
7023        default: false
7024      });
7025      registerOption('allow_svg_data_urls', { processor: 'boolean' });
7026      registerOption('allow_html_in_named_anchor', {
7027        processor: 'boolean',
7028        default: false
7029      });
7030      registerOption('allow_script_urls', {
7031        processor: 'boolean',
7032        default: false
7033      });
7034      registerOption('allow_unsafe_link_target', {
7035        processor: 'boolean',
7036        default: false
7037      });
7038      registerOption('convert_fonts_to_spans', {
7039        processor: 'boolean',
7040        default: true,
7041        deprecated: true
7042      });
7043      registerOption('fix_list_elements', {
7044        processor: 'boolean',
7045        default: false
7046      });
7047      registerOption('preserve_cdata', {
7048        processor: 'boolean',
7049        default: false
7050      });
7051      registerOption('remove_trailing_brs', { processor: 'boolean' });
7052      registerOption('inline_styles', {
7053        processor: 'boolean',
7054        default: true,
7055        deprecated: true
7056      });
7057      registerOption('element_format', {
7058        processor: 'string',
7059        default: 'html'
7060      });
7061      registerOption('entities', { processor: 'string' });
7062      registerOption('schema', {
7063        processor: 'string',
7064        default: 'html5'
7065      });
7066      registerOption('convert_urls', {
7067        processor: 'boolean',
7068        default: true
7069      });
7070      registerOption('relative_urls', {
7071        processor: 'boolean',
7072        default: true
7073      });
7074      registerOption('remove_script_host', {
7075        processor: 'boolean',
7076        default: true
7077      });
7078      registerOption('custom_elements', { processor: 'string' });
7079      registerOption('extended_valid_elements', { processor: 'string' });
7080      registerOption('invalid_elements', { processor: 'string' });
7081      registerOption('invalid_styles', { processor: stringOrObjectProcessor });
7082      registerOption('valid_children', { processor: 'string' });
7083      registerOption('valid_classes', { processor: stringOrObjectProcessor });
7084      registerOption('valid_elements', { processor: 'string' });
7085      registerOption('valid_styles', { processor: stringOrObjectProcessor });
7086      registerOption('verify_html', {
7087        processor: 'boolean',
7088        default: true
7089      });
7090      registerOption('auto_focus', { processor: value => isString(value) || value === true });
7091      registerOption('browser_spellcheck', {
7092        processor: 'boolean',
7093        default: false
7094      });
7095      registerOption('protect', { processor: 'array' });
7096      registerOption('images_file_types', {
7097        processor: 'string',
7098        default: 'jpeg,jpg,jpe,jfi,jif,jfif,png,gif,bmp,webp'
7099      });
7100      registerOption('deprecation_warnings', {
7101        processor: 'boolean',
7102        default: true
7103      });
7104      registerOption('a11y_advanced_options', {
7105        processor: 'boolean',
7106        default: false
7107      });
7108      registerOption('api_key', { processor: 'string' });
7109      registerOption('paste_block_drop', {
7110        processor: 'boolean',
7111        default: false
7112      });
7113      registerOption('paste_data_images', {
7114        processor: 'boolean',
7115        default: true
7116      });
7117      registerOption('paste_preprocess', { processor: 'function' });
7118      registerOption('paste_postprocess', { processor: 'function' });
7119      registerOption('paste_webkit_styles', {
7120        processor: 'string',
7121        default: 'none'
7122      });
7123      registerOption('paste_remove_styles_if_webkit', {
7124        processor: 'boolean',
7125        default: true
7126      });
7127      registerOption('paste_merge_formats', {
7128        processor: 'boolean',
7129        default: true
7130      });
7131      registerOption('smart_paste', {
7132        processor: 'boolean',
7133        default: true
7134      });
7135      registerOption('paste_as_text', {
7136        processor: 'boolean',
7137        default: false
7138      });
7139      registerOption('paste_tab_spaces', {
7140        processor: 'number',
7141        default: 4
7142      });
7143      registerOption('text_patterns', {
7144        processor: value => {
7145          if (isArrayOf(value, isObject) || value === false) {
7146            const patterns = value === false ? [] : value;
7147            return {
7148              value: fromRawPatterns(patterns),
7149              valid: true
7150            };
7151          } else {
7152            return {
7153              valid: false,
7154              message: 'Must be an array of objects or false.'
7155            };
7156          }
7157        },
7158        default: [
7159          {
7160            start: '*',
7161            end: '*',
7162            format: 'italic'
7163          },
7164          {
7165            start: '**',
7166            end: '**',
7167            format: 'bold'
7168          },
7169          {
7170            start: '#',
7171            format: 'h1'
7172          },
7173          {
7174            start: '##',
7175            format: 'h2'
7176          },
7177          {
7178            start: '###',
7179            format: 'h3'
7180          },
7181          {
7182            start: '####',
7183            format: 'h4'
7184          },
7185          {
7186            start: '#####',
7187            format: 'h5'
7188          },
7189          {
7190            start: '######',
7191            format: 'h6'
7192          },
7193          {
7194            start: '1. ',
7195            cmd: 'InsertOrderedList'
7196          },
7197          {
7198            start: '* ',
7199            cmd: 'InsertUnorderedList'
7200          },
7201          {
7202            start: '- ',
7203            cmd: 'InsertUnorderedList'
7204          }
7205        ]
7206      });
7207      registerOption('text_patterns_lookup', {
7208        processor: value => {
7209          if (isFunction(value)) {
7210            return {
7211              value: fromRawPatternsLookup(value),
7212              valid: true
7213            };
7214          } else {
7215            return {
7216              valid: false,
7217              message: 'Must be a single function'
7218            };
7219          }
7220        },
7221        default: _ctx => []
7222      });
7223      registerOption('noneditable_class', {
7224        processor: 'string',
7225        default: 'mceNonEditable'
7226      });
7227      registerOption('editable_class', {
7228        processor: 'string',
7229        default: 'mceEditable'
7230      });
7231      registerOption('noneditable_regexp', {
7232        processor: value => {
7233          if (isArrayOf(value, isRegExp)) {
7234            return {
7235              value,
7236              valid: true
7237            };
7238          } else if (isRegExp(value)) {
7239            return {
7240              value: [value],
7241              valid: true
7242            };
7243          } else {
7244            return {
7245              valid: false,
7246              message: 'Must be a RegExp or an array of RegExp.'
7247            };
7248          }
7249        },
7250        default: []
7251      });
7252      registerOption('table_tab_navigation', {
7253        processor: 'boolean',
7254        default: true
7255      });
7256      registerOption('highlight_on_focus', {
7257        processor: 'boolean',
7258        default: false
7259      });
7260      registerOption('xss_sanitization', {
7261        processor: 'boolean',
7262        default: true
7263      });
7264      editor.on('ScriptsLoaded', () => {
7265        registerOption('directionality', {
7266          processor: 'string',
7267          default: I18n.isRtl() ? 'rtl' : undefined
7268        });
7269        registerOption('placeholder', {
7270          processor: 'string',
7271          default: DOM$a.getAttrib(editor.getElement(), 'placeholder')
7272        });
7273      });
7274    };
7275    const getIframeAttrs = option('iframe_attrs');
7276    const getDocType = option('doctype');
7277    const getDocumentBaseUrl = option('document_base_url');
7278    const getBodyId = option('body_id');
7279    const getBodyClass = option('body_class');
7280    const getContentSecurityPolicy = option('content_security_policy');
7281    const shouldPutBrInPre$1 = option('br_in_pre');
7282    const getForcedRootBlock = option('forced_root_block');
7283    const getForcedRootBlockAttrs = option('forced_root_block_attrs');
7284    const getNewlineBehavior = option('newline_behavior');
7285    const getBrNewLineSelector = option('br_newline_selector');
7286    const getNoNewLineSelector = option('no_newline_selector');
7287    const shouldKeepStyles = option('keep_styles');
7288    const shouldEndContainerOnEmptyBlock = option('end_container_on_empty_block');
7289    const isAutomaticUploadsEnabled = option('automatic_uploads');
7290    const shouldReuseFileName = option('images_reuse_filename');
7291    const shouldReplaceBlobUris = option('images_replace_blob_uris');
7292    const getIconPackName = option('icons');
7293    const getIconsUrl = option('icons_url');
7294    const getImageUploadUrl = option('images_upload_url');
7295    const getImageUploadBasePath = option('images_upload_base_path');
7296    const getImagesUploadCredentials = option('images_upload_credentials');
7297    const getImagesUploadHandler = option('images_upload_handler');
7298    const shouldUseContentCssCors = option('content_css_cors');
7299    const getReferrerPolicy = option('referrer_policy');
7300    const getLanguageCode = option('language');
7301    const getLanguageUrl = option('language_url');
7302    const shouldIndentUseMargin = option('indent_use_margin');
7303    const getIndentation = option('indentation');
7304    const getContentCss = option('content_css');
7305    const getContentStyle = option('content_style');
7306    const getFontCss = option('font_css');
7307    const getDirectionality = option('directionality');
7308    const getInlineBoundarySelector = option('inline_boundaries_selector');
7309    const getObjectResizing = option('object_resizing');
7310    const getResizeImgProportional = option('resize_img_proportional');
7311    const getPlaceholder = option('placeholder');
7312    const getEventRoot = option('event_root');
7313    const getServiceMessage = option('service_message');
7314    const getTheme = option('theme');
7315    const getThemeUrl = option('theme_url');
7316    const getModel = option('model');
7317    const getModelUrl = option('model_url');
7318    const isInlineBoundariesEnabled = option('inline_boundaries');
7319    const getFormats = option('formats');
7320    const getPreviewStyles = option('preview_styles');
7321    const canFormatEmptyLines = option('format_empty_lines');
7322    const getFormatNoneditableSelector = option('format_noneditable_selector');
7323    const getCustomUiSelector = option('custom_ui_selector');
7324    const isInline = option('inline');
7325    const hasHiddenInput = option('hidden_input');
7326    const shouldPatchSubmit = option('submit_patch');
7327    const shouldAddFormSubmitTrigger = option('add_form_submit_trigger');
7328    const shouldAddUnloadTrigger = option('add_unload_trigger');
7329    const getCustomUndoRedoLevels = option('custom_undo_redo_levels');
7330    const shouldDisableNodeChange = option('disable_nodechange');
7331    const isReadOnly$1 = option('readonly');
7332    const hasContentCssCors = option('content_css_cors');
7333    const getPlugins = option('plugins');
7334    const getExternalPlugins$1 = option('external_plugins');
7335    const shouldBlockUnsupportedDrop = option('block_unsupported_drop');
7336    const isVisualAidsEnabled = option('visual');
7337    const getVisualAidsTableClass = option('visual_table_class');
7338    const getVisualAidsAnchorClass = option('visual_anchor_class');
7339    const getIframeAriaText = option('iframe_aria_text');
7340    const getSetupCallback = option('setup');
7341    const getInitInstanceCallback = option('init_instance_callback');
7342    const getUrlConverterCallback = option('urlconverter_callback');
7343    const getAutoFocus = option('auto_focus');
7344    const shouldBrowserSpellcheck = option('browser_spellcheck');
7345    const getProtect = option('protect');
7346    const shouldPasteBlockDrop = option('paste_block_drop');
7347    const shouldPasteDataImages = option('paste_data_images');
7348    const getPastePreProcess = option('paste_preprocess');
7349    const getPastePostProcess = option('paste_postprocess');
7350    const getPasteWebkitStyles = option('paste_webkit_styles');
7351    const shouldPasteRemoveWebKitStyles = option('paste_remove_styles_if_webkit');
7352    const shouldPasteMergeFormats = option('paste_merge_formats');
7353    const isSmartPasteEnabled = option('smart_paste');
7354    const isPasteAsTextEnabled = option('paste_as_text');
vendor: 7,864 bytes, lines 7355-7544
7355    const getPasteTabSpaces = option('paste_tab_spaces');
7356    const shouldAllowHtmlDataUrls = option('allow_html_data_urls');
7357    const getTextPatterns = option('text_patterns');
7358    const getTextPatternsLookup = option('text_patterns_lookup');
7359    const getNonEditableClass = option('noneditable_class');
7360    const getEditableClass = option('editable_class');
7361    const getNonEditableRegExps = option('noneditable_regexp');
7362    const shouldPreserveCData = option('preserve_cdata');
7363    const shouldHighlightOnFocus = option('highlight_on_focus');
7364    const shouldSanitizeXss = option('xss_sanitization');
7365    const hasTextPatternsLookup = editor => editor.options.isSet('text_patterns_lookup');
7366    const getFontStyleValues = editor => Tools.explode(editor.options.get('font_size_style_values'));
7367    const getFontSizeClasses = editor => Tools.explode(editor.options.get('font_size_classes'));
7368    const isEncodingXml = editor => editor.options.get('encoding') === 'xml';
7369    const getAllowedImageFileTypes = editor => Tools.explode(editor.options.get('images_file_types'));
7370    const hasTableTabNavigation = option('table_tab_navigation');
7371
7372    const isElement$3 = isElement$6;
7373    const isText$5 = isText$a;
7374    const removeNode$1 = node => {
7375      const parentNode = node.parentNode;
7376      if (parentNode) {
7377        parentNode.removeChild(node);
7378      }
7379    };
7380    const trimCount = text => {
7381      const trimmedText = trim$1(text);
7382      return {
7383        count: text.length - trimmedText.length,
7384        text: trimmedText
7385      };
7386    };
7387    const deleteZwspChars = caretContainer => {
7388      let idx;
7389      while ((idx = caretContainer.data.lastIndexOf(ZWSP$1)) !== -1) {
7390        caretContainer.deleteData(idx, 1);
7391      }
7392    };
7393    const removeUnchanged = (caretContainer, pos) => {
7394      remove$4(caretContainer);
7395      return pos;
7396    };
7397    const removeTextAndReposition = (caretContainer, pos) => {
7398      const before = trimCount(caretContainer.data.substr(0, pos.offset()));
7399      const after = trimCount(caretContainer.data.substr(pos.offset()));
7400      const text = before.text + after.text;
7401      if (text.length > 0) {
7402        deleteZwspChars(caretContainer);
7403        return CaretPosition(caretContainer, pos.offset() - before.count);
7404      } else {
7405        return pos;
7406      }
7407    };
7408    const removeElementAndReposition = (caretContainer, pos) => {
7409      const parentNode = pos.container();
7410      const newPosition = indexOf$1(from(parentNode.childNodes), caretContainer).map(index => {
7411        return index < pos.offset() ? CaretPosition(parentNode, pos.offset() - 1) : pos;
7412      }).getOr(pos);
7413      remove$4(caretContainer);
7414      return newPosition;
7415    };
7416    const removeTextCaretContainer = (caretContainer, pos) => isText$5(caretContainer) && pos.container() === caretContainer ? removeTextAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
7417    const removeElementCaretContainer = (caretContainer, pos) => pos.container() === caretContainer.parentNode ? removeElementAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
7418    const removeAndReposition = (container, pos) => CaretPosition.isTextPosition(pos) ? removeTextCaretContainer(container, pos) : removeElementCaretContainer(container, pos);
7419    const remove$4 = caretContainerNode => {
7420      if (isElement$3(caretContainerNode) && isCaretContainer$2(caretContainerNode)) {
7421        if (hasContent(caretContainerNode)) {
7422          caretContainerNode.removeAttribute('data-mce-caret');
7423        } else {
7424          removeNode$1(caretContainerNode);
7425        }
7426      }
7427      if (isText$5(caretContainerNode)) {
7428        deleteZwspChars(caretContainerNode);
7429        if (caretContainerNode.data.length === 0) {
7430          removeNode$1(caretContainerNode);
7431        }
7432      }
7433    };
7434
7435    const isContentEditableFalse$8 = isContentEditableFalse$b;
7436    const isMedia$1 = isMedia$2;
7437    const isTableCell$1 = isTableCell$3;
7438    const inlineFakeCaretSelector = '*[contentEditable=false],video,audio,embed,object';
7439    const getAbsoluteClientRect = (root, element, before) => {
7440      const clientRect = collapse(element.getBoundingClientRect(), before);
7441      let scrollX;
7442      let scrollY;
7443      if (root.tagName === 'BODY') {
7444        const docElm = root.ownerDocument.documentElement;
7445        scrollX = root.scrollLeft || docElm.scrollLeft;
7446        scrollY = root.scrollTop || docElm.scrollTop;
7447      } else {
7448        const rootRect = root.getBoundingClientRect();
7449        scrollX = root.scrollLeft - rootRect.left;
7450        scrollY = root.scrollTop - rootRect.top;
7451      }
7452      clientRect.left += scrollX;
7453      clientRect.right += scrollX;
7454      clientRect.top += scrollY;
7455      clientRect.bottom += scrollY;
7456      clientRect.width = 1;
7457      let margin = element.offsetWidth - element.clientWidth;
7458      if (margin > 0) {
7459        if (before) {
7460          margin *= -1;
7461        }
7462        clientRect.left += margin;
7463        clientRect.right += margin;
7464      }
7465      return clientRect;
7466    };
7467    const trimInlineCaretContainers = root => {
7468      var _a, _b;
7469      const fakeCaretTargetNodes = descendants(SugarElement.fromDom(root), inlineFakeCaretSelector);
7470      for (let i = 0; i < fakeCaretTargetNodes.length; i++) {
7471        const node = fakeCaretTargetNodes[i].dom;
7472        let sibling = node.previousSibling;
7473        if (endsWithCaretContainer$1(sibling)) {
7474          const data = sibling.data;
7475          if (data.length === 1) {
7476            (_a = sibling.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(sibling);
7477          } else {
7478            sibling.deleteData(data.length - 1, 1);
7479          }
7480        }
7481        sibling = node.nextSibling;
7482        if (startsWithCaretContainer$1(sibling)) {
7483          const data = sibling.data;
7484          if (data.length === 1) {
7485            (_b = sibling.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(sibling);
7486          } else {
7487            sibling.deleteData(0, 1);
7488          }
7489        }
7490      }
7491    };
7492    const FakeCaret = (editor, root, isBlock, hasFocus) => {
7493      const lastVisualCaret = value$2();
7494      let cursorInterval;
7495      let caretContainerNode;
7496      const caretBlock = getForcedRootBlock(editor);
7497      const dom = editor.dom;
7498      const show = (before, element) => {
7499        let rng;
7500        hide();
7501        if (isTableCell$1(element)) {
7502          return null;
7503        }
7504        if (isBlock(element)) {
7505          const caretContainer = insertBlock(caretBlock, element, before);
7506          const clientRect = getAbsoluteClientRect(root, element, before);
7507          dom.setStyle(caretContainer, 'top', clientRect.top);
7508          caretContainerNode = caretContainer;
7509          const caret = dom.create('div', {
7510            'class': 'mce-visual-caret',
7511            'data-mce-bogus': 'all'
7512          });
7513          dom.setStyles(caret, { ...clientRect });
7514          dom.add(root, caret);
7515          lastVisualCaret.set({
7516            caret,
7517            element,
7518            before
7519          });
7520          if (before) {
7521            dom.addClass(caret, 'mce-visual-caret-before');
7522          }
7523          startBlink();
7524          rng = element.ownerDocument.createRange();
7525          rng.setStart(caretContainer, 0);
7526          rng.setEnd(caretContainer, 0);
7527        } else {
7528          caretContainerNode = insertInline$1(element, before);
7529          rng = element.ownerDocument.createRange();
7530          if (isInlineFakeCaretTarget(caretContainerNode.nextSibling)) {
7531            rng.setStart(caretContainerNode, 0);
7532            rng.setEnd(caretContainerNode, 0);
7533          } else {
7534            rng.setStart(caretContainerNode, 1);
7535            rng.setEnd(caretContainerNode, 1);
7536          }
7537          return rng;
7538        }
7539        return rng;
7540      };
7541      const hide = () => {
7542        trimInlineCaretContainers(root);
7543        if (caretContainerNode) {
7544          remove$4
vendor: 27,224 bytes, lines 7544-8266
7544(caretContainerNode);
7545          caretContainerNode = null;
7546        }
7547        lastVisualCaret.on(caretState => {
7548          dom.remove(caretState.caret);
7549          lastVisualCaret.clear();
7550        });
7551        if (cursorInterval) {
7552          clearInterval(cursorInterval);
7553          cursorInterval = undefined;
7554        }
7555      };
7556      const startBlink = () => {
7557        cursorInterval = setInterval(() => {
7558          lastVisualCaret.on(caretState => {
7559            if (hasFocus()) {
7560              dom.toggleClass(caretState.caret, 'mce-visual-caret-hidden');
7561            } else {
7562              dom.addClass(caretState.caret, 'mce-visual-caret-hidden');
7563            }
7564          });
7565        }, 500);
7566      };
7567      const reposition = () => {
7568        lastVisualCaret.on(caretState => {
7569          const clientRect = getAbsoluteClientRect(root, caretState.element, caretState.before);
7570          dom.setStyles(caretState.caret, { ...clientRect });
7571        });
7572      };
7573      const destroy = () => clearInterval(cursorInterval);
7574      const getCss = () => '.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;' + '}';
7575      return {
7576        show,
7577        hide,
7578        getCss,
7579        reposition,
7580        destroy
7581      };
7582    };
7583    const isFakeCaretTableBrowser = () => Env.browser.isFirefox();
7584    const isInlineFakeCaretTarget = node => isContentEditableFalse$8(node) || isMedia$1(node);
7585    const isFakeCaretTarget = node => {
7586      const isTarget = isInlineFakeCaretTarget(node) || isTable$2(node) && isFakeCaretTableBrowser();
7587      return isTarget && parentElement(SugarElement.fromDom(node)).exists(isEditable$3);
7588    };
7589
7590    const isContentEditableTrue$1 = isContentEditableTrue$3;
7591    const isContentEditableFalse$7 = isContentEditableFalse$b;
7592    const isMedia = isMedia$2;
7593    const isBlockLike = matchStyleValues('display', 'block table table-cell table-caption list-item');
7594    const isCaretContainer = isCaretContainer$2;
7595    const isCaretContainerBlock = isCaretContainerBlock$1;
7596    const isElement$2 = isElement$6;
7597    const isText$4 = isText$a;
7598    const isCaretCandidate$1 = isCaretCandidate$3;
7599    const isForwards = direction => direction > 0;
7600    const isBackwards = direction => direction < 0;
7601    const skipCaretContainers = (walk, shallow) => {
7602      let node;
7603      while (node = walk(shallow)) {
7604        if (!isCaretContainerBlock(node)) {
7605          return node;
7606        }
7607      }
7608      return null;
7609    };
7610    const findNode = (node, direction, predicateFn, rootNode, shallow) => {
7611      const walker = new DomTreeWalker(node, rootNode);
7612      const isCefOrCaretContainer = isContentEditableFalse$7(node) || isCaretContainerBlock(node);
7613      let tempNode;
7614      if (isBackwards(direction)) {
7615        if (isCefOrCaretContainer) {
7616          tempNode = skipCaretContainers(walker.prev.bind(walker), true);
7617          if (predicateFn(tempNode)) {
7618            return tempNode;
7619          }
7620        }
7621        while (tempNode = skipCaretContainers(walker.prev.bind(walker), shallow)) {
7622          if (predicateFn(tempNode)) {
7623            return tempNode;
7624          }
7625        }
7626      }
7627      if (isForwards(direction)) {
7628        if (isCefOrCaretContainer) {
7629          tempNode = skipCaretContainers(walker.next.bind(walker), true);
7630          if (predicateFn(tempNode)) {
7631            return tempNode;
7632          }
7633        }
7634        while (tempNode = skipCaretContainers(walker.next.bind(walker), shallow)) {
7635          if (predicateFn(tempNode)) {
7636            return tempNode;
7637          }
7638        }
7639      }
7640      return null;
7641    };
7642    const getEditingHost = (node, rootNode) => {
7643      const isCETrue = node => isContentEditableTrue$1(node.dom);
7644      const isRoot = node => node.dom === rootNode;
7645      return ancestor$4(SugarElement.fromDom(node), isCETrue, isRoot).map(elm => elm.dom).getOr(rootNode);
7646    };
7647    const getParentBlock$3 = (node, rootNode) => {
7648      while (node && node !== rootNode) {
7649        if (isBlockLike(node)) {
7650          return node;
7651        }
7652        node = node.parentNode;
7653      }
7654      return null;
7655    };
7656    const isInSameBlock = (caretPosition1, caretPosition2, rootNode) => getParentBlock$3(caretPosition1.container(), rootNode) === getParentBlock$3(caretPosition2.container(), rootNode);
7657    const getChildNodeAtRelativeOffset = (relativeOffset, caretPosition) => {
7658      if (!caretPosition) {
7659        return Optional.none();
7660      }
7661      const container = caretPosition.container();
7662      const offset = caretPosition.offset();
7663      if (!isElement$2(container)) {
7664        return Optional.none();
7665      }
7666      return Optional.from(container.childNodes[offset + relativeOffset]);
7667    };
7668    const beforeAfter = (before, node) => {
7669      var _a;
7670      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
7671      const range = doc.createRange();
7672      if (before) {
7673        range.setStartBefore(node);
7674        range.setEndBefore(node);
7675      } else {
7676        range.setStartAfter(node);
7677        range.setEndAfter(node);
7678      }
7679      return range;
7680    };
7681    const isNodesInSameBlock = (root, node1, node2) => getParentBlock$3(node1, root) === getParentBlock$3(node2, root);
7682    const lean = (left, root, node) => {
7683      const siblingName = left ? 'previousSibling' : 'nextSibling';
7684      let tempNode = node;
7685      while (tempNode && tempNode !== root) {
7686        let sibling = tempNode[siblingName];
7687        if (sibling && isCaretContainer(sibling)) {
7688          sibling = sibling[siblingName];
7689        }
7690        if (isContentEditableFalse$7(sibling) || isMedia(sibling)) {
7691          if (isNodesInSameBlock(root, sibling, tempNode)) {
7692            return sibling;
7693          }
7694          break;
7695        }
7696        if (isCaretCandidate$1(sibling)) {
7697          break;
7698        }
7699        tempNode = tempNode.parentNode;
7700      }
7701      return null;
7702    };
7703    const before$2 = curry(beforeAfter, true);
7704    const after$2 = curry(beforeAfter, false);
7705    const normalizeRange = (direction, root, range) => {
7706      let node;
7707      const leanLeft = curry(lean, true, root);
7708      const leanRight = curry(lean, false, root);
7709      const container = range.startContainer;
7710      const offset = range.startOffset;
7711      if (isCaretContainerBlock$1(container)) {
7712        const block = isText$4(container) ? container.parentNode : container;
7713        const location = block.getAttribute('data-mce-caret');
7714        if (location === 'before') {
7715          node = block.nextSibling;
7716          if (isFakeCaretTarget(node)) {
7717            return before$2(node);
7718          }
7719        }
7720        if (location === 'after') {
7721          node = block.previousSibling;
7722          if (isFakeCaretTarget(node)) {
7723            return after$2(node);
7724          }
7725        }
7726      }
7727      if (!range.collapsed) {
7728        return range;
7729      }
7730      if (isText$a(container)) {
7731        if (isCaretContainer(container)) {
7732          if (direction === 1) {
7733            node = leanRight(container);
7734            if (node) {
7735              return before$2(node);
7736            }
7737            node = leanLeft(container);
7738            if (node) {
7739              return after$2(node);
7740            }
7741          }
7742          if (direction === -1) {
7743            node = leanLeft(container);
7744            if (node) {
7745              return after$2(node);
7746            }
7747            node = leanRight(container);
7748            if (node) {
7749              return before$2(node);
7750            }
7751          }
7752          return range;
7753        }
7754        if (endsWithCaretContainer$1(container) && offset >= container.data.length - 1) {
7755          if (direction === 1) {
7756            node = leanRight(container);
7757            if (node) {
7758              return before$2(node);
7759            }
7760          }
7761          return range;
7762        }
7763        if (startsWithCaretContainer$1(container) && offset <= 1) {
7764          if (direction === -1) {
7765            node = leanLeft(container);
7766            if (node) {
7767              return after$2(node);
7768            }
7769          }
7770          return range;
7771        }
7772        if (offset === container.data.length) {
7773          node = leanRight(container);
7774          if (node) {
7775            return before$2(node);
7776          }
7777          return range;
7778        }
7779        if (offset === 0) {
7780          node = leanLeft(container);
7781          if (node) {
7782            return after$2(node);
7783          }
7784          return range;
7785        }
7786      }
7787      return range;
7788    };
7789    const getRelativeCefElm = (forward, caretPosition) => getChildNodeAtRelativeOffset(forward ? 0 : -1, caretPosition).filter(isContentEditableFalse$7);
7790    const getNormalizedRangeEndPoint = (direction, root, range) => {
7791      const normalizedRange = normalizeRange(direction, root, range);
7792      return direction === -1 ? CaretPosition.fromRangeStart(normalizedRange) : CaretPosition.fromRangeEnd(normalizedRange);
7793    };
7794    const getElementFromPosition = pos => Optional.from(pos.getNode()).map(SugarElement.fromDom);
7795    const getElementFromPrevPosition = pos => Optional.from(pos.getNode(true)).map(SugarElement.fromDom);
7796    const getVisualCaretPosition = (walkFn, caretPosition) => {
7797      let pos = caretPosition;
7798      while (pos = walkFn(pos)) {
7799        if (pos.isVisible()) {
7800          return pos;
7801        }
7802      }
7803      return pos;
7804    };
7805    const isMoveInsideSameBlock = (from, to) => {
7806      const inSameBlock = isInSameBlock(from, to);
7807      if (!inSameBlock && isBr$6(from.getNode())) {
7808        return true;
7809      }
7810      return inSameBlock;
7811    };
7812
7813    var HDirection;
7814    (function (HDirection) {
7815      HDirection[HDirection['Backwards'] = -1] = 'Backwards';
7816      HDirection[HDirection['Forwards'] = 1] = 'Forwards';
7817    }(HDirection || (HDirection = {})));
7818    const isContentEditableFalse$6 = isContentEditableFalse$b;
7819    const isText$3 = isText$a;
7820    const isElement$1 = isElement$6;
7821    const isBr$2 = isBr$6;
7822    const isCaretCandidate = isCaretCandidate$3;
7823    const isAtomic = isAtomic$1;
7824    const isEditableCaretCandidate = isEditableCaretCandidate$1;
7825    const getParents$3 = (node, root) => {
7826      const parents = [];
7827      let tempNode = node;
7828      while (tempNode && tempNode !== root) {
7829        parents.push(tempNode);
7830        tempNode = tempNode.parentNode;
7831      }
7832      return parents;
7833    };
7834    const nodeAtIndex = (container, offset) => {
7835      if (container.hasChildNodes() && offset < container.childNodes.length) {
7836        return container.childNodes[offset];
7837      }
7838      return null;
7839    };
7840    const getCaretCandidatePosition = (direction, node) => {
7841      if (isForwards(direction)) {
7842        if (isCaretCandidate(node.previousSibling) && !isText$3(node.previousSibling)) {
7843          return CaretPosition.before(node);
7844        }
7845        if (isText$3(node)) {
7846          return CaretPosition(node, 0);
7847        }
7848      }
7849      if (isBackwards(direction)) {
7850        if (isCaretCandidate(node.nextSibling) && !isText$3(node.nextSibling)) {
7851          return CaretPosition.after(node);
7852        }
7853        if (isText$3(node)) {
7854          return CaretPosition(node, node.data.length);
7855        }
7856      }
7857      if (isBackwards(direction)) {
7858        if (isBr$2(node)) {
7859          return CaretPosition.before(node);
7860        }
7861        return CaretPosition.after(node);
7862      }
7863      return CaretPosition.before(node);
7864    };
7865    const moveForwardFromBr = (root, nextNode) => {
7866      const nextSibling = nextNode.nextSibling;
7867      if (nextSibling && isCaretCandidate(nextSibling)) {
7868        if (isText$3(nextSibling)) {
7869          return CaretPosition(nextSibling, 0);
7870        } else {
7871          return CaretPosition.before(nextSibling);
7872        }
7873      } else {
7874        return findCaretPosition$1(HDirection.Forwards, CaretPosition.after(nextNode), root);
7875      }
7876    };
7877    const findCaretPosition$1 = (direction, startPos, root) => {
7878      let node;
7879      let nextNode;
7880      let innerNode;
7881      let caretPosition;
7882      if (!isElement$1(root) || !startPos) {
7883        return null;
7884      }
7885      if (startPos.isEqual(CaretPosition.after(root)) && root.lastChild) {
7886        caretPosition = CaretPosition.after(root.lastChild);
7887        if (isBackwards(direction) && isCaretCandidate(root.lastChild) && isElement$1(root.lastChild)) {
7888          return isBr$2(root.lastChild) ? CaretPosition.before(root.lastChild) : caretPosition;
7889        }
7890      } else {
7891        caretPosition = startPos;
7892      }
7893      const container = caretPosition.container();
7894      let offset = caretPosition.offset();
7895      if (isText$3(container)) {
7896        if (isBackwards(direction) && offset > 0) {
7897          return CaretPosition(container, --offset);
7898        }
7899        if (isForwards(direction) && offset < container.length) {
7900          return CaretPosition(container, ++offset);
7901        }
7902        node = container;
7903      } else {
7904        if (isBackwards(direction) && offset > 0) {
7905          nextNode = nodeAtIndex(container, offset - 1);
7906          if (isCaretCandidate(nextNode)) {
7907            if (!isAtomic(nextNode)) {
7908              innerNode = findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
7909              if (innerNode) {
7910                if (isText$3(innerNode)) {
7911                  return CaretPosition(innerNode, innerNode.data.length);
7912                }
7913                return CaretPosition.after(innerNode);
7914              }
7915            }
7916            if (isText$3(nextNode)) {
7917              return CaretPosition(nextNode, nextNode.data.length);
7918            }
7919            return CaretPosition.before(nextNode);
7920          }
7921        }
7922        if (isForwards(direction) && offset < container.childNodes.length) {
7923          nextNode = nodeAtIndex(container, offset);
7924          if (isCaretCandidate(nextNode)) {
7925            if (isBr$2(nextNode)) {
7926              return moveForwardFromBr(root, nextNode);
7927            }
7928            if (!isAtomic(nextNode)) {
7929              innerNode = findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
7930              if (innerNode) {
7931                if (isText$3(innerNode)) {
7932                  return CaretPosition(innerNode, 0);
7933                }
7934                return CaretPosition.before(innerNode);
7935              }
7936            }
7937            if (isText$3(nextNode)) {
7938              return CaretPosition(nextNode, 0);
7939            }
7940            return CaretPosition.after(nextNode);
7941          }
7942        }
7943        node = nextNode ? nextNode : caretPosition.getNode();
7944      }
7945      if (node && (isForwards(direction) && caretPosition.isAtEnd() || isBackwards(direction) && caretPosition.isAtStart())) {
7946        node = findNode(node, direction, always, root, true);
7947        if (isEditableCaretCandidate(node, root)) {
7948          return getCaretCandidatePosition(direction, node);
7949        }
7950      }
7951      nextNode = node ? findNode(node, direction, isEditableCaretCandidate, root) : node;
7952      const rootContentEditableFalseElm = last$2(filter$5(getParents$3(container, root), isContentEditableFalse$6));
7953      if (rootContentEditableFalseElm && (!nextNode || !rootContentEditableFalseElm.contains(nextNode))) {
7954        if (isForwards(direction)) {
7955          caretPosition = CaretPosition.after(rootContentEditableFalseElm);
7956        } else {
7957          caretPosition = CaretPosition.before(rootContentEditableFalseElm);
7958        }
7959        return caretPosition;
7960      }
7961      if (nextNode) {
7962        return getCaretCandidatePosition(direction, nextNode);
7963      }
7964      return null;
7965    };
7966    const CaretWalker = root => ({
7967      next: caretPosition => {
7968        return findCaretPosition$1(HDirection.Forwards, caretPosition, root);
7969      },
7970      prev: caretPosition => {
7971        return findCaretPosition$1(HDirection.Backwards, caretPosition, root);
7972      }
7973    });
7974
7975    const walkToPositionIn = (forward, root, start) => {
7976      const position = forward ? CaretPosition.before(start) : CaretPosition.after(start);
7977      return fromPosition(forward, root, position);
7978    };
7979    const afterElement = node => isBr$6(node) ? CaretPosition.before(node) : CaretPosition.after(node);
7980    const isBeforeOrStart = position => {
7981      if (CaretPosition.isTextPosition(position)) {
7982        return position.offset() === 0;
7983      } else {
7984        return isCaretCandidate$3(position.getNode());
7985      }
7986    };
7987    const isAfterOrEnd = position => {
7988      if (CaretPosition.isTextPosition(position)) {
7989        const container = position.container();
7990        return position.offset() === container.data.length;
7991      } else {
7992        return isCaretCandidate$3(position.getNode(true));
7993      }
7994    };
7995    const isBeforeAfterSameElement = (from, to) => !CaretPosition.isTextPosition(from) && !CaretPosition.isTextPosition(to) && from.getNode() === to.getNode(true);
7996    const isAtBr = position => !CaretPosition.isTextPosition(position) && isBr$6(position.getNode());
7997    const shouldSkipPosition = (forward, from, to) => {
7998      if (forward) {
7999        return !isBeforeAfterSameElement(from, to) && !isAtBr(from) && isAfterOrEnd(from) && isBeforeOrStart(to);
8000      } else {
8001        return !isBeforeAfterSameElement(to, from) && isBeforeOrStart(from) && isAfterOrEnd(to);
8002      }
8003    };
8004    const fromPosition = (forward, root, pos) => {
8005      const walker = CaretWalker(root);
8006      return Optional.from(forward ? walker.next(pos) : walker.prev(pos));
8007    };
8008    const navigate = (forward, root, from) => fromPosition(forward, root, from).bind(to => {
8009      if (isInSameBlock(from, to, root) && shouldSkipPosition(forward, from, to)) {
8010        return fromPosition(forward, root, to);
8011      } else {
8012        return Optional.some(to);
8013      }
8014    });
8015    const navigateIgnore = (forward, root, from, ignoreFilter) => navigate(forward, root, from).bind(pos => ignoreFilter(pos) ? navigateIgnore(forward, root, pos, ignoreFilter) : Optional.some(pos));
8016    const positionIn = (forward, element) => {
8017      const startNode = forward ? element.firstChild : element.lastChild;
8018      if (isText$a(startNode)) {
8019        return Optional.some(CaretPosition(startNode, forward ? 0 : startNode.data.length));
8020      } else if (startNode) {
8021        if (isCaretCandidate$3(startNode)) {
8022          return Optional.some(forward ? CaretPosition.before(startNode) : afterElement(startNode));
8023        } else {
8024          return walkToPositionIn(forward, element, startNode);
8025        }
8026      } else {
8027        return Optional.none();
8028      }
8029    };
8030    const nextPosition = curry(fromPosition, true);
8031    const prevPosition = curry(fromPosition, false);
8032    const firstPositionIn = curry(positionIn, true);
8033    const lastPositionIn = curry(positionIn, false);
8034
8035    const CARET_ID = '_mce_caret';
8036    const isCaretNode = node => isElement$6(node) && node.id === CARET_ID;
8037    const getParentCaretContainer = (body, node) => {
8038      let currentNode = node;
8039      while (currentNode && currentNode !== body) {
8040        if (isCaretNode(currentNode)) {
8041          return currentNode;
8042        }
8043        currentNode = currentNode.parentNode;
8044      }
8045      return null;
8046    };
8047
8048    const isStringPathBookmark = bookmark => isString(bookmark.start);
8049    const isRangeBookmark = bookmark => has$2(bookmark, 'rng');
8050    const isIdBookmark = bookmark => has$2(bookmark, 'id');
8051    const isIndexBookmark = bookmark => has$2(bookmark, 'name');
8052    const isPathBookmark = bookmark => Tools.isArray(bookmark.start);
8053
8054    const isForwardBookmark = bookmark => !isIndexBookmark(bookmark) && isBoolean(bookmark.forward) ? bookmark.forward : true;
8055    const addBogus = (dom, node) => {
8056      if (isElement$6(node) && dom.isBlock(node) && !node.innerHTML) {
8057        node.innerHTML = '<br data-mce-bogus="1" />';
8058      }
8059      return node;
8060    };
8061    const resolveCaretPositionBookmark = (dom, bookmark) => {
8062      const startPos = Optional.from(resolve$1(dom.getRoot(), bookmark.start));
8063      const endPos = Optional.from(resolve$1(dom.getRoot(), bookmark.end));
8064      return lift2(startPos, endPos, (start, end) => {
8065        const range = dom.createRng();
8066        range.setStart(start.container(), start.offset());
8067        range.setEnd(end.container(), end.offset());
8068        return {
8069          range,
8070          forward: isForwardBookmark(bookmark)
8071        };
8072      });
8073    };
8074    const insertZwsp = (node, rng) => {
8075      var _a;
8076      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
8077      const textNode = doc.createTextNode(ZWSP$1);
8078      node.appendChild(textNode);
8079      rng.setStart(textNode, 0);
8080      rng.setEnd(textNode, 0);
8081    };
8082    const isEmpty$1 = node => !node.hasChildNodes();
8083    const tryFindRangePosition = (node, rng) => lastPositionIn(node).fold(never, pos => {
8084      rng.setStart(pos.container(), pos.offset());
8085      rng.setEnd(pos.container(), pos.offset());
8086      return true;
8087    });
8088    const padEmptyCaretContainer = (root, node, rng) => {
8089      if (isEmpty$1(node) && getParentCaretContainer(root, node)) {
8090        insertZwsp(node, rng);
8091        return true;
8092      } else {
8093        return false;
8094      }
8095    };
8096    const setEndPoint = (dom, start, bookmark, rng) => {
8097      const point = bookmark[start ? 'start' : 'end'];
8098      const root = dom.getRoot();
8099      if (point) {
8100        let node = root;
8101        let offset = point[0];
8102        for (let i = point.length - 1; node && i >= 1; i--) {
8103          const children = node.childNodes;
8104          if (padEmptyCaretContainer(root, node, rng)) {
8105            return true;
8106          }
8107          if (point[i] > children.length - 1) {
8108            if (padEmptyCaretContainer(root, node, rng)) {
8109              return true;
8110            }
8111            return tryFindRangePosition(node, rng);
8112          }
8113          node = children[point[i]];
8114        }
8115        if (isText$a(node)) {
8116          offset = Math.min(point[0], node.data.length);
8117        }
8118        if (isElement$6(node)) {
8119          offset = Math.min(point[0], node.childNodes.length);
8120        }
8121        if (start) {
8122          rng.setStart(node, offset);
8123        } else {
8124          rng.setEnd(node, offset);
8125        }
8126      }
8127      return true;
8128    };
8129    const isValidTextNode = node => isText$a(node) && node.data.length > 0;
8130    const restoreEndPoint = (dom, suffix, bookmark) => {
8131      const marker = dom.get(bookmark.id + '_' + suffix);
8132      const markerParent = marker === null || marker === void 0 ? void 0 : marker.parentNode;
8133      const keep = bookmark.keep;
8134      if (marker && markerParent) {
8135        let container;
8136        let offset;
8137        if (suffix === 'start') {
8138          if (!keep) {
8139            container = markerParent;
8140            offset = dom.nodeIndex(marker);
8141          } else {
8142            if (marker.hasChildNodes()) {
8143              container = marker.firstChild;
8144              offset = 1;
8145            } else if (isValidTextNode(marker.nextSibling)) {
8146              container = marker.nextSibling;
8147              offset = 0;
8148            } else if (isValidTextNode(marker.previousSibling)) {
8149              container = marker.previousSibling;
8150              offset = marker.previousSibling.data.length;
8151            } else {
8152              container = markerParent;
8153              offset = dom.nodeIndex(marker) + 1;
8154            }
8155          }
8156        } else {
8157          if (!keep) {
8158            container = markerParent;
8159            offset = dom.nodeIndex(marker);
8160          } else {
8161            if (marker.hasChildNodes()) {
8162              container = marker.firstChild;
8163              offset = 1;
8164            } else if (isValidTextNode(marker.previousSibling)) {
8165              container = marker.previousSibling;
8166              offset = marker.previousSibling.data.length;
8167            } else {
8168              container = markerParent;
8169              offset = dom.nodeIndex(marker);
8170            }
8171          }
8172        }
8173        if (!keep) {
8174          const prev = marker.previousSibling;
8175          const next = marker.nextSibling;
8176          Tools.each(Tools.grep(marker.childNodes), node => {
8177            if (isText$a(node)) {
8178              node.data = node.data.replace(/\uFEFF/g, '');
8179            }
8180          });
8181          let otherMarker;
8182          while (otherMarker = dom.get(bookmark.id + '_' + suffix)) {
8183            dom.remove(otherMarker, true);
8184          }
8185          if (isText$a(next) && isText$a(prev) && !Env.browser.isOpera()) {
8186            const idx = prev.data.length;
8187            prev.appendData(next.data);
8188            dom.remove(next);
8189            container = prev;
8190            offset = idx;
8191          }
8192        }
8193        return Optional.some(CaretPosition(container, offset));
8194      } else {
8195        return Optional.none();
8196      }
8197    };
8198    const resolvePaths = (dom, bookmark) => {
8199      const range = dom.createRng();
8200      if (setEndPoint(dom, true, bookmark, range) && setEndPoint(dom, false, bookmark, range)) {
8201        return Optional.some({
8202          range,
8203          forward: isForwardBookmark(bookmark)
8204        });
8205      } else {
8206        return Optional.none();
8207      }
8208    };
8209    const resolveId = (dom, bookmark) => {
8210      const startPos = restoreEndPoint(dom, 'start', bookmark);
8211      const endPos = restoreEndPoint(dom, 'end', bookmark);
8212      return lift2(startPos, endPos.or(startPos), (spos, epos) => {
8213        const range = dom.createRng();
8214        range.setStart(addBogus(dom, spos.container()), spos.offset());
8215        range.setEnd(addBogus(dom, epos.container()), epos.offset());
8216        return {
8217          range,
8218          forward: isForwardBookmark(bookmark)
8219        };
8220      });
8221    };
8222    const resolveIndex = (dom, bookmark) => Optional.from(dom.select(bookmark.name)[bookmark.index]).map(elm => {
8223      const range = dom.createRng();
8224      range.selectNode(elm);
8225      return {
8226        range,
8227        forward: true
8228      };
8229    });
8230    const resolve = (selection, bookmark) => {
8231      const dom = selection.dom;
8232      if (bookmark) {
8233        if (isPathBookmark(bookmark)) {
8234          return resolvePaths(dom, bookmark);
8235        } else if (isStringPathBookmark(bookmark)) {
8236          return resolveCaretPositionBookmark(dom, bookmark);
8237        } else if (isIdBookmark(bookmark)) {
8238          return resolveId(dom, bookmark);
8239        } else if (isIndexBookmark(bookmark)) {
8240          return resolveIndex(dom, bookmark);
8241        } else if (isRangeBookmark(bookmark)) {
8242          return Optional.some({
8243            range: bookmark.rng,
8244            forward: isForwardBookmark(bookmark)
8245          });
8246        }
8247      }
8248      return Optional.none();
8249    };
8250
8251    const getBookmark$1 = (selection, type, normalized) => {
8252      return getBookmark$2(selection, type, normalized);
8253    };
8254    const moveToBookmark = (selection, bookmark) => {
8255      resolve(selection, bookmark).each(({range, forward}) => {
8256        selection.setRng(range, forward);
8257      });
8258    };
8259    const isBookmarkNode$1 = node => {
8260      return isElement$6(node) && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
8261    };
8262
8263    const is = expected => actual => expected === actual;
8264    const isNbsp = is(nbsp);
8265    const isWhiteSpace = chr => chr !== '' && ' \f\n\r\t\x0B'.indexOf(chr) !== -1;
8266    const isContent = chr => !isWhiteSpace(chr) && !isNbsp(chr) && !isZwsp$
82661
vendor: 28,894 bytes, lines 8266-8969
8266(chr);
8267
8268    const hexColour = value => ({ value: normalizeHex(value) });
8269    const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
8270    const toHex = component => {
8271      const hex = component.toString(16);
8272      return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
8273    };
8274    const fromRgba = rgbaColour => {
8275      const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
8276      return hexColour(value);
8277    };
8278
8279    const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
8280    const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
8281    const rgbaColour = (red, green, blue, alpha) => ({
8282      red,
8283      green,
8284      blue,
8285      alpha
8286    });
8287    const fromStringValues = (red, green, blue, alpha) => {
8288      const r = parseInt(red, 10);
8289      const g = parseInt(green, 10);
8290      const b = parseInt(blue, 10);
8291      const a = parseFloat(alpha);
8292      return rgbaColour(r, g, b, a);
8293    };
8294    const fromString = rgbaString => {
8295      if (rgbaString === 'transparent') {
8296        return Optional.some(rgbaColour(0, 0, 0, 0));
8297      }
8298      const rgbMatch = rgbRegex.exec(rgbaString);
8299      if (rgbMatch !== null) {
8300        return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
8301      }
8302      const rgbaMatch = rgbaRegex.exec(rgbaString);
8303      if (rgbaMatch !== null) {
8304        return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
8305      }
8306      return Optional.none();
8307    };
8308
8309    const rgbaToHexString = color => fromString(color).map(fromRgba).map(h => '#' + h.value).getOr(color);
8310
8311    const getRanges$1 = selection => {
8312      const ranges = [];
8313      if (selection) {
8314        for (let i = 0; i < selection.rangeCount; i++) {
8315          ranges.push(selection.getRangeAt(i));
8316        }
8317      }
8318      return ranges;
8319    };
8320    const getSelectedNodes = ranges => {
8321      return bind$3(ranges, range => {
8322        const node = getSelectedNode(range);
8323        return node ? [SugarElement.fromDom(node)] : [];
8324      });
8325    };
8326    const hasMultipleRanges = selection => {
8327      return getRanges$1(selection).length > 1;
8328    };
8329
8330    const getCellsFromRanges = ranges => filter$5(getSelectedNodes(ranges), isTableCell$2);
8331    const getCellsFromElement = elm => descendants(elm, 'td[data-mce-selected],th[data-mce-selected]');
8332    const getCellsFromElementOrRanges = (ranges, element) => {
8333      const selectedCells = getCellsFromElement(element);
8334      return selectedCells.length > 0 ? selectedCells : getCellsFromRanges(ranges);
8335    };
8336    const getCellsFromEditor = editor => getCellsFromElementOrRanges(getRanges$1(editor.selection.getSel()), SugarElement.fromDom(editor.getBody()));
8337    const getClosestTable = (cell, isRoot) => ancestor$3(cell, 'table', isRoot);
8338
8339    const getStartNode = rng => {
8340      const sc = rng.startContainer, so = rng.startOffset;
8341      if (isText$a(sc)) {
8342        return so === 0 ? Optional.some(SugarElement.fromDom(sc)) : Optional.none();
8343      } else {
8344        return Optional.from(sc.childNodes[so]).map(SugarElement.fromDom);
8345      }
8346    };
8347    const getEndNode = rng => {
8348      const ec = rng.endContainer, eo = rng.endOffset;
8349      if (isText$a(ec)) {
8350        return eo === ec.data.length ? Optional.some(SugarElement.fromDom(ec)) : Optional.none();
8351      } else {
8352        return Optional.from(ec.childNodes[eo - 1]).map(SugarElement.fromDom);
8353      }
8354    };
8355    const getFirstChildren = node => {
8356      return firstChild(node).fold(constant([node]), child => {
8357        return [node].concat(getFirstChildren(child));
8358      });
8359    };
8360    const getLastChildren = node => {
8361      return lastChild(node).fold(constant([node]), child => {
8362        if (name(child) === 'br') {
8363          return prevSibling(child).map(sibling => {
8364            return [node].concat(getLastChildren(sibling));
8365          }).getOr([]);
8366        } else {
8367          return [node].concat(getLastChildren(child));
8368        }
8369      });
8370    };
8371    const hasAllContentsSelected = (elm, rng) => {
8372      return lift2(getStartNode(rng), getEndNode(rng), (startNode, endNode) => {
8373        const start = find$2(getFirstChildren(elm), curry(eq, startNode));
8374        const end = find$2(getLastChildren(elm), curry(eq, endNode));
8375        return start.isSome() && end.isSome();
8376      }).getOr(false);
8377    };
8378    const moveEndPoint = (dom, rng, node, start) => {
8379      const root = node;
8380      const walker = new DomTreeWalker(node, root);
8381      const moveCaretBeforeOnEnterElementsMap = filter$4(dom.schema.getMoveCaretBeforeOnEnterElements(), (_, name) => !contains$2([
8382        'td',
8383        'th',
8384        'table'
8385      ], name.toLowerCase()));
8386      let currentNode = node;
8387      do {
8388        if (isText$a(currentNode) && Tools.trim(currentNode.data).length !== 0) {
8389          if (start) {
8390            rng.setStart(currentNode, 0);
8391          } else {
8392            rng.setEnd(currentNode, currentNode.data.length);
8393          }
8394          return;
8395        }
8396        if (moveCaretBeforeOnEnterElementsMap[currentNode.nodeName]) {
8397          if (start) {
8398            rng.setStartBefore(currentNode);
8399          } else {
8400            if (currentNode.nodeName === 'BR') {
8401              rng.setEndBefore(currentNode);
8402            } else {
8403              rng.setEndAfter(currentNode);
8404            }
8405          }
8406          return;
8407        }
8408      } while (currentNode = start ? walker.next() : walker.prev());
8409      if (root.nodeName === 'BODY') {
8410        if (start) {
8411          rng.setStart(root, 0);
8412        } else {
8413          rng.setEnd(root, root.childNodes.length);
8414        }
8415      }
8416    };
8417    const hasAnyRanges = editor => {
8418      const sel = editor.selection.getSel();
8419      return isNonNullable(sel) && sel.rangeCount > 0;
8420    };
8421    const runOnRanges = (editor, executor) => {
8422      const fakeSelectionNodes = getCellsFromEditor(editor);
8423      if (fakeSelectionNodes.length > 0) {
8424        each$e(fakeSelectionNodes, elem => {
8425          const node = elem.dom;
8426          const fakeNodeRng = editor.dom.createRng();
8427          fakeNodeRng.setStartBefore(node);
8428          fakeNodeRng.setEndAfter(node);
8429          executor(fakeNodeRng, true);
8430        });
8431      } else {
8432        executor(editor.selection.getRng(), false);
8433      }
8434    };
8435    const preserve = (selection, fillBookmark, executor) => {
8436      const bookmark = getPersistentBookmark(selection, fillBookmark);
8437      executor(bookmark);
8438      selection.moveToBookmark(bookmark);
8439    };
8440
8441    const isNode = node => isNumber(node === null || node === void 0 ? void 0 : node.nodeType);
8442    const isElementNode$1 = node => isElement$6(node) && !isBookmarkNode$1(node) && !isCaretNode(node) && !isBogus$2(node);
8443    const isElementDirectlySelected = (dom, node) => {
8444      if (isElementNode$1(node) && !/^(TD|TH)$/.test(node.nodeName)) {
8445        const selectedAttr = dom.getAttrib(node, 'data-mce-selected');
8446        const value = parseInt(selectedAttr, 10);
8447        return !isNaN(value) && value > 0;
8448      } else {
8449        return false;
8450      }
8451    };
8452    const isEditable$2 = elm => elm.isContentEditable === true;
8453    const preserveSelection = (editor, action, shouldMoveStart) => {
8454      const {selection, dom} = editor;
8455      const selectedNodeBeforeAction = selection.getNode();
8456      const isSelectedBeforeNodeNoneditable = isContentEditableFalse$b(selectedNodeBeforeAction);
8457      preserve(selection, true, () => {
8458        action();
8459      });
8460      const isBeforeNodeStillNoneditable = isSelectedBeforeNodeNoneditable && isContentEditableFalse$b(selectedNodeBeforeAction);
8461      if (isBeforeNodeStillNoneditable && dom.isChildOf(selectedNodeBeforeAction, editor.getBody())) {
8462        editor.selection.select(selectedNodeBeforeAction);
8463      } else if (shouldMoveStart(selection.getStart())) {
8464        moveStartToNearestText(dom, selection);
8465      }
8466    };
8467    const moveStartToNearestText = (dom, selection) => {
8468      var _a, _b;
8469      const rng = selection.getRng();
8470      const {startContainer, startOffset} = rng;
8471      const selectedNode = selection.getNode();
8472      if (isElementDirectlySelected(dom, selectedNode)) {
8473        return;
8474      }
8475      if (isElement$6(startContainer)) {
8476        const nodes = startContainer.childNodes;
8477        const root = dom.getRoot();
8478        let walker;
8479        if (startOffset < nodes.length) {
8480          const startNode = nodes[startOffset];
8481          walker = new DomTreeWalker(startNode, (_a = dom.getParent(startNode, dom.isBlock)) !== null && _a !== void 0 ? _a : root);
8482        } else {
8483          const startNode = nodes[nodes.length - 1];
8484          walker = new DomTreeWalker(startNode, (_b = dom.getParent(startNode, dom.isBlock)) !== null && _b !== void 0 ? _b : root);
8485          walker.next(true);
8486        }
8487        for (let node = walker.current(); node; node = walker.next()) {
8488          if (dom.getContentEditable(node) === 'false') {
8489            return;
8490          } else if (isText$a(node) && !isWhiteSpaceNode$1(node)) {
8491            rng.setStart(node, 0);
8492            selection.setRng(rng);
8493            return;
8494          }
8495        }
8496      }
8497    };
8498    const getNonWhiteSpaceSibling = (node, next, inc) => {
8499      if (node) {
8500        const nextName = next ? 'nextSibling' : 'previousSibling';
8501        for (node = inc ? node : node[nextName]; node; node = node[nextName]) {
8502          if (isElement$6(node) || !isWhiteSpaceNode$1(node)) {
8503            return node;
8504          }
8505        }
8506      }
8507      return undefined;
8508    };
8509    const isTextBlock$1 = (schema, node) => !!schema.getTextBlockElements()[node.nodeName.toLowerCase()] || isTransparentBlock(schema, node);
8510    const isValid = (ed, parent, child) => {
8511      return ed.schema.isValidChild(parent, child);
8512    };
8513    const isWhiteSpaceNode$1 = (node, allowSpaces = false) => {
8514      if (isNonNullable(node) && isText$a(node)) {
8515        const data = allowSpaces ? node.data.replace(/ /g, '\xA0') : node.data;
8516        return isWhitespaceText(data);
8517      } else {
8518        return false;
8519      }
8520    };
8521    const isEmptyTextNode$1 = node => {
8522      return isNonNullable(node) && isText$a(node) && node.length === 0;
8523    };
8524    const isWrapNoneditableTarget = (editor, node) => {
8525      const baseDataSelector = '[data-mce-cef-wrappable]';
8526      const formatNoneditableSelector = getFormatNoneditableSelector(editor);
8527      const selector = isEmpty$3(formatNoneditableSelector) ? baseDataSelector : `${ baseDataSelector },${ formatNoneditableSelector }`;
8528      return is$1(SugarElement.fromDom(node), selector);
8529    };
8530    const isWrappableNoneditable = (editor, node) => {
8531      const dom = editor.dom;
8532      return isElementNode$1(node) && dom.getContentEditable(node) === 'false' && isWrapNoneditableTarget(editor, node) && dom.select('[contenteditable="true"]', node).length === 0;
8533    };
8534    const replaceVars = (value, vars) => {
8535      if (isFunction(value)) {
8536        return value(vars);
8537      } else if (isNonNullable(vars)) {
8538        value = value.replace(/%(\w+)/g, (str, name) => {
8539          return vars[name] || str;
8540        });
8541      }
8542      return value;
8543    };
8544    const isEq$5 = (str1, str2) => {
8545      str1 = str1 || '';
8546      str2 = str2 || '';
8547      str1 = '' + (str1.nodeName || str1);
8548      str2 = '' + (str2.nodeName || str2);
8549      return str1.toLowerCase() === str2.toLowerCase();
8550    };
8551    const normalizeStyleValue = (value, name) => {
8552      if (isNullable(value)) {
8553        return null;
8554      } else {
8555        let strValue = String(value);
8556        if (name === 'color' || name === 'backgroundColor') {
8557          strValue = rgbaToHexString(strValue);
8558        }
8559        if (name === 'fontWeight' && value === 700) {
8560          strValue = 'bold';
8561        }
8562        if (name === 'fontFamily') {
8563          strValue = strValue.replace(/[\'\"]/g, '').replace(/,\s+/g, ',');
8564        }
8565        return strValue;
8566      }
8567    };
8568    const getStyle = (dom, node, name) => {
8569      const style = dom.getStyle(node, name);
8570      return normalizeStyleValue(style, name);
8571    };
8572    const getTextDecoration = (dom, node) => {
8573      let decoration;
8574      dom.getParent(node, n => {
8575        if (isElement$6(n)) {
8576          decoration = dom.getStyle(n, 'text-decoration');
8577          return !!decoration && decoration !== 'none';
8578        } else {
8579          return false;
8580        }
8581      });
8582      return decoration;
8583    };
8584    const getParents$2 = (dom, node, selector) => {
8585      return dom.getParents(node, selector, dom.getRoot());
8586    };
8587    const isFormatPredicate = (editor, formatName, predicate) => {
8588      const formats = editor.formatter.get(formatName);
8589      return isNonNullable(formats) && exists(formats, predicate);
8590    };
8591    const isVariableFormatName = (editor, formatName) => {
8592      const hasVariableValues = format => {
8593        const isVariableValue = val => isFunction(val) || val.length > 1 && val.charAt(0) === '%';
8594        return exists([
8595          'styles',
8596          'attributes'
8597        ], key => get$a(format, key).exists(field => {
8598          const fieldValues = isArray$1(field) ? field : values(field);
8599          return exists(fieldValues, isVariableValue);
8600        }));
8601      };
8602      return isFormatPredicate(editor, formatName, hasVariableValues);
8603    };
8604    const areSimilarFormats = (editor, formatName, otherFormatName) => {
8605      const validKeys = [
8606        'inline',
8607        'block',
8608        'selector',
8609        'attributes',
8610        'styles',
8611        'classes'
8612      ];
8613      const filterObj = format => filter$4(format, (_, key) => exists(validKeys, validKey => validKey === key));
8614      return isFormatPredicate(editor, formatName, fmt1 => {
8615        const filteredFmt1 = filterObj(fmt1);
8616        return isFormatPredicate(editor, otherFormatName, fmt2 => {
8617          const filteredFmt2 = filterObj(fmt2);
8618          return equal$1(filteredFmt1, filteredFmt2);
8619        });
8620      });
8621    };
8622    const isBlockFormat = format => hasNonNullableKey(format, 'block');
8623    const isWrappingBlockFormat = format => isBlockFormat(format) && format.wrapper === true;
8624    const isNonWrappingBlockFormat = format => isBlockFormat(format) && format.wrapper !== true;
8625    const isSelectorFormat = format => hasNonNullableKey(format, 'selector');
8626    const isInlineFormat = format => hasNonNullableKey(format, 'inline');
8627    const isMixedFormat = format => isSelectorFormat(format) && isInlineFormat(format) && is$2(get$a(format, 'mixed'), true);
8628    const shouldExpandToSelector = format => isSelectorFormat(format) && format.expand !== false && !isInlineFormat(format);
8629
8630    const isBookmarkNode = isBookmarkNode$1;
8631    const getParents$1 = getParents$2;
8632    const isWhiteSpaceNode = isWhiteSpaceNode$1;
8633    const isTextBlock = isTextBlock$1;
8634    const isBogusBr = node => {
8635      return isBr$6(node) && node.getAttribute('data-mce-bogus') && !node.nextSibling;
8636    };
8637    const findParentContentEditable = (dom, node) => {
8638      let parent = node;
8639      while (parent) {
8640        if (isElement$6(parent) && dom.getContentEditable(parent)) {
8641          return dom.getContentEditable(parent) === 'false' ? parent : node;
8642        }
8643        parent = parent.parentNode;
8644      }
8645      return node;
8646    };
8647    const walkText = (start, node, offset, predicate) => {
8648      const str = node.data;
8649      if (start) {
8650        for (let i = offset; i > 0; i--) {
8651          if (predicate(str.charAt(i - 1))) {
8652            return i;
8653          }
8654        }
8655      } else {
8656        for (let i = offset; i < str.length; i++) {
8657          if (predicate(str.charAt(i))) {
8658            return i;
8659          }
8660        }
8661      }
8662      return -1;
8663    };
8664    const findSpace = (start, node, offset) => walkText(start, node, offset, c => isNbsp(c) || isWhiteSpace(c));
8665    const findContent = (start, node, offset) => walkText(start, node, offset, isContent);
8666    const findWordEndPoint = (dom, body, container, offset, start, includeTrailingSpaces) => {
8667      let lastTextNode;
8668      const rootNode = dom.getParent(container, dom.isBlock) || body;
8669      const walk = (container, offset, pred) => {
8670        const textSeeker = TextSeeker(dom);
8671        const walker = start ? textSeeker.backwards : textSeeker.forwards;
8672        return Optional.from(walker(container, offset, (text, textOffset) => {
8673          if (isBookmarkNode(text.parentNode)) {
8674            return -1;
8675          } else {
8676            lastTextNode = text;
8677            return pred(start, text, textOffset);
8678          }
8679        }, rootNode));
8680      };
8681      const spaceResult = walk(container, offset, findSpace);
8682      return spaceResult.bind(result => includeTrailingSpaces ? walk(result.container, result.offset + (start ? -1 : 0), findContent) : Optional.some(result)).orThunk(() => lastTextNode ? Optional.some({
8683        container: lastTextNode,
8684        offset: start ? 0 : lastTextNode.length
8685      }) : Optional.none());
8686    };
8687    const findSelectorEndPoint = (dom, formatList, rng, container, siblingName) => {
8688      const sibling = container[siblingName];
8689      if (isText$a(container) && isEmpty$3(container.data) && sibling) {
8690        container = sibling;
8691      }
8692      const parents = getParents$1(dom, container);
8693      for (let i = 0; i < parents.length; i++) {
8694        for (let y = 0; y < formatList.length; y++) {
8695          const curFormat = formatList[y];
8696          if (isNonNullable(curFormat.collapsed) && curFormat.collapsed !== rng.collapsed) {
8697            continue;
8698          }
8699          if (isSelectorFormat(curFormat) && dom.is(parents[i], curFormat.selector)) {
8700            return parents[i];
8701          }
8702        }
8703      }
8704      return container;
8705    };
8706    const findBlockEndPoint = (dom, formatList, container, siblingName) => {
8707      var _a;
8708      let node = container;
8709      const root = dom.getRoot();
8710      const format = formatList[0];
8711      if (isBlockFormat(format)) {
8712        node = format.wrapper ? null : dom.getParent(container, format.block, root);
8713      }
8714      if (!node) {
8715        const scopeRoot = (_a = dom.getParent(container, 'LI,TD,TH')) !== null && _a !== void 0 ? _a : root;
8716        node = dom.getParent(isText$a(container) ? container.parentNode : container, node => node !== root && isTextBlock(dom.schema, node), scopeRoot);
8717      }
8718      if (node && isBlockFormat(format) && format.wrapper) {
8719        node = getParents$1(dom, node, 'ul,ol').reverse()[0] || node;
8720      }
8721      if (!node) {
8722        node = container;
8723        while (node && node[siblingName] && !dom.isBlock(node[siblingName])) {
8724          node = node[siblingName];
8725          if (isEq$5(node, 'br')) {
8726            break;
8727          }
8728        }
8729      }
8730      return node || container;
8731    };
8732    const isAtBlockBoundary$1 = (dom, root, container, siblingName) => {
8733      const parent = container.parentNode;
8734      if (isNonNullable(container[siblingName])) {
8735        return false;
8736      } else if (parent === root || isNullable(parent) || dom.isBlock(parent)) {
8737        return true;
8738      } else {
8739        return isAtBlockBoundary$1(dom, root, parent, siblingName);
8740      }
8741    };
8742    const findParentContainer = (dom, formatList, container, offset, start) => {
8743      let parent = container;
8744      const siblingName = start ? 'previousSibling' : 'nextSibling';
8745      const root = dom.getRoot();
8746      if (isText$a(container) && !isWhiteSpaceNode(container)) {
8747        if (start ? offset > 0 : offset < container.data.length) {
8748          return container;
8749        }
8750      }
8751      while (parent) {
8752        if (!formatList[0].block_expand && dom.isBlock(parent)) {
8753          return parent;
8754        }
8755        for (let sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
8756          const allowSpaces = isText$a(sibling) && !isAtBlockBoundary$1(dom, root, sibling, siblingName);
8757          if (!isBookmarkNode(sibling) && !isBogusBr(sibling) && !isWhiteSpaceNode(sibling, allowSpaces)) {
8758            return parent;
8759          }
8760        }
8761        if (parent === root || parent.parentNode === root) {
8762          container = parent;
8763          break;
8764        }
8765        parent = parent.parentNode;
8766      }
8767      return container;
8768    };
8769    const isSelfOrParentBookmark = container => isBookmarkNode(container.parentNode) || isBookmarkNode(container);
8770    const expandRng = (dom, rng, formatList, includeTrailingSpace = false) => {
8771      let {startContainer, startOffset, endContainer, endOffset} = rng;
8772      const format = formatList[0];
8773      if (isElement$6(startContainer) && startContainer.hasChildNodes()) {
8774        startContainer = getNode$1(startContainer, startOffset);
8775        if (isText$a(startContainer)) {
8776          startOffset = 0;
8777        }
8778      }
8779      if (isElement$6(endContainer) && endContainer.hasChildNodes()) {
8780        endContainer = getNode$1(endContainer, rng.collapsed ? endOffset : endOffset - 1);
8781        if (isText$a(endContainer)) {
8782          endOffset = endContainer.data.length;
8783        }
8784      }
8785      startContainer = findParentContentEditable(dom, startContainer);
8786      endContainer = findParentContentEditable(dom, endContainer);
8787      if (isSelfOrParentBookmark(startContainer)) {
8788        startContainer = isBookmarkNode(startContainer) ? startContainer : startContainer.parentNode;
8789        if (rng.collapsed) {
8790          startContainer = startContainer.previousSibling || startContainer;
8791        } else {
8792          startContainer = startContainer.nextSibling || startContainer;
8793        }
8794        if (isText$a(startContainer)) {
8795          startOffset = rng.collapsed ? startContainer.length : 0;
8796        }
8797      }
8798      if (isSelfOrParentBookmark(endContainer)) {
8799        endContainer = isBookmarkNode(endContainer) ? endContainer : endContainer.parentNode;
8800        if (rng.collapsed) {
8801          endContainer = endContainer.nextSibling || endContainer;
8802        } else {
8803          endContainer = endContainer.previousSibling || endContainer;
8804        }
8805        if (isText$a(endContainer)) {
8806          endOffset = rng.collapsed ? 0 : endContainer.length;
8807        }
8808      }
8809      if (rng.collapsed) {
8810        const startPoint = findWordEndPoint(dom, dom.getRoot(), startContainer, startOffset, true, includeTrailingSpace);
8811        startPoint.each(({container, offset}) => {
8812          startContainer = container;
8813          startOffset = offset;
8814        });
8815        const endPoint = findWordEndPoint(dom, dom.getRoot(), endContainer, endOffset, false, includeTrailingSpace);
8816        endPoint.each(({container, offset}) => {
8817          endContainer = container;
8818          endOffset = offset;
8819        });
8820      }
8821      if (isInlineFormat(format) || format.block_expand) {
8822        if (!isInlineFormat(format) || (!isText$a(startContainer) || startOffset === 0)) {
8823          startContainer = findParentContainer(dom, formatList, startContainer, startOffset, true);
8824        }
8825        if (!isInlineFormat(format) || (!isText$a(endContainer) || endOffset === endContainer.data.length)) {
8826          endContainer = findParentContainer(dom, formatList, endContainer, endOffset, false);
8827        }
8828      }
8829      if (shouldExpandToSelector(format)) {
8830        startContainer = findSelectorEndPoint(dom, formatList, rng, startContainer, 'previousSibling');
8831        endContainer = findSelectorEndPoint(dom, formatList, rng, endContainer, 'nextSibling');
8832      }
8833      if (isBlockFormat(format) || isSelectorFormat(format)) {
8834        startContainer = findBlockEndPoint(dom, formatList, startContainer, 'previousSibling');
8835        endContainer = findBlockEndPoint(dom, formatList, endContainer, 'nextSibling');
8836        if (isBlockFormat(format)) {
8837          if (!dom.isBlock(startContainer)) {
8838            startContainer = findParentContainer(dom, formatList, startContainer, startOffset, true);
8839          }
8840          if (!dom.isBlock(endContainer)) {
8841            endContainer = findParentContainer(dom, formatList, endContainer, endOffset, false);
8842          }
8843        }
8844      }
8845      if (isElement$6(startContainer) && startContainer.parentNode) {
8846        startOffset = dom.nodeIndex(startContainer);
8847        startContainer = startContainer.parentNode;
8848      }
8849      if (isElement$6(endContainer) && endContainer.parentNode) {
8850        endOffset = dom.nodeIndex(endContainer) + 1;
8851        endContainer = endContainer.parentNode;
8852      }
8853      return {
8854        startContainer,
8855        startOffset,
8856        endContainer,
8857        endOffset
8858      };
8859    };
8860
8861    const walk$3 = (dom, rng, callback) => {
8862      var _a;
8863      const startOffset = rng.startOffset;
8864      const startContainer = getNode$1(rng.startContainer, startOffset);
8865      const endOffset = rng.endOffset;
8866      const endContainer = getNode$1(rng.endContainer, endOffset - 1);
8867      const exclude = nodes => {
8868        const firstNode = nodes[0];
8869        if (isText$a(firstNode) && firstNode === startContainer && startOffset >= firstNode.data.length) {
8870          nodes.splice(0, 1);
8871        }
8872        const lastNode = nodes[nodes.length - 1];
8873        if (endOffset === 0 && nodes.length > 0 && lastNode === endContainer && isText$a(lastNode)) {
8874          nodes.splice(nodes.length - 1, 1);
8875        }
8876        return nodes;
8877      };
8878      const collectSiblings = (node, name, endNode) => {
8879        const siblings = [];
8880        for (; node && node !== endNode; node = node[name]) {
8881          siblings.push(node);
8882        }
8883        return siblings;
8884      };
8885      const findEndPoint = (node, root) => dom.getParent(node, node => node.parentNode === root, root);
8886      const walkBoundary = (startNode, endNode, next) => {
8887        const siblingName = next ? 'nextSibling' : 'previousSibling';
8888        for (let node = startNode, parent = node.parentNode; node && node !== endNode; node = parent) {
8889          parent = node.parentNode;
8890          const siblings = collectSiblings(node === startNode ? node : node[siblingName], siblingName);
8891          if (siblings.length) {
8892            if (!next) {
8893              siblings.reverse();
8894            }
8895            callback(exclude(siblings));
8896          }
8897        }
8898      };
8899      if (startContainer === endContainer) {
8900        return callback(exclude([startContainer]));
8901      }
8902      const ancestor = (_a = dom.findCommonAncestor(startContainer, endContainer)) !== null && _a !== void 0 ? _a : dom.getRoot();
8903      if (dom.isChildOf(startContainer, endContainer)) {
8904        return walkBoundary(startContainer, ancestor, true);
8905      }
8906      if (dom.isChildOf(endContainer, startContainer)) {
8907        return walkBoundary(endContainer, ancestor);
8908      }
8909      const startPoint = findEndPoint(startContainer, ancestor) || startContainer;
8910      const endPoint = findEndPoint(endContainer, ancestor) || endContainer;
8911      walkBoundary(startContainer, startPoint, true);
8912      const siblings = collectSiblings(startPoint === startContainer ? startPoint : startPoint.nextSibling, 'nextSibling', endPoint === endContainer ? endPoint.nextSibling : endPoint);
8913      if (siblings.length) {
8914        callback(exclude(siblings));
8915      }
8916      walkBoundary(endContainer, endPoint);
8917    };
8918
8919    const validBlocks = [
8920      'pre[class*=language-][contenteditable="false"]',
8921      'figure.image',
8922      'div[data-ephox-embed-iri]',
8923      'div.tiny-pageembed',
8924      'div.mce-toc',
8925      'div[data-mce-toc]'
8926    ];
8927    const isZeroWidth = elem => isText$b(elem) && get$3(elem) === ZWSP$1;
8928    const context = (editor, elem, wrapName, nodeName) => parent(elem).fold(() => 'skipping', parent => {
8929      if (nodeName === 'br' || isZeroWidth(elem)) {
8930        return 'valid';
8931      } else if (isAnnotation(elem)) {
8932        return 'existing';
8933      } else if (isCaretNode(elem.dom)) {
8934        return 'caret';
8935      } else if (exists(validBlocks, selector => is$1(elem, selector))) {
8936        return 'valid-block';
8937      } else if (!isValid(editor, wrapName, nodeName) || !isValid(editor, name(parent), wrapName)) {
8938        return 'invalid-child';
8939      } else {
8940        return 'valid';
8941      }
8942    });
8943
8944    const applyWordGrab = (editor, rng) => {
8945      const r = expandRng(editor.dom, rng, [{ inline: 'span' }]);
8946      rng.setStart(r.startContainer, r.startOffset);
8947      rng.setEnd(r.endContainer, r.endOffset);
8948      editor.selection.setRng(rng);
8949    };
8950    const applyAnnotation = (elem, masterUId, data, annotationName, decorate, directAnnotation) => {
8951      const {uid = masterUId, ...otherData} = data;
8952      add$2(elem, annotation());
8953      set$3(elem, `${ dataAnnotationId() }`, uid);
8954      set$3(elem, `${ dataAnnotation() }`, annotationName);
8955      const {attributes = {}, classes = []} = decorate(uid, otherData);
8956      setAll$1(elem, attributes);
8957      add(elem, classes);
8958      if (directAnnotation) {
8959        if (classes.length > 0) {
8960          set$3(elem, `${ dataAnnotationClasses() }`, classes.join(','));
8961        }
8962        const attributeNames = keys(attributes);
8963        if (attributeNames.length > 0) {
8964          set$3(elem, `${ dataAnnotationAttributes() }`, attributeNames.join(','));
8965        }
8966      }
8967    };
8968    const removeDirectAnnotation = elem => {
8969      remove$
vendor: 8,668 bytes, lines 8969-9223
89698(elem, annotation());
8970      remove$b(elem, `${ dataAnnotationId() }`);
8971      remove$b(elem, `${ dataAnnotation() }`);
8972      remove$b(elem, `${ dataAnnotationActive() }`);
8973      const customAttrNames = getOpt(elem, `${ dataAnnotationAttributes() }`).map(names => names.split(',')).getOr([]);
8974      const customClasses = getOpt(elem, `${ dataAnnotationClasses() }`).map(names => names.split(',')).getOr([]);
8975      each$e(customAttrNames, name => remove$b(elem, name));
8976      remove$5(elem, customClasses);
8977      remove$b(elem, `${ dataAnnotationClasses() }`);
8978      remove$b(elem, `${ dataAnnotationAttributes() }`);
8979    };
8980    const makeAnnotation = (eDoc, uid, data, annotationName, decorate) => {
8981      const master = SugarElement.fromTag('span', eDoc);
8982      applyAnnotation(master, uid, data, annotationName, decorate, false);
8983      return master;
8984    };
8985    const annotate = (editor, rng, uid, annotationName, decorate, data) => {
8986      const newWrappers = [];
8987      const master = makeAnnotation(editor.getDoc(), uid, data, annotationName, decorate);
8988      const wrapper = value$2();
8989      const finishWrapper = () => {
8990        wrapper.clear();
8991      };
8992      const getOrOpenWrapper = () => wrapper.get().getOrThunk(() => {
8993        const nu = shallow$1(master);
8994        newWrappers.push(nu);
8995        wrapper.set(nu);
8996        return nu;
8997      });
8998      const processElements = elems => {
8999        each$e(elems, processElement);
9000      };
9001      const processElement = elem => {
9002        const ctx = context(editor, elem, 'span', name(elem));
9003        switch (ctx) {
9004        case 'invalid-child': {
9005            finishWrapper();
9006            const children = children$1(elem);
9007            processElements(children);
9008            finishWrapper();
9009            break;
9010          }
9011        case 'valid-block': {
9012            finishWrapper();
9013            applyAnnotation(elem, uid, data, annotationName, decorate, true);
9014            break;
9015          }
9016        case 'valid': {
9017            const w = getOrOpenWrapper();
9018            wrap$2(elem, w);
9019            break;
9020          }
9021        }
9022      };
9023      const processNodes = nodes => {
9024        const elems = map$3(nodes, SugarElement.fromDom);
9025        processElements(elems);
9026      };
9027      walk$3(editor.dom, rng, nodes => {
9028        finishWrapper();
9029        processNodes(nodes);
9030      });
9031      return newWrappers;
9032    };
9033    const annotateWithBookmark = (editor, name, settings, data) => {
9034      editor.undoManager.transact(() => {
9035        const selection = editor.selection;
9036        const initialRng = selection.getRng();
9037        const hasFakeSelection = getCellsFromEditor(editor).length > 0;
9038        const masterUid = generate$1('mce-annotation');
9039        if (initialRng.collapsed && !hasFakeSelection) {
9040          applyWordGrab(editor, initialRng);
9041        }
9042        if (selection.getRng().collapsed && !hasFakeSelection) {
9043          const wrapper = makeAnnotation(editor.getDoc(), masterUid, data, name, settings.decorate);
9044          set$1(wrapper, nbsp);
9045          selection.getRng().insertNode(wrapper.dom);
9046          selection.select(wrapper.dom);
9047        } else {
9048          preserve(selection, false, () => {
9049            runOnRanges(editor, selectionRng => {
9050              annotate(editor, selectionRng, masterUid, name, settings.decorate, data);
9051            });
9052          });
9053        }
9054      });
9055    };
9056
9057    const Annotator = editor => {
9058      const registry = create$c();
9059      setup$w(editor, registry);
9060      const changes = setup$x(editor, registry);
9061      const isSpan = isTag('span');
9062      const removeAnnotations = elements => {
9063        each$e(elements, element => {
9064          if (isSpan(element)) {
9065            unwrap(element);
9066          } else {
9067            removeDirectAnnotation(element);
9068          }
9069        });
9070      };
9071      return {
9072        register: (name, settings) => {
9073          registry.register(name, settings);
9074        },
9075        annotate: (name, data) => {
9076          registry.lookup(name).each(settings => {
9077            annotateWithBookmark(editor, name, settings, data);
9078          });
9079        },
9080        annotationChanged: (name, callback) => {
9081          changes.addListener(name, callback);
9082        },
9083        remove: name => {
9084          identify(editor, Optional.some(name)).each(({elements}) => {
9085            const bookmark = editor.selection.getBookmark();
9086            removeAnnotations(elements);
9087            editor.selection.moveToBookmark(bookmark);
9088          });
9089        },
9090        removeAll: name => {
9091          const bookmark = editor.selection.getBookmark();
9092          each$d(findAll(editor, name), (elements, _) => {
9093            removeAnnotations(elements);
9094          });
9095          editor.selection.moveToBookmark(bookmark);
9096        },
9097        getAll: name => {
9098          const directory = findAll(editor, name);
9099          return map$2(directory, elems => map$3(elems, elem => elem.dom));
9100        }
9101      };
9102    };
9103
9104    const BookmarkManager = selection => {
9105      return {
9106        getBookmark: curry(getBookmark$1, selection),
9107        moveToBookmark: curry(moveToBookmark, selection)
9108      };
9109    };
9110    BookmarkManager.isBookmarkNode = isBookmarkNode$1;
9111
9112    const isXYWithinRange = (clientX, clientY, range) => {
9113      if (range.collapsed) {
9114        return false;
9115      } else {
9116        return exists(range.getClientRects(), rect => containsXY(rect, clientX, clientY));
9117      }
9118    };
9119
9120    const firePreProcess = (editor, args) => editor.dispatch('PreProcess', args);
9121    const firePostProcess = (editor, args) => editor.dispatch('PostProcess', args);
9122    const fireRemove = editor => {
9123      editor.dispatch('remove');
9124    };
9125    const fireDetach = editor => {
9126      editor.dispatch('detach');
9127    };
9128    const fireSwitchMode = (editor, mode) => {
9129      editor.dispatch('SwitchMode', { mode });
9130    };
9131    const fireObjectResizeStart = (editor, target, width, height, origin) => {
9132      editor.dispatch('ObjectResizeStart', {
9133        target,
9134        width,
9135        height,
9136        origin
9137      });
9138    };
9139    const fireObjectResized = (editor, target, width, height, origin) => {
9140      editor.dispatch('ObjectResized', {
9141        target,
9142        width,
9143        height,
9144        origin
9145      });
9146    };
9147    const firePreInit = editor => {
9148      editor.dispatch('PreInit');
9149    };
9150    const firePostRender = editor => {
9151      editor.dispatch('PostRender');
9152    };
9153    const fireInit = editor => {
9154      editor.dispatch('Init');
9155    };
9156    const firePlaceholderToggle = (editor, state) => {
9157      editor.dispatch('PlaceholderToggle', { state });
9158    };
9159    const fireError = (editor, errorType, error) => {
9160      editor.dispatch(errorType, error);
9161    };
9162    const fireFormatApply = (editor, format, node, vars) => {
9163      editor.dispatch('FormatApply', {
9164        format,
9165        node,
9166        vars
9167      });
9168    };
9169    const fireFormatRemove = (editor, format, node, vars) => {
9170      editor.dispatch('FormatRemove', {
9171        format,
9172        node,
9173        vars
9174      });
9175    };
9176    const fireBeforeSetContent = (editor, args) => editor.dispatch('BeforeSetContent', args);
9177    const fireSetContent = (editor, args) => editor.dispatch('SetContent', args);
9178    const fireBeforeGetContent = (editor, args) => editor.dispatch('BeforeGetContent', args);
9179    const fireGetContent = (editor, args) => editor.dispatch('GetContent', args);
9180    const fireAutocompleterStart = (editor, args) => {
9181      editor.dispatch('AutocompleterStart', args);
9182    };
9183    const fireAutocompleterUpdate = (editor, args) => {
9184      editor.dispatch('AutocompleterUpdate', args);
9185    };
9186    const fireAutocompleterEnd = editor => {
9187      editor.dispatch('AutocompleterEnd');
9188    };
9189    const firePastePreProcess = (editor, html, internal) => editor.dispatch('PastePreProcess', {
9190      content: html,
9191      internal
9192    });
9193    const firePastePostProcess = (editor, node, internal) => editor.dispatch('PastePostProcess', {
9194      node,
9195      internal
9196    });
9197    const firePastePlainTextToggle = (editor, state) => editor.dispatch('PastePlainTextToggle', { state });
9198
9199    const VK = {
9200      BACKSPACE: 8,
9201      DELETE: 46,
9202      DOWN: 40,
9203      ENTER: 13,
9204      ESC: 27,
9205      LEFT: 37,
9206      RIGHT: 39,
9207      SPACEBAR: 32,
9208      TAB: 9,
9209      UP: 38,
9210      PAGE_UP: 33,
9211      PAGE_DOWN: 34,
9212      END: 35,
9213      HOME: 36,
9214      modifierPressed: e => {
9215        return e.shiftKey || e.ctrlKey || e.altKey || VK.metaKeyPressed(e);
9216      },
9217      metaKeyPressed: e => {
9218        return Env.os.isMacOS() || Env.os.isiOS() ? e.metaKey : e.ctrlKey && !e.altKey;
9219      }
9220    };
9221
9222    const elementSelectionAttr = 'data-mce-selected';
9223    const controlElmSelector = 'table,img,figure.image,hr,video,span.mce-preview-object
vendor: 37,290 bytes, lines 9223-10248
9223';
9224    const abs = Math.abs;
9225    const round$1 = Math.round;
9226    const resizeHandles = {
9227      nw: [
9228        0,
9229        0,
9230        -1,
9231        -1
9232      ],
9233      ne: [
9234        1,
9235        0,
9236        1,
9237        -1
9238      ],
9239      se: [
9240        1,
9241        1,
9242        1,
9243        1
9244      ],
9245      sw: [
9246        0,
9247        1,
9248        -1,
9249        1
9250      ]
9251    };
9252    const isTouchEvent = evt => evt.type === 'longpress' || evt.type.indexOf('touch') === 0;
9253    const ControlSelection = (selection, editor) => {
9254      const dom = editor.dom;
9255      const editableDoc = editor.getDoc();
9256      const rootDocument = document;
9257      const rootElement = editor.getBody();
9258      let selectedElm, selectedElmGhost, resizeHelper, selectedHandle, resizeBackdrop;
9259      let startX, startY, selectedElmX, selectedElmY, startW, startH, ratio, resizeStarted;
9260      let width;
9261      let height;
9262      let startScrollWidth;
9263      let startScrollHeight;
9264      const isImage = elm => isNonNullable(elm) && (isImg(elm) || dom.is(elm, 'figure.image'));
9265      const isMedia = elm => isMedia$2(elm) || dom.hasClass(elm, 'mce-preview-object');
9266      const isEventOnImageOutsideRange = (evt, range) => {
9267        if (isTouchEvent(evt)) {
9268          const touch = evt.touches[0];
9269          return isImage(evt.target) && !isXYWithinRange(touch.clientX, touch.clientY, range);
9270        } else {
9271          return isImage(evt.target) && !isXYWithinRange(evt.clientX, evt.clientY, range);
9272        }
9273      };
9274      const contextMenuSelectImage = evt => {
9275        const target = evt.target;
9276        if (isEventOnImageOutsideRange(evt, editor.selection.getRng()) && !evt.isDefaultPrevented()) {
9277          editor.selection.select(target);
9278        }
9279      };
9280      const getResizeTargets = elm => {
9281        if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
9282          return [
9283            elm,
9284            elm.firstElementChild
9285          ];
9286        } else if (dom.is(elm, 'figure.image')) {
9287          return [elm.querySelector('img')];
9288        } else {
9289          return [elm];
9290        }
9291      };
9292      const isResizable = elm => {
9293        const selector = getObjectResizing(editor);
9294        if (!selector) {
9295          return false;
9296        }
9297        if (elm.getAttribute('data-mce-resize') === 'false') {
9298          return false;
9299        }
9300        if (elm === editor.getBody()) {
9301          return false;
9302        }
9303        if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
9304          return is$1(SugarElement.fromDom(elm.firstElementChild), selector);
9305        } else {
9306          return is$1(SugarElement.fromDom(elm), selector);
9307        }
9308      };
9309      const createGhostElement = elm => {
9310        if (isMedia(elm)) {
9311          return dom.create('img', { src: Env.transparentSrc });
9312        } else {
9313          return elm.cloneNode(true);
9314        }
9315      };
9316      const setSizeProp = (element, name, value) => {
9317        if (isNonNullable(value)) {
9318          const targets = getResizeTargets(element);
9319          each$e(targets, target => {
9320            if (target.style[name] || !editor.schema.isValid(target.nodeName.toLowerCase(), name)) {
9321              dom.setStyle(target, name, value);
9322            } else {
9323              dom.setAttrib(target, name, '' + value);
9324            }
9325          });
9326        }
9327      };
9328      const setGhostElmSize = (ghostElm, width, height) => {
9329        setSizeProp(ghostElm, 'width', width);
9330        setSizeProp(ghostElm, 'height', height);
9331      };
9332      const resizeGhostElement = e => {
9333        let deltaX, deltaY, proportional;
9334        let resizeHelperX, resizeHelperY;
9335        deltaX = e.screenX - startX;
9336        deltaY = e.screenY - startY;
9337        width = deltaX * selectedHandle[2] + startW;
9338        height = deltaY * selectedHandle[3] + startH;
9339        width = width < 5 ? 5 : width;
9340        height = height < 5 ? 5 : height;
9341        if ((isImage(selectedElm) || isMedia(selectedElm)) && getResizeImgProportional(editor) !== false) {
9342          proportional = !VK.modifierPressed(e);
9343        } else {
9344          proportional = VK.modifierPressed(e);
9345        }
9346        if (proportional) {
9347          if (abs(deltaX) > abs(deltaY)) {
9348            height = round$1(width * ratio);
9349            width = round$1(height / ratio);
9350          } else {
9351            width = round$1(height / ratio);
9352            height = round$1(width * ratio);
9353          }
9354        }
9355        setGhostElmSize(selectedElmGhost, width, height);
9356        resizeHelperX = selectedHandle.startPos.x + deltaX;
9357        resizeHelperY = selectedHandle.startPos.y + deltaY;
9358        resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
9359        resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
9360        dom.setStyles(resizeHelper, {
9361          left: resizeHelperX,
9362          top: resizeHelperY,
9363          display: 'block'
9364        });
9365        resizeHelper.innerHTML = width + ' &times; ' + height;
9366        if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
9367          dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
9368        }
9369        if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
9370          dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
9371        }
9372        deltaX = rootElement.scrollWidth - startScrollWidth;
9373        deltaY = rootElement.scrollHeight - startScrollHeight;
9374        if (deltaX + deltaY !== 0) {
9375          dom.setStyles(resizeHelper, {
9376            left: resizeHelperX - deltaX,
9377            top: resizeHelperY - deltaY
9378          });
9379        }
9380        if (!resizeStarted) {
9381          fireObjectResizeStart(editor, selectedElm, startW, startH, 'corner-' + selectedHandle.name);
9382          resizeStarted = true;
9383        }
9384      };
9385      const endGhostResize = () => {
9386        const wasResizeStarted = resizeStarted;
9387        resizeStarted = false;
9388        if (wasResizeStarted) {
9389          setSizeProp(selectedElm, 'width', width);
9390          setSizeProp(selectedElm, 'height', height);
9391        }
9392        dom.unbind(editableDoc, 'mousemove', resizeGhostElement);
9393        dom.unbind(editableDoc, 'mouseup', endGhostResize);
9394        if (rootDocument !== editableDoc) {
9395          dom.unbind(rootDocument, 'mousemove', resizeGhostElement);
9396          dom.unbind(rootDocument, 'mouseup', endGhostResize);
9397        }
9398        dom.remove(selectedElmGhost);
9399        dom.remove(resizeHelper);
9400        dom.remove(resizeBackdrop);
9401        showResizeRect(selectedElm);
9402        if (wasResizeStarted) {
9403          fireObjectResized(editor, selectedElm, width, height, 'corner-' + selectedHandle.name);
9404          dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
9405        }
9406        editor.nodeChanged();
9407      };
9408      const showResizeRect = targetElm => {
9409        unbindResizeHandleEvents();
9410        const position = dom.getPos(targetElm, rootElement);
9411        const selectedElmX = position.x;
9412        const selectedElmY = position.y;
9413        const rect = targetElm.getBoundingClientRect();
9414        const targetWidth = rect.width || rect.right - rect.left;
9415        const targetHeight = rect.height || rect.bottom - rect.top;
9416        if (selectedElm !== targetElm) {
9417          hideResizeRect();
9418          selectedElm = targetElm;
9419          width = height = 0;
9420        }
9421        const e = editor.dispatch('ObjectSelected', { target: targetElm });
9422        if (isResizable(targetElm) && !e.isDefaultPrevented()) {
9423          each$d(resizeHandles, (handle, name) => {
9424            const startDrag = e => {
9425              const target = getResizeTargets(selectedElm)[0];
9426              startX = e.screenX;
9427              startY = e.screenY;
9428              startW = target.clientWidth;
9429              startH = target.clientHeight;
9430              ratio = startH / startW;
9431              selectedHandle = handle;
9432              selectedHandle.name = name;
9433              selectedHandle.startPos = {
9434                x: targetWidth * handle[0] + selectedElmX,
9435                y: targetHeight * handle[1] + selectedElmY
9436              };
9437              startScrollWidth = rootElement.scrollWidth;
9438              startScrollHeight = rootElement.scrollHeight;
9439              resizeBackdrop = dom.add(rootElement, 'div', {
9440                'class': 'mce-resize-backdrop',
9441                'data-mce-bogus': 'all'
9442              });
9443              dom.setStyles(resizeBackdrop, {
9444                position: 'fixed',
9445                left: '0',
9446                top: '0',
9447                width: '100%',
9448                height: '100%'
9449              });
9450              selectedElmGhost = createGhostElement(selectedElm);
9451              dom.addClass(selectedElmGhost, 'mce-clonedresizable');
9452              dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all');
9453              selectedElmGhost.contentEditable = 'false';
9454              dom.setStyles(selectedElmGhost, {
9455                left: selectedElmX,
9456                top: selectedElmY,
9457                margin: 0
9458              });
9459              setGhostElmSize(selectedElmGhost, targetWidth, targetHeight);
9460              selectedElmGhost.removeAttribute(elementSelectionAttr);
9461              rootElement.appendChild(selectedElmGhost);
9462              dom.bind(editableDoc, 'mousemove', resizeGhostElement);
9463              dom.bind(editableDoc, 'mouseup', endGhostResize);
9464              if (rootDocument !== editableDoc) {
9465                dom.bind(rootDocument, 'mousemove', resizeGhostElement);
9466                dom.bind(rootDocument, 'mouseup', endGhostResize);
9467              }
9468              resizeHelper = dom.add(rootElement, 'div', {
9469                'class': 'mce-resize-helper',
9470                'data-mce-bogus': 'all'
9471              }, startW + ' &times; ' + startH);
9472            };
9473            let handleElm = dom.get('mceResizeHandle' + name);
9474            if (handleElm) {
9475              dom.remove(handleElm);
9476            }
9477            handleElm = dom.add(rootElement, 'div', {
9478              'id': 'mceResizeHandle' + name,
9479              'data-mce-bogus': 'all',
9480              'class': 'mce-resizehandle',
9481              'unselectable': true,
9482              'style': 'cursor:' + name + '-resize; margin:0; padding:0'
9483            });
9484            dom.bind(handleElm, 'mousedown', e => {
9485              e.stopImmediatePropagation();
9486              e.preventDefault();
9487              startDrag(e);
9488            });
9489            handle.elm = handleElm;
9490            dom.setStyles(handleElm, {
9491              left: targetWidth * handle[0] + selectedElmX - handleElm.offsetWidth / 2,
9492              top: targetHeight * handle[1] + selectedElmY - handleElm.offsetHeight / 2
9493            });
9494          });
9495        } else {
9496          hideResizeRect(false);
9497        }
9498      };
9499      const throttledShowResizeRect = first$1(showResizeRect, 0);
9500      const hideResizeRect = (removeSelected = true) => {
9501        throttledShowResizeRect.cancel();
9502        unbindResizeHandleEvents();
9503        if (selectedElm && removeSelected) {
9504          selectedElm.removeAttribute(elementSelectionAttr);
9505        }
9506        each$d(resizeHandles, (value, name) => {
9507          const handleElm = dom.get('mceResizeHandle' + name);
9508          if (handleElm) {
9509            dom.unbind(handleElm);
9510            dom.remove(handleElm);
9511          }
9512        });
9513      };
9514      const isChildOrEqual = (node, parent) => dom.isChildOf(node, parent);
9515      const updateResizeRect = e => {
9516        if (resizeStarted || editor.removed || editor.composing) {
9517          return;
9518        }
9519        const targetElm = e.type === 'mousedown' ? e.target : selection.getNode();
9520        const controlElm = closest$3(SugarElement.fromDom(targetElm), controlElmSelector).map(e => e.dom).filter(e => dom.isEditable(e.parentElement)).getOrUndefined();
9521        const selectedValue = isNonNullable(controlElm) ? dom.getAttrib(controlElm, elementSelectionAttr, '1') : '1';
9522        each$e(dom.select(`img[${ elementSelectionAttr }],hr[${ elementSelectionAttr }]`), img => {
9523          img.removeAttribute(elementSelectionAttr);
9524        });
9525        if (isNonNullable(controlElm) && isChildOrEqual(controlElm, rootElement)) {
9526          disableGeckoResize();
9527          const startElm = selection.getStart(true);
9528          if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
9529            dom.setAttrib(controlElm, elementSelectionAttr, selectedValue);
9530            throttledShowResizeRect.throttle(controlElm);
9531            return;
9532          }
9533        }
9534        hideResizeRect();
9535      };
9536      const unbindResizeHandleEvents = () => {
9537        each$d(resizeHandles, handle => {
9538          if (handle.elm) {
9539            dom.unbind(handle.elm);
9540            delete handle.elm;
9541          }
9542        });
9543      };
9544      const disableGeckoResize = () => {
9545        try {
9546          editor.getDoc().execCommand('enableObjectResizing', false, 'false');
9547        } catch (ex) {
9548        }
9549      };
9550      editor.on('init', () => {
9551        disableGeckoResize();
9552        editor.on('NodeChange ResizeEditor ResizeWindow ResizeContent drop', updateResizeRect);
9553        editor.on('keyup compositionend', e => {
9554          if (selectedElm && selectedElm.nodeName === 'TABLE') {
9555            updateResizeRect(e);
9556          }
9557        });
9558        editor.on('hide blur', hideResizeRect);
9559        editor.on('contextmenu longpress', contextMenuSelectImage, true);
9560      });
9561      editor.on('remove', unbindResizeHandleEvents);
9562      const destroy = () => {
9563        throttledShowResizeRect.cancel();
9564        selectedElm = selectedElmGhost = resizeBackdrop = null;
9565      };
9566      return {
9567        isResizable,
9568        showResizeRect,
9569        hideResizeRect,
9570        updateResizeRect,
9571        destroy
9572      };
9573    };
9574
9575    const setStart = (rng, situ) => {
9576      situ.fold(e => {
9577        rng.setStartBefore(e.dom);
9578      }, (e, o) => {
9579        rng.setStart(e.dom, o);
9580      }, e => {
9581        rng.setStartAfter(e.dom);
9582      });
9583    };
9584    const setFinish = (rng, situ) => {
9585      situ.fold(e => {
9586        rng.setEndBefore(e.dom);
9587      }, (e, o) => {
9588        rng.setEnd(e.dom, o);
9589      }, e => {
9590        rng.setEndAfter(e.dom);
9591      });
9592    };
9593    const relativeToNative = (win, startSitu, finishSitu) => {
9594      const range = win.document.createRange();
9595      setStart(range, startSitu);
9596      setFinish(range, finishSitu);
9597      return range;
9598    };
9599    const exactToNative = (win, start, soffset, finish, foffset) => {
9600      const rng = win.document.createRange();
9601      rng.setStart(start.dom, soffset);
9602      rng.setEnd(finish.dom, foffset);
9603      return rng;
9604    };
9605
9606    const adt$3 = Adt.generate([
9607      {
9608        ltr: [
9609          'start',
9610          'soffset',
9611          'finish',
9612          'foffset'
9613        ]
9614      },
9615      {
9616        rtl: [
9617          'start',
9618          'soffset',
9619          'finish',
9620          'foffset'
9621        ]
9622      }
9623    ]);
9624    const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
9625    const getRanges = (win, selection) => selection.match({
9626      domRange: rng => {
9627        return {
9628          ltr: constant(rng),
9629          rtl: Optional.none
9630        };
9631      },
9632      relative: (startSitu, finishSitu) => {
9633        return {
9634          ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
9635          rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
9636        };
9637      },
9638      exact: (start, soffset, finish, foffset) => {
9639        return {
9640          ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
9641          rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
9642        };
9643      }
9644    });
9645    const doDiagnose = (win, ranges) => {
9646      const rng = ranges.ltr();
9647      if (rng.collapsed) {
9648        const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
9649        return reversed.map(rev => adt$3.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$3.ltr, rng));
9650      } else {
9651        return fromRange(win, adt$3.ltr, rng);
9652      }
9653    };
9654    const diagnose = (win, selection) => {
9655      const ranges = getRanges(win, selection);
9656      return doDiagnose(win, ranges);
9657    };
9658    adt$3.ltr;
9659    adt$3.rtl;
9660
9661    const create$a = (start, soffset, finish, foffset) => ({
9662      start,
9663      soffset,
9664      finish,
9665      foffset
9666    });
9667    const SimRange = { create: create$a };
9668
9669    const caretPositionFromPoint = (doc, x, y) => {
9670      var _a, _b;
9671      return Optional.from((_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y)).bind(pos => {
9672        if (pos.offsetNode === null) {
9673          return Optional.none();
9674        }
9675        const r = doc.dom.createRange();
9676        r.setStart(pos.offsetNode, pos.offset);
9677        r.collapse();
9678        return Optional.some(r);
9679      });
9680    };
9681    const caretRangeFromPoint = (doc, x, y) => {
9682      var _a, _b;
9683      return Optional.from((_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y));
9684    };
9685    const availableSearch = (() => {
9686      if (document.caretPositionFromPoint) {
9687        return caretPositionFromPoint;
9688      } else if (document.caretRangeFromPoint) {
9689        return caretRangeFromPoint;
9690      } else {
9691        return Optional.none;
9692      }
9693    })();
9694    const fromPoint$1 = (win, x, y) => {
9695      const doc = SugarElement.fromDom(win.document);
9696      return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
9697    };
9698
9699    const adt$2 = Adt.generate([
9700      { before: ['element'] },
9701      {
9702        on: [
9703          'element',
9704          'offset'
9705        ]
9706      },
9707      { after: ['element'] }
9708    ]);
9709    const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
9710    const getStart$2 = situ => situ.fold(identity, identity, identity);
9711    const before$1 = adt$2.before;
9712    const on = adt$2.on;
9713    const after$1 = adt$2.after;
9714    const Situ = {
9715      before: before$1,
9716      on,
9717      after: after$1,
9718      cata,
9719      getStart: getStart$2
9720    };
9721
9722    const adt$1 = Adt.generate([
9723      { domRange: ['rng'] },
9724      {
9725        relative: [
9726          'startSitu',
9727          'finishSitu'
9728        ]
9729      },
9730      {
9731        exact: [
9732          'start',
9733          'soffset',
9734          'finish',
9735          'foffset'
9736        ]
9737      }
9738    ]);
9739    const exactFromRange = simRange => adt$1.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
9740    const getStart$1 = selection => selection.match({
9741      domRange: rng => SugarElement.fromDom(rng.startContainer),
9742      relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
9743      exact: (start, _soffset, _finish, _foffset) => start
9744    });
9745    const domRange = adt$1.domRange;
9746    const relative = adt$1.relative;
9747    const exact = adt$1.exact;
9748    const getWin = selection => {
9749      const start = getStart$1(selection);
9750      return defaultView(start);
9751    };
9752    const range = SimRange.create;
9753    const SimSelection = {
9754      domRange,
9755      relative,
9756      exact,
9757      exactFromRange,
9758      getWin,
9759      range
9760    };
9761
9762    const beforeSpecial = (element, offset) => {
9763      const name$1 = name(element);
9764      if ('input' === name$1) {
9765        return Situ.after(element);
9766      } else if (!contains$2([
9767          'br',
9768          'img'
9769        ], name$1)) {
9770        return Situ.on(element, offset);
9771      } else {
9772        return offset === 0 ? Situ.before(element) : Situ.after(element);
9773      }
9774    };
9775    const preprocessRelative = (startSitu, finishSitu) => {
9776      const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
9777      const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
9778      return SimSelection.relative(start, finish);
9779    };
9780    const preprocessExact = (start, soffset, finish, foffset) => {
9781      const startSitu = beforeSpecial(start, soffset);
9782      const finishSitu = beforeSpecial(finish, foffset);
9783      return SimSelection.relative(startSitu, finishSitu);
9784    };
9785    const preprocess = selection => selection.match({
9786      domRange: rng => {
9787        const start = SugarElement.fromDom(rng.startContainer);
9788        const finish = SugarElement.fromDom(rng.endContainer);
9789        return preprocessExact(start, rng.startOffset, finish, rng.endOffset);
9790      },
9791      relative: preprocessRelative,
9792      exact: preprocessExact
9793    });
9794
9795    const fromElements = (elements, scope) => {
9796      const doc = scope || document;
9797      const fragment = doc.createDocumentFragment();
9798      each$e(elements, element => {
9799        fragment.appendChild(element.dom);
9800      });
9801      return SugarElement.fromDom(fragment);
9802    };
9803
9804    const toNative = selection => {
9805      const win = SimSelection.getWin(selection).dom;
9806      const getDomRange = (start, soffset, finish, foffset) => exactToNative(win, start, soffset, finish, foffset);
9807      const filtered = preprocess(selection);
9808      return diagnose(win, filtered).match({
9809        ltr: getDomRange,
9810        rtl: getDomRange
9811      });
9812    };
9813    const getAtPoint = (win, x, y) => fromPoint$1(win, x, y);
9814
9815    const fromPoint = (clientX, clientY, doc) => {
9816      const win = defaultView(SugarElement.fromDom(doc));
9817      return getAtPoint(win.dom, clientX, clientY).map(simRange => {
9818        const rng = doc.createRange();
9819        rng.setStart(simRange.start.dom, simRange.soffset);
9820        rng.setEnd(simRange.finish.dom, simRange.foffset);
9821        return rng;
9822      }).getOrUndefined();
9823    };
9824
9825    const isEq$4 = (rng1, rng2) => {
9826      return isNonNullable(rng1) && isNonNullable(rng2) && (rng1.startContainer === rng2.startContainer && rng1.startOffset === rng2.startOffset) && (rng1.endContainer === rng2.endContainer && rng1.endOffset === rng2.endOffset);
9827    };
9828
9829    const findParent = (node, rootNode, predicate) => {
9830      let currentNode = node;
9831      while (currentNode && currentNode !== rootNode) {
9832        if (predicate(currentNode)) {
9833          return currentNode;
9834        }
9835        currentNode = currentNode.parentNode;
9836      }
9837      return null;
9838    };
9839    const hasParent$1 = (node, rootNode, predicate) => findParent(node, rootNode, predicate) !== null;
9840    const hasParentWithName = (node, rootNode, name) => hasParent$1(node, rootNode, node => node.nodeName === name);
9841    const isCeFalseCaretContainer = (node, rootNode) => isCaretContainer$2(node) && !hasParent$1(node, rootNode, isCaretNode);
9842    const hasBrBeforeAfter = (dom, node, left) => {
9843      const parentNode = node.parentNode;
9844      if (parentNode) {
9845        const walker = new DomTreeWalker(node, dom.getParent(parentNode, dom.isBlock) || dom.getRoot());
9846        let currentNode;
9847        while (currentNode = walker[left ? 'prev' : 'next']()) {
9848          if (isBr$6(currentNode)) {
9849            return true;
9850          }
9851        }
9852      }
9853      return false;
9854    };
9855    const isPrevNode = (node, name) => {
9856      var _a;
9857      return ((_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.nodeName) === name;
9858    };
9859    const hasContentEditableFalseParent = (root, node) => {
9860      let currentNode = node;
9861      while (currentNode && currentNode !== root) {
9862        if (isContentEditableFalse$b(currentNode)) {
9863          return true;
9864        }
9865        currentNode = currentNode.parentNode;
9866      }
9867      return false;
9868    };
9869    const findTextNodeRelative = (dom, isAfterNode, collapsed, left, startNode) => {
9870      const body = dom.getRoot();
9871      const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
9872      const parentNode = startNode.parentNode;
9873      let lastInlineElement;
9874      let node;
9875      if (!parentNode) {
9876        return Optional.none();
9877      }
9878      const parentBlockContainer = dom.getParent(parentNode, dom.isBlock) || body;
9879      if (left && isBr$6(startNode) && isAfterNode && dom.isEmpty(parentBlockContainer)) {
9880        return Optional.some(CaretPosition(parentNode, dom.nodeIndex(startNode)));
9881      }
9882      const walker = new DomTreeWalker(startNode, parentBlockContainer);
9883      while (node = walker[left ? 'prev' : 'next']()) {
9884        if (dom.getContentEditableParent(node) === 'false' || isCeFalseCaretContainer(node, body)) {
9885          return Optional.none();
9886        }
9887        if (isText$a(node) && node.data.length > 0) {
9888          if (!hasParentWithName(node, body, 'A')) {
9889            return Optional.some(CaretPosition(node, left ? node.data.length : 0));
9890          }
9891          return Optional.none();
9892        }
9893        if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
9894          return Optional.none();
9895        }
9896        lastInlineElement = node;
9897      }
9898      if (isComment(lastInlineElement)) {
9899        return Optional.none();
9900      }
9901      if (collapsed && lastInlineElement) {
9902        return Optional.some(CaretPosition(lastInlineElement, 0));
9903      }
9904      return Optional.none();
9905    };
9906    const normalizeEndPoint = (dom, collapsed, start, rng) => {
9907      const body = dom.getRoot();
9908      let node;
9909      let normalized = false;
9910      let container = start ? rng.startContainer : rng.endContainer;
9911      let offset = start ? rng.startOffset : rng.endOffset;
9912      const isAfterNode = isElement$6(container) && offset === container.childNodes.length;
9913      const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
9914      let directionLeft = start;
9915      if (isCaretContainer$2(container)) {
9916        return Optional.none();
9917      }
9918      if (isElement$6(container) && offset > container.childNodes.length - 1) {
9919        directionLeft = false;
9920      }
9921      if (isDocument$1(container)) {
9922        container = body;
9923        offset = 0;
9924      }
9925      if (container === body) {
9926        if (directionLeft) {
9927          node = container.childNodes[offset > 0 ? offset - 1 : 0];
9928          if (node) {
9929            if (isCaretContainer$2(node)) {
9930              return Optional.none();
9931            }
9932            if (nonEmptyElementsMap[node.nodeName] || isTable$2(node)) {
9933              return Optional.none();
9934            }
9935          }
9936        }
9937        if (container.hasChildNodes()) {
9938          offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
9939          container = container.childNodes[offset];
9940          offset = isText$a(container) && isAfterNode ? container.data.length : 0;
9941          if (!collapsed && container === body.lastChild && isTable$2(container)) {
9942            return Optional.none();
9943          }
9944          if (hasContentEditableFalseParent(body, container) || isCaretContainer$2(container)) {
9945            return Optional.none();
9946          }
9947          if (container.hasChildNodes() && !isTable$2(container)) {
9948            node = container;
9949            const walker = new DomTreeWalker(container, body);
9950            do {
9951              if (isContentEditableFalse$b(node) || isCaretContainer$2(node)) {
9952                normalized = false;
9953                break;
9954              }
9955              if (isText$a(node) && node.data.length > 0) {
9956                offset = directionLeft ? 0 : node.data.length;
9957                container = node;
9958                normalized = true;
9959                break;
9960              }
9961              if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCellOrCaption(node)) {
9962                offset = dom.nodeIndex(node);
9963                container = node.parentNode;
9964                if (!directionLeft) {
9965                  offset++;
9966                }
9967                normalized = true;
9968                break;
9969              }
9970            } while (node = directionLeft ? walker.next() : walker.prev());
9971          }
9972        }
9973      }
9974      if (collapsed) {
9975        if (isText$a(container) && offset === 0) {
9976          findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(pos => {
9977            container = pos.container();
9978            offset = pos.offset();
9979            normalized = true;
9980          });
9981        }
9982        if (isElement$6(container)) {
9983          node = container.childNodes[offset];
9984          if (!node) {
9985            node = container.childNodes[offset - 1];
9986          }
9987          if (node && isBr$6(node) && !isPrevNode(node, 'A') && !hasBrBeforeAfter(dom, node, false) && !hasBrBeforeAfter(dom, node, true)) {
9988            findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(pos => {
9989              container = pos.container();
9990              offset = pos.offset();
9991              normalized = true;
9992            });
9993          }
9994        }
9995      }
9996      if (directionLeft && !collapsed && isText$a(container) && offset === container.data.length) {
9997        findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(pos => {
9998          container = pos.container();
9999          offset = pos.offset();
10000          normalized = true;
10001        });
10002      }
10003      return normalized && container ? Optional.some(CaretPosition(container, offset)) : Optional.none();
10004    };
10005    const normalize$2 = (dom, rng) => {
10006      const collapsed = rng.collapsed, normRng = rng.cloneRange();
10007      const startPos = CaretPosition.fromRangeStart(rng);
10008      normalizeEndPoint(dom, collapsed, true, normRng).each(pos => {
10009        if (!collapsed || !CaretPosition.isAbove(startPos, pos)) {
10010          normRng.setStart(pos.container(), pos.offset());
10011        }
10012      });
10013      if (!collapsed) {
10014        normalizeEndPoint(dom, collapsed, false, normRng).each(pos => {
10015          normRng.setEnd(pos.container(), pos.offset());
10016        });
10017      }
10018      if (collapsed) {
10019        normRng.collapse(true);
10020      }
10021      return isEq$4(rng, normRng) ? Optional.none() : Optional.some(normRng);
10022    };
10023
10024    const splitText = (node, offset) => {
10025      return node.splitText(offset);
10026    };
10027    const split = rng => {
10028      let startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset;
10029      if (startContainer === endContainer && isText$a(startContainer)) {
10030        if (startOffset > 0 && startOffset < startContainer.data.length) {
10031          endContainer = splitText(startContainer, startOffset);
10032          startContainer = endContainer.previousSibling;
10033          if (endOffset > startOffset) {
10034            endOffset = endOffset - startOffset;
10035            const newContainer = splitText(endContainer, endOffset).previousSibling;
10036            startContainer = endContainer = newContainer;
10037            endOffset = newContainer.data.length;
10038            startOffset = 0;
10039          } else {
10040            endOffset = 0;
10041          }
10042        }
10043      } else {
10044        if (isText$a(startContainer) && startOffset > 0 && startOffset < startContainer.data.length) {
10045          startContainer = splitText(startContainer, startOffset);
10046          startOffset = 0;
10047        }
10048        if (isText$a(endContainer) && endOffset > 0 && endOffset < endContainer.data.length) {
10049          const newContainer = splitText(endContainer, endOffset).previousSibling;
10050          endContainer = newContainer;
10051          endOffset = newContainer.data.length;
10052        }
10053      }
10054      return {
10055        startContainer,
10056        startOffset,
10057        endContainer,
10058        endOffset
10059      };
10060    };
10061
10062    const RangeUtils = dom => {
10063      const walk = (rng, callback) => {
10064        return walk$3(dom, rng, callback);
10065      };
10066      const split$1 = split;
10067      const normalize = rng => {
10068        return normalize$2(dom, rng).fold(never, normalizedRng => {
10069          rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset);
10070          rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset);
10071          return true;
10072        });
10073      };
10074      const expand = (rng, options = { type: 'word' }) => {
10075        if (options.type === 'word') {
10076          const rangeLike = expandRng(dom, rng, [{ inline: 'span' }]);
10077          const newRange = dom.createRng();
10078          newRange.setStart(rangeLike.startContainer, rangeLike.startOffset);
10079          newRange.setEnd(rangeLike.endContainer, rangeLike.endOffset);
10080          return newRange;
10081        }
10082        return rng;
10083      };
10084      return {
10085        walk,
10086        split: split$1,
10087        expand,
10088        normalize
10089      };
10090    };
10091    RangeUtils.compareRanges = isEq$4;
10092    RangeUtils.getCaretRangeFromPoint = fromPoint;
10093    RangeUtils.getSelectedNode = getSelectedNode;
10094    RangeUtils.getNode = getNode$1;
10095
10096    const Dimension = (name, getOffset) => {
10097      const set = (element, h) => {
10098        if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
10099          throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
10100        }
10101        const dom = element.dom;
10102        if (isSupported(dom)) {
10103          dom.style[name] = h + 'px';
10104        }
10105      };
10106      const get = element => {
10107        const r = getOffset(element);
10108        if (r <= 0 || r === null) {
10109          const css = get$7(element, name);
10110          return parseFloat(css) || 0;
10111        }
10112        return r;
10113      };
10114      const getOuter = get;
10115      const aggregate = (element, properties) => foldl(properties, (acc, property) => {
10116        const val = get$7(element, property);
10117        const value = val === undefined ? 0 : parseInt(val, 10);
10118        return isNaN(value) ? acc : acc + value;
10119      }, 0);
10120      const max = (element, value, properties) => {
10121        const cumulativeInclusions = aggregate(element, properties);
10122        const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
10123        return absoluteMax;
10124      };
10125      return {
10126        set,
10127        get,
10128        getOuter,
10129        aggregate,
10130        max
10131      };
10132    };
10133
10134    const api = Dimension('height', element => {
10135      const dom = element.dom;
10136      return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
10137    });
10138    const get$2 = element => api.get(element);
10139
10140    const getDocument = () => SugarElement.fromDom(document);
10141
10142    const walkUp = (navigation, doc) => {
10143      const frame = navigation.view(doc);
10144      return frame.fold(constant([]), f => {
10145        const parent = navigation.owner(f);
10146        const rest = walkUp(navigation, parent);
10147        return [f].concat(rest);
10148      });
10149    };
10150    const pathTo = (element, navigation) => {
10151      const d = navigation.owner(element);
10152      return walkUp(navigation, d);
10153    };
10154
10155    const view = doc => {
10156      var _a;
10157      const element = doc.dom === document ? Optional.none() : Optional.from((_a = doc.dom.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement);
10158      return element.map(SugarElement.fromDom);
10159    };
10160    const owner = element => documentOrOwner(element);
10161
10162    var Navigation = /*#__PURE__*/Object.freeze({
10163        __proto__: null,
10164        view: view,
10165        owner: owner
10166    });
10167
10168    const find = element => {
10169      const doc = getDocument();
10170      const scroll = get$5(doc);
10171      const frames = pathTo(element, Navigation);
10172      const offset = viewport(element);
10173      const r = foldr(frames, (b, a) => {
10174        const loc = viewport(a);
10175        return {
10176          left: b.left + loc.left,
10177          top: b.top + loc.top
10178        };
10179      }, {
10180        left: 0,
10181        top: 0
10182      });
10183      return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top);
10184    };
10185
10186    const excludeFromDescend = element => name(element) === 'textarea';
10187    const fireScrollIntoViewEvent = (editor, data) => {
10188      const scrollEvent = editor.dispatch('ScrollIntoView', data);
10189      return scrollEvent.isDefaultPrevented();
10190    };
10191    const fireAfterScrollIntoViewEvent = (editor, data) => {
10192      editor.dispatch('AfterScrollIntoView', data);
10193    };
10194    const descend = (element, offset) => {
10195      const children = children$1(element);
10196      if (children.length === 0 || excludeFromDescend(element)) {
10197        return {
10198          element,
10199          offset
10200        };
10201      } else if (offset < children.length && !excludeFromDescend(children[offset])) {
10202        return {
10203          element: children[offset],
10204          offset: 0
10205        };
10206      } else {
10207        const last = children[children.length - 1];
10208        if (excludeFromDescend(last)) {
10209          return {
10210            element,
10211            offset
10212          };
10213        } else {
10214          if (name(last) === 'img') {
10215            return {
10216              element: last,
10217              offset: 1
10218            };
10219          } else if (isText$b(last)) {
10220            return {
10221              element: last,
10222              offset: get$3(last).length
10223            };
10224          } else {
10225            return {
10226              element: last,
10227              offset: children$1(last).length
10228            };
10229          }
10230        }
10231      }
10232    };
10233    const markerInfo = (element, cleanupFun) => {
10234      const pos = absolute(element);
10235      const height = get$2(element);
10236      return {
10237        element,
10238        bottom: pos.top + height,
10239        height,
10240        pos,
10241        cleanup: cleanupFun
10242      };
10243    };
10244    const createMarker$1 = (element, offset) => {
10245      const startPoint = descend(element, offset);
10246      const span = SugarElement.fromHtml('<span data-mce-bogus="all" style="display: inline-block;">' + ZWSP$1 + '</span>');
10247      before$3(startPoint.element, span);
10248      return markerInfo(span, () => remove$
102486
vendor: 11,311 bytes, lines 10248-10520
10248(span));
10249    };
10250    const elementMarker = element => markerInfo(SugarElement.fromDom(element), noop);
10251    const withMarker = (editor, f, rng, alignToTop) => {
10252      preserveWith(editor, (_s, _e) => applyWithMarker(editor, f, rng, alignToTop), rng);
10253    };
10254    const withScrollEvents = (editor, doc, f, marker, alignToTop) => {
10255      const data = {
10256        elm: marker.element.dom,
10257        alignToTop
10258      };
10259      if (fireScrollIntoViewEvent(editor, data)) {
10260        return;
10261      }
10262      const scrollTop = get$5(doc).top;
10263      f(doc, scrollTop, marker, alignToTop);
10264      fireAfterScrollIntoViewEvent(editor, data);
10265    };
10266    const applyWithMarker = (editor, f, rng, alignToTop) => {
10267      const body = SugarElement.fromDom(editor.getBody());
10268      const doc = SugarElement.fromDom(editor.getDoc());
10269      reflow(body);
10270      const marker = createMarker$1(SugarElement.fromDom(rng.startContainer), rng.startOffset);
10271      withScrollEvents(editor, doc, f, marker, alignToTop);
10272      marker.cleanup();
10273    };
10274    const withElement = (editor, element, f, alignToTop) => {
10275      const doc = SugarElement.fromDom(editor.getDoc());
10276      withScrollEvents(editor, doc, f, elementMarker(element), alignToTop);
10277    };
10278    const preserveWith = (editor, f, rng) => {
10279      const startElement = rng.startContainer;
10280      const startOffset = rng.startOffset;
10281      const endElement = rng.endContainer;
10282      const endOffset = rng.endOffset;
10283      f(SugarElement.fromDom(startElement), SugarElement.fromDom(endElement));
10284      const newRng = editor.dom.createRng();
10285      newRng.setStart(startElement, startOffset);
10286      newRng.setEnd(endElement, endOffset);
10287      editor.selection.setRng(rng);
10288    };
10289    const scrollToMarker = (marker, alignToTop) => marker.element.dom.scrollIntoView({ block: alignToTop ? 'start' : 'end' });
10290    const intoWindowIfNeeded = (scrollTop, viewHeight, marker, alignToTop) => {
10291      const viewportBottom = viewHeight + scrollTop;
10292      const markerTop = marker.pos.top;
10293      const markerBottom = marker.bottom;
10294      const largerThanViewport = markerBottom - markerTop >= viewHeight;
10295      if (markerTop < scrollTop) {
10296        scrollToMarker(marker, alignToTop !== false);
10297      } else if (markerTop > viewportBottom) {
10298        const align = largerThanViewport ? alignToTop !== false : alignToTop === true;
10299        scrollToMarker(marker, align);
10300      } else if (markerBottom > viewportBottom && !largerThanViewport) {
10301        scrollToMarker(marker, alignToTop === true);
10302      }
10303    };
10304    const intoWindow = (doc, scrollTop, marker, alignToTop) => {
10305      const viewHeight = defaultView(doc).dom.innerHeight;
10306      intoWindowIfNeeded(scrollTop, viewHeight, marker, alignToTop);
10307    };
10308    const intoFrame = (doc, scrollTop, marker, alignToTop) => {
10309      const frameViewHeight = defaultView(doc).dom.innerHeight;
10310      intoWindowIfNeeded(scrollTop, frameViewHeight, marker, alignToTop);
10311      const op = find(marker.element);
10312      const viewportBounds = getBounds(window);
10313      if (op.top < viewportBounds.y) {
10314        intoView(marker.element, alignToTop !== false);
10315      } else if (op.top > viewportBounds.bottom) {
10316        intoView(marker.element, alignToTop === true);
10317      }
10318    };
10319    const rangeIntoWindow = (editor, rng, alignToTop) => withMarker(editor, intoWindow, rng, alignToTop);
10320    const elementIntoWindow = (editor, element, alignToTop) => withElement(editor, element, intoWindow, alignToTop);
10321    const rangeIntoFrame = (editor, rng, alignToTop) => withMarker(editor, intoFrame, rng, alignToTop);
10322    const elementIntoFrame = (editor, element, alignToTop) => withElement(editor, element, intoFrame, alignToTop);
10323    const scrollElementIntoView = (editor, element, alignToTop) => {
10324      const scroller = editor.inline ? elementIntoWindow : elementIntoFrame;
10325      scroller(editor, element, alignToTop);
10326    };
10327    const scrollRangeIntoView = (editor, rng, alignToTop) => {
10328      const scroller = editor.inline ? rangeIntoWindow : rangeIntoFrame;
10329      scroller(editor, rng, alignToTop);
10330    };
10331
10332    const focus$1 = element => element.dom.focus();
10333    const hasFocus$1 = element => {
10334      const root = getRootNode(element).dom;
10335      return element.dom === root.activeElement;
10336    };
10337    const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
10338    const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom));
10339
10340    const clamp$1 = (offset, element) => {
10341      const max = isText$b(element) ? get$3(element).length : children$1(element).length + 1;
10342      if (offset > max) {
10343        return max;
10344      } else if (offset < 0) {
10345        return 0;
10346      }
10347      return offset;
10348    };
10349    const normalizeRng = rng => SimSelection.range(rng.start, clamp$1(rng.soffset, rng.start), rng.finish, clamp$1(rng.foffset, rng.finish));
10350    const isOrContains = (root, elm) => !isRestrictedNode(elm.dom) && (contains(root, elm) || eq(root, elm));
10351    const isRngInRoot = root => rng => isOrContains(root, rng.start) && isOrContains(root, rng.finish);
10352    const shouldStore = editor => editor.inline || Env.browser.isFirefox();
10353    const nativeRangeToSelectionRange = r => SimSelection.range(SugarElement.fromDom(r.startContainer), r.startOffset, SugarElement.fromDom(r.endContainer), r.endOffset);
10354    const readRange = win => {
10355      const selection = win.getSelection();
10356      const rng = !selection || selection.rangeCount === 0 ? Optional.none() : Optional.from(selection.getRangeAt(0));
10357      return rng.map(nativeRangeToSelectionRange);
10358    };
10359    const getBookmark = root => {
10360      const win = defaultView(root);
10361      return readRange(win.dom).filter(isRngInRoot(root));
10362    };
10363    const validate = (root, bookmark) => Optional.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng);
10364    const bookmarkToNativeRng = bookmark => {
10365      const rng = document.createRange();
10366      try {
10367        rng.setStart(bookmark.start.dom, bookmark.soffset);
10368        rng.setEnd(bookmark.finish.dom, bookmark.foffset);
10369        return Optional.some(rng);
10370      } catch (_) {
10371        return Optional.none();
10372      }
10373    };
10374    const store = editor => {
10375      const newBookmark = shouldStore(editor) ? getBookmark(SugarElement.fromDom(editor.getBody())) : Optional.none();
10376      editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
10377    };
10378    const getRng = editor => {
10379      const bookmark = editor.bookmark ? editor.bookmark : Optional.none();
10380      return bookmark.bind(x => validate(SugarElement.fromDom(editor.getBody()), x)).bind(bookmarkToNativeRng);
10381    };
10382    const restore = editor => {
10383      getRng(editor).each(rng => editor.selection.setRng(rng));
10384    };
10385
10386    const isEditorUIElement$1 = elm => {
10387      const className = elm.className.toString();
10388      return className.indexOf('tox-') !== -1 || className.indexOf('mce-') !== -1;
10389    };
10390    const FocusManager = { isEditorUIElement: isEditorUIElement$1 };
10391
10392    const wrappedSetTimeout = (callback, time) => {
10393      if (!isNumber(time)) {
10394        time = 0;
10395      }
10396      return setTimeout(callback, time);
10397    };
10398    const wrappedSetInterval = (callback, time) => {
10399      if (!isNumber(time)) {
10400        time = 0;
10401      }
10402      return setInterval(callback, time);
10403    };
10404    const Delay = {
10405      setEditorTimeout: (editor, callback, time) => {
10406        return wrappedSetTimeout(() => {
10407          if (!editor.removed) {
10408            callback();
10409          }
10410        }, time);
10411      },
10412      setEditorInterval: (editor, callback, time) => {
10413        const timer = wrappedSetInterval(() => {
10414          if (!editor.removed) {
10415            callback();
10416          } else {
10417            clearInterval(timer);
10418          }
10419        }, time);
10420        return timer;
10421      }
10422    };
10423
10424    const isManualNodeChange = e => {
10425      return e.type === 'nodechange' && e.selectionChange;
10426    };
10427    const registerPageMouseUp = (editor, throttledStore) => {
10428      const mouseUpPage = () => {
10429        throttledStore.throttle();
10430      };
10431      DOMUtils.DOM.bind(document, 'mouseup', mouseUpPage);
10432      editor.on('remove', () => {
10433        DOMUtils.DOM.unbind(document, 'mouseup', mouseUpPage);
10434      });
10435    };
10436    const registerMouseUp = (editor, throttledStore) => {
10437      editor.on('mouseup touchend', _e => {
10438        throttledStore.throttle();
10439      });
10440    };
10441    const registerEditorEvents = (editor, throttledStore) => {
10442      registerMouseUp(editor, throttledStore);
10443      editor.on('keyup NodeChange AfterSetSelectionRange', e => {
10444        if (!isManualNodeChange(e)) {
10445          store(editor);
10446        }
10447      });
10448    };
10449    const register$6 = editor => {
10450      const throttledStore = first$1(() => {
10451        store(editor);
10452      }, 0);
10453      editor.on('init', () => {
10454        if (editor.inline) {
10455          registerPageMouseUp(editor, throttledStore);
10456        }
10457        registerEditorEvents(editor, throttledStore);
10458      });
10459      editor.on('remove', () => {
10460        throttledStore.cancel();
10461      });
10462    };
10463
10464    let documentFocusInHandler;
10465    const DOM$9 = DOMUtils.DOM;
10466    const isEditorUIElement = elm => {
10467      return isElement$6(elm) && FocusManager.isEditorUIElement(elm);
10468    };
10469    const isEditorContentAreaElement = elm => {
10470      const classList = elm.classList;
10471      if (classList !== undefined) {
10472        return classList.contains('tox-edit-area') || classList.contains('tox-edit-area__iframe') || classList.contains('mce-content-body');
10473      } else {
10474        return false;
10475      }
10476    };
10477    const isUIElement = (editor, elm) => {
10478      const customSelector = getCustomUiSelector(editor);
10479      const parent = DOM$9.getParent(elm, elm => {
10480        return isEditorUIElement(elm) || (customSelector ? editor.dom.is(elm, customSelector) : false);
10481      });
10482      return parent !== null;
10483    };
10484    const getActiveElement = editor => {
10485      try {
10486        const root = getRootNode(SugarElement.fromDom(editor.getElement()));
10487        return active$1(root).fold(() => document.body, x => x.dom);
10488      } catch (ex) {
10489        return document.body;
10490      }
10491    };
10492    const registerEvents$1 = (editorManager, e) => {
10493      const editor = e.editor;
10494      register$6(editor);
10495      const toggleContentAreaOnFocus = (editor, fn) => {
10496        if (shouldHighlightOnFocus(editor) && editor.inline !== true) {
10497          const contentArea = SugarElement.fromDom(editor.getContainer());
10498          fn(contentArea, 'tox-edit-focus');
10499        }
10500      };
10501      editor.on('focusin', () => {
10502        const focusedEditor = editorManager.focusedEditor;
10503        if (isEditorContentAreaElement(getActiveElement(editor))) {
10504          toggleContentAreaOnFocus(editor, add$2);
10505        }
10506        if (focusedEditor !== editor) {
10507          if (focusedEditor) {
10508            focusedEditor.dispatch('blur', { focusedEditor: editor });
10509          }
10510          editorManager.setActive(editor);
10511          editorManager.focusedEditor = editor;
10512          editor.dispatch('focus', { blurredEditor: focusedEditor });
10513          editor.focus(true);
10514        }
10515      });
10516      editor.on('focusout', () => {
10517        Delay.setEditorTimeout(editor, () => {
10518          const focusedEditor = editorManager.focusedEditor;
10519          if (!isEditorContentAreaElement(getActiveElement(editor)) || focusedEditor !== editor) {
10520            toggleContentAreaOnFocus(editor, remove$
105208
vendor: 10,567 bytes, lines 10520-10778
10520);
10521          }
10522          if (!isUIElement(editor, getActiveElement(editor)) && focusedEditor === editor) {
10523            editor.dispatch('blur', { focusedEditor: null });
10524            editorManager.focusedEditor = null;
10525          }
10526        });
10527      });
10528      if (!documentFocusInHandler) {
10529        documentFocusInHandler = e => {
10530          const activeEditor = editorManager.activeEditor;
10531          if (activeEditor) {
10532            getOriginalEventTarget(e).each(target => {
10533              const elem = target;
10534              if (elem.ownerDocument === document) {
10535                if (elem !== document.body && !isUIElement(activeEditor, elem) && editorManager.focusedEditor === activeEditor) {
10536                  activeEditor.dispatch('blur', { focusedEditor: null });
10537                  editorManager.focusedEditor = null;
10538                }
10539              }
10540            });
10541          }
10542        };
10543        DOM$9.bind(document, 'focusin', documentFocusInHandler);
10544      }
10545    };
10546    const unregisterDocumentEvents = (editorManager, e) => {
10547      if (editorManager.focusedEditor === e.editor) {
10548        editorManager.focusedEditor = null;
10549      }
10550      if (!editorManager.activeEditor && documentFocusInHandler) {
10551        DOM$9.unbind(document, 'focusin', documentFocusInHandler);
10552        documentFocusInHandler = null;
10553      }
10554    };
10555    const setup$v = editorManager => {
10556      editorManager.on('AddEditor', curry(registerEvents$1, editorManager));
10557      editorManager.on('RemoveEditor', curry(unregisterDocumentEvents, editorManager));
10558    };
10559
10560    const getContentEditableHost = (editor, node) => editor.dom.getParent(node, node => editor.dom.getContentEditable(node) === 'true');
10561    const getCollapsedNode = rng => rng.collapsed ? Optional.from(getNode$1(rng.startContainer, rng.startOffset)).map(SugarElement.fromDom) : Optional.none();
10562    const getFocusInElement = (root, rng) => getCollapsedNode(rng).bind(node => {
10563      if (isTableSection(node)) {
10564        return Optional.some(node);
10565      } else if (!contains(root, node)) {
10566        return Optional.some(root);
10567      } else {
10568        return Optional.none();
10569      }
10570    });
10571    const normalizeSelection = (editor, rng) => {
10572      getFocusInElement(SugarElement.fromDom(editor.getBody()), rng).bind(elm => {
10573        return firstPositionIn(elm.dom);
10574      }).fold(() => {
10575        editor.selection.normalize();
10576      }, caretPos => editor.selection.setRng(caretPos.toRange()));
10577    };
10578    const focusBody = body => {
10579      if (body.setActive) {
10580        try {
10581          body.setActive();
10582        } catch (ex) {
10583          body.focus();
10584        }
10585      } else {
10586        body.focus();
10587      }
10588    };
10589    const hasElementFocus = elm => hasFocus$1(elm) || search(elm).isSome();
10590    const hasIframeFocus = editor => isNonNullable(editor.iframeElement) && hasFocus$1(SugarElement.fromDom(editor.iframeElement));
10591    const hasInlineFocus = editor => {
10592      const rawBody = editor.getBody();
10593      return rawBody && hasElementFocus(SugarElement.fromDom(rawBody));
10594    };
10595    const hasUiFocus = editor => {
10596      const dos = getRootNode(SugarElement.fromDom(editor.getElement()));
10597      return active$1(dos).filter(elem => !isEditorContentAreaElement(elem.dom) && isUIElement(editor, elem.dom)).isSome();
10598    };
10599    const hasFocus = editor => editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor);
10600    const hasEditorOrUiFocus = editor => hasFocus(editor) || hasUiFocus(editor);
10601    const focusEditor = editor => {
10602      const selection = editor.selection;
10603      const body = editor.getBody();
10604      let rng = selection.getRng();
10605      editor.quirks.refreshContentEditable();
10606      if (isNonNullable(editor.bookmark) && !hasFocus(editor)) {
10607        getRng(editor).each(bookmarkRng => {
10608          editor.selection.setRng(bookmarkRng);
10609          rng = bookmarkRng;
10610        });
10611      }
10612      const contentEditableHost = getContentEditableHost(editor, selection.getNode());
10613      if (contentEditableHost && editor.dom.isChildOf(contentEditableHost, body)) {
10614        focusBody(contentEditableHost);
10615        normalizeSelection(editor, rng);
10616        activateEditor(editor);
10617        return;
10618      }
10619      if (!editor.inline) {
10620        if (!Env.browser.isOpera()) {
10621          focusBody(body);
10622        }
10623        editor.getWin().focus();
10624      }
10625      if (Env.browser.isFirefox() || editor.inline) {
10626        focusBody(body);
10627        normalizeSelection(editor, rng);
10628      }
10629      activateEditor(editor);
10630    };
10631    const activateEditor = editor => editor.editorManager.setActive(editor);
10632    const focus = (editor, skipFocus) => {
10633      if (editor.removed) {
10634        return;
10635      }
10636      if (skipFocus) {
10637        activateEditor(editor);
10638      } else {
10639        focusEditor(editor);
10640      }
10641    };
10642
10643    const getEndpointElement = (root, rng, start, real, resolve) => {
10644      const container = start ? rng.startContainer : rng.endContainer;
10645      const offset = start ? rng.startOffset : rng.endOffset;
10646      return Optional.from(container).map(SugarElement.fromDom).map(elm => !real || !rng.collapsed ? child$1(elm, resolve(elm, offset)).getOr(elm) : elm).bind(elm => isElement$7(elm) ? Optional.some(elm) : parent(elm).filter(isElement$7)).map(elm => elm.dom).getOr(root);
10647    };
10648    const getStart = (root, rng, real = false) => getEndpointElement(root, rng, true, real, (elm, offset) => Math.min(childNodesCount(elm), offset));
10649    const getEnd$1 = (root, rng, real = false) => getEndpointElement(root, rng, false, real, (elm, offset) => offset > 0 ? offset - 1 : offset);
10650    const skipEmptyTextNodes = (node, forwards) => {
10651      const orig = node;
10652      while (node && isText$a(node) && node.length === 0) {
10653        node = forwards ? node.nextSibling : node.previousSibling;
10654      }
10655      return node || orig;
10656    };
10657    const getNode = (root, rng) => {
10658      if (!rng) {
10659        return root;
10660      }
10661      let startContainer = rng.startContainer;
10662      let endContainer = rng.endContainer;
10663      const startOffset = rng.startOffset;
10664      const endOffset = rng.endOffset;
10665      let node = rng.commonAncestorContainer;
10666      if (!rng.collapsed) {
10667        if (startContainer === endContainer) {
10668          if (endOffset - startOffset < 2) {
10669            if (startContainer.hasChildNodes()) {
10670              node = startContainer.childNodes[startOffset];
10671            }
10672          }
10673        }
10674        if (isText$a(startContainer) && isText$a(endContainer)) {
10675          if (startContainer.length === startOffset) {
10676            startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
10677          } else {
10678            startContainer = startContainer.parentNode;
10679          }
10680          if (endOffset === 0) {
10681            endContainer = skipEmptyTextNodes(endContainer.previousSibling, false);
10682          } else {
10683            endContainer = endContainer.parentNode;
10684          }
10685          if (startContainer && startContainer === endContainer) {
10686            node = startContainer;
10687          }
10688        }
10689      }
10690      const elm = isText$a(node) ? node.parentNode : node;
10691      return isElement$6(elm) ? elm : root;
10692    };
10693    const getSelectedBlocks = (dom, rng, startElm, endElm) => {
10694      const selectedBlocks = [];
10695      const root = dom.getRoot();
10696      const start = dom.getParent(startElm || getStart(root, rng, rng.collapsed), dom.isBlock);
10697      const end = dom.getParent(endElm || getEnd$1(root, rng, rng.collapsed), dom.isBlock);
10698      if (start && start !== root) {
10699        selectedBlocks.push(start);
10700      }
10701      if (start && end && start !== end) {
10702        let node;
10703        const walker = new DomTreeWalker(start, root);
10704        while ((node = walker.next()) && node !== end) {
10705          if (dom.isBlock(node)) {
10706            selectedBlocks.push(node);
10707          }
10708        }
10709      }
10710      if (end && start !== end && end !== root) {
10711        selectedBlocks.push(end);
10712      }
10713      return selectedBlocks;
10714    };
10715    const select = (dom, node, content) => Optional.from(node).bind(node => Optional.from(node.parentNode).map(parent => {
10716      const idx = dom.nodeIndex(node);
10717      const rng = dom.createRng();
10718      rng.setStart(parent, idx);
10719      rng.setEnd(parent, idx + 1);
10720      if (content) {
10721        moveEndPoint(dom, rng, node, true);
10722        moveEndPoint(dom, rng, node, false);
10723      }
10724      return rng;
10725    }));
10726
10727    const processRanges = (editor, ranges) => map$3(ranges, range => {
10728      const evt = editor.dispatch('GetSelectionRange', { range });
10729      return evt.range !== range ? evt.range : range;
10730    });
10731
10732    const getEnd = element => name(element) === 'img' ? 1 : getOption(element).fold(() => children$1(element).length, v => v.length);
10733    const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome();
10734    const isContentEditableFalse$5 = elem => isHTMLElement(elem) && get$9(elem, 'contenteditable') === 'false';
10735    const elementsWithCursorPosition = [
10736      'img',
10737      'br'
10738    ];
10739    const isCursorPosition = elem => {
10740      const hasCursorPosition = isTextNodeWithCursorPosition(elem);
10741      return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse$5(elem);
10742    };
10743
10744    const first = element => descendant$1(element, isCursorPosition);
10745    const last = element => descendantRtl(element, isCursorPosition);
10746    const descendantRtl = (scope, predicate) => {
10747      const descend = element => {
10748        const children = children$1(element);
10749        for (let i = children.length - 1; i >= 0; i--) {
10750          const child = children[i];
10751          if (predicate(child)) {
10752            return Optional.some(child);
10753          }
10754          const res = descend(child);
10755          if (res.isSome()) {
10756            return res;
10757          }
10758        }
10759        return Optional.none();
10760      };
10761      return descend(scope);
10762    };
10763
10764    const autocompleteSelector = '[data-mce-autocompleter]';
10765    const create$9 = (editor, range) => {
10766      if (findIn(SugarElement.fromDom(editor.getBody())).isNone()) {
10767        const wrapper = SugarElement.fromHtml('<span data-mce-autocompleter="1" data-mce-bogus="1"></span>', editor.getDoc());
10768        append$1(wrapper, SugarElement.fromDom(range.extractContents()));
10769        range.insertNode(wrapper.dom);
10770        parent(wrapper).each(elm => elm.dom.normalize());
10771        last(wrapper).map(last => {
10772          editor.selection.setCursorLocation(last.dom, getEnd(last));
10773        });
10774      }
10775    };
10776    const detect$1 = elm => closest$3(elm, autocompleteSelector);
10777    const findIn = elm => descendant(elm, autocompleteSelector);
10778    const remove$
vendor: 24,116 bytes, lines 10778-11496
107783 = (editor, elm) => findIn(elm).each(wrapper => {
10779      const bookmark = editor.selection.getBookmark();
10780      unwrap(wrapper);
10781      editor.selection.moveToBookmark(bookmark);
10782    });
10783
10784    const typeLookup = {
10785      '#text': 3,
10786      '#comment': 8,
10787      '#cdata': 4,
10788      '#pi': 7,
10789      '#doctype': 10,
10790      '#document-fragment': 11
10791    };
10792    const walk$2 = (node, root, prev) => {
10793      const startName = prev ? 'lastChild' : 'firstChild';
10794      const siblingName = prev ? 'prev' : 'next';
10795      if (node[startName]) {
10796        return node[startName];
10797      }
10798      if (node !== root) {
10799        let sibling = node[siblingName];
10800        if (sibling) {
10801          return sibling;
10802        }
10803        for (let parent = node.parent; parent && parent !== root; parent = parent.parent) {
10804          sibling = parent[siblingName];
10805          if (sibling) {
10806            return sibling;
10807          }
10808        }
10809      }
10810      return undefined;
10811    };
10812    const isEmptyTextNode = node => {
10813      var _a;
10814      const text = (_a = node.value) !== null && _a !== void 0 ? _a : '';
10815      if (!isWhitespaceText(text)) {
10816        return false;
10817      }
10818      const parentNode = node.parent;
10819      if (parentNode && (parentNode.name !== 'span' || parentNode.attr('style')) && /^[ ]+$/.test(text)) {
10820        return false;
10821      }
10822      return true;
10823    };
10824    const isNonEmptyElement = node => {
10825      const isNamedAnchor = node.name === 'a' && !node.attr('href') && node.attr('id');
10826      return node.attr('name') || node.attr('id') && !node.firstChild || node.attr('data-mce-bookmark') || isNamedAnchor;
10827    };
10828    class AstNode {
10829      constructor(name, type) {
10830        this.name = name;
10831        this.type = type;
10832        if (type === 1) {
10833          this.attributes = [];
10834          this.attributes.map = {};
10835        }
10836      }
10837      static create(name, attrs) {
10838        const node = new AstNode(name, typeLookup[name] || 1);
10839        if (attrs) {
10840          each$d(attrs, (value, attrName) => {
10841            node.attr(attrName, value);
10842          });
10843        }
10844        return node;
10845      }
10846      replace(node) {
10847        const self = this;
10848        if (node.parent) {
10849          node.remove();
10850        }
10851        self.insert(node, self);
10852        self.remove();
10853        return self;
10854      }
10855      attr(name, value) {
10856        const self = this;
10857        if (!isString(name)) {
10858          if (isNonNullable(name)) {
10859            each$d(name, (value, key) => {
10860              self.attr(key, value);
10861            });
10862          }
10863          return self;
10864        }
10865        const attrs = self.attributes;
10866        if (attrs) {
10867          if (value !== undefined) {
10868            if (value === null) {
10869              if (name in attrs.map) {
10870                delete attrs.map[name];
10871                let i = attrs.length;
10872                while (i--) {
10873                  if (attrs[i].name === name) {
10874                    attrs.splice(i, 1);
10875                    return self;
10876                  }
10877                }
10878              }
10879              return self;
10880            }
10881            if (name in attrs.map) {
10882              let i = attrs.length;
10883              while (i--) {
10884                if (attrs[i].name === name) {
10885                  attrs[i].value = value;
10886                  break;
10887                }
10888              }
10889            } else {
10890              attrs.push({
10891                name,
10892                value
10893              });
10894            }
10895            attrs.map[name] = value;
10896            return self;
10897          }
10898          return attrs.map[name];
10899        }
10900        return undefined;
10901      }
10902      clone() {
10903        const self = this;
10904        const clone = new AstNode(self.name, self.type);
10905        const selfAttrs = self.attributes;
10906        if (selfAttrs) {
10907          const cloneAttrs = [];
10908          cloneAttrs.map = {};
10909          for (let i = 0, l = selfAttrs.length; i < l; i++) {
10910            const selfAttr = selfAttrs[i];
10911            if (selfAttr.name !== 'id') {
10912              cloneAttrs[cloneAttrs.length] = {
10913                name: selfAttr.name,
10914                value: selfAttr.value
10915              };
10916              cloneAttrs.map[selfAttr.name] = selfAttr.value;
10917            }
10918          }
10919          clone.attributes = cloneAttrs;
10920        }
10921        clone.value = self.value;
10922        return clone;
10923      }
10924      wrap(wrapper) {
10925        const self = this;
10926        if (self.parent) {
10927          self.parent.insert(wrapper, self);
10928          wrapper.append(self);
10929        }
10930        return self;
10931      }
10932      unwrap() {
10933        const self = this;
10934        for (let node = self.firstChild; node;) {
10935          const next = node.next;
10936          self.insert(node, self, true);
10937          node = next;
10938        }
10939        self.remove();
10940      }
10941      remove() {
10942        const self = this, parent = self.parent, next = self.next, prev = self.prev;
10943        if (parent) {
10944          if (parent.firstChild === self) {
10945            parent.firstChild = next;
10946            if (next) {
10947              next.prev = null;
10948            }
10949          } else if (prev) {
10950            prev.next = next;
10951          }
10952          if (parent.lastChild === self) {
10953            parent.lastChild = prev;
10954            if (prev) {
10955              prev.next = null;
10956            }
10957          } else if (next) {
10958            next.prev = prev;
10959          }
10960          self.parent = self.next = self.prev = null;
10961        }
10962        return self;
10963      }
10964      append(node) {
10965        const self = this;
10966        if (node.parent) {
10967          node.remove();
10968        }
10969        const last = self.lastChild;
10970        if (last) {
10971          last.next = node;
10972          node.prev = last;
10973          self.lastChild = node;
10974        } else {
10975          self.lastChild = self.firstChild = node;
10976        }
10977        node.parent = self;
10978        return node;
10979      }
10980      insert(node, refNode, before) {
10981        if (node.parent) {
10982          node.remove();
10983        }
10984        const parent = refNode.parent || this;
10985        if (before) {
10986          if (refNode === parent.firstChild) {
10987            parent.firstChild = node;
10988          } else if (refNode.prev) {
10989            refNode.prev.next = node;
10990          }
10991          node.prev = refNode.prev;
10992          node.next = refNode;
10993          refNode.prev = node;
10994        } else {
10995          if (refNode === parent.lastChild) {
10996            parent.lastChild = node;
10997          } else if (refNode.next) {
10998            refNode.next.prev = node;
10999          }
11000          node.next = refNode.next;
11001          node.prev = refNode;
11002          refNode.next = node;
11003        }
11004        node.parent = parent;
11005        return node;
11006      }
11007      getAll(name) {
11008        const self = this;
11009        const collection = [];
11010        for (let node = self.firstChild; node; node = walk$2(node, self)) {
11011          if (node.name === name) {
11012            collection.push(node);
11013          }
11014        }
11015        return collection;
11016      }
11017      children() {
11018        const self = this;
11019        const collection = [];
11020        for (let node = self.firstChild; node; node = node.next) {
11021          collection.push(node);
11022        }
11023        return collection;
11024      }
11025      empty() {
11026        const self = this;
11027        if (self.firstChild) {
11028          const nodes = [];
11029          for (let node = self.firstChild; node; node = walk$2(node, self)) {
11030            nodes.push(node);
11031          }
11032          let i = nodes.length;
11033          while (i--) {
11034            const node = nodes[i];
11035            node.parent = node.firstChild = node.lastChild = node.next = node.prev = null;
11036          }
11037        }
11038        self.firstChild = self.lastChild = null;
11039        return self;
11040      }
11041      isEmpty(elements, whitespace = {}, predicate) {
11042        var _a;
11043        const self = this;
11044        let node = self.firstChild;
11045        if (isNonEmptyElement(self)) {
11046          return false;
11047        }
11048        if (node) {
11049          do {
11050            if (node.type === 1) {
11051              if (node.attr('data-mce-bogus')) {
11052                continue;
11053              }
11054              if (elements[node.name]) {
11055                return false;
11056              }
11057              if (isNonEmptyElement(node)) {
11058                return false;
11059              }
11060            }
11061            if (node.type === 8) {
11062              return false;
11063            }
11064            if (node.type === 3 && !isEmptyTextNode(node)) {
11065              return false;
11066            }
11067            if (node.type === 3 && node.parent && whitespace[node.parent.name] && isWhitespaceText((_a = node.value) !== null && _a !== void 0 ? _a : '')) {
11068              return false;
11069            }
11070            if (predicate && predicate(node)) {
11071              return false;
11072            }
11073          } while (node = walk$2(node, self));
11074        }
11075        return true;
11076      }
11077      walk(prev) {
11078        return walk$2(this, null, prev);
11079      }
11080    }
11081
11082    const isConditionalComment = (html, startIndex) => /^\s*\[if [\w\W]+\]>.*<!\[endif\](--!?)?>/.test(html.substr(startIndex));
11083    const findCommentEndIndex = (html, isBogus, startIndex = 0) => {
11084      const lcHtml = html.toLowerCase();
11085      if (lcHtml.indexOf('[if ', startIndex) !== -1 && isConditionalComment(lcHtml, startIndex)) {
11086        const endIfIndex = lcHtml.indexOf('[endif]', startIndex);
11087        return lcHtml.indexOf('>', endIfIndex);
11088      } else {
11089        if (isBogus) {
11090          const endIndex = lcHtml.indexOf('>', startIndex);
11091          return endIndex !== -1 ? endIndex : lcHtml.length;
11092        } else {
11093          const endCommentRegexp = /--!?>/g;
11094          endCommentRegexp.lastIndex = startIndex;
11095          const match = endCommentRegexp.exec(html);
11096          return match ? match.index + match[0].length : lcHtml.length;
11097        }
11098      }
11099    };
11100    const findMatchingEndTagIndex = (schema, html, startIndex) => {
11101      const startTagRegExp = /<([!?\/])?([A-Za-z0-9\-_:.]+)/g;
11102      const endTagRegExp = /(?:\s(?:[^'">]+(?:"[^"]*"|'[^']*'))*[^"'>]*(?:"[^">]*|'[^'>]*)?|\s*|\/)>/g;
11103      const voidElements = schema.getVoidElements();
11104      let count = 1, index = startIndex;
11105      while (count !== 0) {
11106        startTagRegExp.lastIndex = index;
11107        while (true) {
11108          const startMatch = startTagRegExp.exec(html);
11109          if (startMatch === null) {
11110            return index;
11111          } else if (startMatch[1] === '!') {
11112            if (startsWith(startMatch[2], '--')) {
11113              index = findCommentEndIndex(html, false, startMatch.index + '!--'.length);
11114            } else {
11115              index = findCommentEndIndex(html, true, startMatch.index + 1);
11116            }
11117            break;
11118          } else {
11119            endTagRegExp.lastIndex = startTagRegExp.lastIndex;
11120            const endMatch = endTagRegExp.exec(html);
11121            if (isNull(endMatch) || endMatch.index !== startTagRegExp.lastIndex) {
11122              continue;
11123            }
11124            if (startMatch[1] === '/') {
11125              count -= 1;
11126            } else if (!has$2(voidElements, startMatch[2])) {
11127              count += 1;
11128            }
11129            index = startTagRegExp.lastIndex + endMatch[0].length;
11130            break;
11131          }
11132        }
11133      }
11134      return index;
11135    };
11136    const trimHtml$1 = (tempAttrs, html) => {
11137      const trimContentRegExp = new RegExp(['\\s?(' + tempAttrs.join('|') + ')="[^"]+"'].join('|'), 'gi');
11138      return html.replace(trimContentRegExp, '');
11139    };
11140    const trimInternal = (serializer, html) => {
11141      const bogusAllRegExp = /<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g;
11142      const schema = serializer.schema;
11143      let content = trimHtml$1(serializer.getTempAttrs(), html);
11144      const voidElements = schema.getVoidElements();
11145      let matches;
11146      while (matches = bogusAllRegExp.exec(content)) {
11147        const index = bogusAllRegExp.lastIndex;
11148        const matchLength = matches[0].length;
11149        let endTagIndex;
11150        if (voidElements[matches[1]]) {
11151          endTagIndex = index;
11152        } else {
11153          endTagIndex = findMatchingEndTagIndex(schema, content, index);
11154        }
11155        content = content.substring(0, index - matchLength) + content.substring(endTagIndex);
11156        bogusAllRegExp.lastIndex = index - matchLength;
11157      }
11158      return trim$1(content);
11159    };
11160    const trimExternal = trimInternal;
11161
11162    const cleanupBogusElements = parent => {
11163      const bogusElements = descendants(parent, '[data-mce-bogus]');
11164      each$e(bogusElements, elem => {
11165        const bogusValue = get$9(elem, 'data-mce-bogus');
11166        if (bogusValue === 'all') {
11167          remove$6(elem);
11168        } else if (isBr$5(elem)) {
11169          before$3(elem, SugarElement.fromText(zeroWidth));
11170          remove$6(elem);
11171        } else {
11172          unwrap(elem);
11173        }
11174      });
11175    };
11176    const cleanupInputNames = parent => {
11177      const inputs = descendants(parent, 'input');
11178      each$e(inputs, input => {
11179        remove$b(input, 'name');
11180      });
11181    };
11182
11183    const trimEmptyContents = (editor, html) => {
11184      const blockName = getForcedRootBlock(editor);
11185      const emptyRegExp = new RegExp(`^(<${ blockName }[^>]*>(&nbsp;|&#160;|\\s|\u00a0|<br \\/>|)<\\/${ blockName }>[\r\n]*|<br \\/>[\r\n]*)$`);
11186      return html.replace(emptyRegExp, '');
11187    };
11188    const getPlainTextContent = (editor, body) => {
11189      const doc = editor.getDoc();
11190      const dos = getRootNode(SugarElement.fromDom(editor.getBody()));
11191      const offscreenDiv = SugarElement.fromTag('div', doc);
11192      set$3(offscreenDiv, 'data-mce-bogus', 'all');
11193      setAll(offscreenDiv, {
11194        position: 'fixed',
11195        left: '-9999999px',
11196        top: '0'
11197      });
11198      set$1(offscreenDiv, body.innerHTML);
11199      cleanupBogusElements(offscreenDiv);
11200      cleanupInputNames(offscreenDiv);
11201      const root = getContentContainer(dos);
11202      append$1(root, offscreenDiv);
11203      const content = trim$1(offscreenDiv.dom.innerText);
11204      remove$6(offscreenDiv);
11205      return content;
11206    };
11207    const getContentFromBody = (editor, args, body) => {
11208      let content;
11209      if (args.format === 'raw') {
11210        content = Tools.trim(trimExternal(editor.serializer, body.innerHTML));
11211      } else if (args.format === 'text') {
11212        content = getPlainTextContent(editor, body);
11213      } else if (args.format === 'tree') {
11214        content = editor.serializer.serialize(body, args);
11215      } else {
11216        content = trimEmptyContents(editor, editor.serializer.serialize(body, args));
11217      }
11218      const shouldTrim = args.format !== 'text' && !isWsPreserveElement(SugarElement.fromDom(body));
11219      return shouldTrim && isString(content) ? Tools.trim(content) : content;
11220    };
11221    const getContentInternal = (editor, args) => Optional.from(editor.getBody()).fold(constant(args.format === 'tree' ? new AstNode('body', 11) : ''), body => getContentFromBody(editor, args, body));
11222
11223    const makeMap$1 = Tools.makeMap;
11224    const Writer = settings => {
11225      const html = [];
11226      settings = settings || {};
11227      const indent = settings.indent;
11228      const indentBefore = makeMap$1(settings.indent_before || '');
11229      const indentAfter = makeMap$1(settings.indent_after || '');
11230      const encode = Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities);
11231      const htmlOutput = settings.element_format !== 'xhtml';
11232      return {
11233        start: (name, attrs, empty) => {
11234          if (indent && indentBefore[name] && html.length > 0) {
11235            const value = html[html.length - 1];
11236            if (value.length > 0 && value !== '\n') {
11237              html.push('\n');
11238            }
11239          }
11240          html.push('<', name);
11241          if (attrs) {
11242            for (let i = 0, l = attrs.length; i < l; i++) {
11243              const attr = attrs[i];
11244              html.push(' ', attr.name, '="', encode(attr.value, true), '"');
11245            }
11246          }
11247          if (!empty || htmlOutput) {
11248            html[html.length] = '>';
11249          } else {
11250            html[html.length] = ' />';
11251          }
11252          if (empty && indent && indentAfter[name] && html.length > 0) {
11253            const value = html[html.length - 1];
11254            if (value.length > 0 && value !== '\n') {
11255              html.push('\n');
11256            }
11257          }
11258        },
11259        end: name => {
11260          let value;
11261          html.push('</', name, '>');
11262          if (indent && indentAfter[name] && html.length > 0) {
11263            value = html[html.length - 1];
11264            if (value.length > 0 && value !== '\n') {
11265              html.push('\n');
11266            }
11267          }
11268        },
11269        text: (text, raw) => {
11270          if (text.length > 0) {
11271            html[html.length] = raw ? text : encode(text);
11272          }
11273        },
11274        cdata: text => {
11275          html.push('<![CDATA[', text, ']]>');
11276        },
11277        comment: text => {
11278          html.push('<!--', text, '-->');
11279        },
11280        pi: (name, text) => {
11281          if (text) {
11282            html.push('<?', name, ' ', encode(text), '?>');
11283          } else {
11284            html.push('<?', name, '?>');
11285          }
11286          if (indent) {
11287            html.push('\n');
11288          }
11289        },
11290        doctype: text => {
11291          html.push('<!DOCTYPE', text, '>', indent ? '\n' : '');
11292        },
11293        reset: () => {
11294          html.length = 0;
11295        },
11296        getContent: () => {
11297          return html.join('').replace(/\n$/, '');
11298        }
11299      };
11300    };
11301
11302    const HtmlSerializer = (settings = {}, schema = Schema()) => {
11303      const writer = Writer(settings);
11304      settings.validate = 'validate' in settings ? settings.validate : true;
11305      const serialize = node => {
11306        const validate = settings.validate;
11307        const handlers = {
11308          3: node => {
11309            var _a;
11310            writer.text((_a = node.value) !== null && _a !== void 0 ? _a : '', node.raw);
11311          },
11312          8: node => {
11313            var _a;
11314            writer.comment((_a = node.value) !== null && _a !== void 0 ? _a : '');
11315          },
11316          7: node => {
11317            writer.pi(node.name, node.value);
11318          },
11319          10: node => {
11320            var _a;
11321            writer.doctype((_a = node.value) !== null && _a !== void 0 ? _a : '');
11322          },
11323          4: node => {
11324            var _a;
11325            writer.cdata((_a = node.value) !== null && _a !== void 0 ? _a : '');
11326          },
11327          11: node => {
11328            let tempNode = node;
11329            if (tempNode = tempNode.firstChild) {
11330              do {
11331                walk(tempNode);
11332              } while (tempNode = tempNode.next);
11333            }
11334          }
11335        };
11336        writer.reset();
11337        const walk = node => {
11338          var _a;
11339          const handler = handlers[node.type];
11340          if (!handler) {
11341            const name = node.name;
11342            const isEmpty = name in schema.getVoidElements();
11343            let attrs = node.attributes;
11344            if (validate && attrs && attrs.length > 1) {
11345              const sortedAttrs = [];
11346              sortedAttrs.map = {};
11347              const elementRule = schema.getElementRule(node.name);
11348              if (elementRule) {
11349                for (let i = 0, l = elementRule.attributesOrder.length; i < l; i++) {
11350                  const attrName = elementRule.attributesOrder[i];
11351                  if (attrName in attrs.map) {
11352                    const attrValue = attrs.map[attrName];
11353                    sortedAttrs.map[attrName] = attrValue;
11354                    sortedAttrs.push({
11355                      name: attrName,
11356                      value: attrValue
11357                    });
11358                  }
11359                }
11360                for (let i = 0, l = attrs.length; i < l; i++) {
11361                  const attrName = attrs[i].name;
11362                  if (!(attrName in sortedAttrs.map)) {
11363                    const attrValue = attrs.map[attrName];
11364                    sortedAttrs.map[attrName] = attrValue;
11365                    sortedAttrs.push({
11366                      name: attrName,
11367                      value: attrValue
11368                    });
11369                  }
11370                }
11371                attrs = sortedAttrs;
11372              }
11373            }
11374            writer.start(name, attrs, isEmpty);
11375            if (!isEmpty) {
11376              let child = node.firstChild;
11377              if (child) {
11378                if ((name === 'pre' || name === 'textarea') && child.type === 3 && ((_a = child.value) === null || _a === void 0 ? void 0 : _a[0]) === '\n') {
11379                  writer.text('\n', true);
11380                }
11381                do {
11382                  walk(child);
11383                } while (child = child.next);
11384              }
11385              writer.end(name);
11386            }
11387          } else {
11388            handler(node);
11389          }
11390        };
11391        if (node.type === 1 && !settings.inner) {
11392          walk(node);
11393        } else if (node.type === 3) {
11394          handlers[3](node);
11395        } else {
11396          handlers[11](node);
11397        }
11398        return writer.getContent();
11399      };
11400      return { serialize };
11401    };
11402
11403    const nonInheritableStyles = new Set();
11404    (() => {
11405      const nonInheritableStylesArr = [
11406        'margin',
11407        'margin-left',
11408        'margin-right',
11409        'margin-top',
11410        'margin-bottom',
11411        'padding',
11412        'padding-left',
11413        'padding-right',
11414        'padding-top',
11415        'padding-bottom',
11416        'border',
11417        'border-width',
11418        'border-style',
11419        'border-color',
11420        'background',
11421        'background-attachment',
11422        'background-clip',
11423        'background-color',
11424        'background-image',
11425        'background-origin',
11426        'background-position',
11427        'background-repeat',
11428        'background-size',
11429        'float',
11430        'position',
11431        'left',
11432        'right',
11433        'top',
11434        'bottom',
11435        'z-index',
11436        'display',
11437        'transform',
11438        'width',
11439        'max-width',
11440        'min-width',
11441        'height',
11442        'max-height',
11443        'min-height',
11444        'overflow',
11445        'overflow-x',
11446        'overflow-y',
11447        'text-overflow',
11448        'vertical-align',
11449        'transition',
11450        'transition-delay',
11451        'transition-duration',
11452        'transition-property',
11453        'transition-timing-function'
11454      ];
11455      each$e(nonInheritableStylesArr, style => {
11456        nonInheritableStyles.add(style);
11457      });
11458    })();
11459    const shorthandStyleProps = [
11460      'font',
11461      'text-decoration',
11462      'text-emphasis'
11463    ];
11464    const getStyleProps = (dom, node) => keys(dom.parseStyle(dom.getAttrib(node, 'style')));
11465    const isNonInheritableStyle = style => nonInheritableStyles.has(style);
11466    const hasInheritableStyles = (dom, node) => forall(getStyleProps(dom, node), style => !isNonInheritableStyle(style));
11467    const getLonghandStyleProps = styles => filter$5(styles, style => exists(shorthandStyleProps, prop => startsWith(style, prop)));
11468    const hasStyleConflict = (dom, node, parentNode) => {
11469      const nodeStyleProps = getStyleProps(dom, node);
11470      const parentNodeStyleProps = getStyleProps(dom, parentNode);
11471      const valueMismatch = prop => {
11472        var _a, _b;
11473        const nodeValue = (_a = dom.getStyle(node, prop)) !== null && _a !== void 0 ? _a : '';
11474        const parentValue = (_b = dom.getStyle(parentNode, prop)) !== null && _b !== void 0 ? _b : '';
11475        return isNotEmpty(nodeValue) && isNotEmpty(parentValue) && nodeValue !== parentValue;
11476      };
11477      return exists(nodeStyleProps, nodeStyleProp => {
11478        const propExists = props => exists(props, prop => prop === nodeStyleProp);
11479        if (!propExists(parentNodeStyleProps) && propExists(shorthandStyleProps)) {
11480          const longhandProps = getLonghandStyleProps(parentNodeStyleProps);
11481          return exists(longhandProps, valueMismatch);
11482        } else {
11483          return valueMismatch(nodeStyleProp);
11484        }
11485      });
11486    };
11487
11488    const isChar = (forward, predicate, pos) => Optional.from(pos.container()).filter(isText$a).exists(text => {
11489      const delta = forward ? 0 : -1;
11490      return predicate(text.data.charAt(pos.offset() + delta));
11491    });
11492    const isBeforeSpace = curry(isChar, true, isWhiteSpace);
11493    const isAfterSpace = curry(isChar, false, isWhiteSpace);
11494    const isEmptyText = pos => {
11495      const container = pos.container();
11496      return isText$a(container) && (container.data.length === 0 || isZwsp
vendor: 11,094 bytes, lines 11496-11721
11496(container.data) && BookmarkManager.isBookmarkNode(container.parentNode));
11497    };
11498    const matchesElementPosition = (before, predicate) => pos => getChildNodeAtRelativeOffset(before ? 0 : -1, pos).filter(predicate).isSome();
11499    const isImageBlock = node => isImg(node) && get$7(SugarElement.fromDom(node), 'display') === 'block';
11500    const isCefNode = node => isContentEditableFalse$b(node) && !isBogusAll$1(node);
11501    const isBeforeImageBlock = matchesElementPosition(true, isImageBlock);
11502    const isAfterImageBlock = matchesElementPosition(false, isImageBlock);
11503    const isBeforeMedia = matchesElementPosition(true, isMedia$2);
11504    const isAfterMedia = matchesElementPosition(false, isMedia$2);
11505    const isBeforeTable = matchesElementPosition(true, isTable$2);
11506    const isAfterTable = matchesElementPosition(false, isTable$2);
11507    const isBeforeContentEditableFalse = matchesElementPosition(true, isCefNode);
11508    const isAfterContentEditableFalse = matchesElementPosition(false, isCefNode);
11509
11510    const dropLast = xs => xs.slice(0, -1);
11511    const parentsUntil = (start, root, predicate) => {
11512      if (contains(root, start)) {
11513        return dropLast(parents$1(start, elm => {
11514          return predicate(elm) || eq(elm, root);
11515        }));
11516      } else {
11517        return [];
11518      }
11519    };
11520    const parents = (start, root) => parentsUntil(start, root, never);
11521    const parentsAndSelf = (start, root) => [start].concat(parents(start, root));
11522
11523    const navigateIgnoreEmptyTextNodes = (forward, root, from) => navigateIgnore(forward, root, from, isEmptyText);
11524    const getClosestBlock$1 = (root, pos) => find$2(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$2);
11525    const isAtBeforeAfterBlockBoundary = (forward, root, pos) => navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(newPos => getClosestBlock$1(root, pos).fold(() => !isInSameBlock(newPos, pos, root.dom), fromBlock => !isInSameBlock(newPos, pos, root.dom) && contains(fromBlock, SugarElement.fromDom(newPos.container()))));
11526    const isAtBlockBoundary = (forward, root, pos) => getClosestBlock$1(root, pos).fold(() => navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(newPos => !isInSameBlock(newPos, pos, root.dom)), parent => navigateIgnoreEmptyTextNodes(forward, parent.dom, pos).isNone());
11527    const isAtStartOfBlock = curry(isAtBlockBoundary, false);
11528    const isAtEndOfBlock = curry(isAtBlockBoundary, true);
11529    const isBeforeBlock = curry(isAtBeforeAfterBlockBoundary, false);
11530    const isAfterBlock = curry(isAtBeforeAfterBlockBoundary, true);
11531
11532    const isBr$1 = pos => getElementFromPosition(pos).exists(isBr$5);
11533    const findBr = (forward, root, pos) => {
11534      const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$2);
11535      const scope = head(parentBlocks).getOr(root);
11536      return fromPosition(forward, scope.dom, pos).filter(isBr$1);
11537    };
11538    const isBeforeBr$1 = (root, pos) => getElementFromPosition(pos).exists(isBr$5) || findBr(true, root, pos).isSome();
11539    const isAfterBr = (root, pos) => getElementFromPrevPosition(pos).exists(isBr$5) || findBr(false, root, pos).isSome();
11540    const findPreviousBr = curry(findBr, false);
11541    const findNextBr = curry(findBr, true);
11542
11543    const isInMiddleOfText = pos => CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd();
11544    const getClosestBlock = (root, pos) => {
11545      const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$2);
11546      return head(parentBlocks).getOr(root);
11547    };
11548    const hasSpaceBefore = (root, pos) => {
11549      if (isInMiddleOfText(pos)) {
11550        return isAfterSpace(pos);
11551      } else {
11552        return isAfterSpace(pos) || prevPosition(getClosestBlock(root, pos).dom, pos).exists(isAfterSpace);
11553      }
11554    };
11555    const hasSpaceAfter = (root, pos) => {
11556      if (isInMiddleOfText(pos)) {
11557        return isBeforeSpace(pos);
11558      } else {
11559        return isBeforeSpace(pos) || nextPosition(getClosestBlock(root, pos).dom, pos).exists(isBeforeSpace);
11560      }
11561    };
11562    const isPreValue = value => contains$2([
11563      'pre',
11564      'pre-wrap'
11565    ], value);
11566    const isInPre = pos => getElementFromPosition(pos).bind(elm => closest$4(elm, isElement$7)).exists(elm => isPreValue(get$7(elm, 'white-space')));
11567    const isAtBeginningOfBody = (root, pos) => prevPosition(root.dom, pos).isNone();
11568    const isAtEndOfBody = (root, pos) => nextPosition(root.dom, pos).isNone();
11569    const isAtLineBoundary = (root, pos) => isAtBeginningOfBody(root, pos) || isAtEndOfBody(root, pos) || isAtStartOfBlock(root, pos) || isAtEndOfBlock(root, pos) || isAfterBr(root, pos) || isBeforeBr$1(root, pos);
11570    const isCefBlock = node => isNonNullable(node) && isContentEditableFalse$b(node) && isBlockLike(node);
11571    const isSiblingCefBlock = (root, direction) => container => {
11572      return isCefBlock(new DomTreeWalker(container, root)[direction]());
11573    };
11574    const isBeforeCefBlock = (root, pos) => {
11575      const nextPos = nextPosition(root.dom, pos).getOr(pos);
11576      const isNextCefBlock = isSiblingCefBlock(root.dom, 'next');
11577      return pos.isAtEnd() && (isNextCefBlock(pos.container()) || isNextCefBlock(nextPos.container()));
11578    };
11579    const isAfterCefBlock = (root, pos) => {
11580      const prevPos = prevPosition(root.dom, pos).getOr(pos);
11581      const isPrevCefBlock = isSiblingCefBlock(root.dom, 'prev');
11582      return pos.isAtStart() && (isPrevCefBlock(pos.container()) || isPrevCefBlock(prevPos.container()));
11583    };
11584    const needsToHaveNbsp = (root, pos) => {
11585      if (isInPre(pos)) {
11586        return false;
11587      } else {
11588        return isAtLineBoundary(root, pos) || hasSpaceBefore(root, pos) || hasSpaceAfter(root, pos);
11589      }
11590    };
11591    const needsToBeNbspLeft = (root, pos) => {
11592      if (isInPre(pos)) {
11593        return false;
11594      } else {
11595        return isAtStartOfBlock(root, pos) || isBeforeBlock(root, pos) || isAfterBr(root, pos) || hasSpaceBefore(root, pos) || isAfterCefBlock(root, pos);
11596      }
11597    };
11598    const leanRight = pos => {
11599      const container = pos.container();
11600      const offset = pos.offset();
11601      if (isText$a(container) && offset < container.data.length) {
11602        return CaretPosition(container, offset + 1);
11603      } else {
11604        return pos;
11605      }
11606    };
11607    const needsToBeNbspRight = (root, pos) => {
11608      if (isInPre(pos)) {
11609        return false;
11610      } else {
11611        return isAtEndOfBlock(root, pos) || isAfterBlock(root, pos) || isBeforeBr$1(root, pos) || hasSpaceAfter(root, pos) || isBeforeCefBlock(root, pos);
11612      }
11613    };
11614    const needsToBeNbsp = (root, pos) => needsToBeNbspLeft(root, pos) || needsToBeNbspRight(root, leanRight(pos));
11615    const isNbspAt = (text, offset) => isNbsp(text.charAt(offset));
11616    const isWhiteSpaceAt = (text, offset) => isWhiteSpace(text.charAt(offset));
11617    const hasNbsp = pos => {
11618      const container = pos.container();
11619      return isText$a(container) && contains$1(container.data, nbsp);
11620    };
11621    const normalizeNbspMiddle = text => {
11622      const chars = text.split('');
11623      return map$3(chars, (chr, i) => {
11624        if (isNbsp(chr) && i > 0 && i < chars.length - 1 && isContent(chars[i - 1]) && isContent(chars[i + 1])) {
11625          return ' ';
11626        } else {
11627          return chr;
11628        }
11629      }).join('');
11630    };
11631    const normalizeNbspAtStart = (root, node, makeNbsp) => {
11632      const text = node.data;
11633      const firstPos = CaretPosition(node, 0);
11634      if (!makeNbsp && isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos)) {
11635        node.data = ' ' + text.slice(1);
11636        return true;
11637      } else if (makeNbsp && isWhiteSpaceAt(text, 0) && needsToBeNbspLeft(root, firstPos)) {
11638        node.data = nbsp + text.slice(1);
11639        return true;
11640      } else {
11641        return false;
11642      }
11643    };
11644    const normalizeNbspInMiddleOfTextNode = node => {
11645      const text = node.data;
11646      const newText = normalizeNbspMiddle(text);
11647      if (newText !== text) {
11648        node.data = newText;
11649        return true;
11650      } else {
11651        return false;
11652      }
11653    };
11654    const normalizeNbspAtEnd = (root, node, makeNbsp) => {
11655      const text = node.data;
11656      const lastPos = CaretPosition(node, text.length - 1);
11657      if (!makeNbsp && isNbspAt(text, text.length - 1) && !needsToBeNbsp(root, lastPos)) {
11658        node.data = text.slice(0, -1) + ' ';
11659        return true;
11660      } else if (makeNbsp && isWhiteSpaceAt(text, text.length - 1) && needsToBeNbspRight(root, lastPos)) {
11661        node.data = text.slice(0, -1) + nbsp;
11662        return true;
11663      } else {
11664        return false;
11665      }
11666    };
11667    const normalizeNbsps = (root, pos) => {
11668      const container = pos.container();
11669      if (!isText$a(container)) {
11670        return Optional.none();
11671      }
11672      if (hasNbsp(pos)) {
11673        const normalized = normalizeNbspAtStart(root, container, false) || normalizeNbspInMiddleOfTextNode(container) || normalizeNbspAtEnd(root, container, false);
11674        return someIf(normalized, pos);
11675      } else if (needsToBeNbsp(root, pos)) {
11676        const normalized = normalizeNbspAtStart(root, container, true) || normalizeNbspAtEnd(root, container, true);
11677        return someIf(normalized, pos);
11678      } else {
11679        return Optional.none();
11680      }
11681    };
11682    const normalizeNbspsInEditor = editor => {
11683      const root = SugarElement.fromDom(editor.getBody());
11684      if (editor.selection.isCollapsed()) {
11685        normalizeNbsps(root, CaretPosition.fromRangeStart(editor.selection.getRng())).each(pos => {
11686          editor.selection.setRng(pos.toRange());
11687        });
11688      }
11689    };
11690
11691    const normalize$1 = (node, offset, count) => {
11692      if (count === 0) {
11693        return;
11694      }
11695      const elm = SugarElement.fromDom(node);
11696      const root = ancestor$4(elm, isBlock$2).getOr(elm);
11697      const whitespace = node.data.slice(offset, offset + count);
11698      const isEndOfContent = offset + count >= node.data.length && needsToBeNbspRight(root, CaretPosition(node, node.data.length));
11699      const isStartOfContent = offset === 0 && needsToBeNbspLeft(root, CaretPosition(node, 0));
11700      node.replaceData(offset, count, normalize$4(whitespace, 4, isStartOfContent, isEndOfContent));
11701    };
11702    const normalizeWhitespaceAfter = (node, offset) => {
11703      const content = node.data.slice(offset);
11704      const whitespaceCount = content.length - lTrim(content).length;
11705      normalize$1(node, offset, whitespaceCount);
11706    };
11707    const normalizeWhitespaceBefore = (node, offset) => {
11708      const content = node.data.slice(0, offset);
11709      const whitespaceCount = content.length - rTrim(content).length;
11710      normalize$1(node, offset - whitespaceCount, whitespaceCount);
11711    };
11712    const mergeTextNodes = (prevNode, nextNode, normalizeWhitespace, mergeToPrev = true) => {
11713      const whitespaceOffset = rTrim(prevNode.data).length;
11714      const newNode = mergeToPrev ? prevNode : nextNode;
11715      const removeNode = mergeToPrev ? nextNode : prevNode;
11716      if (mergeToPrev) {
11717        newNode.appendData(removeNode.data);
11718      } else {
11719        newNode.insertData(0, removeNode.data);
11720      }
11721      remove$
vendor: 2,489 bytes, lines 11721-11757
117216(SugarElement.fromDom(removeNode));
11722      if (normalizeWhitespace) {
11723        normalizeWhitespaceAfter(newNode, whitespaceOffset);
11724      }
11725      return newNode;
11726    };
11727
11728    const needsReposition = (pos, elm) => {
11729      const container = pos.container();
11730      const offset = pos.offset();
11731      return !CaretPosition.isTextPosition(pos) && container === elm.parentNode && offset > CaretPosition.before(elm).offset();
11732    };
11733    const reposition = (elm, pos) => needsReposition(pos, elm) ? CaretPosition(pos.container(), pos.offset() - 1) : pos;
11734    const beforeOrStartOf = node => isText$a(node) ? CaretPosition(node, 0) : CaretPosition.before(node);
11735    const afterOrEndOf = node => isText$a(node) ? CaretPosition(node, node.data.length) : CaretPosition.after(node);
11736    const getPreviousSiblingCaretPosition = elm => {
11737      if (isCaretCandidate$3(elm.previousSibling)) {
11738        return Optional.some(afterOrEndOf(elm.previousSibling));
11739      } else {
11740        return elm.previousSibling ? lastPositionIn(elm.previousSibling) : Optional.none();
11741      }
11742    };
11743    const getNextSiblingCaretPosition = elm => {
11744      if (isCaretCandidate$3(elm.nextSibling)) {
11745        return Optional.some(beforeOrStartOf(elm.nextSibling));
11746      } else {
11747        return elm.nextSibling ? firstPositionIn(elm.nextSibling) : Optional.none();
11748      }
11749    };
11750    const findCaretPositionBackwardsFromElm = (rootElement, elm) => {
11751      return Optional.from(elm.previousSibling ? elm.previousSibling : elm.parentNode).bind(node => prevPosition(rootElement, CaretPosition.before(node))).orThunk(() => nextPosition(rootElement, CaretPosition.after(elm)));
11752    };
11753    const findCaretPositionForwardsFromElm = (rootElement, elm) => nextPosition(rootElement, CaretPosition.after(elm)).orThunk(() => prevPosition(rootElement, CaretPosition.before(elm)));
11754    const findCaretPositionBackwards = (rootElement, elm) => getPreviousSiblingCaretPosition(elm).orThunk(() => getNextSiblingCaretPosition(elm)).orThunk(() => findCaretPositionBackwardsFromElm(rootElement, elm));
11755    const findCaretPositionForward = (rootElement, elm) => getNextSiblingCaretPosition(elm).orThunk(() => getPreviousSiblingCaretPosition(elm)).orThunk(() => findCaretPositionForwardsFromElm(rootElement, elm));
11756    const findCaretPosition = (forward, rootElement, elm) => forward ? findCaretPositionForward(rootElement, elm) : findCaretPositionBackwards(rootElement, elm);
11757    const findCaretPosOutsideElmAfterDelete = (forward, rootElement, elm) =>
vendor: 6,336 bytes, lines 11757-11891
11757 findCaretPosition(forward, rootElement, elm).map(curry(reposition, elm));
11758    const setSelection$1 = (editor, forward, pos) => {
11759      pos.fold(() => {
11760        editor.focus();
11761      }, pos => {
11762        editor.selection.setRng(pos.toRange(), forward);
11763      });
11764    };
11765    const eqRawNode = rawNode => elm => elm.dom === rawNode;
11766    const isBlock = (editor, elm) => elm && has$2(editor.schema.getBlockElements(), name(elm));
11767    const paddEmptyBlock = elm => {
11768      if (isEmpty$2(elm)) {
11769        const br = SugarElement.fromHtml('<br data-mce-bogus="1">');
11770        empty(elm);
11771        append$1(elm, br);
11772        return Optional.some(CaretPosition.before(br.dom));
11773      } else {
11774        return Optional.none();
11775      }
11776    };
11777    const deleteNormalized = (elm, afterDeletePosOpt, normalizeWhitespace) => {
11778      const prevTextOpt = prevSibling(elm).filter(isText$b);
11779      const nextTextOpt = nextSibling(elm).filter(isText$b);
11780      remove$6(elm);
11781      return lift3(prevTextOpt, nextTextOpt, afterDeletePosOpt, (prev, next, pos) => {
11782        const prevNode = prev.dom, nextNode = next.dom;
11783        const offset = prevNode.data.length;
11784        mergeTextNodes(prevNode, nextNode, normalizeWhitespace);
11785        return pos.container() === nextNode ? CaretPosition(prevNode, offset) : pos;
11786      }).orThunk(() => {
11787        if (normalizeWhitespace) {
11788          prevTextOpt.each(elm => normalizeWhitespaceBefore(elm.dom, elm.dom.length));
11789          nextTextOpt.each(elm => normalizeWhitespaceAfter(elm.dom, 0));
11790        }
11791        return afterDeletePosOpt;
11792      });
11793    };
11794    const isInlineElement = (editor, element) => has$2(editor.schema.getTextInlineElements(), name(element));
11795    const deleteElement$2 = (editor, forward, elm, moveCaret = true) => {
11796      const afterDeletePos = findCaretPosOutsideElmAfterDelete(forward, editor.getBody(), elm.dom);
11797      const parentBlock = ancestor$4(elm, curry(isBlock, editor), eqRawNode(editor.getBody()));
11798      const normalizedAfterDeletePos = deleteNormalized(elm, afterDeletePos, isInlineElement(editor, elm));
11799      if (editor.dom.isEmpty(editor.getBody())) {
11800        editor.setContent('');
11801        editor.selection.setCursorLocation();
11802      } else {
11803        parentBlock.bind(paddEmptyBlock).fold(() => {
11804          if (moveCaret) {
11805            setSelection$1(editor, forward, normalizedAfterDeletePos);
11806          }
11807        }, paddPos => {
11808          if (moveCaret) {
11809            setSelection$1(editor, forward, Optional.some(paddPos));
11810          }
11811        });
11812      }
11813    };
11814
11815    const strongRtl = /[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/;
11816    const hasStrongRtl = text => strongRtl.test(text);
11817
11818    const isInlineTarget = (editor, elm) => is$1(SugarElement.fromDom(elm), getInlineBoundarySelector(editor)) && !isTransparentBlock(editor.schema, elm) && editor.dom.isEditable(elm);
11819    const isRtl = element => {
11820      var _a;
11821      return DOMUtils.DOM.getStyle(element, 'direction', true) === 'rtl' || hasStrongRtl((_a = element.textContent) !== null && _a !== void 0 ? _a : '');
11822    };
11823    const findInlineParents = (isInlineTarget, rootNode, pos) => filter$5(DOMUtils.DOM.getParents(pos.container(), '*', rootNode), isInlineTarget);
11824    const findRootInline = (isInlineTarget, rootNode, pos) => {
11825      const parents = findInlineParents(isInlineTarget, rootNode, pos);
11826      return Optional.from(parents[parents.length - 1]);
11827    };
11828    const hasSameParentBlock = (rootNode, node1, node2) => {
11829      const block1 = getParentBlock$3(node1, rootNode);
11830      const block2 = getParentBlock$3(node2, rootNode);
11831      return isNonNullable(block1) && block1 === block2;
11832    };
11833    const isAtZwsp = pos => isBeforeInline(pos) || isAfterInline(pos);
11834    const normalizePosition = (forward, pos) => {
11835      const container = pos.container(), offset = pos.offset();
11836      if (forward) {
11837        if (isCaretContainerInline(container)) {
11838          if (isText$a(container.nextSibling)) {
11839            return CaretPosition(container.nextSibling, 0);
11840          } else {
11841            return CaretPosition.after(container);
11842          }
11843        } else {
11844          return isBeforeInline(pos) ? CaretPosition(container, offset + 1) : pos;
11845        }
11846      } else {
11847        if (isCaretContainerInline(container)) {
11848          if (isText$a(container.previousSibling)) {
11849            return CaretPosition(container.previousSibling, container.previousSibling.data.length);
11850          } else {
11851            return CaretPosition.before(container);
11852          }
11853        } else {
11854          return isAfterInline(pos) ? CaretPosition(container, offset - 1) : pos;
11855        }
11856      }
11857    };
11858    const normalizeForwards = curry(normalizePosition, true);
11859    const normalizeBackwards = curry(normalizePosition, false);
11860
11861    const execCommandIgnoreInputEvents = (editor, command) => {
11862      const inputBlocker = e => e.stopImmediatePropagation();
11863      editor.on('beforeinput input', inputBlocker, true);
11864      editor.getDoc().execCommand(command);
11865      editor.off('beforeinput input', inputBlocker);
11866    };
11867    const execEditorDeleteCommand = editor => {
11868      editor.execCommand('delete');
11869    };
11870    const execNativeDeleteCommand = editor => execCommandIgnoreInputEvents(editor, 'Delete');
11871    const execNativeForwardDeleteCommand = editor => execCommandIgnoreInputEvents(editor, 'ForwardDelete');
11872    const isBeforeRoot = rootNode => elm => is$2(parent(elm), rootNode, eq);
11873    const isTextBlockOrListItem = element => isTextBlock$2(element) || isListItem$1(element);
11874    const getParentBlock$2 = (rootNode, elm) => {
11875      if (contains(rootNode, elm)) {
11876        return closest$4(elm, isTextBlockOrListItem, isBeforeRoot(rootNode));
11877      } else {
11878        return Optional.none();
11879      }
11880    };
11881    const paddEmptyBody = (editor, moveSelection = true) => {
11882      if (editor.dom.isEmpty(editor.getBody())) {
11883        editor.setContent('', { no_selection: !moveSelection });
11884      }
11885    };
11886    const willDeleteLastPositionInElement = (forward, fromPos, elm) => lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => {
11887      const normalizedFirstPos = normalizePosition(true, firstPos);
11888      const normalizedLastPos = normalizePosition(false, lastPos);
11889      const normalizedFromPos = normalizePosition(false, fromPos);
11890      if (forward) {
11891        return nextPosition(elm, normalizedFromPos).exists(nextPos 
vendor: 1,381 bytes, lines 11891-11917
11891=> nextPos.isEqual(normalizedLastPos) && fromPos.isEqual(normalizedFirstPos));
11892      } else {
11893        return prevPosition(elm, normalizedFromPos).exists(prevPos => prevPos.isEqual(normalizedFirstPos) && fromPos.isEqual(normalizedLastPos));
11894      }
11895    }).getOr(true);
11896    const freefallRtl = root => {
11897      const child = isComment$1(root) ? prevSibling(root) : lastChild(root);
11898      return child.bind(freefallRtl).orThunk(() => Optional.some(root));
11899    };
11900    const deleteRangeContents = (editor, rng, root, moveSelection = true) => {
11901      var _a;
11902      rng.deleteContents();
11903      const lastNode = freefallRtl(root).getOr(root);
11904      const lastBlock = SugarElement.fromDom((_a = editor.dom.getParent(lastNode.dom, editor.dom.isBlock)) !== null && _a !== void 0 ? _a : root.dom);
11905      if (lastBlock.dom === editor.getBody()) {
11906        paddEmptyBody(editor, moveSelection);
11907      } else if (isEmpty$2(lastBlock)) {
11908        fillWithPaddingBr(lastBlock);
11909        if (moveSelection) {
11910          editor.selection.setCursorLocation(lastBlock.dom, 0);
11911        }
11912      }
11913      if (!eq(root, lastBlock)) {
11914        const additionalCleanupNodes = is$2(parent(lastBlock), root) ? [] : siblings(lastBlock);
11915        each$e(additionalCleanupNodes.concat(children$1(root)), node => {
11916          if (!eq(node, lastBlock) && !contains(node, lastBlock) && isEmpty$2(node)) {
11917            remove$6
vendor: 6,955 bytes, lines 11917-12062
11917(node);
11918          }
11919        });
11920      }
11921    };
11922
11923    const isRootFromElement = root => cur => eq(root, cur);
11924    const getTableCells = table => descendants(table, 'td,th');
11925    const getTableDetailsFromRange = (rng, isRoot) => {
11926      const getTable = node => getClosestTable(SugarElement.fromDom(node), isRoot);
11927      const startTable = getTable(rng.startContainer);
11928      const endTable = getTable(rng.endContainer);
11929      const isStartInTable = startTable.isSome();
11930      const isEndInTable = endTable.isSome();
11931      const isSameTable = lift2(startTable, endTable, eq).getOr(false);
11932      const isMultiTable = !isSameTable && isStartInTable && isEndInTable;
11933      return {
11934        startTable,
11935        endTable,
11936        isStartInTable,
11937        isEndInTable,
11938        isSameTable,
11939        isMultiTable
11940      };
11941    };
11942
11943    const tableCellRng = (start, end) => ({
11944      start,
11945      end
11946    });
11947    const tableSelection = (rng, table, cells) => ({
11948      rng,
11949      table,
11950      cells
11951    });
11952    const deleteAction = Adt.generate([
11953      {
11954        singleCellTable: [
11955          'rng',
11956          'cell'
11957        ]
11958      },
11959      { fullTable: ['table'] },
11960      {
11961        partialTable: [
11962          'cells',
11963          'outsideDetails'
11964        ]
11965      },
11966      {
11967        multiTable: [
11968          'startTableCells',
11969          'endTableCells',
11970          'betweenRng'
11971        ]
11972      }
11973    ]);
11974    const getClosestCell$1 = (container, isRoot) => closest$3(SugarElement.fromDom(container), 'td,th', isRoot);
11975    const isExpandedCellRng = cellRng => !eq(cellRng.start, cellRng.end);
11976    const getTableFromCellRng = (cellRng, isRoot) => getClosestTable(cellRng.start, isRoot).bind(startParentTable => getClosestTable(cellRng.end, isRoot).bind(endParentTable => someIf(eq(startParentTable, endParentTable), startParentTable)));
11977    const isSingleCellTable = (cellRng, isRoot) => !isExpandedCellRng(cellRng) && getTableFromCellRng(cellRng, isRoot).exists(table => {
11978      const rows = table.dom.rows;
11979      return rows.length === 1 && rows[0].cells.length === 1;
11980    });
11981    const getCellRng = (rng, isRoot) => {
11982      const startCell = getClosestCell$1(rng.startContainer, isRoot);
11983      const endCell = getClosestCell$1(rng.endContainer, isRoot);
11984      return lift2(startCell, endCell, tableCellRng);
11985    };
11986    const getCellRangeFromStartTable = isRoot => startCell => getClosestTable(startCell, isRoot).bind(table => last$3(getTableCells(table)).map(endCell => tableCellRng(startCell, endCell)));
11987    const getCellRangeFromEndTable = isRoot => endCell => getClosestTable(endCell, isRoot).bind(table => head(getTableCells(table)).map(startCell => tableCellRng(startCell, endCell)));
11988    const getTableSelectionFromCellRng = isRoot => cellRng => getTableFromCellRng(cellRng, isRoot).map(table => tableSelection(cellRng, table, getTableCells(table)));
11989    const getTableSelections = (cellRng, selectionDetails, rng, isRoot) => {
11990      if (rng.collapsed || !cellRng.forall(isExpandedCellRng)) {
11991        return Optional.none();
11992      } else if (selectionDetails.isSameTable) {
11993        const sameTableSelection = cellRng.bind(getTableSelectionFromCellRng(isRoot));
11994        return Optional.some({
11995          start: sameTableSelection,
11996          end: sameTableSelection
11997        });
11998      } else {
11999        const startCell = getClosestCell$1(rng.startContainer, isRoot);
12000        const endCell = getClosestCell$1(rng.endContainer, isRoot);
12001        const startTableSelection = startCell.bind(getCellRangeFromStartTable(isRoot)).bind(getTableSelectionFromCellRng(isRoot));
12002        const endTableSelection = endCell.bind(getCellRangeFromEndTable(isRoot)).bind(getTableSelectionFromCellRng(isRoot));
12003        return Optional.some({
12004          start: startTableSelection,
12005          end: endTableSelection
12006        });
12007      }
12008    };
12009    const getCellIndex = (cells, cell) => findIndex$2(cells, x => eq(x, cell));
12010    const getSelectedCells = tableSelection => lift2(getCellIndex(tableSelection.cells, tableSelection.rng.start), getCellIndex(tableSelection.cells, tableSelection.rng.end), (startIndex, endIndex) => tableSelection.cells.slice(startIndex, endIndex + 1));
12011    const isSingleCellTableContentSelected = (optCellRng, rng, isRoot) => optCellRng.exists(cellRng => isSingleCellTable(cellRng, isRoot) && hasAllContentsSelected(cellRng.start, rng));
12012    const unselectCells = (rng, selectionDetails) => {
12013      const {startTable, endTable} = selectionDetails;
12014      const otherContentRng = rng.cloneRange();
12015      startTable.each(table => otherContentRng.setStartAfter(table.dom));
12016      endTable.each(table => otherContentRng.setEndBefore(table.dom));
12017      return otherContentRng;
12018    };
12019    const handleSingleTable = (cellRng, selectionDetails, rng, isRoot) => getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(({start, end}) => start.or(end)).bind(tableSelection => {
12020      const {isSameTable} = selectionDetails;
12021      const selectedCells = getSelectedCells(tableSelection).getOr([]);
12022      if (isSameTable && tableSelection.cells.length === selectedCells.length) {
12023        return Optional.some(deleteAction.fullTable(tableSelection.table));
12024      } else if (selectedCells.length > 0) {
12025        if (isSameTable) {
12026          return Optional.some(deleteAction.partialTable(selectedCells, Optional.none()));
12027        } else {
12028          const otherContentRng = unselectCells(rng, selectionDetails);
12029          return Optional.some(deleteAction.partialTable(selectedCells, Optional.some({
12030            ...selectionDetails,
12031            rng: otherContentRng
12032          })));
12033        }
12034      } else {
12035        return Optional.none();
12036      }
12037    });
12038    const handleMultiTable = (cellRng, selectionDetails, rng, isRoot) => getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(({start, end}) => {
12039      const startTableSelectedCells = start.bind(getSelectedCells).getOr([]);
12040      const endTableSelectedCells = end.bind(getSelectedCells).getOr([]);
12041      if (startTableSelectedCells.length > 0 && endTableSelectedCells.length > 0) {
12042        const otherContentRng = unselectCells(rng, selectionDetails);
12043        return Optional.some(deleteAction.multiTable(startTableSelectedCells, endTableSelectedCells, otherContentRng));
12044      } else {
12045        return Optional.none();
12046      }
12047    });
12048    const getActionFromRange = (root, rng) => {
12049      const isRoot = isRootFromElement(root);
12050      const optCellRng = getCellRng(rng, isRoot);
12051      const selectionDetails = getTableDetailsFromRange(rng, isRoot);
12052      if (isSingleCellTableContentSelected(optCellRng, rng, isRoot)) {
12053        return optCellRng.map(cellRng => deleteAction.singleCellTable(rng, cellRng.start));
12054      } else if (selectionDetails.isMultiTable) {
12055        return handleMultiTable(optCellRng, selectionDetails, rng, isRoot);
12056      } else {
12057        return handleSingleTable(optCellRng, selectionDetails, rng, isRoot);
12058      }
12059    };
12060
12061    const cleanCells = cells => each$e(cells, cell => {
12062      remove$
12062b(cell, 'contenteditable');
12063      fillWithPaddingBr(cell);
12064    });
12065    const getOutsideBlock = (editor, container) => Optional.from(editor.dom.getParent(container, editor.dom.isBlock)).map(SugarElement.fromDom);
12066    const handleEmptyBlock = (editor, startInTable, emptyBlock) => {
12067      emptyBlock.each(block => {
12068        if (startInTable) {
12069          remove$6
vendor: 19,607 bytes, lines 12069-12509
12069(block);
12070        } else {
12071          fillWithPaddingBr(block);
12072          editor.selection.setCursorLocation(block.dom, 0);
12073        }
12074      });
12075    };
12076    const deleteContentInsideCell = (editor, cell, rng, isFirstCellInSelection) => {
12077      const insideTableRng = rng.cloneRange();
12078      if (isFirstCellInSelection) {
12079        insideTableRng.setStart(rng.startContainer, rng.startOffset);
12080        insideTableRng.setEndAfter(cell.dom.lastChild);
12081      } else {
12082        insideTableRng.setStartBefore(cell.dom.firstChild);
12083        insideTableRng.setEnd(rng.endContainer, rng.endOffset);
12084      }
12085      deleteCellContents(editor, insideTableRng, cell, false).each(action => action());
12086    };
12087    const collapseAndRestoreCellSelection = editor => {
12088      const selectedCells = getCellsFromEditor(editor);
12089      const selectedNode = SugarElement.fromDom(editor.selection.getNode());
12090      if (isTableCell$3(selectedNode.dom) && isEmpty$2(selectedNode)) {
12091        editor.selection.setCursorLocation(selectedNode.dom, 0);
12092      } else {
12093        editor.selection.collapse(true);
12094      }
12095      if (selectedCells.length > 1 && exists(selectedCells, cell => eq(cell, selectedNode))) {
12096        set$3(selectedNode, 'data-mce-selected', '1');
12097      }
12098    };
12099    const emptySingleTableCells = (editor, cells, outsideDetails) => Optional.some(() => {
12100      const editorRng = editor.selection.getRng();
12101      const cellsToClean = outsideDetails.bind(({rng, isStartInTable}) => {
12102        const outsideBlock = getOutsideBlock(editor, isStartInTable ? rng.endContainer : rng.startContainer);
12103        rng.deleteContents();
12104        handleEmptyBlock(editor, isStartInTable, outsideBlock.filter(isEmpty$2));
12105        const endPointCell = isStartInTable ? cells[0] : cells[cells.length - 1];
12106        deleteContentInsideCell(editor, endPointCell, editorRng, isStartInTable);
12107        if (!isEmpty$2(endPointCell)) {
12108          return Optional.some(isStartInTable ? cells.slice(1) : cells.slice(0, -1));
12109        } else {
12110          return Optional.none();
12111        }
12112      }).getOr(cells);
12113      cleanCells(cellsToClean);
12114      collapseAndRestoreCellSelection(editor);
12115    });
12116    const emptyMultiTableCells = (editor, startTableCells, endTableCells, betweenRng) => Optional.some(() => {
12117      const rng = editor.selection.getRng();
12118      const startCell = startTableCells[0];
12119      const endCell = endTableCells[endTableCells.length - 1];
12120      deleteContentInsideCell(editor, startCell, rng, true);
12121      deleteContentInsideCell(editor, endCell, rng, false);
12122      const startTableCellsToClean = isEmpty$2(startCell) ? startTableCells : startTableCells.slice(1);
12123      const endTableCellsToClean = isEmpty$2(endCell) ? endTableCells : endTableCells.slice(0, -1);
12124      cleanCells(startTableCellsToClean.concat(endTableCellsToClean));
12125      betweenRng.deleteContents();
12126      collapseAndRestoreCellSelection(editor);
12127    });
12128    const deleteCellContents = (editor, rng, cell, moveSelection = true) => Optional.some(() => {
12129      deleteRangeContents(editor, rng, cell, moveSelection);
12130    });
12131    const deleteTableElement = (editor, table) => Optional.some(() => deleteElement$2(editor, false, table));
12132    const deleteCellRange = (editor, rootElm, rng) => getActionFromRange(rootElm, rng).bind(action => action.fold(curry(deleteCellContents, editor), curry(deleteTableElement, editor), curry(emptySingleTableCells, editor), curry(emptyMultiTableCells, editor)));
12133    const deleteCaptionRange = (editor, caption) => emptyElement(editor, caption);
12134    const deleteTableRange = (editor, rootElm, rng, startElm) => getParentCaption(rootElm, startElm).fold(() => deleteCellRange(editor, rootElm, rng), caption => deleteCaptionRange(editor, caption));
12135    const deleteRange$3 = (editor, startElm, selectedCells) => {
12136      const rootNode = SugarElement.fromDom(editor.getBody());
12137      const rng = editor.selection.getRng();
12138      return selectedCells.length !== 0 ? emptySingleTableCells(editor, selectedCells, Optional.none()) : deleteTableRange(editor, rootNode, rng, startElm);
12139    };
12140    const getParentCell = (rootElm, elm) => find$2(parentsAndSelf(elm, rootElm), isTableCell$2);
12141    const getParentCaption = (rootElm, elm) => find$2(parentsAndSelf(elm, rootElm), isTag('caption'));
12142    const deleteBetweenCells = (editor, rootElm, forward, fromCell, from) => navigate(forward, editor.getBody(), from).bind(to => getParentCell(rootElm, SugarElement.fromDom(to.getNode())).bind(toCell => eq(toCell, fromCell) ? Optional.none() : Optional.some(noop)));
12143    const emptyElement = (editor, elm) => Optional.some(() => {
12144      fillWithPaddingBr(elm);
12145      editor.selection.setCursorLocation(elm.dom, 0);
12146    });
12147    const isDeleteOfLastCharPos = (fromCaption, forward, from, to) => firstPositionIn(fromCaption.dom).bind(first => lastPositionIn(fromCaption.dom).map(last => forward ? from.isEqual(first) && to.isEqual(last) : from.isEqual(last) && to.isEqual(first))).getOr(true);
12148    const emptyCaretCaption = (editor, elm) => emptyElement(editor, elm);
12149    const validateCaretCaption = (rootElm, fromCaption, to) => getParentCaption(rootElm, SugarElement.fromDom(to.getNode())).fold(() => Optional.some(noop), toCaption => someIf(!eq(toCaption, fromCaption), noop));
12150    const deleteCaretInsideCaption = (editor, rootElm, forward, fromCaption, from) => navigate(forward, editor.getBody(), from).fold(() => Optional.some(noop), to => isDeleteOfLastCharPos(fromCaption, forward, from, to) ? emptyCaretCaption(editor, fromCaption) : validateCaretCaption(rootElm, fromCaption, to));
12151    const deleteCaretCells = (editor, forward, rootElm, startElm) => {
12152      const from = CaretPosition.fromRangeStart(editor.selection.getRng());
12153      return getParentCell(rootElm, startElm).bind(fromCell => isEmpty$2(fromCell) ? emptyElement(editor, fromCell) : deleteBetweenCells(editor, rootElm, forward, fromCell, from));
12154    };
12155    const deleteCaretCaption = (editor, forward, rootElm, fromCaption) => {
12156      const from = CaretPosition.fromRangeStart(editor.selection.getRng());
12157      return isEmpty$2(fromCaption) ? emptyElement(editor, fromCaption) : deleteCaretInsideCaption(editor, rootElm, forward, fromCaption, from);
12158    };
12159    const isNearTable = (forward, pos) => forward ? isBeforeTable(pos) : isAfterTable(pos);
12160    const isBeforeOrAfterTable = (editor, forward) => {
12161      const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
12162      return isNearTable(forward, fromPos) || fromPosition(forward, editor.getBody(), fromPos).exists(pos => isNearTable(forward, pos));
12163    };
12164    const deleteCaret$3 = (editor, forward, startElm) => {
12165      const rootElm = SugarElement.fromDom(editor.getBody());
12166      return getParentCaption(rootElm, startElm).fold(() => deleteCaretCells(editor, forward, rootElm, startElm).orThunk(() => someIf(isBeforeOrAfterTable(editor, forward), noop)), fromCaption => deleteCaretCaption(editor, forward, rootElm, fromCaption));
12167    };
12168    const backspaceDelete$9 = (editor, forward) => {
12169      const startElm = SugarElement.fromDom(editor.selection.getStart(true));
12170      const cells = getCellsFromEditor(editor);
12171      return editor.selection.isCollapsed() && cells.length === 0 ? deleteCaret$3(editor, forward, startElm) : deleteRange$3(editor, startElm, cells);
12172    };
12173
12174    const getContentEditableRoot$1 = (root, node) => {
12175      let tempNode = node;
12176      while (tempNode && tempNode !== root) {
12177        if (isContentEditableTrue$3(tempNode) || isContentEditableFalse$b(tempNode)) {
12178          return tempNode;
12179        }
12180        tempNode = tempNode.parentNode;
12181      }
12182      return null;
12183    };
12184
12185    const internalAttributesPrefixes = [
12186      'data-ephox-',
12187      'data-mce-',
12188      'data-alloy-',
12189      'data-snooker-',
12190      '_'
12191    ];
12192    const each$9 = Tools.each;
12193    const ElementUtils = editor => {
12194      const dom = editor.dom;
12195      const internalAttributes = new Set(editor.serializer.getTempAttrs());
12196      const compare = (node1, node2) => {
12197        if (node1.nodeName !== node2.nodeName || node1.nodeType !== node2.nodeType) {
12198          return false;
12199        }
12200        const getAttribs = node => {
12201          const attribs = {};
12202          each$9(dom.getAttribs(node), attr => {
12203            const name = attr.nodeName.toLowerCase();
12204            if (name !== 'style' && !isAttributeInternal(name)) {
12205              attribs[name] = dom.getAttrib(node, name);
12206            }
12207          });
12208          return attribs;
12209        };
12210        const compareObjects = (obj1, obj2) => {
12211          for (const name in obj1) {
12212            if (has$2(obj1, name)) {
12213              const value = obj2[name];
12214              if (isUndefined(value)) {
12215                return false;
12216              }
12217              if (obj1[name] !== value) {
12218                return false;
12219              }
12220              delete obj2[name];
12221            }
12222          }
12223          for (const name in obj2) {
12224            if (has$2(obj2, name)) {
12225              return false;
12226            }
12227          }
12228          return true;
12229        };
12230        if (isElement$6(node1) && isElement$6(node2)) {
12231          if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
12232            return false;
12233          }
12234          if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) {
12235            return false;
12236          }
12237        }
12238        return !isBookmarkNode$1(node1) && !isBookmarkNode$1(node2);
12239      };
12240      const isAttributeInternal = attributeName => exists(internalAttributesPrefixes, value => startsWith(attributeName, value)) || internalAttributes.has(attributeName);
12241      return {
12242        compare,
12243        isAttributeInternal
12244      };
12245    };
12246
12247    const traverse = (root, fn) => {
12248      let node = root;
12249      while (node = node.walk()) {
12250        fn(node);
12251      }
12252    };
12253    const matchNode$1 = (nodeFilters, attributeFilters, node, matches) => {
12254      const name = node.name;
12255      for (let ni = 0, nl = nodeFilters.length; ni < nl; ni++) {
12256        const filter = nodeFilters[ni];
12257        if (filter.name === name) {
12258          const match = matches.nodes[name];
12259          if (match) {
12260            match.nodes.push(node);
12261          } else {
12262            matches.nodes[name] = {
12263              filter,
12264              nodes: [node]
12265            };
12266          }
12267        }
12268      }
12269      if (node.attributes) {
12270        for (let ai = 0, al = attributeFilters.length; ai < al; ai++) {
12271          const filter = attributeFilters[ai];
12272          const attrName = filter.name;
12273          if (attrName in node.attributes.map) {
12274            const match = matches.attributes[attrName];
12275            if (match) {
12276              match.nodes.push(node);
12277            } else {
12278              matches.attributes[attrName] = {
12279                filter,
12280                nodes: [node]
12281              };
12282            }
12283          }
12284        }
12285      }
12286    };
12287    const findMatchingNodes = (nodeFilters, attributeFilters, node) => {
12288      const matches = {
12289        nodes: {},
12290        attributes: {}
12291      };
12292      if (node.firstChild) {
12293        traverse(node, childNode => {
12294          matchNode$1(nodeFilters, attributeFilters, childNode, matches);
12295        });
12296      }
12297      return matches;
12298    };
12299    const runFilters = (matches, args) => {
12300      const run = (matchRecord, filteringAttributes) => {
12301        each$d(matchRecord, match => {
12302          const nodes = from(match.nodes);
12303          each$e(match.filter.callbacks, callback => {
12304            for (let i = nodes.length - 1; i >= 0; i--) {
12305              const node = nodes[i];
12306              const valueMatches = filteringAttributes ? node.attr(match.filter.name) !== undefined : node.name === match.filter.name;
12307              if (!valueMatches || isNullable(node.parent)) {
12308                nodes.splice(i, 1);
12309              }
12310            }
12311            if (nodes.length > 0) {
12312              callback(nodes, match.filter.name, args);
12313            }
12314          });
12315        });
12316      };
12317      run(matches.nodes, false);
12318      run(matches.attributes, true);
12319    };
12320    const filter$2 = (nodeFilters, attributeFilters, node, args = {}) => {
12321      const matches = findMatchingNodes(nodeFilters, attributeFilters, node);
12322      runFilters(matches, args);
12323    };
12324
12325    const paddEmptyNode = (args, isBlock, node) => {
12326      if (args.insert && isBlock(node)) {
12327        const astNode = new AstNode('br', 1);
12328        astNode.attr('data-mce-bogus', '1');
12329        node.empty().append(astNode);
12330      } else {
12331        node.empty().append(new AstNode('#text', 3)).value = nbsp;
12332      }
12333    };
12334    const isPaddedWithNbsp = node => {
12335      var _a;
12336      return hasOnlyChild(node, '#text') && ((_a = node === null || node === void 0 ? void 0 : node.firstChild) === null || _a === void 0 ? void 0 : _a.value) === nbsp;
12337    };
12338    const hasOnlyChild = (node, name) => {
12339      const firstChild = node === null || node === void 0 ? void 0 : node.firstChild;
12340      return isNonNullable(firstChild) && firstChild === node.lastChild && firstChild.name === name;
12341    };
12342    const isPadded = (schema, node) => {
12343      const rule = schema.getElementRule(node.name);
12344      return (rule === null || rule === void 0 ? void 0 : rule.paddEmpty) === true;
12345    };
12346    const isEmpty = (schema, nonEmptyElements, whitespaceElements, node) => node.isEmpty(nonEmptyElements, whitespaceElements, node => isPadded(schema, node));
12347    const isLineBreakNode = (node, isBlock) => isNonNullable(node) && (isBlock(node) || node.name === 'br');
12348    const findClosestEditingHost = scope => {
12349      let editableNode;
12350      for (let node = scope; node; node = node.parent) {
12351        const contentEditable = node.attr('contenteditable');
12352        if (contentEditable === 'false') {
12353          break;
12354        } else if (contentEditable === 'true') {
12355          editableNode = node;
12356        }
12357      }
12358      return Optional.from(editableNode);
12359    };
12360
12361    const removeOrUnwrapInvalidNode = (node, schema, originalNodeParent = node.parent) => {
12362      if (schema.getSpecialElements()[node.name]) {
12363        node.empty().remove();
12364      } else {
12365        const children = node.children();
12366        for (const childNode of children) {
12367          if (originalNodeParent && !schema.isValidChild(originalNodeParent.name, childNode.name)) {
12368            removeOrUnwrapInvalidNode(childNode, schema, originalNodeParent);
12369          }
12370        }
12371        node.unwrap();
12372      }
12373    };
12374    const cleanInvalidNodes = (nodes, schema, rootNode, onCreate = noop) => {
12375      const textBlockElements = schema.getTextBlockElements();
12376      const nonEmptyElements = schema.getNonEmptyElements();
12377      const whitespaceElements = schema.getWhitespaceElements();
12378      const nonSplittableElements = Tools.makeMap('tr,td,th,tbody,thead,tfoot,table');
12379      const fixed = new Set();
12380      const isSplittableElement = node => node !== rootNode && !nonSplittableElements[node.name];
12381      for (let ni = 0; ni < nodes.length; ni++) {
12382        const node = nodes[ni];
12383        let parent;
12384        let newParent;
12385        let tempNode;
12386        if (!node.parent || fixed.has(node)) {
12387          continue;
12388        }
12389        if (textBlockElements[node.name] && node.parent.name === 'li') {
12390          let sibling = node.next;
12391          while (sibling) {
12392            if (textBlockElements[sibling.name]) {
12393              sibling.name = 'li';
12394              fixed.add(sibling);
12395              node.parent.insert(sibling, node.parent);
12396            } else {
12397              break;
12398            }
12399            sibling = sibling.next;
12400          }
12401          node.unwrap();
12402          continue;
12403        }
12404        const parents = [node];
12405        for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && isSplittableElement(parent); parent = parent.parent) {
12406          parents.push(parent);
12407        }
12408        if (parent && parents.length > 1) {
12409          if (schema.isValidChild(parent.name, node.name)) {
12410            parents.reverse();
12411            newParent = parents[0].clone();
12412            onCreate(newParent);
12413            let currentNode = newParent;
12414            for (let i = 0; i < parents.length - 1; i++) {
12415              if (schema.isValidChild(currentNode.name, parents[i].name) && i > 0) {
12416                tempNode = parents[i].clone();
12417                onCreate(tempNode);
12418                currentNode.append(tempNode);
12419              } else {
12420                tempNode = currentNode;
12421              }
12422              for (let childNode = parents[i].firstChild; childNode && childNode !== parents[i + 1];) {
12423                const nextNode = childNode.next;
12424                tempNode.append(childNode);
12425                childNode = nextNode;
12426              }
12427              currentNode = tempNode;
12428            }
12429            if (!isEmpty(schema, nonEmptyElements, whitespaceElements, newParent)) {
12430              parent.insert(newParent, parents[0], true);
12431              parent.insert(node, newParent);
12432            } else {
12433              parent.insert(node, parents[0], true);
12434            }
12435            parent = parents[0];
12436            if (isEmpty(schema, nonEmptyElements, whitespaceElements, parent) || hasOnlyChild(parent, 'br')) {
12437              parent.empty().remove();
12438            }
12439          } else {
12440            removeOrUnwrapInvalidNode(node, schema);
12441          }
12442        } else if (node.parent) {
12443          if (node.name === 'li') {
12444            let sibling = node.prev;
12445            if (sibling && (sibling.name === 'ul' || sibling.name === 'ol')) {
12446              sibling.append(node);
12447              continue;
12448            }
12449            sibling = node.next;
12450            if (sibling && (sibling.name === 'ul' || sibling.name === 'ol') && sibling.firstChild) {
12451              sibling.insert(node, sibling.firstChild, true);
12452              continue;
12453            }
12454            const wrapper = new AstNode('ul', 1);
12455            onCreate(wrapper);
12456            node.wrap(wrapper);
12457            continue;
12458          }
12459          if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) {
12460            const wrapper = new AstNode('div', 1);
12461            onCreate(wrapper);
12462            node.wrap(wrapper);
12463          } else {
12464            removeOrUnwrapInvalidNode(node, schema);
12465          }
12466        }
12467      }
12468    };
12469    const hasClosest = (node, parentName) => {
12470      let tempNode = node;
12471      while (tempNode) {
12472        if (tempNode.name === parentName) {
12473          return true;
12474        }
12475        tempNode = tempNode.parent;
12476      }
12477      return false;
12478    };
12479    const isInvalid = (schema, node, parent = node.parent) => {
12480      if (parent && schema.children[node.name] && !schema.isValidChild(parent.name, node.name)) {
12481        return true;
12482      } else if (parent && node.name === 'a' && hasClosest(parent, 'a')) {
12483        return true;
12484      } else {
12485        return false;
12486      }
12487    };
12488
12489    const createRange = (sc, so, ec, eo) => {
12490      const rng = document.createRange();
12491      rng.setStart(sc, so);
12492      rng.setEnd(ec, eo);
12493      return rng;
12494    };
12495    const normalizeBlockSelectionRange = rng => {
12496      const startPos = CaretPosition.fromRangeStart(rng);
12497      const endPos = CaretPosition.fromRangeEnd(rng);
12498      const rootNode = rng.commonAncestorContainer;
12499      return fromPosition(false, rootNode, endPos).map(newEndPos => {
12500        if (!isInSameBlock(startPos, endPos, rootNode) && isInSameBlock(startPos, newEndPos, rootNode)) {
12501          return createRange(startPos.container(), startPos.offset(), newEndPos.container(), newEndPos.offset());
12502        } else {
12503          return rng;
12504        }
12505      }).getOr(rng);
12506    };
12507    const normalize = rng => rng.collapsed ? rng : normalizeBlockSelectionRange(rng);
12508
12509    const hasOnlyOneChild
12509 = node => {
12510      return isNonNullable(node.firstChild) && node.firstChild === node.lastChild;
12511    };
12512    const isPaddingNode = node => {
12513      return node.name === 'br' || node.value === nbsp;
12514    };
12515    const isPaddedEmptyBlock = (schema, node) => {
12516      const blockElements = schema.getBlockElements();
12517      return blockElements[node.name] && hasOnlyOneChild
vendor: 12,206 bytes, lines 12517-12809
12517(node) && isPaddingNode(node.firstChild);
12518    };
12519    const isEmptyFragmentElement = (schema, node) => {
12520      const nonEmptyElements = schema.getNonEmptyElements();
12521      return isNonNullable(node) && (node.isEmpty(nonEmptyElements) || isPaddedEmptyBlock(schema, node));
12522    };
12523    const isListFragment = (schema, fragment) => {
12524      let firstChild = fragment.firstChild;
12525      let lastChild = fragment.lastChild;
12526      if (firstChild && firstChild.name === 'meta') {
12527        firstChild = firstChild.next;
12528      }
12529      if (lastChild && lastChild.attr('id') === 'mce_marker') {
12530        lastChild = lastChild.prev;
12531      }
12532      if (isEmptyFragmentElement(schema, lastChild)) {
12533        lastChild = lastChild === null || lastChild === void 0 ? void 0 : lastChild.prev;
12534      }
12535      if (!firstChild || firstChild !== lastChild) {
12536        return false;
12537      }
12538      return firstChild.name === 'ul' || firstChild.name === 'ol';
12539    };
12540    const cleanupDomFragment = domFragment => {
12541      var _a, _b;
12542      const firstChild = domFragment.firstChild;
12543      const lastChild = domFragment.lastChild;
12544      if (firstChild && firstChild.nodeName === 'META') {
12545        (_a = firstChild.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(firstChild);
12546      }
12547      if (lastChild && lastChild.id === 'mce_marker') {
12548        (_b = lastChild.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(lastChild);
12549      }
12550      return domFragment;
12551    };
12552    const toDomFragment = (dom, serializer, fragment) => {
12553      const html = serializer.serialize(fragment);
12554      const domFragment = dom.createFragment(html);
12555      return cleanupDomFragment(domFragment);
12556    };
12557    const listItems = elm => {
12558      var _a;
12559      return filter$5((_a = elm === null || elm === void 0 ? void 0 : elm.childNodes) !== null && _a !== void 0 ? _a : [], child => {
12560        return child.nodeName === 'LI';
12561      });
12562    };
12563    const isPadding = node => {
12564      return node.data === nbsp || isBr$6(node);
12565    };
12566    const isListItemPadded = node => {
12567      return isNonNullable(node === null || node === void 0 ? void 0 : node.firstChild) && node.firstChild === node.lastChild && isPadding(node.firstChild);
12568    };
12569    const isEmptyOrPadded = elm => {
12570      return !elm.firstChild || isListItemPadded(elm);
12571    };
12572    const trimListItems = elms => {
12573      return elms.length > 0 && isEmptyOrPadded(elms[elms.length - 1]) ? elms.slice(0, -1) : elms;
12574    };
12575    const getParentLi = (dom, node) => {
12576      const parentBlock = dom.getParent(node, dom.isBlock);
12577      return parentBlock && parentBlock.nodeName === 'LI' ? parentBlock : null;
12578    };
12579    const isParentBlockLi = (dom, node) => {
12580      return !!getParentLi(dom, node);
12581    };
12582    const getSplit = (parentNode, rng) => {
12583      const beforeRng = rng.cloneRange();
12584      const afterRng = rng.cloneRange();
12585      beforeRng.setStartBefore(parentNode);
12586      afterRng.setEndAfter(parentNode);
12587      return [
12588        beforeRng.cloneContents(),
12589        afterRng.cloneContents()
12590      ];
12591    };
12592    const findFirstIn = (node, rootNode) => {
12593      const caretPos = CaretPosition.before(node);
12594      const caretWalker = CaretWalker(rootNode);
12595      const newCaretPos = caretWalker.next(caretPos);
12596      return newCaretPos ? newCaretPos.toRange() : null;
12597    };
12598    const findLastOf = (node, rootNode) => {
12599      const caretPos = CaretPosition.after(node);
12600      const caretWalker = CaretWalker(rootNode);
12601      const newCaretPos = caretWalker.prev(caretPos);
12602      return newCaretPos ? newCaretPos.toRange() : null;
12603    };
12604    const insertMiddle = (target, elms, rootNode, rng) => {
12605      const parts = getSplit(target, rng);
12606      const parentElm = target.parentNode;
12607      if (parentElm) {
12608        parentElm.insertBefore(parts[0], target);
12609        Tools.each(elms, li => {
12610          parentElm.insertBefore(li, target);
12611        });
12612        parentElm.insertBefore(parts[1], target);
12613        parentElm.removeChild(target);
12614      }
12615      return findLastOf(elms[elms.length - 1], rootNode);
12616    };
12617    const insertBefore$1 = (target, elms, rootNode) => {
12618      const parentElm = target.parentNode;
12619      if (parentElm) {
12620        Tools.each(elms, elm => {
12621          parentElm.insertBefore(elm, target);
12622        });
12623      }
12624      return findFirstIn(target, rootNode);
12625    };
12626    const insertAfter$1 = (target, elms, rootNode, dom) => {
12627      dom.insertAfter(elms.reverse(), target);
12628      return findLastOf(elms[0], rootNode);
12629    };
12630    const insertAtCaret$1 = (serializer, dom, rng, fragment) => {
12631      const domFragment = toDomFragment(dom, serializer, fragment);
12632      const liTarget = getParentLi(dom, rng.startContainer);
12633      const liElms = trimListItems(listItems(domFragment.firstChild));
12634      const BEGINNING = 1, END = 2;
12635      const rootNode = dom.getRoot();
12636      const isAt = location => {
12637        const caretPos = CaretPosition.fromRangeStart(rng);
12638        const caretWalker = CaretWalker(dom.getRoot());
12639        const newPos = location === BEGINNING ? caretWalker.prev(caretPos) : caretWalker.next(caretPos);
12640        const newPosNode = newPos === null || newPos === void 0 ? void 0 : newPos.getNode();
12641        return newPosNode ? getParentLi(dom, newPosNode) !== liTarget : true;
12642      };
12643      if (!liTarget) {
12644        return null;
12645      } else if (isAt(BEGINNING)) {
12646        return insertBefore$1(liTarget, liElms, rootNode);
12647      } else if (isAt(END)) {
12648        return insertAfter$1(liTarget, liElms, rootNode, dom);
12649      } else {
12650        return insertMiddle(liTarget, liElms, rootNode, rng);
12651      }
12652    };
12653
12654    const mergeableWrappedElements = ['pre'];
12655    const shouldPasteContentOnly = (dom, fragment, parentNode, root) => {
12656      var _a;
12657      const firstNode = fragment.firstChild;
12658      const lastNode = fragment.lastChild;
12659      const last = lastNode.attr('data-mce-type') === 'bookmark' ? lastNode.prev : lastNode;
12660      const isPastingSingleElement = firstNode === last;
12661      const isWrappedElement = contains$2(mergeableWrappedElements, firstNode.name);
12662      if (isPastingSingleElement && isWrappedElement) {
12663        const isContentEditable = firstNode.attr('contenteditable') !== 'false';
12664        const isPastingInTheSameBlockTag = ((_a = dom.getParent(parentNode, dom.isBlock)) === null || _a === void 0 ? void 0 : _a.nodeName.toLowerCase()) === firstNode.name;
12665        const isPastingInContentEditable = Optional.from(getContentEditableRoot$1(root, parentNode)).forall(isContentEditableTrue$3);
12666        return isContentEditable && isPastingInTheSameBlockTag && isPastingInContentEditable;
12667      } else {
12668        return false;
12669      }
12670    };
12671    const isTableCell = isTableCell$3;
12672    const isTableCellContentSelected = (dom, rng, cell) => {
12673      if (isNonNullable(cell)) {
12674        const endCell = dom.getParent(rng.endContainer, isTableCell);
12675        return cell === endCell && hasAllContentsSelected(SugarElement.fromDom(cell), rng);
12676      } else {
12677        return false;
12678      }
12679    };
12680    const validInsertion = (editor, value, parentNode) => {
12681      var _a;
12682      if (parentNode.getAttribute('data-mce-bogus') === 'all') {
12683        (_a = parentNode.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(editor.dom.createFragment(value), parentNode);
12684      } else {
12685        const node = parentNode.firstChild;
12686        const node2 = parentNode.lastChild;
12687        if (!node || node === node2 && node.nodeName === 'BR') {
12688          editor.dom.setHTML(parentNode, value);
12689        } else {
12690          editor.selection.setContent(value, { no_events: true });
12691        }
12692      }
12693    };
12694    const trimBrsFromTableCell = (dom, elm) => {
12695      Optional.from(dom.getParent(elm, 'td,th')).map(SugarElement.fromDom).each(trimBlockTrailingBr);
12696    };
12697    const reduceInlineTextElements = (editor, merge) => {
12698      const textInlineElements = editor.schema.getTextInlineElements();
12699      const dom = editor.dom;
12700      if (merge) {
12701        const root = editor.getBody();
12702        const elementUtils = ElementUtils(editor);
12703        Tools.each(dom.select('*[data-mce-fragment]'), node => {
12704          const isInline = isNonNullable(textInlineElements[node.nodeName.toLowerCase()]);
12705          if (isInline && hasInheritableStyles(dom, node)) {
12706            for (let parentNode = node.parentElement; isNonNullable(parentNode) && parentNode !== root; parentNode = parentNode.parentElement) {
12707              const styleConflict = hasStyleConflict(dom, node, parentNode);
12708              if (styleConflict) {
12709                break;
12710              }
12711              if (elementUtils.compare(parentNode, node)) {
12712                dom.remove(node, true);
12713                break;
12714              }
12715            }
12716          }
12717        });
12718      }
12719    };
12720    const markFragmentElements = fragment => {
12721      let node = fragment;
12722      while (node = node.walk()) {
12723        if (node.type === 1) {
12724          node.attr('data-mce-fragment', '1');
12725        }
12726      }
12727    };
12728    const unmarkFragmentElements = elm => {
12729      Tools.each(elm.getElementsByTagName('*'), elm => {
12730        elm.removeAttribute('data-mce-fragment');
12731      });
12732    };
12733    const isPartOfFragment = node => {
12734      return !!node.getAttribute('data-mce-fragment');
12735    };
12736    const canHaveChildren = (editor, node) => {
12737      return isNonNullable(node) && !editor.schema.getVoidElements()[node.nodeName];
12738    };
12739    const moveSelectionToMarker = (editor, marker) => {
12740      var _a, _b, _c;
12741      let nextRng;
12742      const dom = editor.dom;
12743      const selection = editor.selection;
12744      if (!marker) {
12745        return;
12746      }
12747      selection.scrollIntoView(marker);
12748      const parentEditableElm = getContentEditableRoot$1(editor.getBody(), marker);
12749      if (parentEditableElm && dom.getContentEditable(parentEditableElm) === 'false') {
12750        dom.remove(marker);
12751        selection.select(parentEditableElm);
12752        return;
12753      }
12754      let rng = dom.createRng();
12755      const node = marker.previousSibling;
12756      if (isText$a(node)) {
12757        rng.setStart(node, (_b = (_a = node.nodeValue) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0);
12758        const node2 = marker.nextSibling;
12759        if (isText$a(node2)) {
12760          node.appendData(node2.data);
12761          (_c = node2.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(node2);
12762        }
12763      } else {
12764        rng.setStartBefore(marker);
12765        rng.setEndBefore(marker);
12766      }
12767      const findNextCaretRng = rng => {
12768        let caretPos = CaretPosition.fromRangeStart(rng);
12769        const caretWalker = CaretWalker(editor.getBody());
12770        caretPos = caretWalker.next(caretPos);
12771        return caretPos === null || caretPos === void 0 ? void 0 : caretPos.toRange();
12772      };
12773      const parentBlock = dom.getParent(marker, dom.isBlock);
12774      dom.remove(marker);
12775      if (parentBlock && dom.isEmpty(parentBlock)) {
12776        empty(SugarElement.fromDom(parentBlock));
12777        rng.setStart(parentBlock, 0);
12778        rng.setEnd(parentBlock, 0);
12779        if (!isTableCell(parentBlock) && !isPartOfFragment(parentBlock) && (nextRng = findNextCaretRng(rng))) {
12780          rng = nextRng;
12781          dom.remove(parentBlock);
12782        } else {
12783          dom.add(parentBlock, dom.create('br', { 'data-mce-bogus': '1' }));
12784        }
12785      }
12786      selection.setRng(rng);
12787    };
12788    const deleteSelectedContent = editor => {
12789      const dom = editor.dom;
12790      const rng = normalize(editor.selection.getRng());
12791      editor.selection.setRng(rng);
12792      const startCell = dom.getParent(rng.startContainer, isTableCell);
12793      if (isTableCellContentSelected(dom, rng, startCell)) {
12794        deleteCellContents(editor, rng, SugarElement.fromDom(startCell));
12795      } else if (rng.startContainer === rng.endContainer && rng.endOffset - rng.startOffset === 1 && isText$a(rng.startContainer.childNodes[rng.startOffset])) {
12796        rng.deleteContents();
12797      } else {
12798        editor.getDoc().execCommand('Delete', false);
12799      }
12800    };
12801    const findMarkerNode = scope => {
12802      for (let markerNode = scope; markerNode; markerNode = markerNode.walk()) {
12803        if (markerNode.attr('id') === 'mce_marker') {
12804          return Optional.some(markerNode);
12805        }
12806      }
12807      return Optional.none();
12808    };
12809    const 
12809insertHtmlAtCaret = (editor, value, details) => {
12810      var _a, _b;
12811      const selection = editor.selection;
12812      const dom = editor.dom;
12813      const parser = editor.parser;
12814      const merge = details.merge;
12815      const serializer = HtmlSerializer({ validate: true }, editor.schema);
12816      const bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">
vendor: 7,676 bytes, lines 12816-13006
12816&#xFEFF;</span>';
12817      if (value.indexOf('{$caret}') === -1) {
12818        value += '{$caret}';
12819      }
12820      value = value.replace(/\{\$caret\}/, bookmarkHtml);
12821      let rng = selection.getRng();
12822      const caretElement = rng.startContainer;
12823      const body = editor.getBody();
12824      if (caretElement === body && selection.isCollapsed()) {
12825        if (dom.isBlock(body.firstChild) && canHaveChildren(editor, body.firstChild) && dom.isEmpty(body.firstChild)) {
12826          rng = dom.createRng();
12827          rng.setStart(body.firstChild, 0);
12828          rng.setEnd(body.firstChild, 0);
12829          selection.setRng(rng);
12830        }
12831      }
12832      if (!selection.isCollapsed()) {
12833        deleteSelectedContent(editor);
12834      }
12835      const parentNode = selection.getNode();
12836      const parserArgs = {
12837        context: parentNode.nodeName.toLowerCase(),
12838        data: details.data,
12839        insert: true
12840      };
12841      const fragment = parser.parse(value, parserArgs);
12842      if (details.paste === true && isListFragment(editor.schema, fragment) && isParentBlockLi(dom, parentNode)) {
12843        rng = insertAtCaret$1(serializer, dom, selection.getRng(), fragment);
12844        if (rng) {
12845          selection.setRng(rng);
12846        }
12847        return value;
12848      }
12849      if (details.paste === true && shouldPasteContentOnly(dom, fragment, parentNode, editor.getBody())) {
12850        (_a = fragment.firstChild) === null || _a === void 0 ? void 0 : _a.unwrap();
12851      }
12852      markFragmentElements(fragment);
12853      let node = fragment.lastChild;
12854      if (node && node.attr('id') === 'mce_marker') {
12855        const marker = node;
12856        for (node = node.prev; node; node = node.walk(true)) {
12857          if (node.type === 3 || !dom.isBlock(node.name)) {
12858            if (node.parent && editor.schema.isValidChild(node.parent.name, 'span')) {
12859              node.parent.insert(marker, node, node.name === 'br');
12860            }
12861            break;
12862          }
12863        }
12864      }
12865      editor._selectionOverrides.showBlockCaretContainer(parentNode);
12866      if (!parserArgs.invalid) {
12867        value = serializer.serialize(fragment);
12868        validInsertion(editor, value, parentNode);
12869      } else {
12870        editor.selection.setContent(bookmarkHtml);
12871        let parentNode = selection.getNode();
12872        let tempNode;
12873        const rootNode = editor.getBody();
12874        if (isDocument$1(parentNode)) {
12875          parentNode = tempNode = rootNode;
12876        } else {
12877          tempNode = parentNode;
12878        }
12879        while (tempNode && tempNode !== rootNode) {
12880          parentNode = tempNode;
12881          tempNode = tempNode.parentNode;
12882        }
12883        value = parentNode === rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode);
12884        const root = parser.parse(value);
12885        const markerNode = findMarkerNode(root);
12886        const editingHost = markerNode.bind(findClosestEditingHost).getOr(root);
12887        markerNode.each(marker => marker.replace(fragment));
12888        const toExtract = fragment.children();
12889        const parent = (_b = fragment.parent) !== null && _b !== void 0 ? _b : root;
12890        fragment.unwrap();
12891        const invalidChildren = filter$5(toExtract, node => isInvalid(editor.schema, node, parent));
12892        cleanInvalidNodes(invalidChildren, editor.schema, editingHost);
12893        filter$2(parser.getNodeFilters(), parser.getAttributeFilters(), root);
12894        value = serializer.serialize(root);
12895        if (parentNode === rootNode) {
12896          dom.setHTML(rootNode, value);
12897        } else {
12898          dom.setOuterHTML(parentNode, value);
12899        }
12900      }
12901      reduceInlineTextElements(editor, merge);
12902      moveSelectionToMarker(editor, dom.get('mce_marker'));
12903      unmarkFragmentElements(editor.getBody());
12904      trimBrsFromTableCell(dom, selection.getStart());
12905      updateCaret(editor.schema, editor.getBody(), selection.getStart());
12906      return value;
12907    };
12908
12909    const isTreeNode = content => content instanceof AstNode;
12910
12911    const moveSelection = editor => {
12912      if (hasFocus(editor)) {
12913        firstPositionIn(editor.getBody()).each(pos => {
12914          const node = pos.getNode();
12915          const caretPos = isTable$2(node) ? firstPositionIn(node).getOr(pos) : pos;
12916          editor.selection.setRng(caretPos.toRange());
12917        });
12918      }
12919    };
12920    const setEditorHtml = (editor, html, noSelection) => {
12921      editor.dom.setHTML(editor.getBody(), html);
12922      if (noSelection !== true) {
12923        moveSelection(editor);
12924      }
12925    };
12926    const setContentString = (editor, body, content, args) => {
12927      if (content.length === 0 || /^\s+$/.test(content)) {
12928        const padd = '<br data-mce-bogus="1">';
12929        if (body.nodeName === 'TABLE') {
12930          content = '<tr><td>' + padd + '</td></tr>';
12931        } else if (/^(UL|OL)$/.test(body.nodeName)) {
12932          content = '<li>' + padd + '</li>';
12933        }
12934        const forcedRootBlockName = getForcedRootBlock(editor);
12935        if (editor.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
12936          content = padd;
12937          content = editor.dom.createHTML(forcedRootBlockName, getForcedRootBlockAttrs(editor), content);
12938        } else if (!content) {
12939          content = padd;
12940        }
12941        setEditorHtml(editor, content, args.no_selection);
12942        return {
12943          content,
12944          html: content
12945        };
12946      } else {
12947        if (args.format !== 'raw') {
12948          content = HtmlSerializer({ validate: false }, editor.schema).serialize(editor.parser.parse(content, {
12949            isRootContent: true,
12950            insert: true
12951          }));
12952        }
12953        const trimmedHtml = isWsPreserveElement(SugarElement.fromDom(body)) ? content : Tools.trim(content);
12954        setEditorHtml(editor, trimmedHtml, args.no_selection);
12955        return {
12956          content: trimmedHtml,
12957          html: trimmedHtml
12958        };
12959      }
12960    };
12961    const setContentTree = (editor, body, content, args) => {
12962      filter$2(editor.parser.getNodeFilters(), editor.parser.getAttributeFilters(), content);
12963      const html = HtmlSerializer({ validate: false }, editor.schema).serialize(content);
12964      const trimmedHtml = isWsPreserveElement(SugarElement.fromDom(body)) ? html : Tools.trim(html);
12965      setEditorHtml(editor, trimmedHtml, args.no_selection);
12966      return {
12967        content,
12968        html: trimmedHtml
12969      };
12970    };
12971    const setContentInternal = (editor, content, args) => {
12972      return Optional.from(editor.getBody()).map(body => {
12973        if (isTreeNode(content)) {
12974          return setContentTree(editor, body, content, args);
12975        } else {
12976          return setContentString(editor, body, content, args);
12977        }
12978      }).getOr({
12979        content,
12980        html: isTreeNode(args.content) ? '' : args.content
12981      });
12982    };
12983
12984    const ancestor$1 = (scope, predicate, isRoot) => ancestor$4(scope, predicate, isRoot).isSome();
12985    const sibling = (scope, predicate) => sibling$1(scope, predicate).isSome();
12986
12987    const ensureIsRoot = isRoot => isFunction(isRoot) ? isRoot : never;
12988    const ancestor = (scope, transform, isRoot) => {
12989      let element = scope.dom;
12990      const stop = ensureIsRoot(isRoot);
12991      while (element.parentNode) {
12992        element = element.parentNode;
12993        const el = SugarElement.fromDom(element);
12994        const transformed = transform(el);
12995        if (transformed.isSome()) {
12996          return transformed;
12997        } else if (stop(el)) {
12998          break;
12999        }
13000      }
13001      return Optional.none();
13002    };
13003    const closest$1 = (scope, transform, isRoot) => {
13004      const current = transform(scope);
13005      const stop = ensureIsRoot(isRoot);
13006      return current.orThunk(() => stop(scope) ? Optional.none() : ancestor(scope, transform, stop
vendor: 5,553 bytes, lines 13006-13156
13006));
13007    };
13008
13009    const isEq$3 = isEq$5;
13010    const matchesUnInheritedFormatSelector = (ed, node, name) => {
13011      const formatList = ed.formatter.get(name);
13012      if (formatList) {
13013        for (let i = 0; i < formatList.length; i++) {
13014          const format = formatList[i];
13015          if (isSelectorFormat(format) && format.inherit === false && ed.dom.is(node, format.selector)) {
13016            return true;
13017          }
13018        }
13019      }
13020      return false;
13021    };
13022    const matchParents = (editor, node, name, vars, similar) => {
13023      const root = editor.dom.getRoot();
13024      if (node === root) {
13025        return false;
13026      }
13027      const matchedNode = editor.dom.getParent(node, elm => {
13028        if (matchesUnInheritedFormatSelector(editor, elm, name)) {
13029          return true;
13030        }
13031        return elm.parentNode === root || !!matchNode(editor, elm, name, vars, true);
13032      });
13033      return !!matchNode(editor, matchedNode, name, vars, similar);
13034    };
13035    const matchName = (dom, node, format) => {
13036      if (isInlineFormat(format) && isEq$3(node, format.inline)) {
13037        return true;
13038      }
13039      if (isBlockFormat(format) && isEq$3(node, format.block)) {
13040        return true;
13041      }
13042      if (isSelectorFormat(format)) {
13043        return isElement$6(node) && dom.is(node, format.selector);
13044      }
13045      return false;
13046    };
13047    const matchItems = (dom, node, format, itemName, similar, vars) => {
13048      const items = format[itemName];
13049      const matchAttributes = itemName === 'attributes';
13050      if (isFunction(format.onmatch)) {
13051        return format.onmatch(node, format, itemName);
13052      }
13053      if (items) {
13054        if (!isArrayLike(items)) {
13055          for (const key in items) {
13056            if (has$2(items, key)) {
13057              const value = matchAttributes ? dom.getAttrib(node, key) : getStyle(dom, node, key);
13058              const expectedValue = replaceVars(items[key], vars);
13059              const isEmptyValue = isNullable(value) || isEmpty$3(value);
13060              if (isEmptyValue && isNullable(expectedValue)) {
13061                continue;
13062              }
13063              if (similar && isEmptyValue && !format.exact) {
13064                return false;
13065              }
13066              if ((!similar || format.exact) && !isEq$3(value, normalizeStyleValue(expectedValue, key))) {
13067                return false;
13068              }
13069            }
13070          }
13071        } else {
13072          for (let i = 0; i < items.length; i++) {
13073            if (matchAttributes ? dom.getAttrib(node, items[i]) : getStyle(dom, node, items[i])) {
13074              return true;
13075            }
13076          }
13077        }
13078      }
13079      return true;
13080    };
13081    const matchNode = (ed, node, name, vars, similar) => {
13082      const formatList = ed.formatter.get(name);
13083      const dom = ed.dom;
13084      if (formatList && isElement$6(node)) {
13085        for (let i = 0; i < formatList.length; i++) {
13086          const format = formatList[i];
13087          if (matchName(ed.dom, node, format) && matchItems(dom, node, format, 'attributes', similar, vars) && matchItems(dom, node, format, 'styles', similar, vars)) {
13088            const classes = format.classes;
13089            if (classes) {
13090              for (let x = 0; x < classes.length; x++) {
13091                if (!ed.dom.hasClass(node, replaceVars(classes[x], vars))) {
13092                  return;
13093                }
13094              }
13095            }
13096            return format;
13097          }
13098        }
13099      }
13100      return undefined;
13101    };
13102    const match$2 = (editor, name, vars, node, similar) => {
13103      if (node) {
13104        return matchParents(editor, node, name, vars, similar);
13105      }
13106      node = editor.selection.getNode();
13107      if (matchParents(editor, node, name, vars, similar)) {
13108        return true;
13109      }
13110      const startNode = editor.selection.getStart();
13111      if (startNode !== node) {
13112        if (matchParents(editor, startNode, name, vars, similar)) {
13113          return true;
13114        }
13115      }
13116      return false;
13117    };
13118    const matchAll = (editor, names, vars) => {
13119      const matchedFormatNames = [];
13120      const checkedMap = {};
13121      const startElement = editor.selection.getStart();
13122      editor.dom.getParent(startElement, node => {
13123        for (let i = 0; i < names.length; i++) {
13124          const name = names[i];
13125          if (!checkedMap[name] && matchNode(editor, node, name, vars)) {
13126            checkedMap[name] = true;
13127            matchedFormatNames.push(name);
13128          }
13129        }
13130      }, editor.dom.getRoot());
13131      return matchedFormatNames;
13132    };
13133    const closest = (editor, names) => {
13134      const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody()));
13135      const match = (elm, name) => matchNode(editor, elm.dom, name) ? Optional.some(name) : Optional.none();
13136      return Optional.from(editor.selection.getStart(true)).bind(rawElm => closest$1(SugarElement.fromDom(rawElm), elm => findMap(names, name => match(elm, name)), isRoot)).getOrNull();
13137    };
13138    const canApply = (editor, name) => {
13139      const formatList = editor.formatter.get(name);
13140      const dom = editor.dom;
13141      if (formatList) {
13142        const startNode = editor.selection.getStart();
13143        const parents = getParents$2(dom, startNode);
13144        for (let x = formatList.length - 1; x >= 0; x--) {
13145          const format = formatList[x];
13146          if (!isSelectorFormat(format)) {
13147            return true;
13148          }
13149          for (let i = parents.length - 1; i >= 0; i--) {
13150            if (dom.is(parents[i], format.selector)) {
13151              return true;
13152            }
13153          }
13154        }
13155      }
13156      return false;
vendor: 39,730 bytes, lines 13157-14130
13157    };
13158    const matchAllOnNode = (editor, node, formatNames) => foldl(formatNames, (acc, name) => {
13159      const matchSimilar = isVariableFormatName(editor, name);
13160      if (editor.formatter.matchNode(node, name, {}, matchSimilar)) {
13161        return acc.concat([name]);
13162      } else {
13163        return acc;
13164      }
13165    }, []);
13166
13167    const ZWSP = ZWSP$1;
13168    const importNode = (ownerDocument, node) => {
13169      return ownerDocument.importNode(node, true);
13170    };
13171    const getEmptyCaretContainers = node => {
13172      const nodes = [];
13173      let tempNode = node;
13174      while (tempNode) {
13175        if (isText$a(tempNode) && tempNode.data !== ZWSP || tempNode.childNodes.length > 1) {
13176          return [];
13177        }
13178        if (isElement$6(tempNode)) {
13179          nodes.push(tempNode);
13180        }
13181        tempNode = tempNode.firstChild;
13182      }
13183      return nodes;
13184    };
13185    const isCaretContainerEmpty = node => {
13186      return getEmptyCaretContainers(node).length > 0;
13187    };
13188    const findFirstTextNode = node => {
13189      if (node) {
13190        const walker = new DomTreeWalker(node, node);
13191        for (let tempNode = walker.current(); tempNode; tempNode = walker.next()) {
13192          if (isText$a(tempNode)) {
13193            return tempNode;
13194          }
13195        }
13196      }
13197      return null;
13198    };
13199    const createCaretContainer = fill => {
13200      const caretContainer = SugarElement.fromTag('span');
13201      setAll$1(caretContainer, {
13202        'id': CARET_ID,
13203        'data-mce-bogus': '1',
13204        'data-mce-type': 'format-caret'
13205      });
13206      if (fill) {
13207        append$1(caretContainer, SugarElement.fromText(ZWSP));
13208      }
13209      return caretContainer;
13210    };
13211    const trimZwspFromCaretContainer = caretContainerNode => {
13212      const textNode = findFirstTextNode(caretContainerNode);
13213      if (textNode && textNode.data.charAt(0) === ZWSP) {
13214        textNode.deleteData(0, 1);
13215      }
13216      return textNode;
13217    };
13218    const removeCaretContainerNode = (editor, node, moveCaret = true) => {
13219      const dom = editor.dom, selection = editor.selection;
13220      if (isCaretContainerEmpty(node)) {
13221        deleteElement$2(editor, false, SugarElement.fromDom(node), moveCaret);
13222      } else {
13223        const rng = selection.getRng();
13224        const block = dom.getParent(node, dom.isBlock);
13225        const startContainer = rng.startContainer;
13226        const startOffset = rng.startOffset;
13227        const endContainer = rng.endContainer;
13228        const endOffset = rng.endOffset;
13229        const textNode = trimZwspFromCaretContainer(node);
13230        dom.remove(node, true);
13231        if (startContainer === textNode && startOffset > 0) {
13232          rng.setStart(textNode, startOffset - 1);
13233        }
13234        if (endContainer === textNode && endOffset > 0) {
13235          rng.setEnd(textNode, endOffset - 1);
13236        }
13237        if (block && dom.isEmpty(block)) {
13238          fillWithPaddingBr(SugarElement.fromDom(block));
13239        }
13240        selection.setRng(rng);
13241      }
13242    };
13243    const removeCaretContainer = (editor, node, moveCaret = true) => {
13244      const dom = editor.dom, selection = editor.selection;
13245      if (!node) {
13246        node = getParentCaretContainer(editor.getBody(), selection.getStart());
13247        if (!node) {
13248          while (node = dom.get(CARET_ID)) {
13249            removeCaretContainerNode(editor, node, false);
13250          }
13251        }
13252      } else {
13253        removeCaretContainerNode(editor, node, moveCaret);
13254      }
13255    };
13256    const insertCaretContainerNode = (editor, caretContainer, formatNode) => {
13257      var _a, _b;
13258      const dom = editor.dom;
13259      const block = dom.getParent(formatNode, curry(isTextBlock$1, editor.schema));
13260      if (block && dom.isEmpty(block)) {
13261        (_a = formatNode.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(caretContainer, formatNode);
13262      } else {
13263        removeTrailingBr(SugarElement.fromDom(formatNode));
13264        if (dom.isEmpty(formatNode)) {
13265          (_b = formatNode.parentNode) === null || _b === void 0 ? void 0 : _b.replaceChild(caretContainer, formatNode);
13266        } else {
13267          dom.insertAfter(caretContainer, formatNode);
13268        }
13269      }
13270    };
13271    const appendNode = (parentNode, node) => {
13272      parentNode.appendChild(node);
13273      return node;
13274    };
13275    const insertFormatNodesIntoCaretContainer = (formatNodes, caretContainer) => {
13276      var _a;
13277      const innerMostFormatNode = foldr(formatNodes, (parentNode, formatNode) => {
13278        return appendNode(parentNode, formatNode.cloneNode(false));
13279      }, caretContainer);
13280      const doc = (_a = innerMostFormatNode.ownerDocument) !== null && _a !== void 0 ? _a : document;
13281      return appendNode(innerMostFormatNode, doc.createTextNode(ZWSP));
13282    };
13283    const cleanFormatNode = (editor, caretContainer, formatNode, name, vars, similar) => {
13284      const formatter = editor.formatter;
13285      const dom = editor.dom;
13286      const validFormats = filter$5(keys(formatter.get()), formatName => formatName !== name && !contains$1(formatName, 'removeformat'));
13287      const matchedFormats = matchAllOnNode(editor, formatNode, validFormats);
13288      const uniqueFormats = filter$5(matchedFormats, fmtName => !areSimilarFormats(editor, fmtName, name));
13289      if (uniqueFormats.length > 0) {
13290        const clonedFormatNode = formatNode.cloneNode(false);
13291        dom.add(caretContainer, clonedFormatNode);
13292        formatter.remove(name, vars, clonedFormatNode, similar);
13293        dom.remove(clonedFormatNode);
13294        return Optional.some(clonedFormatNode);
13295      } else {
13296        return Optional.none();
13297      }
13298    };
13299    const applyCaretFormat = (editor, name, vars) => {
13300      let caretContainer;
13301      const selection = editor.selection;
13302      const formatList = editor.formatter.get(name);
13303      if (!formatList) {
13304        return;
13305      }
13306      const selectionRng = selection.getRng();
13307      let offset = selectionRng.startOffset;
13308      const container = selectionRng.startContainer;
13309      const text = container.nodeValue;
13310      caretContainer = getParentCaretContainer(editor.getBody(), selection.getStart());
13311      const wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/;
13312      if (text && offset > 0 && offset < text.length && wordcharRegex.test(text.charAt(offset)) && wordcharRegex.test(text.charAt(offset - 1))) {
13313        const bookmark = selection.getBookmark();
13314        selectionRng.collapse(true);
13315        let rng = expandRng(editor.dom, selectionRng, formatList);
13316        rng = split(rng);
13317        editor.formatter.apply(name, vars, rng);
13318        selection.moveToBookmark(bookmark);
13319      } else {
13320        let textNode = caretContainer ? findFirstTextNode(caretContainer) : null;
13321        if (!caretContainer || (textNode === null || textNode === void 0 ? void 0 : textNode.data) !== ZWSP) {
13322          caretContainer = importNode(editor.getDoc(), createCaretContainer(true).dom);
13323          textNode = caretContainer.firstChild;
13324          selectionRng.insertNode(caretContainer);
13325          offset = 1;
13326          editor.formatter.apply(name, vars, caretContainer);
13327        } else {
13328          editor.formatter.apply(name, vars, caretContainer);
13329        }
13330        selection.setCursorLocation(textNode, offset);
13331      }
13332    };
13333    const removeCaretFormat = (editor, name, vars, similar) => {
13334      const dom = editor.dom;
13335      const selection = editor.selection;
13336      let hasContentAfter = false;
13337      const formatList = editor.formatter.get(name);
13338      if (!formatList) {
13339        return;
13340      }
13341      const rng = selection.getRng();
13342      const container = rng.startContainer;
13343      const offset = rng.startOffset;
13344      let node = container;
13345      if (isText$a(container)) {
13346        if (offset !== container.data.length) {
13347          hasContentAfter = true;
13348        }
13349        node = node.parentNode;
13350      }
13351      const parents = [];
13352      let formatNode;
13353      while (node) {
13354        if (matchNode(editor, node, name, vars, similar)) {
13355          formatNode = node;
13356          break;
13357        }
13358        if (node.nextSibling) {
13359          hasContentAfter = true;
13360        }
13361        parents.push(node);
13362        node = node.parentNode;
13363      }
13364      if (!formatNode) {
13365        return;
13366      }
13367      if (hasContentAfter) {
13368        const bookmark = selection.getBookmark();
13369        rng.collapse(true);
13370        let expandedRng = expandRng(dom, rng, formatList, true);
13371        expandedRng = split(expandedRng);
13372        editor.formatter.remove(name, vars, expandedRng, similar);
13373        selection.moveToBookmark(bookmark);
13374      } else {
13375        const caretContainer = getParentCaretContainer(editor.getBody(), formatNode);
13376        const newCaretContainer = createCaretContainer(false).dom;
13377        insertCaretContainerNode(editor, newCaretContainer, caretContainer !== null && caretContainer !== void 0 ? caretContainer : formatNode);
13378        const cleanedFormatNode = cleanFormatNode(editor, newCaretContainer, formatNode, name, vars, similar);
13379        const caretTextNode = insertFormatNodesIntoCaretContainer(parents.concat(cleanedFormatNode.toArray()), newCaretContainer);
13380        if (caretContainer) {
13381          removeCaretContainerNode(editor, caretContainer, false);
13382        }
13383        selection.setCursorLocation(caretTextNode, 1);
13384        if (dom.isEmpty(formatNode)) {
13385          dom.remove(formatNode);
13386        }
13387      }
13388    };
13389    const disableCaretContainer = (editor, keyCode) => {
13390      const selection = editor.selection, body = editor.getBody();
13391      removeCaretContainer(editor, null, false);
13392      if ((keyCode === 8 || keyCode === 46) && selection.isCollapsed() && selection.getStart().innerHTML === ZWSP) {
13393        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()));
13394      }
13395      if (keyCode === 37 || keyCode === 39) {
13396        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()));
13397      }
13398    };
13399    const setup$u = editor => {
13400      editor.on('mouseup keydown', e => {
13401        disableCaretContainer(editor, e.keyCode);
13402      });
13403    };
13404    const createCaretFormat = formatNodes => {
13405      const caretContainer = createCaretContainer(false);
13406      const innerMost = insertFormatNodesIntoCaretContainer(formatNodes, caretContainer.dom);
13407      return {
13408        caretContainer,
13409        caretPosition: CaretPosition(innerMost, 0)
13410      };
13411    };
13412    const replaceWithCaretFormat = (targetNode, formatNodes) => {
13413      const {caretContainer, caretPosition} = createCaretFormat(formatNodes);
13414      before$3(SugarElement.fromDom(targetNode), caretContainer);
13415      remove$6(SugarElement.fromDom(targetNode));
13416      return caretPosition;
13417    };
13418    const createCaretFormatAtStart$1 = (editor, formatNodes) => {
13419      const {caretContainer, caretPosition} = createCaretFormat(formatNodes);
13420      editor.selection.getRng().insertNode(caretContainer.dom);
13421      return caretPosition;
13422    };
13423    const isFormatElement = (editor, element) => {
13424      const inlineElements = editor.schema.getTextInlineElements();
13425      return has$2(inlineElements, name(element)) && !isCaretNode(element.dom) && !isBogus$2(element.dom);
13426    };
13427    const isEmptyCaretFormatElement = element => {
13428      return isCaretNode(element.dom) && isCaretContainerEmpty(element.dom);
13429    };
13430
13431    const postProcessHooks = {};
13432    const isPre = matchNodeNames(['pre']);
13433    const addPostProcessHook = (name, hook) => {
13434      const hooks = postProcessHooks[name];
13435      if (!hooks) {
13436        postProcessHooks[name] = [];
13437      }
13438      postProcessHooks[name].push(hook);
13439    };
13440    const postProcess$1 = (name, editor) => {
13441      if (has$2(postProcessHooks, name)) {
13442        each$e(postProcessHooks[name], hook => {
13443          hook(editor);
13444        });
13445      }
13446    };
13447    addPostProcessHook('pre', editor => {
13448      const rng = editor.selection.getRng();
13449      const hasPreSibling = blocks => pre => {
13450        const prev = pre.previousSibling;
13451        return isPre(prev) && contains$2(blocks, prev);
13452      };
13453      const joinPre = (pre1, pre2) => {
13454        const sPre2 = SugarElement.fromDom(pre2);
13455        const doc = documentOrOwner(sPre2).dom;
13456        remove$6(sPre2);
13457        append(SugarElement.fromDom(pre1), [
13458          SugarElement.fromTag('br', doc),
13459          SugarElement.fromTag('br', doc),
13460          ...children$1(sPre2)
13461        ]);
13462      };
13463      if (!rng.collapsed) {
13464        const blocks = editor.selection.getSelectedBlocks();
13465        const preBlocks = filter$5(filter$5(blocks, isPre), hasPreSibling(blocks));
13466        each$e(preBlocks, pre => {
13467          joinPre(pre.previousSibling, pre);
13468        });
13469      }
13470    });
13471
13472    const listItemStyles = [
13473      'fontWeight',
13474      'fontStyle',
13475      'color',
13476      'fontSize',
13477      'fontFamily'
13478    ];
13479    const hasListStyles = fmt => isObject(fmt.styles) && exists(keys(fmt.styles), name => contains$2(listItemStyles, name));
13480    const findExpandedListItemFormat = formats => find$2(formats, fmt => isInlineFormat(fmt) && fmt.inline === 'span' && hasListStyles(fmt));
13481    const getExpandedListItemFormat = (formatter, format) => {
13482      const formatList = formatter.get(format);
13483      return isArray$1(formatList) ? findExpandedListItemFormat(formatList) : Optional.none();
13484    };
13485    const isRngStartAtStartOfElement = (rng, elm) => prevPosition(elm, CaretPosition.fromRangeStart(rng)).isNone();
13486    const isRngEndAtEndOfElement = (rng, elm) => {
13487      return nextPosition(elm, CaretPosition.fromRangeEnd(rng)).exists(pos => !isBr$6(pos.getNode()) || nextPosition(elm, pos).isSome()) === false;
13488    };
13489    const isEditableListItem = dom => elm => isListItem$2(elm) && dom.isEditable(elm);
13490    const getFullySelectedBlocks = selection => {
13491      const blocks = selection.getSelectedBlocks();
13492      const rng = selection.getRng();
13493      if (selection.isCollapsed()) {
13494        return [];
13495      }
13496      if (blocks.length === 1) {
13497        return isRngStartAtStartOfElement(rng, blocks[0]) && isRngEndAtEndOfElement(rng, blocks[0]) ? blocks : [];
13498      } else {
13499        const first = head(blocks).filter(elm => isRngStartAtStartOfElement(rng, elm)).toArray();
13500        const last = last$3(blocks).filter(elm => isRngEndAtEndOfElement(rng, elm)).toArray();
13501        const middle = blocks.slice(1, -1);
13502        return first.concat(middle).concat(last);
13503      }
13504    };
13505    const getFullySelectedListItems = selection => filter$5(getFullySelectedBlocks(selection), isEditableListItem(selection.dom));
13506    const getPartiallySelectedListItems = selection => filter$5(selection.getSelectedBlocks(), isEditableListItem(selection.dom));
13507
13508    const each$8 = Tools.each;
13509    const isElementNode = node => isElement$6(node) && !isBookmarkNode$1(node) && !isCaretNode(node) && !isBogus$2(node);
13510    const findElementSibling = (node, siblingName) => {
13511      for (let sibling = node; sibling; sibling = sibling[siblingName]) {
13512        if (isText$a(sibling) && isNotEmpty(sibling.data)) {
13513          return node;
13514        }
13515        if (isElement$6(sibling) && !isBookmarkNode$1(sibling)) {
13516          return sibling;
13517        }
13518      }
13519      return node;
13520    };
13521    const mergeSiblingsNodes = (editor, prev, next) => {
13522      const elementUtils = ElementUtils(editor);
13523      const isPrevEditable = isElement$6(prev) && isEditable$2(prev);
13524      const isNextEditable = isElement$6(next) && isEditable$2(next);
13525      if (isPrevEditable && isNextEditable) {
13526        const prevSibling = findElementSibling(prev, 'previousSibling');
13527        const nextSibling = findElementSibling(next, 'nextSibling');
13528        if (elementUtils.compare(prevSibling, nextSibling)) {
13529          for (let sibling = prevSibling.nextSibling; sibling && sibling !== nextSibling;) {
13530            const tmpSibling = sibling;
13531            sibling = sibling.nextSibling;
13532            prevSibling.appendChild(tmpSibling);
13533          }
13534          editor.dom.remove(nextSibling);
13535          Tools.each(Tools.grep(nextSibling.childNodes), node => {
13536            prevSibling.appendChild(node);
13537          });
13538          return prevSibling;
13539        }
13540      }
13541      return next;
13542    };
13543    const mergeSiblings = (editor, format, vars, node) => {
13544      var _a;
13545      if (node && format.merge_siblings !== false) {
13546        const newNode = (_a = mergeSiblingsNodes(editor, getNonWhiteSpaceSibling(node), node)) !== null && _a !== void 0 ? _a : node;
13547        mergeSiblingsNodes(editor, newNode, getNonWhiteSpaceSibling(newNode, true));
13548      }
13549    };
13550    const clearChildStyles = (dom, format, node) => {
13551      if (format.clear_child_styles) {
13552        const selector = format.links ? '*:not(a)' : '*';
13553        each$8(dom.select(selector, node), childNode => {
13554          if (isElementNode(childNode) && isEditable$2(childNode)) {
13555            each$8(format.styles, (_value, name) => {
13556              dom.setStyle(childNode, name, '');
13557            });
13558          }
13559        });
13560      }
13561    };
13562    const processChildElements = (node, filter, process) => {
13563      each$8(node.childNodes, node => {
13564        if (isElementNode(node)) {
13565          if (filter(node)) {
13566            process(node);
13567          }
13568          if (node.hasChildNodes()) {
13569            processChildElements(node, filter, process);
13570          }
13571        }
13572      });
13573    };
13574    const unwrapEmptySpan = (dom, node) => {
13575      if (node.nodeName === 'SPAN' && dom.getAttribs(node).length === 0) {
13576        dom.remove(node, true);
13577      }
13578    };
13579    const hasStyle = (dom, name) => node => !!(node && getStyle(dom, node, name));
13580    const applyStyle = (dom, name, value) => node => {
13581      dom.setStyle(node, name, value);
13582      if (node.getAttribute('style') === '') {
13583        node.removeAttribute('style');
13584      }
13585      unwrapEmptySpan(dom, node);
13586    };
13587
13588    const removeResult = Adt.generate([
13589      { keep: [] },
13590      { rename: ['name'] },
13591      { removed: [] }
13592    ]);
13593    const MCE_ATTR_RE = /^(src|href|style)$/;
13594    const each$7 = Tools.each;
13595    const isEq$2 = isEq$5;
13596    const isTableCellOrRow = node => /^(TR|TH|TD)$/.test(node.nodeName);
13597    const isChildOfInlineParent = (dom, node, parent) => dom.isChildOf(node, parent) && node !== parent && !dom.isBlock(parent);
13598    const getContainer = (ed, rng, start) => {
13599      let container = rng[start ? 'startContainer' : 'endContainer'];
13600      let offset = rng[start ? 'startOffset' : 'endOffset'];
13601      if (isElement$6(container)) {
13602        const lastIdx = container.childNodes.length - 1;
13603        if (!start && offset) {
13604          offset--;
13605        }
13606        container = container.childNodes[offset > lastIdx ? lastIdx : offset];
13607      }
13608      if (isText$a(container) && start && offset >= container.data.length) {
13609        container = new DomTreeWalker(container, ed.getBody()).next() || container;
13610      }
13611      if (isText$a(container) && !start && offset === 0) {
13612        container = new DomTreeWalker(container, ed.getBody()).prev() || container;
13613      }
13614      return container;
13615    };
13616    const normalizeTableSelection = (node, start) => {
13617      const prop = start ? 'firstChild' : 'lastChild';
13618      const childNode = node[prop];
13619      if (isTableCellOrRow(node) && childNode) {
13620        if (node.nodeName === 'TR') {
13621          return childNode[prop] || childNode;
13622        } else {
13623          return childNode;
13624        }
13625      }
13626      return node;
13627    };
13628    const wrap$1 = (dom, node, name, attrs) => {
13629      var _a;
13630      const wrapper = dom.create(name, attrs);
13631      (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(wrapper, node);
13632      wrapper.appendChild(node);
13633      return wrapper;
13634    };
13635    const wrapWithSiblings = (dom, node, next, name, attrs) => {
13636      const start = SugarElement.fromDom(node);
13637      const wrapper = SugarElement.fromDom(dom.create(name, attrs));
13638      const siblings = next ? nextSiblings(start) : prevSiblings(start);
13639      append(wrapper, siblings);
13640      if (next) {
13641        before$3(start, wrapper);
13642        prepend(wrapper, start);
13643      } else {
13644        after$4(start, wrapper);
13645        append$1(wrapper, start);
13646      }
13647      return wrapper.dom;
13648    };
13649    const isColorFormatAndAnchor = (node, format) => format.links && node.nodeName === 'A';
13650    const removeNode = (ed, node, format) => {
13651      const parentNode = node.parentNode;
13652      let rootBlockElm;
13653      const dom = ed.dom;
13654      const forcedRootBlock = getForcedRootBlock(ed);
13655      if (isBlockFormat(format)) {
13656        if (parentNode === dom.getRoot()) {
13657          if (!format.list_block || !isEq$2(node, format.list_block)) {
13658            each$e(from(node.childNodes), node => {
13659              if (isValid(ed, forcedRootBlock, node.nodeName.toLowerCase())) {
13660                if (!rootBlockElm) {
13661                  rootBlockElm = wrap$1(dom, node, forcedRootBlock);
13662                  dom.setAttribs(rootBlockElm, getForcedRootBlockAttrs(ed));
13663                } else {
13664                  rootBlockElm.appendChild(node);
13665                }
13666              } else {
13667                rootBlockElm = null;
13668              }
13669            });
13670          }
13671        }
13672      }
13673      if (isMixedFormat(format) && !isEq$2(format.inline, node)) {
13674        return;
13675      }
13676      dom.remove(node, true);
13677    };
13678    const processFormatAttrOrStyle = (name, value, vars) => {
13679      if (isNumber(name)) {
13680        return {
13681          name: value,
13682          value: null
13683        };
13684      } else {
13685        return {
13686          name,
13687          value: replaceVars(value, vars)
13688        };
13689      }
13690    };
13691    const removeEmptyStyleAttributeIfNeeded = (dom, elm) => {
13692      if (dom.getAttrib(elm, 'style') === '') {
13693        elm.removeAttribute('style');
13694        elm.removeAttribute('data-mce-style');
13695      }
13696    };
13697    const removeStyles = (dom, elm, format, vars, compareNode) => {
13698      let stylesModified = false;
13699      each$7(format.styles, (value, name) => {
13700        const {
13701          name: styleName,
13702          value: styleValue
13703        } = processFormatAttrOrStyle(name, value, vars);
13704        const normalizedStyleValue = normalizeStyleValue(styleValue, styleName);
13705        if (format.remove_similar || isNull(styleValue) || !isElement$6(compareNode) || isEq$2(getStyle(dom, compareNode, styleName), normalizedStyleValue)) {
13706          dom.setStyle(elm, styleName, '');
13707        }
13708        stylesModified = true;
13709      });
13710      if (stylesModified) {
13711        removeEmptyStyleAttributeIfNeeded(dom, elm);
13712      }
13713    };
13714    const removeListStyleFormats = (editor, name, vars) => {
13715      if (name === 'removeformat') {
13716        each$e(getPartiallySelectedListItems(editor.selection), li => {
13717          each$e(listItemStyles, name => editor.dom.setStyle(li, name, ''));
13718          removeEmptyStyleAttributeIfNeeded(editor.dom, li);
13719        });
13720      } else {
13721        getExpandedListItemFormat(editor.formatter, name).each(liFmt => {
13722          each$e(getPartiallySelectedListItems(editor.selection), li => removeStyles(editor.dom, li, liFmt, vars, null));
13723        });
13724      }
13725    };
13726    const removeFormatInternal = (ed, format, vars, node, compareNode) => {
13727      const dom = ed.dom;
13728      const elementUtils = ElementUtils(ed);
13729      const schema = ed.schema;
13730      if (isInlineFormat(format) && isTransparentElementName(schema, format.inline) && isTransparentBlock(schema, node) && node.parentElement === ed.getBody()) {
13731        removeNode(ed, node, format);
13732        return removeResult.removed();
13733      }
13734      if (!format.ceFalseOverride && node && dom.getContentEditableParent(node) === 'false') {
13735        return removeResult.keep();
13736      }
13737      if (node && !matchName(dom, node, format) && !isColorFormatAndAnchor(node, format)) {
13738        return removeResult.keep();
13739      }
13740      const elm = node;
13741      const preserveAttributes = format.preserve_attributes;
13742      if (isInlineFormat(format) && format.remove === 'all' && isArray$1(preserveAttributes)) {
13743        const attrsToPreserve = filter$5(dom.getAttribs(elm), attr => contains$2(preserveAttributes, attr.name.toLowerCase()));
13744        dom.removeAllAttribs(elm);
13745        each$e(attrsToPreserve, attr => dom.setAttrib(elm, attr.name, attr.value));
13746        if (attrsToPreserve.length > 0) {
13747          return removeResult.rename('span');
13748        }
13749      }
13750      if (format.remove !== 'all') {
13751        removeStyles(dom, elm, format, vars, compareNode);
13752        each$7(format.attributes, (value, name) => {
13753          const {
13754            name: attrName,
13755            value: attrValue
13756          } = processFormatAttrOrStyle(name, value, vars);
13757          if (format.remove_similar || isNull(attrValue) || !isElement$6(compareNode) || isEq$2(dom.getAttrib(compareNode, attrName), attrValue)) {
13758            if (attrName === 'class') {
13759              const currentValue = dom.getAttrib(elm, attrName);
13760              if (currentValue) {
13761                let valueOut = '';
13762                each$e(currentValue.split(/\s+/), cls => {
13763                  if (/mce\-\w+/.test(cls)) {
13764                    valueOut += (valueOut ? ' ' : '') + cls;
13765                  }
13766                });
13767                if (valueOut) {
13768                  dom.setAttrib(elm, attrName, valueOut);
13769                  return;
13770                }
13771              }
13772            }
13773            if (MCE_ATTR_RE.test(attrName)) {
13774              elm.removeAttribute('data-mce-' + attrName);
13775            }
13776            if (attrName === 'style' && matchNodeNames(['li'])(elm) && dom.getStyle(elm, 'list-style-type') === 'none') {
13777              elm.removeAttribute(attrName);
13778              dom.setStyle(elm, 'list-style-type', 'none');
13779              return;
13780            }
13781            if (attrName === 'class') {
13782              elm.removeAttribute('className');
13783            }
13784            elm.removeAttribute(attrName);
13785          }
13786        });
13787        each$7(format.classes, value => {
13788          value = replaceVars(value, vars);
13789          if (!isElement$6(compareNode) || dom.hasClass(compareNode, value)) {
13790            dom.removeClass(elm, value);
13791          }
13792        });
13793        const attrs = dom.getAttribs(elm);
13794        for (let i = 0; i < attrs.length; i++) {
13795          const attrName = attrs[i].nodeName;
13796          if (!elementUtils.isAttributeInternal(attrName)) {
13797            return removeResult.keep();
13798          }
13799        }
13800      }
13801      if (format.remove !== 'none') {
13802        removeNode(ed, elm, format);
13803        return removeResult.removed();
13804      }
13805      return removeResult.keep();
13806    };
13807    const removeFormat$1 = (ed, format, vars, node, compareNode) => removeFormatInternal(ed, format, vars, node, compareNode).fold(never, newName => {
13808      ed.dom.rename(node, newName);
13809      return true;
13810    }, always);
13811    const findFormatRoot = (editor, container, name, vars, similar) => {
13812      let formatRoot;
13813      if (container.parentNode) {
13814        each$e(getParents$2(editor.dom, container.parentNode).reverse(), parent => {
13815          if (!formatRoot && isElement$6(parent) && parent.id !== '_start' && parent.id !== '_end') {
13816            const format = matchNode(editor, parent, name, vars, similar);
13817            if (format && format.split !== false) {
13818              formatRoot = parent;
13819            }
13820          }
13821        });
13822      }
13823      return formatRoot;
13824    };
13825    const removeFormatFromClone = (editor, format, vars, clone) => removeFormatInternal(editor, format, vars, clone, clone).fold(constant(clone), newName => {
13826      const fragment = editor.dom.createFragment();
13827      fragment.appendChild(clone);
13828      return editor.dom.rename(clone, newName);
13829    }, constant(null));
13830    const wrapAndSplit = (editor, formatList, formatRoot, container, target, split, format, vars) => {
13831      var _a, _b;
13832      let lastClone;
13833      let firstClone;
13834      const dom = editor.dom;
13835      if (formatRoot) {
13836        const formatRootParent = formatRoot.parentNode;
13837        for (let parent = container.parentNode; parent && parent !== formatRootParent; parent = parent.parentNode) {
13838          let clone = dom.clone(parent, false);
13839          for (let i = 0; i < formatList.length; i++) {
13840            clone = removeFormatFromClone(editor, formatList[i], vars, clone);
13841            if (clone === null) {
13842              break;
13843            }
13844          }
13845          if (clone) {
13846            if (lastClone) {
13847              clone.appendChild(lastClone);
13848            }
13849            if (!firstClone) {
13850              firstClone = clone;
13851            }
13852            lastClone = clone;
13853          }
13854        }
13855        if (split && (!format.mixed || !dom.isBlock(formatRoot))) {
13856          container = (_a = dom.split(formatRoot, container)) !== null && _a !== void 0 ? _a : container;
13857        }
13858        if (lastClone && firstClone) {
13859          (_b = target.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(lastClone, target);
13860          firstClone.appendChild(target);
13861          if (isInlineFormat(format)) {
13862            mergeSiblings(editor, format, vars, lastClone);
13863          }
13864        }
13865      }
13866      return container;
13867    };
13868    const remove$2 = (ed, name, vars, node, similar) => {
13869      const formatList = ed.formatter.get(name);
13870      const format = formatList[0];
13871      const dom = ed.dom;
13872      const selection = ed.selection;
13873      const splitToFormatRoot = container => {
13874        const formatRoot = findFormatRoot(ed, container, name, vars, similar);
13875        return wrapAndSplit(ed, formatList, formatRoot, container, container, true, format, vars);
13876      };
13877      const isRemoveBookmarkNode = node => isBookmarkNode$1(node) && isElement$6(node) && (node.id === '_start' || node.id === '_end');
13878      const removeNodeFormat = node => exists(formatList, fmt => removeFormat$1(ed, fmt, vars, node, node));
13879      const process = node => {
13880        const children = from(node.childNodes);
13881        const removed = removeNodeFormat(node);
13882        const currentNodeMatches = removed || exists(formatList, f => matchName(dom, node, f));
13883        const parentNode = node.parentNode;
13884        if (!currentNodeMatches && isNonNullable(parentNode) && shouldExpandToSelector(format)) {
13885          removeNodeFormat(parentNode);
13886        }
13887        if (format.deep) {
13888          if (children.length) {
13889            for (let i = 0; i < children.length; i++) {
13890              process(children[i]);
13891            }
13892          }
13893        }
13894        const textDecorations = [
13895          'underline',
13896          'line-through',
13897          'overline'
13898        ];
13899        each$e(textDecorations, decoration => {
13900          if (isElement$6(node) && ed.dom.getStyle(node, 'text-decoration') === decoration && node.parentNode && getTextDecoration(dom, node.parentNode) === decoration) {
13901            removeFormat$1(ed, {
13902              deep: false,
13903              exact: true,
13904              inline: 'span',
13905              styles: { textDecoration: decoration }
13906            }, undefined, node);
13907          }
13908        });
13909      };
13910      const unwrap = start => {
13911        const node = dom.get(start ? '_start' : '_end');
13912        if (node) {
13913          let out = node[start ? 'firstChild' : 'lastChild'];
13914          if (isRemoveBookmarkNode(out)) {
13915            out = out[start ? 'firstChild' : 'lastChild'];
13916          }
13917          if (isText$a(out) && out.data.length === 0) {
13918            out = start ? node.previousSibling || node.nextSibling : node.nextSibling || node.previousSibling;
13919          }
13920          dom.remove(node, true);
13921          return out;
13922        } else {
13923          return null;
13924        }
13925      };
13926      const removeRngStyle = rng => {
13927        let startContainer;
13928        let endContainer;
13929        let expandedRng = expandRng(dom, rng, formatList, rng.collapsed);
13930        if (format.split) {
13931          expandedRng = split(expandedRng);
13932          startContainer = getContainer(ed, expandedRng, true);
13933          endContainer = getContainer(ed, expandedRng);
13934          if (startContainer !== endContainer) {
13935            startContainer = normalizeTableSelection(startContainer, true);
13936            endContainer = normalizeTableSelection(endContainer, false);
13937            if (isChildOfInlineParent(dom, startContainer, endContainer)) {
13938              const marker = Optional.from(startContainer.firstChild).getOr(startContainer);
13939              splitToFormatRoot(wrapWithSiblings(dom, marker, true, 'span', {
13940                'id': '_start',
13941                'data-mce-type': 'bookmark'
13942              }));
13943              unwrap(true);
13944              return;
13945            }
13946            if (isChildOfInlineParent(dom, endContainer, startContainer)) {
13947              const marker = Optional.from(endContainer.lastChild).getOr(endContainer);
13948              splitToFormatRoot(wrapWithSiblings(dom, marker, false, 'span', {
13949                'id': '_end',
13950                'data-mce-type': 'bookmark'
13951              }));
13952              unwrap(false);
13953              return;
13954            }
13955            startContainer = wrap$1(dom, startContainer, 'span', {
13956              'id': '_start',
13957              'data-mce-type': 'bookmark'
13958            });
13959            endContainer = wrap$1(dom, endContainer, 'span', {
13960              'id': '_end',
13961              'data-mce-type': 'bookmark'
13962            });
13963            const newRng = dom.createRng();
13964            newRng.setStartAfter(startContainer);
13965            newRng.setEndBefore(endContainer);
13966            walk$3(dom, newRng, nodes => {
13967              each$e(nodes, n => {
13968                if (!isBookmarkNode$1(n) && !isBookmarkNode$1(n.parentNode)) {
13969                  splitToFormatRoot(n);
13970                }
13971              });
13972            });
13973            splitToFormatRoot(startContainer);
13974            splitToFormatRoot(endContainer);
13975            startContainer = unwrap(true);
13976            endContainer = unwrap();
13977          } else {
13978            startContainer = endContainer = splitToFormatRoot(startContainer);
13979          }
13980          expandedRng.startContainer = startContainer.parentNode ? startContainer.parentNode : startContainer;
13981          expandedRng.startOffset = dom.nodeIndex(startContainer);
13982          expandedRng.endContainer = endContainer.parentNode ? endContainer.parentNode : endContainer;
13983          expandedRng.endOffset = dom.nodeIndex(endContainer) + 1;
13984        }
13985        walk$3(dom, expandedRng, nodes => {
13986          each$e(nodes, process);
13987        });
13988      };
13989      if (node) {
13990        if (isNode(node)) {
13991          const rng = dom.createRng();
13992          rng.setStartBefore(node);
13993          rng.setEndAfter(node);
13994          removeRngStyle(rng);
13995        } else {
13996          removeRngStyle(node);
13997        }
13998        fireFormatRemove(ed, name, node, vars);
13999        return;
14000      }
14001      if (!selection.isCollapsed() || !isInlineFormat(format) || getCellsFromEditor(ed).length) {
14002        preserveSelection(ed, () => runOnRanges(ed, removeRngStyle), startNode => isInlineFormat(format) && match$2(ed, name, vars, startNode));
14003        ed.nodeChanged();
14004      } else {
14005        removeCaretFormat(ed, name, vars, similar);
14006      }
14007      removeListStyleFormats(ed, name, vars);
14008      fireFormatRemove(ed, name, node, vars);
14009    };
14010
14011    const each$6 = Tools.each;
14012    const mergeTextDecorationsAndColor = (dom, format, vars, node) => {
14013      const processTextDecorationsAndColor = n => {
14014        if (isElement$6(n) && isElement$6(n.parentNode) && isEditable$2(n)) {
14015          const parentTextDecoration = getTextDecoration(dom, n.parentNode);
14016          if (dom.getStyle(n, 'color') && parentTextDecoration) {
14017            dom.setStyle(n, 'text-decoration', parentTextDecoration);
14018          } else if (dom.getStyle(n, 'text-decoration') === parentTextDecoration) {
14019            dom.setStyle(n, 'text-decoration', null);
14020          }
14021        }
14022      };
14023      if (format.styles && (format.styles.color || format.styles.textDecoration)) {
14024        Tools.walk(node, processTextDecorationsAndColor, 'childNodes');
14025        processTextDecorationsAndColor(node);
14026      }
14027    };
14028    const mergeBackgroundColorAndFontSize = (dom, format, vars, node) => {
14029      if (format.styles && format.styles.backgroundColor) {
14030        const hasFontSize = hasStyle(dom, 'fontSize');
14031        processChildElements(node, elm => hasFontSize(elm) && isEditable$2(elm), applyStyle(dom, 'backgroundColor', replaceVars(format.styles.backgroundColor, vars)));
14032      }
14033    };
14034    const mergeSubSup = (dom, format, vars, node) => {
14035      if (isInlineFormat(format) && (format.inline === 'sub' || format.inline === 'sup')) {
14036        const hasFontSize = hasStyle(dom, 'fontSize');
14037        processChildElements(node, elm => hasFontSize(elm) && isEditable$2(elm), applyStyle(dom, 'fontSize', ''));
14038        const inverseTagDescendants = filter$5(dom.select(format.inline === 'sup' ? 'sub' : 'sup', node), isEditable$2);
14039        dom.remove(inverseTagDescendants, true);
14040      }
14041    };
14042    const mergeWithChildren = (editor, formatList, vars, node) => {
14043      each$6(formatList, format => {
14044        if (isInlineFormat(format)) {
14045          each$6(editor.dom.select(format.inline, node), child => {
14046            if (isElementNode(child)) {
14047              removeFormat$1(editor, format, vars, child, format.exact ? child : null);
14048            }
14049          });
14050        }
14051        clearChildStyles(editor.dom, format, node);
14052      });
14053    };
14054    const mergeWithParents = (editor, format, name, vars, node) => {
14055      const parentNode = node.parentNode;
14056      if (matchNode(editor, parentNode, name, vars)) {
14057        if (removeFormat$1(editor, format, vars, node)) {
14058          return;
14059        }
14060      }
14061      if (format.merge_with_parents && parentNode) {
14062        editor.dom.getParent(parentNode, parent => {
14063          if (matchNode(editor, parent, name, vars)) {
14064            removeFormat$1(editor, format, vars, node);
14065            return true;
14066          } else {
14067            return false;
14068          }
14069        });
14070      }
14071    };
14072
14073    const each$5 = Tools.each;
14074    const canFormatBR = (editor, format, node, parentName) => {
14075      if (canFormatEmptyLines(editor) && isInlineFormat(format) && node.parentNode) {
14076        const validBRParentElements = getTextRootBlockElements(editor.schema);
14077        const hasCaretNodeSibling = sibling(SugarElement.fromDom(node), sibling => isCaretNode(sibling.dom));
14078        return hasNonNullableKey(validBRParentElements, parentName) && isEmpty$2(SugarElement.fromDom(node.parentNode), false) && !hasCaretNodeSibling;
14079      } else {
14080        return false;
14081      }
14082    };
14083    const applyStyles = (dom, elm, format, vars) => {
14084      each$5(format.styles, (value, name) => {
14085        dom.setStyle(elm, name, replaceVars(value, vars));
14086      });
14087      if (format.styles) {
14088        const styleVal = dom.getAttrib(elm, 'style');
14089        if (styleVal) {
14090          dom.setAttrib(elm, 'data-mce-style', styleVal);
14091        }
14092      }
14093    };
14094    const applyFormat$1 = (ed, name, vars, node) => {
14095      const formatList = ed.formatter.get(name);
14096      const format = formatList[0];
14097      const isCollapsed = !node && ed.selection.isCollapsed();
14098      const dom = ed.dom;
14099      const selection = ed.selection;
14100      const setElementFormat = (elm, fmt = format) => {
14101        if (isFunction(fmt.onformat)) {
14102          fmt.onformat(elm, fmt, vars, node);
14103        }
14104        applyStyles(dom, elm, fmt, vars);
14105        each$5(fmt.attributes, (value, name) => {
14106          dom.setAttrib(elm, name, replaceVars(value, vars));
14107        });
14108        each$5(fmt.classes, value => {
14109          const newValue = replaceVars(value, vars);
14110          if (!dom.hasClass(elm, newValue)) {
14111            dom.addClass(elm, newValue);
14112          }
14113        });
14114      };
14115      const applyNodeStyle = (formatList, node) => {
14116        let found = false;
14117        each$5(formatList, format => {
14118          if (!isSelectorFormat(format)) {
14119            return false;
14120          }
14121          if (dom.getContentEditable(node) === 'false' && !format.ceFalseOverride) {
14122            return true;
14123          }
14124          if (isNonNullable(format.collapsed) && format.collapsed !== isCollapsed) {
14125            return true;
14126          }
14127          if (dom.is(node, format.selector) && !isCaretNode(node)) {
14128            setElementFormat(node, format);
14129            found = true;
14130            return false;
vendor: 18,703 bytes, lines 14131-14618
14131          }
14132          return true;
14133        });
14134        return found;
14135      };
14136      const createWrapElement = wrapName => {
14137        if (isString(wrapName)) {
14138          const wrapElm = dom.create(wrapName);
14139          setElementFormat(wrapElm);
14140          return wrapElm;
14141        } else {
14142          return null;
14143        }
14144      };
14145      const applyRngStyle = (dom, rng, nodeSpecific) => {
14146        const newWrappers = [];
14147        let contentEditable = true;
14148        const wrapName = format.inline || format.block;
14149        const wrapElm = createWrapElement(wrapName);
14150        const isMatchingWrappingBlock = node => isWrappingBlockFormat(format) && matchNode(ed, node, name, vars);
14151        const canRenameBlock = (node, parentName, isEditableDescendant) => {
14152          const isValidBlockFormatForNode = isNonWrappingBlockFormat(format) && isTextBlock$1(ed.schema, node) && isValid(ed, parentName, wrapName);
14153          return isEditableDescendant && isValidBlockFormatForNode;
14154        };
14155        const canWrapNode = (node, parentName, isEditableDescendant, isWrappableNoneditableElm) => {
14156          const nodeName = node.nodeName.toLowerCase();
14157          const isValidWrapNode = isValid(ed, wrapName, nodeName) && isValid(ed, parentName, wrapName);
14158          const isZwsp$1 = !nodeSpecific && isText$a(node) && isZwsp(node.data);
14159          const isCaret = isCaretNode(node);
14160          const isCorrectFormatForNode = !isInlineFormat(format) || !dom.isBlock(node);
14161          return (isEditableDescendant || isWrappableNoneditableElm) && isValidWrapNode && !isZwsp$1 && !isCaret && isCorrectFormatForNode;
14162        };
14163        walk$3(dom, rng, nodes => {
14164          let currentWrapElm;
14165          const process = node => {
14166            let hasContentEditableState = false;
14167            let lastContentEditable = contentEditable;
14168            let isWrappableNoneditableElm = false;
14169            const parentNode = node.parentNode;
14170            const parentName = parentNode.nodeName.toLowerCase();
14171            const contentEditableValue = dom.getContentEditable(node);
14172            if (isNonNullable(contentEditableValue)) {
14173              lastContentEditable = contentEditable;
14174              contentEditable = contentEditableValue === 'true';
14175              hasContentEditableState = true;
14176              isWrappableNoneditableElm = isWrappableNoneditable(ed, node);
14177            }
14178            const isEditableDescendant = contentEditable && !hasContentEditableState;
14179            if (isBr$6(node) && !canFormatBR(ed, format, node, parentName)) {
14180              currentWrapElm = null;
14181              if (isBlockFormat(format)) {
14182                dom.remove(node);
14183              }
14184              return;
14185            }
14186            if (isMatchingWrappingBlock(node)) {
14187              currentWrapElm = null;
14188              return;
14189            }
14190            if (canRenameBlock(node, parentName, isEditableDescendant)) {
14191              const elm = dom.rename(node, wrapName);
14192              setElementFormat(elm);
14193              newWrappers.push(elm);
14194              currentWrapElm = null;
14195              return;
14196            }
14197            if (isSelectorFormat(format)) {
14198              let found = applyNodeStyle(formatList, node);
14199              if (!found && isNonNullable(parentNode) && shouldExpandToSelector(format)) {
14200                found = applyNodeStyle(formatList, parentNode);
14201              }
14202              if (!isInlineFormat(format) || found) {
14203                currentWrapElm = null;
14204                return;
14205              }
14206            }
14207            if (isNonNullable(wrapElm) && canWrapNode(node, parentName, isEditableDescendant, isWrappableNoneditableElm)) {
14208              if (!currentWrapElm) {
14209                currentWrapElm = dom.clone(wrapElm, false);
14210                parentNode.insertBefore(currentWrapElm, node);
14211                newWrappers.push(currentWrapElm);
14212              }
14213              if (isWrappableNoneditableElm && hasContentEditableState) {
14214                contentEditable = lastContentEditable;
14215              }
14216              currentWrapElm.appendChild(node);
14217            } else {
14218              currentWrapElm = null;
14219              each$e(from(node.childNodes), process);
14220              if (hasContentEditableState) {
14221                contentEditable = lastContentEditable;
14222              }
14223              currentWrapElm = null;
14224            }
14225          };
14226          each$e(nodes, process);
14227        });
14228        if (format.links === true) {
14229          each$e(newWrappers, node => {
14230            const process = node => {
14231              if (node.nodeName === 'A') {
14232                setElementFormat(node, format);
14233              }
14234              each$e(from(node.childNodes), process);
14235            };
14236            process(node);
14237          });
14238        }
14239        each$e(newWrappers, node => {
14240          const getChildCount = node => {
14241            let count = 0;
14242            each$e(node.childNodes, node => {
14243              if (!isEmptyTextNode$1(node) && !isBookmarkNode$1(node)) {
14244                count++;
14245              }
14246            });
14247            return count;
14248          };
14249          const mergeStyles = node => {
14250            const childElement = find$2(node.childNodes, isElementNode$1).filter(child => dom.getContentEditable(child) !== 'false' && matchName(dom, child, format));
14251            return childElement.map(child => {
14252              const clone = dom.clone(child, false);
14253              setElementFormat(clone);
14254              dom.replace(clone, node, true);
14255              dom.remove(child, true);
14256              return clone;
14257            }).getOr(node);
14258          };
14259          const childCount = getChildCount(node);
14260          if ((newWrappers.length > 1 || !dom.isBlock(node)) && childCount === 0) {
14261            dom.remove(node, true);
14262            return;
14263          }
14264          if (isInlineFormat(format) || isBlockFormat(format) && format.wrapper) {
14265            if (!format.exact && childCount === 1) {
14266              node = mergeStyles(node);
14267            }
14268            mergeWithChildren(ed, formatList, vars, node);
14269            mergeWithParents(ed, format, name, vars, node);
14270            mergeBackgroundColorAndFontSize(dom, format, vars, node);
14271            mergeTextDecorationsAndColor(dom, format, vars, node);
14272            mergeSubSup(dom, format, vars, node);
14273            mergeSiblings(ed, format, vars, node);
14274          }
14275        });
14276      };
14277      const targetNode = isNode(node) ? node : selection.getNode();
14278      if (dom.getContentEditable(targetNode) === 'false' && !isWrappableNoneditable(ed, targetNode)) {
14279        node = targetNode;
14280        applyNodeStyle(formatList, node);
14281        fireFormatApply(ed, name, node, vars);
14282        return;
14283      }
14284      if (format) {
14285        if (node) {
14286          if (isNode(node)) {
14287            if (!applyNodeStyle(formatList, node)) {
14288              const rng = dom.createRng();
14289              rng.setStartBefore(node);
14290              rng.setEndAfter(node);
14291              applyRngStyle(dom, expandRng(dom, rng, formatList), true);
14292            }
14293          } else {
14294            applyRngStyle(dom, node, true);
14295          }
14296        } else {
14297          if (!isCollapsed || !isInlineFormat(format) || getCellsFromEditor(ed).length) {
14298            selection.setRng(normalize(selection.getRng()));
14299            preserveSelection(ed, () => {
14300              runOnRanges(ed, (selectionRng, fake) => {
14301                const expandedRng = fake ? selectionRng : expandRng(dom, selectionRng, formatList);
14302                applyRngStyle(dom, expandedRng, false);
14303              });
14304            }, always);
14305            ed.nodeChanged();
14306          } else {
14307            applyCaretFormat(ed, name, vars);
14308          }
14309          getExpandedListItemFormat(ed.formatter, name).each(liFmt => {
14310            each$e(getFullySelectedListItems(ed.selection), li => applyStyles(dom, li, liFmt, vars));
14311          });
14312        }
14313        postProcess$1(name, ed);
14314      }
14315      fireFormatApply(ed, name, node, vars);
14316    };
14317
14318    const hasVars = value => has$2(value, 'vars');
14319    const setup$t = (registeredFormatListeners, editor) => {
14320      registeredFormatListeners.set({});
14321      editor.on('NodeChange', e => {
14322        updateAndFireChangeCallbacks(editor, e.element, registeredFormatListeners.get());
14323      });
14324      editor.on('FormatApply FormatRemove', e => {
14325        const element = Optional.from(e.node).map(nodeOrRange => isNode(nodeOrRange) ? nodeOrRange : nodeOrRange.startContainer).bind(node => isElement$6(node) ? Optional.some(node) : Optional.from(node.parentElement)).getOrThunk(() => fallbackElement(editor));
14326        updateAndFireChangeCallbacks(editor, element, registeredFormatListeners.get());
14327      });
14328    };
14329    const fallbackElement = editor => editor.selection.getStart();
14330    const matchingNode = (editor, parents, format, similar, vars) => {
14331      const isMatchingNode = node => {
14332        const matchingFormat = editor.formatter.matchNode(node, format, vars !== null && vars !== void 0 ? vars : {}, similar);
14333        return !isUndefined(matchingFormat);
14334      };
14335      const isUnableToMatch = node => {
14336        if (matchesUnInheritedFormatSelector(editor, node, format)) {
14337          return true;
14338        } else {
14339          if (!similar) {
14340            return isNonNullable(editor.formatter.matchNode(node, format, vars, true));
14341          } else {
14342            return false;
14343          }
14344        }
14345      };
14346      return findUntil$1(parents, isMatchingNode, isUnableToMatch);
14347    };
14348    const getParents = (editor, elm) => {
14349      const element = elm !== null && elm !== void 0 ? elm : fallbackElement(editor);
14350      return filter$5(getParents$2(editor.dom, element), node => isElement$6(node) && !isBogus$2(node));
14351    };
14352    const updateAndFireChangeCallbacks = (editor, elm, registeredCallbacks) => {
14353      const parents = getParents(editor, elm);
14354      each$d(registeredCallbacks, (data, format) => {
14355        const runIfChanged = spec => {
14356          const match = matchingNode(editor, parents, format, spec.similar, hasVars(spec) ? spec.vars : undefined);
14357          const isSet = match.isSome();
14358          if (spec.state.get() !== isSet) {
14359            spec.state.set(isSet);
14360            const node = match.getOr(elm);
14361            if (hasVars(spec)) {
14362              spec.callback(isSet, {
14363                node,
14364                format,
14365                parents
14366              });
14367            } else {
14368              each$e(spec.callbacks, callback => callback(isSet, {
14369                node,
14370                format,
14371                parents
14372              }));
14373            }
14374          }
14375        };
14376        each$e([
14377          data.withSimilar,
14378          data.withoutSimilar
14379        ], runIfChanged);
14380        each$e(data.withVars, runIfChanged);
14381      });
14382    };
14383    const addListeners = (editor, registeredFormatListeners, formats, callback, similar, vars) => {
14384      const formatChangeItems = registeredFormatListeners.get();
14385      each$e(formats.split(','), format => {
14386        const group = get$a(formatChangeItems, format).getOrThunk(() => {
14387          const base = {
14388            withSimilar: {
14389              state: Cell(false),
14390              similar: true,
14391              callbacks: []
14392            },
14393            withoutSimilar: {
14394              state: Cell(false),
14395              similar: false,
14396              callbacks: []
14397            },
14398            withVars: []
14399          };
14400          formatChangeItems[format] = base;
14401          return base;
14402        });
14403        const getCurrent = () => {
14404          const parents = getParents(editor);
14405          return matchingNode(editor, parents, format, similar, vars).isSome();
14406        };
14407        if (isUndefined(vars)) {
14408          const toAppendTo = similar ? group.withSimilar : group.withoutSimilar;
14409          toAppendTo.callbacks.push(callback);
14410          if (toAppendTo.callbacks.length === 1) {
14411            toAppendTo.state.set(getCurrent());
14412          }
14413        } else {
14414          group.withVars.push({
14415            state: Cell(getCurrent()),
14416            similar,
14417            vars,
14418            callback
14419          });
14420        }
14421      });
14422      registeredFormatListeners.set(formatChangeItems);
14423    };
14424    const removeListeners = (registeredFormatListeners, formats, callback) => {
14425      const formatChangeItems = registeredFormatListeners.get();
14426      each$e(formats.split(','), format => get$a(formatChangeItems, format).each(group => {
14427        formatChangeItems[format] = {
14428          withSimilar: {
14429            ...group.withSimilar,
14430            callbacks: filter$5(group.withSimilar.callbacks, cb => cb !== callback)
14431          },
14432          withoutSimilar: {
14433            ...group.withoutSimilar,
14434            callbacks: filter$5(group.withoutSimilar.callbacks, cb => cb !== callback)
14435          },
14436          withVars: filter$5(group.withVars, item => item.callback !== callback)
14437        };
14438      }));
14439      registeredFormatListeners.set(formatChangeItems);
14440    };
14441    const formatChangedInternal = (editor, registeredFormatListeners, formats, callback, similar, vars) => {
14442      addListeners(editor, registeredFormatListeners, formats, callback, similar, vars);
14443      return { unbind: () => removeListeners(registeredFormatListeners, formats, callback) };
14444    };
14445
14446    const toggle = (editor, name, vars, node) => {
14447      const fmt = editor.formatter.get(name);
14448      if (fmt) {
14449        if (match$2(editor, name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) {
14450          remove$2(editor, name, vars, node);
14451        } else {
14452          applyFormat$1(editor, name, vars, node);
14453        }
14454      }
14455    };
14456
14457    const explode$1 = Tools.explode;
14458    const create$8 = () => {
14459      const filters = {};
14460      const addFilter = (name, callback) => {
14461        each$e(explode$1(name), name => {
14462          if (!has$2(filters, name)) {
14463            filters[name] = {
14464              name,
14465              callbacks: []
14466            };
14467          }
14468          filters[name].callbacks.push(callback);
14469        });
14470      };
14471      const getFilters = () => values(filters);
14472      const removeFilter = (name, callback) => {
14473        each$e(explode$1(name), name => {
14474          if (has$2(filters, name)) {
14475            if (isNonNullable(callback)) {
14476              const filter = filters[name];
14477              const newCallbacks = filter$5(filter.callbacks, c => c !== callback);
14478              if (newCallbacks.length > 0) {
14479                filter.callbacks = newCallbacks;
14480              } else {
14481                delete filters[name];
14482              }
14483            } else {
14484              delete filters[name];
14485            }
14486          }
14487        });
14488      };
14489      return {
14490        addFilter,
14491        getFilters,
14492        removeFilter
14493      };
14494    };
14495
14496    const removeAttrs = (node, names) => {
14497      each$e(names, name => {
14498        node.attr(name, null);
14499      });
14500    };
14501    const addFontToSpansFilter = (domParser, styles, fontSizes) => {
14502      domParser.addNodeFilter('font', nodes => {
14503        each$e(nodes, node => {
14504          const props = styles.parse(node.attr('style'));
14505          const color = node.attr('color');
14506          const face = node.attr('face');
14507          const size = node.attr('size');
14508          if (color) {
14509            props.color = color;
14510          }
14511          if (face) {
14512            props['font-family'] = face;
14513          }
14514          if (size) {
14515            toInt(size).each(num => {
14516              props['font-size'] = fontSizes[num - 1];
14517            });
14518          }
14519          node.name = 'span';
14520          node.attr('style', styles.serialize(props));
14521          removeAttrs(node, [
14522            'color',
14523            'face',
14524            'size'
14525          ]);
14526        });
14527      });
14528    };
14529    const addStrikeFilter = (domParser, schema, styles) => {
14530      domParser.addNodeFilter('strike', nodes => {
14531        const convertToSTag = schema.type !== 'html4';
14532        each$e(nodes, node => {
14533          if (convertToSTag) {
14534            node.name = 's';
14535          } else {
14536            const props = styles.parse(node.attr('style'));
14537            props['text-decoration'] = 'line-through';
14538            node.name = 'span';
14539            node.attr('style', styles.serialize(props));
14540          }
14541        });
14542      });
14543    };
14544    const addFilters = (domParser, settings, schema) => {
14545      var _a;
14546      const styles = Styles();
14547      if (settings.convert_fonts_to_spans) {
14548        addFontToSpansFilter(domParser, styles, Tools.explode((_a = settings.font_size_legacy_values) !== null && _a !== void 0 ? _a : ''));
14549      }
14550      addStrikeFilter(domParser, schema, styles);
14551    };
14552    const register$5 = (domParser, settings, schema) => {
14553      if (settings.inline_styles) {
14554        addFilters(domParser, settings, schema);
14555      }
14556    };
14557
14558    const blobUriToBlob = url => fetch(url).then(res => res.ok ? res.blob() : Promise.reject()).catch(() => Promise.reject({
14559      message: `Cannot convert ${ url } to Blob. Resource might not exist or is inaccessible.`,
14560      uriType: 'blob'
14561    }));
14562    const extractBase64Data = data => {
14563      const matches = /([a-z0-9+\/=\s]+)/i.exec(data);
14564      return matches ? matches[1] : '';
14565    };
14566    const parseDataUri = uri => {
14567      const [type, ...rest] = uri.split(',');
14568      const data = rest.join(',');
14569      const matches = /data:([^/]+\/[^;]+)(;.+)?/.exec(type);
14570      if (matches) {
14571        const base64Encoded = matches[2] === ';base64';
14572        const extractedData = base64Encoded ? extractBase64Data(data) : decodeURIComponent(data);
14573        return Optional.some({
14574          type: matches[1],
14575          data: extractedData,
14576          base64Encoded
14577        });
14578      } else {
14579        return Optional.none();
14580      }
14581    };
14582    const buildBlob = (type, data, base64Encoded = true) => {
14583      let str = data;
14584      if (base64Encoded) {
14585        try {
14586          str = atob(data);
14587        } catch (e) {
14588          return Optional.none();
14589        }
14590      }
14591      const arr = new Uint8Array(str.length);
14592      for (let i = 0; i < arr.length; i++) {
14593        arr[i] = str.charCodeAt(i);
14594      }
14595      return Optional.some(new Blob([arr], { type }));
14596    };
14597    const dataUriToBlob = uri => {
14598      return new Promise((resolve, reject) => {
14599        parseDataUri(uri).bind(({type, data, base64Encoded}) => buildBlob(type, data, base64Encoded)).fold(() => reject('Invalid data URI'), resolve);
14600      });
14601    };
14602    const uriToBlob = url => {
14603      if (startsWith(url, 'blob:')) {
14604        return blobUriToBlob(url);
14605      } else if (startsWith(url, 'data:')) {
14606        return dataUriToBlob(url);
14607      } else {
14608        return Promise.reject('Unknown URI format');
14609      }
14610    };
14611    const blobToDataUri = blob => {
14612      return new Promise((resolve, reject) => {
14613        const reader = new FileReader();
14614        reader.onloadend = () => {
14615          resolve(reader.result);
14616        };
14617        reader.onerror = () => {
14618          var _a;
vendor: 5,071 bytes, lines 14619-14739
14619          reject((_a = reader.error) === null || _a === void 0 ? void 0 : _a.message);
14620        };
14621        reader.readAsDataURL(blob);
14622      });
14623    };
14624
14625    let count$1 = 0;
14626    const uniqueId$1 = prefix => {
14627      return (prefix || 'blobid') + count$1++;
14628    };
14629    const processDataUri = (dataUri, base64Only, generateBlobInfo) => {
14630      return parseDataUri(dataUri).bind(({data, type, base64Encoded}) => {
14631        if (base64Only && !base64Encoded) {
14632          return Optional.none();
14633        } else {
14634          const base64 = base64Encoded ? data : btoa(data);
14635          return generateBlobInfo(base64, type);
14636        }
14637      });
14638    };
14639    const createBlobInfo$1 = (blobCache, blob, base64) => {
14640      const blobInfo = blobCache.create(uniqueId$1(), blob, base64);
14641      blobCache.add(blobInfo);
14642      return blobInfo;
14643    };
14644    const dataUriToBlobInfo = (blobCache, dataUri, base64Only = false) => {
14645      return processDataUri(dataUri, base64Only, (base64, type) => Optional.from(blobCache.getByData(base64, type)).orThunk(() => buildBlob(type, base64).map(blob => createBlobInfo$1(blobCache, blob, base64))));
14646    };
14647    const imageToBlobInfo = (blobCache, imageSrc) => {
14648      const invalidDataUri = () => Promise.reject('Invalid data URI');
14649      if (startsWith(imageSrc, 'blob:')) {
14650        const blobInfo = blobCache.getByUri(imageSrc);
14651        if (isNonNullable(blobInfo)) {
14652          return Promise.resolve(blobInfo);
14653        } else {
14654          return uriToBlob(imageSrc).then(blob => {
14655            return blobToDataUri(blob).then(dataUri => {
14656              return processDataUri(dataUri, false, base64 => {
14657                return Optional.some(createBlobInfo$1(blobCache, blob, base64));
14658              }).getOrThunk(invalidDataUri);
14659            });
14660          });
14661        }
14662      } else if (startsWith(imageSrc, 'data:')) {
14663        return dataUriToBlobInfo(blobCache, imageSrc).fold(invalidDataUri, blobInfo => Promise.resolve(blobInfo));
14664      } else {
14665        return Promise.reject('Unknown image data format');
14666      }
14667    };
14668
14669    const isBogusImage = img => isNonNullable(img.attr('data-mce-bogus'));
14670    const isInternalImageSource = img => img.attr('src') === Env.transparentSrc || isNonNullable(img.attr('data-mce-placeholder'));
14671    const registerBase64ImageFilter = (parser, settings) => {
14672      const {blob_cache: blobCache} = settings;
14673      if (blobCache) {
14674        const processImage = img => {
14675          const inputSrc = img.attr('src');
14676          if (isInternalImageSource(img) || isBogusImage(img) || isNullable(inputSrc)) {
14677            return;
14678          }
14679          dataUriToBlobInfo(blobCache, inputSrc, true).each(blobInfo => {
14680            img.attr('src', blobInfo.blobUri());
14681          });
14682        };
14683        parser.addAttributeFilter('src', nodes => each$e(nodes, processImage));
14684      }
14685    };
14686    const register$4 = (parser, settings) => {
14687      const schema = parser.schema;
14688      if (settings.remove_trailing_brs) {
14689        parser.addNodeFilter('br', (nodes, _, args) => {
14690          const blockElements = Tools.extend({}, schema.getBlockElements());
14691          const nonEmptyElements = schema.getNonEmptyElements();
14692          const whitespaceElements = schema.getWhitespaceElements();
14693          blockElements.body = 1;
14694          const isBlock = node => node.name in blockElements && isTransparentAstInline(schema, node);
14695          for (let i = 0, l = nodes.length; i < l; i++) {
14696            let node = nodes[i];
14697            let parent = node.parent;
14698            if (parent && blockElements[parent.name] && node === parent.lastChild) {
14699              let prev = node.prev;
14700              while (prev) {
14701                const prevName = prev.name;
14702                if (prevName !== 'span' || prev.attr('data-mce-type') !== 'bookmark') {
14703                  if (prevName === 'br') {
14704                    node = null;
14705                  }
14706                  break;
14707                }
14708                prev = prev.prev;
14709              }
14710              if (node) {
14711                node.remove();
14712                if (isEmpty(schema, nonEmptyElements, whitespaceElements, parent)) {
14713                  const elementRule = schema.getElementRule(parent.name);
14714                  if (elementRule) {
14715                    if (elementRule.removeEmpty) {
14716                      parent.remove();
14717                    } else if (elementRule.paddEmpty) {
14718                      paddEmptyNode(args, isBlock, parent);
14719                    }
14720                  }
14721                }
14722              }
14723            } else {
14724              let lastParent = node;
14725              while (parent && parent.firstChild === lastParent && parent.lastChild === lastParent) {
14726                lastParent = parent;
14727                if (blockElements[parent.name]) {
14728                  break;
14729                }
14730                parent = parent.parent;
14731              }
14732              if (lastParent === parent) {
14733                const textNode = new AstNode('#text', 3);
14734                textNode.value = nbsp;
14735                node.replace(textNode);
14736              }
14737            }
14738          }
14739        }
vendor: 14,430 bytes, lines 14739-15302
14739);
14740      }
14741      parser.addAttributeFilter('href', nodes => {
14742        let i = nodes.length;
14743        const appendRel = rel => {
14744          const parts = rel.split(' ').filter(p => p.length > 0);
14745          return parts.concat(['noopener']).sort().join(' ');
14746        };
14747        const addNoOpener = rel => {
14748          const newRel = rel ? Tools.trim(rel) : '';
14749          if (!/\b(noopener)\b/g.test(newRel)) {
14750            return appendRel(newRel);
14751          } else {
14752            return newRel;
14753          }
14754        };
14755        if (!settings.allow_unsafe_link_target) {
14756          while (i--) {
14757            const node = nodes[i];
14758            if (node.name === 'a' && node.attr('target') === '_blank') {
14759              node.attr('rel', addNoOpener(node.attr('rel')));
14760            }
14761          }
14762        }
14763      });
14764      if (!settings.allow_html_in_named_anchor) {
14765        parser.addAttributeFilter('id,name', nodes => {
14766          let i = nodes.length, sibling, prevSibling, parent, node;
14767          while (i--) {
14768            node = nodes[i];
14769            if (node.name === 'a' && node.firstChild && !node.attr('href')) {
14770              parent = node.parent;
14771              sibling = node.lastChild;
14772              while (sibling && parent) {
14773                prevSibling = sibling.prev;
14774                parent.insert(sibling, node);
14775                sibling = prevSibling;
14776              }
14777            }
14778          }
14779        });
14780      }
14781      if (settings.fix_list_elements) {
14782        parser.addNodeFilter('ul,ol', nodes => {
14783          let i = nodes.length, node, parentNode;
14784          while (i--) {
14785            node = nodes[i];
14786            parentNode = node.parent;
14787            if (parentNode && (parentNode.name === 'ul' || parentNode.name === 'ol')) {
14788              if (node.prev && node.prev.name === 'li') {
14789                node.prev.append(node);
14790              } else {
14791                const li = new AstNode('li', 1);
14792                li.attr('style', 'list-style-type: none');
14793                node.wrap(li);
14794              }
14795            }
14796          }
14797        });
14798      }
14799      const validClasses = schema.getValidClasses();
14800      if (settings.validate && validClasses) {
14801        parser.addAttributeFilter('class', nodes => {
14802          var _a;
14803          let i = nodes.length;
14804          while (i--) {
14805            const node = nodes[i];
14806            const clazz = (_a = node.attr('class')) !== null && _a !== void 0 ? _a : '';
14807            const classList = Tools.explode(clazz, ' ');
14808            let classValue = '';
14809            for (let ci = 0; ci < classList.length; ci++) {
14810              const className = classList[ci];
14811              let valid = false;
14812              let validClassesMap = validClasses['*'];
14813              if (validClassesMap && validClassesMap[className]) {
14814                valid = true;
14815              }
14816              validClassesMap = validClasses[node.name];
14817              if (!valid && validClassesMap && validClassesMap[className]) {
14818                valid = true;
14819              }
14820              if (valid) {
14821                if (classValue) {
14822                  classValue += ' ';
14823                }
14824                classValue += className;
14825              }
14826            }
14827            if (!classValue.length) {
14828              classValue = null;
14829            }
14830            node.attr('class', classValue);
14831          }
14832        });
14833      }
14834      registerBase64ImageFilter(parser, settings);
14835    };
14836
14837    function _typeof(obj) {
14838      '@babel/helpers - typeof';
14839      return _typeof = 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator ? function (obj) {
14840        return typeof obj;
14841      } : function (obj) {
14842        return obj && 'function' == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj;
14843      }, _typeof(obj);
14844    }
14845    function _setPrototypeOf(o, p) {
14846      _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
14847        o.__proto__ = p;
14848        return o;
14849      };
14850      return _setPrototypeOf(o, p);
14851    }
14852    function _isNativeReflectConstruct() {
14853      if (typeof Reflect === 'undefined' || !Reflect.construct)
14854        return false;
14855      if (Reflect.construct.sham)
14856        return false;
14857      if (typeof Proxy === 'function')
14858        return true;
14859      try {
14860        Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {
14861        }));
14862        return true;
14863      } catch (e) {
14864        return false;
14865      }
14866    }
14867    function _construct(Parent, args, Class) {
14868      if (_isNativeReflectConstruct()) {
14869        _construct = Reflect.construct;
14870      } else {
14871        _construct = function _construct(Parent, args, Class) {
14872          var a = [null];
14873          a.push.apply(a, args);
14874          var Constructor = Function.bind.apply(Parent, a);
14875          var instance = new Constructor();
14876          if (Class)
14877            _setPrototypeOf(instance, Class.prototype);
14878          return instance;
14879        };
14880      }
14881      return _construct.apply(null, arguments);
14882    }
14883    function _toConsumableArray(arr) {
14884      return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
14885    }
14886    function _arrayWithoutHoles(arr) {
14887      if (Array.isArray(arr))
14888        return _arrayLikeToArray(arr);
14889    }
14890    function _iterableToArray(iter) {
14891      if (typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null || iter['@@iterator'] != null)
14892        return Array.from(iter);
14893    }
14894    function _unsupportedIterableToArray(o, minLen) {
14895      if (!o)
14896        return;
14897      if (typeof o === 'string')
14898        return _arrayLikeToArray(o, minLen);
14899      var n = Object.prototype.toString.call(o).slice(8, -1);
14900      if (n === 'Object' && o.constructor)
14901        n = o.constructor.name;
14902      if (n === 'Map' || n === 'Set')
14903        return Array.from(o);
14904      if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
14905        return _arrayLikeToArray(o, minLen);
14906    }
14907    function _arrayLikeToArray(arr, len) {
14908      if (len == null || len > arr.length)
14909        len = arr.length;
14910      for (var i = 0, arr2 = new Array(len); i < len; i++)
14911        arr2[i] = arr[i];
14912      return arr2;
14913    }
14914    function _nonIterableSpread() {
14915      throw new TypeError('Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.');
14916    }
14917    var hasOwnProperty = Object.hasOwnProperty, setPrototypeOf = Object.setPrototypeOf, isFrozen = Object.isFrozen, getPrototypeOf = Object.getPrototypeOf, getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
14918    var freeze = Object.freeze, seal = Object.seal, create$7 = Object.create;
14919    var _ref = typeof Reflect !== 'undefined' && Reflect, apply = _ref.apply, construct = _ref.construct;
14920    if (!apply) {
14921      apply = function apply(fun, thisValue, args) {
14922        return fun.apply(thisValue, args);
14923      };
14924    }
14925    if (!freeze) {
14926      freeze = function freeze(x) {
14927        return x;
14928      };
14929    }
14930    if (!seal) {
14931      seal = function seal(x) {
14932        return x;
14933      };
14934    }
14935    if (!construct) {
14936      construct = function construct(Func, args) {
14937        return _construct(Func, _toConsumableArray(args));
14938      };
14939    }
14940    var arrayForEach = unapply(Array.prototype.forEach);
14941    var arrayPop = unapply(Array.prototype.pop);
14942    var arrayPush = unapply(Array.prototype.push);
14943    var stringToLowerCase = unapply(String.prototype.toLowerCase);
14944    var stringMatch = unapply(String.prototype.match);
14945    var stringReplace = unapply(String.prototype.replace);
14946    var stringIndexOf = unapply(String.prototype.indexOf);
14947    var stringTrim = unapply(String.prototype.trim);
14948    var regExpTest = unapply(RegExp.prototype.test);
14949    var typeErrorCreate = unconstruct(TypeError);
14950    function unapply(func) {
14951      return function (thisArg) {
14952        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
14953          args[_key - 1] = arguments[_key];
14954        }
14955        return apply(func, thisArg, args);
14956      };
14957    }
14958    function unconstruct(func) {
14959      return function () {
14960        for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
14961          args[_key2] = arguments[_key2];
14962        }
14963        return construct(func, args);
14964      };
14965    }
14966    function addToSet(set, array) {
14967      if (setPrototypeOf) {
14968        setPrototypeOf(set, null);
14969      }
14970      var l = array.length;
14971      while (l--) {
14972        var element = array[l];
14973        if (typeof element === 'string') {
14974          var lcElement = stringToLowerCase(element);
14975          if (lcElement !== element) {
14976            if (!isFrozen(array)) {
14977              array[l] = lcElement;
14978            }
14979            element = lcElement;
14980          }
14981        }
14982        set[element] = true;
14983      }
14984      return set;
14985    }
14986    function clone(object) {
14987      var newObject = create$7(null);
14988      var property;
14989      for (property in object) {
14990        if (apply(hasOwnProperty, object, [property])) {
14991          newObject[property] = object[property];
14992        }
14993      }
14994      return newObject;
14995    }
14996    function lookupGetter(object, prop) {
14997      while (object !== null) {
14998        var desc = getOwnPropertyDescriptor(object, prop);
14999        if (desc) {
15000          if (desc.get) {
15001            return unapply(desc.get);
15002          }
15003          if (typeof desc.value === 'function') {
15004            return unapply(desc.value);
15005          }
15006        }
15007        object = getPrototypeOf(object);
15008      }
15009      function fallbackValue(element) {
15010        console.warn('fallback value for', element);
15011        return null;
15012      }
15013      return fallbackValue;
15014    }
15015    var html$1 = freeze([
15016      'a',
15017      'abbr',
15018      'acronym',
15019      'address',
15020      'area',
15021      'article',
15022      'aside',
15023      'audio',
15024      'b',
15025      'bdi',
15026      'bdo',
15027      'big',
15028      'blink',
15029      'blockquote',
15030      'body',
15031      'br',
15032      'button',
15033      'canvas',
15034      'caption',
15035      'center',
15036      'cite',
15037      'code',
15038      'col',
15039      'colgroup',
15040      'content',
15041      'data',
15042      'datalist',
15043      'dd',
15044      'decorator',
15045      'del',
15046      'details',
15047      'dfn',
15048      'dialog',
15049      'dir',
15050      'div',
15051      'dl',
15052      'dt',
15053      'element',
15054      'em',
15055      'fieldset',
15056      'figcaption',
15057      'figure',
15058      'font',
15059      'footer',
15060      'form',
15061      'h1',
15062      'h2',
15063      'h3',
15064      'h4',
15065      'h5',
15066      'h6',
15067      'head',
15068      'header',
15069      'hgroup',
15070      'hr',
15071      'html',
15072      'i',
15073      'img',
15074      'input',
15075      'ins',
15076      'kbd',
15077      'label',
15078      'legend',
15079      'li',
15080      'main',
15081      'map',
15082      'mark',
15083      'marquee',
15084      'menu',
15085      'menuitem',
15086      'meter',
15087      'nav',
15088      'nobr',
15089      'ol',
15090      'optgroup',
15091      'option',
15092      'output',
15093      'p',
15094      'picture',
15095      'pre',
15096      'progress',
15097      'q',
15098      'rp',
15099      'rt',
15100      'ruby',
15101      's',
15102      'samp',
15103      'section',
15104      'select',
15105      'shadow',
15106      'small',
15107      'source',
15108      'spacer',
15109      'span',
15110      'strike',
15111      'strong',
15112      'style',
15113      'sub',
15114      'summary',
15115      'sup',
15116      'table',
15117      'tbody',
15118      'td',
15119      'template',
15120      'textarea',
15121      'tfoot',
15122      'th',
15123      'thead',
15124      'time',
15125      'tr',
15126      'track',
15127      'tt',
15128      'u',
15129      'ul',
15130      'var',
15131      'video',
15132      'wbr'
15133    ]);
15134    var svg$1 = freeze([
15135      'svg',
15136      'a',
15137      'altglyph',
15138      'altglyphdef',
15139      'altglyphitem',
15140      'animatecolor',
15141      'animatemotion',
15142      'animatetransform',
15143      'circle',
15144      'clippath',
15145      'defs',
15146      'desc',
15147      'ellipse',
15148      'filter',
15149      'font',
15150      'g',
15151      'glyph',
15152      'glyphref',
15153      'hkern',
15154      'image',
15155      'line',
15156      'lineargradient',
15157      'marker',
15158      'mask',
15159      'metadata',
15160      'mpath',
15161      'path',
15162      'pattern',
15163      'polygon',
15164      'polyline',
15165      'radialgradient',
15166      'rect',
15167      'stop',
15168      'style',
15169      'switch',
15170      'symbol',
15171      'text',
15172      'textpath',
15173      'title',
15174      'tref',
15175      'tspan',
15176      'view',
15177      'vkern'
15178    ]);
15179    var svgFilters = freeze([
15180      'feBlend',
15181      'feColorMatrix',
15182      'feComponentTransfer',
15183      'feComposite',
15184      'feConvolveMatrix',
15185      'feDiffuseLighting',
15186      'feDisplacementMap',
15187      'feDistantLight',
15188      'feFlood',
15189      'feFuncA',
15190      'feFuncB',
15191      'feFuncG',
15192      'feFuncR',
15193      'feGaussianBlur',
15194      'feImage',
15195      'feMerge',
15196      'feMergeNode',
15197      'feMorphology',
15198      'feOffset',
15199      'fePointLight',
15200      'feSpecularLighting',
15201      'feSpotLight',
15202      'feTile',
15203      'feTurbulence'
15204    ]);
15205    var svgDisallowed = freeze([
15206      'animate',
15207      'color-profile',
15208      'cursor',
15209      'discard',
15210      'fedropshadow',
15211      'font-face',
15212      'font-face-format',
15213      'font-face-name',
15214      'font-face-src',
15215      'font-face-uri',
15216      'foreignobject',
15217      'hatch',
15218      'hatchpath',
15219      'mesh',
15220      'meshgradient',
15221      'meshpatch',
15222      'meshrow',
15223      'missing-glyph',
15224      'script',
15225      'set',
15226      'solidcolor',
15227      'unknown',
15228      'use'
15229    ]);
15230    var mathMl$1 = freeze([
15231      'math',
15232      'menclose',
15233      'merror',
15234      'mfenced',
15235      'mfrac',
15236      'mglyph',
15237      'mi',
15238      'mlabeledtr',
15239      'mmultiscripts',
15240      'mn',
15241      'mo',
15242      'mover',
15243      'mpadded',
15244      'mphantom',
15245      'mroot',
15246      'mrow',
15247      'ms',
15248      'mspace',
15249      'msqrt',
15250      'mstyle',
15251      'msub',
15252      'msup',
15253      'msubsup',
15254      'mtable',
15255      'mtd',
15256      'mtext',
15257      'mtr',
15258      'munder',
15259      'munderover'
15260    ]);
15261    var mathMlDisallowed = freeze([
15262      'maction',
15263      'maligngroup',
15264      'malignmark',
15265      'mlongdiv',
15266      'mscarries',
15267      'mscarry',
15268      'msgroup',
15269      'mstack',
15270      'msline',
15271      'msrow',
15272      'semantics',
15273      'annotation',
15274      'annotation-xml',
15275      'mprescripts',
15276      'none'
15277    ]);
15278    var text = freeze(['#text']);
15279    var html = freeze([
15280      'accept',
15281      'action',
15282      'align',
15283      'alt',
15284      'autocapitalize',
15285      'autocomplete',
15286      'autopictureinpicture',
15287      'autoplay',
15288      'background',
15289      'bgcolor',
15290      'border',
15291      'capture',
15292      'cellpadding',
15293      'cellspacing',
15294      'checked',
15295      'cite',
15296      'class',
15297      'clear',
15298      'color',
15299      'cols',
15300      'colspan',
15301      'controls',
15302      'controlslist',
vendor: 37,839 bytes, lines 15303-16400
15303      'coords',
15304      'crossorigin',
15305      'datetime',
15306      'decoding',
15307      'default',
15308      'dir',
15309      'disabled',
15310      'disablepictureinpicture',
15311      'disableremoteplayback',
15312      'download',
15313      'draggable',
15314      'enctype',
15315      'enterkeyhint',
15316      'face',
15317      'for',
15318      'headers',
15319      'height',
15320      'hidden',
15321      'high',
15322      'href',
15323      'hreflang',
15324      'id',
15325      'inputmode',
15326      'integrity',
15327      'ismap',
15328      'kind',
15329      'label',
15330      'lang',
15331      'list',
15332      'loading',
15333      'loop',
15334      'low',
15335      'max',
15336      'maxlength',
15337      'media',
15338      'method',
15339      'min',
15340      'minlength',
15341      'multiple',
15342      'muted',
15343      'name',
15344      'nonce',
15345      'noshade',
15346      'novalidate',
15347      'nowrap',
15348      'open',
15349      'optimum',
15350      'pattern',
15351      'placeholder',
15352      'playsinline',
15353      'poster',
15354      'preload',
15355      'pubdate',
15356      'radiogroup',
15357      'readonly',
15358      'rel',
15359      'required',
15360      'rev',
15361      'reversed',
15362      'role',
15363      'rows',
15364      'rowspan',
15365      'spellcheck',
15366      'scope',
15367      'selected',
15368      'shape',
15369      'size',
15370      'sizes',
15371      'span',
15372      'srclang',
15373      'start',
15374      'src',
15375      'srcset',
15376      'step',
15377      'style',
15378      'summary',
15379      'tabindex',
15380      'title',
15381      'translate',
15382      'type',
15383      'usemap',
15384      'valign',
15385      'value',
15386      'width',
15387      'xmlns',
15388      'slot'
15389    ]);
15390    var svg = freeze([
15391      'accent-height',
15392      'accumulate',
15393      'additive',
15394      'alignment-baseline',
15395      'ascent',
15396      'attributename',
15397      'attributetype',
15398      'azimuth',
15399      'basefrequency',
15400      'baseline-shift',
15401      'begin',
15402      'bias',
15403      'by',
15404      'class',
15405      'clip',
15406      'clippathunits',
15407      'clip-path',
15408      'clip-rule',
15409      'color',
15410      'color-interpolation',
15411      'color-interpolation-filters',
15412      'color-profile',
15413      'color-rendering',
15414      'cx',
15415      'cy',
15416      'd',
15417      'dx',
15418      'dy',
15419      'diffuseconstant',
15420      'direction',
15421      'display',
15422      'divisor',
15423      'dur',
15424      'edgemode',
15425      'elevation',
15426      'end',
15427      'fill',
15428      'fill-opacity',
15429      'fill-rule',
15430      'filter',
15431      'filterunits',
15432      'flood-color',
15433      'flood-opacity',
15434      'font-family',
15435      'font-size',
15436      'font-size-adjust',
15437      'font-stretch',
15438      'font-style',
15439      'font-variant',
15440      'font-weight',
15441      'fx',
15442      'fy',
15443      'g1',
15444      'g2',
15445      'glyph-name',
15446      'glyphref',
15447      'gradientunits',
15448      'gradienttransform',
15449      'height',
15450      'href',
15451      'id',
15452      'image-rendering',
15453      'in',
15454      'in2',
15455      'k',
15456      'k1',
15457      'k2',
15458      'k3',
15459      'k4',
15460      'kerning',
15461      'keypoints',
15462      'keysplines',
15463      'keytimes',
15464      'lang',
15465      'lengthadjust',
15466      'letter-spacing',
15467      'kernelmatrix',
15468      'kernelunitlength',
15469      'lighting-color',
15470      'local',
15471      'marker-end',
15472      'marker-mid',
15473      'marker-start',
15474      'markerheight',
15475      'markerunits',
15476      'markerwidth',
15477      'maskcontentunits',
15478      'maskunits',
15479      'max',
15480      'mask',
15481      'media',
15482      'method',
15483      'mode',
15484      'min',
15485      'name',
15486      'numoctaves',
15487      'offset',
15488      'operator',
15489      'opacity',
15490      'order',
15491      'orient',
15492      'orientation',
15493      'origin',
15494      'overflow',
15495      'paint-order',
15496      'path',
15497      'pathlength',
15498      'patterncontentunits',
15499      'patterntransform',
15500      'patternunits',
15501      'points',
15502      'preservealpha',
15503      'preserveaspectratio',
15504      'primitiveunits',
15505      'r',
15506      'rx',
15507      'ry',
15508      'radius',
15509      'refx',
15510      'refy',
15511      'repeatcount',
15512      'repeatdur',
15513      'restart',
15514      'result',
15515      'rotate',
15516      'scale',
15517      'seed',
15518      'shape-rendering',
15519      'specularconstant',
15520      'specularexponent',
15521      'spreadmethod',
15522      'startoffset',
15523      'stddeviation',
15524      'stitchtiles',
15525      'stop-color',
15526      'stop-opacity',
15527      'stroke-dasharray',
15528      'stroke-dashoffset',
15529      'stroke-linecap',
15530      'stroke-linejoin',
15531      'stroke-miterlimit',
15532      'stroke-opacity',
15533      'stroke',
15534      'stroke-width',
15535      'style',
15536      'surfacescale',
15537      'systemlanguage',
15538      'tabindex',
15539      'targetx',
15540      'targety',
15541      'transform',
15542      'transform-origin',
15543      'text-anchor',
15544      'text-decoration',
15545      'text-rendering',
15546      'textlength',
15547      'type',
15548      'u1',
15549      'u2',
15550      'unicode',
15551      'values',
15552      'viewbox',
15553      'visibility',
15554      'version',
15555      'vert-adv-y',
15556      'vert-origin-x',
15557      'vert-origin-y',
15558      'width',
15559      'word-spacing',
15560      'wrap',
15561      'writing-mode',
15562      'xchannelselector',
15563      'ychannelselector',
15564      'x',
15565      'x1',
15566      'x2',
15567      'xmlns',
15568      'y',
15569      'y1',
15570      'y2',
15571      'z',
15572      'zoomandpan'
15573    ]);
15574    var mathMl = freeze([
15575      'accent',
15576      'accentunder',
15577      'align',
15578      'bevelled',
15579      'close',
15580      'columnsalign',
15581      'columnlines',
15582      'columnspan',
15583      'denomalign',
15584      'depth',
15585      'dir',
15586      'display',
15587      'displaystyle',
15588      'encoding',
15589      'fence',
15590      'frame',
15591      'height',
15592      'href',
15593      'id',
15594      'largeop',
15595      'length',
15596      'linethickness',
15597      'lspace',
15598      'lquote',
15599      'mathbackground',
15600      'mathcolor',
15601      'mathsize',
15602      'mathvariant',
15603      'maxsize',
15604      'minsize',
15605      'movablelimits',
15606      'notation',
15607      'numalign',
15608      'open',
15609      'rowalign',
15610      'rowlines',
15611      'rowspacing',
15612      'rowspan',
15613      'rspace',
15614      'rquote',
15615      'scriptlevel',
15616      'scriptminsize',
15617      'scriptsizemultiplier',
15618      'selection',
15619      'separator',
15620      'separators',
15621      'stretchy',
15622      'subscriptshift',
15623      'supscriptshift',
15624      'symmetric',
15625      'voffset',
15626      'width',
15627      'xmlns'
15628    ]);
15629    var xml = freeze([
15630      'xlink:href',
15631      'xml:id',
15632      'xlink:title',
15633      'xml:space',
15634      'xmlns:xlink'
15635    ]);
15636    var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
15637    var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
15638    var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/);
15639    var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
15640    var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i);
15641    var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
15642    var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g);
15643    var DOCTYPE_NAME = seal(/^html$/i);
15644    var getGlobal = function getGlobal() {
15645      return typeof window === 'undefined' ? null : window;
15646    };
15647    var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
15648      if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
15649        return null;
15650      }
15651      var suffix = null;
15652      var ATTR_NAME = 'data-tt-policy-suffix';
15653      if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
15654        suffix = document.currentScript.getAttribute(ATTR_NAME);
15655      }
15656      var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
15657      try {
15658        return trustedTypes.createPolicy(policyName, {
15659          createHTML: function createHTML(html) {
15660            return html;
15661          }
15662        });
15663      } catch (_) {
15664        console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
15665        return null;
15666      }
15667    };
15668    function createDOMPurify() {
15669      var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
15670      var DOMPurify = function DOMPurify(root) {
15671        return createDOMPurify(root);
15672      };
15673      DOMPurify.version = '2.3.8';
15674      DOMPurify.removed = [];
15675      if (!window || !window.document || window.document.nodeType !== 9) {
15676        DOMPurify.isSupported = false;
15677        return DOMPurify;
15678      }
15679      var originalDocument = window.document;
15680      var document = window.document;
15681      var DocumentFragment = window.DocumentFragment, HTMLTemplateElement = window.HTMLTemplateElement, Node = window.Node, Element = window.Element, NodeFilter = window.NodeFilter, _window$NamedNodeMap = window.NamedNodeMap, NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap, HTMLFormElement = window.HTMLFormElement, DOMParser = window.DOMParser, trustedTypes = window.trustedTypes;
15682      var ElementPrototype = Element.prototype;
15683      var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
15684      var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
15685      var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
15686      var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
15687      if (typeof HTMLTemplateElement === 'function') {
15688        var template = document.createElement('template');
15689        if (template.content && template.content.ownerDocument) {
15690          document = template.content.ownerDocument;
15691        }
15692      }
15693      var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
15694      var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
15695      var _document = document, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
15696      var importNode = originalDocument.importNode;
15697      var documentMode = {};
15698      try {
15699        documentMode = clone(document).documentMode ? document.documentMode : {};
15700      } catch (_) {
15701      }
15702      var hooks = {};
15703      DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
15704      var MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE;
15705      var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
15706      var ALLOWED_TAGS = null;
15707      var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text)));
15708      var ALLOWED_ATTR = null;
15709      var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml)));
15710      var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
15711        tagNameCheck: {
15712          writable: true,
15713          configurable: false,
15714          enumerable: true,
15715          value: null
15716        },
15717        attributeNameCheck: {
15718          writable: true,
15719          configurable: false,
15720          enumerable: true,
15721          value: null
15722        },
15723        allowCustomizedBuiltInElements: {
15724          writable: true,
15725          configurable: false,
15726          enumerable: true,
15727          value: false
15728        }
15729      }));
15730      var FORBID_TAGS = null;
15731      var FORBID_ATTR = null;
15732      var ALLOW_ARIA_ATTR = true;
15733      var ALLOW_DATA_ATTR = true;
15734      var ALLOW_UNKNOWN_PROTOCOLS = false;
15735      var SAFE_FOR_TEMPLATES = false;
15736      var WHOLE_DOCUMENT = false;
15737      var SET_CONFIG = false;
15738      var FORCE_BODY = false;
15739      var RETURN_DOM = false;
15740      var RETURN_DOM_FRAGMENT = false;
15741      var RETURN_TRUSTED_TYPE = false;
15742      var SANITIZE_DOM = true;
15743      var KEEP_CONTENT = true;
15744      var IN_PLACE = false;
15745      var USE_PROFILES = {};
15746      var FORBID_CONTENTS = null;
15747      var DEFAULT_FORBID_CONTENTS = addToSet({}, [
15748        'annotation-xml',
15749        'audio',
15750        'colgroup',
15751        'desc',
15752        'foreignobject',
15753        'head',
15754        'iframe',
15755        'math',
15756        'mi',
15757        'mn',
15758        'mo',
15759        'ms',
15760        'mtext',
15761        'noembed',
15762        'noframes',
15763        'noscript',
15764        'plaintext',
15765        'script',
15766        'style',
15767        'svg',
15768        'template',
15769        'thead',
15770        'title',
15771        'video',
15772        'xmp'
15773      ]);
15774      var DATA_URI_TAGS = null;
15775      var DEFAULT_DATA_URI_TAGS = addToSet({}, [
15776        'audio',
15777        'video',
15778        'img',
15779        'source',
15780        'image',
15781        'track'
15782      ]);
15783      var URI_SAFE_ATTRIBUTES = null;
15784      var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [
15785        'alt',
15786        'class',
15787        'for',
15788        'id',
15789        'label',
15790        'name',
15791        'pattern',
15792        'placeholder',
15793        'role',
15794        'summary',
15795        'title',
15796        'value',
15797        'style',
15798        'xmlns'
15799      ]);
15800      var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
15801      var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
15802      var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
15803      var NAMESPACE = HTML_NAMESPACE;
15804      var IS_EMPTY_INPUT = false;
15805      var PARSER_MEDIA_TYPE;
15806      var SUPPORTED_PARSER_MEDIA_TYPES = [
15807        'application/xhtml+xml',
15808        'text/html'
15809      ];
15810      var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
15811      var transformCaseFunc;
15812      var CONFIG = null;
15813      var formElement = document.createElement('form');
15814      var isRegexOrFunction = function isRegexOrFunction(testValue) {
15815        return testValue instanceof RegExp || testValue instanceof Function;
15816      };
15817      var _parseConfig = function _parseConfig(cfg) {
15818        if (CONFIG && CONFIG === cfg) {
15819          return;
15820        }
15821        if (!cfg || _typeof(cfg) !== 'object') {
15822          cfg = {};
15823        }
15824        cfg = clone(cfg);
15825        ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
15826        ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
15827        URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
15828        DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
15829        FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
15830        FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
15831        FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
15832        USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
15833        ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
15834        ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
15835        ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
15836        SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
15837        WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
15838        RETURN_DOM = cfg.RETURN_DOM || false;
15839        RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
15840        RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
15841        FORCE_BODY = cfg.FORCE_BODY || false;
15842        SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
15843        KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
15844        IN_PLACE = cfg.IN_PLACE || false;
15845        IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
15846        NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
15847        if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
15848          CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
15849        }
15850        if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
15851          CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
15852        }
15853        if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
15854          CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
15855        }
15856        PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
15857        transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
15858          return x;
15859        } : stringToLowerCase;
15860        if (SAFE_FOR_TEMPLATES) {
15861          ALLOW_DATA_ATTR = false;
15862        }
15863        if (RETURN_DOM_FRAGMENT) {
15864          RETURN_DOM = true;
15865        }
15866        if (USE_PROFILES) {
15867          ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
15868          ALLOWED_ATTR = [];
15869          if (USE_PROFILES.html === true) {
15870            addToSet(ALLOWED_TAGS, html$1);
15871            addToSet(ALLOWED_ATTR, html);
15872          }
15873          if (USE_PROFILES.svg === true) {
15874            addToSet(ALLOWED_TAGS, svg$1);
15875            addToSet(ALLOWED_ATTR, svg);
15876            addToSet(ALLOWED_ATTR, xml);
15877          }
15878          if (USE_PROFILES.svgFilters === true) {
15879            addToSet(ALLOWED_TAGS, svgFilters);
15880            addToSet(ALLOWED_ATTR, svg);
15881            addToSet(ALLOWED_ATTR, xml);
15882          }
15883          if (USE_PROFILES.mathMl === true) {
15884            addToSet(ALLOWED_TAGS, mathMl$1);
15885            addToSet(ALLOWED_ATTR, mathMl);
15886            addToSet(ALLOWED_ATTR, xml);
15887          }
15888        }
15889        if (cfg.ADD_TAGS) {
15890          if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
15891            ALLOWED_TAGS = clone(ALLOWED_TAGS);
15892          }
15893          addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
15894        }
15895        if (cfg.ADD_ATTR) {
15896          if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
15897            ALLOWED_ATTR = clone(ALLOWED_ATTR);
15898          }
15899          addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
15900        }
15901        if (cfg.ADD_URI_SAFE_ATTR) {
15902          addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
15903        }
15904        if (cfg.FORBID_CONTENTS) {
15905          if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
15906            FORBID_CONTENTS = clone(FORBID_CONTENTS);
15907          }
15908          addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
15909        }
15910        if (KEEP_CONTENT) {
15911          ALLOWED_TAGS['#text'] = true;
15912        }
15913        if (WHOLE_DOCUMENT) {
15914          addToSet(ALLOWED_TAGS, [
15915            'html',
15916            'head',
15917            'body'
15918          ]);
15919        }
15920        if (ALLOWED_TAGS.table) {
15921          addToSet(ALLOWED_TAGS, ['tbody']);
15922          delete FORBID_TAGS.tbody;
15923        }
15924        if (freeze) {
15925          freeze(cfg);
15926        }
15927        CONFIG = cfg;
15928      };
15929      var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [
15930        'mi',
15931        'mo',
15932        'mn',
15933        'ms',
15934        'mtext'
15935      ]);
15936      var HTML_INTEGRATION_POINTS = addToSet({}, [
15937        'foreignobject',
15938        'desc',
15939        'title',
15940        'annotation-xml'
15941      ]);
15942      var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [
15943        'title',
15944        'style',
15945        'font',
15946        'a',
15947        'script'
15948      ]);
15949      var ALL_SVG_TAGS = addToSet({}, svg$1);
15950      addToSet(ALL_SVG_TAGS, svgFilters);
15951      addToSet(ALL_SVG_TAGS, svgDisallowed);
15952      var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
15953      addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
15954      var _checkValidNamespace = function _checkValidNamespace(element) {
15955        var parent = getParentNode(element);
15956        if (!parent || !parent.tagName) {
15957          parent = {
15958            namespaceURI: HTML_NAMESPACE,
15959            tagName: 'template'
15960          };
15961        }
15962        var tagName = stringToLowerCase(element.tagName);
15963        var parentTagName = stringToLowerCase(parent.tagName);
15964        if (element.namespaceURI === SVG_NAMESPACE) {
15965          if (parent.namespaceURI === HTML_NAMESPACE) {
15966            return tagName === 'svg';
15967          }
15968          if (parent.namespaceURI === MATHML_NAMESPACE) {
15969            return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
15970          }
15971          return Boolean(ALL_SVG_TAGS[tagName]);
15972        }
15973        if (element.namespaceURI === MATHML_NAMESPACE) {
15974          if (parent.namespaceURI === HTML_NAMESPACE) {
15975            return tagName === 'math';
15976          }
15977          if (parent.namespaceURI === SVG_NAMESPACE) {
15978            return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
15979          }
15980          return Boolean(ALL_MATHML_TAGS[tagName]);
15981        }
15982        if (element.namespaceURI === HTML_NAMESPACE) {
15983          if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
15984            return false;
15985          }
15986          if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
15987            return false;
15988          }
15989          return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
15990        }
15991        return false;
15992      };
15993      var _forceRemove = function _forceRemove(node) {
15994        arrayPush(DOMPurify.removed, { element: node });
15995        try {
15996          node.parentNode.removeChild(node);
15997        } catch (_) {
15998          try {
15999            node.outerHTML = emptyHTML;
16000          } catch (_) {
16001            node.remove();
16002          }
16003        }
16004      };
16005      var _removeAttribute = function _removeAttribute(name, node) {
16006        try {
16007          arrayPush(DOMPurify.removed, {
16008            attribute: node.getAttributeNode(name),
16009            from: node
16010          });
16011        } catch (_) {
16012          arrayPush(DOMPurify.removed, {
16013            attribute: null,
16014            from: node
16015          });
16016        }
16017        node.removeAttribute(name);
16018        if (name === 'is' && !ALLOWED_ATTR[name]) {
16019          if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
16020            try {
16021              _forceRemove(node);
16022            } catch (_) {
16023            }
16024          } else {
16025            try {
16026              node.setAttribute(name, '');
16027            } catch (_) {
16028            }
16029          }
16030        }
16031      };
16032      var _initDocument = function _initDocument(dirty) {
16033        var doc;
16034        var leadingWhitespace;
16035        if (FORCE_BODY) {
16036          dirty = '<remove></remove>' + dirty;
16037        } else {
16038          var matches = stringMatch(dirty, /^[\r\n\t ]+/);
16039          leadingWhitespace = matches && matches[0];
16040        }
16041        if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
16042          dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
16043        }
16044        var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
16045        if (NAMESPACE === HTML_NAMESPACE) {
16046          try {
16047            doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
16048          } catch (_) {
16049          }
16050        }
16051        if (!doc || !doc.documentElement) {
16052          doc = implementation.createDocument(NAMESPACE, 'template', null);
16053          try {
16054            doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
16055          } catch (_) {
16056          }
16057        }
16058        var body = doc.body || doc.documentElement;
16059        if (dirty && leadingWhitespace) {
16060          body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
16061        }
16062        if (NAMESPACE === HTML_NAMESPACE) {
16063          return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
16064        }
16065        return WHOLE_DOCUMENT ? doc.documentElement : body;
16066      };
16067      var _createIterator = function _createIterator(root) {
16068        return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
16069      };
16070      var _isClobbered = function _isClobbered(elm) {
16071        return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function');
16072      };
16073      var _isNode = function _isNode(object) {
16074        return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
16075      };
16076      var _executeHook = function _executeHook(entryPoint, currentNode, data) {
16077        if (!hooks[entryPoint]) {
16078          return;
16079        }
16080        arrayForEach(hooks[entryPoint], function (hook) {
16081          hook.call(DOMPurify, currentNode, data, CONFIG);
16082        });
16083      };
16084      var _sanitizeElements = function _sanitizeElements(currentNode) {
16085        var content;
16086        _executeHook('beforeSanitizeElements', currentNode, null);
16087        if (_isClobbered(currentNode)) {
16088          _forceRemove(currentNode);
16089          return true;
16090        }
16091        if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
16092          _forceRemove(currentNode);
16093          return true;
16094        }
16095        var tagName = transformCaseFunc(currentNode.nodeName);
16096        _executeHook('uponSanitizeElement', currentNode, {
16097          tagName: tagName,
16098          allowedTags: ALLOWED_TAGS
16099        });
16100        if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
16101          _forceRemove(currentNode);
16102          return true;
16103        }
16104        if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
16105          _forceRemove(currentNode);
16106          return true;
16107        }
16108        if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
16109          if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
16110            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName))
16111              return false;
16112            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName))
16113              return false;
16114          }
16115          if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
16116            var parentNode = getParentNode(currentNode) || currentNode.parentNode;
16117            var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
16118            if (childNodes && parentNode) {
16119              var childCount = childNodes.length;
16120              for (var i = childCount - 1; i >= 0; --i) {
16121                parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
16122              }
16123            }
16124          }
16125          _forceRemove(currentNode);
16126          return true;
16127        }
16128        if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
16129          _forceRemove(currentNode);
16130          return true;
16131        }
16132        if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
16133          _forceRemove(currentNode);
16134          return true;
16135        }
16136        if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
16137          content = currentNode.textContent;
16138          content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
16139          content = stringReplace(content, ERB_EXPR$1, ' ');
16140          if (currentNode.textContent !== content) {
16141            arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
16142            currentNode.textContent = content;
16143          }
16144        }
16145        _executeHook('afterSanitizeElements', currentNode, null);
16146        return false;
16147      };
16148      var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
16149        if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
16150          return false;
16151        }
16152        if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName));
16153        else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName));
16154        else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
16155          if (_basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) || lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value)));
16156          else {
16157            return false;
16158          }
16159        } else if (URI_SAFE_ATTRIBUTES[lcName]);
16160        else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
16161        else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]);
16162        else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
16163        else if (!value);
16164        else {
16165          return false;
16166        }
16167        return true;
16168      };
16169      var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
16170        return tagName.indexOf('-') > 0;
16171      };
16172      var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
16173        var attr;
16174        var value;
16175        var lcName;
16176        var l;
16177        _executeHook('beforeSanitizeAttributes', currentNode, null);
16178        var attributes = currentNode.attributes;
16179        if (!attributes) {
16180          return;
16181        }
16182        var hookEvent = {
16183          attrName: '',
16184          attrValue: '',
16185          keepAttr: true,
16186          allowedAttributes: ALLOWED_ATTR
16187        };
16188        l = attributes.length;
16189        while (l--) {
16190          attr = attributes[l];
16191          var _attr = attr, name = _attr.name, namespaceURI = _attr.namespaceURI;
16192          value = name === 'value' ? attr.value : stringTrim(attr.value);
16193          lcName = transformCaseFunc(name);
16194          var initValue = value;
16195          hookEvent.attrName = lcName;
16196          hookEvent.attrValue = value;
16197          hookEvent.keepAttr = true;
16198          hookEvent.forceKeepAttr = undefined;
16199          _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
16200          value = hookEvent.attrValue;
16201          if (hookEvent.forceKeepAttr) {
16202            continue;
16203          }
16204          if (!hookEvent.keepAttr) {
16205            _removeAttribute(name, currentNode);
16206            continue;
16207          }
16208          if (regExpTest(/\/>/i, value)) {
16209            _removeAttribute(name, currentNode);
16210            continue;
16211          }
16212          if (SAFE_FOR_TEMPLATES) {
16213            value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
16214            value = stringReplace(value, ERB_EXPR$1, ' ');
16215          }
16216          var lcTag = transformCaseFunc(currentNode.nodeName);
16217          if (!_isValidAttribute(lcTag, lcName, value)) {
16218            _removeAttribute(name, currentNode);
16219            continue;
16220          }
16221          if (value !== initValue) {
16222            try {
16223              if (namespaceURI) {
16224                currentNode.setAttributeNS(namespaceURI, name, value);
16225              } else {
16226                currentNode.setAttribute(name, value);
16227              }
16228            } catch (_) {
16229              _removeAttribute(name, currentNode);
16230            }
16231          }
16232        }
16233        _executeHook('afterSanitizeAttributes', currentNode, null);
16234      };
16235      var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
16236        var shadowNode;
16237        var shadowIterator = _createIterator(fragment);
16238        _executeHook('beforeSanitizeShadowDOM', fragment, null);
16239        while (shadowNode = shadowIterator.nextNode()) {
16240          _executeHook('uponSanitizeShadowNode', shadowNode, null);
16241          if (_sanitizeElements(shadowNode)) {
16242            continue;
16243          }
16244          if (shadowNode.content instanceof DocumentFragment) {
16245            _sanitizeShadowDOM(shadowNode.content);
16246          }
16247          _sanitizeAttributes(shadowNode);
16248        }
16249        _executeHook('afterSanitizeShadowDOM', fragment, null);
16250      };
16251      DOMPurify.sanitize = function (dirty, cfg) {
16252        var body;
16253        var importedNode;
16254        var currentNode;
16255        var oldNode;
16256        var returnNode;
16257        IS_EMPTY_INPUT = !dirty;
16258        if (IS_EMPTY_INPUT) {
16259          dirty = '<!-->';
16260        }
16261        if (typeof dirty !== 'string' && !_isNode(dirty)) {
16262          if (typeof dirty.toString !== 'function') {
16263            throw typeErrorCreate('toString is not a function');
16264          } else {
16265            dirty = dirty.toString();
16266            if (typeof dirty !== 'string') {
16267              throw typeErrorCreate('dirty is not a string, aborting');
16268            }
16269          }
16270        }
16271        if (!DOMPurify.isSupported) {
16272          if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
16273            if (typeof dirty === 'string') {
16274              return window.toStaticHTML(dirty);
16275            }
16276            if (_isNode(dirty)) {
16277              return window.toStaticHTML(dirty.outerHTML);
16278            }
16279          }
16280          return dirty;
16281        }
16282        if (!SET_CONFIG) {
16283          _parseConfig(cfg);
16284        }
16285        DOMPurify.removed = [];
16286        if (typeof dirty === 'string') {
16287          IN_PLACE = false;
16288        }
16289        if (IN_PLACE) {
16290          if (dirty.nodeName) {
16291            var tagName = transformCaseFunc(dirty.nodeName);
16292            if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
16293              throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
16294            }
16295          }
16296        } else if (dirty instanceof Node) {
16297          body = _initDocument('<!---->');
16298          importedNode = body.ownerDocument.importNode(dirty, true);
16299          if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
16300            body = importedNode;
16301          } else if (importedNode.nodeName === 'HTML') {
16302            body = importedNode;
16303          } else {
16304            body.appendChild(importedNode);
16305          }
16306        } else {
16307          if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
16308            return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
16309          }
16310          body = _initDocument(dirty);
16311          if (!body) {
16312            return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
16313          }
16314        }
16315        if (body && FORCE_BODY) {
16316          _forceRemove(body.firstChild);
16317        }
16318        var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
16319        while (currentNode = nodeIterator.nextNode()) {
16320          if (currentNode.nodeType === 3 && currentNode === oldNode) {
16321            continue;
16322          }
16323          if (_sanitizeElements(currentNode)) {
16324            continue;
16325          }
16326          if (currentNode.content instanceof DocumentFragment) {
16327            _sanitizeShadowDOM(currentNode.content);
16328          }
16329          _sanitizeAttributes(currentNode);
16330          oldNode = currentNode;
16331        }
16332        oldNode = null;
16333        if (IN_PLACE) {
16334          return dirty;
16335        }
16336        if (RETURN_DOM) {
16337          if (RETURN_DOM_FRAGMENT) {
16338            returnNode = createDocumentFragment.call(body.ownerDocument);
16339            while (body.firstChild) {
16340              returnNode.appendChild(body.firstChild);
16341            }
16342          } else {
16343            returnNode = body;
16344          }
16345          if (ALLOWED_ATTR.shadowroot) {
16346            returnNode = importNode.call(originalDocument, returnNode, true);
16347          }
16348          return returnNode;
16349        }
16350        var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
16351        if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
16352          serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
16353        }
16354        if (SAFE_FOR_TEMPLATES) {
16355          serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
16356          serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
16357        }
16358        return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
16359      };
16360      DOMPurify.setConfig = function (cfg) {
16361        _parseConfig(cfg);
16362        SET_CONFIG = true;
16363      };
16364      DOMPurify.clearConfig = function () {
16365        CONFIG = null;
16366        SET_CONFIG = false;
16367      };
16368      DOMPurify.isValidAttribute = function (tag, attr, value) {
16369        if (!CONFIG) {
16370          _parseConfig({});
16371        }
16372        var lcTag = transformCaseFunc(tag);
16373        var lcName = transformCaseFunc(attr);
16374        return _isValidAttribute(lcTag, lcName, value);
16375      };
16376      DOMPurify.addHook = function (entryPoint, hookFunction) {
16377        if (typeof hookFunction !== 'function') {
16378          return;
16379        }
16380        hooks[entryPoint] = hooks[entryPoint] || [];
16381        arrayPush(hooks[entryPoint], hookFunction);
16382      };
16383      DOMPurify.removeHook = function (entryPoint) {
16384        if (hooks[entryPoint]) {
16385          return arrayPop(hooks[entryPoint]);
16386        }
16387      };
16388      DOMPurify.removeHooks = function (entryPoint) {
16389        if (hooks[entryPoint]) {
16390          hooks[entryPoint] = [];
16391        }
16392      };
16393      DOMPurify.removeAllHooks = function () {
16394        hooks = {};
16395      };
16396      return DOMPurify;
16397    }
16398    var purify = createDOMPurify();
16399
16400    const 
vendor: 3,141 bytes, lines 16400-16490
16400each$4 = Tools.each, trim = Tools.trim;
16401    const queryParts = [
16402      'source',
16403      'protocol',
16404      'authority',
16405      'userInfo',
16406      'user',
16407      'password',
16408      'host',
16409      'port',
16410      'relative',
16411      'path',
16412      'directory',
16413      'file',
16414      'query',
16415      'anchor'
16416    ];
16417    const DEFAULT_PORTS = {
16418      ftp: 21,
16419      http: 80,
16420      https: 443,
16421      mailto: 25
16422    };
16423    const safeSvgDataUrlElements = [
16424      'img',
16425      'video'
16426    ];
16427    const blockSvgDataUris = (allowSvgDataUrls, tagName) => {
16428      if (isNonNullable(allowSvgDataUrls)) {
16429        return !allowSvgDataUrls;
16430      } else {
16431        return isNonNullable(tagName) ? !contains$2(safeSvgDataUrlElements, tagName) : true;
16432      }
16433    };
16434    const decodeUri = encodedUri => {
16435      try {
16436        return decodeURIComponent(encodedUri);
16437      } catch (ex) {
16438        return unescape(encodedUri);
16439      }
16440    };
16441    const isInvalidUri = (settings, uri, tagName) => {
16442      const decodedUri = decodeUri(uri).replace(/\s/g, '');
16443      if (settings.allow_script_urls) {
16444        return false;
16445      } else if (/((java|vb)script|mhtml):/i.test(decodedUri)) {
16446        return true;
16447      } else if (settings.allow_html_data_urls) {
16448        return false;
16449      } else if (/^data:image\//i.test(decodedUri)) {
16450        return blockSvgDataUris(settings.allow_svg_data_urls, tagName) && /^data:image\/svg\+xml/i.test(decodedUri);
16451      } else {
16452        return /^data:/i.test(decodedUri);
16453      }
16454    };
16455    class URI {
16456      constructor(url, settings = {}) {
16457        this.path = '';
16458        this.directory = '';
16459        url = trim(url);
16460        this.settings = settings;
16461        const baseUri = settings.base_uri;
16462        const self = this;
16463        if (/^([\w\-]+):([^\/]{2})/i.test(url) || /^\s*#/.test(url)) {
16464          self.source = url;
16465          return;
16466        }
16467        const isProtocolRelative = url.indexOf('//') === 0;
16468        if (url.indexOf('/') === 0 && !isProtocolRelative) {
16469          url = (baseUri ? baseUri.protocol || 'http' : 'http') + '://mce_host' + url;
16470        }
16471        if (!/^[\w\-]*:?\/\//.test(url)) {
16472          const baseUrl = baseUri ? baseUri.path : new URI(document.location.href).directory;
16473          if ((baseUri === null || baseUri === void 0 ? void 0 : baseUri.protocol) === '') {
16474            url = '//mce_host' + self.toAbsPath(baseUrl, url);
16475          } else {
16476            const match = /([^#?]*)([#?]?.*)/.exec(url);
16477            if (match) {
16478              url = (baseUri && baseUri.protocol || 'http') + '://mce_host' + self.toAbsPath(baseUrl, match[1]) + match[2];
16479            }
16480          }
16481        }
16482        url = url.replace(/@@/g, '(mce_at)');
16483        const urlMatch = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?(\[[a-zA-Z0-9:.%]+\]|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url);
16484        if (urlMatch) {
16485          each$4(queryParts, (v, i) => {
16486            let part = urlMatch[i];
16487            if (part) {
16488              part = part.replace(/\(mce_at\)/g, '@@');
16489            }
16490            self[v] = part;
vendor: 15,763 bytes, lines 16491-16919
16491          });
16492        }
16493        if (baseUri) {
16494          if (!self.protocol) {
16495            self.protocol = baseUri.protocol;
16496          }
16497          if (!self.userInfo) {
16498            self.userInfo = baseUri.userInfo;
16499          }
16500          if (!self.port && self.host === 'mce_host') {
16501            self.port = baseUri.port;
16502          }
16503          if (!self.host || self.host === 'mce_host') {
16504            self.host = baseUri.host;
16505          }
16506          self.source = '';
16507        }
16508        if (isProtocolRelative) {
16509          self.protocol = '';
16510        }
16511      }
16512      static parseDataUri(uri) {
16513        let type;
16514        const uriComponents = decodeURIComponent(uri).split(',');
16515        const matches = /data:([^;]+)/.exec(uriComponents[0]);
16516        if (matches) {
16517          type = matches[1];
16518        }
16519        return {
16520          type,
16521          data: uriComponents[1]
16522        };
16523      }
16524      static isDomSafe(uri, context, options = {}) {
16525        if (options.allow_script_urls) {
16526          return true;
16527        } else {
16528          const decodedUri = Entities.decode(uri).replace(/[\s\u0000-\u001F]+/g, '');
16529          return !isInvalidUri(options, decodedUri, context);
16530        }
16531      }
16532      static getDocumentBaseUrl(loc) {
16533        var _a;
16534        let baseUrl;
16535        if (loc.protocol.indexOf('http') !== 0 && loc.protocol !== 'file:') {
16536          baseUrl = (_a = loc.href) !== null && _a !== void 0 ? _a : '';
16537        } else {
16538          baseUrl = loc.protocol + '//' + loc.host + loc.pathname;
16539        }
16540        if (/^[^:]+:\/\/\/?[^\/]+\//.test(baseUrl)) {
16541          baseUrl = baseUrl.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
16542          if (!/[\/\\]$/.test(baseUrl)) {
16543            baseUrl += '/';
16544          }
16545        }
16546        return baseUrl;
16547      }
16548      setPath(path) {
16549        const pathMatch = /^(.*?)\/?(\w+)?$/.exec(path);
16550        if (pathMatch) {
16551          this.path = pathMatch[0];
16552          this.directory = pathMatch[1];
16553          this.file = pathMatch[2];
16554        }
16555        this.source = '';
16556        this.getURI();
16557      }
16558      toRelative(uri) {
16559        if (uri === './') {
16560          return uri;
16561        }
16562        const relativeUri = new URI(uri, { base_uri: this });
16563        if (relativeUri.host !== 'mce_host' && this.host !== relativeUri.host && relativeUri.host || this.port !== relativeUri.port || this.protocol !== relativeUri.protocol && relativeUri.protocol !== '') {
16564          return relativeUri.getURI();
16565        }
16566        const tu = this.getURI(), uu = relativeUri.getURI();
16567        if (tu === uu || tu.charAt(tu.length - 1) === '/' && tu.substr(0, tu.length - 1) === uu) {
16568          return tu;
16569        }
16570        let output = this.toRelPath(this.path, relativeUri.path);
16571        if (relativeUri.query) {
16572          output += '?' + relativeUri.query;
16573        }
16574        if (relativeUri.anchor) {
16575          output += '#' + relativeUri.anchor;
16576        }
16577        return output;
16578      }
16579      toAbsolute(uri, noHost) {
16580        const absoluteUri = new URI(uri, { base_uri: this });
16581        return absoluteUri.getURI(noHost && this.isSameOrigin(absoluteUri));
16582      }
16583      isSameOrigin(uri) {
16584        if (this.host == uri.host && this.protocol == uri.protocol) {
16585          if (this.port == uri.port) {
16586            return true;
16587          }
16588          const defaultPort = this.protocol ? DEFAULT_PORTS[this.protocol] : null;
16589          if (defaultPort && (this.port || defaultPort) == (uri.port || defaultPort)) {
16590            return true;
16591          }
16592        }
16593        return false;
16594      }
16595      toRelPath(base, path) {
16596        let breakPoint = 0, out = '', i, l;
16597        const normalizedBase = base.substring(0, base.lastIndexOf('/')).split('/');
16598        const items = path.split('/');
16599        if (normalizedBase.length >= items.length) {
16600          for (i = 0, l = normalizedBase.length; i < l; i++) {
16601            if (i >= items.length || normalizedBase[i] !== items[i]) {
16602              breakPoint = i + 1;
16603              break;
16604            }
16605          }
16606        }
16607        if (normalizedBase.length < items.length) {
16608          for (i = 0, l = items.length; i < l; i++) {
16609            if (i >= normalizedBase.length || normalizedBase[i] !== items[i]) {
16610              breakPoint = i + 1;
16611              break;
16612            }
16613          }
16614        }
16615        if (breakPoint === 1) {
16616          return path;
16617        }
16618        for (i = 0, l = normalizedBase.length - (breakPoint - 1); i < l; i++) {
16619          out += '../';
16620        }
16621        for (i = breakPoint - 1, l = items.length; i < l; i++) {
16622          if (i !== breakPoint - 1) {
16623            out += '/' + items[i];
16624          } else {
16625            out += items[i];
16626          }
16627        }
16628        return out;
16629      }
16630      toAbsPath(base, path) {
16631        let nb = 0;
16632        const tr = /\/$/.test(path) ? '/' : '';
16633        const normalizedBase = base.split('/');
16634        const normalizedPath = path.split('/');
16635        const baseParts = [];
16636        each$4(normalizedBase, k => {
16637          if (k) {
16638            baseParts.push(k);
16639          }
16640        });
16641        const pathParts = [];
16642        for (let i = normalizedPath.length - 1; i >= 0; i--) {
16643          if (normalizedPath[i].length === 0 || normalizedPath[i] === '.') {
16644            continue;
16645          }
16646          if (normalizedPath[i] === '..') {
16647            nb++;
16648            continue;
16649          }
16650          if (nb > 0) {
16651            nb--;
16652            continue;
16653          }
16654          pathParts.push(normalizedPath[i]);
16655        }
16656        const i = baseParts.length - nb;
16657        let outPath;
16658        if (i <= 0) {
16659          outPath = reverse(pathParts).join('/');
16660        } else {
16661          outPath = baseParts.slice(0, i).join('/') + '/' + reverse(pathParts).join('/');
16662        }
16663        if (outPath.indexOf('/') !== 0) {
16664          outPath = '/' + outPath;
16665        }
16666        if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) {
16667          outPath += tr;
16668        }
16669        return outPath;
16670      }
16671      getURI(noProtoHost = false) {
16672        let s;
16673        if (!this.source || noProtoHost) {
16674          s = '';
16675          if (!noProtoHost) {
16676            if (this.protocol) {
16677              s += this.protocol + '://';
16678            } else {
16679              s += '//';
16680            }
16681            if (this.userInfo) {
16682              s += this.userInfo + '@';
16683            }
16684            if (this.host) {
16685              s += this.host;
16686            }
16687            if (this.port) {
16688              s += ':' + this.port;
16689            }
16690          }
16691          if (this.path) {
16692            s += this.path;
16693          }
16694          if (this.query) {
16695            s += '?' + this.query;
16696          }
16697          if (this.anchor) {
16698            s += '#' + this.anchor;
16699          }
16700          this.source = s;
16701        }
16702        return this.source;
16703      }
16704    }
16705
16706    const filteredUrlAttrs = Tools.makeMap('src,href,data,background,action,formaction,poster,xlink:href');
16707    const internalElementAttr = 'data-mce-type';
16708    let uid = 0;
16709    const processNode = (node, settings, schema, evt) => {
16710      var _a, _b, _c, _d;
16711      const validate = settings.validate;
16712      const specialElements = schema.getSpecialElements();
16713      if (node.nodeType === COMMENT && !settings.allow_conditional_comments && /^\[if/i.test((_a = node.nodeValue) !== null && _a !== void 0 ? _a : '')) {
16714        node.nodeValue = ' ' + node.nodeValue;
16715      }
16716      const lcTagName = (_b = evt === null || evt === void 0 ? void 0 : evt.tagName) !== null && _b !== void 0 ? _b : node.nodeName.toLowerCase();
16717      if (node.nodeType !== ELEMENT || lcTagName === 'body') {
16718        return;
16719      }
16720      const element = SugarElement.fromDom(node);
16721      const isInternalElement = has$1(element, internalElementAttr);
16722      const bogus = get$9(element, 'data-mce-bogus');
16723      if (!isInternalElement && isString(bogus)) {
16724        if (bogus === 'all') {
16725          remove$6(element);
16726        } else {
16727          unwrap(element);
16728        }
16729        return;
16730      }
16731      const rule = schema.getElementRule(lcTagName);
16732      if (validate && !rule) {
16733        if (has$2(specialElements, lcTagName)) {
16734          remove$6(element);
16735        } else {
16736          unwrap(element);
16737        }
16738        return;
16739      } else {
16740        if (isNonNullable(evt)) {
16741          evt.allowedTags[lcTagName] = true;
16742        }
16743      }
16744      if (validate && rule && !isInternalElement) {
16745        each$e((_c = rule.attributesForced) !== null && _c !== void 0 ? _c : [], attr => {
16746          set$3(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
16747        });
16748        each$e((_d = rule.attributesDefault) !== null && _d !== void 0 ? _d : [], attr => {
16749          if (!has$1(element, attr.name)) {
16750            set$3(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
16751          }
16752        });
16753        if (rule.attributesRequired && !exists(rule.attributesRequired, attr => has$1(element, attr))) {
16754          unwrap(element);
16755          return;
16756        }
16757        if (rule.removeEmptyAttrs && hasNone(element)) {
16758          unwrap(element);
16759          return;
16760        }
16761        if (rule.outputName && rule.outputName !== lcTagName) {
16762          mutate(element, rule.outputName);
16763        }
16764      }
16765    };
16766    const shouldKeepAttribute = (settings, schema, tagName, attrName, attrValue) => !(attrName in filteredUrlAttrs && isInvalidUri(settings, attrValue, tagName)) && (!settings.validate || schema.isValid(tagName, attrName) || startsWith(attrName, 'data-') || startsWith(attrName, 'aria-'));
16767    const isRequiredAttributeOfInternalElement = (ele, attrName) => ele.hasAttribute(internalElementAttr) && (attrName === 'id' || attrName === 'class' || attrName === 'style');
16768    const isBooleanAttribute = (attrName, schema) => attrName in schema.getBoolAttrs();
16769    const filterAttributes = (ele, settings, schema) => {
16770      const {attributes} = ele;
16771      for (let i = attributes.length - 1; i >= 0; i--) {
16772        const attr = attributes[i];
16773        const attrName = attr.name;
16774        const attrValue = attr.value;
16775        if (!shouldKeepAttribute(settings, schema, ele.tagName.toLowerCase(), attrName, attrValue) && !isRequiredAttributeOfInternalElement(ele, attrName)) {
16776          ele.removeAttribute(attrName);
16777        } else if (isBooleanAttribute(attrName, schema)) {
16778          ele.setAttribute(attrName, attrName);
16779        }
16780      }
16781    };
16782    const setupPurify = (settings, schema) => {
16783      const purify$1 = purify();
16784      purify$1.addHook('uponSanitizeElement', (ele, evt) => {
16785        processNode(ele, settings, schema, evt);
16786      });
16787      purify$1.addHook('uponSanitizeAttribute', (ele, evt) => {
16788        const tagName = ele.tagName.toLowerCase();
16789        const {attrName, attrValue} = evt;
16790        evt.keepAttr = shouldKeepAttribute(settings, schema, tagName, attrName, attrValue);
16791        if (evt.keepAttr) {
16792          evt.allowedAttributes[attrName] = true;
16793          if (isBooleanAttribute(attrName, schema)) {
16794            evt.attrValue = attrName;
16795          }
16796          if (settings.allow_svg_data_urls && startsWith(attrValue, 'data:image/svg+xml')) {
16797            evt.forceKeepAttr = true;
16798          }
16799        } else if (isRequiredAttributeOfInternalElement(ele, attrName)) {
16800          evt.forceKeepAttr = true;
16801        }
16802      });
16803      return purify$1;
16804    };
16805    const getPurifyConfig = (settings, mimeType) => {
16806      const basePurifyConfig = {
16807        IN_PLACE: true,
16808        ALLOW_UNKNOWN_PROTOCOLS: true,
16809        ALLOWED_TAGS: [
16810          '#comment',
16811          '#cdata-section',
16812          'body'
16813        ],
16814        ALLOWED_ATTR: []
16815      };
16816      const config = { ...basePurifyConfig };
16817      config.PARSER_MEDIA_TYPE = mimeType;
16818      if (settings.allow_script_urls) {
16819        config.ALLOWED_URI_REGEXP = /.*/;
16820      } else if (settings.allow_html_data_urls) {
16821        config.ALLOWED_URI_REGEXP = /^(?!(\w+script|mhtml):)/i;
16822      }
16823      return config;
16824    };
16825    const getSanitizer = (settings, schema) => {
16826      if (settings.sanitize) {
16827        const purify = setupPurify(settings, schema);
16828        return (body, mimeType) => {
16829          purify.sanitize(body, getPurifyConfig(settings, mimeType));
16830          purify.removed = [];
16831        };
16832      } else {
16833        return (body, _) => {
16834          const nodeIterator = document.createNodeIterator(body, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT);
16835          let node;
16836          while (node = nodeIterator.nextNode()) {
16837            processNode(node, settings, schema);
16838            if (isElement$6(node)) {
16839              filterAttributes(node, settings, schema);
16840            }
16841          }
16842        };
16843      }
16844    };
16845
16846    const makeMap = Tools.makeMap, extend$1 = Tools.extend;
16847    const transferChildren = (parent, nativeParent, specialElements) => {
16848      const parentName = parent.name;
16849      const isSpecial = parentName in specialElements && parentName !== 'title' && parentName !== 'textarea';
16850      const childNodes = nativeParent.childNodes;
16851      for (let ni = 0, nl = childNodes.length; ni < nl; ni++) {
16852        const nativeChild = childNodes[ni];
16853        const child = new AstNode(nativeChild.nodeName.toLowerCase(), nativeChild.nodeType);
16854        if (isElement$6(nativeChild)) {
16855          const attributes = nativeChild.attributes;
16856          for (let ai = 0, al = attributes.length; ai < al; ai++) {
16857            const attr = attributes[ai];
16858            child.attr(attr.name, attr.value);
16859          }
16860        } else if (isText$a(nativeChild)) {
16861          child.value = nativeChild.data;
16862          if (isSpecial) {
16863            child.raw = true;
16864          }
16865        } else if (isComment(nativeChild) || isCData(nativeChild) || isPi(nativeChild)) {
16866          child.value = nativeChild.data;
16867        }
16868        transferChildren(child, nativeChild, specialElements);
16869        parent.append(child);
16870      }
16871    };
16872    const walkTree = (root, preprocessors, postprocessors) => {
16873      const traverseOrder = [];
16874      for (let node = root, lastNode = node; node; lastNode = node, node = node.walk()) {
16875        const tempNode = node;
16876        each$e(preprocessors, preprocess => preprocess(tempNode));
16877        if (isNullable(tempNode.parent) && tempNode !== root) {
16878          node = lastNode;
16879        } else {
16880          traverseOrder.push(tempNode);
16881        }
16882      }
16883      for (let i = traverseOrder.length - 1; i >= 0; i--) {
16884        const node = traverseOrder[i];
16885        each$e(postprocessors, postprocess => postprocess(node));
16886      }
16887    };
16888    const whitespaceCleaner = (root, schema, settings, args) => {
16889      const validate = settings.validate;
16890      const nonEmptyElements = schema.getNonEmptyElements();
16891      const whitespaceElements = schema.getWhitespaceElements();
16892      const blockElements = extend$1(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
16893      const textRootBlockElements = getTextRootBlockElements(schema);
16894      const allWhiteSpaceRegExp = /[ \t\r\n]+/g;
16895      const startWhiteSpaceRegExp = /^[ \t\r\n]+/;
16896      const endWhiteSpaceRegExp = /[ \t\r\n]+$/;
16897      const hasWhitespaceParent = node => {
16898        let tempNode = node.parent;
16899        while (isNonNullable(tempNode)) {
16900          if (tempNode.name in whitespaceElements) {
16901            return true;
16902          } else {
16903            tempNode = tempNode.parent;
16904          }
16905        }
16906        return false;
16907      };
16908      const isTextRootBlockEmpty = node => {
16909        let tempNode = node;
16910        while (isNonNullable(tempNode)) {
16911          if (tempNode.name in textRootBlockElements) {
16912            return isEmpty(schema, nonEmptyElements, whitespaceElements, tempNode);
16913          } else {
16914            tempNode = tempNode.parent;
16915          }
16916        }
16917        return false;
16918      };
16919      const isBlock = node => node.name in blockElements && !isTransparentAstInline
vendor: 13,742 bytes, lines 16919-17292
16919(schema, node);
16920      const isAtEdgeOfBlock = (node, start) => {
16921        const neighbour = start ? node.prev : node.next;
16922        if (isNonNullable(neighbour) || isNullable(node.parent)) {
16923          return false;
16924        }
16925        return isBlock(node.parent) && (node.parent !== root || args.isRootContent === true);
16926      };
16927      const preprocess = node => {
16928        var _a;
16929        if (node.type === 3) {
16930          if (!hasWhitespaceParent(node)) {
16931            let text = (_a = node.value) !== null && _a !== void 0 ? _a : '';
16932            text = text.replace(allWhiteSpaceRegExp, ' ');
16933            if (isLineBreakNode(node.prev, isBlock) || isAtEdgeOfBlock(node, true)) {
16934              text = text.replace(startWhiteSpaceRegExp, '');
16935            }
16936            if (text.length === 0) {
16937              node.remove();
16938            } else {
16939              node.value = text;
16940            }
16941          }
16942        }
16943      };
16944      const postprocess = node => {
16945        var _a;
16946        if (node.type === 1) {
16947          const elementRule = schema.getElementRule(node.name);
16948          if (validate && elementRule) {
16949            const isNodeEmpty = isEmpty(schema, nonEmptyElements, whitespaceElements, node);
16950            if (elementRule.paddInEmptyBlock && isNodeEmpty && isTextRootBlockEmpty(node)) {
16951              paddEmptyNode(args, isBlock, node);
16952            } else if (elementRule.removeEmpty && isNodeEmpty) {
16953              if (isBlock(node)) {
16954                node.remove();
16955              } else {
16956                node.unwrap();
16957              }
16958            } else if (elementRule.paddEmpty && (isNodeEmpty || isPaddedWithNbsp(node))) {
16959              paddEmptyNode(args, isBlock, node);
16960            }
16961          }
16962        } else if (node.type === 3) {
16963          if (!hasWhitespaceParent(node)) {
16964            let text = (_a = node.value) !== null && _a !== void 0 ? _a : '';
16965            if (node.next && isBlock(node.next) || isAtEdgeOfBlock(node, false)) {
16966              text = text.replace(endWhiteSpaceRegExp, '');
16967            }
16968            if (text.length === 0) {
16969              node.remove();
16970            } else {
16971              node.value = text;
16972            }
16973          }
16974        }
16975      };
16976      return [
16977        preprocess,
16978        postprocess
16979      ];
16980    };
16981    const getRootBlockName = (settings, args) => {
16982      var _a;
16983      const name = (_a = args.forced_root_block) !== null && _a !== void 0 ? _a : settings.forced_root_block;
16984      if (name === false) {
16985        return '';
16986      } else if (name === true) {
16987        return 'p';
16988      } else {
16989        return name;
16990      }
16991    };
16992    const DomParser = (settings = {}, schema = Schema()) => {
16993      const nodeFilterRegistry = create$8();
16994      const attributeFilterRegistry = create$8();
16995      const defaultedSettings = {
16996        validate: true,
16997        root_name: 'body',
16998        sanitize: true,
16999        ...settings
17000      };
17001      const parser = new DOMParser();
17002      const sanitize = getSanitizer(defaultedSettings, schema);
17003      const parseAndSanitizeWithContext = (html, rootName, format = 'html') => {
17004        const mimeType = format === 'xhtml' ? 'application/xhtml+xml' : 'text/html';
17005        const isSpecialRoot = has$2(schema.getSpecialElements(), rootName.toLowerCase());
17006        const content = isSpecialRoot ? `<${ rootName }>${ html }</${ rootName }>` : html;
17007        const wrappedHtml = format === 'xhtml' ? `<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>${ content }</body></html>` : `<body>${ content }</body>`;
17008        const body = parser.parseFromString(wrappedHtml, mimeType).body;
17009        sanitize(body, mimeType);
17010        return isSpecialRoot ? body.firstChild : body;
17011      };
17012      const addNodeFilter = nodeFilterRegistry.addFilter;
17013      const getNodeFilters = nodeFilterRegistry.getFilters;
17014      const removeNodeFilter = nodeFilterRegistry.removeFilter;
17015      const addAttributeFilter = attributeFilterRegistry.addFilter;
17016      const getAttributeFilters = attributeFilterRegistry.getFilters;
17017      const removeAttributeFilter = attributeFilterRegistry.removeFilter;
17018      const findInvalidChildren = (node, invalidChildren) => {
17019        if (isInvalid(schema, node)) {
17020          invalidChildren.push(node);
17021        }
17022      };
17023      const isWrappableNode = (blockElements, node) => {
17024        const isInternalElement = isString(node.attr(internalElementAttr));
17025        const isInlineElement = node.type === 1 && (!has$2(blockElements, node.name) && !isTransparentAstBlock(schema, node));
17026        return node.type === 3 || isInlineElement && !isInternalElement;
17027      };
17028      const addRootBlocks = (rootNode, rootBlockName) => {
17029        const blockElements = extend$1(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
17030        const startWhiteSpaceRegExp = /^[ \t\r\n]+/;
17031        const endWhiteSpaceRegExp = /[ \t\r\n]+$/;
17032        let node = rootNode.firstChild, rootBlockNode = null;
17033        const trim = rootBlock => {
17034          var _a, _b;
17035          if (rootBlock) {
17036            node = rootBlock.firstChild;
17037            if (node && node.type === 3) {
17038              node.value = (_a = node.value) === null || _a === void 0 ? void 0 : _a.replace(startWhiteSpaceRegExp, '');
17039            }
17040            node = rootBlock.lastChild;
17041            if (node && node.type === 3) {
17042              node.value = (_b = node.value) === null || _b === void 0 ? void 0 : _b.replace(endWhiteSpaceRegExp, '');
17043            }
17044          }
17045        };
17046        if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) {
17047          return;
17048        }
17049        while (node) {
17050          const next = node.next;
17051          if (isWrappableNode(blockElements, node)) {
17052            if (!rootBlockNode) {
17053              rootBlockNode = new AstNode(rootBlockName, 1);
17054              rootBlockNode.attr(defaultedSettings.forced_root_block_attrs);
17055              rootNode.insert(rootBlockNode, node);
17056              rootBlockNode.append(node);
17057            } else {
17058              rootBlockNode.append(node);
17059            }
17060          } else {
17061            trim(rootBlockNode);
17062            rootBlockNode = null;
17063          }
17064          node = next;
17065        }
17066        trim(rootBlockNode);
17067      };
17068      const parse = (html, args = {}) => {
17069        var _a;
17070        const validate = defaultedSettings.validate;
17071        const rootName = (_a = args.context) !== null && _a !== void 0 ? _a : defaultedSettings.root_name;
17072        const element = parseAndSanitizeWithContext(html, rootName, args.format);
17073        updateChildren(schema, element);
17074        const rootNode = new AstNode(rootName, 11);
17075        transferChildren(rootNode, element, schema.getSpecialElements());
17076        element.innerHTML = '';
17077        const [whitespacePre, whitespacePost] = whitespaceCleaner(rootNode, schema, defaultedSettings, args);
17078        const invalidChildren = [];
17079        const invalidFinder = validate ? node => findInvalidChildren(node, invalidChildren) : noop;
17080        const matches = {
17081          nodes: {},
17082          attributes: {}
17083        };
17084        const matchFinder = node => matchNode$1(getNodeFilters(), getAttributeFilters(), node, matches);
17085        walkTree(rootNode, [
17086          whitespacePre,
17087          matchFinder
17088        ], [
17089          whitespacePost,
17090          invalidFinder
17091        ]);
17092        invalidChildren.reverse();
17093        if (validate && invalidChildren.length > 0) {
17094          if (args.context) {
17095            const {
17096              pass: topLevelChildren,
17097              fail: otherChildren
17098            } = partition$2(invalidChildren, child => child.parent === rootNode);
17099            cleanInvalidNodes(otherChildren, schema, rootNode, matchFinder);
17100            args.invalid = topLevelChildren.length > 0;
17101          } else {
17102            cleanInvalidNodes(invalidChildren, schema, rootNode, matchFinder);
17103          }
17104        }
17105        const rootBlockName = getRootBlockName(defaultedSettings, args);
17106        if (rootBlockName && (rootNode.name === 'body' || args.isRootContent)) {
17107          addRootBlocks(rootNode, rootBlockName);
17108        }
17109        if (!args.invalid) {
17110          runFilters(matches, args);
17111        }
17112        return rootNode;
17113      };
17114      const exports = {
17115        schema,
17116        addAttributeFilter,
17117        getAttributeFilters,
17118        removeAttributeFilter,
17119        addNodeFilter,
17120        getNodeFilters,
17121        removeNodeFilter,
17122        parse
17123      };
17124      register$4(exports, defaultedSettings);
17125      register$5(exports, defaultedSettings, schema);
17126      return exports;
17127    };
17128
17129    const serializeContent = content => isTreeNode(content) ? HtmlSerializer({ validate: false }).serialize(content) : content;
17130    const withSerializedContent = (content, fireEvent, sanitize) => {
17131      const serializedContent = serializeContent(content);
17132      const eventArgs = fireEvent(serializedContent);
17133      if (eventArgs.isDefaultPrevented()) {
17134        return eventArgs;
17135      } else if (isTreeNode(content)) {
17136        if (eventArgs.content !== serializedContent) {
17137          const rootNode = DomParser({
17138            validate: false,
17139            forced_root_block: false,
17140            sanitize
17141          }).parse(eventArgs.content, { context: content.name });
17142          return {
17143            ...eventArgs,
17144            content: rootNode
17145          };
17146        } else {
17147          return {
17148            ...eventArgs,
17149            content
17150          };
17151        }
17152      } else {
17153        return eventArgs;
17154      }
17155    };
17156    const preProcessGetContent = (editor, args) => {
17157      if (args.no_events) {
17158        return Result.value(args);
17159      } else {
17160        const eventArgs = fireBeforeGetContent(editor, args);
17161        if (eventArgs.isDefaultPrevented()) {
17162          return Result.error(fireGetContent(editor, {
17163            content: '',
17164            ...eventArgs
17165          }).content);
17166        } else {
17167          return Result.value(eventArgs);
17168        }
17169      }
17170    };
17171    const postProcessGetContent = (editor, content, args) => {
17172      if (args.no_events) {
17173        return content;
17174      } else {
17175        const processedEventArgs = withSerializedContent(content, content => fireGetContent(editor, {
17176          ...args,
17177          content
17178        }), shouldSanitizeXss(editor));
17179        return processedEventArgs.content;
17180      }
17181    };
17182    const preProcessSetContent = (editor, args) => {
17183      if (args.no_events) {
17184        return Result.value(args);
17185      } else {
17186        const processedEventArgs = withSerializedContent(args.content, content => fireBeforeSetContent(editor, {
17187          ...args,
17188          content
17189        }), shouldSanitizeXss(editor));
17190        if (processedEventArgs.isDefaultPrevented()) {
17191          fireSetContent(editor, processedEventArgs);
17192          return Result.error(undefined);
17193        } else {
17194          return Result.value(processedEventArgs);
17195        }
17196      }
17197    };
17198    const postProcessSetContent = (editor, content, args) => {
17199      if (!args.no_events) {
17200        fireSetContent(editor, {
17201          ...args,
17202          content
17203        });
17204      }
17205    };
17206
17207    const tableModel = (element, width, rows) => ({
17208      element,
17209      width,
17210      rows
17211    });
17212    const tableRow = (element, cells) => ({
17213      element,
17214      cells
17215    });
17216    const cellPosition = (x, y) => ({
17217      x,
17218      y
17219    });
17220    const getSpan = (td, key) => {
17221      return getOpt(td, key).bind(toInt).getOr(1);
17222    };
17223    const fillout = (table, x, y, tr, td) => {
17224      const rowspan = getSpan(td, 'rowspan');
17225      const colspan = getSpan(td, 'colspan');
17226      const rows = table.rows;
17227      for (let y2 = y; y2 < y + rowspan; y2++) {
17228        if (!rows[y2]) {
17229          rows[y2] = tableRow(deep$1(tr), []);
17230        }
17231        for (let x2 = x; x2 < x + colspan; x2++) {
17232          const cells = rows[y2].cells;
17233          cells[x2] = y2 === y && x2 === x ? td : shallow$1(td);
17234        }
17235      }
17236    };
17237    const cellExists = (table, x, y) => {
17238      const rows = table.rows;
17239      const cells = rows[y] ? rows[y].cells : [];
17240      return !!cells[x];
17241    };
17242    const skipCellsX = (table, x, y) => {
17243      while (cellExists(table, x, y)) {
17244        x++;
17245      }
17246      return x;
17247    };
17248    const getWidth = rows => {
17249      return foldl(rows, (acc, row) => {
17250        return row.cells.length > acc ? row.cells.length : acc;
17251      }, 0);
17252    };
17253    const findElementPos = (table, element) => {
17254      const rows = table.rows;
17255      for (let y = 0; y < rows.length; y++) {
17256        const cells = rows[y].cells;
17257        for (let x = 0; x < cells.length; x++) {
17258          if (eq(cells[x], element)) {
17259            return Optional.some(cellPosition(x, y));
17260          }
17261        }
17262      }
17263      return Optional.none();
17264    };
17265    const extractRows = (table, sx, sy, ex, ey) => {
17266      const newRows = [];
17267      const rows = table.rows;
17268      for (let y = sy; y <= ey; y++) {
17269        const cells = rows[y].cells;
17270        const slice = sx < ex ? cells.slice(sx, ex + 1) : cells.slice(ex, sx + 1);
17271        newRows.push(tableRow(rows[y].element, slice));
17272      }
17273      return newRows;
17274    };
17275    const subTable = (table, startPos, endPos) => {
17276      const sx = startPos.x, sy = startPos.y;
17277      const ex = endPos.x, ey = endPos.y;
17278      const newRows = sy < ey ? extractRows(table, sx, sy, ex, ey) : extractRows(table, sx, ey, ex, sy);
17279      return tableModel(table.element, getWidth(newRows), newRows);
17280    };
17281    const createDomTable = (table, rows) => {
17282      const tableElement = shallow$1(table.element);
17283      const tableBody = SugarElement.fromTag('tbody');
17284      append(tableBody, rows);
17285      append$1(tableElement, tableBody);
17286      return tableElement;
17287    };
17288    const modelRowsToDomRows = table => {
17289      return map$3(table.rows, row => {
17290        const cells = map$3(row.cells, cell => {
17291          const td = deep$1(cell);
17292          remove$
17292b(td, 'colspan');
17293          remove$b
vendor: 22,612 bytes, lines 17293-17885
17293(td, 'rowspan');
17294          return td;
17295        });
17296        const tr = shallow$1(row.element);
17297        append(tr, cells);
17298        return tr;
17299      });
17300    };
17301    const fromDom = tableElm => {
17302      const table = tableModel(shallow$1(tableElm), 0, []);
17303      each$e(descendants(tableElm, 'tr'), (tr, y) => {
17304        each$e(descendants(tr, 'td,th'), (td, x) => {
17305          fillout(table, skipCellsX(table, x, y), y, tr, td);
17306        });
17307      });
17308      return tableModel(table.element, getWidth(table.rows), table.rows);
17309    };
17310    const toDom = table => {
17311      return createDomTable(table, modelRowsToDomRows(table));
17312    };
17313    const subsection = (table, startElement, endElement) => {
17314      return findElementPos(table, startElement).bind(startPos => {
17315        return findElementPos(table, endElement).map(endPos => {
17316          return subTable(table, startPos, endPos);
17317        });
17318      });
17319    };
17320
17321    const findParentListContainer = parents => find$2(parents, elm => name(elm) === 'ul' || name(elm) === 'ol');
17322    const getFullySelectedListWrappers = (parents, rng) => find$2(parents, elm => name(elm) === 'li' && hasAllContentsSelected(elm, rng)).fold(constant([]), _li => findParentListContainer(parents).map(listCont => {
17323      const listElm = SugarElement.fromTag(name(listCont));
17324      const listStyles = filter$4(getAllRaw(listCont), (_style, name) => startsWith(name, 'list-style'));
17325      setAll(listElm, listStyles);
17326      return [
17327        SugarElement.fromTag('li'),
17328        listElm
17329      ];
17330    }).getOr([]));
17331    const wrap = (innerElm, elms) => {
17332      const wrapped = foldl(elms, (acc, elm) => {
17333        append$1(elm, acc);
17334        return elm;
17335      }, innerElm);
17336      return elms.length > 0 ? fromElements([wrapped]) : wrapped;
17337    };
17338    const directListWrappers = commonAnchorContainer => {
17339      if (isListItem$1(commonAnchorContainer)) {
17340        return parent(commonAnchorContainer).filter(isList).fold(constant([]), listElm => [
17341          commonAnchorContainer,
17342          listElm
17343        ]);
17344      } else {
17345        return isList(commonAnchorContainer) ? [commonAnchorContainer] : [];
17346      }
17347    };
17348    const getWrapElements = (rootNode, rng) => {
17349      const commonAnchorContainer = SugarElement.fromDom(rng.commonAncestorContainer);
17350      const parents = parentsAndSelf(commonAnchorContainer, rootNode);
17351      const wrapElements = filter$5(parents, isWrapElement);
17352      const listWrappers = getFullySelectedListWrappers(parents, rng);
17353      const allWrappers = wrapElements.concat(listWrappers.length ? listWrappers : directListWrappers(commonAnchorContainer));
17354      return map$3(allWrappers, shallow$1);
17355    };
17356    const emptyFragment = () => fromElements([]);
17357    const getFragmentFromRange = (rootNode, rng) => wrap(SugarElement.fromDom(rng.cloneContents()), getWrapElements(rootNode, rng));
17358    const getParentTable = (rootElm, cell) => ancestor$3(cell, 'table', curry(eq, rootElm));
17359    const getTableFragment = (rootNode, selectedTableCells) => getParentTable(rootNode, selectedTableCells[0]).bind(tableElm => {
17360      const firstCell = selectedTableCells[0];
17361      const lastCell = selectedTableCells[selectedTableCells.length - 1];
17362      const fullTableModel = fromDom(tableElm);
17363      return subsection(fullTableModel, firstCell, lastCell).map(sectionedTableModel => fromElements([toDom(sectionedTableModel)]));
17364    }).getOrThunk(emptyFragment);
17365    const getSelectionFragment = (rootNode, ranges) => ranges.length > 0 && ranges[0].collapsed ? emptyFragment() : getFragmentFromRange(rootNode, ranges[0]);
17366    const read$3 = (rootNode, ranges) => {
17367      const selectedCells = getCellsFromElementOrRanges(ranges, rootNode);
17368      return selectedCells.length > 0 ? getTableFragment(rootNode, selectedCells) : getSelectionFragment(rootNode, ranges);
17369    };
17370
17371    const isCollapsibleWhitespace = (text, index) => index >= 0 && index < text.length && isWhiteSpace(text.charAt(index));
17372    const getInnerText = bin => {
17373      return trim$1(bin.innerText);
17374    };
17375    const getContextNodeName = parentBlockOpt => parentBlockOpt.map(block => block.nodeName).getOr('div').toLowerCase();
17376    const getTextContent = editor => Optional.from(editor.selection.getRng()).map(rng => {
17377      var _a;
17378      const parentBlockOpt = Optional.from(editor.dom.getParent(rng.commonAncestorContainer, editor.dom.isBlock));
17379      const body = editor.getBody();
17380      const contextNodeName = getContextNodeName(parentBlockOpt);
17381      const rangeContentClone = SugarElement.fromDom(rng.cloneContents());
17382      cleanupBogusElements(rangeContentClone);
17383      cleanupInputNames(rangeContentClone);
17384      const bin = editor.dom.add(body, contextNodeName, {
17385        'data-mce-bogus': 'all',
17386        'style': 'overflow: hidden; opacity: 0;'
17387      }, rangeContentClone.dom);
17388      const text = getInnerText(bin);
17389      const nonRenderedText = trim$1((_a = bin.textContent) !== null && _a !== void 0 ? _a : '');
17390      editor.dom.remove(bin);
17391      if (isCollapsibleWhitespace(nonRenderedText, 0) || isCollapsibleWhitespace(nonRenderedText, nonRenderedText.length - 1)) {
17392        const parentBlock = parentBlockOpt.getOr(body);
17393        const parentBlockText = getInnerText(parentBlock);
17394        const textIndex = parentBlockText.indexOf(text);
17395        if (textIndex === -1) {
17396          return text;
17397        } else {
17398          const hasProceedingSpace = isCollapsibleWhitespace(parentBlockText, textIndex - 1);
17399          const hasTrailingSpace = isCollapsibleWhitespace(parentBlockText, textIndex + text.length);
17400          return (hasProceedingSpace ? ' ' : '') + text + (hasTrailingSpace ? ' ' : '');
17401        }
17402      } else {
17403        return text;
17404      }
17405    }).getOr('');
17406    const getSerializedContent = (editor, args) => {
17407      const rng = editor.selection.getRng(), tmpElm = editor.dom.create('body');
17408      const sel = editor.selection.getSel();
17409      const ranges = processRanges(editor, getRanges$1(sel));
17410      const fragment = args.contextual ? read$3(SugarElement.fromDom(editor.getBody()), ranges).dom : rng.cloneContents();
17411      if (fragment) {
17412        tmpElm.appendChild(fragment);
17413      }
17414      return editor.selection.serializer.serialize(tmpElm, args);
17415    };
17416    const extractSelectedContent = (editor, args) => {
17417      if (args.format === 'text') {
17418        return getTextContent(editor);
17419      } else {
17420        const content = getSerializedContent(editor, args);
17421        if (args.format === 'tree') {
17422          return content;
17423        } else {
17424          return editor.selection.isCollapsed() ? '' : content;
17425        }
17426      }
17427    };
17428    const setupArgs$3 = (args, format) => ({
17429      ...args,
17430      format,
17431      get: true,
17432      selection: true,
17433      getInner: true
17434    });
17435    const getSelectedContentInternal = (editor, format, args = {}) => {
17436      const defaultedArgs = setupArgs$3(args, format);
17437      return preProcessGetContent(editor, defaultedArgs).fold(identity, updatedArgs => {
17438        const content = extractSelectedContent(editor, updatedArgs);
17439        return postProcessGetContent(editor, content, updatedArgs);
17440      });
17441    };
17442
17443    const KEEP = 0, INSERT = 1, DELETE = 2;
17444    const diff = (left, right) => {
17445      const size = left.length + right.length + 2;
17446      const vDown = new Array(size);
17447      const vUp = new Array(size);
17448      const snake = (start, end, diag) => {
17449        return {
17450          start,
17451          end,
17452          diag
17453        };
17454      };
17455      const buildScript = (start1, end1, start2, end2, script) => {
17456        const middle = getMiddleSnake(start1, end1, start2, end2);
17457        if (middle === null || middle.start === end1 && middle.diag === end1 - end2 || middle.end === start1 && middle.diag === start1 - start2) {
17458          let i = start1;
17459          let j = start2;
17460          while (i < end1 || j < end2) {
17461            if (i < end1 && j < end2 && left[i] === right[j]) {
17462              script.push([
17463                KEEP,
17464                left[i]
17465              ]);
17466              ++i;
17467              ++j;
17468            } else {
17469              if (end1 - start1 > end2 - start2) {
17470                script.push([
17471                  DELETE,
17472                  left[i]
17473                ]);
17474                ++i;
17475              } else {
17476                script.push([
17477                  INSERT,
17478                  right[j]
17479                ]);
17480                ++j;
17481              }
17482            }
17483          }
17484        } else {
17485          buildScript(start1, middle.start, start2, middle.start - middle.diag, script);
17486          for (let i2 = middle.start; i2 < middle.end; ++i2) {
17487            script.push([
17488              KEEP,
17489              left[i2]
17490            ]);
17491          }
17492          buildScript(middle.end, end1, middle.end - middle.diag, end2, script);
17493        }
17494      };
17495      const buildSnake = (start, diag, end1, end2) => {
17496        let end = start;
17497        while (end - diag < end2 && end < end1 && left[end] === right[end - diag]) {
17498          ++end;
17499        }
17500        return snake(start, end, diag);
17501      };
17502      const getMiddleSnake = (start1, end1, start2, end2) => {
17503        const m = end1 - start1;
17504        const n = end2 - start2;
17505        if (m === 0 || n === 0) {
17506          return null;
17507        }
17508        const delta = m - n;
17509        const sum = n + m;
17510        const offset = (sum % 2 === 0 ? sum : sum + 1) / 2;
17511        vDown[1 + offset] = start1;
17512        vUp[1 + offset] = end1 + 1;
17513        let d, k, i, x, y;
17514        for (d = 0; d <= offset; ++d) {
17515          for (k = -d; k <= d; k += 2) {
17516            i = k + offset;
17517            if (k === -d || k !== d && vDown[i - 1] < vDown[i + 1]) {
17518              vDown[i] = vDown[i + 1];
17519            } else {
17520              vDown[i] = vDown[i - 1] + 1;
17521            }
17522            x = vDown[i];
17523            y = x - start1 + start2 - k;
17524            while (x < end1 && y < end2 && left[x] === right[y]) {
17525              vDown[i] = ++x;
17526              ++y;
17527            }
17528            if (delta % 2 !== 0 && delta - d <= k && k <= delta + d) {
17529              if (vUp[i - delta] <= vDown[i]) {
17530                return buildSnake(vUp[i - delta], k + start1 - start2, end1, end2);
17531              }
17532            }
17533          }
17534          for (k = delta - d; k <= delta + d; k += 2) {
17535            i = k + offset - delta;
17536            if (k === delta - d || k !== delta + d && vUp[i + 1] <= vUp[i - 1]) {
17537              vUp[i] = vUp[i + 1] - 1;
17538            } else {
17539              vUp[i] = vUp[i - 1];
17540            }
17541            x = vUp[i] - 1;
17542            y = x - start1 + start2 - k;
17543            while (x >= start1 && y >= start2 && left[x] === right[y]) {
17544              vUp[i] = x--;
17545              y--;
17546            }
17547            if (delta % 2 === 0 && -d <= k && k <= d) {
17548              if (vUp[i] <= vDown[i + delta]) {
17549                return buildSnake(vUp[i], k + start1 - start2, end1, end2);
17550              }
17551            }
17552          }
17553        }
17554        return null;
17555      };
17556      const script = [];
17557      buildScript(0, left.length, 0, right.length, script);
17558      return script;
17559    };
17560
17561    const getOuterHtml = elm => {
17562      if (isElement$6(elm)) {
17563        return elm.outerHTML;
17564      } else if (isText$a(elm)) {
17565        return Entities.encodeRaw(elm.data, false);
17566      } else if (isComment(elm)) {
17567        return '<!--' + elm.data + '-->';
17568      }
17569      return '';
17570    };
17571    const createFragment = html => {
17572      let node;
17573      const container = document.createElement('div');
17574      const frag = document.createDocumentFragment();
17575      if (html) {
17576        container.innerHTML = html;
17577      }
17578      while (node = container.firstChild) {
17579        frag.appendChild(node);
17580      }
17581      return frag;
17582    };
17583    const insertAt = (elm, html, index) => {
17584      const fragment = createFragment(html);
17585      if (elm.hasChildNodes() && index < elm.childNodes.length) {
17586        const target = elm.childNodes[index];
17587        elm.insertBefore(fragment, target);
17588      } else {
17589        elm.appendChild(fragment);
17590      }
17591    };
17592    const removeAt = (elm, index) => {
17593      if (elm.hasChildNodes() && index < elm.childNodes.length) {
17594        const target = elm.childNodes[index];
17595        elm.removeChild(target);
17596      }
17597    };
17598    const applyDiff = (diff, elm) => {
17599      let index = 0;
17600      each$e(diff, action => {
17601        if (action[0] === KEEP) {
17602          index++;
17603        } else if (action[0] === INSERT) {
17604          insertAt(elm, action[1], index);
17605          index++;
17606        } else if (action[0] === DELETE) {
17607          removeAt(elm, index);
17608        }
17609      });
17610    };
17611    const read$2 = elm => {
17612      return filter$5(map$3(from(elm.childNodes), getOuterHtml), item => {
17613        return item.length > 0;
17614      });
17615    };
17616    const write = (fragments, elm) => {
17617      const currentFragments = map$3(from(elm.childNodes), getOuterHtml);
17618      applyDiff(diff(currentFragments, fragments), elm);
17619      return elm;
17620    };
17621
17622    const lazyTempDocument = cached(() => document.implementation.createHTMLDocument('undo'));
17623    const hasIframes = html => {
17624      return html.indexOf('</iframe>') !== -1;
17625    };
17626    const createFragmentedLevel = fragments => {
17627      return {
17628        type: 'fragmented',
17629        fragments,
17630        content: '',
17631        bookmark: null,
17632        beforeBookmark: null
17633      };
17634    };
17635    const createCompleteLevel = content => {
17636      return {
17637        type: 'complete',
17638        fragments: null,
17639        content,
17640        bookmark: null,
17641        beforeBookmark: null
17642      };
17643    };
17644    const createFromEditor = editor => {
17645      const fragments = read$2(editor.getBody());
17646      const trimmedFragments = bind$3(fragments, html => {
17647        const trimmed = trimInternal(editor.serializer, html);
17648        return trimmed.length > 0 ? [trimmed] : [];
17649      });
17650      const content = trimmedFragments.join('');
17651      return hasIframes(content) ? createFragmentedLevel(trimmedFragments) : createCompleteLevel(content);
17652    };
17653    const applyToEditor = (editor, level, before) => {
17654      const bookmark = before ? level.beforeBookmark : level.bookmark;
17655      if (level.type === 'fragmented') {
17656        write(level.fragments, editor.getBody());
17657      } else {
17658        editor.setContent(level.content, {
17659          format: 'raw',
17660          no_selection: isNonNullable(bookmark) && isPathBookmark(bookmark) ? !bookmark.isFakeCaret : true
17661        });
17662      }
17663      if (bookmark) {
17664        editor.selection.moveToBookmark(bookmark);
17665        editor.selection.scrollIntoView();
17666      }
17667    };
17668    const getLevelContent = level => {
17669      return level.type === 'fragmented' ? level.fragments.join('') : level.content;
17670    };
17671    const getCleanLevelContent = level => {
17672      const elm = SugarElement.fromTag('body', lazyTempDocument());
17673      set$1(elm, getLevelContent(level));
17674      each$e(descendants(elm, '*[data-mce-bogus]'), unwrap);
17675      return get$6(elm);
17676    };
17677    const hasEqualContent = (level1, level2) => getLevelContent(level1) === getLevelContent(level2);
17678    const hasEqualCleanedContent = (level1, level2) => getCleanLevelContent(level1) === getCleanLevelContent(level2);
17679    const isEq$1 = (level1, level2) => {
17680      if (!level1 || !level2) {
17681        return false;
17682      } else if (hasEqualContent(level1, level2)) {
17683        return true;
17684      } else {
17685        return hasEqualCleanedContent(level1, level2);
17686      }
17687    };
17688
17689    const isUnlocked = locks => locks.get() === 0;
17690
17691    const setTyping = (undoManager, typing, locks) => {
17692      if (isUnlocked(locks)) {
17693        undoManager.typing = typing;
17694      }
17695    };
17696    const endTyping = (undoManager, locks) => {
17697      if (undoManager.typing) {
17698        setTyping(undoManager, false, locks);
17699        undoManager.add();
17700      }
17701    };
17702    const endTypingLevelIgnoreLocks = undoManager => {
17703      if (undoManager.typing) {
17704        undoManager.typing = false;
17705        undoManager.add();
17706      }
17707    };
17708
17709    const beforeChange$1 = (editor, locks, beforeBookmark) => {
17710      if (isUnlocked(locks)) {
17711        beforeBookmark.set(getUndoBookmark(editor.selection));
17712      }
17713    };
17714    const addUndoLevel$1 = (editor, undoManager, index, locks, beforeBookmark, level, event) => {
17715      const currentLevel = createFromEditor(editor);
17716      const newLevel = Tools.extend(level || {}, currentLevel);
17717      if (!isUnlocked(locks) || editor.removed) {
17718        return null;
17719      }
17720      const lastLevel = undoManager.data[index.get()];
17721      if (editor.dispatch('BeforeAddUndo', {
17722          level: newLevel,
17723          lastLevel,
17724          originalEvent: event
17725        }).isDefaultPrevented()) {
17726        return null;
17727      }
17728      if (lastLevel && isEq$1(lastLevel, newLevel)) {
17729        return null;
17730      }
17731      if (undoManager.data[index.get()]) {
17732        beforeBookmark.get().each(bm => {
17733          undoManager.data[index.get()].beforeBookmark = bm;
17734        });
17735      }
17736      const customUndoRedoLevels = getCustomUndoRedoLevels(editor);
17737      if (customUndoRedoLevels) {
17738        if (undoManager.data.length > customUndoRedoLevels) {
17739          for (let i = 0; i < undoManager.data.length - 1; i++) {
17740            undoManager.data[i] = undoManager.data[i + 1];
17741          }
17742          undoManager.data.length--;
17743          index.set(undoManager.data.length);
17744        }
17745      }
17746      newLevel.bookmark = getUndoBookmark(editor.selection);
17747      if (index.get() < undoManager.data.length - 1) {
17748        undoManager.data.length = index.get() + 1;
17749      }
17750      undoManager.data.push(newLevel);
17751      index.set(undoManager.data.length - 1);
17752      const args = {
17753        level: newLevel,
17754        lastLevel,
17755        originalEvent: event
17756      };
17757      if (index.get() > 0) {
17758        editor.setDirty(true);
17759        editor.dispatch('AddUndo', args);
17760        editor.dispatch('change', args);
17761      } else {
17762        editor.dispatch('AddUndo', args);
17763      }
17764      return newLevel;
17765    };
17766    const clear$1 = (editor, undoManager, index) => {
17767      undoManager.data = [];
17768      index.set(0);
17769      undoManager.typing = false;
17770      editor.dispatch('ClearUndos');
17771    };
17772    const extra$1 = (editor, undoManager, index, callback1, callback2) => {
17773      if (undoManager.transact(callback1)) {
17774        const bookmark = undoManager.data[index.get()].bookmark;
17775        const lastLevel = undoManager.data[index.get() - 1];
17776        applyToEditor(editor, lastLevel, true);
17777        if (undoManager.transact(callback2)) {
17778          undoManager.data[index.get() - 1].beforeBookmark = bookmark;
17779        }
17780      }
17781    };
17782    const redo$1 = (editor, index, data) => {
17783      let level;
17784      if (index.get() < data.length - 1) {
17785        index.set(index.get() + 1);
17786        level = data[index.get()];
17787        applyToEditor(editor, level, false);
17788        editor.setDirty(true);
17789        editor.dispatch('Redo', { level });
17790      }
17791      return level;
17792    };
17793    const undo$1 = (editor, undoManager, locks, index) => {
17794      let level;
17795      if (undoManager.typing) {
17796        undoManager.add();
17797        undoManager.typing = false;
17798        setTyping(undoManager, false, locks);
17799      }
17800      if (index.get() > 0) {
17801        index.set(index.get() - 1);
17802        level = undoManager.data[index.get()];
17803        applyToEditor(editor, level, true);
17804        editor.setDirty(true);
17805        editor.dispatch('Undo', { level });
17806      }
17807      return level;
17808    };
17809    const reset$1 = undoManager => {
17810      undoManager.clear();
17811      undoManager.add();
17812    };
17813    const hasUndo$1 = (editor, undoManager, index) => index.get() > 0 || undoManager.typing && undoManager.data[0] && !isEq$1(createFromEditor(editor), undoManager.data[0]);
17814    const hasRedo$1 = (undoManager, index) => index.get() < undoManager.data.length - 1 && !undoManager.typing;
17815    const transact$1 = (undoManager, locks, callback) => {
17816      endTyping(undoManager, locks);
17817      undoManager.beforeChange();
17818      undoManager.ignore(callback);
17819      return undoManager.add();
17820    };
17821    const ignore$1 = (locks, callback) => {
17822      try {
17823        locks.set(locks.get() + 1);
17824        callback();
17825      } finally {
17826        locks.set(locks.get() - 1);
17827      }
17828    };
17829
17830    const addVisualInternal = (editor, elm) => {
17831      const dom = editor.dom;
17832      const scope = isNonNullable(elm) ? elm : editor.getBody();
17833      each$e(dom.select('table,a', scope), matchedElm => {
17834        switch (matchedElm.nodeName) {
17835        case 'TABLE':
17836          const cls = getVisualAidsTableClass(editor);
17837          const value = dom.getAttrib(matchedElm, 'border');
17838          if ((!value || value === '0') && editor.hasVisual) {
17839            dom.addClass(matchedElm, cls);
17840          } else {
17841            dom.removeClass(matchedElm, cls);
17842          }
17843          break;
17844        case 'A':
17845          if (!dom.getAttrib(matchedElm, 'href')) {
17846            const value = dom.getAttrib(matchedElm, 'name') || matchedElm.id;
17847            const cls = getVisualAidsAnchorClass(editor);
17848            if (value && editor.hasVisual) {
17849              dom.addClass(matchedElm, cls);
17850            } else {
17851              dom.removeClass(matchedElm, cls);
17852            }
17853          }
17854          break;
17855        }
17856      });
17857      editor.dispatch('VisualAid', {
17858        element: elm,
17859        hasVisual: editor.hasVisual
17860      });
17861    };
17862
17863    const makePlainAdaptor = editor => ({
17864      init: { bindEvents: noop },
17865      undoManager: {
17866        beforeChange: (locks, beforeBookmark) => beforeChange$1(editor, locks, beforeBookmark),
17867        add: (undoManager, index, locks, beforeBookmark, level, event) => addUndoLevel$1(editor, undoManager, index, locks, beforeBookmark, level, event),
17868        undo: (undoManager, locks, index) => undo$1(editor, undoManager, locks, index),
17869        redo: (index, data) => redo$1(editor, index, data),
17870        clear: (undoManager, index) => clear$1(editor, undoManager, index),
17871        reset: undoManager => reset$1(undoManager),
17872        hasUndo: (undoManager, index) => hasUndo$1(editor, undoManager, index),
17873        hasRedo: (undoManager, index) => hasRedo$1(undoManager, index),
17874        transact: (undoManager, locks, callback) => transact$1(undoManager, locks, callback),
17875        ignore: (locks, callback) => ignore$1(locks, callback),
17876        extra: (undoManager, index, callback1, callback2) => extra$1(editor, undoManager, index, callback1, callback2)
17877      },
17878      formatter: {
17879        match: (name, vars, node, similar) => match$2(editor, name, vars, node, similar),
17880        matchAll: (names, vars) => matchAll(editor, names, vars),
17881        matchNode: (node, name, vars, similar) => matchNode(editor, node, name, vars, similar),
17882        canApply: name => canApply(editor, name),
17883        closest: names => closest(editor, names),
17884        apply: (name, vars, node) => applyFormat$1(editor, name, vars, node),
17885        remove: (name, vars, node, similar) => remove
17885$2(editor, name, vars, node, similar),
17886        toggle: (name, vars, node) => toggle(editor, name, vars, node),
17887        formatChanged: (registeredFormatListeners, formats, callback, similar, vars) => formatChangedInternal(editor, registeredFormatListeners, formats, callback, similar, vars)
17888      },
17889      editor: {
17890        getContent: args => getContentInternal(editor, args),
17891        setContent: (content, args) => setContentInternal(editor, content, args),
17892        insertContent: (value, details) => insertHtmlAtCaret(editor, value, details),
17893        addVisual: elm => addVisualInternal(editor, elm)
17894      },
17895      selection: { getContent: (format, args) => getSelectedContentInternal(editor, format, args) },
17896      autocompleter: {
17897        addDecoration: range => create$9(editor, range),
17898        removeDecoration: () => remove$3
vendor: 8,579 bytes, lines 17898-18075
17898(editor, SugarElement.fromDom(editor.getBody()))
17899      },
17900      raw: { getModel: () => Optional.none() }
17901    });
17902    const makeRtcAdaptor = rtcEditor => {
17903      const defaultVars = vars => isObject(vars) ? vars : {};
17904      const {init, undoManager, formatter, editor, selection, autocompleter, raw} = rtcEditor;
17905      return {
17906        init: { bindEvents: init.bindEvents },
17907        undoManager: {
17908          beforeChange: undoManager.beforeChange,
17909          add: undoManager.add,
17910          undo: undoManager.undo,
17911          redo: undoManager.redo,
17912          clear: undoManager.clear,
17913          reset: undoManager.reset,
17914          hasUndo: undoManager.hasUndo,
17915          hasRedo: undoManager.hasRedo,
17916          transact: (_undoManager, _locks, fn) => undoManager.transact(fn),
17917          ignore: (_locks, callback) => undoManager.ignore(callback),
17918          extra: (_undoManager, _index, callback1, callback2) => undoManager.extra(callback1, callback2)
17919        },
17920        formatter: {
17921          match: (name, vars, _node, similar) => formatter.match(name, defaultVars(vars), similar),
17922          matchAll: formatter.matchAll,
17923          matchNode: formatter.matchNode,
17924          canApply: name => formatter.canApply(name),
17925          closest: names => formatter.closest(names),
17926          apply: (name, vars, _node) => formatter.apply(name, defaultVars(vars)),
17927          remove: (name, vars, _node, _similar) => formatter.remove(name, defaultVars(vars)),
17928          toggle: (name, vars, _node) => formatter.toggle(name, defaultVars(vars)),
17929          formatChanged: (_rfl, formats, callback, similar, vars) => formatter.formatChanged(formats, callback, similar, vars)
17930        },
17931        editor: {
17932          getContent: args => editor.getContent(args),
17933          setContent: (content, args) => {
17934            return {
17935              content: editor.setContent(content, args),
17936              html: ''
17937            };
17938          },
17939          insertContent: (content, _details) => {
17940            editor.insertContent(content);
17941            return '';
17942          },
17943          addVisual: editor.addVisual
17944        },
17945        selection: { getContent: (_format, args) => selection.getContent(args) },
17946        autocompleter: {
17947          addDecoration: autocompleter.addDecoration,
17948          removeDecoration: autocompleter.removeDecoration
17949        },
17950        raw: { getModel: () => Optional.some(raw.getRawModel()) }
17951      };
17952    };
17953    const makeNoopAdaptor = () => {
17954      const nul = constant(null);
17955      const empty = constant('');
17956      return {
17957        init: { bindEvents: noop },
17958        undoManager: {
17959          beforeChange: noop,
17960          add: nul,
17961          undo: nul,
17962          redo: nul,
17963          clear: noop,
17964          reset: noop,
17965          hasUndo: never,
17966          hasRedo: never,
17967          transact: nul,
17968          ignore: noop,
17969          extra: noop
17970        },
17971        formatter: {
17972          match: never,
17973          matchAll: constant([]),
17974          matchNode: constant(undefined),
17975          canApply: never,
17976          closest: empty,
17977          apply: noop,
17978          remove: noop,
17979          toggle: noop,
17980          formatChanged: constant({ unbind: noop })
17981        },
17982        editor: {
17983          getContent: empty,
17984          setContent: constant({
17985            content: '',
17986            html: ''
17987          }),
17988          insertContent: constant(''),
17989          addVisual: noop
17990        },
17991        selection: { getContent: empty },
17992        autocompleter: {
17993          addDecoration: noop,
17994          removeDecoration: noop
17995        },
17996        raw: { getModel: constant(Optional.none()) }
17997      };
17998    };
17999    const isRtc = editor => has$2(editor.plugins, 'rtc');
18000    const getRtcSetup = editor => get$a(editor.plugins, 'rtc').bind(rtcPlugin => Optional.from(rtcPlugin.setup));
18001    const setup$s = editor => {
18002      const editorCast = editor;
18003      return getRtcSetup(editor).fold(() => {
18004        editorCast.rtcInstance = makePlainAdaptor(editor);
18005        return Optional.none();
18006      }, setup => {
18007        editorCast.rtcInstance = makeNoopAdaptor();
18008        return Optional.some(() => setup().then(rtcEditor => {
18009          editorCast.rtcInstance = makeRtcAdaptor(rtcEditor);
18010          return rtcEditor.rtc.isRemote;
18011        }));
18012      });
18013    };
18014    const getRtcInstanceWithFallback = editor => editor.rtcInstance ? editor.rtcInstance : makePlainAdaptor(editor);
18015    const getRtcInstanceWithError = editor => {
18016      const rtcInstance = editor.rtcInstance;
18017      if (!rtcInstance) {
18018        throw new Error('Failed to get RTC instance not yet initialized.');
18019      } else {
18020        return rtcInstance;
18021      }
18022    };
18023    const beforeChange = (editor, locks, beforeBookmark) => {
18024      getRtcInstanceWithError(editor).undoManager.beforeChange(locks, beforeBookmark);
18025    };
18026    const addUndoLevel = (editor, undoManager, index, locks, beforeBookmark, level, event) => getRtcInstanceWithError(editor).undoManager.add(undoManager, index, locks, beforeBookmark, level, event);
18027    const undo = (editor, undoManager, locks, index) => getRtcInstanceWithError(editor).undoManager.undo(undoManager, locks, index);
18028    const redo = (editor, index, data) => getRtcInstanceWithError(editor).undoManager.redo(index, data);
18029    const clear = (editor, undoManager, index) => {
18030      getRtcInstanceWithError(editor).undoManager.clear(undoManager, index);
18031    };
18032    const reset = (editor, undoManager) => {
18033      getRtcInstanceWithError(editor).undoManager.reset(undoManager);
18034    };
18035    const hasUndo = (editor, undoManager, index) => getRtcInstanceWithError(editor).undoManager.hasUndo(undoManager, index);
18036    const hasRedo = (editor, undoManager, index) => getRtcInstanceWithError(editor).undoManager.hasRedo(undoManager, index);
18037    const transact = (editor, undoManager, locks, callback) => getRtcInstanceWithError(editor).undoManager.transact(undoManager, locks, callback);
18038    const ignore = (editor, locks, callback) => {
18039      getRtcInstanceWithError(editor).undoManager.ignore(locks, callback);
18040    };
18041    const extra = (editor, undoManager, index, callback1, callback2) => {
18042      getRtcInstanceWithError(editor).undoManager.extra(undoManager, index, callback1, callback2);
18043    };
18044    const matchFormat = (editor, name, vars, node, similar) => getRtcInstanceWithError(editor).formatter.match(name, vars, node, similar);
18045    const matchAllFormats = (editor, names, vars) => getRtcInstanceWithError(editor).formatter.matchAll(names, vars);
18046    const matchNodeFormat = (editor, node, name, vars, similar) => getRtcInstanceWithError(editor).formatter.matchNode(node, name, vars, similar);
18047    const canApplyFormat = (editor, name) => getRtcInstanceWithError(editor).formatter.canApply(name);
18048    const closestFormat = (editor, names) => getRtcInstanceWithError(editor).formatter.closest(names);
18049    const applyFormat = (editor, name, vars, node) => {
18050      getRtcInstanceWithError(editor).formatter.apply(name, vars, node);
18051    };
18052    const removeFormat = (editor, name, vars, node, similar) => {
18053      getRtcInstanceWithError(editor).formatter.remove(name, vars, node, similar);
18054    };
18055    const toggleFormat = (editor, name, vars, node) => {
18056      getRtcInstanceWithError(editor).formatter.toggle(name, vars, node);
18057    };
18058    const formatChanged = (editor, registeredFormatListeners, formats, callback, similar, vars) => getRtcInstanceWithError(editor).formatter.formatChanged(registeredFormatListeners, formats, callback, similar, vars);
18059    const getContent$2 = (editor, args) => getRtcInstanceWithFallback(editor).editor.getContent(args);
18060    const setContent$2 = (editor, content, args) => getRtcInstanceWithFallback(editor).editor.setContent(content, args);
18061    const insertContent$1 = (editor, value, details) => getRtcInstanceWithFallback(editor).editor.insertContent(value, details);
18062    const getSelectedContent = (editor, format, args) => getRtcInstanceWithError(editor).selection.getContent(format, args);
18063    const addVisual$1 = (editor, elm) => getRtcInstanceWithError(editor).editor.addVisual(elm);
18064    const bindEvents = editor => getRtcInstanceWithError(editor).init.bindEvents();
18065    const addAutocompleterDecoration = (editor, range) => getRtcInstanceWithError(editor).autocompleter.addDecoration(range);
18066    const removeAutocompleterDecoration = editor => getRtcInstanceWithError(editor).autocompleter.removeDecoration();
18067
18068    const getContent$1 = (editor, args = {}) => {
18069      const format = args.format ? args.format : 'html';
18070      return getSelectedContent(editor, format, args);
18071    };
18072
18073    const removeEmpty = text => {
18074      if (text.dom.length === 0) {
18075        remove$
180756
vendor: 17,637 bytes, lines 18075-18541
18075(text);
18076        return Optional.none();
18077      } else {
18078        return Optional.some(text);
18079      }
18080    };
18081    const walkPastBookmark = (node, start) => node.filter(elm => BookmarkManager.isBookmarkNode(elm.dom)).bind(start ? nextSibling : prevSibling);
18082    const merge$1 = (outer, inner, rng, start) => {
18083      const outerElm = outer.dom;
18084      const innerElm = inner.dom;
18085      const oldLength = start ? outerElm.length : innerElm.length;
18086      if (start) {
18087        mergeTextNodes(outerElm, innerElm, false, !start);
18088        rng.setStart(innerElm, oldLength);
18089      } else {
18090        mergeTextNodes(innerElm, outerElm, false, !start);
18091        rng.setEnd(innerElm, oldLength);
18092      }
18093    };
18094    const normalizeTextIfRequired = (inner, start) => {
18095      parent(inner).each(root => {
18096        const text = inner.dom;
18097        if (start && needsToBeNbspLeft(root, CaretPosition(text, 0))) {
18098          normalizeWhitespaceAfter(text, 0);
18099        } else if (!start && needsToBeNbspRight(root, CaretPosition(text, text.length))) {
18100          normalizeWhitespaceBefore(text, text.length);
18101        }
18102      });
18103    };
18104    const mergeAndNormalizeText = (outerNode, innerNode, rng, start) => {
18105      outerNode.bind(outer => {
18106        const normalizer = start ? normalizeWhitespaceBefore : normalizeWhitespaceAfter;
18107        normalizer(outer.dom, start ? outer.dom.length : 0);
18108        return innerNode.filter(isText$b).map(inner => merge$1(outer, inner, rng, start));
18109      }).orThunk(() => {
18110        const innerTextNode = walkPastBookmark(innerNode, start).or(innerNode).filter(isText$b);
18111        return innerTextNode.map(inner => normalizeTextIfRequired(inner, start));
18112      });
18113    };
18114    const rngSetContent = (rng, fragment) => {
18115      const firstChild = Optional.from(fragment.firstChild).map(SugarElement.fromDom);
18116      const lastChild = Optional.from(fragment.lastChild).map(SugarElement.fromDom);
18117      rng.deleteContents();
18118      rng.insertNode(fragment);
18119      const prevText = firstChild.bind(prevSibling).filter(isText$b).bind(removeEmpty);
18120      const nextText = lastChild.bind(nextSibling).filter(isText$b).bind(removeEmpty);
18121      mergeAndNormalizeText(prevText, firstChild, rng, true);
18122      mergeAndNormalizeText(nextText, lastChild, rng, false);
18123      rng.collapse(false);
18124    };
18125    const setupArgs$2 = (args, content) => ({
18126      format: 'html',
18127      ...args,
18128      set: true,
18129      selection: true,
18130      content
18131    });
18132    const cleanContent = (editor, args) => {
18133      if (args.format !== 'raw') {
18134        const rng = editor.selection.getRng();
18135        const contextBlock = editor.dom.getParent(rng.commonAncestorContainer, editor.dom.isBlock);
18136        const contextArgs = contextBlock ? { context: contextBlock.nodeName.toLowerCase() } : {};
18137        const node = editor.parser.parse(args.content, {
18138          forced_root_block: false,
18139          ...contextArgs,
18140          ...args
18141        });
18142        return HtmlSerializer({ validate: false }, editor.schema).serialize(node);
18143      } else {
18144        return args.content;
18145      }
18146    };
18147    const setContent$1 = (editor, content, args = {}) => {
18148      const defaultedArgs = setupArgs$2(args, content);
18149      preProcessSetContent(editor, defaultedArgs).each(updatedArgs => {
18150        const cleanedContent = cleanContent(editor, updatedArgs);
18151        const rng = editor.selection.getRng();
18152        rngSetContent(rng, rng.createContextualFragment(cleanedContent));
18153        editor.selection.setRng(rng);
18154        scrollRangeIntoView(editor, rng);
18155        postProcessSetContent(editor, cleanedContent, updatedArgs);
18156      });
18157    };
18158
18159    const deleteFromCallbackMap = (callbackMap, selector, callback) => {
18160      if (has$2(callbackMap, selector)) {
18161        const newCallbacks = filter$5(callbackMap[selector], cb => cb !== callback);
18162        if (newCallbacks.length === 0) {
18163          delete callbackMap[selector];
18164        } else {
18165          callbackMap[selector] = newCallbacks;
18166        }
18167      }
18168    };
18169    var SelectorChanged = (dom, editor) => {
18170      let selectorChangedData;
18171      let currentSelectors;
18172      const findMatchingNode = (selector, nodes) => find$2(nodes, node => dom.is(node, selector));
18173      const getParents = elem => dom.getParents(elem, undefined, dom.getRoot());
18174      const setup = () => {
18175        selectorChangedData = {};
18176        currentSelectors = {};
18177        editor.on('NodeChange', e => {
18178          const node = e.element;
18179          const parents = getParents(node);
18180          const matchedSelectors = {};
18181          each$d(selectorChangedData, (callbacks, selector) => {
18182            findMatchingNode(selector, parents).each(node => {
18183              if (!currentSelectors[selector]) {
18184                each$e(callbacks, callback => {
18185                  callback(true, {
18186                    node,
18187                    selector,
18188                    parents
18189                  });
18190                });
18191                currentSelectors[selector] = callbacks;
18192              }
18193              matchedSelectors[selector] = callbacks;
18194            });
18195          });
18196          each$d(currentSelectors, (callbacks, selector) => {
18197            if (!matchedSelectors[selector]) {
18198              delete currentSelectors[selector];
18199              each$e(callbacks, callback => {
18200                callback(false, {
18201                  node,
18202                  selector,
18203                  parents
18204                });
18205              });
18206            }
18207          });
18208        });
18209      };
18210      return {
18211        selectorChangedWithUnbind: (selector, callback) => {
18212          if (!selectorChangedData) {
18213            setup();
18214          }
18215          if (!selectorChangedData[selector]) {
18216            selectorChangedData[selector] = [];
18217          }
18218          selectorChangedData[selector].push(callback);
18219          findMatchingNode(selector, getParents(editor.selection.getStart())).each(() => {
18220            currentSelectors[selector] = selectorChangedData[selector];
18221          });
18222          return {
18223            unbind: () => {
18224              deleteFromCallbackMap(selectorChangedData, selector, callback);
18225              deleteFromCallbackMap(currentSelectors, selector, callback);
18226            }
18227          };
18228        }
18229      };
18230    };
18231
18232    const isAttachedToDom = node => {
18233      return !!(node && node.ownerDocument) && contains(SugarElement.fromDom(node.ownerDocument), SugarElement.fromDom(node));
18234    };
18235    const isValidRange = rng => {
18236      if (!rng) {
18237        return false;
18238      } else {
18239        return isAttachedToDom(rng.startContainer) && isAttachedToDom(rng.endContainer);
18240      }
18241    };
18242    const EditorSelection = (dom, win, serializer, editor) => {
18243      let selectedRange;
18244      let explicitRange;
18245      const {selectorChangedWithUnbind} = SelectorChanged(dom, editor);
18246      const setCursorLocation = (node, offset) => {
18247        const rng = dom.createRng();
18248        if (isNonNullable(node) && isNonNullable(offset)) {
18249          rng.setStart(node, offset);
18250          rng.setEnd(node, offset);
18251          setRng(rng);
18252          collapse(false);
18253        } else {
18254          moveEndPoint(dom, rng, editor.getBody(), true);
18255          setRng(rng);
18256        }
18257      };
18258      const getContent = args => getContent$1(editor, args);
18259      const setContent = (content, args) => setContent$1(editor, content, args);
18260      const getStart$1 = real => getStart(editor.getBody(), getRng$1(), real);
18261      const getEnd = real => getEnd$1(editor.getBody(), getRng$1(), real);
18262      const getBookmark = (type, normalized) => bookmarkManager.getBookmark(type, normalized);
18263      const moveToBookmark = bookmark => bookmarkManager.moveToBookmark(bookmark);
18264      const select$1 = (node, content) => {
18265        select(dom, node, content).each(setRng);
18266        return node;
18267      };
18268      const isCollapsed = () => {
18269        const rng = getRng$1(), sel = getSel();
18270        if (!rng || rng.item) {
18271          return false;
18272        }
18273        if (rng.compareEndPoints) {
18274          return rng.compareEndPoints('StartToEnd', rng) === 0;
18275        }
18276        return !sel || rng.collapsed;
18277      };
18278      const isEditable = () => {
18279        const rng = getRng$1();
18280        const fakeSelectedElements = editor.getBody().querySelectorAll('[data-mce-selected="1"]');
18281        if (fakeSelectedElements.length > 0) {
18282          return forall(fakeSelectedElements, el => dom.isEditable(el.parentElement));
18283        } else if (rng.startContainer === rng.endContainer) {
18284          return dom.isEditable(rng.startContainer);
18285        } else {
18286          return dom.isEditable(rng.startContainer) && dom.isEditable(rng.endContainer);
18287        }
18288      };
18289      const collapse = toStart => {
18290        const rng = getRng$1();
18291        rng.collapse(!!toStart);
18292        setRng(rng);
18293      };
18294      const getSel = () => win.getSelection ? win.getSelection() : win.document.selection;
18295      const getRng$1 = () => {
18296        let rng;
18297        const tryCompareBoundaryPoints = (how, sourceRange, destinationRange) => {
18298          try {
18299            return sourceRange.compareBoundaryPoints(how, destinationRange);
18300          } catch (ex) {
18301            return -1;
18302          }
18303        };
18304        const doc = win.document;
18305        if (isNonNullable(editor.bookmark) && !hasFocus(editor)) {
18306          const bookmark = getRng(editor);
18307          if (bookmark.isSome()) {
18308            return bookmark.map(r => processRanges(editor, [r])[0]).getOr(doc.createRange());
18309          }
18310        }
18311        try {
18312          const selection = getSel();
18313          if (selection && !isRestrictedNode(selection.anchorNode)) {
18314            if (selection.rangeCount > 0) {
18315              rng = selection.getRangeAt(0);
18316            } else {
18317              rng = doc.createRange();
18318            }
18319            rng = processRanges(editor, [rng])[0];
18320          }
18321        } catch (ex) {
18322        }
18323        if (!rng) {
18324          rng = doc.createRange();
18325        }
18326        if (isDocument$1(rng.startContainer) && rng.collapsed) {
18327          const elm = dom.getRoot();
18328          rng.setStart(elm, 0);
18329          rng.setEnd(elm, 0);
18330        }
18331        if (selectedRange && explicitRange) {
18332          if (tryCompareBoundaryPoints(rng.START_TO_START, rng, selectedRange) === 0 && tryCompareBoundaryPoints(rng.END_TO_END, rng, selectedRange) === 0) {
18333            rng = explicitRange;
18334          } else {
18335            selectedRange = null;
18336            explicitRange = null;
18337          }
18338        }
18339        return rng;
18340      };
18341      const setRng = (rng, forward) => {
18342        if (!isValidRange(rng)) {
18343          return;
18344        }
18345        const sel = getSel();
18346        const evt = editor.dispatch('SetSelectionRange', {
18347          range: rng,
18348          forward
18349        });
18350        rng = evt.range;
18351        if (sel) {
18352          explicitRange = rng;
18353          try {
18354            sel.removeAllRanges();
18355            sel.addRange(rng);
18356          } catch (ex) {
18357          }
18358          if (forward === false && sel.extend) {
18359            sel.collapse(rng.endContainer, rng.endOffset);
18360            sel.extend(rng.startContainer, rng.startOffset);
18361          }
18362          selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
18363        }
18364        if (!rng.collapsed && rng.startContainer === rng.endContainer && (sel === null || sel === void 0 ? void 0 : sel.setBaseAndExtent)) {
18365          if (rng.endOffset - rng.startOffset < 2) {
18366            if (rng.startContainer.hasChildNodes()) {
18367              const node = rng.startContainer.childNodes[rng.startOffset];
18368              if (node && node.nodeName === 'IMG') {
18369                sel.setBaseAndExtent(rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset);
18370                if (sel.anchorNode !== rng.startContainer || sel.focusNode !== rng.endContainer) {
18371                  sel.setBaseAndExtent(node, 0, node, 1);
18372                }
18373              }
18374            }
18375          }
18376        }
18377        editor.dispatch('AfterSetSelectionRange', {
18378          range: rng,
18379          forward
18380        });
18381      };
18382      const setNode = elm => {
18383        setContent(dom.getOuterHTML(elm));
18384        return elm;
18385      };
18386      const getNode$1 = () => getNode(editor.getBody(), getRng$1());
18387      const getSelectedBlocks$1 = (startElm, endElm) => getSelectedBlocks(dom, getRng$1(), startElm, endElm);
18388      const isForward = () => {
18389        const sel = getSel();
18390        const anchorNode = sel === null || sel === void 0 ? void 0 : sel.anchorNode;
18391        const focusNode = sel === null || sel === void 0 ? void 0 : sel.focusNode;
18392        if (!sel || !anchorNode || !focusNode || isRestrictedNode(anchorNode) || isRestrictedNode(focusNode)) {
18393          return true;
18394        }
18395        const anchorRange = dom.createRng();
18396        const focusRange = dom.createRng();
18397        try {
18398          anchorRange.setStart(anchorNode, sel.anchorOffset);
18399          anchorRange.collapse(true);
18400          focusRange.setStart(focusNode, sel.focusOffset);
18401          focusRange.collapse(true);
18402        } catch (e) {
18403          return true;
18404        }
18405        return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
18406      };
18407      const normalize = () => {
18408        const rng = getRng$1();
18409        const sel = getSel();
18410        if (!hasMultipleRanges(sel) && hasAnyRanges(editor)) {
18411          const normRng = normalize$2(dom, rng);
18412          normRng.each(normRng => {
18413            setRng(normRng, isForward());
18414          });
18415          return normRng.getOr(rng);
18416        }
18417        return rng;
18418      };
18419      const selectorChanged = (selector, callback) => {
18420        selectorChangedWithUnbind(selector, callback);
18421        return exports;
18422      };
18423      const getScrollContainer = () => {
18424        let scrollContainer;
18425        let node = dom.getRoot();
18426        while (node && node.nodeName !== 'BODY') {
18427          if (node.scrollHeight > node.clientHeight) {
18428            scrollContainer = node;
18429            break;
18430          }
18431          node = node.parentNode;
18432        }
18433        return scrollContainer;
18434      };
18435      const scrollIntoView = (elm, alignToTop) => {
18436        if (isNonNullable(elm)) {
18437          scrollElementIntoView(editor, elm, alignToTop);
18438        } else {
18439          scrollRangeIntoView(editor, getRng$1(), alignToTop);
18440        }
18441      };
18442      const placeCaretAt = (clientX, clientY) => setRng(fromPoint(clientX, clientY, editor.getDoc()));
18443      const getBoundingClientRect = () => {
18444        const rng = getRng$1();
18445        return rng.collapsed ? CaretPosition.fromRangeStart(rng).getClientRects()[0] : rng.getBoundingClientRect();
18446      };
18447      const destroy = () => {
18448        win = selectedRange = explicitRange = null;
18449        controlSelection.destroy();
18450      };
18451      const expand = (options = { type: 'word' }) => setRng(RangeUtils(dom).expand(getRng$1(), options));
18452      const exports = {
18453        dom,
18454        win,
18455        serializer,
18456        editor,
18457        expand,
18458        collapse,
18459        setCursorLocation,
18460        getContent,
18461        setContent,
18462        getBookmark,
18463        moveToBookmark,
18464        select: select$1,
18465        isCollapsed,
18466        isEditable,
18467        isForward,
18468        setNode,
18469        getNode: getNode$1,
18470        getSel,
18471        setRng,
18472        getRng: getRng$1,
18473        getStart: getStart$1,
18474        getEnd,
18475        getSelectedBlocks: getSelectedBlocks$1,
18476        normalize,
18477        selectorChanged,
18478        selectorChangedWithUnbind,
18479        getScrollContainer,
18480        scrollIntoView,
18481        placeCaretAt,
18482        getBoundingClientRect,
18483        destroy
18484      };
18485      const bookmarkManager = BookmarkManager(exports);
18486      const controlSelection = ControlSelection(exports, editor);
18487      exports.bookmarkManager = bookmarkManager;
18488      exports.controlSelection = controlSelection;
18489      return exports;
18490    };
18491
18492    const register$3 = (htmlParser, settings, dom) => {
18493      htmlParser.addAttributeFilter('data-mce-tabindex', (nodes, name) => {
18494        let i = nodes.length;
18495        while (i--) {
18496          const node = nodes[i];
18497          node.attr('tabindex', node.attr('data-mce-tabindex'));
18498          node.attr(name, null);
18499        }
18500      });
18501      htmlParser.addAttributeFilter('src,href,style', (nodes, name) => {
18502        const internalName = 'data-mce-' + name;
18503        const urlConverter = settings.url_converter;
18504        const urlConverterScope = settings.url_converter_scope;
18505        let i = nodes.length;
18506        while (i--) {
18507          const node = nodes[i];
18508          let value = node.attr(internalName);
18509          if (value !== undefined) {
18510            node.attr(name, value.length > 0 ? value : null);
18511            node.attr(internalName, null);
18512          } else {
18513            value = node.attr(name);
18514            if (name === 'style') {
18515              value = dom.serializeStyle(dom.parseStyle(value), node.name);
18516            } else if (urlConverter) {
18517              value = urlConverter.call(urlConverterScope, value, name, node.name);
18518            }
18519            node.attr(name, value.length > 0 ? value : null);
18520          }
18521        }
18522      });
18523      htmlParser.addAttributeFilter('class', nodes => {
18524        let i = nodes.length;
18525        while (i--) {
18526          const node = nodes[i];
18527          let value = node.attr('class');
18528          if (value) {
18529            value = value.replace(/(?:^|\s)mce-item-\w+(?!\S)/g, '');
18530            node.attr('class', value.length > 0 ? value : null);
18531          }
18532        }
18533      });
18534      htmlParser.addAttributeFilter('data-mce-type', (nodes, name, args) => {
18535        let i = nodes.length;
18536        while (i--) {
18537          const node = nodes[i];
18538          if (node.attr('data-mce-type') === 'bookmark' && !args.cleanup) {
18539            const hasChildren = Optional.from(node.firstChild).exists(firstChild => {
18540              var _a;
18541              return !isZwsp
vendor: 6,082 bytes, lines 18541-18707
18541((_a = firstChild.value) !== null && _a !== void 0 ? _a : '');
18542            });
18543            if (hasChildren) {
18544              node.unwrap();
18545            } else {
18546              node.remove();
18547            }
18548          }
18549        }
18550      });
18551      htmlParser.addNodeFilter('noscript', nodes => {
18552        var _a;
18553        let i = nodes.length;
18554        while (i--) {
18555          const node = nodes[i].firstChild;
18556          if (node) {
18557            node.value = Entities.decode((_a = node.value) !== null && _a !== void 0 ? _a : '');
18558          }
18559        }
18560      });
18561      htmlParser.addNodeFilter('script,style', (nodes, name) => {
18562        var _a;
18563        const trim = value => {
18564          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, '');
18565        };
18566        let i = nodes.length;
18567        while (i--) {
18568          const node = nodes[i];
18569          const firstChild = node.firstChild;
18570          const value = (_a = firstChild === null || firstChild === void 0 ? void 0 : firstChild.value) !== null && _a !== void 0 ? _a : '';
18571          if (name === 'script') {
18572            const type = node.attr('type');
18573            if (type) {
18574              node.attr('type', type === 'mce-no/type' ? null : type.replace(/^mce\-/, ''));
18575            }
18576            if (settings.element_format === 'xhtml' && firstChild && value.length > 0) {
18577              firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>';
18578            }
18579          } else {
18580            if (settings.element_format === 'xhtml' && firstChild && value.length > 0) {
18581              firstChild.value = '<!--\n' + trim(value) + '\n-->';
18582            }
18583          }
18584        }
18585      });
18586      htmlParser.addNodeFilter('#comment', nodes => {
18587        let i = nodes.length;
18588        while (i--) {
18589          const node = nodes[i];
18590          const value = node.value;
18591          if (settings.preserve_cdata && (value === null || value === void 0 ? void 0 : value.indexOf('[CDATA[')) === 0) {
18592            node.name = '#cdata';
18593            node.type = 4;
18594            node.value = dom.decode(value.replace(/^\[CDATA\[|\]\]$/g, ''));
18595          } else if ((value === null || value === void 0 ? void 0 : value.indexOf('mce:protected ')) === 0) {
18596            node.name = '#text';
18597            node.type = 3;
18598            node.raw = true;
18599            node.value = unescape(value).substr(14);
18600          }
18601        }
18602      });
18603      htmlParser.addNodeFilter('xml:namespace,input', (nodes, name) => {
18604        let i = nodes.length;
18605        while (i--) {
18606          const node = nodes[i];
18607          if (node.type === 7) {
18608            node.remove();
18609          } else if (node.type === 1) {
18610            if (name === 'input' && !node.attr('type')) {
18611              node.attr('type', 'text');
18612            }
18613          }
18614        }
18615      });
18616      htmlParser.addAttributeFilter('data-mce-type', nodes => {
18617        each$e(nodes, node => {
18618          if (node.attr('data-mce-type') === 'format-caret') {
18619            if (node.isEmpty(htmlParser.schema.getNonEmptyElements())) {
18620              node.remove();
18621            } else {
18622              node.unwrap();
18623            }
18624          }
18625        });
18626      });
18627      htmlParser.addAttributeFilter('data-mce-src,data-mce-href,data-mce-style,' + 'data-mce-selected,data-mce-expando,data-mce-block,' + 'data-mce-type,data-mce-resize,data-mce-placeholder', (nodes, name) => {
18628        let i = nodes.length;
18629        while (i--) {
18630          nodes[i].attr(name, null);
18631        }
18632      });
18633    };
18634    const trimTrailingBr = rootNode => {
18635      const isBr = node => {
18636        return (node === null || node === void 0 ? void 0 : node.name) === 'br';
18637      };
18638      const brNode1 = rootNode.lastChild;
18639      if (isBr(brNode1)) {
18640        const brNode2 = brNode1.prev;
18641        if (isBr(brNode2)) {
18642          brNode1.remove();
18643          brNode2.remove();
18644        }
18645      }
18646    };
18647
18648    const preProcess$1 = (editor, node, args) => {
18649      let oldDoc;
18650      const dom = editor.dom;
18651      let clonedNode = node.cloneNode(true);
18652      const impl = document.implementation;
18653      if (impl.createHTMLDocument) {
18654        const doc = impl.createHTMLDocument('');
18655        Tools.each(clonedNode.nodeName === 'BODY' ? clonedNode.childNodes : [clonedNode], node => {
18656          doc.body.appendChild(doc.importNode(node, true));
18657        });
18658        if (clonedNode.nodeName !== 'BODY') {
18659          clonedNode = doc.body.firstChild;
18660        } else {
18661          clonedNode = doc.body;
18662        }
18663        oldDoc = dom.doc;
18664        dom.doc = doc;
18665      }
18666      firePreProcess(editor, {
18667        ...args,
18668        node: clonedNode
18669      });
18670      if (oldDoc) {
18671        dom.doc = oldDoc;
18672      }
18673      return clonedNode;
18674    };
18675    const shouldFireEvent = (editor, args) => {
18676      return isNonNullable(editor) && editor.hasEventListeners('PreProcess') && !args.no_events;
18677    };
18678    const process$1 = (editor, node, args) => {
18679      return shouldFireEvent(editor, args) ? preProcess$1(editor, node, args) : node;
18680    };
18681
18682    const addTempAttr = (htmlParser, tempAttrs, name) => {
18683      if (Tools.inArray(tempAttrs, name) === -1) {
18684        htmlParser.addAttributeFilter(name, (nodes, name) => {
18685          let i = nodes.length;
18686          while (i--) {
18687            nodes[i].attr(name, null);
18688          }
18689        });
18690        tempAttrs.push(name);
18691      }
18692    };
18693    const postProcess = (editor, args, content) => {
18694      if (!args.no_events && editor) {
18695        const outArgs = firePostProcess(editor, {
18696          ...args,
18697          content
18698        });
18699        return outArgs.content;
18700      } else {
18701        return content;
18702      }
18703    };
18704    const getHtmlFromNode = (dom, node, args) => {
18705      const html = trim$1(args.getInner ? node.innerHTML : dom.getOuterHTML(node));
18706      return args.selection || isWsPreserveElement(SugarElement.fromDom(node)) ? html : Tools.trim(html);
18707    };
vendor: 7,820 bytes, lines 18708-18851
18708    const parseHtml = (htmlParser, html, args) => {
18709      const parserArgs = args.selection ? {
18710        forced_root_block: false,
18711        ...args
18712      } : args;
18713      const rootNode = htmlParser.parse(html, parserArgs);
18714      trimTrailingBr(rootNode);
18715      return rootNode;
18716    };
18717    const serializeNode = (settings, schema, node) => {
18718      const htmlSerializer = HtmlSerializer(settings, schema);
18719      return htmlSerializer.serialize(node);
18720    };
18721    const toHtml = (editor, settings, schema, rootNode, args) => {
18722      const content = serializeNode(settings, schema, rootNode);
18723      return postProcess(editor, args, content);
18724    };
18725    const DomSerializerImpl = (settings, editor) => {
18726      const tempAttrs = ['data-mce-selected'];
18727      const dom = editor && editor.dom ? editor.dom : DOMUtils.DOM;
18728      const schema = editor && editor.schema ? editor.schema : Schema(settings);
18729      settings.entity_encoding = settings.entity_encoding || 'named';
18730      settings.remove_trailing_brs = 'remove_trailing_brs' in settings ? settings.remove_trailing_brs : true;
18731      const htmlParser = DomParser(settings, schema);
18732      register$3(htmlParser, settings, dom);
18733      const serialize = (node, parserArgs = {}) => {
18734        const args = {
18735          format: 'html',
18736          ...parserArgs
18737        };
18738        const targetNode = process$1(editor, node, args);
18739        const html = getHtmlFromNode(dom, targetNode, args);
18740        const rootNode = parseHtml(htmlParser, html, args);
18741        return args.format === 'tree' ? rootNode : toHtml(editor, settings, schema, rootNode, args);
18742      };
18743      return {
18744        schema,
18745        addNodeFilter: htmlParser.addNodeFilter,
18746        addAttributeFilter: htmlParser.addAttributeFilter,
18747        serialize: serialize,
18748        addRules: schema.addValidElements,
18749        setRules: schema.setValidElements,
18750        addTempAttr: curry(addTempAttr, htmlParser, tempAttrs),
18751        getTempAttrs: constant(tempAttrs),
18752        getNodeFilters: htmlParser.getNodeFilters,
18753        getAttributeFilters: htmlParser.getAttributeFilters,
18754        removeNodeFilter: htmlParser.removeNodeFilter,
18755        removeAttributeFilter: htmlParser.removeAttributeFilter
18756      };
18757    };
18758
18759    const DomSerializer = (settings, editor) => {
18760      const domSerializer = DomSerializerImpl(settings, editor);
18761      return {
18762        schema: domSerializer.schema,
18763        addNodeFilter: domSerializer.addNodeFilter,
18764        addAttributeFilter: domSerializer.addAttributeFilter,
18765        serialize: domSerializer.serialize,
18766        addRules: domSerializer.addRules,
18767        setRules: domSerializer.setRules,
18768        addTempAttr: domSerializer.addTempAttr,
18769        getTempAttrs: domSerializer.getTempAttrs,
18770        getNodeFilters: domSerializer.getNodeFilters,
18771        getAttributeFilters: domSerializer.getAttributeFilters,
18772        removeNodeFilter: domSerializer.removeNodeFilter,
18773        removeAttributeFilter: domSerializer.removeAttributeFilter
18774      };
18775    };
18776
18777    const defaultFormat$1 = 'html';
18778    const setupArgs$1 = (args, format) => ({
18779      ...args,
18780      format,
18781      get: true,
18782      getInner: true
18783    });
18784    const getContent = (editor, args = {}) => {
18785      const format = args.format ? args.format : defaultFormat$1;
18786      const defaultedArgs = setupArgs$1(args, format);
18787      return preProcessGetContent(editor, defaultedArgs).fold(identity, updatedArgs => {
18788        const content = getContent$2(editor, updatedArgs);
18789        return postProcessGetContent(editor, content, updatedArgs);
18790      });
18791    };
18792
18793    const defaultFormat = 'html';
18794    const setupArgs = (args, content) => ({
18795      format: defaultFormat,
18796      ...args,
18797      set: true,
18798      content
18799    });
18800    const setContent = (editor, content, args = {}) => {
18801      const defaultedArgs = setupArgs(args, content);
18802      return preProcessSetContent(editor, defaultedArgs).map(updatedArgs => {
18803        const result = setContent$2(editor, updatedArgs.content, updatedArgs);
18804        postProcessSetContent(editor, result.html, updatedArgs);
18805        return result.content;
18806      }).getOr(content);
18807    };
18808
18809    const removedOptions = ('autoresize_on_init,content_editable_state,padd_empty_with_br,block_elements,' + 'boolean_attributes,editor_deselector,editor_selector,elements,file_browser_callback_types,filepicker_validator_handler,' + 'force_hex_style_colors,force_p_newlines,gecko_spellcheck,images_dataimg_filter,media_scripts,mode,move_caret_before_on_enter_elements,' + 'non_empty_elements,self_closing_elements,short_ended_elements,special,spellchecker_select_languages,spellchecker_whitelist,' + 'tab_focus,tabfocus_elements,table_responsive_width,text_block_elements,text_inline_elements,toolbar_drawer,types,validate,whitespace_elements,' + 'paste_enable_default_filters,paste_filter_drop,paste_word_valid_elements,paste_retain_style_properties,paste_convert_word_fake_lists').split(',');
18810    const deprecatedOptions = 'template_cdate_classes,template_mdate_classes,template_selected_content_classes,template_preview_replace_values,template_replace_values,templates,template_cdate_format,template_mdate_format'.split(',');
18811    const removedPlugins = 'bbcode,colorpicker,contextmenu,fullpage,legacyoutput,spellchecker,textcolor'.split(',');
18812    const deprecatedPlugins = [{
18813        name: 'template',
18814        replacedWith: 'Advanced Template'
18815      }];
18816    const getMatchingOptions = (options, searchingFor) => {
18817      const settingNames = filter$5(searchingFor, setting => has$2(options, setting));
18818      return sort(settingNames);
18819    };
18820    const getRemovedOptions = options => {
18821      const settingNames = getMatchingOptions(options, removedOptions);
18822      const forcedRootBlock = options.forced_root_block;
18823      if (forcedRootBlock === false || forcedRootBlock === '') {
18824        settingNames.push('forced_root_block (false only)');
18825      }
18826      return sort(settingNames);
18827    };
18828    const getDeprecatedOptions = options => getMatchingOptions(options, deprecatedOptions);
18829    const getMatchingPlugins = (options, searchingFor) => {
18830      const plugins = Tools.makeMap(options.plugins, ' ');
18831      const hasPlugin = plugin => has$2(plugins, plugin);
18832      const pluginNames = filter$5(searchingFor, hasPlugin);
18833      return sort(pluginNames);
18834    };
18835    const getRemovedPlugins = options => getMatchingPlugins(options, removedPlugins);
18836    const getDeprecatedPlugins = options => getMatchingPlugins(options, deprecatedPlugins.map(entry => entry.name));
18837    const logRemovedWarnings = (rawOptions, normalizedOptions) => {
18838      const removedOptions = getRemovedOptions(rawOptions);
18839      const removedPlugins = getRemovedPlugins(normalizedOptions);
18840      const hasRemovedPlugins = removedPlugins.length > 0;
18841      const hasRemovedOptions = removedOptions.length > 0;
18842      const isLegacyMobileTheme = normalizedOptions.theme === 'mobile';
18843      if (hasRemovedPlugins || hasRemovedOptions || isLegacyMobileTheme) {
18844        const listJoiner = '\n- ';
18845        const themesMessage = isLegacyMobileTheme ? `\n\nThemes:${ listJoiner }mobile` : '';
18846        const pluginsMessage = hasRemovedPlugins ? `\n\nPlugins:${ listJoiner }${ removedPlugins.join(listJoiner) }` : '';
18847        const optionsMessage = hasRemovedOptions ? `\n\nOptions:${ listJoiner }${ removedOptions.join(listJoiner) }` : '';
18848        console.warn('The following deprecated features are currently enabled and have been removed in TinyMCE 6.0. These features will no longer work and should be removed from the TinyMCE configuration. ' + 'See https://www.tiny.cloud/docs/tinymce/6/migration-from-5x/ for more information.' + themesMessage + pluginsMessage + optionsMessage);
18849      }
18850    };
18851    const getPluginDescription = name => find$2(deprecatedPlugins, entry => entry.name === name).fold(() => name, entry => `${ name }, replaced by ${ entry.replacedWith }`
vendor: 26,591 bytes, lines 18851-19608
18851);
18852    const logDeprecatedWarnings = (rawOptions, normalizedOptions) => {
18853      const deprecatedOptions = getDeprecatedOptions(rawOptions);
18854      const deprecatedPlugins = getDeprecatedPlugins(normalizedOptions);
18855      const hasDeprecatedPlugins = deprecatedPlugins.length > 0;
18856      const hasDeprecatedOptions = deprecatedOptions.length > 0;
18857      if (hasDeprecatedPlugins || hasDeprecatedOptions) {
18858        const listJoiner = '\n- ';
18859        const pluginsMessage = hasDeprecatedPlugins ? `\n\nPlugins:${ listJoiner }${ deprecatedPlugins.map(getPluginDescription).join(listJoiner) }` : '';
18860        const optionsMessage = hasDeprecatedOptions ? `\n\nOptions:${ listJoiner }${ deprecatedOptions.join(listJoiner) }` : '';
18861        console.warn('The following deprecated features are currently enabled but will be removed soon.' + pluginsMessage + optionsMessage);
18862      }
18863    };
18864    const logWarnings = (rawOptions, normalizedOptions) => {
18865      logRemovedWarnings(rawOptions, normalizedOptions);
18866      logDeprecatedWarnings(rawOptions, normalizedOptions);
18867    };
18868
18869    const DOM$8 = DOMUtils.DOM;
18870    const restoreOriginalStyles = editor => {
18871      DOM$8.setStyle(editor.id, 'display', editor.orgDisplay);
18872    };
18873    const safeDestroy = x => Optional.from(x).each(x => x.destroy());
18874    const clearDomReferences = editor => {
18875      const ed = editor;
18876      ed.contentAreaContainer = ed.formElement = ed.container = ed.editorContainer = null;
18877      ed.bodyElement = ed.contentDocument = ed.contentWindow = null;
18878      ed.iframeElement = ed.targetElm = null;
18879      const selection = editor.selection;
18880      if (selection) {
18881        const dom = selection.dom;
18882        ed.selection = selection.win = selection.dom = dom.doc = null;
18883      }
18884    };
18885    const restoreForm = editor => {
18886      const form = editor.formElement;
18887      if (form) {
18888        if (form._mceOldSubmit) {
18889          form.submit = form._mceOldSubmit;
18890          delete form._mceOldSubmit;
18891        }
18892        DOM$8.unbind(form, 'submit reset', editor.formEventDelegate);
18893      }
18894    };
18895    const remove$1 = editor => {
18896      if (!editor.removed) {
18897        const {_selectionOverrides, editorUpload} = editor;
18898        const body = editor.getBody();
18899        const element = editor.getElement();
18900        if (body) {
18901          editor.save({ is_removing: true });
18902        }
18903        editor.removed = true;
18904        editor.unbindAllNativeEvents();
18905        if (editor.hasHiddenInput && isNonNullable(element === null || element === void 0 ? void 0 : element.nextSibling)) {
18906          DOM$8.remove(element.nextSibling);
18907        }
18908        fireRemove(editor);
18909        editor.editorManager.remove(editor);
18910        if (!editor.inline && body) {
18911          restoreOriginalStyles(editor);
18912        }
18913        fireDetach(editor);
18914        DOM$8.remove(editor.getContainer());
18915        safeDestroy(_selectionOverrides);
18916        safeDestroy(editorUpload);
18917        editor.destroy();
18918      }
18919    };
18920    const destroy = (editor, automatic) => {
18921      const {selection, dom} = editor;
18922      if (editor.destroyed) {
18923        return;
18924      }
18925      if (!automatic && !editor.removed) {
18926        editor.remove();
18927        return;
18928      }
18929      if (!automatic) {
18930        editor.editorManager.off('beforeunload', editor._beforeUnload);
18931        if (editor.theme && editor.theme.destroy) {
18932          editor.theme.destroy();
18933        }
18934        safeDestroy(selection);
18935        safeDestroy(dom);
18936      }
18937      restoreForm(editor);
18938      clearDomReferences(editor);
18939      editor.destroyed = true;
18940    };
18941
18942    const CreateIconManager = () => {
18943      const lookup = {};
18944      const add = (id, iconPack) => {
18945        lookup[id] = iconPack;
18946      };
18947      const get = id => {
18948        if (lookup[id]) {
18949          return lookup[id];
18950        } else {
18951          return { icons: {} };
18952        }
18953      };
18954      const has = id => has$2(lookup, id);
18955      return {
18956        add,
18957        get,
18958        has
18959      };
18960    };
18961    const IconManager = CreateIconManager();
18962
18963    const ModelManager = AddOnManager.ModelManager;
18964
18965    const getProp = (propName, elm) => {
18966      const rawElm = elm.dom;
18967      return rawElm[propName];
18968    };
18969    const getComputedSizeProp = (propName, elm) => parseInt(get$7(elm, propName), 10);
18970    const getClientWidth = curry(getProp, 'clientWidth');
18971    const getClientHeight = curry(getProp, 'clientHeight');
18972    const getMarginTop = curry(getComputedSizeProp, 'margin-top');
18973    const getMarginLeft = curry(getComputedSizeProp, 'margin-left');
18974    const getBoundingClientRect = elm => elm.dom.getBoundingClientRect();
18975    const isInsideElementContentArea = (bodyElm, clientX, clientY) => {
18976      const clientWidth = getClientWidth(bodyElm);
18977      const clientHeight = getClientHeight(bodyElm);
18978      return clientX >= 0 && clientY >= 0 && clientX <= clientWidth && clientY <= clientHeight;
18979    };
18980    const transpose = (inline, elm, clientX, clientY) => {
18981      const clientRect = getBoundingClientRect(elm);
18982      const deltaX = inline ? clientRect.left + elm.dom.clientLeft + getMarginLeft(elm) : 0;
18983      const deltaY = inline ? clientRect.top + elm.dom.clientTop + getMarginTop(elm) : 0;
18984      const x = clientX - deltaX;
18985      const y = clientY - deltaY;
18986      return {
18987        x,
18988        y
18989      };
18990    };
18991    const isXYInContentArea = (editor, clientX, clientY) => {
18992      const bodyElm = SugarElement.fromDom(editor.getBody());
18993      const targetElm = editor.inline ? bodyElm : documentElement(bodyElm);
18994      const transposedPoint = transpose(editor.inline, targetElm, clientX, clientY);
18995      return isInsideElementContentArea(targetElm, transposedPoint.x, transposedPoint.y);
18996    };
18997    const fromDomSafe = node => Optional.from(node).map(SugarElement.fromDom);
18998    const isEditorAttachedToDom = editor => {
18999      const rawContainer = editor.inline ? editor.getBody() : editor.getContentAreaContainer();
19000      return fromDomSafe(rawContainer).map(inBody).getOr(false);
19001    };
19002
19003    var NotificationManagerImpl = () => {
19004      const unimplemented = () => {
19005        throw new Error('Theme did not provide a NotificationManager implementation.');
19006      };
19007      return {
19008        open: unimplemented,
19009        close: unimplemented,
19010        getArgs: unimplemented
19011      };
19012    };
19013
19014    const NotificationManager = editor => {
19015      const notifications = [];
19016      const getImplementation = () => {
19017        const theme = editor.theme;
19018        return theme && theme.getNotificationManagerImpl ? theme.getNotificationManagerImpl() : NotificationManagerImpl();
19019      };
19020      const getTopNotification = () => {
19021        return Optional.from(notifications[0]);
19022      };
19023      const isEqual = (a, b) => {
19024        return a.type === b.type && a.text === b.text && !a.progressBar && !a.timeout && !b.progressBar && !b.timeout;
19025      };
19026      const reposition = () => {
19027        each$e(notifications, notification => {
19028          notification.reposition();
19029        });
19030      };
19031      const addNotification = notification => {
19032        notifications.push(notification);
19033      };
19034      const closeNotification = notification => {
19035        findIndex$2(notifications, otherNotification => {
19036          return otherNotification === notification;
19037        }).each(index => {
19038          notifications.splice(index, 1);
19039        });
19040      };
19041      const open = (spec, fireEvent = true) => {
19042        if (editor.removed || !isEditorAttachedToDom(editor)) {
19043          return {};
19044        }
19045        if (fireEvent) {
19046          editor.dispatch('BeforeOpenNotification', { notification: spec });
19047        }
19048        return find$2(notifications, notification => {
19049          return isEqual(getImplementation().getArgs(notification), spec);
19050        }).getOrThunk(() => {
19051          editor.editorManager.setActive(editor);
19052          const notification = getImplementation().open(spec, () => {
19053            closeNotification(notification);
19054            reposition();
19055            getTopNotification().fold(() => editor.focus(), top => focus$1(SugarElement.fromDom(top.getEl())));
19056          });
19057          addNotification(notification);
19058          reposition();
19059          editor.dispatch('OpenNotification', { notification: { ...notification } });
19060          return notification;
19061        });
19062      };
19063      const close = () => {
19064        getTopNotification().each(notification => {
19065          getImplementation().close(notification);
19066          closeNotification(notification);
19067          reposition();
19068        });
19069      };
19070      const getNotifications = constant(notifications);
19071      const registerEvents = editor => {
19072        editor.on('SkinLoaded', () => {
19073          const serviceMessage = getServiceMessage(editor);
19074          if (serviceMessage) {
19075            open({
19076              text: serviceMessage,
19077              type: 'warning',
19078              timeout: 0
19079            }, false);
19080          }
19081          reposition();
19082        });
19083        editor.on('show ResizeEditor ResizeWindow NodeChange', () => {
19084          requestAnimationFrame(reposition);
19085        });
19086        editor.on('remove', () => {
19087          each$e(notifications.slice(), notification => {
19088            getImplementation().close(notification);
19089          });
19090        });
19091      };
19092      registerEvents(editor);
19093      return {
19094        open,
19095        close,
19096        getNotifications
19097      };
19098    };
19099
19100    const PluginManager = AddOnManager.PluginManager;
19101
19102    const ThemeManager = AddOnManager.ThemeManager;
19103
19104    var WindowManagerImpl = () => {
19105      const unimplemented = () => {
19106        throw new Error('Theme did not provide a WindowManager implementation.');
19107      };
19108      return {
19109        open: unimplemented,
19110        openUrl: unimplemented,
19111        alert: unimplemented,
19112        confirm: unimplemented,
19113        close: unimplemented
19114      };
19115    };
19116
19117    const WindowManager = editor => {
19118      let dialogs = [];
19119      const getImplementation = () => {
19120        const theme = editor.theme;
19121        return theme && theme.getWindowManagerImpl ? theme.getWindowManagerImpl() : WindowManagerImpl();
19122      };
19123      const funcBind = (scope, f) => {
19124        return (...args) => {
19125          return f ? f.apply(scope, args) : undefined;
19126        };
19127      };
19128      const fireOpenEvent = dialog => {
19129        editor.dispatch('OpenWindow', { dialog });
19130      };
19131      const fireCloseEvent = dialog => {
19132        editor.dispatch('CloseWindow', { dialog });
19133      };
19134      const addDialog = dialog => {
19135        dialogs.push(dialog);
19136        fireOpenEvent(dialog);
19137      };
19138      const closeDialog = dialog => {
19139        fireCloseEvent(dialog);
19140        dialogs = filter$5(dialogs, otherDialog => {
19141          return otherDialog !== dialog;
19142        });
19143        if (dialogs.length === 0) {
19144          editor.focus();
19145        }
19146      };
19147      const getTopDialog = () => {
19148        return Optional.from(dialogs[dialogs.length - 1]);
19149      };
19150      const storeSelectionAndOpenDialog = openDialog => {
19151        editor.editorManager.setActive(editor);
19152        store(editor);
19153        editor.ui.show();
19154        const dialog = openDialog();
19155        addDialog(dialog);
19156        return dialog;
19157      };
19158      const open = (args, params) => {
19159        return storeSelectionAndOpenDialog(() => getImplementation().open(args, params, closeDialog));
19160      };
19161      const openUrl = args => {
19162        return storeSelectionAndOpenDialog(() => getImplementation().openUrl(args, closeDialog));
19163      };
19164      const alert = (message, callback, scope) => {
19165        const windowManagerImpl = getImplementation();
19166        windowManagerImpl.alert(message, funcBind(scope ? scope : windowManagerImpl, callback));
19167      };
19168      const confirm = (message, callback, scope) => {
19169        const windowManagerImpl = getImplementation();
19170        windowManagerImpl.confirm(message, funcBind(scope ? scope : windowManagerImpl, callback));
19171      };
19172      const close = () => {
19173        getTopDialog().each(dialog => {
19174          getImplementation().close(dialog);
19175          closeDialog(dialog);
19176        });
19177      };
19178      editor.on('remove', () => {
19179        each$e(dialogs, dialog => {
19180          getImplementation().close(dialog);
19181        });
19182      });
19183      return {
19184        open,
19185        openUrl,
19186        alert,
19187        confirm,
19188        close
19189      };
19190    };
19191
19192    const displayNotification = (editor, message) => {
19193      editor.notificationManager.open({
19194        type: 'error',
19195        text: message
19196      });
19197    };
19198    const displayError = (editor, message) => {
19199      if (editor._skinLoaded) {
19200        displayNotification(editor, message);
19201      } else {
19202        editor.on('SkinLoaded', () => {
19203          displayNotification(editor, message);
19204        });
19205      }
19206    };
19207    const uploadError = (editor, message) => {
19208      displayError(editor, I18n.translate([
19209        'Failed to upload image: {0}',
19210        message
19211      ]));
19212    };
19213    const logError = (editor, errorType, msg) => {
19214      fireError(editor, errorType, { message: msg });
19215      console.error(msg);
19216    };
19217    const createLoadError = (type, url, name) => name ? `Failed to load ${ type }: ${ name } from url ${ url }` : `Failed to load ${ type } url: ${ url }`;
19218    const pluginLoadError = (editor, url, name) => {
19219      logError(editor, 'PluginLoadError', createLoadError('plugin', url, name));
19220    };
19221    const iconsLoadError = (editor, url, name) => {
19222      logError(editor, 'IconsLoadError', createLoadError('icons', url, name));
19223    };
19224    const languageLoadError = (editor, url, name) => {
19225      logError(editor, 'LanguageLoadError', createLoadError('language', url, name));
19226    };
19227    const themeLoadError = (editor, url, name) => {
19228      logError(editor, 'ThemeLoadError', createLoadError('theme', url, name));
19229    };
19230    const modelLoadError = (editor, url, name) => {
19231      logError(editor, 'ModelLoadError', createLoadError('model', url, name));
19232    };
19233    const pluginInitError = (editor, name, err) => {
19234      const message = I18n.translate([
19235        'Failed to initialize plugin: {0}',
19236        name
19237      ]);
19238      fireError(editor, 'PluginLoadError', { message });
19239      initError(message, err);
19240      displayError(editor, message);
19241    };
19242    const initError = (message, ...x) => {
19243      const console = window.console;
19244      if (console) {
19245        if (console.error) {
19246          console.error(message, ...x);
19247        } else {
19248          console.log(message, ...x);
19249        }
19250      }
19251    };
19252
19253    const isContentCssSkinName = url => /^[a-z0-9\-]+$/i.test(url);
19254    const getContentCssUrls = editor => {
19255      return transformToUrls(editor, getContentCss(editor));
19256    };
19257    const getFontCssUrls = editor => {
19258      return transformToUrls(editor, getFontCss(editor));
19259    };
19260    const transformToUrls = (editor, cssLinks) => {
19261      const skinUrl = editor.editorManager.baseURL + '/skins/content';
19262      const suffix = editor.editorManager.suffix;
19263      const contentCssFile = `content${ suffix }.css`;
19264      return map$3(cssLinks, url => {
19265        if (isContentCssSkinName(url) && !editor.inline) {
19266          return `${ skinUrl }/${ url }/${ contentCssFile }`;
19267        } else {
19268          return editor.documentBaseURI.toAbsolute(url);
19269        }
19270      });
19271    };
19272    const appendContentCssFromSettings = editor => {
19273      editor.contentCSS = editor.contentCSS.concat(getContentCssUrls(editor), getFontCssUrls(editor));
19274    };
19275
19276    const getAllImages = elm => {
19277      return elm ? from(elm.getElementsByTagName('img')) : [];
19278    };
19279    const ImageScanner = (uploadStatus, blobCache) => {
19280      const cachedPromises = {};
19281      const findAll = (elm, predicate = always) => {
19282        const images = filter$5(getAllImages(elm), img => {
19283          const src = img.src;
19284          if (img.hasAttribute('data-mce-bogus')) {
19285            return false;
19286          }
19287          if (img.hasAttribute('data-mce-placeholder')) {
19288            return false;
19289          }
19290          if (!src || src === Env.transparentSrc) {
19291            return false;
19292          }
19293          if (startsWith(src, 'blob:')) {
19294            return !uploadStatus.isUploaded(src) && predicate(img);
19295          }
19296          if (startsWith(src, 'data:')) {
19297            return predicate(img);
19298          }
19299          return false;
19300        });
19301        const promises = map$3(images, img => {
19302          const imageSrc = img.src;
19303          if (has$2(cachedPromises, imageSrc)) {
19304            return cachedPromises[imageSrc].then(imageInfo => {
19305              if (isString(imageInfo)) {
19306                return imageInfo;
19307              } else {
19308                return {
19309                  image: img,
19310                  blobInfo: imageInfo.blobInfo
19311                };
19312              }
19313            });
19314          } else {
19315            const newPromise = imageToBlobInfo(blobCache, imageSrc).then(blobInfo => {
19316              delete cachedPromises[imageSrc];
19317              return {
19318                image: img,
19319                blobInfo
19320              };
19321            }).catch(error => {
19322              delete cachedPromises[imageSrc];
19323              return error;
19324            });
19325            cachedPromises[imageSrc] = newPromise;
19326            return newPromise;
19327          }
19328        });
19329        return Promise.all(promises);
19330      };
19331      return { findAll };
19332    };
19333
19334    const UploadStatus = () => {
19335      const PENDING = 1, UPLOADED = 2;
19336      let blobUriStatuses = {};
19337      const createStatus = (status, resultUri) => {
19338        return {
19339          status,
19340          resultUri
19341        };
19342      };
19343      const hasBlobUri = blobUri => {
19344        return blobUri in blobUriStatuses;
19345      };
19346      const getResultUri = blobUri => {
19347        const result = blobUriStatuses[blobUri];
19348        return result ? result.resultUri : null;
19349      };
19350      const isPending = blobUri => {
19351        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === PENDING : false;
19352      };
19353      const isUploaded = blobUri => {
19354        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === UPLOADED : false;
19355      };
19356      const markPending = blobUri => {
19357        blobUriStatuses[blobUri] = createStatus(PENDING, null);
19358      };
19359      const markUploaded = (blobUri, resultUri) => {
19360        blobUriStatuses[blobUri] = createStatus(UPLOADED, resultUri);
19361      };
19362      const removeFailed = blobUri => {
19363        delete blobUriStatuses[blobUri];
19364      };
19365      const destroy = () => {
19366        blobUriStatuses = {};
19367      };
19368      return {
19369        hasBlobUri,
19370        getResultUri,
19371        isPending,
19372        isUploaded,
19373        markPending,
19374        markUploaded,
19375        removeFailed,
19376        destroy
19377      };
19378    };
19379
19380    let count = 0;
19381    const seed = () => {
19382      const rnd = () => {
19383        return Math.round(Math.random() * 4294967295).toString(36);
19384      };
19385      const now = new Date().getTime();
19386      return 's' + now.toString(36) + rnd() + rnd() + rnd();
19387    };
19388    const uuid = prefix => {
19389      return prefix + count++ + seed();
19390    };
19391
19392    const BlobCache = () => {
19393      let cache = [];
19394      const mimeToExt = mime => {
19395        const mimes = {
19396          'image/jpeg': 'jpg',
19397          'image/jpg': 'jpg',
19398          'image/gif': 'gif',
19399          'image/png': 'png',
19400          'image/apng': 'apng',
19401          'image/avif': 'avif',
19402          'image/svg+xml': 'svg',
19403          'image/webp': 'webp',
19404          'image/bmp': 'bmp',
19405          'image/tiff': 'tiff'
19406        };
19407        return mimes[mime.toLowerCase()] || 'dat';
19408      };
19409      const create = (o, blob, base64, name, filename) => {
19410        if (isString(o)) {
19411          const id = o;
19412          return toBlobInfo({
19413            id,
19414            name,
19415            filename,
19416            blob: blob,
19417            base64: base64
19418          });
19419        } else if (isObject(o)) {
19420          return toBlobInfo(o);
19421        } else {
19422          throw new Error('Unknown input type');
19423        }
19424      };
19425      const toBlobInfo = o => {
19426        if (!o.blob || !o.base64) {
19427          throw new Error('blob and base64 representations of the image are required for BlobInfo to be created');
19428        }
19429        const id = o.id || uuid('blobid');
19430        const name = o.name || id;
19431        const blob = o.blob;
19432        return {
19433          id: constant(id),
19434          name: constant(name),
19435          filename: constant(o.filename || name + '.' + mimeToExt(blob.type)),
19436          blob: constant(blob),
19437          base64: constant(o.base64),
19438          blobUri: constant(o.blobUri || URL.createObjectURL(blob)),
19439          uri: constant(o.uri)
19440        };
19441      };
19442      const add = blobInfo => {
19443        if (!get(blobInfo.id())) {
19444          cache.push(blobInfo);
19445        }
19446      };
19447      const findFirst = predicate => find$2(cache, predicate).getOrUndefined();
19448      const get = id => findFirst(cachedBlobInfo => cachedBlobInfo.id() === id);
19449      const getByUri = blobUri => findFirst(blobInfo => blobInfo.blobUri() === blobUri);
19450      const getByData = (base64, type) => findFirst(blobInfo => blobInfo.base64() === base64 && blobInfo.blob().type === type);
19451      const removeByUri = blobUri => {
19452        cache = filter$5(cache, blobInfo => {
19453          if (blobInfo.blobUri() === blobUri) {
19454            URL.revokeObjectURL(blobInfo.blobUri());
19455            return false;
19456          }
19457          return true;
19458        });
19459      };
19460      const destroy = () => {
19461        each$e(cache, cachedBlobInfo => {
19462          URL.revokeObjectURL(cachedBlobInfo.blobUri());
19463        });
19464        cache = [];
19465      };
19466      return {
19467        create,
19468        add,
19469        get,
19470        getByUri,
19471        getByData,
19472        findFirst,
19473        removeByUri,
19474        destroy
19475      };
19476    };
19477
19478    const Uploader = (uploadStatus, settings) => {
19479      const pendingPromises = {};
19480      const pathJoin = (path1, path2) => {
19481        if (path1) {
19482          return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '');
19483        }
19484        return path2;
19485      };
19486      const defaultHandler = (blobInfo, progress) => new Promise((success, failure) => {
19487        const xhr = new XMLHttpRequest();
19488        xhr.open('POST', settings.url);
19489        xhr.withCredentials = settings.credentials;
19490        xhr.upload.onprogress = e => {
19491          progress(e.loaded / e.total * 100);
19492        };
19493        xhr.onerror = () => {
19494          failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
19495        };
19496        xhr.onload = () => {
19497          if (xhr.status < 200 || xhr.status >= 300) {
19498            failure('HTTP Error: ' + xhr.status);
19499            return;
19500          }
19501          const json = JSON.parse(xhr.responseText);
19502          if (!json || !isString(json.location)) {
19503            failure('Invalid JSON: ' + xhr.responseText);
19504            return;
19505          }
19506          success(pathJoin(settings.basePath, json.location));
19507        };
19508        const formData = new FormData();
19509        formData.append('file', blobInfo.blob(), blobInfo.filename());
19510        xhr.send(formData);
19511      });
19512      const uploadHandler = isFunction(settings.handler) ? settings.handler : defaultHandler;
19513      const noUpload = () => new Promise(resolve => {
19514        resolve([]);
19515      });
19516      const handlerSuccess = (blobInfo, url) => ({
19517        url,
19518        blobInfo,
19519        status: true
19520      });
19521      const handlerFailure = (blobInfo, error) => ({
19522        url: '',
19523        blobInfo,
19524        status: false,
19525        error
19526      });
19527      const resolvePending = (blobUri, result) => {
19528        Tools.each(pendingPromises[blobUri], resolve => {
19529          resolve(result);
19530        });
19531        delete pendingPromises[blobUri];
19532      };
19533      const uploadBlobInfo = (blobInfo, handler, openNotification) => {
19534        uploadStatus.markPending(blobInfo.blobUri());
19535        return new Promise(resolve => {
19536          let notification;
19537          let progress;
19538          try {
19539            const closeNotification = () => {
19540              if (notification) {
19541                notification.close();
19542                progress = noop;
19543              }
19544            };
19545            const success = url => {
19546              closeNotification();
19547              uploadStatus.markUploaded(blobInfo.blobUri(), url);
19548              resolvePending(blobInfo.blobUri(), handlerSuccess(blobInfo, url));
19549              resolve(handlerSuccess(blobInfo, url));
19550            };
19551            const failure = error => {
19552              closeNotification();
19553              uploadStatus.removeFailed(blobInfo.blobUri());
19554              resolvePending(blobInfo.blobUri(), handlerFailure(blobInfo, error));
19555              resolve(handlerFailure(blobInfo, error));
19556            };
19557            progress = percent => {
19558              if (percent < 0 || percent > 100) {
19559                return;
19560              }
19561              Optional.from(notification).orThunk(() => Optional.from(openNotification).map(apply$1)).each(n => {
19562                notification = n;
19563                n.progressBar.value(percent);
19564              });
19565            };
19566            handler(blobInfo, progress).then(success, err => {
19567              failure(isString(err) ? { message: err } : err);
19568            });
19569          } catch (ex) {
19570            resolve(handlerFailure(blobInfo, ex));
19571          }
19572        });
19573      };
19574      const isDefaultHandler = handler => handler === defaultHandler;
19575      const pendingUploadBlobInfo = blobInfo => {
19576        const blobUri = blobInfo.blobUri();
19577        return new Promise(resolve => {
19578          pendingPromises[blobUri] = pendingPromises[blobUri] || [];
19579          pendingPromises[blobUri].push(resolve);
19580        });
19581      };
19582      const uploadBlobs = (blobInfos, openNotification) => {
19583        blobInfos = Tools.grep(blobInfos, blobInfo => !uploadStatus.isUploaded(blobInfo.blobUri()));
19584        return Promise.all(Tools.map(blobInfos, blobInfo => uploadStatus.isPending(blobInfo.blobUri()) ? pendingUploadBlobInfo(blobInfo) : uploadBlobInfo(blobInfo, uploadHandler, openNotification)));
19585      };
19586      const upload = (blobInfos, openNotification) => !settings.url && isDefaultHandler(uploadHandler) ? noUpload() : uploadBlobs(blobInfos, openNotification);
19587      return { upload };
19588    };
19589
19590    const openNotification = editor => () => editor.notificationManager.open({
19591      text: editor.translate('Image uploading...'),
19592      type: 'info',
19593      timeout: -1,
19594      progressBar: true
19595    });
19596    const createUploader = (editor, uploadStatus) => Uploader(uploadStatus, {
19597      url: getImageUploadUrl(editor),
19598      basePath: getImageUploadBasePath(editor),
19599      credentials: getImagesUploadCredentials(editor),
19600      handler: getImagesUploadHandler(editor)
19601    });
19602    const ImageUploader = editor => {
19603      const uploadStatus = UploadStatus();
19604      const uploader = createUploader(editor, uploadStatus);
19605      return { upload: (blobInfos, showNotification = true) => uploader.upload(blobInfos, showNotification ? openNotification(editor) : undefined) };
19606    };
19607
19608    const 
vendor: 3,946 bytes, lines 19608-19696
19608EditorUpload = editor => {
19609      const blobCache = BlobCache();
19610      let uploader, imageScanner;
19611      const uploadStatus = UploadStatus();
19612      const urlFilters = [];
19613      const aliveGuard = callback => {
19614        return result => {
19615          if (editor.selection) {
19616            return callback(result);
19617          }
19618          return [];
19619        };
19620      };
19621      const cacheInvalidator = url => url + (url.indexOf('?') === -1 ? '?' : '&') + new Date().getTime();
19622      const replaceString = (content, search, replace) => {
19623        let index = 0;
19624        do {
19625          index = content.indexOf(search, index);
19626          if (index !== -1) {
19627            content = content.substring(0, index) + replace + content.substr(index + search.length);
19628            index += replace.length - search.length + 1;
19629          }
19630        } while (index !== -1);
19631        return content;
19632      };
19633      const replaceImageUrl = (content, targetUrl, replacementUrl) => {
19634        const replacementString = `src="${ replacementUrl }"${ replacementUrl === Env.transparentSrc ? ' data-mce-placeholder="1"' : '' }`;
19635        content = replaceString(content, `src="${ targetUrl }"`, replacementString);
19636        content = replaceString(content, 'data-mce-src="' + targetUrl + '"', 'data-mce-src="' + replacementUrl + '"');
19637        return content;
19638      };
19639      const replaceUrlInUndoStack = (targetUrl, replacementUrl) => {
19640        each$e(editor.undoManager.data, level => {
19641          if (level.type === 'fragmented') {
19642            level.fragments = map$3(level.fragments, fragment => replaceImageUrl(fragment, targetUrl, replacementUrl));
19643          } else {
19644            level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
19645          }
19646        });
19647      };
19648      const replaceImageUriInView = (image, resultUri) => {
19649        const src = editor.convertURL(resultUri, 'src');
19650        replaceUrlInUndoStack(image.src, resultUri);
19651        setAll$1(SugarElement.fromDom(image), {
19652          'src': shouldReuseFileName(editor) ? cacheInvalidator(resultUri) : resultUri,
19653          'data-mce-src': src
19654        });
19655      };
19656      const uploadImages = () => {
19657        if (!uploader) {
19658          uploader = createUploader(editor, uploadStatus);
19659        }
19660        return scanForImages().then(aliveGuard(imageInfos => {
19661          const blobInfos = map$3(imageInfos, imageInfo => imageInfo.blobInfo);
19662          return uploader.upload(blobInfos, openNotification(editor)).then(aliveGuard(result => {
19663            const imagesToRemove = [];
19664            let shouldDispatchChange = false;
19665            const filteredResult = map$3(result, (uploadInfo, index) => {
19666              const {blobInfo, image} = imageInfos[index];
19667              let removed = false;
19668              if (uploadInfo.status && shouldReplaceBlobUris(editor)) {
19669                if (uploadInfo.url && !contains$1(image.src, uploadInfo.url)) {
19670                  shouldDispatchChange = true;
19671                }
19672                blobCache.removeByUri(image.src);
19673                if (isRtc(editor)) ; else {
19674                  replaceImageUriInView(image, uploadInfo.url);
19675                }
19676              } else if (uploadInfo.error) {
19677                if (uploadInfo.error.remove) {
19678                  replaceUrlInUndoStack(image.src, Env.transparentSrc);
19679                  imagesToRemove.push(image);
19680                  removed = true;
19681                }
19682                uploadError(editor, uploadInfo.error.message);
19683              }
19684              return {
19685                element: image,
19686                status: uploadInfo.status,
19687                uploadUri: uploadInfo.url,
19688                blobInfo,
19689                removed
19690              };
19691            });
19692            if (imagesToRemove.length > 0 && !isRtc(editor)) {
19693              editor.undoManager.transact(() => {
19694                each$e(imagesToRemove, element => {
19695                  editor.dom.remove(element);
19696                  blobCache.removeByUri(element
vendor: 26,293 bytes, lines 19696-20566
19696.src);
19697                });
19698              });
19699            } else if (shouldDispatchChange) {
19700              editor.undoManager.dispatchChange();
19701            }
19702            return filteredResult;
19703          }));
19704        }));
19705      };
19706      const uploadImagesAuto = () => isAutomaticUploadsEnabled(editor) ? uploadImages() : Promise.resolve([]);
19707      const isValidDataUriImage = imgElm => forall(urlFilters, filter => filter(imgElm));
19708      const addFilter = filter => {
19709        urlFilters.push(filter);
19710      };
19711      const scanForImages = () => {
19712        if (!imageScanner) {
19713          imageScanner = ImageScanner(uploadStatus, blobCache);
19714        }
19715        return imageScanner.findAll(editor.getBody(), isValidDataUriImage).then(aliveGuard(result => {
19716          const filteredResult = filter$5(result, resultItem => {
19717            if (isString(resultItem)) {
19718              displayError(editor, resultItem);
19719              return false;
19720            } else if (resultItem.uriType === 'blob') {
19721              return false;
19722            } else {
19723              return true;
19724            }
19725          });
19726          if (isRtc(editor)) ; else {
19727            each$e(filteredResult, resultItem => {
19728              replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
19729              resultItem.image.src = resultItem.blobInfo.blobUri();
19730              resultItem.image.removeAttribute('data-mce-src');
19731            });
19732          }
19733          return filteredResult;
19734        }));
19735      };
19736      const destroy = () => {
19737        blobCache.destroy();
19738        uploadStatus.destroy();
19739        imageScanner = uploader = null;
19740      };
19741      const replaceBlobUris = content => {
19742        return content.replace(/src="(blob:[^"]+)"/g, (match, blobUri) => {
19743          const resultUri = uploadStatus.getResultUri(blobUri);
19744          if (resultUri) {
19745            return 'src="' + resultUri + '"';
19746          }
19747          let blobInfo = blobCache.getByUri(blobUri);
19748          if (!blobInfo) {
19749            blobInfo = foldl(editor.editorManager.get(), (result, editor) => {
19750              return result || editor.editorUpload && editor.editorUpload.blobCache.getByUri(blobUri);
19751            }, undefined);
19752          }
19753          if (blobInfo) {
19754            const blob = blobInfo.blob();
19755            return 'src="data:' + blob.type + ';base64,' + blobInfo.base64() + '"';
19756          }
19757          return match;
19758        });
19759      };
19760      editor.on('SetContent', () => {
19761        if (isAutomaticUploadsEnabled(editor)) {
19762          uploadImagesAuto();
19763        } else {
19764          scanForImages();
19765        }
19766      });
19767      editor.on('RawSaveContent', e => {
19768        e.content = replaceBlobUris(e.content);
19769      });
19770      editor.on('GetContent', e => {
19771        if (e.source_view || e.format === 'raw' || e.format === 'tree') {
19772          return;
19773        }
19774        e.content = replaceBlobUris(e.content);
19775      });
19776      editor.on('PostRender', () => {
19777        editor.parser.addNodeFilter('img', images => {
19778          each$e(images, img => {
19779            const src = img.attr('src');
19780            if (!src || blobCache.getByUri(src)) {
19781              return;
19782            }
19783            const resultUri = uploadStatus.getResultUri(src);
19784            if (resultUri) {
19785              img.attr('src', resultUri);
19786            }
19787          });
19788        });
19789      });
19790      return {
19791        blobCache,
19792        addFilter,
19793        uploadImages,
19794        uploadImagesAuto,
19795        scanForImages,
19796        destroy
19797      };
19798    };
19799
19800    const get$1 = editor => {
19801      const dom = editor.dom;
19802      const schemaType = editor.schema.type;
19803      const formats = {
19804        valigntop: [{
19805            selector: 'td,th',
19806            styles: { verticalAlign: 'top' }
19807          }],
19808        valignmiddle: [{
19809            selector: 'td,th',
19810            styles: { verticalAlign: 'middle' }
19811          }],
19812        valignbottom: [{
19813            selector: 'td,th',
19814            styles: { verticalAlign: 'bottom' }
19815          }],
19816        alignleft: [
19817          {
19818            selector: 'figure.image',
19819            collapsed: false,
19820            classes: 'align-left',
19821            ceFalseOverride: true,
19822            preview: 'font-family font-size'
19823          },
19824          {
19825            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
19826            styles: { textAlign: 'left' },
19827            inherit: false,
19828            preview: false
19829          },
19830          {
19831            selector: 'img,audio,video',
19832            collapsed: false,
19833            styles: { float: 'left' },
19834            preview: 'font-family font-size'
19835          },
19836          {
19837            selector: 'table',
19838            collapsed: false,
19839            styles: {
19840              marginLeft: '0px',
19841              marginRight: 'auto'
19842            },
19843            onformat: table => {
19844              dom.setStyle(table, 'float', null);
19845            },
19846            preview: 'font-family font-size'
19847          },
19848          {
19849            selector: '.mce-preview-object,[data-ephox-embed-iri]',
19850            ceFalseOverride: true,
19851            styles: { float: 'left' }
19852          }
19853        ],
19854        aligncenter: [
19855          {
19856            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
19857            styles: { textAlign: 'center' },
19858            inherit: false,
19859            preview: 'font-family font-size'
19860          },
19861          {
19862            selector: 'figure.image',
19863            collapsed: false,
19864            classes: 'align-center',
19865            ceFalseOverride: true,
19866            preview: 'font-family font-size'
19867          },
19868          {
19869            selector: 'img,audio,video',
19870            collapsed: false,
19871            styles: {
19872              display: 'block',
19873              marginLeft: 'auto',
19874              marginRight: 'auto'
19875            },
19876            preview: false
19877          },
19878          {
19879            selector: 'table',
19880            collapsed: false,
19881            styles: {
19882              marginLeft: 'auto',
19883              marginRight: 'auto'
19884            },
19885            preview: 'font-family font-size'
19886          },
19887          {
19888            selector: '.mce-preview-object',
19889            ceFalseOverride: true,
19890            styles: {
19891              display: 'table',
19892              marginLeft: 'auto',
19893              marginRight: 'auto'
19894            },
19895            preview: false
19896          },
19897          {
19898            selector: '[data-ephox-embed-iri]',
19899            ceFalseOverride: true,
19900            styles: {
19901              marginLeft: 'auto',
19902              marginRight: 'auto'
19903            },
19904            preview: false
19905          }
19906        ],
19907        alignright: [
19908          {
19909            selector: 'figure.image',
19910            collapsed: false,
19911            classes: 'align-right',
19912            ceFalseOverride: true,
19913            preview: 'font-family font-size'
19914          },
19915          {
19916            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
19917            styles: { textAlign: 'right' },
19918            inherit: false,
19919            preview: 'font-family font-size'
19920          },
19921          {
19922            selector: 'img,audio,video',
19923            collapsed: false,
19924            styles: { float: 'right' },
19925            preview: 'font-family font-size'
19926          },
19927          {
19928            selector: 'table',
19929            collapsed: false,
19930            styles: {
19931              marginRight: '0px',
19932              marginLeft: 'auto'
19933            },
19934            onformat: table => {
19935              dom.setStyle(table, 'float', null);
19936            },
19937            preview: 'font-family font-size'
19938          },
19939          {
19940            selector: '.mce-preview-object,[data-ephox-embed-iri]',
19941            ceFalseOverride: true,
19942            styles: { float: 'right' },
19943            preview: false
19944          }
19945        ],
19946        alignjustify: [{
19947            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
19948            styles: { textAlign: 'justify' },
19949            inherit: false,
19950            preview: 'font-family font-size'
19951          }],
19952        bold: [
19953          {
19954            inline: 'strong',
19955            remove: 'all',
19956            preserve_attributes: [
19957              'class',
19958              'style'
19959            ]
19960          },
19961          {
19962            inline: 'span',
19963            styles: { fontWeight: 'bold' }
19964          },
19965          {
19966            inline: 'b',
19967            remove: 'all',
19968            preserve_attributes: [
19969              'class',
19970              'style'
19971            ]
19972          }
19973        ],
19974        italic: [
19975          {
19976            inline: 'em',
19977            remove: 'all',
19978            preserve_attributes: [
19979              'class',
19980              'style'
19981            ]
19982          },
19983          {
19984            inline: 'span',
19985            styles: { fontStyle: 'italic' }
19986          },
19987          {
19988            inline: 'i',
19989            remove: 'all',
19990            preserve_attributes: [
19991              'class',
19992              'style'
19993            ]
19994          }
19995        ],
19996        underline: [
19997          {
19998            inline: 'span',
19999            styles: { textDecoration: 'underline' },
20000            exact: true
20001          },
20002          {
20003            inline: 'u',
20004            remove: 'all',
20005            preserve_attributes: [
20006              'class',
20007              'style'
20008            ]
20009          }
20010        ],
20011        strikethrough: (() => {
20012          const span = {
20013            inline: 'span',
20014            styles: { textDecoration: 'line-through' },
20015            exact: true
20016          };
20017          const strike = {
20018            inline: 'strike',
20019            remove: 'all',
20020            preserve_attributes: [
20021              'class',
20022              'style'
20023            ]
20024          };
20025          const s = {
20026            inline: 's',
20027            remove: 'all',
20028            preserve_attributes: [
20029              'class',
20030              'style'
20031            ]
20032          };
20033          return schemaType !== 'html4' ? [
20034            s,
20035            span,
20036            strike
20037          ] : [
20038            span,
20039            s,
20040            strike
20041          ];
20042        })(),
20043        forecolor: {
20044          inline: 'span',
20045          styles: { color: '%value' },
20046          links: true,
20047          remove_similar: true,
20048          clear_child_styles: true
20049        },
20050        hilitecolor: {
20051          inline: 'span',
20052          styles: { backgroundColor: '%value' },
20053          links: true,
20054          remove_similar: true,
20055          clear_child_styles: true
20056        },
20057        fontname: {
20058          inline: 'span',
20059          toggle: false,
20060          styles: { fontFamily: '%value' },
20061          clear_child_styles: true
20062        },
20063        fontsize: {
20064          inline: 'span',
20065          toggle: false,
20066          styles: { fontSize: '%value' },
20067          clear_child_styles: true
20068        },
20069        lineheight: {
20070          selector: 'h1,h2,h3,h4,h5,h6,p,li,td,th,div',
20071          styles: { lineHeight: '%value' }
20072        },
20073        fontsize_class: {
20074          inline: 'span',
20075          attributes: { class: '%value' }
20076        },
20077        blockquote: {
20078          block: 'blockquote',
20079          wrapper: true,
20080          remove: 'all'
20081        },
20082        subscript: { inline: 'sub' },
20083        superscript: { inline: 'sup' },
20084        code: { inline: 'code' },
20085        link: {
20086          inline: 'a',
20087          selector: 'a',
20088          remove: 'all',
20089          split: true,
20090          deep: true,
20091          onmatch: (node, _fmt, _itemName) => {
20092            return isElement$6(node) && node.hasAttribute('href');
20093          },
20094          onformat: (elm, _fmt, vars) => {
20095            Tools.each(vars, (value, key) => {
20096              dom.setAttrib(elm, key, value);
20097            });
20098          }
20099        },
20100        lang: {
20101          inline: 'span',
20102          clear_child_styles: true,
20103          remove_similar: true,
20104          attributes: {
20105            'lang': '%value',
20106            'data-mce-lang': vars => {
20107              var _a;
20108              return (_a = vars === null || vars === void 0 ? void 0 : vars.customValue) !== null && _a !== void 0 ? _a : null;
20109            }
20110          }
20111        },
20112        removeformat: [
20113          {
20114            selector: 'b,strong,em,i,font,u,strike,s,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins,small',
20115            remove: 'all',
20116            split: true,
20117            expand: false,
20118            block_expand: true,
20119            deep: true
20120          },
20121          {
20122            selector: 'span',
20123            attributes: [
20124              'style',
20125              'class'
20126            ],
20127            remove: 'empty',
20128            split: true,
20129            expand: false,
20130            deep: true
20131          },
20132          {
20133            selector: '*',
20134            attributes: [
20135              'style',
20136              'class'
20137            ],
20138            split: false,
20139            expand: false,
20140            deep: true
20141          }
20142        ]
20143      };
20144      Tools.each('p h1 h2 h3 h4 h5 h6 div address pre dt dd samp'.split(/\s/), name => {
20145        formats[name] = {
20146          block: name,
20147          remove: 'all'
20148        };
20149      });
20150      return formats;
20151    };
20152
20153    const genericBase = {
20154      remove_similar: true,
20155      inherit: false
20156    };
20157    const cellBase = {
20158      selector: 'td,th',
20159      ...genericBase
20160    };
20161    const cellFormats = {
20162      tablecellbackgroundcolor: {
20163        styles: { backgroundColor: '%value' },
20164        ...cellBase
20165      },
20166      tablecellverticalalign: {
20167        styles: { 'vertical-align': '%value' },
20168        ...cellBase
20169      },
20170      tablecellbordercolor: {
20171        styles: { borderColor: '%value' },
20172        ...cellBase
20173      },
20174      tablecellclass: {
20175        classes: ['%value'],
20176        ...cellBase
20177      },
20178      tableclass: {
20179        selector: 'table',
20180        classes: ['%value'],
20181        ...genericBase
20182      },
20183      tablecellborderstyle: {
20184        styles: { borderStyle: '%value' },
20185        ...cellBase
20186      },
20187      tablecellborderwidth: {
20188        styles: { borderWidth: '%value' },
20189        ...cellBase
20190      }
20191    };
20192    const get = constant(cellFormats);
20193
20194    const FormatRegistry = editor => {
20195      const formats = {};
20196      const get$2 = name => isNonNullable(name) ? formats[name] : formats;
20197      const has = name => has$2(formats, name);
20198      const register = (name, format) => {
20199        if (name) {
20200          if (!isString(name)) {
20201            each$d(name, (format, name) => {
20202              register(name, format);
20203            });
20204          } else {
20205            if (!isArray$1(format)) {
20206              format = [format];
20207            }
20208            each$e(format, format => {
20209              if (isUndefined(format.deep)) {
20210                format.deep = !isSelectorFormat(format);
20211              }
20212              if (isUndefined(format.split)) {
20213                format.split = !isSelectorFormat(format) || isInlineFormat(format);
20214              }
20215              if (isUndefined(format.remove) && isSelectorFormat(format) && !isInlineFormat(format)) {
20216                format.remove = 'none';
20217              }
20218              if (isSelectorFormat(format) && isInlineFormat(format)) {
20219                format.mixed = true;
20220                format.block_expand = true;
20221              }
20222              if (isString(format.classes)) {
20223                format.classes = format.classes.split(/\s+/);
20224              }
20225            });
20226            formats[name] = format;
20227          }
20228        }
20229      };
20230      const unregister = name => {
20231        if (name && formats[name]) {
20232          delete formats[name];
20233        }
20234        return formats;
20235      };
20236      register(get$1(editor));
20237      register(get());
20238      register(getFormats(editor));
20239      return {
20240        get: get$2,
20241        has,
20242        register,
20243        unregister
20244      };
20245    };
20246
20247    const each$3 = Tools.each;
20248    const dom = DOMUtils.DOM;
20249    const isPreviewItem = item => isNonNullable(item) && isObject(item);
20250    const parsedSelectorToHtml = (ancestry, editor) => {
20251      const schema = editor && editor.schema || Schema({});
20252      const decorate = (elm, item) => {
20253        if (item.classes.length > 0) {
20254          dom.addClass(elm, item.classes.join(' '));
20255        }
20256        dom.setAttribs(elm, item.attrs);
20257      };
20258      const createElement = sItem => {
20259        const item = isString(sItem) ? {
20260          name: sItem,
20261          classes: [],
20262          attrs: {}
20263        } : sItem;
20264        const elm = dom.create(item.name);
20265        decorate(elm, item);
20266        return elm;
20267      };
20268      const getRequiredParent = (elm, candidate) => {
20269        const elmRule = schema.getElementRule(elm.nodeName.toLowerCase());
20270        const parentsRequired = elmRule === null || elmRule === void 0 ? void 0 : elmRule.parentsRequired;
20271        if (parentsRequired && parentsRequired.length) {
20272          return candidate && contains$2(parentsRequired, candidate) ? candidate : parentsRequired[0];
20273        } else {
20274          return false;
20275        }
20276      };
20277      const wrapInHtml = (elm, ancestors, siblings) => {
20278        let parentCandidate;
20279        const ancestor = ancestors[0];
20280        const ancestorName = isPreviewItem(ancestor) ? ancestor.name : undefined;
20281        const parentRequired = getRequiredParent(elm, ancestorName);
20282        if (parentRequired) {
20283          if (ancestorName === parentRequired) {
20284            parentCandidate = ancestor;
20285            ancestors = ancestors.slice(1);
20286          } else {
20287            parentCandidate = parentRequired;
20288          }
20289        } else if (ancestor) {
20290          parentCandidate = ancestor;
20291          ancestors = ancestors.slice(1);
20292        } else if (!siblings) {
20293          return elm;
20294        }
20295        const parent = parentCandidate ? createElement(parentCandidate) : dom.create('div');
20296        parent.appendChild(elm);
20297        if (siblings) {
20298          Tools.each(siblings, sibling => {
20299            const siblingElm = createElement(sibling);
20300            parent.insertBefore(siblingElm, elm);
20301          });
20302        }
20303        const parentSiblings = isPreviewItem(parentCandidate) ? parentCandidate.siblings : undefined;
20304        return wrapInHtml(parent, ancestors, parentSiblings);
20305      };
20306      const fragment = dom.create('div');
20307      if (ancestry.length > 0) {
20308        const item = ancestry[0];
20309        const elm = createElement(item);
20310        const siblings = isPreviewItem(item) ? item.siblings : undefined;
20311        fragment.appendChild(wrapInHtml(elm, ancestry.slice(1), siblings));
20312      }
20313      return fragment;
20314    };
20315    const parseSelectorItem = item => {
20316      item = Tools.trim(item);
20317      let tagName = 'div';
20318      const obj = {
20319        name: tagName,
20320        classes: [],
20321        attrs: {},
20322        selector: item
20323      };
20324      if (item !== '*') {
20325        tagName = item.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g, ($0, $1, $2, $3, $4) => {
20326          switch ($1) {
20327          case '#':
20328            obj.attrs.id = $2;
20329            break;
20330          case '.':
20331            obj.classes.push($2);
20332            break;
20333          case ':':
20334            if (Tools.inArray('checked disabled enabled read-only required'.split(' '), $2) !== -1) {
20335              obj.attrs[$2] = $2;
20336            }
20337            break;
20338          }
20339          if ($3 === '[') {
20340            const m = $4.match(/([\w\-]+)(?:\=\"([^\"]+))?/);
20341            if (m) {
20342              obj.attrs[m[1]] = m[2];
20343            }
20344          }
20345          return '';
20346        });
20347      }
20348      obj.name = tagName || 'div';
20349      return obj;
20350    };
20351    const parseSelector = selector => {
20352      if (!isString(selector)) {
20353        return [];
20354      }
20355      selector = selector.split(/\s*,\s*/)[0];
20356      selector = selector.replace(/\s*(~\+|~|\+|>)\s*/g, '$1');
20357      return Tools.map(selector.split(/(?:>|\s+(?![^\[\]]+\]))/), item => {
20358        const siblings = Tools.map(item.split(/(?:~\+|~|\+)/), parseSelectorItem);
20359        const obj = siblings.pop();
20360        if (siblings.length) {
20361          obj.siblings = siblings;
20362        }
20363        return obj;
20364      }).reverse();
20365    };
20366    const getCssText = (editor, format) => {
20367      let previewCss = '';
20368      let previewStyles = getPreviewStyles(editor);
20369      if (previewStyles === '') {
20370        return '';
20371      }
20372      const removeVars = val => {
20373        return isString(val) ? val.replace(/%(\w+)/g, '') : '';
20374      };
20375      const getComputedStyle = (name, elm) => {
20376        return dom.getStyle(elm !== null && elm !== void 0 ? elm : editor.getBody(), name, true);
20377      };
20378      if (isString(format)) {
20379        const formats = editor.formatter.get(format);
20380        if (!formats) {
20381          return '';
20382        }
20383        format = formats[0];
20384      }
20385      if ('preview' in format) {
20386        const preview = format.preview;
20387        if (preview === false) {
20388          return '';
20389        } else {
20390          previewStyles = preview || previewStyles;
20391        }
20392      }
20393      let name = format.block || format.inline || 'span';
20394      let previewFrag;
20395      const items = parseSelector(format.selector);
20396      if (items.length > 0) {
20397        if (!items[0].name) {
20398          items[0].name = name;
20399        }
20400        name = format.selector;
20401        previewFrag = parsedSelectorToHtml(items, editor);
20402      } else {
20403        previewFrag = parsedSelectorToHtml([name], editor);
20404      }
20405      const previewElm = dom.select(name, previewFrag)[0] || previewFrag.firstChild;
20406      each$3(format.styles, (value, name) => {
20407        const newValue = removeVars(value);
20408        if (newValue) {
20409          dom.setStyle(previewElm, name, newValue);
20410        }
20411      });
20412      each$3(format.attributes, (value, name) => {
20413        const newValue = removeVars(value);
20414        if (newValue) {
20415          dom.setAttrib(previewElm, name, newValue);
20416        }
20417      });
20418      each$3(format.classes, value => {
20419        const newValue = removeVars(value);
20420        if (!dom.hasClass(previewElm, newValue)) {
20421          dom.addClass(previewElm, newValue);
20422        }
20423      });
20424      editor.dispatch('PreviewFormats');
20425      dom.setStyles(previewFrag, {
20426        position: 'absolute',
20427        left: -65535
20428      });
20429      editor.getBody().appendChild(previewFrag);
20430      const rawParentFontSize = getComputedStyle('fontSize');
20431      const parentFontSize = /px$/.test(rawParentFontSize) ? parseInt(rawParentFontSize, 10) : 0;
20432      each$3(previewStyles.split(' '), name => {
20433        let value = getComputedStyle(name, previewElm);
20434        if (name === 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) {
20435          value = getComputedStyle(name);
20436          if (rgbaToHexString(value).toLowerCase() === '#ffffff') {
20437            return;
20438          }
20439        }
20440        if (name === 'color') {
20441          if (rgbaToHexString(value).toLowerCase() === '#000000') {
20442            return;
20443          }
20444        }
20445        if (name === 'font-size') {
20446          if (/em|%$/.test(value)) {
20447            if (parentFontSize === 0) {
20448              return;
20449            }
20450            const numValue = parseFloat(value) / (/%$/.test(value) ? 100 : 1);
20451            value = numValue * parentFontSize + 'px';
20452          }
20453        }
20454        if (name === 'border' && value) {
20455          previewCss += 'padding:0 2px;';
20456        }
20457        previewCss += name + ':' + value + ';';
20458      });
20459      editor.dispatch('AfterPreviewFormats');
20460      dom.remove(previewFrag);
20461      return previewCss;
20462    };
20463
20464    const setup$r = editor => {
20465      editor.addShortcut('meta+b', '', 'Bold');
20466      editor.addShortcut('meta+i', '', 'Italic');
20467      editor.addShortcut('meta+u', '', 'Underline');
20468      for (let i = 1; i <= 6; i++) {
20469        editor.addShortcut('access+' + i, '', [
20470          'FormatBlock',
20471          false,
20472          'h' + i
20473        ]);
20474      }
20475      editor.addShortcut('access+7', '', [
20476        'FormatBlock',
20477        false,
20478        'p'
20479      ]);
20480      editor.addShortcut('access+8', '', [
20481        'FormatBlock',
20482        false,
20483        'div'
20484      ]);
20485      editor.addShortcut('access+9', '', [
20486        'FormatBlock',
20487        false,
20488        'address'
20489      ]);
20490    };
20491
20492    const Formatter = editor => {
20493      const formats = FormatRegistry(editor);
20494      const formatChangeState = Cell({});
20495      setup$r(editor);
20496      setup$u(editor);
20497      if (!isRtc(editor)) {
20498        setup$t(formatChangeState, editor);
20499      }
20500      return {
20501        get: formats.get,
20502        has: formats.has,
20503        register: formats.register,
20504        unregister: formats.unregister,
20505        apply: (name, vars, node) => {
20506          applyFormat(editor, name, vars, node);
20507        },
20508        remove: (name, vars, node, similar) => {
20509          removeFormat(editor, name, vars, node, similar);
20510        },
20511        toggle: (name, vars, node) => {
20512          toggleFormat(editor, name, vars, node);
20513        },
20514        match: (name, vars, node, similar) => matchFormat(editor, name, vars, node, similar),
20515        closest: names => closestFormat(editor, names),
20516        matchAll: (names, vars) => matchAllFormats(editor, names, vars),
20517        matchNode: (node, name, vars, similar) => matchNodeFormat(editor, node, name, vars, similar),
20518        canApply: name => canApplyFormat(editor, name),
20519        formatChanged: (formats, callback, similar, vars) => formatChanged(editor, formatChangeState, formats, callback, similar, vars),
20520        getCssText: curry(getCssText, editor)
20521      };
20522    };
20523
20524    const shouldIgnoreCommand = cmd => {
20525      switch (cmd.toLowerCase()) {
20526      case 'undo':
20527      case 'redo':
20528      case 'mcefocus':
20529        return true;
20530      default:
20531        return false;
20532      }
20533    };
20534    const registerEvents = (editor, undoManager, locks) => {
20535      const isFirstTypedCharacter = Cell(false);
20536      const addNonTypingUndoLevel = e => {
20537        setTyping(undoManager, false, locks);
20538        undoManager.add({}, e);
20539      };
20540      editor.on('init', () => {
20541        undoManager.add();
20542      });
20543      editor.on('BeforeExecCommand', e => {
20544        const cmd = e.command;
20545        if (!shouldIgnoreCommand(cmd)) {
20546          endTyping(undoManager, locks);
20547          undoManager.beforeChange();
20548        }
20549      });
20550      editor.on('ExecCommand', e => {
20551        const cmd = e.command;
20552        if (!shouldIgnoreCommand(cmd)) {
20553          addNonTypingUndoLevel(e);
20554        }
20555      });
20556      editor.on('ObjectResizeStart cut', () => {
20557        undoManager.beforeChange();
20558      });
20559      editor.on('SaveContent ObjectResized blur', addNonTypingUndoLevel);
20560      editor.on('dragend', addNonTypingUndoLevel);
20561      editor.on('keyup', e => {
20562        const keyCode = e.keyCode;
20563        if (e.isDefaultPrevented()) {
20564          return;
20565        }
20566        
vendor: 1,294 bytes, lines 20566-20598
20566if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45 || e.ctrlKey) {
20567          addNonTypingUndoLevel();
20568          editor.nodeChanged();
20569        }
20570        if (keyCode === 46 || keyCode === 8) {
20571          editor.nodeChanged();
20572        }
20573        if (isFirstTypedCharacter.get() && undoManager.typing && !isEq$1(createFromEditor(editor), undoManager.data[0])) {
20574          if (!editor.isDirty()) {
20575            editor.setDirty(true);
20576          }
20577          editor.dispatch('TypingUndo');
20578          isFirstTypedCharacter.set(false);
20579          editor.nodeChanged();
20580        }
20581      });
20582      editor.on('keydown', e => {
20583        const keyCode = e.keyCode;
20584        if (e.isDefaultPrevented()) {
20585          return;
20586        }
20587        if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45) {
20588          if (undoManager.typing) {
20589            addNonTypingUndoLevel(e);
20590          }
20591          return;
20592        }
20593        const modKey = e.ctrlKey && !e.altKey || e.metaKey;
20594        if ((keyCode < 16 || keyCode > 20) && keyCode !== 224 && keyCode !== 91 && !undoManager.typing && !modKey) {
20595          undoManager.beforeChange();
20596          setTyping(undoManager, true, locks);
20597          undoManager.add({}, e);
20598          isFirstTypedCharacter.set(true
vendor: 8,750 bytes, lines 20598-20818
20598);
20599        }
20600      });
20601      editor.on('mousedown', e => {
20602        if (undoManager.typing) {
20603          addNonTypingUndoLevel(e);
20604        }
20605      });
20606      const isInsertReplacementText = event => event.inputType === 'insertReplacementText';
20607      const isInsertTextDataNull = event => event.inputType === 'insertText' && event.data === null;
20608      const isInsertFromPasteOrDrop = event => event.inputType === 'insertFromPaste' || event.inputType === 'insertFromDrop';
20609      editor.on('input', e => {
20610        if (e.inputType && (isInsertReplacementText(e) || isInsertTextDataNull(e) || isInsertFromPasteOrDrop(e))) {
20611          addNonTypingUndoLevel(e);
20612        }
20613      });
20614      editor.on('AddUndo Undo Redo ClearUndos', e => {
20615        if (!e.isDefaultPrevented()) {
20616          editor.nodeChanged();
20617        }
20618      });
20619    };
20620    const addKeyboardShortcuts = editor => {
20621      editor.addShortcut('meta+z', '', 'Undo');
20622      editor.addShortcut('meta+y,meta+shift+z', '', 'Redo');
20623    };
20624
20625    const UndoManager = editor => {
20626      const beforeBookmark = value$2();
20627      const locks = Cell(0);
20628      const index = Cell(0);
20629      const undoManager = {
20630        data: [],
20631        typing: false,
20632        beforeChange: () => {
20633          beforeChange(editor, locks, beforeBookmark);
20634        },
20635        add: (level, event) => {
20636          return addUndoLevel(editor, undoManager, index, locks, beforeBookmark, level, event);
20637        },
20638        dispatchChange: () => {
20639          editor.setDirty(true);
20640          const level = createFromEditor(editor);
20641          level.bookmark = getUndoBookmark(editor.selection);
20642          editor.dispatch('change', {
20643            level,
20644            lastLevel: get$b(undoManager.data, index.get()).getOrUndefined()
20645          });
20646        },
20647        undo: () => {
20648          return undo(editor, undoManager, locks, index);
20649        },
20650        redo: () => {
20651          return redo(editor, index, undoManager.data);
20652        },
20653        clear: () => {
20654          clear(editor, undoManager, index);
20655        },
20656        reset: () => {
20657          reset(editor, undoManager);
20658        },
20659        hasUndo: () => {
20660          return hasUndo(editor, undoManager, index);
20661        },
20662        hasRedo: () => {
20663          return hasRedo(editor, undoManager, index);
20664        },
20665        transact: callback => {
20666          return transact(editor, undoManager, locks, callback);
20667        },
20668        ignore: callback => {
20669          ignore(editor, locks, callback);
20670        },
20671        extra: (callback1, callback2) => {
20672          extra(editor, undoManager, index, callback1, callback2);
20673        }
20674      };
20675      if (!isRtc(editor)) {
20676        registerEvents(editor, undoManager, locks);
20677      }
20678      addKeyboardShortcuts(editor);
20679      return undoManager;
20680    };
20681
20682    const nonTypingKeycodes = [
20683      9,
20684      27,
20685      VK.HOME,
20686      VK.END,
20687      19,
20688      20,
20689      44,
20690      144,
20691      145,
20692      33,
20693      34,
20694      45,
20695      16,
20696      17,
20697      18,
20698      91,
20699      92,
20700      93,
20701      VK.DOWN,
20702      VK.UP,
20703      VK.LEFT,
20704      VK.RIGHT
20705    ].concat(Env.browser.isFirefox() ? [224] : []);
20706    const placeholderAttr = 'data-mce-placeholder';
20707    const isKeyboardEvent = e => e.type === 'keydown' || e.type === 'keyup';
20708    const isDeleteEvent = e => {
20709      const keyCode = e.keyCode;
20710      return keyCode === VK.BACKSPACE || keyCode === VK.DELETE;
20711    };
20712    const isNonTypingKeyboardEvent = e => {
20713      if (isKeyboardEvent(e)) {
20714        const keyCode = e.keyCode;
20715        return !isDeleteEvent(e) && (VK.metaKeyPressed(e) || e.altKey || keyCode >= 112 && keyCode <= 123 || contains$2(nonTypingKeycodes, keyCode));
20716      } else {
20717        return false;
20718      }
20719    };
20720    const isTypingKeyboardEvent = e => isKeyboardEvent(e) && !(isDeleteEvent(e) || e.type === 'keyup' && e.keyCode === 229);
20721    const isVisuallyEmpty = (dom, rootElm, forcedRootBlock) => {
20722      if (isEmpty$2(SugarElement.fromDom(rootElm), false)) {
20723        const firstElement = rootElm.firstElementChild;
20724        if (!firstElement) {
20725          return true;
20726        } else if (dom.getStyle(rootElm.firstElementChild, 'padding-left') || dom.getStyle(rootElm.firstElementChild, 'padding-right')) {
20727          return false;
20728        } else {
20729          return forcedRootBlock === firstElement.nodeName.toLowerCase();
20730        }
20731      } else {
20732        return false;
20733      }
20734    };
20735    const setup$q = editor => {
20736      var _a;
20737      const dom = editor.dom;
20738      const rootBlock = getForcedRootBlock(editor);
20739      const placeholder = (_a = getPlaceholder(editor)) !== null && _a !== void 0 ? _a : '';
20740      const updatePlaceholder = (e, initial) => {
20741        if (isNonTypingKeyboardEvent(e)) {
20742          return;
20743        }
20744        const body = editor.getBody();
20745        const showPlaceholder = isTypingKeyboardEvent(e) ? false : isVisuallyEmpty(dom, body, rootBlock);
20746        const isPlaceholderShown = dom.getAttrib(body, placeholderAttr) !== '';
20747        if (isPlaceholderShown !== showPlaceholder || initial) {
20748          dom.setAttrib(body, placeholderAttr, showPlaceholder ? placeholder : null);
20749          dom.setAttrib(body, 'aria-placeholder', showPlaceholder ? placeholder : null);
20750          firePlaceholderToggle(editor, showPlaceholder);
20751          editor.on(showPlaceholder ? 'keydown' : 'keyup', updatePlaceholder);
20752          editor.off(showPlaceholder ? 'keyup' : 'keydown', updatePlaceholder);
20753        }
20754      };
20755      if (isNotEmpty(placeholder)) {
20756        editor.on('init', e => {
20757          updatePlaceholder(e, true);
20758          editor.on('change SetContent ExecCommand', updatePlaceholder);
20759          editor.on('paste', e => Delay.setEditorTimeout(editor, () => updatePlaceholder(e)));
20760        });
20761      }
20762    };
20763
20764    const blockPosition = (block, position) => ({
20765      block,
20766      position
20767    });
20768    const blockBoundary = (from, to) => ({
20769      from,
20770      to
20771    });
20772    const getBlockPosition = (rootNode, pos) => {
20773      const rootElm = SugarElement.fromDom(rootNode);
20774      const containerElm = SugarElement.fromDom(pos.container());
20775      return getParentBlock$2(rootElm, containerElm).map(block => blockPosition(block, pos));
20776    };
20777    const isDifferentBlocks = blockBoundary => !eq(blockBoundary.from.block, blockBoundary.to.block);
20778    const getClosestHost = (root, scope) => {
20779      const isRoot = node => eq(node, root);
20780      const isHost = node => isTableCell$2(node) || isContentEditableTrue$3(node.dom);
20781      return closest$4(scope, isHost, isRoot).filter(isElement$7).getOr(root);
20782    };
20783    const hasSameHost = (rootNode, blockBoundary) => {
20784      const root = SugarElement.fromDom(rootNode);
20785      return eq(getClosestHost(root, blockBoundary.from.block), getClosestHost(root, blockBoundary.to.block));
20786    };
20787    const isEditable$1 = blockBoundary => isContentEditableFalse$b(blockBoundary.from.block.dom) === false && isContentEditableFalse$b(blockBoundary.to.block.dom) === false;
20788    const hasValidBlocks = blockBoundary => {
20789      const isValidBlock = block => isTextBlock$2(block) || hasBlockAttr(block.dom);
20790      return isValidBlock(blockBoundary.from.block) && isValidBlock(blockBoundary.to.block);
20791    };
20792    const skipLastBr = (rootNode, forward, blockPosition) => {
20793      if (isBr$6(blockPosition.position.getNode()) && !isEmpty$2(blockPosition.block)) {
20794        return positionIn(false, blockPosition.block.dom).bind(lastPositionInBlock => {
20795          if (lastPositionInBlock.isEqual(blockPosition.position)) {
20796            return fromPosition(forward, rootNode, lastPositionInBlock).bind(to => getBlockPosition(rootNode, to));
20797          } else {
20798            return Optional.some(blockPosition);
20799          }
20800        }).getOr(blockPosition);
20801      } else {
20802        return blockPosition;
20803      }
20804    };
20805    const readFromRange = (rootNode, forward, rng) => {
20806      const fromBlockPos = getBlockPosition(rootNode, CaretPosition.fromRangeStart(rng));
20807      const toBlockPos = fromBlockPos.bind(blockPos => fromPosition(forward, rootNode, blockPos.position).bind(to => getBlockPosition(rootNode, to).map(blockPos => skipLastBr(rootNode, forward, blockPos))));
20808      return lift2(fromBlockPos, toBlockPos, blockBoundary).filter(blockBoundary => isDifferentBlocks(blockBoundary) && hasSameHost(rootNode, blockBoundary) && isEditable$1(blockBoundary) && hasValidBlocks(blockBoundary));
20809    };
20810    const read$1 = (rootNode, forward, rng) => rng.collapsed ? readFromRange(rootNode, forward, rng) : Optional.none();
20811
20812    const getChildrenUntilBlockBoundary = block => {
20813      const children = children$1(block);
20814      return findIndex$2(children, isBlock$2).fold(constant(children), index => children.slice(0, index));
20815    };
20816    const extractChildren = block => {
20817      const children = getChildrenUntilBlockBoundary(block);
20818      each$e(children, remove$
vendor: 2,486 bytes, lines 20818-20871
208186);
20819      return children;
20820    };
20821    const removeEmptyRoot = (rootNode, block) => {
20822      const parents = parentsAndSelf(block, rootNode);
20823      return find$2(parents.reverse(), element => isEmpty$2(element)).each(remove$6);
20824    };
20825    const isEmptyBefore = el => filter$5(prevSiblings(el), el => !isEmpty$2(el)).length === 0;
20826    const nestedBlockMerge = (rootNode, fromBlock, toBlock, insertionPoint) => {
20827      if (isEmpty$2(toBlock)) {
20828        fillWithPaddingBr(toBlock);
20829        return firstPositionIn(toBlock.dom);
20830      }
20831      if (isEmptyBefore(insertionPoint) && isEmpty$2(fromBlock)) {
20832        before$3(insertionPoint, SugarElement.fromTag('br'));
20833      }
20834      const position = prevPosition(toBlock.dom, CaretPosition.before(insertionPoint.dom));
20835      each$e(extractChildren(fromBlock), child => {
20836        before$3(insertionPoint, child);
20837      });
20838      removeEmptyRoot(rootNode, fromBlock);
20839      return position;
20840    };
20841    const sidelongBlockMerge = (rootNode, fromBlock, toBlock) => {
20842      if (isEmpty$2(toBlock)) {
20843        if (isEmpty$2(fromBlock)) {
20844          const getInlineToBlockDescendants = el => {
20845            const helper = (node, elements) => firstChild(node).fold(() => elements, child => isInline$1(child) ? helper(child, elements.concat(shallow$1(child))) : elements);
20846            return helper(el, []);
20847          };
20848          const newFromBlockDescendants = foldr(getInlineToBlockDescendants(toBlock), (element, descendant) => {
20849            wrap$2(element, descendant);
20850            return descendant;
20851          }, createPaddingBr());
20852          empty(fromBlock);
20853          append$1(fromBlock, newFromBlockDescendants);
20854        }
20855        remove$6(toBlock);
20856        return firstPositionIn(fromBlock.dom);
20857      }
20858      const position = lastPositionIn(toBlock.dom);
20859      each$e(extractChildren(fromBlock), child => {
20860        append$1(toBlock, child);
20861      });
20862      removeEmptyRoot(rootNode, fromBlock);
20863      return position;
20864    };
20865    const findInsertionPoint = (toBlock, block) => {
20866      const parentsAndSelf$1 = parentsAndSelf(block, toBlock);
20867      return Optional.from(parentsAndSelf$1[parentsAndSelf$1.length - 1]);
20868    };
20869    const getInsertionPoint = (fromBlock, toBlock) => contains(toBlock, fromBlock) ? findInsertionPoint(toBlock, fromBlock) : Optional.none();
20870    const trimBr = (first, block) => {
20871      positionIn(first, block.dom).bind(position => Optional.from(position.getNode())).map(SugarElement.fromDom).filter(isBr$5).each(remove$6
vendor: 13,287 bytes, lines 20871-21119
20871);
20872    };
20873    const mergeBlockInto = (rootNode, fromBlock, toBlock) => {
20874      trimBr(true, fromBlock);
20875      trimBr(false, toBlock);
20876      return getInsertionPoint(fromBlock, toBlock).fold(curry(sidelongBlockMerge, rootNode, fromBlock, toBlock), curry(nestedBlockMerge, rootNode, fromBlock, toBlock));
20877    };
20878    const mergeBlocks = (rootNode, forward, block1, block2) => forward ? mergeBlockInto(rootNode, block2, block1) : mergeBlockInto(rootNode, block1, block2);
20879
20880    const backspaceDelete$8 = (editor, forward) => {
20881      const rootNode = SugarElement.fromDom(editor.getBody());
20882      const position = read$1(rootNode.dom, forward, editor.selection.getRng()).map(blockBoundary => () => {
20883        mergeBlocks(rootNode, forward, blockBoundary.from.block, blockBoundary.to.block).each(pos => {
20884          editor.selection.setRng(pos.toRange());
20885        });
20886      });
20887      return position;
20888    };
20889
20890    const deleteRangeMergeBlocks = (rootNode, selection) => {
20891      const rng = selection.getRng();
20892      return lift2(getParentBlock$2(rootNode, SugarElement.fromDom(rng.startContainer)), getParentBlock$2(rootNode, SugarElement.fromDom(rng.endContainer)), (block1, block2) => {
20893        if (!eq(block1, block2)) {
20894          return Optional.some(() => {
20895            rng.deleteContents();
20896            mergeBlocks(rootNode, true, block1, block2).each(pos => {
20897              selection.setRng(pos.toRange());
20898            });
20899          });
20900        } else {
20901          return Optional.none();
20902        }
20903      }).getOr(Optional.none());
20904    };
20905    const isRawNodeInTable = (root, rawNode) => {
20906      const node = SugarElement.fromDom(rawNode);
20907      const isRoot = curry(eq, root);
20908      return ancestor$4(node, isTableCell$2, isRoot).isSome();
20909    };
20910    const isSelectionInTable = (root, rng) => isRawNodeInTable(root, rng.startContainer) || isRawNodeInTable(root, rng.endContainer);
20911    const isEverythingSelected = (root, rng) => {
20912      const noPrevious = prevPosition(root.dom, CaretPosition.fromRangeStart(rng)).isNone();
20913      const noNext = nextPosition(root.dom, CaretPosition.fromRangeEnd(rng)).isNone();
20914      return !isSelectionInTable(root, rng) && noPrevious && noNext;
20915    };
20916    const emptyEditor = editor => {
20917      return Optional.some(() => {
20918        editor.setContent('');
20919        editor.selection.setCursorLocation();
20920      });
20921    };
20922    const deleteRange$2 = editor => {
20923      const rootNode = SugarElement.fromDom(editor.getBody());
20924      const rng = editor.selection.getRng();
20925      return isEverythingSelected(rootNode, rng) ? emptyEditor(editor) : deleteRangeMergeBlocks(rootNode, editor.selection);
20926    };
20927    const backspaceDelete$7 = (editor, _forward) => editor.selection.isCollapsed() ? Optional.none() : deleteRange$2(editor);
20928
20929    const showCaret = (direction, editor, node, before, scrollIntoView) => Optional.from(editor._selectionOverrides.showCaret(direction, node, before, scrollIntoView));
20930    const getNodeRange = node => {
20931      const rng = node.ownerDocument.createRange();
20932      rng.selectNode(node);
20933      return rng;
20934    };
20935    const selectNode = (editor, node) => {
20936      const e = editor.dispatch('BeforeObjectSelected', { target: node });
20937      if (e.isDefaultPrevented()) {
20938        return Optional.none();
20939      }
20940      return Optional.some(getNodeRange(node));
20941    };
20942    const renderCaretAtRange = (editor, range, scrollIntoView) => {
20943      const normalizedRange = normalizeRange(1, editor.getBody(), range);
20944      const caretPosition = CaretPosition.fromRangeStart(normalizedRange);
20945      const caretPositionNode = caretPosition.getNode();
20946      if (isInlineFakeCaretTarget(caretPositionNode)) {
20947        return showCaret(1, editor, caretPositionNode, !caretPosition.isAtEnd(), false);
20948      }
20949      const caretPositionBeforeNode = caretPosition.getNode(true);
20950      if (isInlineFakeCaretTarget(caretPositionBeforeNode)) {
20951        return showCaret(1, editor, caretPositionBeforeNode, false, false);
20952      }
20953      const ceRoot = getContentEditableRoot$1(editor.dom.getRoot(), caretPosition.getNode());
20954      if (isInlineFakeCaretTarget(ceRoot)) {
20955        return showCaret(1, editor, ceRoot, false, scrollIntoView);
20956      }
20957      return Optional.none();
20958    };
20959    const renderRangeCaret = (editor, range, scrollIntoView) => range.collapsed ? renderCaretAtRange(editor, range, scrollIntoView).getOr(range) : range;
20960
20961    const isBeforeBoundary = pos => isBeforeContentEditableFalse(pos) || isBeforeMedia(pos);
20962    const isAfterBoundary = pos => isAfterContentEditableFalse(pos) || isAfterMedia(pos);
20963    const trimEmptyTextNode = (dom, node) => {
20964      if (isText$a(node) && node.data.length === 0) {
20965        dom.remove(node);
20966      }
20967    };
20968    const deleteContentAndShowCaret = (editor, range, node, direction, forward, peekCaretPosition) => {
20969      showCaret(direction, editor, peekCaretPosition.getNode(!forward), forward, true).each(caretRange => {
20970        if (range.collapsed) {
20971          const deleteRange = range.cloneRange();
20972          if (forward) {
20973            deleteRange.setEnd(caretRange.startContainer, caretRange.startOffset);
20974          } else {
20975            deleteRange.setStart(caretRange.endContainer, caretRange.endOffset);
20976          }
20977          deleteRange.deleteContents();
20978        } else {
20979          range.deleteContents();
20980        }
20981        editor.selection.setRng(caretRange);
20982      });
20983      trimEmptyTextNode(editor.dom, node);
20984    };
20985    const deleteBoundaryText = (editor, forward) => {
20986      const range = editor.selection.getRng();
20987      if (!isText$a(range.commonAncestorContainer)) {
20988        return Optional.none();
20989      }
20990      const direction = forward ? HDirection.Forwards : HDirection.Backwards;
20991      const caretWalker = CaretWalker(editor.getBody());
20992      const getNextPosFn = curry(getVisualCaretPosition, forward ? caretWalker.next : caretWalker.prev);
20993      const isBeforeFn = forward ? isBeforeBoundary : isAfterBoundary;
20994      const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
20995      const nextCaretPosition = getNextPosFn(caretPosition);
20996      const normalizedNextCaretPosition = nextCaretPosition ? normalizePosition(forward, nextCaretPosition) : nextCaretPosition;
20997      if (!normalizedNextCaretPosition || !isMoveInsideSameBlock(caretPosition, normalizedNextCaretPosition)) {
20998        return Optional.none();
20999      } else if (isBeforeFn(normalizedNextCaretPosition)) {
21000        return Optional.some(() => deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, normalizedNextCaretPosition));
21001      }
21002      const peekCaretPosition = getNextPosFn(normalizedNextCaretPosition);
21003      if (peekCaretPosition && isBeforeFn(peekCaretPosition)) {
21004        if (isMoveInsideSameBlock(normalizedNextCaretPosition, peekCaretPosition)) {
21005          return Optional.some(() => deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, peekCaretPosition));
21006        }
21007      }
21008      return Optional.none();
21009    };
21010    const backspaceDelete$6 = (editor, forward) => deleteBoundaryText(editor, forward);
21011
21012    const getEdgeCefPosition = (editor, atStart) => {
21013      const root = editor.getBody();
21014      return atStart ? firstPositionIn(root).filter(isBeforeContentEditableFalse) : lastPositionIn(root).filter(isAfterContentEditableFalse);
21015    };
21016    const isCefAtEdgeSelected = editor => {
21017      const rng = editor.selection.getRng();
21018      return !rng.collapsed && (getEdgeCefPosition(editor, true).exists(pos => pos.isEqual(CaretPosition.fromRangeStart(rng))) || getEdgeCefPosition(editor, false).exists(pos => pos.isEqual(CaretPosition.fromRangeEnd(rng))));
21019    };
21020
21021    const isCompoundElement = node => isNonNullable(node) && (isTableCell$2(SugarElement.fromDom(node)) || isListItem$1(SugarElement.fromDom(node)));
21022    const DeleteAction = Adt.generate([
21023      { remove: ['element'] },
21024      { moveToElement: ['element'] },
21025      { moveToPosition: ['position'] }
21026    ]);
21027    const isAtContentEditableBlockCaret = (forward, from) => {
21028      const elm = from.getNode(!forward);
21029      const caretLocation = forward ? 'after' : 'before';
21030      return isElement$6(elm) && elm.getAttribute('data-mce-caret') === caretLocation;
21031    };
21032    const isDeleteFromCefDifferentBlocks = (root, forward, from, to) => {
21033      const inSameBlock = elm => isInline$1(SugarElement.fromDom(elm)) && !isInSameBlock(from, to, root);
21034      return getRelativeCefElm(!forward, from).fold(() => getRelativeCefElm(forward, to).fold(never, inSameBlock), inSameBlock);
21035    };
21036    const deleteEmptyBlockOrMoveToCef = (root, forward, from, to) => {
21037      const toCefElm = to.getNode(!forward);
21038      return getParentBlock$2(SugarElement.fromDom(root), SugarElement.fromDom(from.getNode())).map(blockElm => isEmpty$2(blockElm) ? DeleteAction.remove(blockElm.dom) : DeleteAction.moveToElement(toCefElm)).orThunk(() => Optional.some(DeleteAction.moveToElement(toCefElm)));
21039    };
21040    const findCefPosition = (root, forward, from) => fromPosition(forward, root, from).bind(to => {
21041      if (isCompoundElement(to.getNode())) {
21042        return Optional.none();
21043      } else if (isDeleteFromCefDifferentBlocks(root, forward, from, to)) {
21044        return Optional.none();
21045      } else if (forward && isContentEditableFalse$b(to.getNode())) {
21046        return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
21047      } else if (!forward && isContentEditableFalse$b(to.getNode(true))) {
21048        return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
21049      } else if (forward && isAfterContentEditableFalse(from)) {
21050        return Optional.some(DeleteAction.moveToPosition(to));
21051      } else if (!forward && isBeforeContentEditableFalse(from)) {
21052        return Optional.some(DeleteAction.moveToPosition(to));
21053      } else {
21054        return Optional.none();
21055      }
21056    });
21057    const getContentEditableBlockAction = (forward, elm) => {
21058      if (isNullable(elm)) {
21059        return Optional.none();
21060      } else if (forward && isContentEditableFalse$b(elm.nextSibling)) {
21061        return Optional.some(DeleteAction.moveToElement(elm.nextSibling));
21062      } else if (!forward && isContentEditableFalse$b(elm.previousSibling)) {
21063        return Optional.some(DeleteAction.moveToElement(elm.previousSibling));
21064      } else {
21065        return Optional.none();
21066      }
21067    };
21068    const skipMoveToActionFromInlineCefToContent = (root, from, deleteAction) => deleteAction.fold(elm => Optional.some(DeleteAction.remove(elm)), elm => Optional.some(DeleteAction.moveToElement(elm)), to => {
21069      if (isInSameBlock(from, to, root)) {
21070        return Optional.none();
21071      } else {
21072        return Optional.some(DeleteAction.moveToPosition(to));
21073      }
21074    });
21075    const getContentEditableAction = (root, forward, from) => {
21076      if (isAtContentEditableBlockCaret(forward, from)) {
21077        return getContentEditableBlockAction(forward, from.getNode(!forward)).orThunk(() => findCefPosition(root, forward, from));
21078      } else {
21079        return findCefPosition(root, forward, from).bind(deleteAction => skipMoveToActionFromInlineCefToContent(root, from, deleteAction));
21080      }
21081    };
21082    const read = (root, forward, rng) => {
21083      const normalizedRange = normalizeRange(forward ? 1 : -1, root, rng);
21084      const from = CaretPosition.fromRangeStart(normalizedRange);
21085      const rootElement = SugarElement.fromDom(root);
21086      if (!forward && isAfterContentEditableFalse(from)) {
21087        return Optional.some(DeleteAction.remove(from.getNode(true)));
21088      } else if (forward && isBeforeContentEditableFalse(from)) {
21089        return Optional.some(DeleteAction.remove(from.getNode()));
21090      } else if (!forward && isBeforeContentEditableFalse(from) && isAfterBr(rootElement, from)) {
21091        return findPreviousBr(rootElement, from).map(br => DeleteAction.remove(br.getNode()));
21092      } else if (forward && isAfterContentEditableFalse(from) && isBeforeBr$1(rootElement, from)) {
21093        return findNextBr(rootElement, from).map(br => DeleteAction.remove(br.getNode()));
21094      } else {
21095        return getContentEditableAction(root, forward, from);
21096      }
21097    };
21098
21099    const deleteElement$1 = (editor, forward) => element => {
21100      editor._selectionOverrides.hideFakeCaret();
21101      deleteElement$2(editor, forward, SugarElement.fromDom(element));
21102      return true;
21103    };
21104    const moveToElement = (editor, forward) => element => {
21105      const pos = forward ? CaretPosition.before(element) : CaretPosition.after(element);
21106      editor.selection.setRng(pos.toRange());
21107      return true;
21108    };
21109    const moveToPosition = editor => pos => {
21110      editor.selection.setRng(pos.toRange());
21111      return true;
21112    };
21113    const getAncestorCe = (editor, node) => Optional.from(getContentEditableRoot$1(editor.getBody(), node));
21114    const backspaceDeleteCaret = (editor, forward) => {
21115      const selectedNode = editor.selection.getNode();
21116      return getAncestorCe(editor, selectedNode).filter(isContentEditableFalse$b).fold(() => read(editor.getBody(), forward, editor.selection.getRng()).map(deleteAction => () => deleteAction.fold(deleteElement$1(editor, forward), moveToElement(editor, forward), moveToPosition(editor))), () => Optional.some(noop));
21117    };
21118    const deleteOffscreenSelection = rootElement => {
21119      each$e(descendants(rootElement, '.mce-offscreen-selection'), remove$
vendor: 5,687 bytes, lines 21119-21260
211196);
21120    };
21121    const backspaceDeleteRange = (editor, forward) => {
21122      const selectedNode = editor.selection.getNode();
21123      if (isContentEditableFalse$b(selectedNode) && !isTableCell$3(selectedNode)) {
21124        const hasCefAncestor = getAncestorCe(editor, selectedNode.parentNode).filter(isContentEditableFalse$b);
21125        return hasCefAncestor.fold(() => Optional.some(() => {
21126          deleteOffscreenSelection(SugarElement.fromDom(editor.getBody()));
21127          deleteElement$2(editor, forward, SugarElement.fromDom(editor.selection.getNode()));
21128          paddEmptyBody(editor);
21129        }), () => Optional.some(noop));
21130      }
21131      if (isCefAtEdgeSelected(editor)) {
21132        return Optional.some(() => {
21133          deleteRangeContents(editor, editor.selection.getRng(), SugarElement.fromDom(editor.getBody()));
21134        });
21135      }
21136      return Optional.none();
21137    };
21138    const paddEmptyElement = editor => {
21139      const dom = editor.dom, selection = editor.selection;
21140      const ceRoot = getContentEditableRoot$1(editor.getBody(), selection.getNode());
21141      if (isContentEditableTrue$3(ceRoot) && dom.isBlock(ceRoot) && dom.isEmpty(ceRoot)) {
21142        const br = dom.create('br', { 'data-mce-bogus': '1' });
21143        dom.setHTML(ceRoot, '');
21144        ceRoot.appendChild(br);
21145        selection.setRng(CaretPosition.before(br).toRange());
21146      }
21147      return true;
21148    };
21149    const backspaceDelete$5 = (editor, forward) => {
21150      if (editor.selection.isCollapsed()) {
21151        return backspaceDeleteCaret(editor, forward);
21152      } else {
21153        return backspaceDeleteRange(editor, forward);
21154      }
21155    };
21156
21157    const deleteCaret$2 = (editor, forward) => {
21158      const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
21159      return fromPosition(forward, editor.getBody(), fromPos).filter(pos => forward ? isBeforeImageBlock(pos) : isAfterImageBlock(pos)).bind(pos => getChildNodeAtRelativeOffset(forward ? 0 : -1, pos)).map(elm => () => editor.selection.select(elm));
21160    };
21161    const backspaceDelete$4 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret$2(editor, forward) : Optional.none();
21162
21163    const isText$2 = isText$a;
21164    const startsWithCaretContainer = node => isText$2(node) && node.data[0] === ZWSP$1;
21165    const endsWithCaretContainer = node => isText$2(node) && node.data[node.data.length - 1] === ZWSP$1;
21166    const createZwsp = node => {
21167      var _a;
21168      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
21169      return doc.createTextNode(ZWSP$1);
21170    };
21171    const insertBefore = node => {
21172      var _a;
21173      if (isText$2(node.previousSibling)) {
21174        if (endsWithCaretContainer(node.previousSibling)) {
21175          return node.previousSibling;
21176        } else {
21177          node.previousSibling.appendData(ZWSP$1);
21178          return node.previousSibling;
21179        }
21180      } else if (isText$2(node)) {
21181        if (startsWithCaretContainer(node)) {
21182          return node;
21183        } else {
21184          node.insertData(0, ZWSP$1);
21185          return node;
21186        }
21187      } else {
21188        const newNode = createZwsp(node);
21189        (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newNode, node);
21190        return newNode;
21191      }
21192    };
21193    const insertAfter = node => {
21194      var _a, _b;
21195      if (isText$2(node.nextSibling)) {
21196        if (startsWithCaretContainer(node.nextSibling)) {
21197          return node.nextSibling;
21198        } else {
21199          node.nextSibling.insertData(0, ZWSP$1);
21200          return node.nextSibling;
21201        }
21202      } else if (isText$2(node)) {
21203        if (endsWithCaretContainer(node)) {
21204          return node;
21205        } else {
21206          node.appendData(ZWSP$1);
21207          return node;
21208        }
21209      } else {
21210        const newNode = createZwsp(node);
21211        if (node.nextSibling) {
21212          (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newNode, node.nextSibling);
21213        } else {
21214          (_b = node.parentNode) === null || _b === void 0 ? void 0 : _b.appendChild(newNode);
21215        }
21216        return newNode;
21217      }
21218    };
21219    const insertInline = (before, node) => before ? insertBefore(node) : insertAfter(node);
21220    const insertInlineBefore = curry(insertInline, true);
21221    const insertInlineAfter = curry(insertInline, false);
21222
21223    const insertInlinePos = (pos, before) => {
21224      if (isText$a(pos.container())) {
21225        return insertInline(before, pos.container());
21226      } else {
21227        return insertInline(before, pos.getNode());
21228      }
21229    };
21230    const isPosCaretContainer = (pos, caret) => {
21231      const caretNode = caret.get();
21232      return caretNode && pos.container() === caretNode && isCaretContainerInline(caretNode);
21233    };
21234    const renderCaret = (caret, location) => location.fold(element => {
21235      remove$4(caret.get());
21236      const text = insertInlineBefore(element);
21237      caret.set(text);
21238      return Optional.some(CaretPosition(text, text.length - 1));
21239    }, element => firstPositionIn(element).map(pos => {
21240      if (!isPosCaretContainer(pos, caret)) {
21241        remove$4(caret.get());
21242        const text = insertInlinePos(pos, true);
21243        caret.set(text);
21244        return CaretPosition(text, 1);
21245      } else {
21246        const node = caret.get();
21247        return CaretPosition(node, 1);
21248      }
21249    }), element => lastPositionIn(element).map(pos => {
21250      if (!isPosCaretContainer(pos, caret)) {
21251        remove$4(caret.get());
21252        const text = insertInlinePos(pos, false);
21253        caret.set(text);
21254        return CaretPosition(text, text.length - 1);
21255      } else {
21256        const node = caret.get();
21257        return CaretPosition(node, node.length - 1);
21258      }
21259    }), element => {
21260      remove$4
vendor: 29,150 bytes, lines 21260-21877
21260(caret.get());
21261      const text = insertInlineAfter(element);
21262      caret.set(text);
21263      return Optional.some(CaretPosition(text, 1));
21264    });
21265
21266    const evaluateUntil = (fns, args) => {
21267      for (let i = 0; i < fns.length; i++) {
21268        const result = fns[i].apply(null, args);
21269        if (result.isSome()) {
21270          return result;
21271        }
21272      }
21273      return Optional.none();
21274    };
21275
21276    const Location = Adt.generate([
21277      { before: ['element'] },
21278      { start: ['element'] },
21279      { end: ['element'] },
21280      { after: ['element'] }
21281    ]);
21282    const rescope$1 = (rootNode, node) => {
21283      const parentBlock = getParentBlock$3(node, rootNode);
21284      return parentBlock ? parentBlock : rootNode;
21285    };
21286    const before = (isInlineTarget, rootNode, pos) => {
21287      const nPos = normalizeForwards(pos);
21288      const scope = rescope$1(rootNode, nPos.container());
21289      return findRootInline(isInlineTarget, scope, nPos).fold(() => nextPosition(scope, nPos).bind(curry(findRootInline, isInlineTarget, scope)).map(inline => Location.before(inline)), Optional.none);
21290    };
21291    const isNotInsideFormatCaretContainer = (rootNode, elm) => getParentCaretContainer(rootNode, elm) === null;
21292    const findInsideRootInline = (isInlineTarget, rootNode, pos) => findRootInline(isInlineTarget, rootNode, pos).filter(curry(isNotInsideFormatCaretContainer, rootNode));
21293    const start$1 = (isInlineTarget, rootNode, pos) => {
21294      const nPos = normalizeBackwards(pos);
21295      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(inline => {
21296        const prevPos = prevPosition(inline, nPos);
21297        return prevPos.isNone() ? Optional.some(Location.start(inline)) : Optional.none();
21298      });
21299    };
21300    const end = (isInlineTarget, rootNode, pos) => {
21301      const nPos = normalizeForwards(pos);
21302      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(inline => {
21303        const nextPos = nextPosition(inline, nPos);
21304        return nextPos.isNone() ? Optional.some(Location.end(inline)) : Optional.none();
21305      });
21306    };
21307    const after = (isInlineTarget, rootNode, pos) => {
21308      const nPos = normalizeBackwards(pos);
21309      const scope = rescope$1(rootNode, nPos.container());
21310      return findRootInline(isInlineTarget, scope, nPos).fold(() => prevPosition(scope, nPos).bind(curry(findRootInline, isInlineTarget, scope)).map(inline => Location.after(inline)), Optional.none);
21311    };
21312    const isValidLocation = location => !isRtl(getElement(location));
21313    const readLocation = (isInlineTarget, rootNode, pos) => {
21314      const location = evaluateUntil([
21315        before,
21316        start$1,
21317        end,
21318        after
21319      ], [
21320        isInlineTarget,
21321        rootNode,
21322        pos
21323      ]);
21324      return location.filter(isValidLocation);
21325    };
21326    const getElement = location => location.fold(identity, identity, identity, identity);
21327    const getName = location => location.fold(constant('before'), constant('start'), constant('end'), constant('after'));
21328    const outside = location => location.fold(Location.before, Location.before, Location.after, Location.after);
21329    const inside = location => location.fold(Location.start, Location.start, Location.end, Location.end);
21330    const isEq = (location1, location2) => getName(location1) === getName(location2) && getElement(location1) === getElement(location2);
21331    const betweenInlines = (forward, isInlineTarget, rootNode, from, to, location) => lift2(findRootInline(isInlineTarget, rootNode, from), findRootInline(isInlineTarget, rootNode, to), (fromInline, toInline) => {
21332      if (fromInline !== toInline && hasSameParentBlock(rootNode, fromInline, toInline)) {
21333        return Location.after(forward ? fromInline : toInline);
21334      } else {
21335        return location;
21336      }
21337    }).getOr(location);
21338    const skipNoMovement = (fromLocation, toLocation) => fromLocation.fold(always, fromLocation => !isEq(fromLocation, toLocation));
21339    const findLocationTraverse = (forward, isInlineTarget, rootNode, fromLocation, pos) => {
21340      const from = normalizePosition(forward, pos);
21341      const to = fromPosition(forward, rootNode, from).map(curry(normalizePosition, forward));
21342      const location = to.fold(() => fromLocation.map(outside), to => readLocation(isInlineTarget, rootNode, to).map(curry(betweenInlines, forward, isInlineTarget, rootNode, from, to)).filter(curry(skipNoMovement, fromLocation)));
21343      return location.filter(isValidLocation);
21344    };
21345    const findLocationSimple = (forward, location) => {
21346      if (forward) {
21347        return location.fold(compose(Optional.some, Location.start), Optional.none, compose(Optional.some, Location.after), Optional.none);
21348      } else {
21349        return location.fold(Optional.none, compose(Optional.some, Location.before), Optional.none, compose(Optional.some, Location.end));
21350      }
21351    };
21352    const findLocation$1 = (forward, isInlineTarget, rootNode, pos) => {
21353      const from = normalizePosition(forward, pos);
21354      const fromLocation = readLocation(isInlineTarget, rootNode, from);
21355      return readLocation(isInlineTarget, rootNode, from).bind(curry(findLocationSimple, forward)).orThunk(() => findLocationTraverse(forward, isInlineTarget, rootNode, fromLocation, pos));
21356    };
21357
21358    const hasSelectionModifyApi = editor => {
21359      return isFunction(editor.selection.getSel().modify);
21360    };
21361    const moveRel = (forward, selection, pos) => {
21362      const delta = forward ? 1 : -1;
21363      selection.setRng(CaretPosition(pos.container(), pos.offset() + delta).toRange());
21364      selection.getSel().modify('move', forward ? 'forward' : 'backward', 'word');
21365      return true;
21366    };
21367    const moveByWord = (forward, editor) => {
21368      const rng = editor.selection.getRng();
21369      const pos = forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng);
21370      if (!hasSelectionModifyApi(editor)) {
21371        return false;
21372      } else if (forward && isBeforeInline(pos)) {
21373        return moveRel(true, editor.selection, pos);
21374      } else if (!forward && isAfterInline(pos)) {
21375        return moveRel(false, editor.selection, pos);
21376      } else {
21377        return false;
21378      }
21379    };
21380
21381    var BreakType;
21382    (function (BreakType) {
21383      BreakType[BreakType['Br'] = 0] = 'Br';
21384      BreakType[BreakType['Block'] = 1] = 'Block';
21385      BreakType[BreakType['Wrap'] = 2] = 'Wrap';
21386      BreakType[BreakType['Eol'] = 3] = 'Eol';
21387    }(BreakType || (BreakType = {})));
21388    const flip = (direction, positions) => direction === HDirection.Backwards ? reverse(positions) : positions;
21389    const walk$1 = (direction, caretWalker, pos) => direction === HDirection.Forwards ? caretWalker.next(pos) : caretWalker.prev(pos);
21390    const getBreakType = (scope, direction, currentPos, nextPos) => {
21391      if (isBr$6(nextPos.getNode(direction === HDirection.Forwards))) {
21392        return BreakType.Br;
21393      } else if (isInSameBlock(currentPos, nextPos) === false) {
21394        return BreakType.Block;
21395      } else {
21396        return BreakType.Wrap;
21397      }
21398    };
21399    const getPositionsUntil = (predicate, direction, scope, start) => {
21400      const caretWalker = CaretWalker(scope);
21401      let currentPos = start;
21402      const positions = [];
21403      while (currentPos) {
21404        const nextPos = walk$1(direction, caretWalker, currentPos);
21405        if (!nextPos) {
21406          break;
21407        }
21408        if (isBr$6(nextPos.getNode(false))) {
21409          if (direction === HDirection.Forwards) {
21410            return {
21411              positions: flip(direction, positions).concat([nextPos]),
21412              breakType: BreakType.Br,
21413              breakAt: Optional.some(nextPos)
21414            };
21415          } else {
21416            return {
21417              positions: flip(direction, positions),
21418              breakType: BreakType.Br,
21419              breakAt: Optional.some(nextPos)
21420            };
21421          }
21422        }
21423        if (!nextPos.isVisible()) {
21424          currentPos = nextPos;
21425          continue;
21426        }
21427        if (predicate(currentPos, nextPos)) {
21428          const breakType = getBreakType(scope, direction, currentPos, nextPos);
21429          return {
21430            positions: flip(direction, positions),
21431            breakType,
21432            breakAt: Optional.some(nextPos)
21433          };
21434        }
21435        positions.push(nextPos);
21436        currentPos = nextPos;
21437      }
21438      return {
21439        positions: flip(direction, positions),
21440        breakType: BreakType.Eol,
21441        breakAt: Optional.none()
21442      };
21443    };
21444    const getAdjacentLinePositions = (direction, getPositionsUntilBreak, scope, start) => getPositionsUntilBreak(scope, start).breakAt.map(pos => {
21445      const positions = getPositionsUntilBreak(scope, pos).positions;
21446      return direction === HDirection.Backwards ? positions.concat(pos) : [pos].concat(positions);
21447    }).getOr([]);
21448    const findClosestHorizontalPositionFromPoint = (positions, x) => foldl(positions, (acc, newPos) => acc.fold(() => Optional.some(newPos), lastPos => lift2(head(lastPos.getClientRects()), head(newPos.getClientRects()), (lastRect, newRect) => {
21449      const lastDist = Math.abs(x - lastRect.left);
21450      const newDist = Math.abs(x - newRect.left);
21451      return newDist <= lastDist ? newPos : lastPos;
21452    }).or(acc)), Optional.none());
21453    const findClosestHorizontalPosition = (positions, pos) => head(pos.getClientRects()).bind(targetRect => findClosestHorizontalPositionFromPoint(positions, targetRect.left));
21454    const getPositionsUntilPreviousLine = curry(getPositionsUntil, CaretPosition.isAbove, -1);
21455    const getPositionsUntilNextLine = curry(getPositionsUntil, CaretPosition.isBelow, 1);
21456    const getPositionsAbove = curry(getAdjacentLinePositions, -1, getPositionsUntilPreviousLine);
21457    const getPositionsBelow = curry(getAdjacentLinePositions, 1, getPositionsUntilNextLine);
21458    const isAtFirstLine = (scope, pos) => getPositionsUntilPreviousLine(scope, pos).breakAt.isNone();
21459    const isAtLastLine = (scope, pos) => getPositionsUntilNextLine(scope, pos).breakAt.isNone();
21460    const getFirstLinePositions = scope => firstPositionIn(scope).map(pos => [pos].concat(getPositionsUntilNextLine(scope, pos).positions)).getOr([]);
21461    const getLastLinePositions = scope => lastPositionIn(scope).map(pos => getPositionsUntilPreviousLine(scope, pos).positions.concat(pos)).getOr([]);
21462    const getClosestPositionAbove = (scope, pos) => findClosestHorizontalPosition(getPositionsAbove(scope, pos), pos);
21463    const getClosestPositionBelow = (scope, pos) => findClosestHorizontalPosition(getPositionsBelow(scope, pos), pos);
21464
21465    const isContentEditableFalse$4 = isContentEditableFalse$b;
21466    const distanceToRectLeft$1 = (clientRect, clientX) => Math.abs(clientRect.left - clientX);
21467    const distanceToRectRight$1 = (clientRect, clientX) => Math.abs(clientRect.right - clientX);
21468    const isNodeClientRect = rect => hasNonNullableKey(rect, 'node');
21469    const findClosestClientRect = (clientRects, clientX) => reduce(clientRects, (oldClientRect, clientRect) => {
21470      const oldDistance = Math.min(distanceToRectLeft$1(oldClientRect, clientX), distanceToRectRight$1(oldClientRect, clientX));
21471      const newDistance = Math.min(distanceToRectLeft$1(clientRect, clientX), distanceToRectRight$1(clientRect, clientX));
21472      if (newDistance === oldDistance && isNodeClientRect(clientRect) && isContentEditableFalse$4(clientRect.node)) {
21473        return clientRect;
21474      }
21475      if (newDistance < oldDistance) {
21476        return clientRect;
21477      }
21478      return oldClientRect;
21479    });
21480
21481    const getNodeClientRects = node => {
21482      const toArrayWithNode = clientRects => {
21483        return map$3(clientRects, rect => {
21484          const clientRect = clone$1(rect);
21485          clientRect.node = node;
21486          return clientRect;
21487        });
21488      };
21489      if (isElement$6(node)) {
21490        return toArrayWithNode(node.getClientRects());
21491      } else if (isText$a(node)) {
21492        const rng = node.ownerDocument.createRange();
21493        rng.setStart(node, 0);
21494        rng.setEnd(node, node.data.length);
21495        return toArrayWithNode(rng.getClientRects());
21496      } else {
21497        return [];
21498      }
21499    };
21500    const getClientRects = nodes => bind$3(nodes, getNodeClientRects);
21501
21502    var VDirection;
21503    (function (VDirection) {
21504      VDirection[VDirection['Up'] = -1] = 'Up';
21505      VDirection[VDirection['Down'] = 1] = 'Down';
21506    }(VDirection || (VDirection = {})));
21507    const findUntil = (direction, root, predicateFn, node) => {
21508      let currentNode = node;
21509      while (currentNode = findNode(currentNode, direction, isEditableCaretCandidate$1, root)) {
21510        if (predicateFn(currentNode)) {
21511          return;
21512        }
21513      }
21514    };
21515    const walkUntil = (direction, isAboveFn, isBeflowFn, root, predicateFn, caretPosition) => {
21516      let line = 0;
21517      const result = [];
21518      const add = node => {
21519        let clientRects = getClientRects([node]);
21520        if (direction === -1) {
21521          clientRects = clientRects.reverse();
21522        }
21523        for (let i = 0; i < clientRects.length; i++) {
21524          const clientRect = clientRects[i];
21525          if (isBeflowFn(clientRect, targetClientRect)) {
21526            continue;
21527          }
21528          if (result.length > 0 && isAboveFn(clientRect, last$2(result))) {
21529            line++;
21530          }
21531          clientRect.line = line;
21532          if (predicateFn(clientRect)) {
21533            return true;
21534          }
21535          result.push(clientRect);
21536        }
21537        return false;
21538      };
21539      const targetClientRect = last$2(caretPosition.getClientRects());
21540      if (!targetClientRect) {
21541        return result;
21542      }
21543      const node = caretPosition.getNode();
21544      if (node) {
21545        add(node);
21546        findUntil(direction, root, add, node);
21547      }
21548      return result;
21549    };
21550    const aboveLineNumber = (lineNumber, clientRect) => clientRect.line > lineNumber;
21551    const isLineNumber = (lineNumber, clientRect) => clientRect.line === lineNumber;
21552    const upUntil = curry(walkUntil, VDirection.Up, isAbove$1, isBelow$1);
21553    const downUntil = curry(walkUntil, VDirection.Down, isBelow$1, isAbove$1);
21554    const getLastClientRect = caretPosition => {
21555      return last$2(caretPosition.getClientRects());
21556    };
21557    const positionsUntil = (direction, root, predicateFn, node) => {
21558      const caretWalker = CaretWalker(root);
21559      let walkFn;
21560      let isBelowFn;
21561      let isAboveFn;
21562      let caretPosition;
21563      const result = [];
21564      let line = 0;
21565      if (direction === 1) {
21566        walkFn = caretWalker.next;
21567        isBelowFn = isBelow$1;
21568        isAboveFn = isAbove$1;
21569        caretPosition = CaretPosition.after(node);
21570      } else {
21571        walkFn = caretWalker.prev;
21572        isBelowFn = isAbove$1;
21573        isAboveFn = isBelow$1;
21574        caretPosition = CaretPosition.before(node);
21575      }
21576      const targetClientRect = getLastClientRect(caretPosition);
21577      do {
21578        if (!caretPosition.isVisible()) {
21579          continue;
21580        }
21581        const rect = getLastClientRect(caretPosition);
21582        if (isAboveFn(rect, targetClientRect)) {
21583          continue;
21584        }
21585        if (result.length > 0 && isBelowFn(rect, last$2(result))) {
21586          line++;
21587        }
21588        const clientRect = clone$1(rect);
21589        clientRect.position = caretPosition;
21590        clientRect.line = line;
21591        if (predicateFn(clientRect)) {
21592          return result;
21593        }
21594        result.push(clientRect);
21595      } while (caretPosition = walkFn(caretPosition));
21596      return result;
21597    };
21598    const isAboveLine = lineNumber => clientRect => aboveLineNumber(lineNumber, clientRect);
21599    const isLine = lineNumber => clientRect => isLineNumber(lineNumber, clientRect);
21600
21601    const moveToRange = (editor, rng) => {
21602      editor.selection.setRng(rng);
21603      scrollRangeIntoView(editor, editor.selection.getRng());
21604    };
21605    const renderRangeCaretOpt = (editor, range, scrollIntoView) => Optional.some(renderRangeCaret(editor, range, scrollIntoView));
21606    const moveHorizontally = (editor, direction, range, isBefore, isAfter, isElement) => {
21607      const forwards = direction === HDirection.Forwards;
21608      const caretWalker = CaretWalker(editor.getBody());
21609      const getNextPosFn = curry(getVisualCaretPosition, forwards ? caretWalker.next : caretWalker.prev);
21610      const isBeforeFn = forwards ? isBefore : isAfter;
21611      if (!range.collapsed) {
21612        const node = getSelectedNode(range);
21613        if (isElement(node)) {
21614          return showCaret(direction, editor, node, direction === HDirection.Backwards, false);
21615        } else if (isCefAtEdgeSelected(editor)) {
21616          const newRange = range.cloneRange();
21617          newRange.collapse(direction === HDirection.Backwards);
21618          return Optional.from(newRange);
21619        }
21620      }
21621      const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
21622      if (isBeforeFn(caretPosition)) {
21623        return selectNode(editor, caretPosition.getNode(!forwards));
21624      }
21625      let nextCaretPosition = getNextPosFn(caretPosition);
21626      const rangeIsInContainerBlock = isRangeInCaretContainerBlock(range);
21627      if (!nextCaretPosition) {
21628        return rangeIsInContainerBlock ? Optional.some(range) : Optional.none();
21629      } else {
21630        nextCaretPosition = normalizePosition(forwards, nextCaretPosition);
21631      }
21632      if (isBeforeFn(nextCaretPosition)) {
21633        return showCaret(direction, editor, nextCaretPosition.getNode(!forwards), forwards, false);
21634      }
21635      const peekCaretPosition = getNextPosFn(nextCaretPosition);
21636      if (peekCaretPosition && isBeforeFn(peekCaretPosition)) {
21637        if (isMoveInsideSameBlock(nextCaretPosition, peekCaretPosition)) {
21638          return showCaret(direction, editor, peekCaretPosition.getNode(!forwards), forwards, false);
21639        }
21640      }
21641      if (rangeIsInContainerBlock) {
21642        return renderRangeCaretOpt(editor, nextCaretPosition.toRange(), false);
21643      }
21644      return Optional.none();
21645    };
21646    const moveVertically = (editor, direction, range, isBefore, isAfter, isElement) => {
21647      const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
21648      const caretClientRect = last$2(caretPosition.getClientRects());
21649      const forwards = direction === VDirection.Down;
21650      const root = editor.getBody();
21651      if (!caretClientRect) {
21652        return Optional.none();
21653      }
21654      if (isCefAtEdgeSelected(editor)) {
21655        const caretPosition = forwards ? CaretPosition.fromRangeEnd(range) : CaretPosition.fromRangeStart(range);
21656        const getClosestFn = !forwards ? getClosestPositionAbove : getClosestPositionBelow;
21657        return getClosestFn(root, caretPosition).orThunk(() => Optional.from(caretPosition)).map(pos => pos.toRange());
21658      }
21659      const walkerFn = forwards ? downUntil : upUntil;
21660      const linePositions = walkerFn(root, isAboveLine(1), caretPosition);
21661      const nextLinePositions = filter$5(linePositions, isLine(1));
21662      const clientX = caretClientRect.left;
21663      const nextLineRect = findClosestClientRect(nextLinePositions, clientX);
21664      if (nextLineRect && isElement(nextLineRect.node)) {
21665        const dist1 = Math.abs(clientX - nextLineRect.left);
21666        const dist2 = Math.abs(clientX - nextLineRect.right);
21667        return showCaret(direction, editor, nextLineRect.node, dist1 < dist2, false);
21668      }
21669      let currentNode;
21670      if (isBefore(caretPosition)) {
21671        currentNode = caretPosition.getNode();
21672      } else if (isAfter(caretPosition)) {
21673        currentNode = caretPosition.getNode(true);
21674      } else {
21675        currentNode = getSelectedNode(range);
21676      }
21677      if (currentNode) {
21678        const caretPositions = positionsUntil(direction, root, isAboveLine(1), currentNode);
21679        let closestNextLineRect = findClosestClientRect(filter$5(caretPositions, isLine(1)), clientX);
21680        if (closestNextLineRect) {
21681          return renderRangeCaretOpt(editor, closestNextLineRect.position.toRange(), false);
21682        }
21683        closestNextLineRect = last$2(filter$5(caretPositions, isLine(0)));
21684        if (closestNextLineRect) {
21685          return renderRangeCaretOpt(editor, closestNextLineRect.position.toRange(), false);
21686        }
21687      }
21688      if (nextLinePositions.length === 0) {
21689        return getLineEndPoint(editor, forwards).filter(forwards ? isAfter : isBefore).map(pos => renderRangeCaret(editor, pos.toRange(), false));
21690      }
21691      return Optional.none();
21692    };
21693    const getLineEndPoint = (editor, forward) => {
21694      const rng = editor.selection.getRng();
21695      const from = forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng);
21696      const host = getEditingHost(from.container(), editor.getBody());
21697      if (forward) {
21698        const lineInfo = getPositionsUntilNextLine(host, from);
21699        return last$3(lineInfo.positions);
21700      } else {
21701        const lineInfo = getPositionsUntilPreviousLine(host, from);
21702        return head(lineInfo.positions);
21703      }
21704    };
21705    const moveToLineEndPoint$3 = (editor, forward, isElementPosition) => getLineEndPoint(editor, forward).filter(isElementPosition).exists(pos => {
21706      editor.selection.setRng(pos.toRange());
21707      return true;
21708    });
21709
21710    const setCaretPosition = (editor, pos) => {
21711      const rng = editor.dom.createRng();
21712      rng.setStart(pos.container(), pos.offset());
21713      rng.setEnd(pos.container(), pos.offset());
21714      editor.selection.setRng(rng);
21715    };
21716    const setSelected = (state, elm) => {
21717      if (state) {
21718        elm.setAttribute('data-mce-selected', 'inline-boundary');
21719      } else {
21720        elm.removeAttribute('data-mce-selected');
21721      }
21722    };
21723    const renderCaretLocation = (editor, caret, location) => renderCaret(caret, location).map(pos => {
21724      setCaretPosition(editor, pos);
21725      return location;
21726    });
21727    const getPositionFromRange = (range, root, forward) => {
21728      const start = CaretPosition.fromRangeStart(range);
21729      if (range.collapsed) {
21730        return start;
21731      } else {
21732        const end = CaretPosition.fromRangeEnd(range);
21733        return forward ? prevPosition(root, end).getOr(end) : nextPosition(root, start).getOr(start);
21734      }
21735    };
21736    const findLocation = (editor, caret, forward) => {
21737      const rootNode = editor.getBody();
21738      const from = getPositionFromRange(editor.selection.getRng(), rootNode, forward);
21739      const isInlineTarget$1 = curry(isInlineTarget, editor);
21740      const location = findLocation$1(forward, isInlineTarget$1, rootNode, from);
21741      return location.bind(location => renderCaretLocation(editor, caret, location));
21742    };
21743    const toggleInlines = (isInlineTarget, dom, elms) => {
21744      const inlineBoundaries = map$3(descendants(SugarElement.fromDom(dom.getRoot()), '*[data-mce-selected="inline-boundary"]'), e => e.dom);
21745      const selectedInlines = filter$5(inlineBoundaries, isInlineTarget);
21746      const targetInlines = filter$5(elms, isInlineTarget);
21747      each$e(difference(selectedInlines, targetInlines), curry(setSelected, false));
21748      each$e(difference(targetInlines, selectedInlines), curry(setSelected, true));
21749    };
21750    const safeRemoveCaretContainer = (editor, caret) => {
21751      const caretValue = caret.get();
21752      if (editor.selection.isCollapsed() && !editor.composing && caretValue) {
21753        const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
21754        if (CaretPosition.isTextPosition(pos) && !isAtZwsp(pos)) {
21755          setCaretPosition(editor, removeAndReposition(caretValue, pos));
21756          caret.set(null);
21757        }
21758      }
21759    };
21760    const renderInsideInlineCaret = (isInlineTarget, editor, caret, elms) => {
21761      if (editor.selection.isCollapsed()) {
21762        const inlines = filter$5(elms, isInlineTarget);
21763        each$e(inlines, _inline => {
21764          const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
21765          readLocation(isInlineTarget, editor.getBody(), pos).bind(location => renderCaretLocation(editor, caret, location));
21766        });
21767      }
21768    };
21769    const move$2 = (editor, caret, forward) => isInlineBoundariesEnabled(editor) ? findLocation(editor, caret, forward).isSome() : false;
21770    const moveWord = (forward, editor, _caret) => isInlineBoundariesEnabled(editor) ? moveByWord(forward, editor) : false;
21771    const setupSelectedState = editor => {
21772      const caret = Cell(null);
21773      const isInlineTarget$1 = curry(isInlineTarget, editor);
21774      editor.on('NodeChange', e => {
21775        if (isInlineBoundariesEnabled(editor)) {
21776          toggleInlines(isInlineTarget$1, editor.dom, e.parents);
21777          safeRemoveCaretContainer(editor, caret);
21778          renderInsideInlineCaret(isInlineTarget$1, editor, caret, e.parents);
21779        }
21780      });
21781      return caret;
21782    };
21783    const moveNextWord = curry(moveWord, true);
21784    const movePrevWord = curry(moveWord, false);
21785    const moveToLineEndPoint$2 = (editor, forward, caret) => {
21786      if (isInlineBoundariesEnabled(editor)) {
21787        const linePoint = getLineEndPoint(editor, forward).getOrThunk(() => {
21788          const rng = editor.selection.getRng();
21789          return forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng);
21790        });
21791        return readLocation(curry(isInlineTarget, editor), editor.getBody(), linePoint).exists(loc => {
21792          const outsideLoc = outside(loc);
21793          return renderCaret(caret, outsideLoc).exists(pos => {
21794            setCaretPosition(editor, pos);
21795            return true;
21796          });
21797        });
21798      } else {
21799        return false;
21800      }
21801    };
21802
21803    const rangeFromPositions = (from, to) => {
21804      const range = document.createRange();
21805      range.setStart(from.container(), from.offset());
21806      range.setEnd(to.container(), to.offset());
21807      return range;
21808    };
21809    const hasOnlyTwoOrLessPositionsLeft = elm => lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => {
21810      const normalizedFirstPos = normalizePosition(true, firstPos);
21811      const normalizedLastPos = normalizePosition(false, lastPos);
21812      return nextPosition(elm, normalizedFirstPos).forall(pos => pos.isEqual(normalizedLastPos));
21813    }).getOr(true);
21814    const setCaretLocation = (editor, caret) => location => renderCaret(caret, location).map(pos => () => setCaretPosition(editor, pos));
21815    const deleteFromTo = (editor, caret, from, to) => {
21816      const rootNode = editor.getBody();
21817      const isInlineTarget$1 = curry(isInlineTarget, editor);
21818      editor.undoManager.ignore(() => {
21819        editor.selection.setRng(rangeFromPositions(from, to));
21820        execNativeDeleteCommand(editor);
21821        readLocation(isInlineTarget$1, rootNode, CaretPosition.fromRangeStart(editor.selection.getRng())).map(inside).bind(setCaretLocation(editor, caret)).each(call);
21822      });
21823      editor.nodeChanged();
21824    };
21825    const rescope = (rootNode, node) => {
21826      const parentBlock = getParentBlock$3(node, rootNode);
21827      return parentBlock ? parentBlock : rootNode;
21828    };
21829    const backspaceDeleteCollapsed = (editor, caret, forward, from) => {
21830      const rootNode = rescope(editor.getBody(), from.container());
21831      const isInlineTarget$1 = curry(isInlineTarget, editor);
21832      const fromLocation = readLocation(isInlineTarget$1, rootNode, from);
21833      const location = fromLocation.bind(location => {
21834        if (forward) {
21835          return location.fold(constant(Optional.some(inside(location))), Optional.none, constant(Optional.some(outside(location))), Optional.none);
21836        } else {
21837          return location.fold(Optional.none, constant(Optional.some(outside(location))), Optional.none, constant(Optional.some(inside(location))));
21838        }
21839      });
21840      return location.map(setCaretLocation(editor, caret)).getOrThunk(() => {
21841        const toPosition = navigate(forward, rootNode, from);
21842        const toLocation = toPosition.bind(pos => readLocation(isInlineTarget$1, rootNode, pos));
21843        return lift2(fromLocation, toLocation, () => findRootInline(isInlineTarget$1, rootNode, from).bind(elm => {
21844          if (hasOnlyTwoOrLessPositionsLeft(elm)) {
21845            return Optional.some(() => {
21846              deleteElement$2(editor, forward, SugarElement.fromDom(elm));
21847            });
21848          } else {
21849            return Optional.none();
21850          }
21851        })).getOrThunk(() => toLocation.bind(() => toPosition.map(to => {
21852          return () => {
21853            if (forward) {
21854              deleteFromTo(editor, caret, from, to);
21855            } else {
21856              deleteFromTo(editor, caret, to, from);
21857            }
21858          };
21859        })));
21860      });
21861    };
21862    const backspaceDelete$3 = (editor, caret, forward) => {
21863      if (editor.selection.isCollapsed() && isInlineBoundariesEnabled(editor)) {
21864        const from = CaretPosition.fromRangeStart(editor.selection.getRng());
21865        return backspaceDeleteCollapsed(editor, caret, forward, from);
21866      }
21867      return Optional.none();
21868    };
21869
21870    const hasMultipleChildren = elm => childNodesCount(elm) > 1;
21871    const getParentsUntil = (editor, pred) => {
21872      const rootElm = SugarElement.fromDom(editor.getBody());
21873      const startElm = SugarElement.fromDom(editor.selection.getStart());
21874      const parents = parentsAndSelf(startElm, rootElm);
21875      return findIndex$2(parents, pred).fold(constant(parents), index => parents.slice(0, index));
21876    };
21877    const 
vendor: 948 bytes, lines 21877-21895
21877getParentInlinesUntilMultichildInline = editor => getParentsUntil(editor, elm => isBlock$2(elm) || hasMultipleChildren(elm));
21878    const getParentInlines = editor => getParentsUntil(editor, isBlock$2);
21879    const getFormatNodes = (editor, parentInlines) => {
21880      const isFormatElement$1 = curry(isFormatElement, editor);
21881      return bind$3(parentInlines, elm => isFormatElement$1(elm) ? [elm.dom] : []);
21882    };
21883    const getFormatNodesAtStart = editor => {
21884      const parentInlines = getParentInlines(editor);
21885      return getFormatNodes(editor, parentInlines);
21886    };
21887    const deleteLastPosition = (forward, editor, target, parentInlines) => {
21888      const formatNodes = getFormatNodes(editor, parentInlines);
21889      if (formatNodes.length === 0) {
21890        deleteElement$2(editor, forward, target);
21891      } else {
21892        const pos = replaceWithCaretFormat(target.dom, formatNodes);
21893        editor.selection.setRng(pos.toRange());
21894      }
21895    };
vendor: 1,095 bytes, lines 21896-21914
21896    const deleteCaret$1 = (editor, forward) => {
21897      const parentInlines = getParentInlinesUntilMultichildInline(editor);
21898      return last$3(parentInlines).bind(target => {
21899        const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
21900        if (willDeleteLastPositionInElement(forward, fromPos, target.dom) && !isEmptyCaretFormatElement(target)) {
21901          return Optional.some(() => deleteLastPosition(forward, editor, target, parentInlines));
21902        } else {
21903          return Optional.none();
21904        }
21905      });
21906    };
21907    const isBrInEmptyElement = (editor, elm) => {
21908      const parentElm = elm.parentElement;
21909      return isBr$6(elm) && !isNull(parentElm) && editor.dom.isEmpty(parentElm);
21910    };
21911    const isEmptyCaret = elm => isEmptyCaretFormatElement(SugarElement.fromDom(elm));
21912    const createCaretFormatAtStart = (editor, formatNodes) => {
21913      const startElm = editor.selection.getStart();
21914      const pos = isBrInEmptyElement(editor, startElm) || isEmptyCaret(startElm) ? replaceWithCaretFormat(startElm, formatNodes) : createCaretFormatAtStart$1(editor
vendor: 20,410 bytes, lines 21914-22393
21914, formatNodes);
21915      editor.selection.setRng(pos.toRange());
21916    };
21917    const updateCaretFormat = (editor, updateFormats) => {
21918      const missingFormats = difference(updateFormats, getFormatNodesAtStart(editor));
21919      if (missingFormats.length > 0) {
21920        createCaretFormatAtStart(editor, missingFormats);
21921      }
21922    };
21923    const rangeStartsAtTextContainer = rng => isText$a(rng.startContainer);
21924    const rangeStartsAtStartOfTextContainer = rng => rng.startOffset === 0 && rangeStartsAtTextContainer(rng);
21925    const rangeStartParentIsFormatElement = (editor, rng) => {
21926      const startParent = rng.startContainer.parentElement;
21927      return !isNull(startParent) && isFormatElement(editor, SugarElement.fromDom(startParent));
21928    };
21929    const rangeStartAndEndHaveSameParent = rng => {
21930      const startParent = rng.startContainer.parentNode;
21931      const endParent = rng.endContainer.parentNode;
21932      return !isNull(startParent) && !isNull(endParent) && startParent.isEqualNode(endParent);
21933    };
21934    const rangeEndsAtEndOfEndContainer = rng => {
21935      const endContainer = rng.endContainer;
21936      return rng.endOffset === (isText$a(endContainer) ? endContainer.length : endContainer.childNodes.length);
21937    };
21938    const rangeEndsAtEndOfStartContainer = rng => rangeStartAndEndHaveSameParent(rng) && rangeEndsAtEndOfEndContainer(rng);
21939    const rangeEndsAfterEndOfStartContainer = rng => !rng.endContainer.isEqualNode(rng.commonAncestorContainer);
21940    const rangeEndsAtOrAfterEndOfStartContainer = rng => rangeEndsAtEndOfStartContainer(rng) || rangeEndsAfterEndOfStartContainer(rng);
21941    const requiresDeleteRangeOverride = editor => {
21942      const rng = editor.selection.getRng();
21943      return rangeStartsAtStartOfTextContainer(rng) && rangeStartParentIsFormatElement(editor, rng) && rangeEndsAtOrAfterEndOfStartContainer(rng);
21944    };
21945    const deleteRange$1 = editor => {
21946      if (requiresDeleteRangeOverride(editor)) {
21947        const formatNodes = getFormatNodesAtStart(editor);
21948        return Optional.some(() => {
21949          execNativeDeleteCommand(editor);
21950          updateCaretFormat(editor, formatNodes);
21951        });
21952      } else {
21953        return Optional.none();
21954      }
21955    };
21956    const backspaceDelete$2 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret$1(editor, forward) : deleteRange$1(editor);
21957    const hasAncestorInlineCaret = elm => ancestor$1(elm, node => isCaretNode(node.dom), isBlock$2);
21958    const hasAncestorInlineCaretAtStart = editor => hasAncestorInlineCaret(SugarElement.fromDom(editor.selection.getStart()));
21959    const requiresRefreshCaretOverride = editor => {
21960      const rng = editor.selection.getRng();
21961      return rng.collapsed && (rangeStartsAtTextContainer(rng) || editor.dom.isEmpty(rng.startContainer)) && !hasAncestorInlineCaretAtStart(editor);
21962    };
21963    const refreshCaret = editor => {
21964      if (requiresRefreshCaretOverride(editor)) {
21965        createCaretFormatAtStart(editor, []);
21966      }
21967      return true;
21968    };
21969
21970    const deleteElement = (editor, forward, element) => {
21971      if (isNonNullable(element)) {
21972        return Optional.some(() => {
21973          editor._selectionOverrides.hideFakeCaret();
21974          deleteElement$2(editor, forward, SugarElement.fromDom(element));
21975        });
21976      } else {
21977        return Optional.none();
21978      }
21979    };
21980    const deleteCaret = (editor, forward) => {
21981      const isNearMedia = forward ? isBeforeMedia : isAfterMedia;
21982      const direction = forward ? HDirection.Forwards : HDirection.Backwards;
21983      const fromPos = getNormalizedRangeEndPoint(direction, editor.getBody(), editor.selection.getRng());
21984      if (isNearMedia(fromPos)) {
21985        return deleteElement(editor, forward, fromPos.getNode(!forward));
21986      } else {
21987        return Optional.from(normalizePosition(forward, fromPos)).filter(pos => isNearMedia(pos) && isMoveInsideSameBlock(fromPos, pos)).bind(pos => deleteElement(editor, forward, pos.getNode(!forward)));
21988      }
21989    };
21990    const deleteRange = (editor, forward) => {
21991      const selectedNode = editor.selection.getNode();
21992      return isMedia$2(selectedNode) ? deleteElement(editor, forward, selectedNode) : Optional.none();
21993    };
21994    const backspaceDelete$1 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret(editor, forward) : deleteRange(editor, forward);
21995
21996    const isEditable = target => closest$4(target, elm => isContentEditableTrue$3(elm.dom) || isContentEditableFalse$b(elm.dom)).exists(elm => isContentEditableTrue$3(elm.dom));
21997    const parseIndentValue = value => toInt(value !== null && value !== void 0 ? value : '').getOr(0);
21998    const getIndentStyleName = (useMargin, element) => {
21999      const indentStyleName = useMargin || isTable$1(element) ? 'margin' : 'padding';
22000      const suffix = get$7(element, 'direction') === 'rtl' ? '-right' : '-left';
22001      return indentStyleName + suffix;
22002    };
22003    const indentElement = (dom, command, useMargin, value, unit, element) => {
22004      const indentStyleName = getIndentStyleName(useMargin, SugarElement.fromDom(element));
22005      const parsedValue = parseIndentValue(dom.getStyle(element, indentStyleName));
22006      if (command === 'outdent') {
22007        const styleValue = Math.max(0, parsedValue - value);
22008        dom.setStyle(element, indentStyleName, styleValue ? styleValue + unit : '');
22009      } else {
22010        const styleValue = parsedValue + value + unit;
22011        dom.setStyle(element, indentStyleName, styleValue);
22012      }
22013    };
22014    const validateBlocks = (editor, blocks) => forall(blocks, block => {
22015      const indentStyleName = getIndentStyleName(shouldIndentUseMargin(editor), block);
22016      const intentValue = getRaw(block, indentStyleName).map(parseIndentValue).getOr(0);
22017      const contentEditable = editor.dom.getContentEditable(block.dom);
22018      return contentEditable !== 'false' && intentValue > 0;
22019    });
22020    const canOutdent = editor => {
22021      const blocks = getBlocksToIndent(editor);
22022      return !editor.mode.isReadOnly() && (blocks.length > 1 || validateBlocks(editor, blocks));
22023    };
22024    const isListComponent = el => isList(el) || isListItem$1(el);
22025    const parentIsListComponent = el => parent(el).exists(isListComponent);
22026    const getBlocksToIndent = editor => filter$5(fromDom$1(editor.selection.getSelectedBlocks()), el => !isListComponent(el) && !parentIsListComponent(el) && isEditable(el));
22027    const handle = (editor, command) => {
22028      var _a, _b;
22029      const {dom} = editor;
22030      const indentation = getIndentation(editor);
22031      const indentUnit = (_b = (_a = /[a-z%]+$/i.exec(indentation)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 'px';
22032      const indentValue = parseIndentValue(indentation);
22033      const useMargin = shouldIndentUseMargin(editor);
22034      each$e(getBlocksToIndent(editor), block => {
22035        indentElement(dom, command, useMargin, indentValue, indentUnit, block.dom);
22036      });
22037    };
22038    const indent = editor => handle(editor, 'indent');
22039    const outdent = editor => handle(editor, 'outdent');
22040
22041    const backspaceDelete = editor => {
22042      if (editor.selection.isCollapsed() && canOutdent(editor)) {
22043        const dom = editor.dom;
22044        const rng = editor.selection.getRng();
22045        const pos = CaretPosition.fromRangeStart(rng);
22046        const block = dom.getParent(rng.startContainer, dom.isBlock);
22047        if (block !== null && isAtStartOfBlock(SugarElement.fromDom(block), pos)) {
22048          return Optional.some(() => outdent(editor));
22049        }
22050      }
22051      return Optional.none();
22052    };
22053
22054    const findAction = (editor, caret, forward) => findMap([
22055      backspaceDelete,
22056      backspaceDelete$5,
22057      backspaceDelete$6,
22058      (editor, forward) => backspaceDelete$3(editor, caret, forward),
22059      backspaceDelete$8,
22060      backspaceDelete$9,
22061      backspaceDelete$4,
22062      backspaceDelete$1,
22063      backspaceDelete$7,
22064      backspaceDelete$2
22065    ], item => item(editor, forward)).filter(_ => editor.selection.isEditable());
22066    const deleteCommand = (editor, caret) => {
22067      const result = findAction(editor, caret, false);
22068      result.fold(() => {
22069        execNativeDeleteCommand(editor);
22070        paddEmptyBody(editor);
22071      }, call);
22072    };
22073    const forwardDeleteCommand = (editor, caret) => {
22074      const result = findAction(editor, caret, true);
22075      result.fold(() => execNativeForwardDeleteCommand(editor), call);
22076    };
22077    const setup$p = (editor, caret) => {
22078      editor.addCommand('delete', () => {
22079        deleteCommand(editor, caret);
22080      });
22081      editor.addCommand('forwardDelete', () => {
22082        forwardDeleteCommand(editor, caret);
22083      });
22084    };
22085
22086    const SIGNIFICANT_MOVE = 5;
22087    const LONGPRESS_DELAY = 400;
22088    const getTouch = event => {
22089      if (event.touches === undefined || event.touches.length !== 1) {
22090        return Optional.none();
22091      }
22092      return Optional.some(event.touches[0]);
22093    };
22094    const isFarEnough = (touch, data) => {
22095      const distX = Math.abs(touch.clientX - data.x);
22096      const distY = Math.abs(touch.clientY - data.y);
22097      return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
22098    };
22099    const setup$o = editor => {
22100      const startData = value$2();
22101      const longpressFired = Cell(false);
22102      const debounceLongpress = last$1(e => {
22103        editor.dispatch('longpress', {
22104          ...e,
22105          type: 'longpress'
22106        });
22107        longpressFired.set(true);
22108      }, LONGPRESS_DELAY);
22109      editor.on('touchstart', e => {
22110        getTouch(e).each(touch => {
22111          debounceLongpress.cancel();
22112          const data = {
22113            x: touch.clientX,
22114            y: touch.clientY,
22115            target: e.target
22116          };
22117          debounceLongpress.throttle(e);
22118          longpressFired.set(false);
22119          startData.set(data);
22120        });
22121      }, true);
22122      editor.on('touchmove', e => {
22123        debounceLongpress.cancel();
22124        getTouch(e).each(touch => {
22125          startData.on(data => {
22126            if (isFarEnough(touch, data)) {
22127              startData.clear();
22128              longpressFired.set(false);
22129              editor.dispatch('longpresscancel');
22130            }
22131          });
22132        });
22133      }, true);
22134      editor.on('touchend touchcancel', e => {
22135        debounceLongpress.cancel();
22136        if (e.type === 'touchcancel') {
22137          return;
22138        }
22139        startData.get().filter(data => data.target.isEqualNode(e.target)).each(() => {
22140          if (longpressFired.get()) {
22141            e.preventDefault();
22142          } else {
22143            editor.dispatch('tap', {
22144              ...e,
22145              type: 'tap'
22146            });
22147          }
22148        });
22149      }, true);
22150    };
22151
22152    const isBlockElement = (blockElements, node) => has$2(blockElements, node.nodeName);
22153    const isValidTarget = (schema, node) => {
22154      if (isText$a(node)) {
22155        return true;
22156      } else if (isElement$6(node)) {
22157        return !isBlockElement(schema.getBlockElements(), node) && !isBookmarkNode$1(node) && !isTransparentBlock(schema, node);
22158      } else {
22159        return false;
22160      }
22161    };
22162    const hasBlockParent = (blockElements, root, node) => {
22163      return exists(parents(SugarElement.fromDom(node), SugarElement.fromDom(root)), elm => {
22164        return isBlockElement(blockElements, elm.dom);
22165      });
22166    };
22167    const shouldRemoveTextNode = (blockElements, node) => {
22168      if (isText$a(node)) {
22169        if (node.data.length === 0) {
22170          return true;
22171        } else if (/^\s+$/.test(node.data) && (!node.nextSibling || isBlockElement(blockElements, node.nextSibling))) {
22172          return true;
22173        }
22174      }
22175      return false;
22176    };
22177    const createRootBlock = editor => editor.dom.create(getForcedRootBlock(editor), getForcedRootBlockAttrs(editor));
22178    const addRootBlocks = editor => {
22179      const dom = editor.dom, selection = editor.selection;
22180      const schema = editor.schema;
22181      const blockElements = schema.getBlockElements();
22182      const startNode = selection.getStart();
22183      const rootNode = editor.getBody();
22184      let rootBlockNode;
22185      let tempNode;
22186      let wrapped = false;
22187      const forcedRootBlock = getForcedRootBlock(editor);
22188      if (!startNode || !isElement$6(startNode)) {
22189        return;
22190      }
22191      const rootNodeName = rootNode.nodeName.toLowerCase();
22192      if (!schema.isValidChild(rootNodeName, forcedRootBlock.toLowerCase()) || hasBlockParent(blockElements, rootNode, startNode)) {
22193        return;
22194      }
22195      const rng = selection.getRng();
22196      const {startContainer, startOffset, endContainer, endOffset} = rng;
22197      const restoreSelection = hasFocus(editor);
22198      let node = rootNode.firstChild;
22199      while (node) {
22200        if (isElement$6(node)) {
22201          updateElement(schema, node);
22202        }
22203        if (isValidTarget(schema, node)) {
22204          if (shouldRemoveTextNode(blockElements, node)) {
22205            tempNode = node;
22206            node = node.nextSibling;
22207            dom.remove(tempNode);
22208            continue;
22209          }
22210          if (!rootBlockNode) {
22211            rootBlockNode = createRootBlock(editor);
22212            rootNode.insertBefore(rootBlockNode, node);
22213            wrapped = true;
22214          }
22215          tempNode = node;
22216          node = node.nextSibling;
22217          rootBlockNode.appendChild(tempNode);
22218        } else {
22219          rootBlockNode = null;
22220          node = node.nextSibling;
22221        }
22222      }
22223      if (wrapped && restoreSelection) {
22224        rng.setStart(startContainer, startOffset);
22225        rng.setEnd(endContainer, endOffset);
22226        selection.setRng(rng);
22227        editor.nodeChanged();
22228      }
22229    };
22230    const insertEmptyLine = (editor, root, insertBlock) => {
22231      const block = SugarElement.fromDom(createRootBlock(editor));
22232      const br = createPaddingBr();
22233      append$1(block, br);
22234      insertBlock(root, block);
22235      const rng = document.createRange();
22236      rng.setStartBefore(br.dom);
22237      rng.setEndBefore(br.dom);
22238      return rng;
22239    };
22240    const setup$n = editor => {
22241      editor.on('NodeChange', curry(addRootBlocks, editor));
22242    };
22243
22244    const hasClass = checkClassName => node => (' ' + node.attr('class') + ' ').indexOf(checkClassName) !== -1;
22245    const replaceMatchWithSpan = (editor, content, cls) => {
22246      return function (match) {
22247        const args = arguments, index = args[args.length - 2];
22248        const prevChar = index > 0 ? content.charAt(index - 1) : '';
22249        if (prevChar === '"') {
22250          return match;
22251        }
22252        if (prevChar === '>') {
22253          const findStartTagIndex = content.lastIndexOf('<', index);
22254          if (findStartTagIndex !== -1) {
22255            const tagHtml = content.substring(findStartTagIndex, index);
22256            if (tagHtml.indexOf('contenteditable="false"') !== -1) {
22257              return match;
22258            }
22259          }
22260        }
22261        return '<span class="' + cls + '" data-mce-content="' + editor.dom.encode(args[0]) + '">' + editor.dom.encode(typeof args[1] === 'string' ? args[1] : args[0]) + '</span>';
22262      };
22263    };
22264    const convertRegExpsToNonEditable = (editor, nonEditableRegExps, e) => {
22265      let i = nonEditableRegExps.length, content = e.content;
22266      if (e.format === 'raw') {
22267        return;
22268      }
22269      while (i--) {
22270        content = content.replace(nonEditableRegExps[i], replaceMatchWithSpan(editor, content, getNonEditableClass(editor)));
22271      }
22272      e.content = content;
22273    };
22274    const setup$m = editor => {
22275      const contentEditableAttrName = 'contenteditable';
22276      const editClass = ' ' + Tools.trim(getEditableClass(editor)) + ' ';
22277      const nonEditClass = ' ' + Tools.trim(getNonEditableClass(editor)) + ' ';
22278      const hasEditClass = hasClass(editClass);
22279      const hasNonEditClass = hasClass(nonEditClass);
22280      const nonEditableRegExps = getNonEditableRegExps(editor);
22281      if (nonEditableRegExps.length > 0) {
22282        editor.on('BeforeSetContent', e => {
22283          convertRegExpsToNonEditable(editor, nonEditableRegExps, e);
22284        });
22285      }
22286      editor.parser.addAttributeFilter('class', nodes => {
22287        let i = nodes.length;
22288        while (i--) {
22289          const node = nodes[i];
22290          if (hasEditClass(node)) {
22291            node.attr(contentEditableAttrName, 'true');
22292          } else if (hasNonEditClass(node)) {
22293            node.attr(contentEditableAttrName, 'false');
22294          }
22295        }
22296      });
22297      editor.serializer.addAttributeFilter(contentEditableAttrName, nodes => {
22298        let i = nodes.length;
22299        while (i--) {
22300          const node = nodes[i];
22301          if (!hasEditClass(node) && !hasNonEditClass(node)) {
22302            continue;
22303          }
22304          if (nonEditableRegExps.length > 0 && node.attr('data-mce-content')) {
22305            node.name = '#text';
22306            node.type = 3;
22307            node.raw = true;
22308            node.value = node.attr('data-mce-content');
22309          } else {
22310            node.attr(contentEditableAttrName, null);
22311          }
22312        }
22313      });
22314    };
22315
22316    const findBlockCaretContainer = editor => descendant(SugarElement.fromDom(editor.getBody()), '*[data-mce-caret]').map(elm => elm.dom).getOrNull();
22317    const showBlockCaretContainer = (editor, blockCaretContainer) => {
22318      if (blockCaretContainer.hasAttribute('data-mce-caret')) {
22319        showCaretContainerBlock(blockCaretContainer);
22320        editor.selection.setRng(editor.selection.getRng());
22321        editor.selection.scrollIntoView(blockCaretContainer);
22322      }
22323    };
22324    const handleBlockContainer = (editor, e) => {
22325      const blockCaretContainer = findBlockCaretContainer(editor);
22326      if (!blockCaretContainer) {
22327        return;
22328      }
22329      if (e.type === 'compositionstart') {
22330        e.preventDefault();
22331        e.stopPropagation();
22332        showBlockCaretContainer(editor, blockCaretContainer);
22333        return;
22334      }
22335      if (hasContent(blockCaretContainer)) {
22336        showBlockCaretContainer(editor, blockCaretContainer);
22337        editor.undoManager.add();
22338      }
22339    };
22340    const setup$l = editor => {
22341      editor.on('keyup compositionstart', curry(handleBlockContainer, editor));
22342    };
22343
22344    const isContentEditableFalse$3 = isContentEditableFalse$b;
22345    const moveToCeFalseHorizontally = (direction, editor, range) => moveHorizontally(editor, direction, range, isBeforeContentEditableFalse, isAfterContentEditableFalse, isContentEditableFalse$3);
22346    const moveToCeFalseVertically = (direction, editor, range) => {
22347      const isBefore = caretPosition => isBeforeContentEditableFalse(caretPosition) || isBeforeTable(caretPosition);
22348      const isAfter = caretPosition => isAfterContentEditableFalse(caretPosition) || isAfterTable(caretPosition);
22349      return moveVertically(editor, direction, range, isBefore, isAfter, isContentEditableFalse$3);
22350    };
22351    const createTextBlock = editor => {
22352      const textBlock = editor.dom.create(getForcedRootBlock(editor));
22353      textBlock.innerHTML = '<br data-mce-bogus="1">';
22354      return textBlock;
22355    };
22356    const exitPreBlock = (editor, direction, range) => {
22357      const caretWalker = CaretWalker(editor.getBody());
22358      const getVisualCaretPosition$1 = curry(getVisualCaretPosition, direction === 1 ? caretWalker.next : caretWalker.prev);
22359      if (range.collapsed) {
22360        const pre = editor.dom.getParent(range.startContainer, 'PRE');
22361        if (!pre) {
22362          return;
22363        }
22364        const caretPos = getVisualCaretPosition$1(CaretPosition.fromRangeStart(range));
22365        if (!caretPos) {
22366          const newBlock = SugarElement.fromDom(createTextBlock(editor));
22367          if (direction === 1) {
22368            after$4(SugarElement.fromDom(pre), newBlock);
22369          } else {
22370            before$3(SugarElement.fromDom(pre), newBlock);
22371          }
22372          editor.selection.select(newBlock.dom, true);
22373          editor.selection.collapse();
22374        }
22375      }
22376    };
22377    const getHorizontalRange = (editor, forward) => {
22378      const direction = forward ? HDirection.Forwards : HDirection.Backwards;
22379      const range = editor.selection.getRng();
22380      return moveToCeFalseHorizontally(direction, editor, range).orThunk(() => {
22381        exitPreBlock(editor, direction, range);
22382        return Optional.none();
22383      });
22384    };
22385    const getVerticalRange = (editor, down) => {
22386      const direction = down ? 1 : -1;
22387      const range = editor.selection.getRng();
22388      return moveToCeFalseVertically(direction, editor, range).orThunk(() => {
22389        exitPreBlock(editor, direction, range);
22390        return Optional.none();
22391      });
22392    };
22393    const 
22393moveH$2 = (editor, forward) => getHorizontalRange(editor, forward
vendor: 43,962 bytes, lines 22393-23541
22393).exists(newRange => {
22394      moveToRange(editor, newRange);
22395      return true;
22396    });
22397    const moveV$3 = (editor, down) => getVerticalRange(editor, down).exists(newRange => {
22398      moveToRange(editor, newRange);
22399      return true;
22400    });
22401    const moveToLineEndPoint$1 = (editor, forward) => {
22402      const isCefPosition = forward ? isAfterContentEditableFalse : isBeforeContentEditableFalse;
22403      return moveToLineEndPoint$3(editor, forward, isCefPosition);
22404    };
22405    const selectToEndPoint = (editor, forward) => getEdgeCefPosition(editor, !forward).map(pos => {
22406      const rng = pos.toRange();
22407      const curRng = editor.selection.getRng();
22408      if (forward) {
22409        rng.setStart(curRng.startContainer, curRng.startOffset);
22410      } else {
22411        rng.setEnd(curRng.endContainer, curRng.endOffset);
22412      }
22413      return rng;
22414    }).exists(rng => {
22415      moveToRange(editor, rng);
22416      return true;
22417    });
22418
22419    const isTarget = node => contains$2(['figcaption'], name(node));
22420    const getClosestTargetBlock = (pos, root) => {
22421      const isRoot = curry(eq, root);
22422      return closest$4(SugarElement.fromDom(pos.container()), isBlock$2, isRoot).filter(isTarget);
22423    };
22424    const isAtFirstOrLastLine = (root, forward, pos) => forward ? isAtLastLine(root.dom, pos) : isAtFirstLine(root.dom, pos);
22425    const moveCaretToNewEmptyLine = (editor, forward) => {
22426      const root = SugarElement.fromDom(editor.getBody());
22427      const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
22428      return getClosestTargetBlock(pos, root).exists(() => {
22429        if (isAtFirstOrLastLine(root, forward, pos)) {
22430          const insertFn = forward ? append$1 : prepend;
22431          const rng = insertEmptyLine(editor, root, insertFn);
22432          editor.selection.setRng(rng);
22433          return true;
22434        } else {
22435          return false;
22436        }
22437      });
22438    };
22439    const moveV$2 = (editor, forward) => {
22440      if (editor.selection.isCollapsed()) {
22441        return moveCaretToNewEmptyLine(editor, forward);
22442      } else {
22443        return false;
22444      }
22445    };
22446
22447    const baseKeyPattern = {
22448      shiftKey: false,
22449      altKey: false,
22450      ctrlKey: false,
22451      metaKey: false,
22452      keyCode: 0
22453    };
22454    const defaultPatterns = patterns => map$3(patterns, pattern => ({
22455      ...baseKeyPattern,
22456      ...pattern
22457    }));
22458    const defaultDelayedPatterns = patterns => map$3(patterns, pattern => ({
22459      ...baseKeyPattern,
22460      ...pattern
22461    }));
22462    const matchesEvent = (pattern, evt) => evt.keyCode === pattern.keyCode && evt.shiftKey === pattern.shiftKey && evt.altKey === pattern.altKey && evt.ctrlKey === pattern.ctrlKey && evt.metaKey === pattern.metaKey;
22463    const match$1 = (patterns, evt) => bind$3(defaultPatterns(patterns), pattern => matchesEvent(pattern, evt) ? [pattern] : []);
22464    const matchDelayed = (patterns, evt) => bind$3(defaultDelayedPatterns(patterns), pattern => matchesEvent(pattern, evt) ? [pattern] : []);
22465    const action = (f, ...x) => () => f.apply(null, x);
22466    const execute = (patterns, evt) => find$2(match$1(patterns, evt), pattern => pattern.action());
22467    const executeWithDelayedAction = (patterns, evt) => findMap(matchDelayed(patterns, evt), pattern => pattern.action());
22468
22469    const moveH$1 = (editor, forward) => {
22470      const direction = forward ? HDirection.Forwards : HDirection.Backwards;
22471      const range = editor.selection.getRng();
22472      return moveHorizontally(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists(newRange => {
22473        moveToRange(editor, newRange);
22474        return true;
22475      });
22476    };
22477    const moveV$1 = (editor, down) => {
22478      const direction = down ? 1 : -1;
22479      const range = editor.selection.getRng();
22480      return moveVertically(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists(newRange => {
22481        moveToRange(editor, newRange);
22482        return true;
22483      });
22484    };
22485    const moveToLineEndPoint = (editor, forward) => {
22486      const isNearMedia = forward ? isAfterMedia : isBeforeMedia;
22487      return moveToLineEndPoint$3(editor, forward, isNearMedia);
22488    };
22489
22490    const adt = Adt.generate([
22491      { none: ['current'] },
22492      { first: ['current'] },
22493      {
22494        middle: [
22495          'current',
22496          'target'
22497        ]
22498      },
22499      { last: ['current'] }
22500    ]);
22501    const none = current => adt.none(current);
22502    const CellLocation = {
22503      ...adt,
22504      none
22505    };
22506
22507    const firstLayer = (scope, selector) => {
22508      return filterFirstLayer(scope, selector, always);
22509    };
22510    const filterFirstLayer = (scope, selector, predicate) => {
22511      return bind$3(children$1(scope), x => {
22512        if (is$1(x, selector)) {
22513          return predicate(x) ? [x] : [];
22514        } else {
22515          return filterFirstLayer(x, selector, predicate);
22516        }
22517      });
22518    };
22519
22520    const lookup$1 = (tags, element, isRoot = never) => {
22521      if (isRoot(element)) {
22522        return Optional.none();
22523      }
22524      if (contains$2(tags, name(element))) {
22525        return Optional.some(element);
22526      }
22527      const isRootOrUpperTable = elm => is$1(elm, 'table') || isRoot(elm);
22528      return ancestor$3(element, tags.join(','), isRootOrUpperTable);
22529    };
22530    const cell = (element, isRoot) => lookup$1([
22531      'td',
22532      'th'
22533    ], element, isRoot);
22534    const cells = ancestor => firstLayer(ancestor, 'th,td');
22535    const table = (element, isRoot) => closest$3(element, 'table', isRoot);
22536
22537    const walk = (all, current, index, direction, isEligible = always) => {
22538      const forwards = direction === 1;
22539      if (!forwards && index <= 0) {
22540        return CellLocation.first(all[0]);
22541      } else if (forwards && index >= all.length - 1) {
22542        return CellLocation.last(all[all.length - 1]);
22543      } else {
22544        const newIndex = index + direction;
22545        const elem = all[newIndex];
22546        return isEligible(elem) ? CellLocation.middle(current, elem) : walk(all, current, newIndex, direction, isEligible);
22547      }
22548    };
22549    const detect = (current, isRoot) => {
22550      return table(current, isRoot).bind(table => {
22551        const all = cells(table);
22552        const index = findIndex$2(all, x => eq(current, x));
22553        return index.map(index => ({
22554          index,
22555          all
22556        }));
22557      });
22558    };
22559    const next = (current, isEligible, isRoot) => {
22560      const detection = detect(current, isRoot);
22561      return detection.fold(() => {
22562        return CellLocation.none(current);
22563      }, info => {
22564        return walk(info.all, current, info.index, 1, isEligible);
22565      });
22566    };
22567    const prev = (current, isEligible, isRoot) => {
22568      const detection = detect(current, isRoot);
22569      return detection.fold(() => {
22570        return CellLocation.none();
22571      }, info => {
22572        return walk(info.all, current, info.index, -1, isEligible);
22573      });
22574    };
22575
22576    const deflate = (rect, delta) => ({
22577      left: rect.left - delta,
22578      top: rect.top - delta,
22579      right: rect.right + delta * 2,
22580      bottom: rect.bottom + delta * 2,
22581      width: rect.width + delta,
22582      height: rect.height + delta
22583    });
22584    const getCorners = (getYAxisValue, tds) => bind$3(tds, td => {
22585      const rect = deflate(clone$1(td.getBoundingClientRect()), -1);
22586      return [
22587        {
22588          x: rect.left,
22589          y: getYAxisValue(rect),
22590          cell: td
22591        },
22592        {
22593          x: rect.right,
22594          y: getYAxisValue(rect),
22595          cell: td
22596        }
22597      ];
22598    });
22599    const findClosestCorner = (corners, x, y) => foldl(corners, (acc, newCorner) => acc.fold(() => Optional.some(newCorner), oldCorner => {
22600      const oldDist = Math.sqrt(Math.abs(oldCorner.x - x) + Math.abs(oldCorner.y - y));
22601      const newDist = Math.sqrt(Math.abs(newCorner.x - x) + Math.abs(newCorner.y - y));
22602      return Optional.some(newDist < oldDist ? newCorner : oldCorner);
22603    }), Optional.none());
22604    const getClosestCell = (getYAxisValue, isTargetCorner, table, x, y) => {
22605      const cells = descendants(SugarElement.fromDom(table), 'td,th,caption').map(e => e.dom);
22606      const corners = filter$5(getCorners(getYAxisValue, cells), corner => isTargetCorner(corner, y));
22607      return findClosestCorner(corners, x, y).map(corner => corner.cell);
22608    };
22609    const getBottomValue = rect => rect.bottom;
22610    const getTopValue = rect => rect.top;
22611    const isAbove = (corner, y) => corner.y < y;
22612    const isBelow = (corner, y) => corner.y > y;
22613    const getClosestCellAbove = curry(getClosestCell, getBottomValue, isAbove);
22614    const getClosestCellBelow = curry(getClosestCell, getTopValue, isBelow);
22615    const findClosestPositionInAboveCell = (table, pos) => head(pos.getClientRects()).bind(rect => getClosestCellAbove(table, rect.left, rect.top)).bind(cell => findClosestHorizontalPosition(getLastLinePositions(cell), pos));
22616    const findClosestPositionInBelowCell = (table, pos) => last$3(pos.getClientRects()).bind(rect => getClosestCellBelow(table, rect.left, rect.top)).bind(cell => findClosestHorizontalPosition(getFirstLinePositions(cell), pos));
22617
22618    const hasNextBreak = (getPositionsUntil, scope, lineInfo) => lineInfo.breakAt.exists(breakPos => getPositionsUntil(scope, breakPos).breakAt.isSome());
22619    const startsWithWrapBreak = lineInfo => lineInfo.breakType === BreakType.Wrap && lineInfo.positions.length === 0;
22620    const startsWithBrBreak = lineInfo => lineInfo.breakType === BreakType.Br && lineInfo.positions.length === 1;
22621    const isAtTableCellLine = (getPositionsUntil, scope, pos) => {
22622      const lineInfo = getPositionsUntil(scope, pos);
22623      if (startsWithWrapBreak(lineInfo) || !isBr$6(pos.getNode()) && startsWithBrBreak(lineInfo)) {
22624        return !hasNextBreak(getPositionsUntil, scope, lineInfo);
22625      } else {
22626        return lineInfo.breakAt.isNone();
22627      }
22628    };
22629    const isAtFirstTableCellLine = curry(isAtTableCellLine, getPositionsUntilPreviousLine);
22630    const isAtLastTableCellLine = curry(isAtTableCellLine, getPositionsUntilNextLine);
22631    const isCaretAtStartOrEndOfTable = (forward, rng, table) => {
22632      const caretPos = CaretPosition.fromRangeStart(rng);
22633      return positionIn(!forward, table).exists(pos => pos.isEqual(caretPos));
22634    };
22635    const navigateHorizontally = (editor, forward, table, _td) => {
22636      const rng = editor.selection.getRng();
22637      const direction = forward ? 1 : -1;
22638      if (isFakeCaretTableBrowser() && isCaretAtStartOrEndOfTable(forward, rng, table)) {
22639        showCaret(direction, editor, table, !forward, false).each(newRng => {
22640          moveToRange(editor, newRng);
22641        });
22642        return true;
22643      }
22644      return false;
22645    };
22646    const getClosestAbovePosition = (root, table, start) => findClosestPositionInAboveCell(table, start).orThunk(() => head(start.getClientRects()).bind(rect => findClosestHorizontalPositionFromPoint(getPositionsAbove(root, CaretPosition.before(table)), rect.left))).getOr(CaretPosition.before(table));
22647    const getClosestBelowPosition = (root, table, start) => findClosestPositionInBelowCell(table, start).orThunk(() => head(start.getClientRects()).bind(rect => findClosestHorizontalPositionFromPoint(getPositionsBelow(root, CaretPosition.after(table)), rect.left))).getOr(CaretPosition.after(table));
22648    const getTable = (previous, pos) => {
22649      const node = pos.getNode(previous);
22650      return isTable$2(node) ? Optional.some(node) : Optional.none();
22651    };
22652    const renderBlock = (down, editor, table) => {
22653      editor.undoManager.transact(() => {
22654        const insertFn = down ? after$4 : before$3;
22655        const rng = insertEmptyLine(editor, SugarElement.fromDom(table), insertFn);
22656        moveToRange(editor, rng);
22657      });
22658    };
22659    const moveCaret = (editor, down, pos) => {
22660      const table = down ? getTable(true, pos) : getTable(false, pos);
22661      const last = down === false;
22662      table.fold(() => moveToRange(editor, pos.toRange()), table => positionIn(last, editor.getBody()).filter(lastPos => lastPos.isEqual(pos)).fold(() => moveToRange(editor, pos.toRange()), _ => renderBlock(down, editor, table)));
22663    };
22664    const navigateVertically = (editor, down, table, td) => {
22665      const rng = editor.selection.getRng();
22666      const pos = CaretPosition.fromRangeStart(rng);
22667      const root = editor.getBody();
22668      if (!down && isAtFirstTableCellLine(td, pos)) {
22669        const newPos = getClosestAbovePosition(root, table, pos);
22670        moveCaret(editor, down, newPos);
22671        return true;
22672      } else if (down && isAtLastTableCellLine(td, pos)) {
22673        const newPos = getClosestBelowPosition(root, table, pos);
22674        moveCaret(editor, down, newPos);
22675        return true;
22676      } else {
22677        return false;
22678      }
22679    };
22680    const move$1 = (editor, forward, mover) => Optional.from(editor.dom.getParent(editor.selection.getNode(), 'td,th')).bind(td => Optional.from(editor.dom.getParent(td, 'table')).map(table => mover(editor, forward, table, td))).getOr(false);
22681    const moveH = (editor, forward) => move$1(editor, forward, navigateHorizontally);
22682    const moveV = (editor, forward) => move$1(editor, forward, navigateVertically);
22683    const getCellFirstCursorPosition = cell => {
22684      const selection = SimSelection.exact(cell, 0, cell, 0);
22685      return toNative(selection);
22686    };
22687    const tabGo = (editor, isRoot, cell) => {
22688      return cell.fold(Optional.none, Optional.none, (_current, next) => {
22689        return first(next).map(cell => {
22690          return getCellFirstCursorPosition(cell);
22691        });
22692      }, current => {
22693        editor.execCommand('mceTableInsertRowAfter');
22694        return tabForward(editor, isRoot, current);
22695      });
22696    };
22697    const tabForward = (editor, isRoot, cell) => tabGo(editor, isRoot, next(cell, isEditable$3));
22698    const tabBackward = (editor, isRoot, cell) => tabGo(editor, isRoot, prev(cell, isEditable$3));
22699    const handleTab = (editor, forward) => {
22700      const rootElements = [
22701        'table',
22702        'li',
22703        'dl'
22704      ];
22705      const body = SugarElement.fromDom(editor.getBody());
22706      const isRoot = element => {
22707        const name$1 = name(element);
22708        return eq(element, body) || contains$2(rootElements, name$1);
22709      };
22710      const rng = editor.selection.getRng();
22711      const container = SugarElement.fromDom(!forward ? rng.startContainer : rng.endContainer);
22712      return cell(container, isRoot).map(cell => {
22713        table(cell, isRoot).each(table => {
22714          editor.model.table.clearSelectedCells(table.dom);
22715        });
22716        editor.selection.collapse(!forward);
22717        const navigation = !forward ? tabBackward : tabForward;
22718        const rng = navigation(editor, isRoot, cell);
22719        rng.each(range => {
22720          editor.selection.setRng(range);
22721        });
22722        return true;
22723      }).getOr(false);
22724    };
22725
22726    const executeKeydownOverride$4 = (editor, caret, evt) => {
22727      const isMac = Env.os.isMacOS() || Env.os.isiOS();
22728      execute([
22729        {
22730          keyCode: VK.RIGHT,
22731          action: action(moveH$2, editor, true)
22732        },
22733        {
22734          keyCode: VK.LEFT,
22735          action: action(moveH$2, editor, false)
22736        },
22737        {
22738          keyCode: VK.UP,
22739          action: action(moveV$3, editor, false)
22740        },
22741        {
22742          keyCode: VK.DOWN,
22743          action: action(moveV$3, editor, true)
22744        },
22745        ...isMac ? [
22746          {
22747            keyCode: VK.UP,
22748            action: action(selectToEndPoint, editor, false),
22749            metaKey: true,
22750            shiftKey: true
22751          },
22752          {
22753            keyCode: VK.DOWN,
22754            action: action(selectToEndPoint, editor, true),
22755            metaKey: true,
22756            shiftKey: true
22757          }
22758        ] : [],
22759        {
22760          keyCode: VK.RIGHT,
22761          action: action(moveH, editor, true)
22762        },
22763        {
22764          keyCode: VK.LEFT,
22765          action: action(moveH, editor, false)
22766        },
22767        {
22768          keyCode: VK.UP,
22769          action: action(moveV, editor, false)
22770        },
22771        {
22772          keyCode: VK.DOWN,
22773          action: action(moveV, editor, true)
22774        },
22775        {
22776          keyCode: VK.RIGHT,
22777          action: action(moveH$1, editor, true)
22778        },
22779        {
22780          keyCode: VK.LEFT,
22781          action: action(moveH$1, editor, false)
22782        },
22783        {
22784          keyCode: VK.UP,
22785          action: action(moveV$1, editor, false)
22786        },
22787        {
22788          keyCode: VK.DOWN,
22789          action: action(moveV$1, editor, true)
22790        },
22791        {
22792          keyCode: VK.RIGHT,
22793          action: action(move$2, editor, caret, true)
22794        },
22795        {
22796          keyCode: VK.LEFT,
22797          action: action(move$2, editor, caret, false)
22798        },
22799        {
22800          keyCode: VK.RIGHT,
22801          ctrlKey: !isMac,
22802          altKey: isMac,
22803          action: action(moveNextWord, editor, caret)
22804        },
22805        {
22806          keyCode: VK.LEFT,
22807          ctrlKey: !isMac,
22808          altKey: isMac,
22809          action: action(movePrevWord, editor, caret)
22810        },
22811        {
22812          keyCode: VK.UP,
22813          action: action(moveV$2, editor, false)
22814        },
22815        {
22816          keyCode: VK.DOWN,
22817          action: action(moveV$2, editor, true)
22818        }
22819      ], evt).each(_ => {
22820        evt.preventDefault();
22821      });
22822    };
22823    const setup$k = (editor, caret) => {
22824      editor.on('keydown', evt => {
22825        if (!evt.isDefaultPrevented()) {
22826          executeKeydownOverride$4(editor, caret, evt);
22827        }
22828      });
22829    };
22830
22831    const point = (container, offset) => ({
22832      container,
22833      offset
22834    });
22835
22836    const DOM$7 = DOMUtils.DOM;
22837    const alwaysNext = startNode => node => startNode === node ? -1 : 0;
22838    const isBoundary = dom => node => dom.isBlock(node) || contains$2([
22839      'BR',
22840      'IMG',
22841      'HR',
22842      'INPUT'
22843    ], node.nodeName) || dom.getContentEditable(node) === 'false';
22844    const textBefore = (node, offset, rootNode) => {
22845      if (isText$a(node) && offset >= 0) {
22846        return Optional.some(point(node, offset));
22847      } else {
22848        const textSeeker = TextSeeker(DOM$7);
22849        return Optional.from(textSeeker.backwards(node, offset, alwaysNext(node), rootNode)).map(prev => point(prev.container, prev.container.data.length));
22850      }
22851    };
22852    const textAfter = (node, offset, rootNode) => {
22853      if (isText$a(node) && offset >= node.length) {
22854        return Optional.some(point(node, offset));
22855      } else {
22856        const textSeeker = TextSeeker(DOM$7);
22857        return Optional.from(textSeeker.forwards(node, offset, alwaysNext(node), rootNode)).map(prev => point(prev.container, 0));
22858      }
22859    };
22860    const scanLeft = (node, offset, rootNode) => {
22861      if (!isText$a(node)) {
22862        return Optional.none();
22863      }
22864      const text = node.data;
22865      if (offset >= 0 && offset <= text.length) {
22866        return Optional.some(point(node, offset));
22867      } else {
22868        const textSeeker = TextSeeker(DOM$7);
22869        return Optional.from(textSeeker.backwards(node, offset, alwaysNext(node), rootNode)).bind(prev => {
22870          const prevText = prev.container.data;
22871          return scanLeft(prev.container, offset + prevText.length, rootNode);
22872        });
22873      }
22874    };
22875    const scanRight = (node, offset, rootNode) => {
22876      if (!isText$a(node)) {
22877        return Optional.none();
22878      }
22879      const text = node.data;
22880      if (offset <= text.length) {
22881        return Optional.some(point(node, offset));
22882      } else {
22883        const textSeeker = TextSeeker(DOM$7);
22884        return Optional.from(textSeeker.forwards(node, offset, alwaysNext(node), rootNode)).bind(next => scanRight(next.container, offset - text.length, rootNode));
22885      }
22886    };
22887    const repeatLeft = (dom, node, offset, process, rootNode) => {
22888      const search = TextSeeker(dom, isBoundary(dom));
22889      return Optional.from(search.backwards(node, offset, process, rootNode));
22890    };
22891
22892    const isValidTextRange = rng => rng.collapsed && isText$a(rng.startContainer);
22893    const getText = rng => trim$1(rng.toString().replace(/\u00A0/g, ' '));
22894    const isWhitespace = chr => chr !== '' && ' \xA0\f\n\r\t\x0B'.indexOf(chr) !== -1;
22895
22896    const stripTrigger = (text, trigger) => text.substring(trigger.length);
22897    const findTrigger = (text, index, trigger) => {
22898      let i;
22899      const firstChar = trigger.charAt(0);
22900      for (i = index - 1; i >= 0; i--) {
22901        const char = text.charAt(i);
22902        if (isWhitespace(char)) {
22903          return Optional.none();
22904        }
22905        if (firstChar === char && contains$1(text, trigger, i, index)) {
22906          break;
22907        }
22908      }
22909      return Optional.some(i);
22910    };
22911    const findStart = (dom, initRange, trigger, minChars = 0) => {
22912      if (!isValidTextRange(initRange)) {
22913        return Optional.none();
22914      }
22915      const buffer = {
22916        text: '',
22917        offset: 0
22918      };
22919      const findTriggerIndex = (element, offset, text) => {
22920        buffer.text = text + buffer.text;
22921        buffer.offset += offset;
22922        return findTrigger(buffer.text, buffer.offset, trigger).getOr(offset);
22923      };
22924      const root = dom.getParent(initRange.startContainer, dom.isBlock) || dom.getRoot();
22925      return repeatLeft(dom, initRange.startContainer, initRange.startOffset, findTriggerIndex, root).bind(spot => {
22926        const range = initRange.cloneRange();
22927        range.setStart(spot.container, spot.offset);
22928        range.setEnd(initRange.endContainer, initRange.endOffset);
22929        if (range.collapsed) {
22930          return Optional.none();
22931        }
22932        const text = getText(range);
22933        const triggerIndex = text.lastIndexOf(trigger);
22934        if (triggerIndex !== 0 || stripTrigger(text, trigger).length < minChars) {
22935          return Optional.none();
22936        } else {
22937          return Optional.some({
22938            text: stripTrigger(text, trigger),
22939            range,
22940            trigger
22941          });
22942        }
22943      });
22944    };
22945    const getContext = (dom, initRange, trigger, minChars = 0) => detect$1(SugarElement.fromDom(initRange.startContainer)).fold(() => findStart(dom, initRange, trigger, minChars), elm => {
22946      const range = dom.createRng();
22947      range.selectNode(elm.dom);
22948      const text = getText(range);
22949      return Optional.some({
22950        range,
22951        text: stripTrigger(text, trigger),
22952        trigger
22953      });
22954    });
22955
22956    const isText$1 = node => node.nodeType === TEXT;
22957    const isElement = node => node.nodeType === ELEMENT;
22958    const toLast = node => {
22959      if (isText$1(node)) {
22960        return point(node, node.data.length);
22961      } else {
22962        const children = node.childNodes;
22963        return children.length > 0 ? toLast(children[children.length - 1]) : point(node, children.length);
22964      }
22965    };
22966    const toLeaf = (node, offset) => {
22967      const children = node.childNodes;
22968      if (children.length > 0 && offset < children.length) {
22969        return toLeaf(children[offset], 0);
22970      } else if (children.length > 0 && isElement(node) && children.length === offset) {
22971        return toLast(children[children.length - 1]);
22972      } else {
22973        return point(node, offset);
22974      }
22975    };
22976
22977    const isPreviousCharContent = (dom, leaf) => {
22978      var _a;
22979      const root = (_a = dom.getParent(leaf.container, dom.isBlock)) !== null && _a !== void 0 ? _a : dom.getRoot();
22980      return repeatLeft(dom, leaf.container, leaf.offset, (_element, offset) => offset === 0 ? -1 : offset, root).filter(spot => {
22981        const char = spot.container.data.charAt(spot.offset - 1);
22982        return !isWhitespace(char);
22983      }).isSome();
22984    };
22985    const isStartOfWord = dom => rng => {
22986      const leaf = toLeaf(rng.startContainer, rng.startOffset);
22987      return !isPreviousCharContent(dom, leaf);
22988    };
22989    const getTriggerContext = (dom, initRange, database) => findMap(database.triggers, trigger => getContext(dom, initRange, trigger));
22990    const lookup = (editor, getDatabase) => {
22991      const database = getDatabase();
22992      const rng = editor.selection.getRng();
22993      return getTriggerContext(editor.dom, rng, database).bind(context => lookupWithContext(editor, getDatabase, context));
22994    };
22995    const lookupWithContext = (editor, getDatabase, context, fetchOptions = {}) => {
22996      var _a;
22997      const database = getDatabase();
22998      const rng = editor.selection.getRng();
22999      const startText = (_a = rng.startContainer.nodeValue) !== null && _a !== void 0 ? _a : '';
23000      const autocompleters = filter$5(database.lookupByTrigger(context.trigger), autocompleter => context.text.length >= autocompleter.minChars && autocompleter.matches.getOrThunk(() => isStartOfWord(editor.dom))(context.range, startText, context.text));
23001      if (autocompleters.length === 0) {
23002        return Optional.none();
23003      }
23004      const lookupData = Promise.all(map$3(autocompleters, ac => {
23005        const fetchResult = ac.fetch(context.text, ac.maxResults, fetchOptions);
23006        return fetchResult.then(results => ({
23007          matchText: context.text,
23008          items: results,
23009          columns: ac.columns,
23010          onAction: ac.onAction,
23011          highlightOn: ac.highlightOn
23012        }));
23013      }));
23014      return Optional.some({
23015        lookupData,
23016        context
23017      });
23018    };
23019
23020    var SimpleResultType;
23021    (function (SimpleResultType) {
23022      SimpleResultType[SimpleResultType['Error'] = 0] = 'Error';
23023      SimpleResultType[SimpleResultType['Value'] = 1] = 'Value';
23024    }(SimpleResultType || (SimpleResultType = {})));
23025    const fold$1 = (res, onError, onValue) => res.stype === SimpleResultType.Error ? onError(res.serror) : onValue(res.svalue);
23026    const partition = results => {
23027      const values = [];
23028      const errors = [];
23029      each$e(results, obj => {
23030        fold$1(obj, err => errors.push(err), val => values.push(val));
23031      });
23032      return {
23033        values,
23034        errors
23035      };
23036    };
23037    const mapError = (res, f) => {
23038      if (res.stype === SimpleResultType.Error) {
23039        return {
23040          stype: SimpleResultType.Error,
23041          serror: f(res.serror)
23042        };
23043      } else {
23044        return res;
23045      }
23046    };
23047    const map = (res, f) => {
23048      if (res.stype === SimpleResultType.Value) {
23049        return {
23050          stype: SimpleResultType.Value,
23051          svalue: f(res.svalue)
23052        };
23053      } else {
23054        return res;
23055      }
23056    };
23057    const bind$1 = (res, f) => {
23058      if (res.stype === SimpleResultType.Value) {
23059        return f(res.svalue);
23060      } else {
23061        return res;
23062      }
23063    };
23064    const bindError = (res, f) => {
23065      if (res.stype === SimpleResultType.Error) {
23066        return f(res.serror);
23067      } else {
23068        return res;
23069      }
23070    };
23071    const svalue = v => ({
23072      stype: SimpleResultType.Value,
23073      svalue: v
23074    });
23075    const serror = e => ({
23076      stype: SimpleResultType.Error,
23077      serror: e
23078    });
23079    const toResult = res => fold$1(res, Result.error, Result.value);
23080    const fromResult = res => res.fold(serror, svalue);
23081    const SimpleResult = {
23082      fromResult,
23083      toResult,
23084      svalue,
23085      partition,
23086      serror,
23087      bind: bind$1,
23088      bindError,
23089      map,
23090      mapError,
23091      fold: fold$1
23092    };
23093
23094    const formatObj = input => {
23095      return isObject(input) && keys(input).length > 100 ? ' removed due to size' : JSON.stringify(input, null, 2);
23096    };
23097    const formatErrors = errors => {
23098      const es = errors.length > 10 ? errors.slice(0, 10).concat([{
23099          path: [],
23100          getErrorInfo: constant('... (only showing first ten failures)')
23101        }]) : errors;
23102      return map$3(es, e => {
23103        return 'Failed path: (' + e.path.join(' > ') + ')\n' + e.getErrorInfo();
23104      });
23105    };
23106
23107    const nu = (path, getErrorInfo) => {
23108      return SimpleResult.serror([{
23109          path,
23110          getErrorInfo
23111        }]);
23112    };
23113    const missingRequired = (path, key, obj) => nu(path, () => 'Could not find valid *required* value for "' + key + '" in ' + formatObj(obj));
23114    const missingKey = (path, key) => nu(path, () => 'Choice schema did not contain choice key: "' + key + '"');
23115    const missingBranch = (path, branches, branch) => nu(path, () => 'The chosen schema: "' + branch + '" did not exist in branches: ' + formatObj(branches));
23116    const custom = (path, err) => nu(path, constant(err));
23117
23118    const chooseFrom = (path, input, branches, ch) => {
23119      const fields = get$a(branches, ch);
23120      return fields.fold(() => missingBranch(path, branches, ch), vp => vp.extract(path.concat(['branch: ' + ch]), input));
23121    };
23122    const choose$1 = (key, branches) => {
23123      const extract = (path, input) => {
23124        const choice = get$a(input, key);
23125        return choice.fold(() => missingKey(path, key), chosen => chooseFrom(path, input, branches, chosen));
23126      };
23127      const toString = () => 'chooseOn(' + key + '). Possible values: ' + keys(branches);
23128      return {
23129        extract,
23130        toString
23131      };
23132    };
23133
23134    const shallow = (old, nu) => {
23135      return nu;
23136    };
23137    const deep = (old, nu) => {
23138      const bothObjects = isPlainObject(old) && isPlainObject(nu);
23139      return bothObjects ? deepMerge(old, nu) : nu;
23140    };
23141    const baseMerge = merger => {
23142      return (...objects) => {
23143        if (objects.length === 0) {
23144          throw new Error(`Can't merge zero objects`);
23145        }
23146        const ret = {};
23147        for (let j = 0; j < objects.length; j++) {
23148          const curObject = objects[j];
23149          for (const key in curObject) {
23150            if (has$2(curObject, key)) {
23151              ret[key] = merger(ret[key], curObject[key]);
23152            }
23153          }
23154        }
23155        return ret;
23156      };
23157    };
23158    const deepMerge = baseMerge(deep);
23159    const merge = baseMerge(shallow);
23160
23161    const required = () => ({
23162      tag: 'required',
23163      process: {}
23164    });
23165    const defaultedThunk = fallbackThunk => ({
23166      tag: 'defaultedThunk',
23167      process: fallbackThunk
23168    });
23169    const defaulted$1 = fallback => defaultedThunk(constant(fallback));
23170    const asOption = () => ({
23171      tag: 'option',
23172      process: {}
23173    });
23174
23175    const mergeValues = (values, base) => values.length > 0 ? SimpleResult.svalue(deepMerge(base, merge.apply(undefined, values))) : SimpleResult.svalue(base);
23176    const mergeErrors = errors => compose(SimpleResult.serror, flatten)(errors);
23177    const consolidateObj = (objects, base) => {
23178      const partition = SimpleResult.partition(objects);
23179      return partition.errors.length > 0 ? mergeErrors(partition.errors) : mergeValues(partition.values, base);
23180    };
23181    const consolidateArr = objects => {
23182      const partitions = SimpleResult.partition(objects);
23183      return partitions.errors.length > 0 ? mergeErrors(partitions.errors) : SimpleResult.svalue(partitions.values);
23184    };
23185    const ResultCombine = {
23186      consolidateObj,
23187      consolidateArr
23188    };
23189
23190    const field$1 = (key, newKey, presence, prop) => ({
23191      tag: 'field',
23192      key,
23193      newKey,
23194      presence,
23195      prop
23196    });
23197    const customField$1 = (newKey, instantiator) => ({
23198      tag: 'custom',
23199      newKey,
23200      instantiator
23201    });
23202    const fold = (value, ifField, ifCustom) => {
23203      switch (value.tag) {
23204      case 'field':
23205        return ifField(value.key, value.newKey, value.presence, value.prop);
23206      case 'custom':
23207        return ifCustom(value.newKey, value.instantiator);
23208      }
23209    };
23210
23211    const value = validator => {
23212      const extract = (path, val) => {
23213        return SimpleResult.bindError(validator(val), err => custom(path, err));
23214      };
23215      const toString = constant('val');
23216      return {
23217        extract,
23218        toString
23219      };
23220    };
23221    const anyValue$1 = value(SimpleResult.svalue);
23222
23223    const requiredAccess = (path, obj, key, bundle) => get$a(obj, key).fold(() => missingRequired(path, key, obj), bundle);
23224    const fallbackAccess = (obj, key, fallback, bundle) => {
23225      const v = get$a(obj, key).getOrThunk(() => fallback(obj));
23226      return bundle(v);
23227    };
23228    const optionAccess = (obj, key, bundle) => bundle(get$a(obj, key));
23229    const optionDefaultedAccess = (obj, key, fallback, bundle) => {
23230      const opt = get$a(obj, key).map(val => val === true ? fallback(obj) : val);
23231      return bundle(opt);
23232    };
23233    const extractField = (field, path, obj, key, prop) => {
23234      const bundle = av => prop.extract(path.concat([key]), av);
23235      const bundleAsOption = optValue => optValue.fold(() => SimpleResult.svalue(Optional.none()), ov => {
23236        const result = prop.extract(path.concat([key]), ov);
23237        return SimpleResult.map(result, Optional.some);
23238      });
23239      switch (field.tag) {
23240      case 'required':
23241        return requiredAccess(path, obj, key, bundle);
23242      case 'defaultedThunk':
23243        return fallbackAccess(obj, key, field.process, bundle);
23244      case 'option':
23245        return optionAccess(obj, key, bundleAsOption);
23246      case 'defaultedOptionThunk':
23247        return optionDefaultedAccess(obj, key, field.process, bundleAsOption);
23248      case 'mergeWithThunk': {
23249          return fallbackAccess(obj, key, constant({}), v => {
23250            const result = deepMerge(field.process(obj), v);
23251            return bundle(result);
23252          });
23253        }
23254      }
23255    };
23256    const extractFields = (path, obj, fields) => {
23257      const success = {};
23258      const errors = [];
23259      for (const field of fields) {
23260        fold(field, (key, newKey, presence, prop) => {
23261          const result = extractField(presence, path, obj, key, prop);
23262          SimpleResult.fold(result, err => {
23263            errors.push(...err);
23264          }, res => {
23265            success[newKey] = res;
23266          });
23267        }, (newKey, instantiator) => {
23268          success[newKey] = instantiator(obj);
23269        });
23270      }
23271      return errors.length > 0 ? SimpleResult.serror(errors) : SimpleResult.svalue(success);
23272    };
23273    const objOf = values => {
23274      const extract = (path, o) => extractFields(path, o, values);
23275      const toString = () => {
23276        const fieldStrings = map$3(values, value => fold(value, (key, _okey, _presence, prop) => key + ' -> ' + prop.toString(), (newKey, _instantiator) => 'state(' + newKey + ')'));
23277        return 'obj{\n' + fieldStrings.join('\n') + '}';
23278      };
23279      return {
23280        extract,
23281        toString
23282      };
23283    };
23284    const arrOf = prop => {
23285      const extract = (path, array) => {
23286        const results = map$3(array, (a, i) => prop.extract(path.concat(['[' + i + ']']), a));
23287        return ResultCombine.consolidateArr(results);
23288      };
23289      const toString = () => 'array(' + prop.toString() + ')';
23290      return {
23291        extract,
23292        toString
23293      };
23294    };
23295
23296    const valueOf = validator => value(v => validator(v).fold(SimpleResult.serror, SimpleResult.svalue));
23297    const extractValue = (label, prop, obj) => {
23298      const res = prop.extract([label], obj);
23299      return SimpleResult.mapError(res, errs => ({
23300        input: obj,
23301        errors: errs
23302      }));
23303    };
23304    const asRaw = (label, prop, obj) => SimpleResult.toResult(extractValue(label, prop, obj));
23305    const formatError = errInfo => {
23306      return 'Errors: \n' + formatErrors(errInfo.errors).join('\n') + '\n\nInput object: ' + formatObj(errInfo.input);
23307    };
23308    const choose = (key, branches) => choose$1(key, map$2(branches, objOf));
23309
23310    const anyValue = constant(anyValue$1);
23311    const typedValue = (validator, expectedType) => value(a => {
23312      const actualType = typeof a;
23313      return validator(a) ? SimpleResult.svalue(a) : SimpleResult.serror(`Expected type: ${ expectedType } but got: ${ actualType }`);
23314    });
23315    const number = typedValue(isNumber, 'number');
23316    const string = typedValue(isString, 'string');
23317    const boolean = typedValue(isBoolean, 'boolean');
23318    const functionProcessor = typedValue(isFunction, 'function');
23319
23320    const field = field$1;
23321    const customField = customField$1;
23322    const validateEnum = values => valueOf(value => contains$2(values, value) ? Result.value(value) : Result.error(`Unsupported value: "${ value }", choose one of "${ values.join(', ') }".`));
23323    const requiredOf = (key, schema) => field(key, key, required(), schema);
23324    const requiredString = key => requiredOf(key, string);
23325    const requiredFunction = key => requiredOf(key, functionProcessor);
23326    const requiredArrayOf = (key, schema) => field(key, key, required(), arrOf(schema));
23327    const optionOf = (key, schema) => field(key, key, asOption(), schema);
23328    const optionString = key => optionOf(key, string);
23329    const optionFunction = key => optionOf(key, functionProcessor);
23330    const defaulted = (key, fallback) => field(key, key, defaulted$1(fallback), anyValue());
23331    const defaultedOf = (key, fallback, schema) => field(key, key, defaulted$1(fallback), schema);
23332    const defaultedNumber = (key, fallback) => defaultedOf(key, fallback, number);
23333    const defaultedString = (key, fallback) => defaultedOf(key, fallback, string);
23334    const defaultedStringEnum = (key, fallback, values) => defaultedOf(key, fallback, validateEnum(values));
23335    const defaultedBoolean = (key, fallback) => defaultedOf(key, fallback, boolean);
23336    const defaultedFunction = (key, fallback) => defaultedOf(key, fallback, functionProcessor);
23337    const defaultedArrayOf = (key, fallback, schema) => defaultedOf(key, fallback, arrOf(schema));
23338
23339    const type = requiredString('type');
23340    const fetch$1 = requiredFunction('fetch');
23341    const onAction = requiredFunction('onAction');
23342    const onSetup = defaultedFunction('onSetup', () => noop);
23343    const optionalText = optionString('text');
23344    const optionalIcon = optionString('icon');
23345    const optionalTooltip = optionString('tooltip');
23346    const optionalLabel = optionString('label');
23347    const active = defaultedBoolean('active', false);
23348    const enabled = defaultedBoolean('enabled', true);
23349    const primary = defaultedBoolean('primary', false);
23350    const defaultedColumns = num => defaulted('columns', num);
23351    const defaultedType = type => defaultedString('type', type);
23352
23353    const autocompleterSchema = objOf([
23354      type,
23355      requiredString('trigger'),
23356      defaultedNumber('minChars', 1),
23357      defaultedColumns(1),
23358      defaultedNumber('maxResults', 10),
23359      optionFunction('matches'),
23360      fetch$1,
23361      onAction,
23362      defaultedArrayOf('highlightOn', [], string)
23363    ]);
23364    const createAutocompleter = spec => asRaw('Autocompleter', autocompleterSchema, {
23365      trigger: spec.ch,
23366      ...spec
23367    });
23368
23369    const baseToolbarButtonFields = [
23370      enabled,
23371      optionalTooltip,
23372      optionalIcon,
23373      optionalText,
23374      onSetup
23375    ];
23376
23377    const baseToolbarToggleButtonFields = [active].concat(baseToolbarButtonFields);
23378
23379    const contextBarFields = [
23380      defaultedFunction('predicate', never),
23381      defaultedStringEnum('scope', 'node', [
23382        'node',
23383        'editor'
23384      ]),
23385      defaultedStringEnum('position', 'selection', [
23386        'node',
23387        'selection',
23388        'line'
23389      ])
23390    ];
23391
23392    const contextButtonFields = baseToolbarButtonFields.concat([
23393      defaultedType('contextformbutton'),
23394      primary,
23395      onAction,
23396      customField('original', identity)
23397    ]);
23398    const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([
23399      defaultedType('contextformbutton'),
23400      primary,
23401      onAction,
23402      customField('original', identity)
23403    ]);
23404    const launchButtonFields = baseToolbarButtonFields.concat([defaultedType('contextformbutton')]);
23405    const launchToggleButtonFields = baseToolbarToggleButtonFields.concat([defaultedType('contextformtogglebutton')]);
23406    const toggleOrNormal = choose('type', {
23407      contextformbutton: contextButtonFields,
23408      contextformtogglebutton: contextToggleButtonFields
23409    });
23410    objOf([
23411      defaultedType('contextform'),
23412      defaultedFunction('initValue', constant('')),
23413      optionalLabel,
23414      requiredArrayOf('commands', toggleOrNormal),
23415      optionOf('launch', choose('type', {
23416        contextformbutton: launchButtonFields,
23417        contextformtogglebutton: launchToggleButtonFields
23418      }))
23419    ].concat(contextBarFields));
23420
23421    const register$2 = editor => {
23422      const popups = editor.ui.registry.getAll().popups;
23423      const dataset = map$2(popups, popup => createAutocompleter(popup).fold(err => {
23424        throw new Error(formatError(err));
23425      }, identity));
23426      const triggers = stringArray(mapToArray(dataset, v => v.trigger));
23427      const datasetValues = values(dataset);
23428      const lookupByTrigger = trigger => filter$5(datasetValues, dv => dv.trigger === trigger);
23429      return {
23430        dataset,
23431        triggers,
23432        lookupByTrigger
23433      };
23434    };
23435
23436    const setupEditorInput = (editor, api) => {
23437      const update = last$1(api.load, 50);
23438      editor.on('keypress compositionend', e => {
23439        if (e.which === 27) {
23440          return;
23441        }
23442        update.throttle();
23443      });
23444      editor.on('keydown', e => {
23445        const keyCode = e.which;
23446        if (keyCode === 8) {
23447          update.throttle();
23448        } else if (keyCode === 27) {
23449          api.cancelIfNecessary();
23450        }
23451      });
23452      editor.on('remove', update.cancel);
23453    };
23454    const setup$j = editor => {
23455      const activeAutocompleter = value$2();
23456      const uiActive = Cell(false);
23457      const isActive = activeAutocompleter.isSet;
23458      const cancelIfNecessary = () => {
23459        if (isActive()) {
23460          removeAutocompleterDecoration(editor);
23461          fireAutocompleterEnd(editor);
23462          uiActive.set(false);
23463          activeAutocompleter.clear();
23464        }
23465      };
23466      const commenceIfNecessary = context => {
23467        if (!isActive()) {
23468          addAutocompleterDecoration(editor, context.range);
23469          activeAutocompleter.set({
23470            trigger: context.trigger,
23471            matchLength: context.text.length
23472          });
23473        }
23474      };
23475      const getAutocompleters = cached(() => register$2(editor));
23476      const doLookup = fetchOptions => activeAutocompleter.get().map(ac => getContext(editor.dom, editor.selection.getRng(), ac.trigger).bind(newContext => lookupWithContext(editor, getAutocompleters, newContext, fetchOptions))).getOrThunk(() => lookup(editor, getAutocompleters));
23477      const load = fetchOptions => {
23478        doLookup(fetchOptions).fold(cancelIfNecessary, lookupInfo => {
23479          commenceIfNecessary(lookupInfo.context);
23480          lookupInfo.lookupData.then(lookupData => {
23481            activeAutocompleter.get().map(ac => {
23482              const context = lookupInfo.context;
23483              if (ac.trigger === context.trigger) {
23484                if (context.text.length - ac.matchLength >= 10) {
23485                  cancelIfNecessary();
23486                } else {
23487                  activeAutocompleter.set({
23488                    ...ac,
23489                    matchLength: context.text.length
23490                  });
23491                  if (uiActive.get()) {
23492                    fireAutocompleterUpdate(editor, { lookupData });
23493                  } else {
23494                    uiActive.set(true);
23495                    fireAutocompleterStart(editor, { lookupData });
23496                  }
23497                }
23498              }
23499            });
23500          });
23501        });
23502      };
23503      editor.addCommand('mceAutocompleterReload', (_ui, value) => {
23504        const fetchOptions = isObject(value) ? value.fetchOptions : {};
23505        load(fetchOptions);
23506      });
23507      editor.addCommand('mceAutocompleterClose', cancelIfNecessary);
23508      setupEditorInput(editor, {
23509        cancelIfNecessary,
23510        load
23511      });
23512    };
23513
23514    const createAndFireInputEvent = eventType => (editor, inputType, specifics = {}) => {
23515      const target = editor.getBody();
23516      const overrides = {
23517        bubbles: true,
23518        composed: true,
23519        data: null,
23520        isComposing: false,
23521        detail: 0,
23522        view: null,
23523        target,
23524        currentTarget: target,
23525        eventPhase: Event.AT_TARGET,
23526        originalTarget: target,
23527        explicitOriginalTarget: target,
23528        isTrusted: false,
23529        srcElement: target,
23530        cancelable: false,
23531        preventDefault: noop,
23532        inputType
23533      };
23534      const input = clone$3(new InputEvent(eventType));
23535      return editor.dispatch(eventType, {
23536        ...input,
23537        ...overrides,
23538        ...specifics
23539      });
23540    };
23541    const fire
vendor: 26,267 bytes, lines 23541-24233
23541FakeInputEvent = createAndFireInputEvent('input');
23542    const fireFakeBeforeInputEvent = createAndFireInputEvent('beforeinput');
23543
23544    const executeKeydownOverride$3 = (editor, caret, evt) => {
23545      const inputType = evt.keyCode === VK.BACKSPACE ? 'deleteContentBackward' : 'deleteContentForward';
23546      executeWithDelayedAction([
23547        {
23548          keyCode: VK.BACKSPACE,
23549          action: action(backspaceDelete, editor)
23550        },
23551        {
23552          keyCode: VK.BACKSPACE,
23553          action: action(backspaceDelete$5, editor, false)
23554        },
23555        {
23556          keyCode: VK.DELETE,
23557          action: action(backspaceDelete$5, editor, true)
23558        },
23559        {
23560          keyCode: VK.BACKSPACE,
23561          action: action(backspaceDelete$6, editor, false)
23562        },
23563        {
23564          keyCode: VK.DELETE,
23565          action: action(backspaceDelete$6, editor, true)
23566        },
23567        {
23568          keyCode: VK.BACKSPACE,
23569          action: action(backspaceDelete$3, editor, caret, false)
23570        },
23571        {
23572          keyCode: VK.DELETE,
23573          action: action(backspaceDelete$3, editor, caret, true)
23574        },
23575        {
23576          keyCode: VK.BACKSPACE,
23577          action: action(backspaceDelete$9, editor, false)
23578        },
23579        {
23580          keyCode: VK.DELETE,
23581          action: action(backspaceDelete$9, editor, true)
23582        },
23583        {
23584          keyCode: VK.BACKSPACE,
23585          action: action(backspaceDelete$4, editor, false)
23586        },
23587        {
23588          keyCode: VK.DELETE,
23589          action: action(backspaceDelete$4, editor, true)
23590        },
23591        {
23592          keyCode: VK.BACKSPACE,
23593          action: action(backspaceDelete$1, editor, false)
23594        },
23595        {
23596          keyCode: VK.DELETE,
23597          action: action(backspaceDelete$1, editor, true)
23598        },
23599        {
23600          keyCode: VK.BACKSPACE,
23601          action: action(backspaceDelete$7, editor, false)
23602        },
23603        {
23604          keyCode: VK.DELETE,
23605          action: action(backspaceDelete$7, editor, true)
23606        },
23607        {
23608          keyCode: VK.BACKSPACE,
23609          action: action(backspaceDelete$8, editor, false)
23610        },
23611        {
23612          keyCode: VK.DELETE,
23613          action: action(backspaceDelete$8, editor, true)
23614        },
23615        {
23616          keyCode: VK.BACKSPACE,
23617          action: action(backspaceDelete$2, editor, false)
23618        },
23619        {
23620          keyCode: VK.DELETE,
23621          action: action(backspaceDelete$2, editor, true)
23622        }
23623      ], evt).filter(_ => editor.selection.isEditable()).each(applyAction => {
23624        evt.preventDefault();
23625        const beforeInput = fireFakeBeforeInputEvent(editor, inputType);
23626        if (!beforeInput.isDefaultPrevented()) {
23627          applyAction();
23628          fireFakeInputEvent(editor, inputType);
23629        }
23630      });
23631    };
23632    const executeKeyupOverride = (editor, evt, isBackspaceKeydown) => {
23633      const platform = detect$2();
23634      const os = platform.os;
23635      const browser = platform.browser;
23636      const multiDeleteKeyPatterns = os.isMacOS() ? [
23637        {
23638          keyCode: VK.BACKSPACE,
23639          altKey: true,
23640          action: action(refreshCaret, editor)
23641        },
23642        {
23643          keyCode: VK.DELETE,
23644          altKey: true,
23645          action: action(refreshCaret, editor)
23646        }
23647      ] : [
23648        {
23649          keyCode: VK.BACKSPACE,
23650          ctrlKey: true,
23651          action: action(refreshCaret, editor)
23652        },
23653        {
23654          keyCode: VK.DELETE,
23655          ctrlKey: true,
23656          action: action(refreshCaret, editor)
23657        }
23658      ];
23659      if (os.isMacOS() && isBackspaceKeydown) {
23660        multiDeleteKeyPatterns.push({
23661          keyCode: browser.isFirefox() ? 224 : 91,
23662          action: action(refreshCaret, editor)
23663        });
23664      }
23665      execute([
23666        {
23667          keyCode: VK.BACKSPACE,
23668          action: action(paddEmptyElement, editor)
23669        },
23670        {
23671          keyCode: VK.DELETE,
23672          action: action(paddEmptyElement, editor)
23673        },
23674        ...multiDeleteKeyPatterns
23675      ], evt);
23676    };
23677    const setup$i = (editor, caret) => {
23678      let isBackspaceKeydown = false;
23679      editor.on('keydown', evt => {
23680        isBackspaceKeydown = evt.keyCode === VK.BACKSPACE;
23681        if (!evt.isDefaultPrevented()) {
23682          executeKeydownOverride$3(editor, caret, evt);
23683        }
23684      });
23685      editor.on('keyup', evt => {
23686        if (!evt.isDefaultPrevented()) {
23687          executeKeyupOverride(editor, evt, isBackspaceKeydown);
23688        }
23689        isBackspaceKeydown = false;
23690      });
23691    };
23692
23693    const firstNonWhiteSpaceNodeSibling = node => {
23694      while (node) {
23695        if (isElement$6(node) || isText$a(node) && node.data && /[\r\n\s]/.test(node.data)) {
23696          return node;
23697        }
23698        node = node.nextSibling;
23699      }
23700      return null;
23701    };
23702    const moveToCaretPosition = (editor, root) => {
23703      const dom = editor.dom;
23704      const moveCaretBeforeOnEnterElementsMap = editor.schema.getMoveCaretBeforeOnEnterElements();
23705      if (!root) {
23706        return;
23707      }
23708      if (/^(LI|DT|DD)$/.test(root.nodeName)) {
23709        const firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
23710        if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) {
23711          root.insertBefore(dom.doc.createTextNode(nbsp), root.firstChild);
23712        }
23713      }
23714      const rng = dom.createRng();
23715      root.normalize();
23716      if (root.hasChildNodes()) {
23717        const walker = new DomTreeWalker(root, root);
23718        let lastNode = root;
23719        let node;
23720        while (node = walker.current()) {
23721          if (isText$a(node)) {
23722            rng.setStart(node, 0);
23723            rng.setEnd(node, 0);
23724            break;
23725          }
23726          if (moveCaretBeforeOnEnterElementsMap[node.nodeName.toLowerCase()]) {
23727            rng.setStartBefore(node);
23728            rng.setEndBefore(node);
23729            break;
23730          }
23731          lastNode = node;
23732          node = walker.next();
23733        }
23734        if (!node) {
23735          rng.setStart(lastNode, 0);
23736          rng.setEnd(lastNode, 0);
23737        }
23738      } else {
23739        if (isBr$6(root)) {
23740          if (root.nextSibling && dom.isBlock(root.nextSibling)) {
23741            rng.setStartBefore(root);
23742            rng.setEndBefore(root);
23743          } else {
23744            rng.setStartAfter(root);
23745            rng.setEndAfter(root);
23746          }
23747        } else {
23748          rng.setStart(root, 0);
23749          rng.setEnd(root, 0);
23750        }
23751      }
23752      editor.selection.setRng(rng);
23753      scrollRangeIntoView(editor, rng);
23754    };
23755    const getEditableRoot = (dom, node) => {
23756      const root = dom.getRoot();
23757      let editableRoot;
23758      let parent = node;
23759      while (parent !== root && parent && dom.getContentEditable(parent) !== 'false') {
23760        if (dom.getContentEditable(parent) === 'true') {
23761          editableRoot = parent;
23762        }
23763        parent = parent.parentNode;
23764      }
23765      return parent !== root ? editableRoot : root;
23766    };
23767    const getParentBlock$1 = editor => {
23768      return Optional.from(editor.dom.getParent(editor.selection.getStart(true), editor.dom.isBlock));
23769    };
23770    const getParentBlockName = editor => {
23771      return getParentBlock$1(editor).fold(constant(''), parentBlock => {
23772        return parentBlock.nodeName.toUpperCase();
23773      });
23774    };
23775    const isListItemParentBlock = editor => {
23776      return getParentBlock$1(editor).filter(elm => {
23777        return isListItem$1(SugarElement.fromDom(elm));
23778      }).isSome();
23779    };
23780
23781    const hasFirstChild = (elm, name) => {
23782      return elm.firstChild && elm.firstChild.nodeName === name;
23783    };
23784    const isFirstChild = elm => {
23785      var _a;
23786      return ((_a = elm.parentNode) === null || _a === void 0 ? void 0 : _a.firstChild) === elm;
23787    };
23788    const hasParent = (elm, parentName) => {
23789      const parentNode = elm === null || elm === void 0 ? void 0 : elm.parentNode;
23790      return isNonNullable(parentNode) && parentNode.nodeName === parentName;
23791    };
23792    const isListBlock = elm => {
23793      return isNonNullable(elm) && /^(OL|UL|LI)$/.test(elm.nodeName);
23794    };
23795    const isListItem = elm => {
23796      return isNonNullable(elm) && /^(LI|DT|DD)$/.test(elm.nodeName);
23797    };
23798    const isNestedList = elm => {
23799      return isListBlock(elm) && isListBlock(elm.parentNode);
23800    };
23801    const getContainerBlock = containerBlock => {
23802      const containerBlockParent = containerBlock.parentNode;
23803      return isListItem(containerBlockParent) ? containerBlockParent : containerBlock;
23804    };
23805    const isFirstOrLastLi = (containerBlock, parentBlock, first) => {
23806      let node = containerBlock[first ? 'firstChild' : 'lastChild'];
23807      while (node) {
23808        if (isElement$6(node)) {
23809          break;
23810        }
23811        node = node[first ? 'nextSibling' : 'previousSibling'];
23812      }
23813      return node === parentBlock;
23814    };
23815    const insert$3 = (editor, createNewBlock, containerBlock, parentBlock, newBlockName) => {
23816      const dom = editor.dom;
23817      const rng = editor.selection.getRng();
23818      const containerParent = containerBlock.parentNode;
23819      if (containerBlock === editor.getBody() || !containerParent) {
23820        return;
23821      }
23822      if (isNestedList(containerBlock)) {
23823        newBlockName = 'LI';
23824      }
23825      let newBlock = createNewBlock(newBlockName);
23826      if (isFirstOrLastLi(containerBlock, parentBlock, true) && isFirstOrLastLi(containerBlock, parentBlock, false)) {
23827        if (hasParent(containerBlock, 'LI')) {
23828          const containerBlockParent = getContainerBlock(containerBlock);
23829          dom.insertAfter(newBlock, containerBlockParent);
23830          if (isFirstChild(containerBlock)) {
23831            dom.remove(containerBlockParent);
23832          } else {
23833            dom.remove(containerBlock);
23834          }
23835        } else {
23836          dom.replace(newBlock, containerBlock);
23837        }
23838      } else if (isFirstOrLastLi(containerBlock, parentBlock, true)) {
23839        if (hasParent(containerBlock, 'LI')) {
23840          dom.insertAfter(newBlock, getContainerBlock(containerBlock));
23841          newBlock.appendChild(dom.doc.createTextNode(' '));
23842          newBlock.appendChild(containerBlock);
23843        } else {
23844          containerParent.insertBefore(newBlock, containerBlock);
23845        }
23846        dom.remove(parentBlock);
23847      } else if (isFirstOrLastLi(containerBlock, parentBlock, false)) {
23848        dom.insertAfter(newBlock, getContainerBlock(containerBlock));
23849        dom.remove(parentBlock);
23850      } else {
23851        containerBlock = getContainerBlock(containerBlock);
23852        const tmpRng = rng.cloneRange();
23853        tmpRng.setStartAfter(parentBlock);
23854        tmpRng.setEndAfter(containerBlock);
23855        const fragment = tmpRng.extractContents();
23856        if (newBlockName === 'LI' && hasFirstChild(fragment, 'LI')) {
23857          newBlock = fragment.firstChild;
23858          dom.insertAfter(fragment, containerBlock);
23859        } else {
23860          dom.insertAfter(fragment, containerBlock);
23861          dom.insertAfter(newBlock, containerBlock);
23862        }
23863        dom.remove(parentBlock);
23864      }
23865      moveToCaretPosition(editor, newBlock);
23866    };
23867
23868    const trimZwsp = fragment => {
23869      each$e(descendants$1(SugarElement.fromDom(fragment), isText$b), text => {
23870        const rawNode = text.dom;
23871        rawNode.nodeValue = trim$1(rawNode.data);
23872      });
23873    };
23874    const isWithinNonEditableList = (editor, node) => {
23875      const parentList = editor.dom.getParent(node, 'ol,ul,dl');
23876      return parentList !== null && editor.dom.getContentEditableParent(parentList) === 'false';
23877    };
23878    const isEmptyAnchor = (dom, elm) => {
23879      return elm && elm.nodeName === 'A' && dom.isEmpty(elm);
23880    };
23881    const emptyBlock = elm => {
23882      elm.innerHTML = '<br data-mce-bogus="1">';
23883    };
23884    const containerAndSiblingName = (container, nodeName) => {
23885      return container.nodeName === nodeName || container.previousSibling && container.previousSibling.nodeName === nodeName;
23886    };
23887    const canSplitBlock = (dom, node) => {
23888      return isNonNullable(node) && dom.isBlock(node) && !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) && !/^(fixed|absolute)/i.test(node.style.position) && dom.isEditable(node.parentNode) && dom.getContentEditable(node) !== 'false';
23889    };
23890    const trimInlineElementsOnLeftSideOfBlock = (dom, nonEmptyElementsMap, block) => {
23891      var _a;
23892      const firstChilds = [];
23893      if (!block) {
23894        return;
23895      }
23896      let currentNode = block;
23897      while (currentNode = currentNode.firstChild) {
23898        if (dom.isBlock(currentNode)) {
23899          return;
23900        }
23901        if (isElement$6(currentNode) && !nonEmptyElementsMap[currentNode.nodeName.toLowerCase()]) {
23902          firstChilds.push(currentNode);
23903        }
23904      }
23905      let i = firstChilds.length;
23906      while (i--) {
23907        currentNode = firstChilds[i];
23908        if (!currentNode.hasChildNodes() || currentNode.firstChild === currentNode.lastChild && ((_a = currentNode.firstChild) === null || _a === void 0 ? void 0 : _a.nodeValue) === '') {
23909          dom.remove(currentNode);
23910        } else {
23911          if (isEmptyAnchor(dom, currentNode)) {
23912            dom.remove(currentNode);
23913          }
23914        }
23915      }
23916    };
23917    const normalizeZwspOffset = (start, container, offset) => {
23918      if (!isText$a(container)) {
23919        return offset;
23920      } else if (start) {
23921        return offset === 1 && container.data.charAt(offset - 1) === ZWSP$1 ? 0 : offset;
23922      } else {
23923        return offset === container.data.length - 1 && container.data.charAt(offset) === ZWSP$1 ? container.data.length : offset;
23924      }
23925    };
23926    const includeZwspInRange = rng => {
23927      const newRng = rng.cloneRange();
23928      newRng.setStart(rng.startContainer, normalizeZwspOffset(true, rng.startContainer, rng.startOffset));
23929      newRng.setEnd(rng.endContainer, normalizeZwspOffset(false, rng.endContainer, rng.endOffset));
23930      return newRng;
23931    };
23932    const trimLeadingLineBreaks = node => {
23933      let currentNode = node;
23934      do {
23935        if (isText$a(currentNode)) {
23936          currentNode.data = currentNode.data.replace(/^[\r\n]+/, '');
23937        }
23938        currentNode = currentNode.firstChild;
23939      } while (currentNode);
23940    };
23941    const applyAttributes = (editor, node, forcedRootBlockAttrs) => {
23942      const dom = editor.dom;
23943      Optional.from(forcedRootBlockAttrs.style).map(dom.parseStyle).each(attrStyles => {
23944        const currentStyles = getAllRaw(SugarElement.fromDom(node));
23945        const newStyles = {
23946          ...currentStyles,
23947          ...attrStyles
23948        };
23949        dom.setStyles(node, newStyles);
23950      });
23951      const attrClassesOpt = Optional.from(forcedRootBlockAttrs.class).map(attrClasses => attrClasses.split(/\s+/));
23952      const currentClassesOpt = Optional.from(node.className).map(currentClasses => filter$5(currentClasses.split(/\s+/), clazz => clazz !== ''));
23953      lift2(attrClassesOpt, currentClassesOpt, (attrClasses, currentClasses) => {
23954        const filteredClasses = filter$5(currentClasses, clazz => !contains$2(attrClasses, clazz));
23955        const newClasses = [
23956          ...attrClasses,
23957          ...filteredClasses
23958        ];
23959        dom.setAttrib(node, 'class', newClasses.join(' '));
23960      });
23961      const appliedAttrs = [
23962        'style',
23963        'class'
23964      ];
23965      const remainingAttrs = filter$4(forcedRootBlockAttrs, (_, attrs) => !contains$2(appliedAttrs, attrs));
23966      dom.setAttribs(node, remainingAttrs);
23967    };
23968    const setForcedBlockAttrs = (editor, node) => {
23969      const forcedRootBlockName = getForcedRootBlock(editor);
23970      if (forcedRootBlockName.toLowerCase() === node.tagName.toLowerCase()) {
23971        const forcedRootBlockAttrs = getForcedRootBlockAttrs(editor);
23972        applyAttributes(editor, node, forcedRootBlockAttrs);
23973      }
23974    };
23975    const wrapSelfAndSiblingsInDefaultBlock = (editor, newBlockName, rng, container, offset) => {
23976      var _a, _b;
23977      const dom = editor.dom;
23978      const editableRoot = (_a = getEditableRoot(dom, container)) !== null && _a !== void 0 ? _a : dom.getRoot();
23979      let parentBlock = dom.getParent(container, dom.isBlock);
23980      if (!parentBlock || !canSplitBlock(dom, parentBlock)) {
23981        parentBlock = parentBlock || editableRoot;
23982        if (!parentBlock.hasChildNodes()) {
23983          const newBlock = dom.create(newBlockName);
23984          setForcedBlockAttrs(editor, newBlock);
23985          parentBlock.appendChild(newBlock);
23986          rng.setStart(newBlock, 0);
23987          rng.setEnd(newBlock, 0);
23988          return newBlock;
23989        }
23990        let node = container;
23991        while (node && node.parentNode !== parentBlock) {
23992          node = node.parentNode;
23993        }
23994        let startNode;
23995        while (node && !dom.isBlock(node)) {
23996          startNode = node;
23997          node = node.previousSibling;
23998        }
23999        const startNodeName = (_b = startNode === null || startNode === void 0 ? void 0 : startNode.parentElement) === null || _b === void 0 ? void 0 : _b.nodeName;
24000        if (startNode && startNodeName && editor.schema.isValidChild(startNodeName, newBlockName.toLowerCase())) {
24001          const startNodeParent = startNode.parentNode;
24002          const newBlock = dom.create(newBlockName);
24003          setForcedBlockAttrs(editor, newBlock);
24004          startNodeParent.insertBefore(newBlock, startNode);
24005          node = startNode;
24006          while (node && !dom.isBlock(node)) {
24007            const next = node.nextSibling;
24008            newBlock.appendChild(node);
24009            node = next;
24010          }
24011          rng.setStart(container, offset);
24012          rng.setEnd(container, offset);
24013        }
24014      }
24015      return container;
24016    };
24017    const addBrToBlockIfNeeded = (dom, block) => {
24018      block.normalize();
24019      const lastChild = block.lastChild;
24020      if (!lastChild || isElement$6(lastChild) && /^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true))) {
24021        dom.add(block, 'br');
24022      }
24023    };
24024    const shouldEndContainer = (editor, container) => {
24025      const optionValue = shouldEndContainerOnEmptyBlock(editor);
24026      if (isNullable(container)) {
24027        return false;
24028      } else if (isString(optionValue)) {
24029        return contains$2(Tools.explode(optionValue), container.nodeName.toLowerCase());
24030      } else {
24031        return optionValue;
24032      }
24033    };
24034    const insert$2 = (editor, evt) => {
24035      let container;
24036      let offset;
24037      let parentBlockName;
24038      let containerBlock;
24039      let isAfterLastNodeInContainer = false;
24040      const dom = editor.dom;
24041      const schema = editor.schema, nonEmptyElementsMap = schema.getNonEmptyElements();
24042      const rng = editor.selection.getRng();
24043      const newBlockName = getForcedRootBlock(editor);
24044      const createNewBlock = name => {
24045        let node = container;
24046        const textInlineElements = schema.getTextInlineElements();
24047        let block;
24048        if (name || parentBlockName === 'TABLE' || parentBlockName === 'HR') {
24049          block = dom.create(name || newBlockName);
24050        } else {
24051          block = parentBlock.cloneNode(false);
24052        }
24053        let caretNode = block;
24054        if (shouldKeepStyles(editor) === false) {
24055          dom.setAttrib(block, 'style', null);
24056          dom.setAttrib(block, 'class', null);
24057        } else {
24058          do {
24059            if (textInlineElements[node.nodeName]) {
24060              if (isCaretNode(node) || isBookmarkNode$1(node)) {
24061                continue;
24062              }
24063              const clonedNode = node.cloneNode(false);
24064              dom.setAttrib(clonedNode, 'id', '');
24065              if (block.hasChildNodes()) {
24066                clonedNode.appendChild(block.firstChild);
24067                block.appendChild(clonedNode);
24068              } else {
24069                caretNode = clonedNode;
24070                block.appendChild(clonedNode);
24071              }
24072            }
24073          } while ((node = node.parentNode) && node !== editableRoot);
24074        }
24075        setForcedBlockAttrs(editor, block);
24076        emptyBlock(caretNode);
24077        return block;
24078      };
24079      const isCaretAtStartOrEndOfBlock = start => {
24080        const normalizedOffset = normalizeZwspOffset(start, container, offset);
24081        if (isText$a(container) && (start ? normalizedOffset > 0 : normalizedOffset < container.data.length)) {
24082          return false;
24083        }
24084        if (container.parentNode === parentBlock && isAfterLastNodeInContainer && !start) {
24085          return true;
24086        }
24087        if (start && isElement$6(container) && container === parentBlock.firstChild) {
24088          return true;
24089        }
24090        if (containerAndSiblingName(container, 'TABLE') || containerAndSiblingName(container, 'HR')) {
24091          return isAfterLastNodeInContainer && !start || !isAfterLastNodeInContainer && start;
24092        }
24093        const walker = new DomTreeWalker(container, parentBlock);
24094        if (isText$a(container)) {
24095          if (start && normalizedOffset === 0) {
24096            walker.prev();
24097          } else if (!start && normalizedOffset === container.data.length) {
24098            walker.next();
24099          }
24100        }
24101        let node;
24102        while (node = walker.current()) {
24103          if (isElement$6(node)) {
24104            if (!node.getAttribute('data-mce-bogus')) {
24105              const name = node.nodeName.toLowerCase();
24106              if (nonEmptyElementsMap[name] && name !== 'br') {
24107                return false;
24108              }
24109            }
24110          } else if (isText$a(node) && !isWhitespaceText(node.data)) {
24111            return false;
24112          }
24113          if (start) {
24114            walker.prev();
24115          } else {
24116            walker.next();
24117          }
24118        }
24119        return true;
24120      };
24121      const insertNewBlockAfter = () => {
24122        let block;
24123        if (/^(H[1-6]|PRE|FIGURE)$/.test(parentBlockName) && containerBlockName !== 'HGROUP') {
24124          block = createNewBlock(newBlockName);
24125        } else {
24126          block = createNewBlock();
24127        }
24128        if (shouldEndContainer(editor, containerBlock) && canSplitBlock(dom, containerBlock) && dom.isEmpty(parentBlock)) {
24129          block = dom.split(containerBlock, parentBlock);
24130        } else {
24131          dom.insertAfter(block, parentBlock);
24132        }
24133        moveToCaretPosition(editor, block);
24134        return block;
24135      };
24136      normalize$2(dom, rng).each(normRng => {
24137        rng.setStart(normRng.startContainer, normRng.startOffset);
24138        rng.setEnd(normRng.endContainer, normRng.endOffset);
24139      });
24140      container = rng.startContainer;
24141      offset = rng.startOffset;
24142      const shiftKey = !!(evt && evt.shiftKey);
24143      const ctrlKey = !!(evt && evt.ctrlKey);
24144      if (isElement$6(container) && container.hasChildNodes()) {
24145        isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
24146        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
24147        if (isAfterLastNodeInContainer && isText$a(container)) {
24148          offset = container.data.length;
24149        } else {
24150          offset = 0;
24151        }
24152      }
24153      const editableRoot = getEditableRoot(dom, container);
24154      if (!editableRoot || isWithinNonEditableList(editor, container)) {
24155        return;
24156      }
24157      if (!shiftKey) {
24158        container = wrapSelfAndSiblingsInDefaultBlock(editor, newBlockName, rng, container, offset);
24159      }
24160      let parentBlock = dom.getParent(container, dom.isBlock) || dom.getRoot();
24161      containerBlock = isNonNullable(parentBlock === null || parentBlock === void 0 ? void 0 : parentBlock.parentNode) ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
24162      parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : '';
24163      const containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
24164      if (containerBlockName === 'LI' && !ctrlKey) {
24165        const liBlock = containerBlock;
24166        parentBlock = liBlock;
24167        containerBlock = liBlock.parentNode;
24168        parentBlockName = containerBlockName;
24169      }
24170      if (/^(LI|DT|DD)$/.test(parentBlockName) && isElement$6(containerBlock)) {
24171        if (dom.isEmpty(parentBlock)) {
24172          insert$3(editor, createNewBlock, containerBlock, parentBlock, newBlockName);
24173          return;
24174        }
24175      }
24176      if (parentBlock === editor.getBody() || !canSplitBlock(dom, parentBlock)) {
24177        return;
24178      }
24179      const parentBlockParent = parentBlock.parentNode;
24180      let newBlock;
24181      if (isCaretContainerBlock$1(parentBlock)) {
24182        newBlock = showCaretContainerBlock(parentBlock);
24183        if (dom.isEmpty(parentBlock)) {
24184          emptyBlock(parentBlock);
24185        }
24186        setForcedBlockAttrs(editor, newBlock);
24187        moveToCaretPosition(editor, newBlock);
24188      } else if (isCaretAtStartOrEndOfBlock(false)) {
24189        newBlock = insertNewBlockAfter();
24190      } else if (isCaretAtStartOrEndOfBlock(true) && parentBlockParent) {
24191        newBlock = parentBlockParent.insertBefore(createNewBlock(), parentBlock);
24192        moveToCaretPosition(editor, containerAndSiblingName(parentBlock, 'HR') ? newBlock : parentBlock);
24193      } else {
24194        const tmpRng = includeZwspInRange(rng).cloneRange();
24195        tmpRng.setEndAfter(parentBlock);
24196        const fragment = tmpRng.extractContents();
24197        trimZwsp(fragment);
24198        trimLeadingLineBreaks(fragment);
24199        newBlock = fragment.firstChild;
24200        dom.insertAfter(fragment, parentBlock);
24201        trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock);
24202        addBrToBlockIfNeeded(dom, parentBlock);
24203        if (dom.isEmpty(parentBlock)) {
24204          emptyBlock(parentBlock);
24205        }
24206        newBlock.normalize();
24207        if (dom.isEmpty(newBlock)) {
24208          dom.remove(newBlock);
24209          insertNewBlockAfter();
24210        } else {
24211          setForcedBlockAttrs(editor, newBlock);
24212          moveToCaretPosition(editor, newBlock);
24213        }
24214      }
24215      dom.setAttrib(newBlock, 'id', '');
24216      editor.dispatch('NewBlock', { newBlock });
24217    };
24218    const fakeEventName$1 = 'insertParagraph';
24219    const blockbreak = {
24220      insert: insert$2,
24221      fakeEventName: fakeEventName$1
24222    };
24223
24224    const hasRightSideContent = (schema, container, parentBlock) => {
24225      const walker = new DomTreeWalker(container, parentBlock);
24226      let node;
24227      const nonEmptyElementsMap = schema.getNonEmptyElements();
24228      while (node = walker.next()) {
24229        if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || isText$a(node) && node.length > 0) {
24230          return true;
24231        }
24232      }
24233      return false;
vendor: 9,051 bytes, lines 24234-24487
24234    };
24235    const moveSelectionToBr = (editor, brElm, extraBr) => {
24236      const rng = editor.dom.createRng();
24237      if (!extraBr) {
24238        rng.setStartAfter(brElm);
24239        rng.setEndAfter(brElm);
24240      } else {
24241        rng.setStartBefore(brElm);
24242        rng.setEndBefore(brElm);
24243      }
24244      editor.selection.setRng(rng);
24245      scrollRangeIntoView(editor, rng);
24246    };
24247    const insertBrAtCaret = (editor, evt) => {
24248      const selection = editor.selection;
24249      const dom = editor.dom;
24250      const rng = selection.getRng();
24251      let brElm;
24252      let extraBr = false;
24253      normalize$2(dom, rng).each(normRng => {
24254        rng.setStart(normRng.startContainer, normRng.startOffset);
24255        rng.setEnd(normRng.endContainer, normRng.endOffset);
24256      });
24257      let offset = rng.startOffset;
24258      let container = rng.startContainer;
24259      if (isElement$6(container) && container.hasChildNodes()) {
24260        const isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
24261        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
24262        if (isAfterLastNodeInContainer && isText$a(container)) {
24263          offset = container.data.length;
24264        } else {
24265          offset = 0;
24266        }
24267      }
24268      let parentBlock = dom.getParent(container, dom.isBlock);
24269      const containerBlock = parentBlock && parentBlock.parentNode ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
24270      const containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
24271      const isControlKey = !!(evt && evt.ctrlKey);
24272      if (containerBlockName === 'LI' && !isControlKey) {
24273        parentBlock = containerBlock;
24274      }
24275      if (isText$a(container) && offset >= container.data.length) {
24276        if (!hasRightSideContent(editor.schema, container, parentBlock || dom.getRoot())) {
24277          brElm = dom.create('br');
24278          rng.insertNode(brElm);
24279          rng.setStartAfter(brElm);
24280          rng.setEndAfter(brElm);
24281          extraBr = true;
24282        }
24283      }
24284      brElm = dom.create('br');
24285      rangeInsertNode(dom, rng, brElm);
24286      moveSelectionToBr(editor, brElm, extraBr);
24287      editor.undoManager.add();
24288    };
24289    const insertBrBefore = (editor, inline) => {
24290      const br = SugarElement.fromTag('br');
24291      before$3(SugarElement.fromDom(inline), br);
24292      editor.undoManager.add();
24293    };
24294    const insertBrAfter = (editor, inline) => {
24295      if (!hasBrAfter(editor.getBody(), inline)) {
24296        after$4(SugarElement.fromDom(inline), SugarElement.fromTag('br'));
24297      }
24298      const br = SugarElement.fromTag('br');
24299      after$4(SugarElement.fromDom(inline), br);
24300      moveSelectionToBr(editor, br.dom, false);
24301      editor.undoManager.add();
24302    };
24303    const isBeforeBr = pos => {
24304      return isBr$6(pos.getNode());
24305    };
24306    const hasBrAfter = (rootNode, startNode) => {
24307      if (isBeforeBr(CaretPosition.after(startNode))) {
24308        return true;
24309      } else {
24310        return nextPosition(rootNode, CaretPosition.after(startNode)).map(pos => {
24311          return isBr$6(pos.getNode());
24312        }).getOr(false);
24313      }
24314    };
24315    const isAnchorLink = elm => {
24316      return elm && elm.nodeName === 'A' && 'href' in elm;
24317    };
24318    const isInsideAnchor = location => {
24319      return location.fold(never, isAnchorLink, isAnchorLink, never);
24320    };
24321    const readInlineAnchorLocation = editor => {
24322      const isInlineTarget$1 = curry(isInlineTarget, editor);
24323      const position = CaretPosition.fromRangeStart(editor.selection.getRng());
24324      return readLocation(isInlineTarget$1, editor.getBody(), position).filter(isInsideAnchor);
24325    };
24326    const insertBrOutsideAnchor = (editor, location) => {
24327      location.fold(noop, curry(insertBrBefore, editor), curry(insertBrAfter, editor), noop);
24328    };
24329    const insert$1 = (editor, evt) => {
24330      const anchorLocation = readInlineAnchorLocation(editor);
24331      if (anchorLocation.isSome()) {
24332        anchorLocation.each(curry(insertBrOutsideAnchor, editor));
24333      } else {
24334        insertBrAtCaret(editor, evt);
24335      }
24336    };
24337    const fakeEventName = 'insertLineBreak';
24338    const linebreak = {
24339      insert: insert$1,
24340      fakeEventName
24341    };
24342
24343    const matchesSelector = (editor, selector) => {
24344      return getParentBlock$1(editor).filter(parentBlock => {
24345        return selector.length > 0 && is$1(SugarElement.fromDom(parentBlock), selector);
24346      }).isSome();
24347    };
24348    const shouldInsertBr = editor => {
24349      return matchesSelector(editor, getBrNewLineSelector(editor));
24350    };
24351    const shouldBlockNewLine$1 = editor => {
24352      return matchesSelector(editor, getNoNewLineSelector(editor));
24353    };
24354
24355    const newLineAction = Adt.generate([
24356      { br: [] },
24357      { block: [] },
24358      { none: [] }
24359    ]);
24360    const shouldBlockNewLine = (editor, _shiftKey) => {
24361      return shouldBlockNewLine$1(editor);
24362    };
24363    const inListBlock = requiredState => {
24364      return (editor, _shiftKey) => {
24365        return isListItemParentBlock(editor) === requiredState;
24366      };
24367    };
24368    const inBlock = (blockName, requiredState) => (editor, _shiftKey) => {
24369      const state = getParentBlockName(editor) === blockName.toUpperCase();
24370      return state === requiredState;
24371    };
24372    const inCefBlock = editor => {
24373      const editableRoot = getEditableRoot(editor.dom, editor.selection.getStart());
24374      return isNullable(editableRoot);
24375    };
24376    const inPreBlock = requiredState => inBlock('pre', requiredState);
24377    const inSummaryBlock = () => inBlock('summary', true);
24378    const shouldPutBrInPre = requiredState => {
24379      return (editor, _shiftKey) => {
24380        return shouldPutBrInPre$1(editor) === requiredState;
24381      };
24382    };
24383    const inBrContext = (editor, _shiftKey) => {
24384      return shouldInsertBr(editor);
24385    };
24386    const hasShiftKey = (_editor, shiftKey) => {
24387      return shiftKey;
24388    };
24389    const canInsertIntoEditableRoot = editor => {
24390      const forcedRootBlock = getForcedRootBlock(editor);
24391      const rootEditable = getEditableRoot(editor.dom, editor.selection.getStart());
24392      return isNonNullable(rootEditable) && editor.schema.isValidChild(rootEditable.nodeName, forcedRootBlock);
24393    };
24394    const match = (predicates, action) => {
24395      return (editor, shiftKey) => {
24396        const isMatch = foldl(predicates, (res, p) => {
24397          return res && p(editor, shiftKey);
24398        }, true);
24399        return isMatch ? Optional.some(action) : Optional.none();
24400      };
24401    };
24402    const getAction = (editor, evt) => {
24403      return evaluateUntil([
24404        match([shouldBlockNewLine], newLineAction.none()),
24405        match([
24406          inPreBlock(true),
24407          inCefBlock
24408        ], newLineAction.none()),
24409        match([inSummaryBlock()], newLineAction.br()),
24410        match([
24411          inPreBlock(true),
24412          shouldPutBrInPre(false),
24413          hasShiftKey
24414        ], newLineAction.br()),
24415        match([
24416          inPreBlock(true),
24417          shouldPutBrInPre(false)
24418        ], newLineAction.block()),
24419        match([
24420          inPreBlock(true),
24421          shouldPutBrInPre(true),
24422          hasShiftKey
24423        ], newLineAction.block()),
24424        match([
24425          inPreBlock(true),
24426          shouldPutBrInPre(true)
24427        ], newLineAction.br()),
24428        match([
24429          inListBlock(true),
24430          hasShiftKey
24431        ], newLineAction.br()),
24432        match([inListBlock(true)], newLineAction.block()),
24433        match([inBrContext], newLineAction.br()),
24434        match([hasShiftKey], newLineAction.br()),
24435        match([canInsertIntoEditableRoot], newLineAction.block())
24436      ], [
24437        editor,
24438        !!(evt && evt.shiftKey)
24439      ]).getOr(newLineAction.none());
24440    };
24441
24442    const insertBreak = (breakType, editor, evt) => {
24443      if (!editor.selection.isCollapsed()) {
24444        execEditorDeleteCommand(editor);
24445      }
24446      if (isNonNullable(evt)) {
24447        const event = fireFakeBeforeInputEvent(editor, breakType.fakeEventName);
24448        if (event.isDefaultPrevented()) {
24449          return;
24450        }
24451      }
24452      breakType.insert(editor, evt);
24453      if (isNonNullable(evt)) {
24454        fireFakeInputEvent(editor, breakType.fakeEventName);
24455      }
24456    };
24457    const insert = (editor, evt) => {
24458      const br = () => insertBreak(linebreak, editor, evt);
24459      const block = () => insertBreak(blockbreak, editor, evt);
24460      const logicalAction = getAction(editor, evt);
24461      switch (getNewlineBehavior(editor)) {
24462      case 'linebreak':
24463        logicalAction.fold(br, br, noop);
24464        break;
24465      case 'block':
24466        logicalAction.fold(block, block, noop);
24467        break;
24468      case 'invert':
24469        logicalAction.fold(block, br, noop);
24470        break;
24471      default:
24472        logicalAction.fold(br, block, noop);
24473        break;
24474      }
24475    };
24476
24477    const handleEnterKeyEvent = (editor, event) => {
24478      if (event.isDefaultPrevented()) {
24479        return;
24480      }
24481      event.preventDefault();
24482      endTypingLevelIgnoreLocks(editor.undoManager);
24483      editor.undoManager.transact(() => {
24484        insert(editor, event);
24485      });
24486    };
24487    const setup$h = editor => {
vendor: 5,630 bytes, lines 24488-24649
24488      editor.on('keydown', event => {
24489        if (event.keyCode === VK.ENTER) {
24490          handleEnterKeyEvent(editor, event);
24491        }
24492      });
24493    };
24494
24495    const executeKeydownOverride$2 = (editor, caret, evt) => {
24496      const isMac = Env.os.isMacOS() || Env.os.isiOS();
24497      execute([
24498        {
24499          keyCode: VK.END,
24500          action: action(moveToLineEndPoint$1, editor, true)
24501        },
24502        {
24503          keyCode: VK.HOME,
24504          action: action(moveToLineEndPoint$1, editor, false)
24505        },
24506        ...!isMac ? [
24507          {
24508            keyCode: VK.HOME,
24509            action: action(selectToEndPoint, editor, false),
24510            ctrlKey: true,
24511            shiftKey: true
24512          },
24513          {
24514            keyCode: VK.END,
24515            action: action(selectToEndPoint, editor, true),
24516            ctrlKey: true,
24517            shiftKey: true
24518          }
24519        ] : [],
24520        {
24521          keyCode: VK.END,
24522          action: action(moveToLineEndPoint, editor, true)
24523        },
24524        {
24525          keyCode: VK.HOME,
24526          action: action(moveToLineEndPoint, editor, false)
24527        },
24528        {
24529          keyCode: VK.END,
24530          action: action(moveToLineEndPoint$2, editor, true, caret)
24531        },
24532        {
24533          keyCode: VK.HOME,
24534          action: action(moveToLineEndPoint$2, editor, false, caret)
24535        }
24536      ], evt).each(_ => {
24537        evt.preventDefault();
24538      });
24539    };
24540    const setup$g = (editor, caret) => {
24541      editor.on('keydown', evt => {
24542        if (!evt.isDefaultPrevented()) {
24543          executeKeydownOverride$2(editor, caret, evt);
24544        }
24545      });
24546    };
24547
24548    const setup$f = editor => {
24549      editor.on('input', e => {
24550        if (!e.isComposing) {
24551          normalizeNbspsInEditor(editor);
24552        }
24553      });
24554    };
24555
24556    const platform = detect$2();
24557    const executeKeyupAction = (editor, caret, evt) => {
24558      execute([
24559        {
24560          keyCode: VK.PAGE_UP,
24561          action: action(moveToLineEndPoint$2, editor, false, caret)
24562        },
24563        {
24564          keyCode: VK.PAGE_DOWN,
24565          action: action(moveToLineEndPoint$2, editor, true, caret)
24566        }
24567      ], evt);
24568    };
24569    const stopImmediatePropagation = e => e.stopImmediatePropagation();
24570    const isPageUpDown = evt => evt.keyCode === VK.PAGE_UP || evt.keyCode === VK.PAGE_DOWN;
24571    const setNodeChangeBlocker = (blocked, editor, block) => {
24572      if (block && !blocked.get()) {
24573        editor.on('NodeChange', stopImmediatePropagation, true);
24574      } else if (!block && blocked.get()) {
24575        editor.off('NodeChange', stopImmediatePropagation);
24576      }
24577      blocked.set(block);
24578    };
24579    const setup$e = (editor, caret) => {
24580      if (platform.os.isMacOS()) {
24581        return;
24582      }
24583      const blocked = Cell(false);
24584      editor.on('keydown', evt => {
24585        if (isPageUpDown(evt)) {
24586          setNodeChangeBlocker(blocked, editor, true);
24587        }
24588      });
24589      editor.on('keyup', evt => {
24590        if (!evt.isDefaultPrevented()) {
24591          executeKeyupAction(editor, caret, evt);
24592        }
24593        if (isPageUpDown(evt) && blocked.get()) {
24594          setNodeChangeBlocker(blocked, editor, false);
24595          editor.nodeChanged();
24596        }
24597      });
24598    };
24599
24600    const insertTextAtPosition = (text, pos) => {
24601      const container = pos.container();
24602      const offset = pos.offset();
24603      if (isText$a(container)) {
24604        container.insertData(offset, text);
24605        return Optional.some(CaretPosition(container, offset + text.length));
24606      } else {
24607        return getElementFromPosition(pos).map(elm => {
24608          const textNode = SugarElement.fromText(text);
24609          if (pos.isAtEnd()) {
24610            after$4(elm, textNode);
24611          } else {
24612            before$3(elm, textNode);
24613          }
24614          return CaretPosition(textNode.dom, text.length);
24615        });
24616      }
24617    };
24618    const insertNbspAtPosition = curry(insertTextAtPosition, nbsp);
24619    const insertSpaceAtPosition = curry(insertTextAtPosition, ' ');
24620
24621    const locationToCaretPosition = root => location => location.fold(element => prevPosition(root.dom, CaretPosition.before(element)), element => firstPositionIn(element), element => lastPositionIn(element), element => nextPosition(root.dom, CaretPosition.after(element)));
24622    const insertInlineBoundarySpaceOrNbsp = (root, pos) => checkPos => needsToHaveNbsp(root, checkPos) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
24623    const setSelection = editor => pos => {
24624      editor.selection.setRng(pos.toRange());
24625      editor.nodeChanged();
24626      return true;
24627    };
24628    const insertSpaceOrNbspAtSelection = editor => {
24629      const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
24630      const root = SugarElement.fromDom(editor.getBody());
24631      if (editor.selection.isCollapsed()) {
24632        const isInlineTarget$1 = curry(isInlineTarget, editor);
24633        const caretPosition = CaretPosition.fromRangeStart(editor.selection.getRng());
24634        return readLocation(isInlineTarget$1, editor.getBody(), caretPosition).bind(locationToCaretPosition(root)).map(checkPos => () => insertInlineBoundarySpaceOrNbsp(root, pos)(checkPos).each(setSelection(editor)));
24635      } else {
24636        return Optional.none();
24637      }
24638    };
24639
24640    const executeKeydownOverride$1 = (editor, evt) => {
24641      executeWithDelayedAction([{
24642          keyCode: VK.SPACEBAR,
24643          action: action(insertSpaceOrNbspAtSelection, editor)
24644        }], evt).each(applyAction => {
24645        evt.preventDefault();
24646        const event = fireFakeBeforeInputEvent(editor, 'insertText', { data: ' ' });
24647        if (!event.isDefaultPrevented()) {
24648          applyAction();
24649          fireFak
vendor: 4,619 bytes, lines 24649-24801
24649eInputEvent(editor, 'insertText', { data: ' ' });
24650        }
24651      });
24652    };
24653    const setup$d = editor => {
24654      editor.on('keydown', evt => {
24655        if (!evt.isDefaultPrevented()) {
24656          executeKeydownOverride$1(editor, evt);
24657        }
24658      });
24659    };
24660
24661    const tableTabNavigation = editor => {
24662      if (hasTableTabNavigation(editor)) {
24663        return [
24664          {
24665            keyCode: VK.TAB,
24666            action: action(handleTab, editor, true)
24667          },
24668          {
24669            keyCode: VK.TAB,
24670            shiftKey: true,
24671            action: action(handleTab, editor, false)
24672          }
24673        ];
24674      } else {
24675        return [];
24676      }
24677    };
24678    const executeKeydownOverride = (editor, evt) => {
24679      execute([...tableTabNavigation(editor)], evt).each(_ => {
24680        evt.preventDefault();
24681      });
24682    };
24683    const setup$c = editor => {
24684      editor.on('keydown', evt => {
24685        if (!evt.isDefaultPrevented()) {
24686          executeKeydownOverride(editor, evt);
24687        }
24688      });
24689    };
24690
24691    const setup$b = editor => {
24692      editor.addShortcut('Meta+P', '', 'mcePrint');
24693      setup$j(editor);
24694      if (isRtc(editor)) {
24695        return Cell(null);
24696      } else {
24697        const caret = setupSelectedState(editor);
24698        setup$l(editor);
24699        setup$k(editor, caret);
24700        setup$i(editor, caret);
24701        setup$h(editor);
24702        setup$d(editor);
24703        setup$f(editor);
24704        setup$c(editor);
24705        setup$g(editor, caret);
24706        setup$e(editor, caret);
24707        return caret;
24708      }
24709    };
24710
24711    class NodeChange {
24712      constructor(editor) {
24713        this.lastPath = [];
24714        this.editor = editor;
24715        let lastRng;
24716        const self = this;
24717        if (!('onselectionchange' in editor.getDoc())) {
24718          editor.on('NodeChange click mouseup keyup focus', e => {
24719            const nativeRng = editor.selection.getRng();
24720            const fakeRng = {
24721              startContainer: nativeRng.startContainer,
24722              startOffset: nativeRng.startOffset,
24723              endContainer: nativeRng.endContainer,
24724              endOffset: nativeRng.endOffset
24725            };
24726            if (e.type === 'nodechange' || !isEq$4(fakeRng, lastRng)) {
24727              editor.dispatch('SelectionChange');
24728            }
24729            lastRng = fakeRng;
24730          });
24731        }
24732        editor.on('contextmenu', () => {
24733          editor.dispatch('SelectionChange');
24734        });
24735        editor.on('SelectionChange', () => {
24736          const startElm = editor.selection.getStart(true);
24737          if (!startElm) {
24738            return;
24739          }
24740          if (hasAnyRanges(editor) && !self.isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
24741            editor.nodeChanged({ selectionChange: true });
24742          }
24743        });
24744        editor.on('mouseup', e => {
24745          if (!e.isDefaultPrevented() && hasAnyRanges(editor)) {
24746            if (editor.selection.getNode().nodeName === 'IMG') {
24747              Delay.setEditorTimeout(editor, () => {
24748                editor.nodeChanged();
24749              });
24750            } else {
24751              editor.nodeChanged();
24752            }
24753          }
24754        });
24755      }
24756      nodeChanged(args = {}) {
24757        const selection = this.editor.selection;
24758        let node;
24759        if (this.editor.initialized && selection && !shouldDisableNodeChange(this.editor) && !this.editor.mode.isReadOnly()) {
24760          const root = this.editor.getBody();
24761          node = selection.getStart(true) || root;
24762          if (node.ownerDocument !== this.editor.getDoc() || !this.editor.dom.isChildOf(node, root)) {
24763            node = root;
24764          }
24765          const parents = [];
24766          this.editor.dom.getParent(node, node => {
24767            if (node === root) {
24768              return true;
24769            } else {
24770              parents.push(node);
24771              return false;
24772            }
24773          });
24774          this.editor.dispatch('NodeChange', {
24775            ...args,
24776            element: node,
24777            parents
24778          });
24779        }
24780      }
24781      isSameElementPath(startElm) {
24782        let i;
24783        const editor = this.editor;
24784        const currentPath = reverse(editor.dom.getParents(startElm, always, editor.getBody()));
24785        if (currentPath.length === this.lastPath.length) {
24786          for (i = currentPath.length; i >= 0; i--) {
24787            if (currentPath[i] !== this.lastPath[i]) {
24788              break;
24789            }
24790          }
24791          if (i === -1) {
24792            this.lastPath = currentPath;
24793            return true;
24794          }
24795        }
24796        this.lastPath = currentPath;
24797        return false;
24798      }
24799    }
24800
24801    const i
vendor: 45,989 bytes, lines 24801-25959
24801nternalMimeType = 'x-tinymce/html';
24802    const internalHtmlMime = constant(internalMimeType);
24803    const internalMark = '<!-- ' + internalMimeType + ' -->';
24804    const mark = html => internalMark + html;
24805    const unmark = html => html.replace(internalMark, '');
24806    const isMarked = html => html.indexOf(internalMark) !== -1;
24807
24808    const isPlainText = text => {
24809      return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text);
24810    };
24811    const openContainer = (rootTag, rootAttrs) => {
24812      let tag = '<' + rootTag;
24813      const attrs = mapToArray(rootAttrs, (value, key) => key + '="' + Entities.encodeAllRaw(value) + '"');
24814      if (attrs.length) {
24815        tag += ' ' + attrs.join(' ');
24816      }
24817      return tag + '>';
24818    };
24819    const toBlockElements = (text, rootTag, rootAttrs) => {
24820      const blocks = text.split(/\n\n/);
24821      const tagOpen = openContainer(rootTag, rootAttrs);
24822      const tagClose = '</' + rootTag + '>';
24823      const paragraphs = map$3(blocks, p => {
24824        return p.split(/\n/).join('<br />');
24825      });
24826      const stitch = p => {
24827        return tagOpen + p + tagClose;
24828      };
24829      return paragraphs.length === 1 ? paragraphs[0] : map$3(paragraphs, stitch).join('');
24830    };
24831
24832    const pasteBinDefaultContent = '%MCEPASTEBIN%';
24833    const create$6 = (editor, lastRngCell) => {
24834      const {dom, selection} = editor;
24835      const body = editor.getBody();
24836      lastRngCell.set(selection.getRng());
24837      const pasteBinElm = dom.add(editor.getBody(), 'div', {
24838        'id': 'mcepastebin',
24839        'class': 'mce-pastebin',
24840        'contentEditable': true,
24841        'data-mce-bogus': 'all',
24842        'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0'
24843      }, pasteBinDefaultContent);
24844      if (Env.browser.isFirefox()) {
24845        dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535);
24846      }
24847      dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', e => {
24848        e.stopPropagation();
24849      });
24850      pasteBinElm.focus();
24851      selection.select(pasteBinElm, true);
24852    };
24853    const remove = (editor, lastRngCell) => {
24854      const dom = editor.dom;
24855      if (getEl(editor)) {
24856        let pasteBinClone;
24857        const lastRng = lastRngCell.get();
24858        while (pasteBinClone = getEl(editor)) {
24859          dom.remove(pasteBinClone);
24860          dom.unbind(pasteBinClone);
24861        }
24862        if (lastRng) {
24863          editor.selection.setRng(lastRng);
24864        }
24865      }
24866      lastRngCell.set(null);
24867    };
24868    const getEl = editor => editor.dom.get('mcepastebin');
24869    const isPasteBin = elm => isNonNullable(elm) && elm.id === 'mcepastebin';
24870    const getHtml = editor => {
24871      const dom = editor.dom;
24872      const copyAndRemove = (toElm, fromElm) => {
24873        toElm.appendChild(fromElm);
24874        dom.remove(fromElm, true);
24875      };
24876      const [pasteBinElm, ...pasteBinClones] = filter$5(editor.getBody().childNodes, isPasteBin);
24877      each$e(pasteBinClones, pasteBinClone => {
24878        copyAndRemove(pasteBinElm, pasteBinClone);
24879      });
24880      const dirtyWrappers = dom.select('div[id=mcepastebin]', pasteBinElm);
24881      for (let i = dirtyWrappers.length - 1; i >= 0; i--) {
24882        const cleanWrapper = dom.create('div');
24883        pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]);
24884        copyAndRemove(cleanWrapper, dirtyWrappers[i]);
24885      }
24886      return pasteBinElm ? pasteBinElm.innerHTML : '';
24887    };
24888    const isDefaultPasteBinContent = content => content === pasteBinDefaultContent;
24889    const PasteBin = editor => {
24890      const lastRng = Cell(null);
24891      return {
24892        create: () => create$6(editor, lastRng),
24893        remove: () => remove(editor, lastRng),
24894        getEl: () => getEl(editor),
24895        getHtml: () => getHtml(editor),
24896        getLastRng: lastRng.get
24897      };
24898    };
24899
24900    const filter$1 = (content, items) => {
24901      Tools.each(items, v => {
24902        if (is$4(v, RegExp)) {
24903          content = content.replace(v, '');
24904        } else {
24905          content = content.replace(v[0], v[1]);
24906        }
24907      });
24908      return content;
24909    };
24910    const innerText = html => {
24911      const schema = Schema();
24912      const domParser = DomParser({}, schema);
24913      let text = '';
24914      const voidElements = schema.getVoidElements();
24915      const ignoreElements = Tools.makeMap('script noscript style textarea video audio iframe object', ' ');
24916      const blockElements = schema.getBlockElements();
24917      const walk = node => {
24918        const name = node.name, currentNode = node;
24919        if (name === 'br') {
24920          text += '\n';
24921          return;
24922        }
24923        if (name === 'wbr') {
24924          return;
24925        }
24926        if (voidElements[name]) {
24927          text += ' ';
24928        }
24929        if (ignoreElements[name]) {
24930          text += ' ';
24931          return;
24932        }
24933        if (node.type === 3) {
24934          text += node.value;
24935        }
24936        if (!(node.name in schema.getVoidElements())) {
24937          let currentNode = node.firstChild;
24938          if (currentNode) {
24939            do {
24940              walk(currentNode);
24941            } while (currentNode = currentNode.next);
24942          }
24943        }
24944        if (blockElements[name] && currentNode.next) {
24945          text += '\n';
24946          if (name === 'p') {
24947            text += '\n';
24948          }
24949        }
24950      };
24951      html = filter$1(html, [/<!\[[^\]]+\]>/g]);
24952      walk(domParser.parse(html));
24953      return text;
24954    };
24955    const trimHtml = html => {
24956      const trimSpaces = (all, s1, s2) => {
24957        if (!s1 && !s2) {
24958          return ' ';
24959        }
24960        return nbsp;
24961      };
24962      html = filter$1(html, [
24963        /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig,
24964        /<!--StartFragment-->|<!--EndFragment-->/g,
24965        [
24966          /( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g,
24967          trimSpaces
24968        ],
24969        /<br class="Apple-interchange-newline">/g,
24970        /<br>$/i
24971      ]);
24972      return html;
24973    };
24974    const createIdGenerator = prefix => {
24975      let count = 0;
24976      return () => {
24977        return prefix + count++;
24978      };
24979    };
24980    const getImageMimeType = ext => {
24981      const lowerExt = ext.toLowerCase();
24982      const mimeOverrides = {
24983        jpg: 'jpeg',
24984        jpe: 'jpeg',
24985        jfi: 'jpeg',
24986        jif: 'jpeg',
24987        jfif: 'jpeg',
24988        pjpeg: 'jpeg',
24989        pjp: 'jpeg',
24990        svg: 'svg+xml'
24991      };
24992      return Tools.hasOwn(mimeOverrides, lowerExt) ? 'image/' + mimeOverrides[lowerExt] : 'image/' + lowerExt;
24993    };
24994
24995    const preProcess = (editor, html) => {
24996      const parser = DomParser({ sanitize: shouldSanitizeXss(editor) }, editor.schema);
24997      parser.addNodeFilter('meta', nodes => {
24998        Tools.each(nodes, node => {
24999          node.remove();
25000        });
25001      });
25002      const fragment = parser.parse(html, {
25003        forced_root_block: false,
25004        isRootContent: true
25005      });
25006      return HtmlSerializer({ validate: true }, editor.schema).serialize(fragment);
25007    };
25008    const processResult = (content, cancelled) => ({
25009      content,
25010      cancelled
25011    });
25012    const postProcessFilter = (editor, html, internal) => {
25013      const tempBody = editor.dom.create('div', { style: 'display:none' }, html);
25014      const postProcessArgs = firePastePostProcess(editor, tempBody, internal);
25015      return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented());
25016    };
25017    const filterContent = (editor, content, internal) => {
25018      const preProcessArgs = firePastePreProcess(editor, content, internal);
25019      const filteredContent = preProcess(editor, preProcessArgs.content);
25020      if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) {
25021        return postProcessFilter(editor, filteredContent, internal);
25022      } else {
25023        return processResult(filteredContent, preProcessArgs.isDefaultPrevented());
25024      }
25025    };
25026    const process = (editor, html, internal) => {
25027      return filterContent(editor, html, internal);
25028    };
25029
25030    const pasteHtml$1 = (editor, html) => {
25031      editor.insertContent(html, {
25032        merge: shouldPasteMergeFormats(editor),
25033        paste: true
25034      });
25035      return true;
25036    };
25037    const isAbsoluteUrl = url => /^https?:\/\/[\w\-\/+=.,!;:&%@^~(){}?#]+$/i.test(url);
25038    const isImageUrl = (editor, url) => {
25039      return isAbsoluteUrl(url) && exists(getAllowedImageFileTypes(editor), type => endsWith(url.toLowerCase(), `.${ type.toLowerCase() }`));
25040    };
25041    const createImage = (editor, url, pasteHtmlFn) => {
25042      editor.undoManager.extra(() => {
25043        pasteHtmlFn(editor, url);
25044      }, () => {
25045        editor.insertContent('<img src="' + url + '">');
25046      });
25047      return true;
25048    };
25049    const createLink = (editor, url, pasteHtmlFn) => {
25050      editor.undoManager.extra(() => {
25051        pasteHtmlFn(editor, url);
25052      }, () => {
25053        editor.execCommand('mceInsertLink', false, url);
25054      });
25055      return true;
25056    };
25057    const linkSelection = (editor, html, pasteHtmlFn) => !editor.selection.isCollapsed() && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false;
25058    const insertImage = (editor, html, pasteHtmlFn) => isImageUrl(editor, html) ? createImage(editor, html, pasteHtmlFn) : false;
25059    const smartInsertContent = (editor, html) => {
25060      Tools.each([
25061        linkSelection,
25062        insertImage,
25063        pasteHtml$1
25064      ], action => {
25065        return !action(editor, html, pasteHtml$1);
25066      });
25067    };
25068    const insertContent = (editor, html, pasteAsText) => {
25069      if (pasteAsText || !isSmartPasteEnabled(editor)) {
25070        pasteHtml$1(editor, html);
25071      } else {
25072        smartInsertContent(editor, html);
25073      }
25074    };
25075
25076    const uniqueId = createIdGenerator('mceclip');
25077    const doPaste = (editor, content, internal, pasteAsText) => {
25078      const args = process(editor, content, internal);
25079      if (!args.cancelled) {
25080        insertContent(editor, args.content, pasteAsText);
25081      }
25082    };
25083    const pasteHtml = (editor, html, internalFlag) => {
25084      const internal = internalFlag ? internalFlag : isMarked(html);
25085      doPaste(editor, unmark(html), internal, false);
25086    };
25087    const pasteText = (editor, text) => {
25088      const encodedText = editor.dom.encode(text).replace(/\r\n/g, '\n');
25089      const normalizedText = normalize$4(encodedText, getPasteTabSpaces(editor));
25090      const html = toBlockElements(normalizedText, getForcedRootBlock(editor), getForcedRootBlockAttrs(editor));
25091      doPaste(editor, html, false, true);
25092    };
25093    const getDataTransferItems = dataTransfer => {
25094      const items = {};
25095      if (dataTransfer && dataTransfer.types) {
25096        for (let i = 0; i < dataTransfer.types.length; i++) {
25097          const contentType = dataTransfer.types[i];
25098          try {
25099            items[contentType] = dataTransfer.getData(contentType);
25100          } catch (ex) {
25101            items[contentType] = '';
25102          }
25103        }
25104      }
25105      return items;
25106    };
25107    const hasContentType = (clipboardContent, mimeType) => mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
25108    const hasHtmlOrText = content => hasContentType(content, 'text/html') || hasContentType(content, 'text/plain');
25109    const extractFilename = (editor, str) => {
25110      const m = str.match(/([\s\S]+?)(?:\.[a-z0-9.]+)$/i);
25111      return isNonNullable(m) ? editor.dom.encode(m[1]) : undefined;
25112    };
25113    const createBlobInfo = (editor, blobCache, file, base64) => {
25114      const id = uniqueId();
25115      const useFileName = shouldReuseFileName(editor) && isNonNullable(file.name);
25116      const name = useFileName ? extractFilename(editor, file.name) : id;
25117      const filename = useFileName ? file.name : undefined;
25118      const blobInfo = blobCache.create(id, file, base64, name, filename);
25119      blobCache.add(blobInfo);
25120      return blobInfo;
25121    };
25122    const pasteImage = (editor, imageItem) => {
25123      parseDataUri(imageItem.uri).each(({data, type, base64Encoded}) => {
25124        const base64 = base64Encoded ? data : btoa(data);
25125        const file = imageItem.file;
25126        const blobCache = editor.editorUpload.blobCache;
25127        const existingBlobInfo = blobCache.getByData(base64, type);
25128        const blobInfo = existingBlobInfo !== null && existingBlobInfo !== void 0 ? existingBlobInfo : createBlobInfo(editor, blobCache, file, base64);
25129        pasteHtml(editor, `<img src="${ blobInfo.blobUri() }">`, false);
25130      });
25131    };
25132    const isClipboardEvent = event => event.type === 'paste';
25133    const readFilesAsDataUris = items => Promise.all(map$3(items, file => {
25134      return blobToDataUri(file).then(uri => ({
25135        file,
25136        uri
25137      }));
25138    }));
25139    const isImage = editor => {
25140      const allowedExtensions = getAllowedImageFileTypes(editor);
25141      return file => startsWith(file.type, 'image/') && exists(allowedExtensions, extension => {
25142        return getImageMimeType(extension) === file.type;
25143      });
25144    };
25145    const getImagesFromDataTransfer = (editor, dataTransfer) => {
25146      const items = dataTransfer.items ? bind$3(from(dataTransfer.items), item => {
25147        return item.kind === 'file' ? [item.getAsFile()] : [];
25148      }) : [];
25149      const files = dataTransfer.files ? from(dataTransfer.files) : [];
25150      return filter$5(items.length > 0 ? items : files, isImage(editor));
25151    };
25152    const pasteImageData = (editor, e, rng) => {
25153      const dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer;
25154      if (shouldPasteDataImages(editor) && dataTransfer) {
25155        const images = getImagesFromDataTransfer(editor, dataTransfer);
25156        if (images.length > 0) {
25157          e.preventDefault();
25158          readFilesAsDataUris(images).then(fileResults => {
25159            if (rng) {
25160              editor.selection.setRng(rng);
25161            }
25162            each$e(fileResults, result => {
25163              pasteImage(editor, result);
25164            });
25165          });
25166          return true;
25167        }
25168      }
25169      return false;
25170    };
25171    const isBrokenAndroidClipboardEvent = e => {
25172      var _a, _b;
25173      return Env.os.isAndroid() && ((_b = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.items) === null || _b === void 0 ? void 0 : _b.length) === 0;
25174    };
25175    const isKeyboardPasteEvent = e => VK.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45;
25176    const insertClipboardContent = (editor, clipboardContent, html, plainTextMode) => {
25177      let content = trimHtml(html);
25178      const isInternal = hasContentType(clipboardContent, internalHtmlMime()) || isMarked(html);
25179      const isPlainTextHtml = !isInternal && isPlainText(content);
25180      const isAbsoluteUrl$1 = isAbsoluteUrl(content);
25181      if (isDefaultPasteBinContent(content) || !content.length || isPlainTextHtml && !isAbsoluteUrl$1) {
25182        plainTextMode = true;
25183      }
25184      if (plainTextMode || isAbsoluteUrl$1) {
25185        if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) {
25186          content = clipboardContent['text/plain'];
25187        } else {
25188          content = innerText(content);
25189        }
25190      }
25191      if (isDefaultPasteBinContent(content)) {
25192        return;
25193      }
25194      if (plainTextMode) {
25195        pasteText(editor, content);
25196      } else {
25197        pasteHtml(editor, content, isInternal);
25198      }
25199    };
25200    const registerEventHandlers = (editor, pasteBin, pasteFormat) => {
25201      let keyboardPastePlainTextState;
25202      const getLastRng = () => pasteBin.getLastRng() || editor.selection.getRng();
25203      editor.on('keydown', e => {
25204        if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
25205          keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86;
25206        }
25207      });
25208      editor.on('paste', e => {
25209        if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
25210          return;
25211        }
25212        const plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState;
25213        keyboardPastePlainTextState = false;
25214        const clipboardContent = getDataTransferItems(e.clipboardData);
25215        if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) {
25216          return;
25217        }
25218        if (hasContentType(clipboardContent, 'text/html')) {
25219          e.preventDefault();
25220          insertClipboardContent(editor, clipboardContent, clipboardContent['text/html'], plainTextMode);
25221        } else if (hasContentType(clipboardContent, 'text/plain') && hasContentType(clipboardContent, 'text/uri-list')) {
25222          e.preventDefault();
25223          insertClipboardContent(editor, clipboardContent, clipboardContent['text/plain'], plainTextMode);
25224        } else {
25225          pasteBin.create();
25226          Delay.setEditorTimeout(editor, () => {
25227            const html = pasteBin.getHtml();
25228            pasteBin.remove();
25229            insertClipboardContent(editor, clipboardContent, html, plainTextMode);
25230          }, 0);
25231        }
25232      });
25233    };
25234    const registerDataImageFilter = editor => {
25235      const isWebKitFakeUrl = src => startsWith(src, 'webkit-fake-url');
25236      const isDataUri = src => startsWith(src, 'data:');
25237      const isPasteInsert = args => {
25238        var _a;
25239        return ((_a = args.data) === null || _a === void 0 ? void 0 : _a.paste) === true;
25240      };
25241      editor.parser.addNodeFilter('img', (nodes, name, args) => {
25242        if (!shouldPasteDataImages(editor) && isPasteInsert(args)) {
25243          for (const node of nodes) {
25244            const src = node.attr('src');
25245            if (isString(src) && !node.attr('data-mce-object') && src !== Env.transparentSrc) {
25246              if (isWebKitFakeUrl(src)) {
25247                node.remove();
25248              } else if (!shouldAllowHtmlDataUrls(editor) && isDataUri(src)) {
25249                node.remove();
25250              }
25251            }
25252          }
25253        }
25254      });
25255    };
25256    const registerEventsAndFilters = (editor, pasteBin, pasteFormat) => {
25257      registerEventHandlers(editor, pasteBin, pasteFormat);
25258      registerDataImageFilter(editor);
25259    };
25260
25261    const togglePlainTextPaste = (editor, pasteFormat) => {
25262      if (pasteFormat.get() === 'text') {
25263        pasteFormat.set('html');
25264        firePastePlainTextToggle(editor, false);
25265      } else {
25266        pasteFormat.set('text');
25267        firePastePlainTextToggle(editor, true);
25268      }
25269      editor.focus();
25270    };
25271    const register$1 = (editor, pasteFormat) => {
25272      editor.addCommand('mceTogglePlainTextPaste', () => {
25273        togglePlainTextPaste(editor, pasteFormat);
25274      });
25275      editor.addCommand('mceInsertClipboardContent', (ui, value) => {
25276        if (value.html) {
25277          pasteHtml(editor, value.html, value.internal);
25278        }
25279        if (value.text) {
25280          pasteText(editor, value.text);
25281        }
25282      });
25283    };
25284
25285    const setHtml5Clipboard = (clipboardData, html, text) => {
25286      if (clipboardData) {
25287        try {
25288          clipboardData.clearData();
25289          clipboardData.setData('text/html', html);
25290          clipboardData.setData('text/plain', text);
25291          clipboardData.setData(internalHtmlMime(), html);
25292          return true;
25293        } catch (e) {
25294          return false;
25295        }
25296      } else {
25297        return false;
25298      }
25299    };
25300    const setClipboardData = (evt, data, fallback, done) => {
25301      if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) {
25302        evt.preventDefault();
25303        done();
25304      } else {
25305        fallback(data.html, done);
25306      }
25307    };
25308    const fallback$1 = editor => (html, done) => {
25309      const {dom, selection} = editor;
25310      const outer = dom.create('div', {
25311        'contenteditable': 'false',
25312        'data-mce-bogus': 'all'
25313      });
25314      const inner = dom.create('div', { contenteditable: 'true' }, html);
25315      dom.setStyles(outer, {
25316        position: 'fixed',
25317        top: '0',
25318        left: '-3000px',
25319        width: '1000px',
25320        overflow: 'hidden'
25321      });
25322      outer.appendChild(inner);
25323      dom.add(editor.getBody(), outer);
25324      const range = selection.getRng();
25325      inner.focus();
25326      const offscreenRange = dom.createRng();
25327      offscreenRange.selectNodeContents(inner);
25328      selection.setRng(offscreenRange);
25329      Delay.setEditorTimeout(editor, () => {
25330        selection.setRng(range);
25331        dom.remove(outer);
25332        done();
25333      }, 0);
25334    };
25335    const getData = editor => ({
25336      html: mark(editor.selection.getContent({ contextual: true })),
25337      text: editor.selection.getContent({ format: 'text' })
25338    });
25339    const isTableSelection = editor => !!editor.dom.getParent(editor.selection.getStart(), 'td[data-mce-selected],th[data-mce-selected]', editor.getBody());
25340    const hasSelectedContent = editor => !editor.selection.isCollapsed() || isTableSelection(editor);
25341    const cut = editor => evt => {
25342      if (!evt.isDefaultPrevented() && hasSelectedContent(editor)) {
25343        setClipboardData(evt, getData(editor), fallback$1(editor), () => {
25344          if (Env.browser.isChromium() || Env.browser.isFirefox()) {
25345            const rng = editor.selection.getRng();
25346            Delay.setEditorTimeout(editor, () => {
25347              editor.selection.setRng(rng);
25348              editor.execCommand('Delete');
25349            }, 0);
25350          } else {
25351            editor.execCommand('Delete');
25352          }
25353        });
25354      }
25355    };
25356    const copy = editor => evt => {
25357      if (!evt.isDefaultPrevented() && hasSelectedContent(editor)) {
25358        setClipboardData(evt, getData(editor), fallback$1(editor), noop);
25359      }
25360    };
25361    const register = editor => {
25362      editor.on('cut', cut(editor));
25363      editor.on('copy', copy(editor));
25364    };
25365
25366    const getCaretRangeFromEvent = (editor, e) => {
25367      var _a, _b;
25368      return RangeUtils.getCaretRangeFromPoint((_a = e.clientX) !== null && _a !== void 0 ? _a : 0, (_b = e.clientY) !== null && _b !== void 0 ? _b : 0, editor.getDoc());
25369    };
25370    const isPlainTextFileUrl = content => {
25371      const plainTextContent = content['text/plain'];
25372      return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false;
25373    };
25374    const setFocusedRange = (editor, rng) => {
25375      editor.focus();
25376      if (rng) {
25377        editor.selection.setRng(rng);
25378      }
25379    };
25380    const hasImage = dataTransfer => exists(dataTransfer.files, file => /^image\//.test(file.type));
25381    const isTransparentBlockDrop = (dom, schema, target, dropContent) => {
25382      const parentTransparent = dom.getParent(target, node => isTransparentBlock(schema, node));
25383      if (parentTransparent && has$2(dropContent, 'text/html')) {
25384        const fragment = new DOMParser().parseFromString(dropContent['text/html'], 'text/html').body;
25385        return !isNull(fragment.querySelector(parentTransparent.nodeName.toLowerCase()));
25386      } else {
25387        return false;
25388      }
25389    };
25390    const setup$a = (editor, draggingInternallyState) => {
25391      if (shouldPasteBlockDrop(editor)) {
25392        editor.on('dragend dragover draggesture dragdrop drop drag', e => {
25393          e.preventDefault();
25394          e.stopPropagation();
25395        });
25396      }
25397      if (!shouldPasteDataImages(editor)) {
25398        editor.on('drop', e => {
25399          const dataTransfer = e.dataTransfer;
25400          if (dataTransfer && hasImage(dataTransfer)) {
25401            e.preventDefault();
25402          }
25403        });
25404      }
25405      editor.on('drop', e => {
25406        if (e.isDefaultPrevented()) {
25407          return;
25408        }
25409        const rng = getCaretRangeFromEvent(editor, e);
25410        if (isNullable(rng)) {
25411          return;
25412        }
25413        const dropContent = getDataTransferItems(e.dataTransfer);
25414        const internal = hasContentType(dropContent, internalHtmlMime());
25415        if ((!hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && pasteImageData(editor, e, rng)) {
25416          return;
25417        }
25418        const internalContent = dropContent[internalHtmlMime()];
25419        const content = internalContent || dropContent['text/html'] || dropContent['text/plain'];
25420        const transparentElementDrop = isTransparentBlockDrop(editor.dom, editor.schema, rng.startContainer, dropContent);
25421        if (draggingInternallyState.get() && !transparentElementDrop) {
25422          return;
25423        }
25424        if (content) {
25425          e.preventDefault();
25426          Delay.setEditorTimeout(editor, () => {
25427            editor.undoManager.transact(() => {
25428              if (internalContent) {
25429                editor.execCommand('Delete');
25430              }
25431              setFocusedRange(editor, rng);
25432              const trimmedContent = trimHtml(content);
25433              if (dropContent['text/html']) {
25434                pasteHtml(editor, trimmedContent, internal);
25435              } else {
25436                pasteText(editor, trimmedContent);
25437              }
25438            });
25439          });
25440        }
25441      });
25442      editor.on('dragstart', _e => {
25443        draggingInternallyState.set(true);
25444      });
25445      editor.on('dragover dragend', e => {
25446        if (shouldPasteDataImages(editor) && !draggingInternallyState.get()) {
25447          e.preventDefault();
25448          setFocusedRange(editor, getCaretRangeFromEvent(editor, e));
25449        }
25450        if (e.type === 'dragend') {
25451          draggingInternallyState.set(false);
25452        }
25453      });
25454    };
25455
25456    const setup$9 = editor => {
25457      const processEvent = f => e => {
25458        f(editor, e);
25459      };
25460      const preProcess = getPastePreProcess(editor);
25461      if (isFunction(preProcess)) {
25462        editor.on('PastePreProcess', processEvent(preProcess));
25463      }
25464      const postProcess = getPastePostProcess(editor);
25465      if (isFunction(postProcess)) {
25466        editor.on('PastePostProcess', processEvent(postProcess));
25467      }
25468    };
25469
25470    const addPreProcessFilter = (editor, filterFunc) => {
25471      editor.on('PastePreProcess', e => {
25472        e.content = filterFunc(editor, e.content, e.internal);
25473      });
25474    };
25475    const rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi;
25476    const rgbToHex = value => Tools.trim(value).replace(rgbRegExp, rgbaToHexString).toLowerCase();
25477    const removeWebKitStyles = (editor, content, internal) => {
25478      const webKitStylesOption = getPasteWebkitStyles(editor);
25479      if (internal || webKitStylesOption === 'all' || !shouldPasteRemoveWebKitStyles(editor)) {
25480        return content;
25481      }
25482      const webKitStyles = webKitStylesOption ? webKitStylesOption.split(/[, ]/) : [];
25483      if (webKitStyles && webKitStylesOption !== 'none') {
25484        const dom = editor.dom, node = editor.selection.getNode();
25485        content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, (all, before, value, after) => {
25486          const inputStyles = dom.parseStyle(dom.decode(value));
25487          const outputStyles = {};
25488          for (let i = 0; i < webKitStyles.length; i++) {
25489            const inputValue = inputStyles[webKitStyles[i]];
25490            let compareInput = inputValue;
25491            let currentValue = dom.getStyle(node, webKitStyles[i], true);
25492            if (/color/.test(webKitStyles[i])) {
25493              compareInput = rgbToHex(compareInput);
25494              currentValue = rgbToHex(currentValue);
25495            }
25496            if (currentValue !== compareInput) {
25497              outputStyles[webKitStyles[i]] = inputValue;
25498            }
25499          }
25500          const outputStyle = dom.serializeStyle(outputStyles, 'span');
25501          if (outputStyle) {
25502            return before + ' style="' + outputStyle + '"' + after;
25503          }
25504          return before + after;
25505        });
25506      } else {
25507        content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3');
25508      }
25509      content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, (all, before, value, after) => {
25510        return before + ' style="' + value + '"' + after;
25511      });
25512      return content;
25513    };
25514    const setup$8 = editor => {
25515      if (Env.browser.isChromium() || Env.browser.isSafari()) {
25516        addPreProcessFilter(editor, removeWebKitStyles);
25517      }
25518    };
25519
25520    const setup$7 = editor => {
25521      const draggingInternallyState = Cell(false);
25522      const pasteFormat = Cell(isPasteAsTextEnabled(editor) ? 'text' : 'html');
25523      const pasteBin = PasteBin(editor);
25524      setup$8(editor);
25525      register$1(editor, pasteFormat);
25526      setup$9(editor);
25527      editor.on('PreInit', () => {
25528        register(editor);
25529        setup$a(editor, draggingInternallyState);
25530        registerEventsAndFilters(editor, pasteBin, pasteFormat);
25531      });
25532    };
25533
25534    const preventSummaryToggle = editor => {
25535      editor.on('click', e => {
25536        if (editor.dom.getParent(e.target, 'details')) {
25537          e.preventDefault();
25538        }
25539      });
25540    };
25541    const filterDetails = editor => {
25542      editor.parser.addNodeFilter('details', elms => {
25543        each$e(elms, details => {
25544          details.attr('data-mce-open', details.attr('open'));
25545          details.attr('open', 'open');
25546        });
25547      });
25548      editor.serializer.addNodeFilter('details', elms => {
25549        each$e(elms, details => {
25550          const open = details.attr('data-mce-open');
25551          details.attr('open', isString(open) ? open : null);
25552          details.attr('data-mce-open', null);
25553        });
25554      });
25555    };
25556    const setup$6 = editor => {
25557      preventSummaryToggle(editor);
25558      filterDetails(editor);
25559    };
25560
25561    const isBr = isBr$6;
25562    const isText = isText$a;
25563    const isContentEditableFalse$2 = elm => isContentEditableFalse$b(elm.dom);
25564    const isContentEditableTrue = elm => isContentEditableTrue$3(elm.dom);
25565    const isRoot = rootNode => elm => eq(SugarElement.fromDom(rootNode), elm);
25566    const getClosestScope = (node, rootNode) => closest$4(SugarElement.fromDom(node), elm => isContentEditableTrue(elm) || isBlock$2(elm), isRoot(rootNode)).getOr(SugarElement.fromDom(rootNode)).dom;
25567    const getClosestCef = (node, rootNode) => closest$4(SugarElement.fromDom(node), isContentEditableFalse$2, isRoot(rootNode));
25568    const findEdgeCaretCandidate = (startNode, scope, forward) => {
25569      const walker = new DomTreeWalker(startNode, scope);
25570      const next = forward ? walker.next.bind(walker) : walker.prev.bind(walker);
25571      let result = startNode;
25572      for (let current = forward ? startNode : next(); current && !isBr(current); current = next()) {
25573        if (isCaretCandidate$3(current)) {
25574          result = current;
25575        }
25576      }
25577      return result;
25578    };
25579    const findClosestBlockRange = (startRng, rootNode) => {
25580      const startPos = CaretPosition.fromRangeStart(startRng);
25581      const clickNode = startPos.getNode();
25582      const scope = getClosestScope(clickNode, rootNode);
25583      const startNode = findEdgeCaretCandidate(clickNode, scope, false);
25584      const endNode = findEdgeCaretCandidate(clickNode, scope, true);
25585      const rng = document.createRange();
25586      getClosestCef(startNode, scope).fold(() => {
25587        if (isText(startNode)) {
25588          rng.setStart(startNode, 0);
25589        } else {
25590          rng.setStartBefore(startNode);
25591        }
25592      }, cef => rng.setStartBefore(cef.dom));
25593      getClosestCef(endNode, scope).fold(() => {
25594        if (isText(endNode)) {
25595          rng.setEnd(endNode, endNode.data.length);
25596        } else {
25597          rng.setEndAfter(endNode);
25598        }
25599      }, cef => rng.setEndAfter(cef.dom));
25600      return rng;
25601    };
25602    const onTripleClickSelect = editor => {
25603      const rng = findClosestBlockRange(editor.selection.getRng(), editor.getBody());
25604      editor.selection.setRng(normalize(rng));
25605    };
25606    const setup$5 = editor => {
25607      editor.on('mousedown', e => {
25608        if (e.detail >= 3) {
25609          e.preventDefault();
25610          onTripleClickSelect(editor);
25611        }
25612      });
25613    };
25614
25615    var FakeCaretPosition;
25616    (function (FakeCaretPosition) {
25617      FakeCaretPosition['Before'] = 'before';
25618      FakeCaretPosition['After'] = 'after';
25619    }(FakeCaretPosition || (FakeCaretPosition = {})));
25620    const distanceToRectLeft = (clientRect, clientX) => Math.abs(clientRect.left - clientX);
25621    const distanceToRectRight = (clientRect, clientX) => Math.abs(clientRect.right - clientX);
25622    const isInsideY = (clientY, clientRect) => clientY >= clientRect.top && clientY <= clientRect.bottom;
25623    const collidesY = (r1, r2) => r1.top < r2.bottom && r1.bottom > r2.top;
25624    const isOverlapping = (r1, r2) => {
25625      const overlap = overlapY(r1, r2) / Math.min(r1.height, r2.height);
25626      return collidesY(r1, r2) && overlap > 0.5;
25627    };
25628    const splitRectsPerAxis = (rects, y) => {
25629      const intersectingRects = filter$5(rects, rect => isInsideY(y, rect));
25630      return boundingClientRectFromRects(intersectingRects).fold(() => [
25631        [],
25632        rects
25633      ], boundingRect => {
25634        const {
25635          pass: horizontal,
25636          fail: vertical
25637        } = partition$2(rects, rect => isOverlapping(rect, boundingRect));
25638        return [
25639          horizontal,
25640          vertical
25641        ];
25642      });
25643    };
25644    const clientInfo = (rect, clientX) => {
25645      return {
25646        node: rect.node,
25647        position: distanceToRectLeft(rect, clientX) < distanceToRectRight(rect, clientX) ? FakeCaretPosition.Before : FakeCaretPosition.After
25648      };
25649    };
25650    const horizontalDistance = (rect, x, _y) => x > rect.left && x < rect.right ? 0 : Math.min(Math.abs(rect.left - x), Math.abs(rect.right - x));
25651    const closestChildCaretCandidateNodeRect = (children, clientX, clientY) => {
25652      const caretCandidateRect = rect => {
25653        if (isCaretCandidate$3(rect.node)) {
25654          return Optional.some(rect);
25655        } else if (isElement$6(rect.node)) {
25656          return closestChildCaretCandidateNodeRect(from(rect.node.childNodes), clientX, clientY);
25657        } else {
25658          return Optional.none();
25659        }
25660      };
25661      const getClosestTextNode = (rects, distance) => {
25662        if (rects.length >= 2) {
25663          const r1 = caretCandidateRect(rects[0]).getOr(rects[0]);
25664          const r2 = caretCandidateRect(rects[1]).getOr(rects[1]);
25665          const deltaDistance = Math.abs(distance(r1, clientX, clientY) - distance(r2, clientX, clientY));
25666          if (deltaDistance < 2) {
25667            if (isText$a(r1.node)) {
25668              return Optional.some(r1);
25669            } else if (isText$a(r2.node)) {
25670              return Optional.some(r2);
25671            }
25672          }
25673        }
25674        return Optional.none();
25675      };
25676      const findClosestCaretCandidateNodeRect = (rects, distance) => {
25677        const sortedRects = sort(rects, (r1, r2) => distance(r1, clientX, clientY) - distance(r2, clientX, clientY));
25678        return getClosestTextNode(sortedRects, distance).orThunk(() => findMap(sortedRects, caretCandidateRect));
25679      };
25680      const [horizontalRects, verticalRects] = splitRectsPerAxis(getClientRects(children), clientY);
25681      const {
25682        pass: above,
25683        fail: below
25684      } = partition$2(verticalRects, rect => rect.top < clientY);
25685      return findClosestCaretCandidateNodeRect(horizontalRects, horizontalDistance).orThunk(() => findClosestCaretCandidateNodeRect(below, distanceToRectEdgeFromXY)).orThunk(() => findClosestCaretCandidateNodeRect(above, distanceToRectEdgeFromXY));
25686    };
25687    const traverseUp = (rootElm, scope, clientX, clientY) => {
25688      const helper = (scope, prevScope) => {
25689        const isDragGhostContainer = node => isElement$6(node) && node.classList.contains('mce-drag-container');
25690        const childNodesWithoutGhost = filter$5(scope.dom.childNodes, not(isDragGhostContainer));
25691        return prevScope.fold(() => closestChildCaretCandidateNodeRect(childNodesWithoutGhost, clientX, clientY), prevScope => {
25692          const uncheckedChildren = filter$5(childNodesWithoutGhost, node => node !== prevScope.dom);
25693          return closestChildCaretCandidateNodeRect(uncheckedChildren, clientX, clientY);
25694        }).orThunk(() => {
25695          const parent = eq(scope, rootElm) ? Optional.none() : parentElement(scope);
25696          return parent.bind(newScope => helper(newScope, Optional.some(scope)));
25697        });
25698      };
25699      return helper(scope, Optional.none());
25700    };
25701    const closestCaretCandidateNodeRect = (root, clientX, clientY) => {
25702      const rootElm = SugarElement.fromDom(root);
25703      const ownerDoc = documentOrOwner(rootElm);
25704      const elementAtPoint = SugarElement.fromPoint(ownerDoc, clientX, clientY).filter(elm => contains(rootElm, elm));
25705      const element = elementAtPoint.getOr(rootElm);
25706      return traverseUp(rootElm, element, clientX, clientY);
25707    };
25708    const closestFakeCaretCandidate = (root, clientX, clientY) => closestCaretCandidateNodeRect(root, clientX, clientY).filter(rect => isFakeCaretTarget(rect.node)).map(rect => clientInfo(rect, clientX));
25709
25710    const getAbsolutePosition = elm => {
25711      var _a, _b;
25712      const clientRect = elm.getBoundingClientRect();
25713      const doc = elm.ownerDocument;
25714      const docElem = doc.documentElement;
25715      const win = doc.defaultView;
25716      return {
25717        top: clientRect.top + ((_a = win === null || win === void 0 ? void 0 : win.scrollY) !== null && _a !== void 0 ? _a : 0) - docElem.clientTop,
25718        left: clientRect.left + ((_b = win === null || win === void 0 ? void 0 : win.scrollX) !== null && _b !== void 0 ? _b : 0) - docElem.clientLeft
25719      };
25720    };
25721    const getBodyPosition = editor => editor.inline ? getAbsolutePosition(editor.getBody()) : {
25722      left: 0,
25723      top: 0
25724    };
25725    const getScrollPosition = editor => {
25726      const body = editor.getBody();
25727      return editor.inline ? {
25728        left: body.scrollLeft,
25729        top: body.scrollTop
25730      } : {
25731        left: 0,
25732        top: 0
25733      };
25734    };
25735    const getBodyScroll = editor => {
25736      const body = editor.getBody(), docElm = editor.getDoc().documentElement;
25737      const inlineScroll = {
25738        left: body.scrollLeft,
25739        top: body.scrollTop
25740      };
25741      const iframeScroll = {
25742        left: body.scrollLeft || docElm.scrollLeft,
25743        top: body.scrollTop || docElm.scrollTop
25744      };
25745      return editor.inline ? inlineScroll : iframeScroll;
25746    };
25747    const getMousePosition = (editor, event) => {
25748      if (event.target.ownerDocument !== editor.getDoc()) {
25749        const iframePosition = getAbsolutePosition(editor.getContentAreaContainer());
25750        const scrollPosition = getBodyScroll(editor);
25751        return {
25752          left: event.pageX - iframePosition.left + scrollPosition.left,
25753          top: event.pageY - iframePosition.top + scrollPosition.top
25754        };
25755      }
25756      return {
25757        left: event.pageX,
25758        top: event.pageY
25759      };
25760    };
25761    const calculatePosition = (bodyPosition, scrollPosition, mousePosition) => ({
25762      pageX: mousePosition.left - bodyPosition.left + scrollPosition.left,
25763      pageY: mousePosition.top - bodyPosition.top + scrollPosition.top
25764    });
25765    const calc = (editor, event) => calculatePosition(getBodyPosition(editor), getScrollPosition(editor), getMousePosition(editor, event));
25766
25767    const makeDndEventFromMouseEvent = (type, mouseEvent, extra) => ({
25768      ...mouseEvent,
25769      dataTransfer: null,
25770      type,
25771      ...extra
25772    });
25773    const makeDndEvent = (type, props) => {
25774      const fail = die('Function not supported on simulated event.');
25775      const event = {
25776        bubbles: true,
25777        cancelBubble: false,
25778        cancelable: true,
25779        composed: false,
25780        currentTarget: null,
25781        defaultPrevented: false,
25782        eventPhase: 0,
25783        isTrusted: true,
25784        returnValue: false,
25785        srcElement: null,
25786        target: null,
25787        timeStamp: 0,
25788        type,
25789        composedPath: fail,
25790        initEvent: fail,
25791        preventDefault: noop,
25792        stopImmediatePropagation: noop,
25793        stopPropagation: noop,
25794        AT_TARGET: window.Event.AT_TARGET,
25795        BUBBLING_PHASE: window.Event.BUBBLING_PHASE,
25796        CAPTURING_PHASE: window.Event.CAPTURING_PHASE,
25797        NONE: window.Event.NONE,
25798        altKey: false,
25799        button: 0,
25800        buttons: 0,
25801        clientX: 0,
25802        clientY: 0,
25803        ctrlKey: false,
25804        metaKey: false,
25805        movementX: 0,
25806        movementY: 0,
25807        offsetX: 0,
25808        offsetY: 0,
25809        pageX: 0,
25810        pageY: 0,
25811        relatedTarget: null,
25812        screenX: 0,
25813        screenY: 0,
25814        shiftKey: false,
25815        x: 0,
25816        y: 0,
25817        detail: 0,
25818        view: null,
25819        which: 0,
25820        initUIEvent: fail,
25821        initMouseEvent: fail,
25822        getModifierState: fail,
25823        dataTransfer: null,
25824        ...props
25825      };
25826      return event;
25827    };
25828    const fallback = target => ({
25829      target,
25830      srcElement: target
25831    });
25832    const dndEvent = type => target => makeDndEvent(type, fallback(target));
25833    const dndEventFromMouseEvent = type => (mouseEvent, target) => makeDndEventFromMouseEvent(type, mouseEvent, fallback(target));
25834    const makeDragstartEventFromMouseEvent = dndEventFromMouseEvent('dragstart');
25835    const makeDropEventFromMouseEvent = dndEventFromMouseEvent('drop');
25836    const makeDragendEvent = dndEvent('dragend');
25837    const makeDragendEventFromMouseEvent = dndEventFromMouseEvent('dragend');
25838
25839    const scrollPixelsPerInterval = 32;
25840    const scrollIntervalValue = 100;
25841    const mouseRangeToTriggerScrollInsideEditor = 8;
25842    const mouseRangeToTriggerScrollOutsideEditor = 16;
25843    const isContentEditableFalse$1 = isContentEditableFalse$b;
25844    const isContentEditable = or(isContentEditableFalse$1, isContentEditableTrue$3);
25845    const isDraggable = (dom, rootElm, elm) => isContentEditableFalse$1(elm) && elm !== rootElm && dom.isEditable(elm.parentElement);
25846    const isValidDropTarget = (editor, targetElement, dragElement) => {
25847      if (isNullable(targetElement)) {
25848        return false;
25849      } else if (targetElement === dragElement || editor.dom.isChildOf(targetElement, dragElement)) {
25850        return false;
25851      } else {
25852        return editor.dom.isEditable(targetElement);
25853      }
25854    };
25855    const cloneElement = elm => {
25856      const cloneElm = elm.cloneNode(true);
25857      cloneElm.removeAttribute('data-mce-selected');
25858      return cloneElm;
25859    };
25860    const createGhost = (editor, elm, width, height) => {
25861      const dom = editor.dom;
25862      const clonedElm = elm.cloneNode(true);
25863      dom.setStyles(clonedElm, {
25864        width,
25865        height
25866      });
25867      dom.setAttrib(clonedElm, 'data-mce-selected', null);
25868      const ghostElm = dom.create('div', {
25869        'class': 'mce-drag-container',
25870        'data-mce-bogus': 'all',
25871        'unselectable': 'on',
25872        'contenteditable': 'false'
25873      });
25874      dom.setStyles(ghostElm, {
25875        position: 'absolute',
25876        opacity: 0.5,
25877        overflow: 'hidden',
25878        border: 0,
25879        padding: 0,
25880        margin: 0,
25881        width,
25882        height
25883      });
25884      dom.setStyles(clonedElm, {
25885        margin: 0,
25886        boxSizing: 'border-box'
25887      });
25888      ghostElm.appendChild(clonedElm);
25889      return ghostElm;
25890    };
25891    const appendGhostToBody = (ghostElm, bodyElm) => {
25892      if (ghostElm.parentNode !== bodyElm) {
25893        bodyElm.appendChild(ghostElm);
25894      }
25895    };
25896    const scrollEditor = (direction, amount) => win => () => {
25897      const current = direction === 'left' ? win.scrollX : win.scrollY;
25898      win.scroll({
25899        [direction]: current + amount,
25900        behavior: 'smooth'
25901      });
25902    };
25903    const scrollLeft = scrollEditor('left', -scrollPixelsPerInterval);
25904    const scrollRight = scrollEditor('left', scrollPixelsPerInterval);
25905    const scrollUp = scrollEditor('top', -scrollPixelsPerInterval);
25906    const scrollDown = scrollEditor('top', scrollPixelsPerInterval);
25907    const moveGhost = (ghostElm, position, width, height, maxX, maxY, mouseY, mouseX, contentAreaContainer, win, state, mouseEventOriginatedFromWithinTheEditor) => {
25908      let overflowX = 0, overflowY = 0;
25909      ghostElm.style.left = position.pageX + 'px';
25910      ghostElm.style.top = position.pageY + 'px';
25911      if (position.pageX + width > maxX) {
25912        overflowX = position.pageX + width - maxX;
25913      }
25914      if (position.pageY + height > maxY) {
25915        overflowY = position.pageY + height - maxY;
25916      }
25917      ghostElm.style.width = width - overflowX + 'px';
25918      ghostElm.style.height = height - overflowY + 'px';
25919      const clientHeight = contentAreaContainer.clientHeight;
25920      const clientWidth = contentAreaContainer.clientWidth;
25921      const outerMouseY = mouseY + contentAreaContainer.getBoundingClientRect().top;
25922      const outerMouseX = mouseX + contentAreaContainer.getBoundingClientRect().left;
25923      state.on(state => {
25924        state.intervalId.clear();
25925        if (state.dragging && mouseEventOriginatedFromWithinTheEditor) {
25926          if (mouseY + mouseRangeToTriggerScrollInsideEditor >= clientHeight) {
25927            state.intervalId.set(scrollDown(win));
25928          } else if (mouseY - mouseRangeToTriggerScrollInsideEditor <= 0) {
25929            state.intervalId.set(scrollUp(win));
25930          } else if (mouseX + mouseRangeToTriggerScrollInsideEditor >= clientWidth) {
25931            state.intervalId.set(scrollRight(win));
25932          } else if (mouseX - mouseRangeToTriggerScrollInsideEditor <= 0) {
25933            state.intervalId.set(scrollLeft(win));
25934          } else if (outerMouseY + mouseRangeToTriggerScrollOutsideEditor >= window.innerHeight) {
25935            state.intervalId.set(scrollDown(window));
25936          } else if (outerMouseY - mouseRangeToTriggerScrollOutsideEditor <= 0) {
25937            state.intervalId.set(scrollUp(window));
25938          } else if (outerMouseX + mouseRangeToTriggerScrollOutsideEditor >= window.innerWidth) {
25939            state.intervalId.set(scrollRight(window));
25940          } else if (outerMouseX - mouseRangeToTriggerScrollOutsideEditor <= 0) {
25941            state.intervalId.set(scrollLeft(window));
25942          }
25943        }
25944      });
25945    };
25946    const removeElement = elm => {
25947      if (elm && elm.parentNode) {
25948        elm.parentNode.removeChild(elm);
25949      }
25950    };
25951    const removeElementWithPadding = (dom, elm) => {
25952      const parentBlock = dom.getParent(elm.parentNode, dom.isBlock);
25953      removeElement(elm);
25954      if (parentBlock && parentBlock !== dom.getRoot() && dom.isEmpty(parentBlock)) {
25955        fillWithPaddingBr(SugarElement.fromDom(parentBlock));
25956      }
25957    };
25958    const isLeftMouseButtonPressed = e => e.button === 0;
25959    const applyRelPos = (state, position) => ({
vendor: 4,642 bytes, lines 25960-26058
25960      pageX: position.pageX - state.relX,
25961      pageY: position.pageY + 5
25962    });
25963    const start = (state, editor) => e => {
25964      if (isLeftMouseButtonPressed(e)) {
25965        const ceElm = find$2(editor.dom.getParents(e.target), isContentEditable).getOr(null);
25966        if (isNonNullable(ceElm) && isDraggable(editor.dom, editor.getBody(), ceElm)) {
25967          const elmPos = editor.dom.getPos(ceElm);
25968          const bodyElm = editor.getBody();
25969          const docElm = editor.getDoc().documentElement;
25970          state.set({
25971            element: ceElm,
25972            dragging: false,
25973            screenX: e.screenX,
25974            screenY: e.screenY,
25975            maxX: (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2,
25976            maxY: (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2,
25977            relX: e.pageX - elmPos.x,
25978            relY: e.pageY - elmPos.y,
25979            width: ceElm.offsetWidth,
25980            height: ceElm.offsetHeight,
25981            ghost: createGhost(editor, ceElm, ceElm.offsetWidth, ceElm.offsetHeight),
25982            intervalId: repeatable(scrollIntervalValue)
25983          });
25984        }
25985      }
25986    };
25987    const placeCaretAt = (editor, clientX, clientY) => {
25988      editor._selectionOverrides.hideFakeCaret();
25989      closestFakeCaretCandidate(editor.getBody(), clientX, clientY).fold(() => editor.selection.placeCaretAt(clientX, clientY), caretInfo => {
25990        const range = editor._selectionOverrides.showCaret(1, caretInfo.node, caretInfo.position === FakeCaretPosition.Before, false);
25991        if (range) {
25992          editor.selection.setRng(range);
25993        } else {
25994          editor.selection.placeCaretAt(clientX, clientY);
25995        }
25996      });
25997    };
25998    const move = (state, editor) => {
25999      const throttledPlaceCaretAt = first$1((clientX, clientY) => placeCaretAt(editor, clientX, clientY), 0);
26000      editor.on('remove', throttledPlaceCaretAt.cancel);
26001      const state_ = state;
26002      return e => state.on(state => {
26003        const movement = Math.max(Math.abs(e.screenX - state.screenX), Math.abs(e.screenY - state.screenY));
26004        if (!state.dragging && movement > 10) {
26005          const args = editor.dispatch('dragstart', makeDragstartEventFromMouseEvent(e, state.element));
26006          if (args.isDefaultPrevented()) {
26007            return;
26008          }
26009          state.dragging = true;
26010          editor.focus();
26011        }
26012        if (state.dragging) {
26013          const mouseEventOriginatedFromWithinTheEditor = e.currentTarget === editor.getDoc().documentElement;
26014          const targetPos = applyRelPos(state, calc(editor, e));
26015          appendGhostToBody(state.ghost, editor.getBody());
26016          moveGhost(state.ghost, targetPos, state.width, state.height, state.maxX, state.maxY, e.clientY, e.clientX, editor.getContentAreaContainer(), editor.getWin(), state_, mouseEventOriginatedFromWithinTheEditor);
26017          throttledPlaceCaretAt.throttle(e.clientX, e.clientY);
26018        }
26019      });
26020    };
26021    const getRawTarget = selection => {
26022      const sel = selection.getSel();
26023      if (isNonNullable(sel)) {
26024        const rng = sel.getRangeAt(0);
26025        const startContainer = rng.startContainer;
26026        return isText$a(startContainer) ? startContainer.parentNode : startContainer;
26027      } else {
26028        return null;
26029      }
26030    };
26031    const drop = (state, editor) => e => {
26032      state.on(state => {
26033        var _a;
26034        state.intervalId.clear();
26035        if (state.dragging) {
26036          if (isValidDropTarget(editor, getRawTarget(editor.selection), state.element)) {
26037            const targetClone = cloneElement(state.element);
26038            const dropTarget = (_a = editor.getDoc().elementFromPoint(e.clientX, e.clientY)) !== null && _a !== void 0 ? _a : editor.getBody();
26039            const args = editor.dispatch('drop', makeDropEventFromMouseEvent(e, dropTarget));
26040            if (!args.isDefaultPrevented()) {
26041              editor.undoManager.transact(() => {
26042                removeElementWithPadding(editor.dom, state.element);
26043                editor.insertContent(editor.dom.getOuterHTML(targetClone));
26044                editor._selectionOverrides.hideFakeCaret();
26045              });
26046            }
26047          }
26048          editor.dispatch('dragend', makeDragendEventFromMouseEvent(e, editor.getBody()));
26049        }
26050      });
26051      removeDragState(state);
26052    };
26053    const stopDragging = (state, editor, e) => {
26054      state.on(state => {
26055        state.intervalId.clear();
26056        if (state.dragging) {
26057          const event = e.fold(() => makeDragendEvent(state.element), mouseEvent => makeDragendEventFromMouseEvent(mouseEvent, state.element));
26058          editor.dispatch('dragend', event
vendor: 11,921 bytes, lines 26058-26368
26058);
26059        }
26060      });
26061      removeDragState(state);
26062    };
26063    const stop = (state, editor) => e => stopDragging(state, editor, Optional.some(e));
26064    const removeDragState = state => {
26065      state.on(state => {
26066        state.intervalId.clear();
26067        removeElement(state.ghost);
26068      });
26069      state.clear();
26070    };
26071    const bindFakeDragEvents = editor => {
26072      const state = value$2();
26073      const pageDom = DOMUtils.DOM;
26074      const rootDocument = document;
26075      const dragStartHandler = start(state, editor);
26076      const dragHandler = move(state, editor);
26077      const dropHandler = drop(state, editor);
26078      const dragEndHandler = stop(state, editor);
26079      editor.on('mousedown', dragStartHandler);
26080      editor.on('mousemove', dragHandler);
26081      editor.on('mouseup', dropHandler);
26082      pageDom.bind(rootDocument, 'mousemove', dragHandler);
26083      pageDom.bind(rootDocument, 'mouseup', dragEndHandler);
26084      editor.on('remove', () => {
26085        pageDom.unbind(rootDocument, 'mousemove', dragHandler);
26086        pageDom.unbind(rootDocument, 'mouseup', dragEndHandler);
26087      });
26088      editor.on('keydown', e => {
26089        if (e.keyCode === VK.ESC) {
26090          stopDragging(state, editor, Optional.none());
26091        }
26092      });
26093    };
26094    const blockUnsupportedFileDrop = editor => {
26095      const preventFileDrop = e => {
26096        if (!e.isDefaultPrevented()) {
26097          const dataTransfer = e.dataTransfer;
26098          if (dataTransfer && (contains$2(dataTransfer.types, 'Files') || dataTransfer.files.length > 0)) {
26099            e.preventDefault();
26100            if (e.type === 'drop') {
26101              displayError(editor, 'Dropped file type is not supported');
26102            }
26103          }
26104        }
26105      };
26106      const preventFileDropIfUIElement = e => {
26107        if (isUIElement(editor, e.target)) {
26108          preventFileDrop(e);
26109        }
26110      };
26111      const setup = () => {
26112        const pageDom = DOMUtils.DOM;
26113        const dom = editor.dom;
26114        const doc = document;
26115        const editorRoot = editor.inline ? editor.getBody() : editor.getDoc();
26116        const eventNames = [
26117          'drop',
26118          'dragover'
26119        ];
26120        each$e(eventNames, name => {
26121          pageDom.bind(doc, name, preventFileDropIfUIElement);
26122          dom.bind(editorRoot, name, preventFileDrop);
26123        });
26124        editor.on('remove', () => {
26125          each$e(eventNames, name => {
26126            pageDom.unbind(doc, name, preventFileDropIfUIElement);
26127            dom.unbind(editorRoot, name, preventFileDrop);
26128          });
26129        });
26130      };
26131      editor.on('init', () => {
26132        Delay.setEditorTimeout(editor, setup, 0);
26133      });
26134    };
26135    const init$2 = editor => {
26136      bindFakeDragEvents(editor);
26137      if (shouldBlockUnsupportedDrop(editor)) {
26138        blockUnsupportedFileDrop(editor);
26139      }
26140    };
26141
26142    const setup$4 = editor => {
26143      const renderFocusCaret = first$1(() => {
26144        if (!editor.removed && editor.getBody().contains(document.activeElement)) {
26145          const rng = editor.selection.getRng();
26146          if (rng.collapsed) {
26147            const caretRange = renderRangeCaret(editor, rng, false);
26148            editor.selection.setRng(caretRange);
26149          }
26150        }
26151      }, 0);
26152      editor.on('focus', () => {
26153        renderFocusCaret.throttle();
26154      });
26155      editor.on('blur', () => {
26156        renderFocusCaret.cancel();
26157      });
26158    };
26159
26160    const setup$3 = editor => {
26161      editor.on('init', () => {
26162        editor.on('focusin', e => {
26163          const target = e.target;
26164          if (isMedia$2(target)) {
26165            const ceRoot = getContentEditableRoot$1(editor.getBody(), target);
26166            const node = isContentEditableFalse$b(ceRoot) ? ceRoot : target;
26167            if (editor.selection.getNode() !== node) {
26168              selectNode(editor, node).each(rng => editor.selection.setRng(rng));
26169            }
26170          }
26171        });
26172      });
26173    };
26174
26175    const isContentEditableFalse = isContentEditableFalse$b;
26176    const getContentEditableRoot = (editor, node) => getContentEditableRoot$1(editor.getBody(), node);
26177    const SelectionOverrides = editor => {
26178      const selection = editor.selection, dom = editor.dom;
26179      const rootNode = editor.getBody();
26180      const fakeCaret = FakeCaret(editor, rootNode, dom.isBlock, () => hasFocus(editor));
26181      const realSelectionId = 'sel-' + dom.uniqueId();
26182      const elementSelectionAttr = 'data-mce-selected';
26183      let selectedElement;
26184      const isFakeSelectionElement = node => isNonNullable(node) && dom.hasClass(node, 'mce-offscreen-selection');
26185      const isFakeSelectionTargetElement = node => node !== rootNode && (isContentEditableFalse(node) || isMedia$2(node)) && dom.isChildOf(node, rootNode) && dom.isEditable(node.parentNode);
26186      const setRange = range => {
26187        if (range) {
26188          selection.setRng(range);
26189        }
26190      };
26191      const showCaret = (direction, node, before, scrollIntoView = true) => {
26192        const e = editor.dispatch('ShowCaret', {
26193          target: node,
26194          direction,
26195          before
26196        });
26197        if (e.isDefaultPrevented()) {
26198          return null;
26199        }
26200        if (scrollIntoView) {
26201          selection.scrollIntoView(node, direction === -1);
26202        }
26203        return fakeCaret.show(before, node);
26204      };
26205      const showBlockCaretContainer = blockCaretContainer => {
26206        if (blockCaretContainer.hasAttribute('data-mce-caret')) {
26207          showCaretContainerBlock(blockCaretContainer);
26208          selection.scrollIntoView(blockCaretContainer);
26209        }
26210      };
26211      const registerEvents = () => {
26212        editor.on('click', e => {
26213          if (!dom.isEditable(e.target)) {
26214            e.preventDefault();
26215            editor.focus();
26216          }
26217        });
26218        editor.on('blur NewBlock', removeElementSelection);
26219        editor.on('ResizeWindow FullscreenStateChanged', fakeCaret.reposition);
26220        editor.on('tap', e => {
26221          const targetElm = e.target;
26222          const contentEditableRoot = getContentEditableRoot(editor, targetElm);
26223          if (isContentEditableFalse(contentEditableRoot)) {
26224            e.preventDefault();
26225            selectNode(editor, contentEditableRoot).each(setElementSelection);
26226          } else if (isFakeSelectionTargetElement(targetElm)) {
26227            selectNode(editor, targetElm).each(setElementSelection);
26228          }
26229        }, true);
26230        editor.on('mousedown', e => {
26231          const targetElm = e.target;
26232          if (targetElm !== rootNode && targetElm.nodeName !== 'HTML' && !dom.isChildOf(targetElm, rootNode)) {
26233            return;
26234          }
26235          if (!isXYInContentArea(editor, e.clientX, e.clientY)) {
26236            return;
26237          }
26238          removeElementSelection();
26239          hideFakeCaret();
26240          const closestContentEditable = getContentEditableRoot(editor, targetElm);
26241          if (isContentEditableFalse(closestContentEditable)) {
26242            e.preventDefault();
26243            selectNode(editor, closestContentEditable).each(setElementSelection);
26244          } else {
26245            closestFakeCaretCandidate(rootNode, e.clientX, e.clientY).each(caretInfo => {
26246              e.preventDefault();
26247              const range = showCaret(1, caretInfo.node, caretInfo.position === FakeCaretPosition.Before, false);
26248              setRange(range);
26249              if (isElement$6(closestContentEditable)) {
26250                closestContentEditable.focus();
26251              } else {
26252                editor.getBody().focus();
26253              }
26254            });
26255          }
26256        });
26257        editor.on('keypress', e => {
26258          if (VK.modifierPressed(e)) {
26259            return;
26260          }
26261          if (isContentEditableFalse(selection.getNode())) {
26262            e.preventDefault();
26263          }
26264        });
26265        editor.on('GetSelectionRange', e => {
26266          let rng = e.range;
26267          if (selectedElement) {
26268            if (!selectedElement.parentNode) {
26269              selectedElement = null;
26270              return;
26271            }
26272            rng = rng.cloneRange();
26273            rng.selectNode(selectedElement);
26274            e.range = rng;
26275          }
26276        });
26277        editor.on('SetSelectionRange', e => {
26278          e.range = normalizeVoidElementSelection(e.range);
26279          const rng = setElementSelection(e.range, e.forward);
26280          if (rng) {
26281            e.range = rng;
26282          }
26283        });
26284        const isPasteBin = node => isElement$6(node) && node.id === 'mcepastebin';
26285        editor.on('AfterSetSelectionRange', e => {
26286          const rng = e.range;
26287          const parent = rng.startContainer.parentElement;
26288          if (!isRangeInCaretContainer(rng) && !isPasteBin(parent)) {
26289            hideFakeCaret();
26290          }
26291          if (!isFakeSelectionElement(parent)) {
26292            removeElementSelection();
26293          }
26294        });
26295        init$2(editor);
26296        setup$4(editor);
26297        setup$3(editor);
26298      };
26299      const isWithinCaretContainer = node => isCaretContainer$2(node) || startsWithCaretContainer$1(node) || endsWithCaretContainer$1(node);
26300      const isRangeInCaretContainer = rng => isWithinCaretContainer(rng.startContainer) || isWithinCaretContainer(rng.endContainer);
26301      const normalizeVoidElementSelection = rng => {
26302        const voidElements = editor.schema.getVoidElements();
26303        const newRng = dom.createRng();
26304        const startContainer = rng.startContainer;
26305        const startOffset = rng.startOffset;
26306        const endContainer = rng.endContainer;
26307        const endOffset = rng.endOffset;
26308        if (has$2(voidElements, startContainer.nodeName.toLowerCase())) {
26309          if (startOffset === 0) {
26310            newRng.setStartBefore(startContainer);
26311          } else {
26312            newRng.setStartAfter(startContainer);
26313          }
26314        } else {
26315          newRng.setStart(startContainer, startOffset);
26316        }
26317        if (has$2(voidElements, endContainer.nodeName.toLowerCase())) {
26318          if (endOffset === 0) {
26319            newRng.setEndBefore(endContainer);
26320          } else {
26321            newRng.setEndAfter(endContainer);
26322          }
26323        } else {
26324          newRng.setEnd(endContainer, endOffset);
26325        }
26326        return newRng;
26327      };
26328      const setupOffscreenSelection = (node, targetClone) => {
26329        const body = SugarElement.fromDom(editor.getBody());
26330        const doc = editor.getDoc();
26331        const realSelectionContainer = descendant(body, '#' + realSelectionId).getOrThunk(() => {
26332          const newContainer = SugarElement.fromHtml('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>', doc);
26333          set$3(newContainer, 'id', realSelectionId);
26334          append$1(body, newContainer);
26335          return newContainer;
26336        });
26337        const newRange = dom.createRng();
26338        empty(realSelectionContainer);
26339        append(realSelectionContainer, [
26340          SugarElement.fromText(nbsp, doc),
26341          SugarElement.fromDom(targetClone),
26342          SugarElement.fromText(nbsp, doc)
26343        ]);
26344        newRange.setStart(realSelectionContainer.dom.firstChild, 1);
26345        newRange.setEnd(realSelectionContainer.dom.lastChild, 0);
26346        setAll(realSelectionContainer, { top: dom.getPos(node, editor.getBody()).y + 'px' });
26347        focus$1(realSelectionContainer);
26348        const sel = selection.getSel();
26349        if (sel) {
26350          sel.removeAllRanges();
26351          sel.addRange(newRange);
26352        }
26353        return newRange;
26354      };
26355      const selectElement = elm => {
26356        const targetClone = elm.cloneNode(true);
26357        const e = editor.dispatch('ObjectSelected', {
26358          target: elm,
26359          targetClone
26360        });
26361        if (e.isDefaultPrevented()) {
26362          return null;
26363        }
26364        const range = setupOffscreenSelection(elm, e.targetClone);
26365        const nodeElm = SugarElement.fromDom(elm);
26366        each$e(descendants(SugarElement.fromDom(editor.getBody()), `*[${ elementSelectionAttr }]`), elm => {
26367          if (!eq(nodeElm, elm)) {
26368            remove$
26368b(elm, elementSelectionAttr);
26369          }
26370        });
26371        if (!dom.getAttrib(elm, elementSelectionAttr)) {
26372          elm.setAttribute(elementSelectionAttr, '1');
26373        }
26374        selectedElement = elm;
26375        hideFakeCaret();
26376        return range;
26377      };
26378      const setElementSelection = (range, forward) => {
26379        if (!range) {
26380          return null;
26381        }
26382        if (range.collapsed) {
26383          if (!isRangeInCaretContainer(range)) {
26384            const dir = forward ? 1 : -1;
26385            const caretPosition = getNormalizedRangeEndPoint(dir, rootNode, range);
26386            const beforeNode = caretPosition.getNode(!forward);
26387            if (isNonNullable(beforeNode)) {
26388              if (isFakeCaretTarget(beforeNode)) {
26389                return showCaret(dir, beforeNode, forward ? !caretPosition.isAt
vendor: 1,997 bytes, lines 26389-26436
26389End() : false, false);
26390              }
26391              if (isCaretContainerInline(beforeNode) && isContentEditableFalse$b(beforeNode.nextSibling)) {
26392                const rng = dom.createRng();
26393                rng.setStart(beforeNode, 0);
26394                rng.setEnd(beforeNode, 0);
26395                return rng;
26396              }
26397            }
26398            const afterNode = caretPosition.getNode(forward);
26399            if (isNonNullable(afterNode)) {
26400              if (isFakeCaretTarget(afterNode)) {
26401                return showCaret(dir, afterNode, forward ? false : !caretPosition.isAtEnd(), false);
26402              }
26403              if (isCaretContainerInline(afterNode) && isContentEditableFalse$b(afterNode.previousSibling)) {
26404                const rng = dom.createRng();
26405                rng.setStart(afterNode, 1);
26406                rng.setEnd(afterNode, 1);
26407                return rng;
26408              }
26409            }
26410          }
26411          return null;
26412        }
26413        let startContainer = range.startContainer;
26414        let startOffset = range.startOffset;
26415        const endOffset = range.endOffset;
26416        if (isText$a(startContainer) && startOffset === 0 && isContentEditableFalse(startContainer.parentNode)) {
26417          startContainer = startContainer.parentNode;
26418          startOffset = dom.nodeIndex(startContainer);
26419          startContainer = startContainer.parentNode;
26420        }
26421        if (!isElement$6(startContainer)) {
26422          return null;
26423        }
26424        if (endOffset === startOffset + 1 && startContainer === range.endContainer) {
26425          const node = startContainer.childNodes[startOffset];
26426          if (isFakeSelectionTargetElement(node)) {
26427            return selectElement(node);
26428          }
26429        }
26430        return null;
26431      };
26432      const removeElementSelection = () => {
26433        if (selectedElement) {
26434          selectedElement.removeAttribute(elementSelectionAttr);
26435        }
26436        descendant(SugarElement.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$6
vendor: 35,575 bytes, lines 26436-27328
26436);
26437        selectedElement = null;
26438      };
26439      const destroy = () => {
26440        fakeCaret.destroy();
26441        selectedElement = null;
26442      };
26443      const hideFakeCaret = () => {
26444        fakeCaret.hide();
26445      };
26446      if (!isRtc(editor)) {
26447        registerEvents();
26448      }
26449      return {
26450        showCaret,
26451        showBlockCaretContainer,
26452        hideFakeCaret,
26453        destroy
26454      };
26455    };
26456
26457    const getNormalizedTextOffset = (container, offset) => {
26458      let normalizedOffset = offset;
26459      for (let node = container.previousSibling; isText$a(node); node = node.previousSibling) {
26460        normalizedOffset += node.data.length;
26461      }
26462      return normalizedOffset;
26463    };
26464    const generatePath = (dom, root, node, offset, normalized) => {
26465      if (isText$a(node) && (offset < 0 || offset > node.data.length)) {
26466        return [];
26467      }
26468      const p = normalized && isText$a(node) ? [getNormalizedTextOffset(node, offset)] : [offset];
26469      let current = node;
26470      while (current !== root && current.parentNode) {
26471        p.push(dom.nodeIndex(current, normalized));
26472        current = current.parentNode;
26473      }
26474      return current === root ? p.reverse() : [];
26475    };
26476    const generatePathRange = (dom, root, startNode, startOffset, endNode, endOffset, normalized = false) => {
26477      const start = generatePath(dom, root, startNode, startOffset, normalized);
26478      const end = generatePath(dom, root, endNode, endOffset, normalized);
26479      return {
26480        start,
26481        end
26482      };
26483    };
26484    const resolvePath = (root, path) => {
26485      const nodePath = path.slice();
26486      const offset = nodePath.pop();
26487      if (!isNumber(offset)) {
26488        return Optional.none();
26489      } else {
26490        const resolvedNode = foldl(nodePath, (optNode, index) => optNode.bind(node => Optional.from(node.childNodes[index])), Optional.some(root));
26491        return resolvedNode.bind(node => {
26492          if (isText$a(node) && (offset < 0 || offset > node.data.length)) {
26493            return Optional.none();
26494          } else {
26495            return Optional.some({
26496              node,
26497              offset
26498            });
26499          }
26500        });
26501      }
26502    };
26503    const resolvePathRange = (root, range) => resolvePath(root, range.start).bind(({
26504      node: startNode,
26505      offset: startOffset
26506    }) => resolvePath(root, range.end).map(({
26507      node: endNode,
26508      offset: endOffset
26509    }) => {
26510      const rng = document.createRange();
26511      rng.setStart(startNode, startOffset);
26512      rng.setEnd(endNode, endOffset);
26513      return rng;
26514    }));
26515    const generatePathRangeFromRange = (dom, root, range, normalized = false) => generatePathRange(dom, root, range.startContainer, range.startOffset, range.endContainer, range.endOffset, normalized);
26516
26517    const cleanEmptyNodes = (dom, node, isRoot) => {
26518      if (node && dom.isEmpty(node) && !isRoot(node)) {
26519        const parent = node.parentNode;
26520        dom.remove(node);
26521        cleanEmptyNodes(dom, parent, isRoot);
26522      }
26523    };
26524    const deleteRng = (dom, rng, isRoot, clean = true) => {
26525      const startParent = rng.startContainer.parentNode;
26526      const endParent = rng.endContainer.parentNode;
26527      rng.deleteContents();
26528      if (clean && !isRoot(rng.startContainer)) {
26529        if (isText$a(rng.startContainer) && rng.startContainer.data.length === 0) {
26530          dom.remove(rng.startContainer);
26531        }
26532        if (isText$a(rng.endContainer) && rng.endContainer.data.length === 0) {
26533          dom.remove(rng.endContainer);
26534        }
26535        cleanEmptyNodes(dom, startParent, isRoot);
26536        if (startParent !== endParent) {
26537          cleanEmptyNodes(dom, endParent, isRoot);
26538        }
26539      }
26540    };
26541    const getParentBlock = (editor, rng) => Optional.from(editor.dom.getParent(rng.startContainer, editor.dom.isBlock));
26542    const resolveFromDynamicPatterns = (patternSet, block, beforeText) => {
26543      const dynamicPatterns = patternSet.dynamicPatternsLookup({
26544        text: beforeText,
26545        block
26546      });
26547      return {
26548        ...patternSet,
26549        blockPatterns: getBlockPatterns(dynamicPatterns).concat(patternSet.blockPatterns),
26550        inlinePatterns: getInlinePatterns(dynamicPatterns).concat(patternSet.inlinePatterns)
26551      };
26552    };
26553    const getBeforeText = (dom, block, node, offset) => {
26554      const rng = dom.createRng();
26555      rng.setStart(block, 0);
26556      rng.setEnd(node, offset);
26557      return rng.toString();
26558    };
26559
26560    const startsWithSingleSpace = s => /^\s[^\s]/.test(s);
26561    const stripPattern = (dom, block, pattern) => {
26562      const firstTextNode = textAfter(block, 0, block);
26563      firstTextNode.each(spot => {
26564        const node = spot.container;
26565        scanRight(node, pattern.start.length, block).each(end => {
26566          const rng = dom.createRng();
26567          rng.setStart(node, 0);
26568          rng.setEnd(end.container, end.offset);
26569          deleteRng(dom, rng, e => e === block);
26570        });
26571        const text = SugarElement.fromDom(node);
26572        const textContent = get$3(text);
26573        if (startsWithSingleSpace(textContent)) {
26574          set(text, textContent.slice(1));
26575        }
26576      });
26577    };
26578    const applyPattern$1 = (editor, match) => {
26579      const dom = editor.dom;
26580      const pattern = match.pattern;
26581      const rng = resolvePathRange(dom.getRoot(), match.range).getOrDie('Unable to resolve path range');
26582      const isBlockFormatName = (name, formatter) => {
26583        const formatSet = formatter.get(name);
26584        return isArray$1(formatSet) && head(formatSet).exists(format => has$2(format, 'block'));
26585      };
26586      getParentBlock(editor, rng).each(block => {
26587        if (pattern.type === 'block-format') {
26588          if (isBlockFormatName(pattern.format, editor.formatter)) {
26589            editor.undoManager.transact(() => {
26590              stripPattern(editor.dom, block, pattern);
26591              editor.formatter.apply(pattern.format);
26592            });
26593          }
26594        } else if (pattern.type === 'block-command') {
26595          editor.undoManager.transact(() => {
26596            stripPattern(editor.dom, block, pattern);
26597            editor.execCommand(pattern.cmd, false, pattern.value);
26598          });
26599        }
26600      });
26601      return true;
26602    };
26603    const sortPatterns$1 = patterns => sort(patterns, (a, b) => b.start.length - a.start.length);
26604    const findPattern$1 = (patterns, text) => {
26605      const sortedPatterns = sortPatterns$1(patterns);
26606      const nuText = text.replace(nbsp, ' ');
26607      return find$2(sortedPatterns, pattern => text.indexOf(pattern.start) === 0 || nuText.indexOf(pattern.start) === 0);
26608    };
26609    const findPatterns$1 = (editor, block, patternSet, normalizedMatches) => {
26610      var _a;
26611      const dom = editor.dom;
26612      const forcedRootBlock = getForcedRootBlock(editor);
26613      if (!dom.is(block, forcedRootBlock)) {
26614        return [];
26615      }
26616      const blockText = (_a = block.textContent) !== null && _a !== void 0 ? _a : '';
26617      return findPattern$1(patternSet.blockPatterns, blockText).map(pattern => {
26618        if (Tools.trim(blockText).length === pattern.start.length) {
26619          return [];
26620        }
26621        return [{
26622            pattern,
26623            range: generatePathRange(dom, dom.getRoot(), block, 0, block, 0, normalizedMatches)
26624          }];
26625      }).getOr([]);
26626    };
26627    const applyMatches$1 = (editor, matches) => {
26628      if (matches.length === 0) {
26629        return;
26630      }
26631      const bookmark = editor.selection.getBookmark();
26632      each$e(matches, match => applyPattern$1(editor, match));
26633      editor.selection.moveToBookmark(bookmark);
26634    };
26635
26636    const newMarker = (dom, id) => dom.create('span', {
26637      'data-mce-type': 'bookmark',
26638      id
26639    });
26640    const rangeFromMarker = (dom, marker) => {
26641      const rng = dom.createRng();
26642      rng.setStartAfter(marker.start);
26643      rng.setEndBefore(marker.end);
26644      return rng;
26645    };
26646    const createMarker = (dom, markerPrefix, pathRange) => {
26647      const rng = resolvePathRange(dom.getRoot(), pathRange).getOrDie('Unable to resolve path range');
26648      const startNode = rng.startContainer;
26649      const endNode = rng.endContainer;
26650      const textEnd = rng.endOffset === 0 ? endNode : endNode.splitText(rng.endOffset);
26651      const textStart = rng.startOffset === 0 ? startNode : startNode.splitText(rng.startOffset);
26652      const startParentNode = textStart.parentNode;
26653      const endParentNode = textEnd.parentNode;
26654      return {
26655        prefix: markerPrefix,
26656        end: endParentNode.insertBefore(newMarker(dom, markerPrefix + '-end'), textEnd),
26657        start: startParentNode.insertBefore(newMarker(dom, markerPrefix + '-start'), textStart)
26658      };
26659    };
26660    const removeMarker = (dom, marker, isRoot) => {
26661      cleanEmptyNodes(dom, dom.get(marker.prefix + '-end'), isRoot);
26662      cleanEmptyNodes(dom, dom.get(marker.prefix + '-start'), isRoot);
26663    };
26664
26665    const isReplacementPattern = pattern => pattern.start.length === 0;
26666    const matchesPattern = patternContent => (element, offset) => {
26667      const text = element.data;
26668      const searchText = text.substring(0, offset);
26669      const startEndIndex = searchText.lastIndexOf(patternContent.charAt(patternContent.length - 1));
26670      const startIndex = searchText.lastIndexOf(patternContent);
26671      if (startIndex !== -1) {
26672        return startIndex + patternContent.length;
26673      } else if (startEndIndex !== -1) {
26674        return startEndIndex + 1;
26675      } else {
26676        return -1;
26677      }
26678    };
26679    const findPatternStartFromSpot = (dom, pattern, block, spot) => {
26680      const startPattern = pattern.start;
26681      const startSpot = repeatLeft(dom, spot.container, spot.offset, matchesPattern(startPattern), block);
26682      return startSpot.bind(spot => {
26683        var _a, _b;
26684        const startPatternIndex = (_b = (_a = block.textContent) === null || _a === void 0 ? void 0 : _a.indexOf(startPattern)) !== null && _b !== void 0 ? _b : -1;
26685        const isCompleteMatch = startPatternIndex !== -1 && spot.offset >= startPatternIndex + startPattern.length;
26686        if (isCompleteMatch) {
26687          const rng = dom.createRng();
26688          rng.setStart(spot.container, spot.offset - startPattern.length);
26689          rng.setEnd(spot.container, spot.offset);
26690          return Optional.some(rng);
26691        } else {
26692          const offset = spot.offset - startPattern.length;
26693          return scanLeft(spot.container, offset, block).map(nextSpot => {
26694            const rng = dom.createRng();
26695            rng.setStart(nextSpot.container, nextSpot.offset);
26696            rng.setEnd(spot.container, spot.offset);
26697            return rng;
26698          }).filter(rng => rng.toString() === startPattern).orThunk(() => findPatternStartFromSpot(dom, pattern, block, point(spot.container, 0)));
26699        }
26700      });
26701    };
26702    const findPatternStart = (dom, pattern, node, offset, block, requireGap = false) => {
26703      if (pattern.start.length === 0 && !requireGap) {
26704        const rng = dom.createRng();
26705        rng.setStart(node, offset);
26706        rng.setEnd(node, offset);
26707        return Optional.some(rng);
26708      }
26709      return textBefore(node, offset, block).bind(spot => {
26710        const start = findPatternStartFromSpot(dom, pattern, block, spot);
26711        return start.bind(startRange => {
26712          var _a;
26713          if (requireGap) {
26714            if (startRange.endContainer === spot.container && startRange.endOffset === spot.offset) {
26715              return Optional.none();
26716            } else if (spot.offset === 0 && ((_a = startRange.endContainer.textContent) === null || _a === void 0 ? void 0 : _a.length) === startRange.endOffset) {
26717              return Optional.none();
26718            }
26719          }
26720          return Optional.some(startRange);
26721        });
26722      });
26723    };
26724    const findPattern = (editor, block, details, normalizedMatches) => {
26725      const dom = editor.dom;
26726      const root = dom.getRoot();
26727      const pattern = details.pattern;
26728      const endNode = details.position.container;
26729      const endOffset = details.position.offset;
26730      return scanLeft(endNode, endOffset - details.pattern.end.length, block).bind(spot => {
26731        const endPathRng = generatePathRange(dom, root, spot.container, spot.offset, endNode, endOffset, normalizedMatches);
26732        if (isReplacementPattern(pattern)) {
26733          return Optional.some({
26734            matches: [{
26735                pattern,
26736                startRng: endPathRng,
26737                endRng: endPathRng
26738              }],
26739            position: spot
26740          });
26741        } else {
26742          const resultsOpt = findPatternsRec(editor, details.remainingPatterns, spot.container, spot.offset, block, normalizedMatches);
26743          const results = resultsOpt.getOr({
26744            matches: [],
26745            position: spot
26746          });
26747          const pos = results.position;
26748          const start = findPatternStart(dom, pattern, pos.container, pos.offset, block, resultsOpt.isNone());
26749          return start.map(startRng => {
26750            const startPathRng = generatePathRangeFromRange(dom, root, startRng, normalizedMatches);
26751            return {
26752              matches: results.matches.concat([{
26753                  pattern,
26754                  startRng: startPathRng,
26755                  endRng: endPathRng
26756                }]),
26757              position: point(startRng.startContainer, startRng.startOffset)
26758            };
26759          });
26760        }
26761      });
26762    };
26763    const findPatternsRec = (editor, patterns, node, offset, block, normalizedMatches) => {
26764      const dom = editor.dom;
26765      return textBefore(node, offset, dom.getRoot()).bind(endSpot => {
26766        const text = getBeforeText(dom, block, node, offset);
26767        for (let i = 0; i < patterns.length; i++) {
26768          const pattern = patterns[i];
26769          if (!endsWith(text, pattern.end)) {
26770            continue;
26771          }
26772          const patternsWithoutCurrent = patterns.slice();
26773          patternsWithoutCurrent.splice(i, 1);
26774          const result = findPattern(editor, block, {
26775            pattern,
26776            remainingPatterns: patternsWithoutCurrent,
26777            position: endSpot
26778          }, normalizedMatches);
26779          if (result.isNone() && offset > 0) {
26780            return findPatternsRec(editor, patterns, node, offset - 1, block, normalizedMatches);
26781          }
26782          if (result.isSome()) {
26783            return result;
26784          }
26785        }
26786        return Optional.none();
26787      });
26788    };
26789    const applyPattern = (editor, pattern, patternRange) => {
26790      editor.selection.setRng(patternRange);
26791      if (pattern.type === 'inline-format') {
26792        each$e(pattern.format, format => {
26793          editor.formatter.apply(format);
26794        });
26795      } else {
26796        editor.execCommand(pattern.cmd, false, pattern.value);
26797      }
26798    };
26799    const applyReplacementPattern = (editor, pattern, marker, isRoot) => {
26800      const markerRange = rangeFromMarker(editor.dom, marker);
26801      deleteRng(editor.dom, markerRange, isRoot);
26802      applyPattern(editor, pattern, markerRange);
26803    };
26804    const applyPatternWithContent = (editor, pattern, startMarker, endMarker, isRoot) => {
26805      const dom = editor.dom;
26806      const markerEndRange = rangeFromMarker(dom, endMarker);
26807      const markerStartRange = rangeFromMarker(dom, startMarker);
26808      deleteRng(dom, markerStartRange, isRoot);
26809      deleteRng(dom, markerEndRange, isRoot);
26810      const patternMarker = {
26811        prefix: startMarker.prefix,
26812        start: startMarker.end,
26813        end: endMarker.start
26814      };
26815      const patternRange = rangeFromMarker(dom, patternMarker);
26816      applyPattern(editor, pattern, patternRange);
26817    };
26818    const addMarkers = (dom, matches) => {
26819      const markerPrefix = generate$1('mce_textpattern');
26820      const matchesWithEnds = foldr(matches, (acc, match) => {
26821        const endMarker = createMarker(dom, markerPrefix + `_end${ acc.length }`, match.endRng);
26822        return acc.concat([{
26823            ...match,
26824            endMarker
26825          }]);
26826      }, []);
26827      return foldr(matchesWithEnds, (acc, match) => {
26828        const idx = matchesWithEnds.length - acc.length - 1;
26829        const startMarker = isReplacementPattern(match.pattern) ? match.endMarker : createMarker(dom, markerPrefix + `_start${ idx }`, match.startRng);
26830        return acc.concat([{
26831            ...match,
26832            startMarker
26833          }]);
26834      }, []);
26835    };
26836    const sortPatterns = patterns => sort(patterns, (a, b) => b.end.length - a.end.length);
26837    const getBestMatches = (matches, matchesWithSortedPatterns) => {
26838      const hasSameMatches = forall(matches, match => exists(matchesWithSortedPatterns, sortedMatch => match.pattern.start === sortedMatch.pattern.start && match.pattern.end === sortedMatch.pattern.end));
26839      if (matches.length === matchesWithSortedPatterns.length) {
26840        if (hasSameMatches) {
26841          return matches;
26842        } else {
26843          return matchesWithSortedPatterns;
26844        }
26845      }
26846      return matches.length > matchesWithSortedPatterns.length ? matches : matchesWithSortedPatterns;
26847    };
26848    const findPatterns = (editor, block, node, offset, patternSet, normalizedMatches) => {
26849      const matches = findPatternsRec(editor, patternSet.inlinePatterns, node, offset, block, normalizedMatches).fold(() => [], result => result.matches);
26850      const matchesWithSortedPatterns = findPatternsRec(editor, sortPatterns(patternSet.inlinePatterns), node, offset, block, normalizedMatches).fold(() => [], result => result.matches);
26851      return getBestMatches(matches, matchesWithSortedPatterns);
26852    };
26853    const applyMatches = (editor, matches) => {
26854      if (matches.length === 0) {
26855        return;
26856      }
26857      const dom = editor.dom;
26858      const bookmark = editor.selection.getBookmark();
26859      const matchesWithMarkers = addMarkers(dom, matches);
26860      each$e(matchesWithMarkers, match => {
26861        const block = dom.getParent(match.startMarker.start, dom.isBlock);
26862        const isRoot = node => node === block;
26863        if (isReplacementPattern(match.pattern)) {
26864          applyReplacementPattern(editor, match.pattern, match.endMarker, isRoot);
26865        } else {
26866          applyPatternWithContent(editor, match.pattern, match.startMarker, match.endMarker, isRoot);
26867        }
26868        removeMarker(dom, match.endMarker, isRoot);
26869        removeMarker(dom, match.startMarker, isRoot);
26870      });
26871      editor.selection.moveToBookmark(bookmark);
26872    };
26873
26874    const handleEnter = (editor, patternSet) => {
26875      const rng = editor.selection.getRng();
26876      return getParentBlock(editor, rng).map(block => {
26877        var _a;
26878        const offset = Math.max(0, rng.startOffset);
26879        const dynamicPatternSet = resolveFromDynamicPatterns(patternSet, block, (_a = block.textContent) !== null && _a !== void 0 ? _a : '');
26880        const inlineMatches = findPatterns(editor, block, rng.startContainer, offset, dynamicPatternSet, true);
26881        const blockMatches = findPatterns$1(editor, block, dynamicPatternSet, true);
26882        if (blockMatches.length > 0 || inlineMatches.length > 0) {
26883          editor.undoManager.add();
26884          editor.undoManager.extra(() => {
26885            editor.execCommand('mceInsertNewLine');
26886          }, () => {
26887            editor.insertContent(zeroWidth);
26888            applyMatches(editor, inlineMatches);
26889            applyMatches$1(editor, blockMatches);
26890            const range = editor.selection.getRng();
26891            const spot = textBefore(range.startContainer, range.startOffset, editor.dom.getRoot());
26892            editor.execCommand('mceInsertNewLine');
26893            spot.each(s => {
26894              const node = s.container;
26895              if (node.data.charAt(s.offset - 1) === zeroWidth) {
26896                node.deleteData(s.offset - 1, 1);
26897                cleanEmptyNodes(editor.dom, node.parentNode, e => e === editor.dom.getRoot());
26898              }
26899            });
26900          });
26901          return true;
26902        }
26903        return false;
26904      }).getOr(false);
26905    };
26906    const handleInlineKey = (editor, patternSet) => {
26907      const rng = editor.selection.getRng();
26908      getParentBlock(editor, rng).map(block => {
26909        const offset = Math.max(0, rng.startOffset - 1);
26910        const beforeText = getBeforeText(editor.dom, block, rng.startContainer, offset);
26911        const dynamicPatternSet = resolveFromDynamicPatterns(patternSet, block, beforeText);
26912        const inlineMatches = findPatterns(editor, block, rng.startContainer, offset, dynamicPatternSet, false);
26913        if (inlineMatches.length > 0) {
26914          editor.undoManager.transact(() => {
26915            applyMatches(editor, inlineMatches);
26916          });
26917        }
26918      });
26919    };
26920    const checkKeyEvent = (codes, event, predicate) => {
26921      for (let i = 0; i < codes.length; i++) {
26922        if (predicate(codes[i], event)) {
26923          return true;
26924        }
26925      }
26926      return false;
26927    };
26928    const checkKeyCode = (codes, event) => checkKeyEvent(codes, event, (code, event) => {
26929      return code === event.keyCode && !VK.modifierPressed(event);
26930    });
26931    const checkCharCode = (chars, event) => checkKeyEvent(chars, event, (chr, event) => {
26932      return chr.charCodeAt(0) === event.charCode;
26933    });
26934
26935    const setup$2 = editor => {
26936      const charCodes = [
26937        ',',
26938        '.',
26939        ';',
26940        ':',
26941        '!',
26942        '?'
26943      ];
26944      const keyCodes = [32];
26945      const getPatternSet = () => createPatternSet(getTextPatterns(editor), getTextPatternsLookup(editor));
26946      const hasDynamicPatterns = () => hasTextPatternsLookup(editor);
26947      editor.on('keydown', e => {
26948        if (e.keyCode === 13 && !VK.modifierPressed(e) && editor.selection.isCollapsed()) {
26949          const patternSet = getPatternSet();
26950          const hasPatterns = patternSet.inlinePatterns.length > 0 || patternSet.blockPatterns.length > 0 || hasDynamicPatterns();
26951          if (hasPatterns && handleEnter(editor, patternSet)) {
26952            e.preventDefault();
26953          }
26954        }
26955      }, true);
26956      const handleInlineTrigger = () => {
26957        if (editor.selection.isCollapsed()) {
26958          const patternSet = getPatternSet();
26959          const hasPatterns = patternSet.inlinePatterns.length > 0 || hasDynamicPatterns();
26960          if (hasPatterns) {
26961            handleInlineKey(editor, patternSet);
26962          }
26963        }
26964      };
26965      editor.on('keyup', e => {
26966        if (checkKeyCode(keyCodes, e)) {
26967          handleInlineTrigger();
26968        }
26969      });
26970      editor.on('keypress', e => {
26971        if (checkCharCode(charCodes, e)) {
26972          Delay.setEditorTimeout(editor, handleInlineTrigger);
26973        }
26974      });
26975    };
26976
26977    const setup$1 = editor => {
26978      setup$2(editor);
26979    };
26980
26981    const Quirks = editor => {
26982      const each = Tools.each;
26983      const BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, parser = editor.parser;
26984      const browser = Env.browser;
26985      const isGecko = browser.isFirefox();
26986      const isWebKit = browser.isChromium() || browser.isSafari();
26987      const isiOS = Env.deviceType.isiPhone() || Env.deviceType.isiPad();
26988      const isMac = Env.os.isMacOS() || Env.os.isiOS();
26989      const setEditorCommandState = (cmd, state) => {
26990        try {
26991          editor.getDoc().execCommand(cmd, false, String(state));
26992        } catch (ex) {
26993        }
26994      };
26995      const isDefaultPrevented = e => {
26996        return e.isDefaultPrevented();
26997      };
26998      const emptyEditorWhenDeleting = () => {
26999        const serializeRng = rng => {
27000          const body = dom.create('body');
27001          const contents = rng.cloneContents();
27002          body.appendChild(contents);
27003          return selection.serializer.serialize(body, { format: 'html' });
27004        };
27005        const allContentsSelected = rng => {
27006          const selection = serializeRng(rng);
27007          const allRng = dom.createRng();
27008          allRng.selectNode(editor.getBody());
27009          const allSelection = serializeRng(allRng);
27010          return selection === allSelection;
27011        };
27012        editor.on('keydown', e => {
27013          const keyCode = e.keyCode;
27014          if (!isDefaultPrevented(e) && (keyCode === DELETE || keyCode === BACKSPACE) && editor.selection.isEditable()) {
27015            const isCollapsed = editor.selection.isCollapsed();
27016            const body = editor.getBody();
27017            if (isCollapsed && !dom.isEmpty(body)) {
27018              return;
27019            }
27020            if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
27021              return;
27022            }
27023            e.preventDefault();
27024            editor.setContent('');
27025            if (body.firstChild && dom.isBlock(body.firstChild)) {
27026              editor.selection.setCursorLocation(body.firstChild, 0);
27027            } else {
27028              editor.selection.setCursorLocation(body, 0);
27029            }
27030            editor.nodeChanged();
27031          }
27032        });
27033      };
27034      const selectAll = () => {
27035        editor.shortcuts.add('meta+a', null, 'SelectAll');
27036      };
27037      const documentElementEditingFocus = () => {
27038        if (!editor.inline) {
27039          dom.bind(editor.getDoc(), 'mousedown mouseup', e => {
27040            let rng;
27041            if (e.target === editor.getDoc().documentElement) {
27042              rng = selection.getRng();
27043              editor.getBody().focus();
27044              if (e.type === 'mousedown') {
27045                if (isCaretContainer$2(rng.startContainer)) {
27046                  return;
27047                }
27048                selection.placeCaretAt(e.clientX, e.clientY);
27049              } else {
27050                selection.setRng(rng);
27051              }
27052            }
27053          });
27054        }
27055      };
27056      const removeHrOnBackspace = () => {
27057        editor.on('keydown', e => {
27058          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
27059            if (!editor.getBody().getElementsByTagName('hr').length) {
27060              return;
27061            }
27062            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
27063              const node = selection.getNode();
27064              const previousSibling = node.previousSibling;
27065              if (node.nodeName === 'HR') {
27066                dom.remove(node);
27067                e.preventDefault();
27068                return;
27069              }
27070              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'hr') {
27071                dom.remove(previousSibling);
27072                e.preventDefault();
27073              }
27074            }
27075          }
27076        });
27077      };
27078      const focusBody = () => {
27079        if (!Range.prototype.getClientRects) {
27080          editor.on('mousedown', e => {
27081            if (!isDefaultPrevented(e) && e.target.nodeName === 'HTML') {
27082              const body = editor.getBody();
27083              body.blur();
27084              Delay.setEditorTimeout(editor, () => {
27085                body.focus();
27086              });
27087            }
27088          });
27089        }
27090      };
27091      const selectControlElements = () => {
27092        const visualAidsAnchorClass = getVisualAidsAnchorClass(editor);
27093        editor.on('click', e => {
27094          const target = e.target;
27095          if (/^(IMG|HR)$/.test(target.nodeName) && dom.isEditable(target.parentNode)) {
27096            e.preventDefault();
27097            editor.selection.select(target);
27098            editor.nodeChanged();
27099          }
27100          if (target.nodeName === 'A' && dom.hasClass(target, visualAidsAnchorClass) && target.childNodes.length === 0 && dom.isEditable(target.parentNode)) {
27101            e.preventDefault();
27102            selection.select(target);
27103          }
27104        });
27105      };
27106      const removeStylesWhenDeletingAcrossBlockElements = () => {
27107        const getAttributeApplyFunction = () => {
27108          const template = dom.getAttribs(selection.getStart().cloneNode(false));
27109          return () => {
27110            const target = selection.getStart();
27111            if (target !== editor.getBody()) {
27112              dom.setAttrib(target, 'style', null);
27113              each(template, attr => {
27114                target.setAttributeNode(attr.cloneNode(true));
27115              });
27116            }
27117          };
27118        };
27119        const isSelectionAcrossElements = () => {
27120          return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) !== dom.getParent(selection.getEnd(), dom.isBlock);
27121        };
27122        editor.on('keypress', e => {
27123          let applyAttributes;
27124          if (!isDefaultPrevented(e) && (e.keyCode === 8 || e.keyCode === 46) && isSelectionAcrossElements()) {
27125            applyAttributes = getAttributeApplyFunction();
27126            editor.getDoc().execCommand('delete', false);
27127            applyAttributes();
27128            e.preventDefault();
27129            return false;
27130          } else {
27131            return true;
27132          }
27133        });
27134        dom.bind(editor.getDoc(), 'cut', e => {
27135          if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
27136            const applyAttributes = getAttributeApplyFunction();
27137            Delay.setEditorTimeout(editor, () => {
27138              applyAttributes();
27139            });
27140          }
27141        });
27142      };
27143      const disableBackspaceIntoATable = () => {
27144        editor.on('keydown', e => {
27145          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
27146            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
27147              const previousSibling = selection.getNode().previousSibling;
27148              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'table') {
27149                e.preventDefault();
27150                return false;
27151              }
27152            }
27153          }
27154          return true;
27155        });
27156      };
27157      const removeBlockQuoteOnBackSpace = () => {
27158        editor.on('keydown', e => {
27159          if (isDefaultPrevented(e) || e.keyCode !== VK.BACKSPACE) {
27160            return;
27161          }
27162          let rng = selection.getRng();
27163          const container = rng.startContainer;
27164          const offset = rng.startOffset;
27165          const root = dom.getRoot();
27166          let parent = container;
27167          if (!rng.collapsed || offset !== 0) {
27168            return;
27169          }
27170          while (parent.parentNode && parent.parentNode.firstChild === parent && parent.parentNode !== root) {
27171            parent = parent.parentNode;
27172          }
27173          if (parent.nodeName === 'BLOCKQUOTE') {
27174            editor.formatter.toggle('blockquote', undefined, parent);
27175            rng = dom.createRng();
27176            rng.setStart(container, 0);
27177            rng.setEnd(container, 0);
27178            selection.setRng(rng);
27179          }
27180        });
27181      };
27182      const setGeckoEditingOptions = () => {
27183        const setOpts = () => {
27184          setEditorCommandState('StyleWithCSS', false);
27185          setEditorCommandState('enableInlineTableEditing', false);
27186          if (!getObjectResizing(editor)) {
27187            setEditorCommandState('enableObjectResizing', false);
27188          }
27189        };
27190        if (!isReadOnly$1(editor)) {
27191          editor.on('BeforeExecCommand mousedown', setOpts);
27192        }
27193      };
27194      const addBrAfterLastLinks = () => {
27195        const fixLinks = () => {
27196          each(dom.select('a:not([data-mce-block])'), node => {
27197            var _a;
27198            let parentNode = node.parentNode;
27199            const root = dom.getRoot();
27200            if ((parentNode === null || parentNode === void 0 ? void 0 : parentNode.lastChild) === node) {
27201              while (parentNode && !dom.isBlock(parentNode)) {
27202                if (((_a = parentNode.parentNode) === null || _a === void 0 ? void 0 : _a.lastChild) !== parentNode || parentNode === root) {
27203                  return;
27204                }
27205                parentNode = parentNode.parentNode;
27206              }
27207              dom.add(parentNode, 'br', { 'data-mce-bogus': 1 });
27208            }
27209          });
27210        };
27211        editor.on('SetContent ExecCommand', e => {
27212          if (e.type === 'setcontent' || e.command === 'mceInsertLink') {
27213            fixLinks();
27214          }
27215        });
27216      };
27217      const setDefaultBlockType = () => {
27218        editor.on('init', () => {
27219          setEditorCommandState('DefaultParagraphSeparator', getForcedRootBlock(editor));
27220        });
27221      };
27222      const isAllContentSelected = editor => {
27223        const body = editor.getBody();
27224        const rng = editor.selection.getRng();
27225        return rng.startContainer === rng.endContainer && rng.startContainer === body && rng.startOffset === 0 && rng.endOffset === body.childNodes.length;
27226      };
27227      const normalizeSelection = () => {
27228        editor.on('keyup focusin mouseup', e => {
27229          if (!VK.modifierPressed(e) && !isAllContentSelected(editor)) {
27230            selection.normalize();
27231          }
27232        }, true);
27233      };
27234      const showBrokenImageIcon = () => {
27235        editor.contentStyles.push('img:-moz-broken {' + '-moz-force-broken-image-icon:1;' + 'min-width:24px;' + 'min-height:24px' + '}');
27236      };
27237      const restoreFocusOnKeyDown = () => {
27238        if (!editor.inline) {
27239          editor.on('keydown', () => {
27240            if (document.activeElement === document.body) {
27241              editor.getWin().focus();
27242            }
27243          });
27244        }
27245      };
27246      const bodyHeight = () => {
27247        if (!editor.inline) {
27248          editor.contentStyles.push('body {min-height: 150px}');
27249          editor.on('click', e => {
27250            let rng;
27251            if (e.target.nodeName === 'HTML') {
27252              rng = editor.selection.getRng();
27253              editor.getBody().focus();
27254              editor.selection.setRng(rng);
27255              editor.selection.normalize();
27256              editor.nodeChanged();
27257            }
27258          });
27259        }
27260      };
27261      const blockCmdArrowNavigation = () => {
27262        if (isMac) {
27263          editor.on('keydown', e => {
27264            if (VK.metaKeyPressed(e) && !e.shiftKey && (e.keyCode === 37 || e.keyCode === 39)) {
27265              e.preventDefault();
27266              const selection = editor.selection.getSel();
27267              selection.modify('move', e.keyCode === 37 ? 'backward' : 'forward', 'lineboundary');
27268            }
27269          });
27270        }
27271      };
27272      const tapLinksAndImages = () => {
27273        editor.on('click', e => {
27274          let elm = e.target;
27275          do {
27276            if (elm.tagName === 'A') {
27277              e.preventDefault();
27278              return;
27279            }
27280          } while (elm = elm.parentNode);
27281        });
27282        editor.contentStyles.push('.mce-content-body {-webkit-touch-callout: none}');
27283      };
27284      const blockFormSubmitInsideEditor = () => {
27285        editor.on('init', () => {
27286          editor.dom.bind(editor.getBody(), 'submit', e => {
27287            e.preventDefault();
27288          });
27289        });
27290      };
27291      const removeAppleInterchangeBrs = () => {
27292        parser.addNodeFilter('br', nodes => {
27293          let i = nodes.length;
27294          while (i--) {
27295            if (nodes[i].attr('class') === 'Apple-interchange-newline') {
27296              nodes[i].remove();
27297            }
27298          }
27299        });
27300      };
27301      const refreshContentEditable = noop;
27302      const isHidden = () => {
27303        if (!isGecko || editor.removed) {
27304          return false;
27305        }
27306        const sel = editor.selection.getSel();
27307        return !sel || !sel.rangeCount || sel.rangeCount === 0;
27308      };
27309      const setupRtc = () => {
27310        if (isWebKit) {
27311          documentElementEditingFocus();
27312          selectControlElements();
27313          blockFormSubmitInsideEditor();
27314          selectAll();
27315          if (isiOS) {
27316            restoreFocusOnKeyDown();
27317            bodyHeight();
27318            tapLinksAndImages();
27319          }
27320        }
27321        if (isGecko) {
27322          focusBody();
27323          setGeckoEditingOptions();
27324          showBrokenImageIcon();
27325          blockCmdArrowNavigation();
27326        }
27327      };
27328      const 
vendor: 16,354 bytes, lines 27328-27767
27328setup = () => {
27329        removeBlockQuoteOnBackSpace();
27330        emptyEditorWhenDeleting();
27331        if (!Env.windowsPhone) {
27332          normalizeSelection();
27333        }
27334        if (isWebKit) {
27335          documentElementEditingFocus();
27336          selectControlElements();
27337          setDefaultBlockType();
27338          blockFormSubmitInsideEditor();
27339          disableBackspaceIntoATable();
27340          removeAppleInterchangeBrs();
27341          if (isiOS) {
27342            restoreFocusOnKeyDown();
27343            bodyHeight();
27344            tapLinksAndImages();
27345          } else {
27346            selectAll();
27347          }
27348        }
27349        if (isGecko) {
27350          removeHrOnBackspace();
27351          focusBody();
27352          removeStylesWhenDeletingAcrossBlockElements();
27353          setGeckoEditingOptions();
27354          addBrAfterLastLinks();
27355          showBrokenImageIcon();
27356          blockCmdArrowNavigation();
27357          disableBackspaceIntoATable();
27358        }
27359      };
27360      if (isRtc(editor)) {
27361        setupRtc();
27362      } else {
27363        setup();
27364      }
27365      return {
27366        refreshContentEditable,
27367        isHidden
27368      };
27369    };
27370
27371    const DOM$6 = DOMUtils.DOM;
27372    const appendStyle = (editor, text) => {
27373      const body = SugarElement.fromDom(editor.getBody());
27374      const container = getStyleContainer(getRootNode(body));
27375      const style = SugarElement.fromTag('style');
27376      set$3(style, 'type', 'text/css');
27377      append$1(style, SugarElement.fromText(text));
27378      append$1(container, style);
27379      editor.on('remove', () => {
27380        remove$6(style);
27381      });
27382    };
27383    const getRootName = editor => editor.inline ? editor.getElement().nodeName.toLowerCase() : undefined;
27384    const removeUndefined = obj => filter$4(obj, v => isUndefined(v) === false);
27385    const mkParserSettings = editor => {
27386      const getOption = editor.options.get;
27387      const blobCache = editor.editorUpload.blobCache;
27388      return removeUndefined({
27389        allow_conditional_comments: getOption('allow_conditional_comments'),
27390        allow_html_data_urls: getOption('allow_html_data_urls'),
27391        allow_svg_data_urls: getOption('allow_svg_data_urls'),
27392        allow_html_in_named_anchor: getOption('allow_html_in_named_anchor'),
27393        allow_script_urls: getOption('allow_script_urls'),
27394        allow_unsafe_link_target: getOption('allow_unsafe_link_target'),
27395        convert_fonts_to_spans: getOption('convert_fonts_to_spans'),
27396        fix_list_elements: getOption('fix_list_elements'),
27397        font_size_legacy_values: getOption('font_size_legacy_values'),
27398        forced_root_block: getOption('forced_root_block'),
27399        forced_root_block_attrs: getOption('forced_root_block_attrs'),
27400        preserve_cdata: getOption('preserve_cdata'),
27401        remove_trailing_brs: getOption('remove_trailing_brs'),
27402        inline_styles: getOption('inline_styles'),
27403        root_name: getRootName(editor),
27404        sanitize: getOption('xss_sanitization'),
27405        validate: true,
27406        blob_cache: blobCache,
27407        document: editor.getDoc()
27408      });
27409    };
27410    const mkSchemaSettings = editor => {
27411      const getOption = editor.options.get;
27412      return removeUndefined({
27413        custom_elements: getOption('custom_elements'),
27414        extended_valid_elements: getOption('extended_valid_elements'),
27415        invalid_elements: getOption('invalid_elements'),
27416        invalid_styles: getOption('invalid_styles'),
27417        schema: getOption('schema'),
27418        valid_children: getOption('valid_children'),
27419        valid_classes: getOption('valid_classes'),
27420        valid_elements: getOption('valid_elements'),
27421        valid_styles: getOption('valid_styles'),
27422        verify_html: getOption('verify_html'),
27423        padd_empty_block_inline_children: getOption('format_empty_lines')
27424      });
27425    };
27426    const mkSerializerSettings = editor => {
27427      const getOption = editor.options.get;
27428      return {
27429        ...mkParserSettings(editor),
27430        ...mkSchemaSettings(editor),
27431        ...removeUndefined({
27432          url_converter: getOption('url_converter'),
27433          url_converter_scope: getOption('url_converter_scope'),
27434          element_format: getOption('element_format'),
27435          entities: getOption('entities'),
27436          entity_encoding: getOption('entity_encoding'),
27437          indent: getOption('indent'),
27438          indent_after: getOption('indent_after'),
27439          indent_before: getOption('indent_before')
27440        })
27441      };
27442    };
27443    const createParser = editor => {
27444      const parser = DomParser(mkParserSettings(editor), editor.schema);
27445      parser.addAttributeFilter('src,href,style,tabindex', (nodes, name) => {
27446        const dom = editor.dom;
27447        const internalName = 'data-mce-' + name;
27448        let i = nodes.length;
27449        while (i--) {
27450          const node = nodes[i];
27451          let value = node.attr(name);
27452          if (value && !node.attr(internalName)) {
27453            if (value.indexOf('data:') === 0 || value.indexOf('blob:') === 0) {
27454              continue;
27455            }
27456            if (name === 'style') {
27457              value = dom.serializeStyle(dom.parseStyle(value), node.name);
27458              if (!value.length) {
27459                value = null;
27460              }
27461              node.attr(internalName, value);
27462              node.attr(name, value);
27463            } else if (name === 'tabindex') {
27464              node.attr(internalName, value);
27465              node.attr(name, null);
27466            } else {
27467              node.attr(internalName, editor.convertURL(value, name, node.name));
27468            }
27469          }
27470        }
27471      });
27472      parser.addNodeFilter('script', nodes => {
27473        let i = nodes.length;
27474        while (i--) {
27475          const node = nodes[i];
27476          const type = node.attr('type') || 'no/type';
27477          if (type.indexOf('mce-') !== 0) {
27478            node.attr('type', 'mce-' + type);
27479          }
27480        }
27481      });
27482      if (shouldPreserveCData(editor)) {
27483        parser.addNodeFilter('#cdata', nodes => {
27484          var _a;
27485          let i = nodes.length;
27486          while (i--) {
27487            const node = nodes[i];
27488            node.type = 8;
27489            node.name = '#comment';
27490            node.value = '[CDATA[' + editor.dom.encode((_a = node.value) !== null && _a !== void 0 ? _a : '') + ']]';
27491          }
27492        });
27493      }
27494      parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', nodes => {
27495        let i = nodes.length;
27496        const nonEmptyElements = editor.schema.getNonEmptyElements();
27497        while (i--) {
27498          const node = nodes[i];
27499          if (node.isEmpty(nonEmptyElements) && node.getAll('br').length === 0) {
27500            node.append(new AstNode('br', 1));
27501          }
27502        }
27503      });
27504      return parser;
27505    };
27506    const autoFocus = editor => {
27507      const autoFocus = getAutoFocus(editor);
27508      if (autoFocus) {
27509        Delay.setEditorTimeout(editor, () => {
27510          let focusEditor;
27511          if (autoFocus === true) {
27512            focusEditor = editor;
27513          } else {
27514            focusEditor = editor.editorManager.get(autoFocus);
27515          }
27516          if (focusEditor && !focusEditor.destroyed) {
27517            focusEditor.focus();
27518            focusEditor.selection.scrollIntoView();
27519          }
27520        }, 100);
27521      }
27522    };
27523    const moveSelectionToFirstCaretPosition = editor => {
27524      const root = editor.dom.getRoot();
27525      if (!editor.inline && (!hasAnyRanges(editor) || editor.selection.getStart(true) === root)) {
27526        firstPositionIn(root).each(pos => {
27527          const node = pos.getNode();
27528          const caretPos = isTable$2(node) ? firstPositionIn(node).getOr(pos) : pos;
27529          editor.selection.setRng(caretPos.toRange());
27530        });
27531      }
27532    };
27533    const initEditor = editor => {
27534      editor.bindPendingEventDelegates();
27535      editor.initialized = true;
27536      fireInit(editor);
27537      editor.focus(true);
27538      moveSelectionToFirstCaretPosition(editor);
27539      editor.nodeChanged({ initial: true });
27540      const initInstanceCallback = getInitInstanceCallback(editor);
27541      if (isFunction(initInstanceCallback)) {
27542        initInstanceCallback.call(editor, editor);
27543      }
27544      autoFocus(editor);
27545    };
27546    const getStyleSheetLoader$1 = editor => editor.inline ? editor.ui.styleSheetLoader : editor.dom.styleSheetLoader;
27547    const makeStylesheetLoadingPromises = (editor, css, framedFonts) => {
27548      const promises = [getStyleSheetLoader$1(editor).loadAll(css)];
27549      if (editor.inline) {
27550        return promises;
27551      } else {
27552        return promises.concat([editor.ui.styleSheetLoader.loadAll(framedFonts)]);
27553      }
27554    };
27555    const loadContentCss = editor => {
27556      const styleSheetLoader = getStyleSheetLoader$1(editor);
27557      const fontCss = getFontCss(editor);
27558      const css = editor.contentCSS;
27559      const removeCss = () => {
27560        styleSheetLoader.unloadAll(css);
27561        if (!editor.inline) {
27562          editor.ui.styleSheetLoader.unloadAll(fontCss);
27563        }
27564      };
27565      const loaded = () => {
27566        if (editor.removed) {
27567          removeCss();
27568        } else {
27569          editor.on('remove', removeCss);
27570        }
27571      };
27572      if (editor.contentStyles.length > 0) {
27573        let contentCssText = '';
27574        Tools.each(editor.contentStyles, style => {
27575          contentCssText += style + '\r\n';
27576        });
27577        editor.dom.addStyle(contentCssText);
27578      }
27579      const allStylesheets = Promise.all(makeStylesheetLoadingPromises(editor, css, fontCss)).then(loaded).catch(loaded);
27580      const contentStyle = getContentStyle(editor);
27581      if (contentStyle) {
27582        appendStyle(editor, contentStyle);
27583      }
27584      return allStylesheets;
27585    };
27586    const preInit = editor => {
27587      const doc = editor.getDoc(), body = editor.getBody();
27588      firePreInit(editor);
27589      if (!shouldBrowserSpellcheck(editor)) {
27590        doc.body.spellcheck = false;
27591        DOM$6.setAttrib(body, 'spellcheck', 'false');
27592      }
27593      editor.quirks = Quirks(editor);
27594      firePostRender(editor);
27595      const directionality = getDirectionality(editor);
27596      if (directionality !== undefined) {
27597        body.dir = directionality;
27598      }
27599      const protect = getProtect(editor);
27600      if (protect) {
27601        editor.on('BeforeSetContent', e => {
27602          Tools.each(protect, pattern => {
27603            e.content = e.content.replace(pattern, str => {
27604              return '<!--mce:protected ' + escape(str) + '-->';
27605            });
27606          });
27607        });
27608      }
27609      editor.on('SetContent', () => {
27610        editor.addVisual(editor.getBody());
27611      });
27612      editor.on('compositionstart compositionend', e => {
27613        editor.composing = e.type === 'compositionstart';
27614      });
27615    };
27616    const loadInitialContent = editor => {
27617      if (!isRtc(editor)) {
27618        editor.load({
27619          initial: true,
27620          format: 'html'
27621        });
27622      }
27623      editor.startContent = editor.getContent({ format: 'raw' });
27624    };
27625    const initEditorWithInitialContent = editor => {
27626      if (editor.removed !== true) {
27627        loadInitialContent(editor);
27628        initEditor(editor);
27629      }
27630    };
27631    const contentBodyLoaded = editor => {
27632      const targetElm = editor.getElement();
27633      let doc = editor.getDoc();
27634      if (editor.inline) {
27635        DOM$6.addClass(targetElm, 'mce-content-body');
27636        editor.contentDocument = doc = document;
27637        editor.contentWindow = window;
27638        editor.bodyElement = targetElm;
27639        editor.contentAreaContainer = targetElm;
27640      }
27641      const body = editor.getBody();
27642      body.disabled = true;
27643      editor.readonly = isReadOnly$1(editor);
27644      if (!editor.readonly) {
27645        if (editor.inline && DOM$6.getStyle(body, 'position', true) === 'static') {
27646          body.style.position = 'relative';
27647        }
27648        body.contentEditable = 'true';
27649      }
27650      body.disabled = false;
27651      editor.editorUpload = EditorUpload(editor);
27652      editor.schema = Schema(mkSchemaSettings(editor));
27653      editor.dom = DOMUtils(doc, {
27654        keep_values: true,
27655        url_converter: editor.convertURL,
27656        url_converter_scope: editor,
27657        update_styles: true,
27658        root_element: editor.inline ? editor.getBody() : null,
27659        collect: editor.inline,
27660        schema: editor.schema,
27661        contentCssCors: shouldUseContentCssCors(editor),
27662        referrerPolicy: getReferrerPolicy(editor),
27663        onSetAttrib: e => {
27664          editor.dispatch('SetAttrib', e);
27665        }
27666      });
27667      editor.parser = createParser(editor);
27668      editor.serializer = DomSerializer(mkSerializerSettings(editor), editor);
27669      editor.selection = EditorSelection(editor.dom, editor.getWin(), editor.serializer, editor);
27670      editor.annotator = Annotator(editor);
27671      editor.formatter = Formatter(editor);
27672      editor.undoManager = UndoManager(editor);
27673      editor._nodeChangeDispatcher = new NodeChange(editor);
27674      editor._selectionOverrides = SelectionOverrides(editor);
27675      setup$o(editor);
27676      setup$6(editor);
27677      setup$m(editor);
27678      if (!isRtc(editor)) {
27679        setup$5(editor);
27680        setup$1(editor);
27681      }
27682      const caret = setup$b(editor);
27683      setup$p(editor, caret);
27684      setup$n(editor);
27685      setup$q(editor);
27686      setup$7(editor);
27687      const setupRtcThunk = setup$s(editor);
27688      preInit(editor);
27689      setupRtcThunk.fold(() => {
27690        loadContentCss(editor).then(() => initEditorWithInitialContent(editor));
27691      }, setupRtc => {
27692        editor.setProgressState(true);
27693        loadContentCss(editor).then(() => {
27694          setupRtc().then(_rtcMode => {
27695            editor.setProgressState(false);
27696            initEditorWithInitialContent(editor);
27697            bindEvents(editor);
27698          }, err => {
27699            editor.notificationManager.open({
27700              type: 'error',
27701              text: String(err)
27702            });
27703            initEditorWithInitialContent(editor);
27704            bindEvents(editor);
27705          });
27706        });
27707      });
27708    };
27709
27710    const filter = always;
27711    const bind = (element, event, handler) => bind$2(element, event, filter, handler);
27712
27713    const DOM$5 = DOMUtils.DOM;
27714    const createIframeElement = (id, title, customAttrs, tabindex) => {
27715      const iframe = SugarElement.fromTag('iframe');
27716      tabindex.each(t => set$3(iframe, 'tabindex', t));
27717      setAll$1(iframe, customAttrs);
27718      setAll$1(iframe, {
27719        id: id + '_ifr',
27720        frameBorder: '0',
27721        allowTransparency: 'true',
27722        title
27723      });
27724      add$2(iframe, 'tox-edit-area__iframe');
27725      return iframe;
27726    };
27727    const getIframeHtml = editor => {
27728      let iframeHTML = getDocType(editor) + '<html><head>';
27729      if (getDocumentBaseUrl(editor) !== editor.documentBaseUrl) {
27730        iframeHTML += '<base href="' + editor.documentBaseURI.getURI() + '" />';
27731      }
27732      iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
27733      const bodyId = getBodyId(editor);
27734      const bodyClass = getBodyClass(editor);
27735      const translatedAriaText = editor.translate(getIframeAriaText(editor));
27736      if (getContentSecurityPolicy(editor)) {
27737        iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + getContentSecurityPolicy(editor) + '" />';
27738      }
27739      iframeHTML += '</head>' + `<body id="${ bodyId }" class="mce-content-body ${ bodyClass }" data-id="${ editor.id }" aria-label="${ translatedAriaText }">` + '<br>' + '</body></html>';
27740      return iframeHTML;
27741    };
27742    const createIframe = (editor, boxInfo) => {
27743      const iframeTitle = editor.translate('Rich Text Area');
27744      const tabindex = getOpt(SugarElement.fromDom(editor.getElement()), 'tabindex').bind(toInt);
27745      const ifr = createIframeElement(editor.id, iframeTitle, getIframeAttrs(editor), tabindex).dom;
27746      ifr.onload = () => {
27747        ifr.onload = null;
27748        editor.dispatch('load');
27749      };
27750      editor.contentAreaContainer = boxInfo.iframeContainer;
27751      editor.iframeElement = ifr;
27752      editor.iframeHTML = getIframeHtml(editor);
27753      DOM$5.add(boxInfo.iframeContainer, ifr);
27754    };
27755    const setupIframeBody = editor => {
27756      const iframe = editor.iframeElement;
27757      const binder = bind(SugarElement.fromDom(iframe), 'load', () => {
27758        binder.unbind();
27759        editor.contentDocument = iframe.contentDocument;
27760        contentBodyLoaded(editor);
27761      });
27762      if (Env.browser.isFirefox()) {
27763        const doc = editor.getDoc();
27764        doc.open();
27765        doc.write(editor.iframeHTML);
27766        doc.close();
27767      } else {
vendor: 10,218 bytes, lines 27767-28035
27767
27768        iframe.srcdoc = editor.iframeHTML;
27769      }
27770    };
27771    const init$1 = (editor, boxInfo) => {
27772      createIframe(editor, boxInfo);
27773      if (boxInfo.editorContainer) {
27774        boxInfo.editorContainer.style.display = editor.orgDisplay;
27775        editor.hidden = DOM$5.isHidden(boxInfo.editorContainer);
27776      }
27777      editor.getElement().style.display = 'none';
27778      DOM$5.setAttrib(editor.id, 'aria-hidden', 'true');
27779      editor.getElement().style.visibility = editor.orgVisibility;
27780      setupIframeBody(editor);
27781    };
27782
27783    const DOM$4 = DOMUtils.DOM;
27784    const initPlugin = (editor, initializedPlugins, plugin) => {
27785      const Plugin = PluginManager.get(plugin);
27786      const pluginUrl = PluginManager.urls[plugin] || editor.documentBaseUrl.replace(/\/$/, '');
27787      plugin = Tools.trim(plugin);
27788      if (Plugin && Tools.inArray(initializedPlugins, plugin) === -1) {
27789        if (editor.plugins[plugin]) {
27790          return;
27791        }
27792        try {
27793          const pluginInstance = Plugin(editor, pluginUrl) || {};
27794          editor.plugins[plugin] = pluginInstance;
27795          if (isFunction(pluginInstance.init)) {
27796            pluginInstance.init(editor, pluginUrl);
27797            initializedPlugins.push(plugin);
27798          }
27799        } catch (e) {
27800          pluginInitError(editor, plugin, e);
27801        }
27802      }
27803    };
27804    const trimLegacyPrefix = name => {
27805      return name.replace(/^\-/, '');
27806    };
27807    const initPlugins = editor => {
27808      const initializedPlugins = [];
27809      each$e(getPlugins(editor), name => {
27810        initPlugin(editor, initializedPlugins, trimLegacyPrefix(name));
27811      });
27812    };
27813    const initIcons = editor => {
27814      const iconPackName = Tools.trim(getIconPackName(editor));
27815      const currentIcons = editor.ui.registry.getAll().icons;
27816      const loadIcons = {
27817        ...IconManager.get('default').icons,
27818        ...IconManager.get(iconPackName).icons
27819      };
27820      each$d(loadIcons, (svgData, icon) => {
27821        if (!has$2(currentIcons, icon)) {
27822          editor.ui.registry.addIcon(icon, svgData);
27823        }
27824      });
27825    };
27826    const initTheme = editor => {
27827      const theme = getTheme(editor);
27828      if (isString(theme)) {
27829        const Theme = ThemeManager.get(theme);
27830        editor.theme = Theme(editor, ThemeManager.urls[theme]) || {};
27831        if (isFunction(editor.theme.init)) {
27832          editor.theme.init(editor, ThemeManager.urls[theme] || editor.documentBaseUrl.replace(/\/$/, ''));
27833        }
27834      } else {
27835        editor.theme = {};
27836      }
27837    };
27838    const initModel = editor => {
27839      const model = getModel(editor);
27840      const Model = ModelManager.get(model);
27841      editor.model = Model(editor, ModelManager.urls[model]);
27842    };
27843    const renderFromLoadedTheme = editor => {
27844      const render = editor.theme.renderUI;
27845      return render ? render() : renderThemeFalse(editor);
27846    };
27847    const renderFromThemeFunc = editor => {
27848      const elm = editor.getElement();
27849      const theme = getTheme(editor);
27850      const info = theme(editor, elm);
27851      if (info.editorContainer.nodeType) {
27852        info.editorContainer.id = info.editorContainer.id || editor.id + '_parent';
27853      }
27854      if (info.iframeContainer && info.iframeContainer.nodeType) {
27855        info.iframeContainer.id = info.iframeContainer.id || editor.id + '_iframecontainer';
27856      }
27857      info.height = info.iframeHeight ? info.iframeHeight : elm.offsetHeight;
27858      return info;
27859    };
27860    const createThemeFalseResult = (element, iframe) => {
27861      return {
27862        editorContainer: element,
27863        iframeContainer: iframe,
27864        api: {}
27865      };
27866    };
27867    const renderThemeFalseIframe = targetElement => {
27868      const iframeContainer = DOM$4.create('div');
27869      DOM$4.insertAfter(iframeContainer, targetElement);
27870      return createThemeFalseResult(iframeContainer, iframeContainer);
27871    };
27872    const renderThemeFalse = editor => {
27873      const targetElement = editor.getElement();
27874      return editor.inline ? createThemeFalseResult(null) : renderThemeFalseIframe(targetElement);
27875    };
27876    const renderThemeUi = editor => {
27877      const elm = editor.getElement();
27878      editor.orgDisplay = elm.style.display;
27879      if (isString(getTheme(editor))) {
27880        return renderFromLoadedTheme(editor);
27881      } else if (isFunction(getTheme(editor))) {
27882        return renderFromThemeFunc(editor);
27883      } else {
27884        return renderThemeFalse(editor);
27885      }
27886    };
27887    const augmentEditorUiApi = (editor, api) => {
27888      const uiApiFacade = {
27889        show: Optional.from(api.show).getOr(noop),
27890        hide: Optional.from(api.hide).getOr(noop),
27891        isEnabled: Optional.from(api.isEnabled).getOr(always),
27892        setEnabled: state => {
27893          if (!editor.mode.isReadOnly()) {
27894            Optional.from(api.setEnabled).each(f => f(state));
27895          }
27896        }
27897      };
27898      editor.ui = {
27899        ...editor.ui,
27900        ...uiApiFacade
27901      };
27902    };
27903    const init = async editor => {
27904      editor.dispatch('ScriptsLoaded');
27905      initIcons(editor);
27906      initTheme(editor);
27907      initModel(editor);
27908      initPlugins(editor);
27909      const renderInfo = await renderThemeUi(editor);
27910      augmentEditorUiApi(editor, Optional.from(renderInfo.api).getOr({}));
27911      editor.editorContainer = renderInfo.editorContainer;
27912      appendContentCssFromSettings(editor);
27913      if (editor.inline) {
27914        contentBodyLoaded(editor);
27915      } else {
27916        init$1(editor, {
27917          editorContainer: renderInfo.editorContainer,
27918          iframeContainer: renderInfo.iframeContainer
27919        });
27920      }
27921    };
27922
27923    const DOM$3 = DOMUtils.DOM;
27924    const hasSkipLoadPrefix = name => name.charAt(0) === '-';
27925    const loadLanguage = (scriptLoader, editor) => {
27926      const languageCode = getLanguageCode(editor);
27927      const languageUrl = getLanguageUrl(editor);
27928      if (!I18n.hasCode(languageCode) && languageCode !== 'en') {
27929        const url = isNotEmpty(languageUrl) ? languageUrl : `${ editor.editorManager.baseURL }/langs/${ languageCode }.js`;
27930        scriptLoader.add(url).catch(() => {
27931          languageLoadError(editor, url, languageCode);
27932        });
27933      }
27934    };
27935    const loadTheme = (editor, suffix) => {
27936      const theme = getTheme(editor);
27937      if (isString(theme) && !hasSkipLoadPrefix(theme) && !has$2(ThemeManager.urls, theme)) {
27938        const themeUrl = getThemeUrl(editor);
27939        const url = themeUrl ? editor.documentBaseURI.toAbsolute(themeUrl) : `themes/${ theme }/theme${ suffix }.js`;
27940        ThemeManager.load(theme, url).catch(() => {
27941          themeLoadError(editor, url, theme);
27942        });
27943      }
27944    };
27945    const loadModel = (editor, suffix) => {
27946      const model = getModel(editor);
27947      if (model !== 'plugin' && !has$2(ModelManager.urls, model)) {
27948        const modelUrl = getModelUrl(editor);
27949        const url = isString(modelUrl) ? editor.documentBaseURI.toAbsolute(modelUrl) : `models/${ model }/model${ suffix }.js`;
27950        ModelManager.load(model, url).catch(() => {
27951          modelLoadError(editor, url, model);
27952        });
27953      }
27954    };
27955    const getIconsUrlMetaFromUrl = editor => Optional.from(getIconsUrl(editor)).filter(isNotEmpty).map(url => ({
27956      url,
27957      name: Optional.none()
27958    }));
27959    const getIconsUrlMetaFromName = (editor, name, suffix) => Optional.from(name).filter(name => isNotEmpty(name) && !IconManager.has(name)).map(name => ({
27960      url: `${ editor.editorManager.baseURL }/icons/${ name }/icons${ suffix }.js`,
27961      name: Optional.some(name)
27962    }));
27963    const loadIcons = (scriptLoader, editor, suffix) => {
27964      const defaultIconsUrl = getIconsUrlMetaFromName(editor, 'default', suffix);
27965      const customIconsUrl = getIconsUrlMetaFromUrl(editor).orThunk(() => getIconsUrlMetaFromName(editor, getIconPackName(editor), ''));
27966      each$e(cat([
27967        defaultIconsUrl,
27968        customIconsUrl
27969      ]), urlMeta => {
27970        scriptLoader.add(urlMeta.url).catch(() => {
27971          iconsLoadError(editor, urlMeta.url, urlMeta.name.getOrUndefined());
27972        });
27973      });
27974    };
27975    const loadPlugins = (editor, suffix) => {
27976      const loadPlugin = (name, url) => {
27977        PluginManager.load(name, url).catch(() => {
27978          pluginLoadError(editor, url, name);
27979        });
27980      };
27981      each$d(getExternalPlugins$1(editor), (url, name) => {
27982        loadPlugin(name, url);
27983        editor.options.set('plugins', getPlugins(editor).concat(name));
27984      });
27985      each$e(getPlugins(editor), plugin => {
27986        plugin = Tools.trim(plugin);
27987        if (plugin && !PluginManager.urls[plugin] && !hasSkipLoadPrefix(plugin)) {
27988          loadPlugin(plugin, `plugins/${ plugin }/plugin${ suffix }.js`);
27989        }
27990      });
27991    };
27992    const isThemeLoaded = editor => {
27993      const theme = getTheme(editor);
27994      return !isString(theme) || isNonNullable(ThemeManager.get(theme));
27995    };
27996    const isModelLoaded = editor => {
27997      const model = getModel(editor);
27998      return isNonNullable(ModelManager.get(model));
27999    };
28000    const loadScripts = (editor, suffix) => {
28001      const scriptLoader = ScriptLoader.ScriptLoader;
28002      const initEditor = () => {
28003        if (!editor.removed && isThemeLoaded(editor) && isModelLoaded(editor)) {
28004          init(editor);
28005        }
28006      };
28007      loadTheme(editor, suffix);
28008      loadModel(editor, suffix);
28009      loadLanguage(scriptLoader, editor);
28010      loadIcons(scriptLoader, editor, suffix);
28011      loadPlugins(editor, suffix);
28012      scriptLoader.loadQueue().then(initEditor, initEditor);
28013    };
28014    const getStyleSheetLoader = (element, editor) => instance.forElement(element, {
28015      contentCssCors: hasContentCssCors(editor),
28016      referrerPolicy: getReferrerPolicy(editor)
28017    });
28018    const render = editor => {
28019      const id = editor.id;
28020      I18n.setCode(getLanguageCode(editor));
28021      const readyHandler = () => {
28022        DOM$3.unbind(window, 'ready', readyHandler);
28023        editor.render();
28024      };
28025      if (!EventUtils.Event.domLoaded) {
28026        DOM$3.bind(window, 'ready', readyHandler);
28027        return;
28028      }
28029      if (!editor.getElement()) {
28030        return;
28031      }
28032      const element = SugarElement.fromDom(editor.getElement());
28033      const snapshot = clone$4(element);
28034      editor.on('remove', () => {
28035        eachr(element.dom.attributes, attr => remove$
vendor: 3,848 bytes, lines 28035-28141
28035b(element, attr.name));
28036        setAll$1(element, snapshot);
28037      });
28038      editor.ui.styleSheetLoader = getStyleSheetLoader(element, editor);
28039      if (!isInline(editor)) {
28040        editor.orgVisibility = editor.getElement().style.visibility;
28041        editor.getElement().style.visibility = 'hidden';
28042      } else {
28043        editor.inline = true;
28044      }
28045      const form = editor.getElement().form || DOM$3.getParent(id, 'form');
28046      if (form) {
28047        editor.formElement = form;
28048        if (hasHiddenInput(editor) && !isTextareaOrInput(editor.getElement())) {
28049          DOM$3.insertAfter(DOM$3.create('input', {
28050            type: 'hidden',
28051            name: id
28052          }), id);
28053          editor.hasHiddenInput = true;
28054        }
28055        editor.formEventDelegate = e => {
28056          editor.dispatch(e.type, e);
28057        };
28058        DOM$3.bind(form, 'submit reset', editor.formEventDelegate);
28059        editor.on('reset', () => {
28060          editor.resetContent();
28061        });
28062        if (shouldPatchSubmit(editor) && !form.submit.nodeType && !form.submit.length && !form._mceOldSubmit) {
28063          form._mceOldSubmit = form.submit;
28064          form.submit = () => {
28065            editor.editorManager.triggerSave();
28066            editor.setDirty(false);
28067            return form._mceOldSubmit(form);
28068          };
28069        }
28070      }
28071      editor.windowManager = WindowManager(editor);
28072      editor.notificationManager = NotificationManager(editor);
28073      if (isEncodingXml(editor)) {
28074        editor.on('GetContent', e => {
28075          if (e.save) {
28076            e.content = DOM$3.encode(e.content);
28077          }
28078        });
28079      }
28080      if (shouldAddFormSubmitTrigger(editor)) {
28081        editor.on('submit', () => {
28082          if (editor.initialized) {
28083            editor.save();
28084          }
28085        });
28086      }
28087      if (shouldAddUnloadTrigger(editor)) {
28088        editor._beforeUnload = () => {
28089          if (editor.initialized && !editor.destroyed && !editor.isHidden()) {
28090            editor.save({
28091              format: 'raw',
28092              no_events: true,
28093              set_dirty: false
28094            });
28095          }
28096        };
28097        editor.editorManager.on('BeforeUnload', editor._beforeUnload);
28098      }
28099      editor.editorManager.add(editor);
28100      loadScripts(editor, editor.suffix);
28101    };
28102
28103    const sectionResult = (sections, settings) => ({
28104      sections: constant(sections),
28105      options: constant(settings)
28106    });
28107    const deviceDetection = detect$2().deviceType;
28108    const isPhone = deviceDetection.isPhone();
28109    const isTablet = deviceDetection.isTablet();
28110    const normalizePlugins = plugins => {
28111      if (isNullable(plugins)) {
28112        return [];
28113      } else {
28114        const pluginNames = isArray$1(plugins) ? plugins : plugins.split(/[ ,]/);
28115        const trimmedPlugins = map$3(pluginNames, trim$3);
28116        return filter$5(trimmedPlugins, isNotEmpty);
28117      }
28118    };
28119    const extractSections = (keys, options) => {
28120      const result = bifilter(options, (value, key) => {
28121        return contains$2(keys, key);
28122      });
28123      return sectionResult(result.t, result.f);
28124    };
28125    const getSection = (sectionResult, name, defaults = {}) => {
28126      const sections = sectionResult.sections();
28127      const sectionOptions = get$a(sections, name).getOr({});
28128      return Tools.extend({}, defaults, sectionOptions);
28129    };
28130    const hasSection = (sectionResult, name) => {
28131      return has$2(sectionResult.sections(), name);
28132    };
28133    const getSectionConfig = (sectionResult, name) => {
28134      return hasSection(sectionResult, name) ? sectionResult.sections()[name] : {};
28135    };
28136    const getMobileOverrideOptions = (mobileOptions, isPhone) => {
28137      const defaultMobileOptions = {
28138        table_grid: false,
28139        object_resizing: false,
28140        resize: false,
28141        toolbar_mode: get$a(mobileOptions, 'toolbar_mode').getOr('scrolling'),
vendor: 8,312 bytes, lines 28142-28350
28142        toolbar_sticky: false
28143      };
28144      const defaultPhoneOptions = { menubar: false };
28145      return {
28146        ...defaultMobileOptions,
28147        ...isPhone ? defaultPhoneOptions : {}
28148      };
28149    };
28150    const getExternalPlugins = (overrideOptions, options) => {
28151      var _a;
28152      const userDefinedExternalPlugins = (_a = options.external_plugins) !== null && _a !== void 0 ? _a : {};
28153      if (overrideOptions && overrideOptions.external_plugins) {
28154        return Tools.extend({}, overrideOptions.external_plugins, userDefinedExternalPlugins);
28155      } else {
28156        return userDefinedExternalPlugins;
28157      }
28158    };
28159    const combinePlugins = (forcedPlugins, plugins) => [
28160      ...normalizePlugins(forcedPlugins),
28161      ...normalizePlugins(plugins)
28162    ];
28163    const getPlatformPlugins = (isMobileDevice, sectionResult, desktopPlugins, mobilePlugins) => {
28164      if (isMobileDevice && hasSection(sectionResult, 'mobile')) {
28165        return mobilePlugins;
28166      } else {
28167        return desktopPlugins;
28168      }
28169    };
28170    const processPlugins = (isMobileDevice, sectionResult, defaultOverrideOptions, options) => {
28171      const forcedPlugins = normalizePlugins(defaultOverrideOptions.forced_plugins);
28172      const desktopPlugins = normalizePlugins(options.plugins);
28173      const mobileConfig = getSectionConfig(sectionResult, 'mobile');
28174      const mobilePlugins = mobileConfig.plugins ? normalizePlugins(mobileConfig.plugins) : desktopPlugins;
28175      const platformPlugins = getPlatformPlugins(isMobileDevice, sectionResult, desktopPlugins, mobilePlugins);
28176      const combinedPlugins = combinePlugins(forcedPlugins, platformPlugins);
28177      return Tools.extend(options, {
28178        forced_plugins: forcedPlugins,
28179        plugins: combinedPlugins
28180      });
28181    };
28182    const isOnMobile = (isMobileDevice, sectionResult) => {
28183      return isMobileDevice && hasSection(sectionResult, 'mobile');
28184    };
28185    const combineOptions = (isMobileDevice, isPhone, defaultOptions, defaultOverrideOptions, options) => {
28186      var _a;
28187      const deviceOverrideOptions = isMobileDevice ? { mobile: getMobileOverrideOptions((_a = options.mobile) !== null && _a !== void 0 ? _a : {}, isPhone) } : {};
28188      const sectionResult = extractSections(['mobile'], deepMerge(deviceOverrideOptions, options));
28189      const extendedOptions = Tools.extend(defaultOptions, defaultOverrideOptions, sectionResult.options(), isOnMobile(isMobileDevice, sectionResult) ? getSection(sectionResult, 'mobile') : {}, { external_plugins: getExternalPlugins(defaultOverrideOptions, sectionResult.options()) });
28190      return processPlugins(isMobileDevice, sectionResult, defaultOverrideOptions, extendedOptions);
28191    };
28192    const normalizeOptions = (defaultOverrideOptions, options) => combineOptions(isPhone || isTablet, isPhone, options, defaultOverrideOptions, options);
28193
28194    const addVisual = (editor, elm) => addVisual$1(editor, elm);
28195
28196    const registerExecCommands$3 = editor => {
28197      const toggleFormat = (name, value) => {
28198        editor.formatter.toggle(name, value);
28199        editor.nodeChanged();
28200      };
28201      const toggleAlign = align => () => {
28202        each$e('left,center,right,justify'.split(','), name => {
28203          if (align !== name) {
28204            editor.formatter.remove('align' + name);
28205          }
28206        });
28207        if (align !== 'none') {
28208          toggleFormat('align' + align);
28209        }
28210      };
28211      editor.editorCommands.addCommands({
28212        JustifyLeft: toggleAlign('left'),
28213        JustifyCenter: toggleAlign('center'),
28214        JustifyRight: toggleAlign('right'),
28215        JustifyFull: toggleAlign('justify'),
28216        JustifyNone: toggleAlign('none')
28217      });
28218    };
28219    const registerQueryStateCommands$1 = editor => {
28220      const alignStates = name => () => {
28221        const selection = editor.selection;
28222        const nodes = selection.isCollapsed() ? [editor.dom.getParent(selection.getNode(), editor.dom.isBlock)] : selection.getSelectedBlocks();
28223        return exists(nodes, node => isNonNullable(editor.formatter.matchNode(node, name)));
28224      };
28225      editor.editorCommands.addCommands({
28226        JustifyLeft: alignStates('alignleft'),
28227        JustifyCenter: alignStates('aligncenter'),
28228        JustifyRight: alignStates('alignright'),
28229        JustifyFull: alignStates('alignjustify')
28230      }, 'state');
28231    };
28232    const registerCommands$a = editor => {
28233      registerExecCommands$3(editor);
28234      registerQueryStateCommands$1(editor);
28235    };
28236
28237    const registerCommands$9 = editor => {
28238      editor.editorCommands.addCommands({
28239        'Cut,Copy,Paste': command => {
28240          const doc = editor.getDoc();
28241          let failed;
28242          try {
28243            doc.execCommand(command);
28244          } catch (ex) {
28245            failed = true;
28246          }
28247          if (command === 'paste' && !doc.queryCommandEnabled(command)) {
28248            failed = true;
28249          }
28250          if (failed || !doc.queryCommandSupported(command)) {
28251            let msg = editor.translate(`Your browser doesn't support direct access to the clipboard. ` + 'Please use the Ctrl+X/C/V keyboard shortcuts instead.');
28252            if (Env.os.isMacOS() || Env.os.isiOS()) {
28253              msg = msg.replace(/Ctrl\+/g, '\u2318+');
28254            }
28255            editor.notificationManager.open({
28256              text: msg,
28257              type: 'error'
28258            });
28259          }
28260        }
28261      });
28262    };
28263
28264    const trimOrPadLeftRight = (dom, rng, html) => {
28265      const root = SugarElement.fromDom(dom.getRoot());
28266      if (needsToBeNbspLeft(root, CaretPosition.fromRangeStart(rng))) {
28267        html = html.replace(/^ /, '&nbsp;');
28268      } else {
28269        html = html.replace(/^&nbsp;/, ' ');
28270      }
28271      if (needsToBeNbspRight(root, CaretPosition.fromRangeEnd(rng))) {
28272        html = html.replace(/(&nbsp;| )(<br( \/)>)?$/, '&nbsp;');
28273      } else {
28274        html = html.replace(/&nbsp;(<br( \/)?>)?$/, ' ');
28275      }
28276      return html;
28277    };
28278
28279    const processValue$1 = value => {
28280      if (typeof value !== 'string') {
28281        const details = Tools.extend({
28282          paste: value.paste,
28283          data: { paste: value.paste }
28284        }, value);
28285        return {
28286          content: value.content,
28287          details
28288        };
28289      }
28290      return {
28291        content: value,
28292        details: {}
28293      };
28294    };
28295    const trimOrPad = (editor, value) => {
28296      const selection = editor.selection;
28297      const dom = editor.dom;
28298      if (/^ | $/.test(value)) {
28299        return trimOrPadLeftRight(dom, selection.getRng(), value);
28300      } else {
28301        return value;
28302      }
28303    };
28304    const insertAtCaret = (editor, value) => {
28305      if (editor.selection.isEditable()) {
28306        const {content, details} = processValue$1(value);
28307        preProcessSetContent(editor, {
28308          ...details,
28309          content: trimOrPad(editor, content),
28310          format: 'html',
28311          set: false,
28312          selection: true
28313        }).each(args => {
28314          const insertedContent = insertContent$1(editor, args.content, details);
28315          postProcessSetContent(editor, insertedContent, args);
28316          editor.addVisual();
28317        });
28318      }
28319    };
28320
28321    const registerCommands$8 = editor => {
28322      editor.editorCommands.addCommands({
28323        mceCleanup: () => {
28324          const bm = editor.selection.getBookmark();
28325          editor.setContent(editor.getContent());
28326          editor.selection.moveToBookmark(bm);
28327        },
28328        insertImage: (_command, _ui, value) => {
28329          insertAtCaret(editor, editor.dom.createHTML('img', { src: value }));
28330        },
28331        insertHorizontalRule: () => {
28332          editor.execCommand('mceInsertContent', false, '<hr>');
28333        },
28334        insertText: (_command, _ui, value) => {
28335          insertAtCaret(editor, editor.dom.encode(value));
28336        },
28337        insertHTML: (_command, _ui, value) => {
28338          insertAtCaret(editor, value);
28339        },
28340        mceInsertContent: (_command, _ui, value) => {
28341          insertAtCaret(editor, value);
28342        },
28343        mceSetContent: (_command, _ui, value) => {
28344          editor.setContent(value);
28345        },
28346        mceReplaceContent: (_command, _ui, value) => {
28347          editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, editor.selection.getContent({ format: 'text' })));
28348        },
28349        mceNewDocument: () => {
28350          editor.setContent(''
vendor: 7,989 bytes, lines 28350-28549
28350);
28351        }
28352      });
28353    };
28354
28355    const legacyPropNames = {
28356      'font-size': 'size',
28357      'font-family': 'face'
28358    };
28359    const isFont = isTag('font');
28360    const getSpecifiedFontProp = (propName, rootElm, elm) => {
28361      const getProperty = elm => getRaw(elm, propName).orThunk(() => {
28362        if (isFont(elm)) {
28363          return get$a(legacyPropNames, propName).bind(legacyPropName => getOpt(elm, legacyPropName));
28364        } else {
28365          return Optional.none();
28366        }
28367      });
28368      const isRoot = elm => eq(SugarElement.fromDom(rootElm), elm);
28369      return closest$1(SugarElement.fromDom(elm), elm => getProperty(elm), isRoot);
28370    };
28371    const normalizeFontFamily = fontFamily => fontFamily.replace(/[\'\"\\]/g, '').replace(/,\s+/g, ',');
28372    const getComputedFontProp = (propName, elm) => Optional.from(DOMUtils.DOM.getStyle(elm, propName, true));
28373    const getFontProp = propName => (rootElm, elm) => Optional.from(elm).map(SugarElement.fromDom).filter(isElement$7).bind(element => getSpecifiedFontProp(propName, rootElm, element.dom).or(getComputedFontProp(propName, element.dom))).getOr('');
28374    const getFontSize = getFontProp('font-size');
28375    const getFontFamily = compose(normalizeFontFamily, getFontProp('font-family'));
28376
28377    const findFirstCaretElement = editor => firstPositionIn(editor.getBody()).bind(caret => {
28378      const container = caret.container();
28379      return Optional.from(isText$a(container) ? container.parentNode : container);
28380    });
28381    const getCaretElement = editor => Optional.from(editor.selection.getRng()).bind(rng => {
28382      const root = editor.getBody();
28383      const atStartOfNode = rng.startContainer === root && rng.startOffset === 0;
28384      return atStartOfNode ? Optional.none() : Optional.from(editor.selection.getStart(true));
28385    });
28386    const bindRange = (editor, binder) => getCaretElement(editor).orThunk(curry(findFirstCaretElement, editor)).map(SugarElement.fromDom).filter(isElement$7).bind(binder);
28387    const mapRange = (editor, mapper) => bindRange(editor, compose1(Optional.some, mapper));
28388
28389    const fromFontSizeNumber = (editor, value) => {
28390      if (/^[0-9.]+$/.test(value)) {
28391        const fontSizeNumber = parseInt(value, 10);
28392        if (fontSizeNumber >= 1 && fontSizeNumber <= 7) {
28393          const fontSizes = getFontStyleValues(editor);
28394          const fontClasses = getFontSizeClasses(editor);
28395          if (fontClasses.length > 0) {
28396            return fontClasses[fontSizeNumber - 1] || value;
28397          } else {
28398            return fontSizes[fontSizeNumber - 1] || value;
28399          }
28400        } else {
28401          return value;
28402        }
28403      } else {
28404        return value;
28405      }
28406    };
28407    const normalizeFontNames = font => {
28408      const fonts = font.split(/\s*,\s*/);
28409      return map$3(fonts, font => {
28410        if (font.indexOf(' ') !== -1 && !(startsWith(font, '"') || startsWith(font, `'`))) {
28411          return `'${ font }'`;
28412        } else {
28413          return font;
28414        }
28415      }).join(',');
28416    };
28417    const fontNameAction = (editor, value) => {
28418      const font = fromFontSizeNumber(editor, value);
28419      editor.formatter.toggle('fontname', { value: normalizeFontNames(font) });
28420      editor.nodeChanged();
28421    };
28422    const fontNameQuery = editor => mapRange(editor, elm => getFontFamily(editor.getBody(), elm.dom)).getOr('');
28423    const fontSizeAction = (editor, value) => {
28424      editor.formatter.toggle('fontsize', { value: fromFontSizeNumber(editor, value) });
28425      editor.nodeChanged();
28426    };
28427    const fontSizeQuery = editor => mapRange(editor, elm => getFontSize(editor.getBody(), elm.dom)).getOr('');
28428
28429    const lineHeightQuery = editor => mapRange(editor, elm => {
28430      const root = SugarElement.fromDom(editor.getBody());
28431      const specifiedStyle = closest$1(elm, elm => getRaw(elm, 'line-height'), curry(eq, root));
28432      const computedStyle = () => {
28433        const lineHeight = parseFloat(get$7(elm, 'line-height'));
28434        const fontSize = parseFloat(get$7(elm, 'font-size'));
28435        return String(lineHeight / fontSize);
28436      };
28437      return specifiedStyle.getOrThunk(computedStyle);
28438    }).getOr('');
28439    const lineHeightAction = (editor, lineHeight) => {
28440      editor.formatter.toggle('lineheight', { value: String(lineHeight) });
28441      editor.nodeChanged();
28442    };
28443
28444    const registerExecCommands$2 = editor => {
28445      const toggleFormat = (name, value) => {
28446        editor.formatter.toggle(name, value);
28447        editor.nodeChanged();
28448      };
28449      editor.editorCommands.addCommands({
28450        'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': command => {
28451          toggleFormat(command);
28452        },
28453        'ForeColor,HiliteColor': (command, _ui, value) => {
28454          toggleFormat(command, { value });
28455        },
28456        'BackColor': (_command, _ui, value) => {
28457          toggleFormat('hilitecolor', { value });
28458        },
28459        'FontName': (_command, _ui, value) => {
28460          fontNameAction(editor, value);
28461        },
28462        'FontSize': (_command, _ui, value) => {
28463          fontSizeAction(editor, value);
28464        },
28465        'LineHeight': (_command, _ui, value) => {
28466          lineHeightAction(editor, value);
28467        },
28468        'Lang': (command, _ui, lang) => {
28469          var _a;
28470          toggleFormat(command, {
28471            value: lang.code,
28472            customValue: (_a = lang.customCode) !== null && _a !== void 0 ? _a : null
28473          });
28474        },
28475        'RemoveFormat': command => {
28476          editor.formatter.remove(command);
28477        },
28478        'mceBlockQuote': () => {
28479          toggleFormat('blockquote');
28480        },
28481        'FormatBlock': (_command, _ui, value) => {
28482          toggleFormat(isString(value) ? value : 'p');
28483        },
28484        'mceToggleFormat': (_command, _ui, value) => {
28485          toggleFormat(value);
28486        }
28487      });
28488    };
28489    const registerQueryValueCommands = editor => {
28490      const isFormatMatch = name => editor.formatter.match(name);
28491      editor.editorCommands.addCommands({
28492        'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': command => isFormatMatch(command),
28493        'mceBlockQuote': () => isFormatMatch('blockquote')
28494      }, 'state');
28495      editor.editorCommands.addQueryValueHandler('FontName', () => fontNameQuery(editor));
28496      editor.editorCommands.addQueryValueHandler('FontSize', () => fontSizeQuery(editor));
28497      editor.editorCommands.addQueryValueHandler('LineHeight', () => lineHeightQuery(editor));
28498    };
28499    const registerCommands$7 = editor => {
28500      registerExecCommands$2(editor);
28501      registerQueryValueCommands(editor);
28502    };
28503
28504    const registerCommands$6 = editor => {
28505      editor.editorCommands.addCommands({
28506        mceAddUndoLevel: () => {
28507          editor.undoManager.add();
28508        },
28509        mceEndUndoLevel: () => {
28510          editor.undoManager.add();
28511        },
28512        Undo: () => {
28513          editor.undoManager.undo();
28514        },
28515        Redo: () => {
28516          editor.undoManager.redo();
28517        }
28518      });
28519    };
28520
28521    const registerCommands$5 = editor => {
28522      editor.editorCommands.addCommands({
28523        Indent: () => {
28524          indent(editor);
28525        },
28526        Outdent: () => {
28527          outdent(editor);
28528        }
28529      });
28530      editor.editorCommands.addCommands({ Outdent: () => canOutdent(editor) }, 'state');
28531    };
28532
28533    const registerCommands$4 = editor => {
28534      const applyLinkToSelection = (_command, _ui, value) => {
28535        const linkDetails = isString(value) ? { href: value } : value;
28536        const anchor = editor.dom.getParent(editor.selection.getNode(), 'a');
28537        if (isObject(linkDetails) && isString(linkDetails.href)) {
28538          linkDetails.href = linkDetails.href.replace(/ /g, '%20');
28539          if (!anchor || !linkDetails.href) {
28540            editor.formatter.remove('link');
28541          }
28542          if (linkDetails.href) {
28543            editor.formatter.apply('link', linkDetails, anchor);
28544          }
28545        }
28546      };
28547      editor.editorCommands.addCommands({
28548        unlink: () => {
28549          if (editor.selection.is
vendor: 3,364 bytes, lines 28549-28643
28549Collapsed()) {
28550            const elm = editor.dom.getParent(editor.selection.getStart(), 'a');
28551            if (elm) {
28552              editor.dom.remove(elm, true);
28553            }
28554            return;
28555          }
28556          editor.formatter.remove('link');
28557        },
28558        mceInsertLink: applyLinkToSelection,
28559        createLink: applyLinkToSelection
28560      });
28561    };
28562
28563    const registerExecCommands$1 = editor => {
28564      editor.editorCommands.addCommands({
28565        'InsertUnorderedList,InsertOrderedList': command => {
28566          editor.getDoc().execCommand(command);
28567          const listElm = editor.dom.getParent(editor.selection.getNode(), 'ol,ul');
28568          if (listElm) {
28569            const listParent = listElm.parentNode;
28570            if (listParent && /^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) {
28571              const bm = editor.selection.getBookmark();
28572              editor.dom.split(listParent, listElm);
28573              editor.selection.moveToBookmark(bm);
28574            }
28575          }
28576        }
28577      });
28578    };
28579    const registerQueryStateCommands = editor => {
28580      editor.editorCommands.addCommands({
28581        'InsertUnorderedList,InsertOrderedList': command => {
28582          const list = editor.dom.getParent(editor.selection.getNode(), 'ul,ol');
28583          return list && (command === 'insertunorderedlist' && list.tagName === 'UL' || command === 'insertorderedlist' && list.tagName === 'OL');
28584        }
28585      }, 'state');
28586    };
28587    const registerCommands$3 = editor => {
28588      registerExecCommands$1(editor);
28589      registerQueryStateCommands(editor);
28590    };
28591
28592    const registerCommands$2 = editor => {
28593      editor.editorCommands.addCommands({
28594        insertParagraph: () => {
28595          insertBreak(blockbreak, editor);
28596        },
28597        mceInsertNewLine: (_command, _ui, value) => {
28598          insert(editor, value);
28599        },
28600        InsertLineBreak: (_command, _ui, _value) => {
28601          insertBreak(linebreak, editor);
28602        }
28603      });
28604    };
28605
28606    const registerCommands$1 = editor => {
28607      editor.editorCommands.addCommands({
28608        mceSelectNodeDepth: (_command, _ui, value) => {
28609          let counter = 0;
28610          editor.dom.getParent(editor.selection.getNode(), node => {
28611            if (isElement$6(node) && counter++ === value) {
28612              editor.selection.select(node);
28613              return false;
28614            } else {
28615              return true;
28616            }
28617          }, editor.getBody());
28618        },
28619        mceSelectNode: (_command, _ui, value) => {
28620          editor.selection.select(value);
28621        },
28622        selectAll: () => {
28623          const editingHost = editor.dom.getParent(editor.selection.getStart(), isContentEditableTrue$3);
28624          if (editingHost) {
28625            const rng = editor.dom.createRng();
28626            rng.selectNodeContents(editingHost);
28627            editor.selection.setRng(rng);
28628          }
28629        }
28630      });
28631    };
28632
28633    const registerExecCommands = editor => {
28634      editor.editorCommands.addCommands({
28635        mceRemoveNode: (_command, _ui, value) => {
28636          const node = value !== null && value !== void 0 ? value : editor.selection.getNode();
28637          if (node !== editor.getBody()) {
28638            const bm = editor.selection.getBookmark();
28639            editor.dom.remove(node, true);
28640            editor.selection.moveToBookmark(bm);
28641          }
28642        },
28643        mcePrint: () => {
vendor: 8,603 bytes, lines 28644-28883
28644          editor.getWin().print();
28645        },
28646        mceFocus: (_command, _ui, value) => {
28647          focus(editor, value === true);
28648        },
28649        mceToggleVisualAid: () => {
28650          editor.hasVisual = !editor.hasVisual;
28651          editor.addVisual();
28652        }
28653      });
28654    };
28655    const registerCommands = editor => {
28656      registerCommands$a(editor);
28657      registerCommands$9(editor);
28658      registerCommands$6(editor);
28659      registerCommands$1(editor);
28660      registerCommands$8(editor);
28661      registerCommands$4(editor);
28662      registerCommands$5(editor);
28663      registerCommands$2(editor);
28664      registerCommands$3(editor);
28665      registerCommands$7(editor);
28666      registerExecCommands(editor);
28667    };
28668
28669    const selectionSafeCommands = ['toggleview'];
28670    const isSelectionSafeCommand = command => contains$2(selectionSafeCommands, command.toLowerCase());
28671    class EditorCommands {
28672      constructor(editor) {
28673        this.commands = {
28674          state: {},
28675          exec: {},
28676          value: {}
28677        };
28678        this.editor = editor;
28679      }
28680      execCommand(command, ui = false, value, args) {
28681        const editor = this.editor;
28682        const lowerCaseCommand = command.toLowerCase();
28683        const skipFocus = args === null || args === void 0 ? void 0 : args.skip_focus;
28684        if (editor.removed) {
28685          return false;
28686        }
28687        if (lowerCaseCommand !== 'mcefocus') {
28688          if (!/^(mceAddUndoLevel|mceEndUndoLevel)$/i.test(lowerCaseCommand) && !skipFocus) {
28689            editor.focus();
28690          } else {
28691            restore(editor);
28692          }
28693        }
28694        const eventArgs = editor.dispatch('BeforeExecCommand', {
28695          command,
28696          ui,
28697          value
28698        });
28699        if (eventArgs.isDefaultPrevented()) {
28700          return false;
28701        }
28702        const func = this.commands.exec[lowerCaseCommand];
28703        if (isFunction(func)) {
28704          func(lowerCaseCommand, ui, value);
28705          editor.dispatch('ExecCommand', {
28706            command,
28707            ui,
28708            value
28709          });
28710          return true;
28711        }
28712        return false;
28713      }
28714      queryCommandState(command) {
28715        if (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden() || this.editor.removed) {
28716          return false;
28717        }
28718        const lowerCaseCommand = command.toLowerCase();
28719        const func = this.commands.state[lowerCaseCommand];
28720        if (isFunction(func)) {
28721          return func(lowerCaseCommand);
28722        }
28723        return false;
28724      }
28725      queryCommandValue(command) {
28726        if (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden() || this.editor.removed) {
28727          return '';
28728        }
28729        const lowerCaseCommand = command.toLowerCase();
28730        const func = this.commands.value[lowerCaseCommand];
28731        if (isFunction(func)) {
28732          return func(lowerCaseCommand);
28733        }
28734        return '';
28735      }
28736      addCommands(commandList, type = 'exec') {
28737        const commands = this.commands;
28738        each$d(commandList, (callback, command) => {
28739          each$e(command.toLowerCase().split(','), command => {
28740            commands[type][command] = callback;
28741          });
28742        });
28743      }
28744      addCommand(command, callback, scope) {
28745        const lowerCaseCommand = command.toLowerCase();
28746        this.commands.exec[lowerCaseCommand] = (_command, ui, value) => callback.call(scope !== null && scope !== void 0 ? scope : this.editor, ui, value);
28747      }
28748      queryCommandSupported(command) {
28749        const lowerCaseCommand = command.toLowerCase();
28750        if (this.commands.exec[lowerCaseCommand]) {
28751          return true;
28752        } else {
28753          return false;
28754        }
28755      }
28756      addQueryStateHandler(command, callback, scope) {
28757        this.commands.state[command.toLowerCase()] = () => callback.call(scope !== null && scope !== void 0 ? scope : this.editor);
28758      }
28759      addQueryValueHandler(command, callback, scope) {
28760        this.commands.value[command.toLowerCase()] = () => callback.call(scope !== null && scope !== void 0 ? scope : this.editor);
28761      }
28762    }
28763
28764    const internalContentEditableAttr = 'data-mce-contenteditable';
28765    const toggleClass = (elm, cls, state) => {
28766      if (has(elm, cls) && !state) {
28767        remove$8(elm, cls);
28768      } else if (state) {
28769        add$2(elm, cls);
28770      }
28771    };
28772    const setEditorCommandState = (editor, cmd, state) => {
28773      try {
28774        editor.getDoc().execCommand(cmd, false, String(state));
28775      } catch (ex) {
28776      }
28777    };
28778    const setContentEditable = (elm, state) => {
28779      elm.dom.contentEditable = state ? 'true' : 'false';
28780    };
28781    const switchOffContentEditableTrue = elm => {
28782      each$e(descendants(elm, '*[contenteditable="true"]'), elm => {
28783        set$3(elm, internalContentEditableAttr, 'true');
28784        setContentEditable(elm, false);
28785      });
28786    };
28787    const switchOnContentEditableTrue = elm => {
28788      each$e(descendants(elm, `*[${ internalContentEditableAttr }="true"]`), elm => {
28789        remove$b(elm, internalContentEditableAttr);
28790        setContentEditable(elm, true);
28791      });
28792    };
28793    const removeFakeSelection = editor => {
28794      Optional.from(editor.selection.getNode()).each(elm => {
28795        elm.removeAttribute('data-mce-selected');
28796      });
28797    };
28798    const restoreFakeSelection = editor => {
28799      editor.selection.setRng(editor.selection.getRng());
28800    };
28801    const toggleReadOnly = (editor, state) => {
28802      const body = SugarElement.fromDom(editor.getBody());
28803      toggleClass(body, 'mce-content-readonly', state);
28804      if (state) {
28805        editor.selection.controlSelection.hideResizeRect();
28806        editor._selectionOverrides.hideFakeCaret();
28807        removeFakeSelection(editor);
28808        editor.readonly = true;
28809        setContentEditable(body, false);
28810        switchOffContentEditableTrue(body);
28811      } else {
28812        editor.readonly = false;
28813        setContentEditable(body, true);
28814        switchOnContentEditableTrue(body);
28815        setEditorCommandState(editor, 'StyleWithCSS', false);
28816        setEditorCommandState(editor, 'enableInlineTableEditing', false);
28817        setEditorCommandState(editor, 'enableObjectResizing', false);
28818        if (hasEditorOrUiFocus(editor)) {
28819          editor.focus();
28820        }
28821        restoreFakeSelection(editor);
28822        editor.nodeChanged();
28823      }
28824    };
28825    const isReadOnly = editor => editor.readonly;
28826    const registerFilters = editor => {
28827      editor.parser.addAttributeFilter('contenteditable', nodes => {
28828        if (isReadOnly(editor)) {
28829          each$e(nodes, node => {
28830            node.attr(internalContentEditableAttr, node.attr('contenteditable'));
28831            node.attr('contenteditable', 'false');
28832          });
28833        }
28834      });
28835      editor.serializer.addAttributeFilter(internalContentEditableAttr, nodes => {
28836        if (isReadOnly(editor)) {
28837          each$e(nodes, node => {
28838            node.attr('contenteditable', node.attr(internalContentEditableAttr));
28839          });
28840        }
28841      });
28842      editor.serializer.addTempAttr(internalContentEditableAttr);
28843    };
28844    const registerReadOnlyContentFilters = editor => {
28845      if (editor.serializer) {
28846        registerFilters(editor);
28847      } else {
28848        editor.on('PreInit', () => {
28849          registerFilters(editor);
28850        });
28851      }
28852    };
28853    const isClickEvent = e => e.type === 'click';
28854    const allowedEvents = ['copy'];
28855    const isReadOnlyAllowedEvent = e => contains$2(allowedEvents, e.type);
28856    const getAnchorHrefOpt = (editor, elm) => {
28857      const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody()));
28858      return closest$3(elm, 'a', isRoot).bind(a => getOpt(a, 'href'));
28859    };
28860    const processReadonlyEvents = (editor, e) => {
28861      if (isClickEvent(e) && !VK.metaKeyPressed(e)) {
28862        const elm = SugarElement.fromDom(e.target);
28863        getAnchorHrefOpt(editor, elm).each(href => {
28864          e.preventDefault();
28865          if (/^#/.test(href)) {
28866            const targetEl = editor.dom.select(`${ href },[name="${ removeLeading(href, '#') }"]`);
28867            if (targetEl.length) {
28868              editor.selection.scrollIntoView(targetEl[0], true);
28869            }
28870          } else {
28871            window.open(href, '_blank', 'rel=noopener noreferrer,menubar=yes,toolbar=yes,location=yes,status=yes,resizable=yes,scrollbars=yes');
28872          }
28873        });
28874      } else if (isReadOnlyAllowedEvent(e)) {
28875        editor.dispatch(e.type, e);
28876      }
28877    };
28878    const registerReadOnlySelectionBlockers = editor => {
28879      editor.on('ShowCaret', e => {
28880        if (isReadOnly(editor)) {
28881          e.preventDefault();
28882        }
28883      });
28884      editor.on('ObjectSelected', e => {
28885        if (isReadOnly(editor)) {
28886          e.preventDefault();
28887        }
28888      });
28889    };
28890
28891    const nativeEvents = Tools.makeMap('focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange ' + 'mouseout mouseenter mouseleave wheel keydown keypress keyup input beforeinput contextmenu dragstart dragend dragover ' + 'draggesture dragdrop drop drag submit ' + 'compositionstart compositionend compositionupdate touchstart touchmove touchend touchcancel', ' ');
28892    class EventDispatcher {
28893      constructor(settings) {
28894        this.bindings = {};
28895        this.settings = settings || {};
28896        this.scope = this.settings.scope || this;
28897        this.toggleEvent = this.settings.toggleEvent || never;
28898      }
28899      static isNative(name) {
28900        return !!nativeEvents[name.toLowerCase()]
vendor: 34,147 bytes, lines 28900-29970
28900;
28901      }
28902      fire(name, args) {
28903        return this.dispatch(name, args);
28904      }
28905      dispatch(name, args) {
28906        const lcName = name.toLowerCase();
28907        const event = normalize$3(lcName, args !== null && args !== void 0 ? args : {}, this.scope);
28908        if (this.settings.beforeFire) {
28909          this.settings.beforeFire(event);
28910        }
28911        const handlers = this.bindings[lcName];
28912        if (handlers) {
28913          for (let i = 0, l = handlers.length; i < l; i++) {
28914            const callback = handlers[i];
28915            if (callback.removed) {
28916              continue;
28917            }
28918            if (callback.once) {
28919              this.off(lcName, callback.func);
28920            }
28921            if (event.isImmediatePropagationStopped()) {
28922              return event;
28923            }
28924            if (callback.func.call(this.scope, event) === false) {
28925              event.preventDefault();
28926              return event;
28927            }
28928          }
28929        }
28930        return event;
28931      }
28932      on(name, callback, prepend, extra) {
28933        if (callback === false) {
28934          callback = never;
28935        }
28936        if (callback) {
28937          const wrappedCallback = {
28938            func: callback,
28939            removed: false
28940          };
28941          if (extra) {
28942            Tools.extend(wrappedCallback, extra);
28943          }
28944          const names = name.toLowerCase().split(' ');
28945          let i = names.length;
28946          while (i--) {
28947            const currentName = names[i];
28948            let handlers = this.bindings[currentName];
28949            if (!handlers) {
28950              handlers = [];
28951              this.toggleEvent(currentName, true);
28952            }
28953            if (prepend) {
28954              handlers = [
28955                wrappedCallback,
28956                ...handlers
28957              ];
28958            } else {
28959              handlers = [
28960                ...handlers,
28961                wrappedCallback
28962              ];
28963            }
28964            this.bindings[currentName] = handlers;
28965          }
28966        }
28967        return this;
28968      }
28969      off(name, callback) {
28970        if (name) {
28971          const names = name.toLowerCase().split(' ');
28972          let i = names.length;
28973          while (i--) {
28974            const currentName = names[i];
28975            let handlers = this.bindings[currentName];
28976            if (!currentName) {
28977              each$d(this.bindings, (_value, bindingName) => {
28978                this.toggleEvent(bindingName, false);
28979                delete this.bindings[bindingName];
28980              });
28981              return this;
28982            }
28983            if (handlers) {
28984              if (!callback) {
28985                handlers.length = 0;
28986              } else {
28987                const filteredHandlers = partition$2(handlers, handler => handler.func === callback);
28988                handlers = filteredHandlers.fail;
28989                this.bindings[currentName] = handlers;
28990                each$e(filteredHandlers.pass, handler => {
28991                  handler.removed = true;
28992                });
28993              }
28994              if (!handlers.length) {
28995                this.toggleEvent(name, false);
28996                delete this.bindings[currentName];
28997              }
28998            }
28999          }
29000        } else {
29001          each$d(this.bindings, (_value, name) => {
29002            this.toggleEvent(name, false);
29003          });
29004          this.bindings = {};
29005        }
29006        return this;
29007      }
29008      once(name, callback, prepend) {
29009        return this.on(name, callback, prepend, { once: true });
29010      }
29011      has(name) {
29012        name = name.toLowerCase();
29013        const binding = this.bindings[name];
29014        return !(!binding || binding.length === 0);
29015      }
29016    }
29017
29018    const getEventDispatcher = obj => {
29019      if (!obj._eventDispatcher) {
29020        obj._eventDispatcher = new EventDispatcher({
29021          scope: obj,
29022          toggleEvent: (name, state) => {
29023            if (EventDispatcher.isNative(name) && obj.toggleNativeEvent) {
29024              obj.toggleNativeEvent(name, state);
29025            }
29026          }
29027        });
29028      }
29029      return obj._eventDispatcher;
29030    };
29031    const Observable = {
29032      fire(name, args, bubble) {
29033        return this.dispatch(name, args, bubble);
29034      },
29035      dispatch(name, args, bubble) {
29036        const self = this;
29037        if (self.removed && name !== 'remove' && name !== 'detach') {
29038          return normalize$3(name.toLowerCase(), args !== null && args !== void 0 ? args : {}, self);
29039        }
29040        const dispatcherArgs = getEventDispatcher(self).dispatch(name, args);
29041        if (bubble !== false && self.parent) {
29042          let parent = self.parent();
29043          while (parent && !dispatcherArgs.isPropagationStopped()) {
29044            parent.dispatch(name, dispatcherArgs, false);
29045            parent = parent.parent ? parent.parent() : undefined;
29046          }
29047        }
29048        return dispatcherArgs;
29049      },
29050      on(name, callback, prepend) {
29051        return getEventDispatcher(this).on(name, callback, prepend);
29052      },
29053      off(name, callback) {
29054        return getEventDispatcher(this).off(name, callback);
29055      },
29056      once(name, callback) {
29057        return getEventDispatcher(this).once(name, callback);
29058      },
29059      hasEventListeners(name) {
29060        return getEventDispatcher(this).has(name);
29061      }
29062    };
29063
29064    const DOM$2 = DOMUtils.DOM;
29065    let customEventRootDelegates;
29066    const getEventTarget = (editor, eventName) => {
29067      if (eventName === 'selectionchange') {
29068        return editor.getDoc();
29069      }
29070      if (!editor.inline && /^(?:mouse|touch|click|contextmenu|drop|dragover|dragend)/.test(eventName)) {
29071        return editor.getDoc().documentElement;
29072      }
29073      const eventRoot = getEventRoot(editor);
29074      if (eventRoot) {
29075        if (!editor.eventRoot) {
29076          editor.eventRoot = DOM$2.select(eventRoot)[0];
29077        }
29078        return editor.eventRoot;
29079      }
29080      return editor.getBody();
29081    };
29082    const isListening = editor => !editor.hidden && !isReadOnly(editor);
29083    const fireEvent = (editor, eventName, e) => {
29084      if (isListening(editor)) {
29085        editor.dispatch(eventName, e);
29086      } else if (isReadOnly(editor)) {
29087        processReadonlyEvents(editor, e);
29088      }
29089    };
29090    const bindEventDelegate = (editor, eventName) => {
29091      if (!editor.delegates) {
29092        editor.delegates = {};
29093      }
29094      if (editor.delegates[eventName] || editor.removed) {
29095        return;
29096      }
29097      const eventRootElm = getEventTarget(editor, eventName);
29098      if (getEventRoot(editor)) {
29099        if (!customEventRootDelegates) {
29100          customEventRootDelegates = {};
29101          editor.editorManager.on('removeEditor', () => {
29102            if (!editor.editorManager.activeEditor) {
29103              if (customEventRootDelegates) {
29104                each$d(customEventRootDelegates, (_value, name) => {
29105                  editor.dom.unbind(getEventTarget(editor, name));
29106                });
29107                customEventRootDelegates = null;
29108              }
29109            }
29110          });
29111        }
29112        if (customEventRootDelegates[eventName]) {
29113          return;
29114        }
29115        const delegate = e => {
29116          const target = e.target;
29117          const editors = editor.editorManager.get();
29118          let i = editors.length;
29119          while (i--) {
29120            const body = editors[i].getBody();
29121            if (body === target || DOM$2.isChildOf(target, body)) {
29122              fireEvent(editors[i], eventName, e);
29123            }
29124          }
29125        };
29126        customEventRootDelegates[eventName] = delegate;
29127        DOM$2.bind(eventRootElm, eventName, delegate);
29128      } else {
29129        const delegate = e => {
29130          fireEvent(editor, eventName, e);
29131        };
29132        DOM$2.bind(eventRootElm, eventName, delegate);
29133        editor.delegates[eventName] = delegate;
29134      }
29135    };
29136    const EditorObservable = {
29137      ...Observable,
29138      bindPendingEventDelegates() {
29139        const self = this;
29140        Tools.each(self._pendingNativeEvents, name => {
29141          bindEventDelegate(self, name);
29142        });
29143      },
29144      toggleNativeEvent(name, state) {
29145        const self = this;
29146        if (name === 'focus' || name === 'blur') {
29147          return;
29148        }
29149        if (self.removed) {
29150          return;
29151        }
29152        if (state) {
29153          if (self.initialized) {
29154            bindEventDelegate(self, name);
29155          } else {
29156            if (!self._pendingNativeEvents) {
29157              self._pendingNativeEvents = [name];
29158            } else {
29159              self._pendingNativeEvents.push(name);
29160            }
29161          }
29162        } else if (self.initialized && self.delegates) {
29163          self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
29164          delete self.delegates[name];
29165        }
29166      },
29167      unbindAllNativeEvents() {
29168        const self = this;
29169        const body = self.getBody();
29170        const dom = self.dom;
29171        if (self.delegates) {
29172          each$d(self.delegates, (value, name) => {
29173            self.dom.unbind(getEventTarget(self, name), name, value);
29174          });
29175          delete self.delegates;
29176        }
29177        if (!self.inline && body && dom) {
29178          body.onload = null;
29179          dom.unbind(self.getWin());
29180          dom.unbind(self.getDoc());
29181        }
29182        if (dom) {
29183          dom.unbind(body);
29184          dom.unbind(self.getContainer());
29185        }
29186      }
29187    };
29188
29189    const stringListProcessor = value => {
29190      if (isString(value)) {
29191        return {
29192          value: value.split(/[ ,]/),
29193          valid: true
29194        };
29195      } else if (isArrayOf(value, isString)) {
29196        return {
29197          value,
29198          valid: true
29199        };
29200      } else {
29201        return {
29202          valid: false,
29203          message: `The value must be a string[] or a comma/space separated string.`
29204        };
29205      }
29206    };
29207    const getBuiltInProcessor = type => {
29208      const validator = (() => {
29209        switch (type) {
29210        case 'array':
29211          return isArray$1;
29212        case 'boolean':
29213          return isBoolean;
29214        case 'function':
29215          return isFunction;
29216        case 'number':
29217          return isNumber;
29218        case 'object':
29219          return isObject;
29220        case 'string':
29221          return isString;
29222        case 'string[]':
29223          return stringListProcessor;
29224        case 'object[]':
29225          return val => isArrayOf(val, isObject);
29226        case 'regexp':
29227          return val => is$4(val, RegExp);
29228        default:
29229          return always;
29230        }
29231      })();
29232      return value => processValue(value, validator, `The value must be a ${ type }.`);
29233    };
29234    const isBuiltInSpec = spec => isString(spec.processor);
29235    const getErrorMessage = (message, result) => {
29236      const additionalText = isEmpty$3(result.message) ? '' : `. ${ result.message }`;
29237      return message + additionalText;
29238    };
29239    const isValidResult = result => result.valid;
29240    const processValue = (value, processor, message = '') => {
29241      const result = processor(value);
29242      if (isBoolean(result)) {
29243        return result ? {
29244          value: value,
29245          valid: true
29246        } : {
29247          valid: false,
29248          message
29249        };
29250      } else {
29251        return result;
29252      }
29253    };
29254    const processDefaultValue = (name, defaultValue, processor) => {
29255      if (!isUndefined(defaultValue)) {
29256        const result = processValue(defaultValue, processor);
29257        if (isValidResult(result)) {
29258          return result.value;
29259        } else {
29260          console.error(getErrorMessage(`Invalid default value passed for the "${ name }" option`, result));
29261        }
29262      }
29263      return undefined;
29264    };
29265    const create$5 = (editor, initialOptions) => {
29266      const registry = {};
29267      const values = {};
29268      const setValue = (name, value, processor) => {
29269        const result = processValue(value, processor);
29270        if (isValidResult(result)) {
29271          values[name] = result.value;
29272          return true;
29273        } else {
29274          console.warn(getErrorMessage(`Invalid value passed for the ${ name } option`, result));
29275          return false;
29276        }
29277      };
29278      const register = (name, spec) => {
29279        const processor = isBuiltInSpec(spec) ? getBuiltInProcessor(spec.processor) : spec.processor;
29280        const defaultValue = processDefaultValue(name, spec.default, processor);
29281        registry[name] = {
29282          ...spec,
29283          default: defaultValue,
29284          processor
29285        };
29286        const initValue = get$a(values, name).orThunk(() => get$a(initialOptions, name));
29287        initValue.each(value => setValue(name, value, processor));
29288      };
29289      const isRegistered = name => has$2(registry, name);
29290      const get = name => get$a(values, name).orThunk(() => get$a(registry, name).map(spec => spec.default)).getOrUndefined();
29291      const set = (name, value) => {
29292        if (!isRegistered(name)) {
29293          console.warn(`"${ name }" is not a registered option. Ensure the option has been registered before setting a value.`);
29294          return false;
29295        } else {
29296          const spec = registry[name];
29297          if (spec.immutable) {
29298            console.error(`"${ name }" is an immutable option and cannot be updated`);
29299            return false;
29300          } else {
29301            return setValue(name, value, spec.processor);
29302          }
29303        }
29304      };
29305      const unset = name => {
29306        const registered = isRegistered(name);
29307        if (registered) {
29308          delete values[name];
29309        }
29310        return registered;
29311      };
29312      const isSet = name => has$2(values, name);
29313      return {
29314        register,
29315        isRegistered,
29316        get,
29317        set,
29318        unset,
29319        isSet
29320      };
29321    };
29322
29323    const defaultModes = [
29324      'design',
29325      'readonly'
29326    ];
29327    const switchToMode = (editor, activeMode, availableModes, mode) => {
29328      const oldMode = availableModes[activeMode.get()];
29329      const newMode = availableModes[mode];
29330      try {
29331        newMode.activate();
29332      } catch (e) {
29333        console.error(`problem while activating editor mode ${ mode }:`, e);
29334        return;
29335      }
29336      oldMode.deactivate();
29337      if (oldMode.editorReadOnly !== newMode.editorReadOnly) {
29338        toggleReadOnly(editor, newMode.editorReadOnly);
29339      }
29340      activeMode.set(mode);
29341      fireSwitchMode(editor, mode);
29342    };
29343    const setMode = (editor, availableModes, activeMode, mode) => {
29344      if (mode === activeMode.get()) {
29345        return;
29346      } else if (!has$2(availableModes, mode)) {
29347        throw new Error(`Editor mode '${ mode }' is invalid`);
29348      }
29349      if (editor.initialized) {
29350        switchToMode(editor, activeMode, availableModes, mode);
29351      } else {
29352        editor.on('init', () => switchToMode(editor, activeMode, availableModes, mode));
29353      }
29354    };
29355    const registerMode = (availableModes, mode, api) => {
29356      if (contains$2(defaultModes, mode)) {
29357        throw new Error(`Cannot override default mode ${ mode }`);
29358      }
29359      return {
29360        ...availableModes,
29361        [mode]: {
29362          ...api,
29363          deactivate: () => {
29364            try {
29365              api.deactivate();
29366            } catch (e) {
29367              console.error(`problem while deactivating editor mode ${ mode }:`, e);
29368            }
29369          }
29370        }
29371      };
29372    };
29373
29374    const create$4 = editor => {
29375      const activeMode = Cell('design');
29376      const availableModes = Cell({
29377        design: {
29378          activate: noop,
29379          deactivate: noop,
29380          editorReadOnly: false
29381        },
29382        readonly: {
29383          activate: noop,
29384          deactivate: noop,
29385          editorReadOnly: true
29386        }
29387      });
29388      registerReadOnlyContentFilters(editor);
29389      registerReadOnlySelectionBlockers(editor);
29390      return {
29391        isReadOnly: () => isReadOnly(editor),
29392        set: mode => setMode(editor, availableModes.get(), activeMode, mode),
29393        get: () => activeMode.get(),
29394        register: (mode, api) => {
29395          availableModes.set(registerMode(availableModes.get(), mode, api));
29396        }
29397      };
29398    };
29399
29400    const each$2 = Tools.each, explode = Tools.explode;
29401    const keyCodeLookup = {
29402      f1: 112,
29403      f2: 113,
29404      f3: 114,
29405      f4: 115,
29406      f5: 116,
29407      f6: 117,
29408      f7: 118,
29409      f8: 119,
29410      f9: 120,
29411      f10: 121,
29412      f11: 122,
29413      f12: 123
29414    };
29415    const modifierNames = Tools.makeMap('alt,ctrl,shift,meta,access');
29416    const isModifier = key => key in modifierNames;
29417    const parseShortcut = pattern => {
29418      const shortcut = {};
29419      const isMac = Env.os.isMacOS() || Env.os.isiOS();
29420      each$2(explode(pattern.toLowerCase(), '+'), value => {
29421        if (isModifier(value)) {
29422          shortcut[value] = true;
29423        } else {
29424          if (/^[0-9]{2,}$/.test(value)) {
29425            shortcut.keyCode = parseInt(value, 10);
29426          } else {
29427            shortcut.charCode = value.charCodeAt(0);
29428            shortcut.keyCode = keyCodeLookup[value] || value.toUpperCase().charCodeAt(0);
29429          }
29430        }
29431      });
29432      const id = [shortcut.keyCode];
29433      let key;
29434      for (key in modifierNames) {
29435        if (shortcut[key]) {
29436          id.push(key);
29437        } else {
29438          shortcut[key] = false;
29439        }
29440      }
29441      shortcut.id = id.join(',');
29442      if (shortcut.access) {
29443        shortcut.alt = true;
29444        if (isMac) {
29445          shortcut.ctrl = true;
29446        } else {
29447          shortcut.shift = true;
29448        }
29449      }
29450      if (shortcut.meta) {
29451        if (isMac) {
29452          shortcut.meta = true;
29453        } else {
29454          shortcut.ctrl = true;
29455          shortcut.meta = false;
29456        }
29457      }
29458      return shortcut;
29459    };
29460    class Shortcuts {
29461      constructor(editor) {
29462        this.shortcuts = {};
29463        this.pendingPatterns = [];
29464        this.editor = editor;
29465        const self = this;
29466        editor.on('keyup keypress keydown', e => {
29467          if ((self.hasModifier(e) || self.isFunctionKey(e)) && !e.isDefaultPrevented()) {
29468            each$2(self.shortcuts, shortcut => {
29469              if (self.matchShortcut(e, shortcut)) {
29470                self.pendingPatterns = shortcut.subpatterns.slice(0);
29471                if (e.type === 'keydown') {
29472                  self.executeShortcutAction(shortcut);
29473                }
29474              }
29475            });
29476            if (self.matchShortcut(e, self.pendingPatterns[0])) {
29477              if (self.pendingPatterns.length === 1) {
29478                if (e.type === 'keydown') {
29479                  self.executeShortcutAction(self.pendingPatterns[0]);
29480                }
29481              }
29482              self.pendingPatterns.shift();
29483            }
29484          }
29485        });
29486      }
29487      add(pattern, desc, cmdFunc, scope) {
29488        const self = this;
29489        const func = self.normalizeCommandFunc(cmdFunc);
29490        each$2(explode(Tools.trim(pattern)), pattern => {
29491          const shortcut = self.createShortcut(pattern, desc, func, scope);
29492          self.shortcuts[shortcut.id] = shortcut;
29493        });
29494        return true;
29495      }
29496      remove(pattern) {
29497        const shortcut = this.createShortcut(pattern);
29498        if (this.shortcuts[shortcut.id]) {
29499          delete this.shortcuts[shortcut.id];
29500          return true;
29501        }
29502        return false;
29503      }
29504      normalizeCommandFunc(cmdFunc) {
29505        const self = this;
29506        const cmd = cmdFunc;
29507        if (typeof cmd === 'string') {
29508          return () => {
29509            self.editor.execCommand(cmd, false, null);
29510          };
29511        } else if (Tools.isArray(cmd)) {
29512          return () => {
29513            self.editor.execCommand(cmd[0], cmd[1], cmd[2]);
29514          };
29515        } else {
29516          return cmd;
29517        }
29518      }
29519      createShortcut(pattern, desc, cmdFunc, scope) {
29520        const shortcuts = Tools.map(explode(pattern, '>'), parseShortcut);
29521        shortcuts[shortcuts.length - 1] = Tools.extend(shortcuts[shortcuts.length - 1], {
29522          func: cmdFunc,
29523          scope: scope || this.editor
29524        });
29525        return Tools.extend(shortcuts[0], {
29526          desc: this.editor.translate(desc),
29527          subpatterns: shortcuts.slice(1)
29528        });
29529      }
29530      hasModifier(e) {
29531        return e.altKey || e.ctrlKey || e.metaKey;
29532      }
29533      isFunctionKey(e) {
29534        return e.type === 'keydown' && e.keyCode >= 112 && e.keyCode <= 123;
29535      }
29536      matchShortcut(e, shortcut) {
29537        if (!shortcut) {
29538          return false;
29539        }
29540        if (shortcut.ctrl !== e.ctrlKey || shortcut.meta !== e.metaKey) {
29541          return false;
29542        }
29543        if (shortcut.alt !== e.altKey || shortcut.shift !== e.shiftKey) {
29544          return false;
29545        }
29546        if (e.keyCode === shortcut.keyCode || e.charCode && e.charCode === shortcut.charCode) {
29547          e.preventDefault();
29548          return true;
29549        }
29550        return false;
29551      }
29552      executeShortcutAction(shortcut) {
29553        return shortcut.func ? shortcut.func.call(shortcut.scope) : null;
29554      }
29555    }
29556
29557    const create$3 = () => {
29558      const buttons = {};
29559      const menuItems = {};
29560      const popups = {};
29561      const icons = {};
29562      const contextMenus = {};
29563      const contextToolbars = {};
29564      const sidebars = {};
29565      const views = {};
29566      const add = (collection, type) => (name, spec) => {
29567        collection[name.toLowerCase()] = {
29568          ...spec,
29569          type
29570        };
29571      };
29572      const addIcon = (name, svgData) => icons[name.toLowerCase()] = svgData;
29573      return {
29574        addButton: add(buttons, 'button'),
29575        addGroupToolbarButton: add(buttons, 'grouptoolbarbutton'),
29576        addToggleButton: add(buttons, 'togglebutton'),
29577        addMenuButton: add(buttons, 'menubutton'),
29578        addSplitButton: add(buttons, 'splitbutton'),
29579        addMenuItem: add(menuItems, 'menuitem'),
29580        addNestedMenuItem: add(menuItems, 'nestedmenuitem'),
29581        addToggleMenuItem: add(menuItems, 'togglemenuitem'),
29582        addAutocompleter: add(popups, 'autocompleter'),
29583        addContextMenu: add(contextMenus, 'contextmenu'),
29584        addContextToolbar: add(contextToolbars, 'contexttoolbar'),
29585        addContextForm: add(contextToolbars, 'contextform'),
29586        addSidebar: add(sidebars, 'sidebar'),
29587        addView: add(views, 'views'),
29588        addIcon,
29589        getAll: () => ({
29590          buttons,
29591          menuItems,
29592          icons,
29593          popups,
29594          contextMenus,
29595          contextToolbars,
29596          sidebars,
29597          views
29598        })
29599      };
29600    };
29601
29602    const registry = () => {
29603      const bridge = create$3();
29604      return {
29605        addAutocompleter: bridge.addAutocompleter,
29606        addButton: bridge.addButton,
29607        addContextForm: bridge.addContextForm,
29608        addContextMenu: bridge.addContextMenu,
29609        addContextToolbar: bridge.addContextToolbar,
29610        addIcon: bridge.addIcon,
29611        addMenuButton: bridge.addMenuButton,
29612        addMenuItem: bridge.addMenuItem,
29613        addNestedMenuItem: bridge.addNestedMenuItem,
29614        addSidebar: bridge.addSidebar,
29615        addSplitButton: bridge.addSplitButton,
29616        addToggleButton: bridge.addToggleButton,
29617        addGroupToolbarButton: bridge.addGroupToolbarButton,
29618        addToggleMenuItem: bridge.addToggleMenuItem,
29619        addView: bridge.addView,
29620        getAll: bridge.getAll
29621      };
29622    };
29623
29624    const DOM$1 = DOMUtils.DOM;
29625    const extend = Tools.extend, each$1 = Tools.each;
29626    class Editor {
29627      constructor(id, options, editorManager) {
29628        this.plugins = {};
29629        this.contentCSS = [];
29630        this.contentStyles = [];
29631        this.loadedCSS = {};
29632        this.isNotDirty = false;
29633        this.composing = false;
29634        this.destroyed = false;
29635        this.hasHiddenInput = false;
29636        this.iframeElement = null;
29637        this.initialized = false;
29638        this.readonly = false;
29639        this.removed = false;
29640        this.startContent = '';
29641        this._pendingNativeEvents = [];
29642        this._skinLoaded = false;
29643        this.editorManager = editorManager;
29644        this.documentBaseUrl = editorManager.documentBaseURL;
29645        extend(this, EditorObservable);
29646        const self = this;
29647        this.id = id;
29648        this.hidden = false;
29649        const normalizedOptions = normalizeOptions(editorManager.defaultOptions, options);
29650        this.options = create$5(self, normalizedOptions);
29651        register$7(self);
29652        const getOption = this.options.get;
29653        if (getOption('deprecation_warnings')) {
29654          logWarnings(options, normalizedOptions);
29655        }
29656        const suffix = getOption('suffix');
29657        if (suffix) {
29658          editorManager.suffix = suffix;
29659        }
29660        this.suffix = editorManager.suffix;
29661        const baseUrl = getOption('base_url');
29662        if (baseUrl) {
29663          editorManager._setBaseUrl(baseUrl);
29664        }
29665        this.baseUri = editorManager.baseURI;
29666        const referrerPolicy = getReferrerPolicy(self);
29667        if (referrerPolicy) {
29668          ScriptLoader.ScriptLoader._setReferrerPolicy(referrerPolicy);
29669          DOMUtils.DOM.styleSheetLoader._setReferrerPolicy(referrerPolicy);
29670        }
29671        const contentCssCors = hasContentCssCors(self);
29672        if (isNonNullable(contentCssCors)) {
29673          DOMUtils.DOM.styleSheetLoader._setContentCssCors(contentCssCors);
29674        }
29675        AddOnManager.languageLoad = getOption('language_load');
29676        AddOnManager.baseURL = editorManager.baseURL;
29677        this.setDirty(false);
29678        this.documentBaseURI = new URI(getDocumentBaseUrl(self), { base_uri: this.baseUri });
29679        this.baseURI = this.baseUri;
29680        this.inline = isInline(self);
29681        this.hasVisual = isVisualAidsEnabled(self);
29682        this.shortcuts = new Shortcuts(this);
29683        this.editorCommands = new EditorCommands(this);
29684        registerCommands(this);
29685        const cacheSuffix = getOption('cache_suffix');
29686        if (cacheSuffix) {
29687          Env.cacheSuffix = cacheSuffix.replace(/^[\?\&]+/, '');
29688        }
29689        this.ui = {
29690          registry: registry(),
29691          styleSheetLoader: undefined,
29692          show: noop,
29693          hide: noop,
29694          setEnabled: noop,
29695          isEnabled: always
29696        };
29697        this.mode = create$4(self);
29698        editorManager.dispatch('SetupEditor', { editor: this });
29699        const setupCallback = getSetupCallback(self);
29700        if (isFunction(setupCallback)) {
29701          setupCallback.call(self, self);
29702        }
29703      }
29704      render() {
29705        render(this);
29706      }
29707      focus(skipFocus) {
29708        this.execCommand('mceFocus', false, skipFocus);
29709      }
29710      hasFocus() {
29711        return hasFocus(this);
29712      }
29713      translate(text) {
29714        return I18n.translate(text);
29715      }
29716      getParam(name, defaultVal, type) {
29717        const options = this.options;
29718        if (!options.isRegistered(name)) {
29719          if (isNonNullable(type)) {
29720            options.register(name, {
29721              processor: type,
29722              default: defaultVal
29723            });
29724          } else {
29725            options.register(name, {
29726              processor: always,
29727              default: defaultVal
29728            });
29729          }
29730        }
29731        return !options.isSet(name) && !isUndefined(defaultVal) ? defaultVal : options.get(name);
29732      }
29733      hasPlugin(name, loaded) {
29734        const hasPlugin = contains$2(getPlugins(this), name);
29735        if (hasPlugin) {
29736          return loaded ? PluginManager.get(name) !== undefined : true;
29737        } else {
29738          return false;
29739        }
29740      }
29741      nodeChanged(args) {
29742        this._nodeChangeDispatcher.nodeChanged(args);
29743      }
29744      addCommand(name, callback, scope) {
29745        this.editorCommands.addCommand(name, callback, scope);
29746      }
29747      addQueryStateHandler(name, callback, scope) {
29748        this.editorCommands.addQueryStateHandler(name, callback, scope);
29749      }
29750      addQueryValueHandler(name, callback, scope) {
29751        this.editorCommands.addQueryValueHandler(name, callback, scope);
29752      }
29753      addShortcut(pattern, desc, cmdFunc, scope) {
29754        this.shortcuts.add(pattern, desc, cmdFunc, scope);
29755      }
29756      execCommand(cmd, ui, value, args) {
29757        return this.editorCommands.execCommand(cmd, ui, value, args);
29758      }
29759      queryCommandState(cmd) {
29760        return this.editorCommands.queryCommandState(cmd);
29761      }
29762      queryCommandValue(cmd) {
29763        return this.editorCommands.queryCommandValue(cmd);
29764      }
29765      queryCommandSupported(cmd) {
29766        return this.editorCommands.queryCommandSupported(cmd);
29767      }
29768      show() {
29769        const self = this;
29770        if (self.hidden) {
29771          self.hidden = false;
29772          if (self.inline) {
29773            self.getBody().contentEditable = 'true';
29774          } else {
29775            DOM$1.show(self.getContainer());
29776            DOM$1.hide(self.id);
29777          }
29778          self.load();
29779          self.dispatch('show');
29780        }
29781      }
29782      hide() {
29783        const self = this;
29784        if (!self.hidden) {
29785          self.save();
29786          if (self.inline) {
29787            self.getBody().contentEditable = 'false';
29788            if (self === self.editorManager.focusedEditor) {
29789              self.editorManager.focusedEditor = null;
29790            }
29791          } else {
29792            DOM$1.hide(self.getContainer());
29793            DOM$1.setStyle(self.id, 'display', self.orgDisplay);
29794          }
29795          self.hidden = true;
29796          self.dispatch('hide');
29797        }
29798      }
29799      isHidden() {
29800        return this.hidden;
29801      }
29802      setProgressState(state, time) {
29803        this.dispatch('ProgressState', {
29804          state,
29805          time
29806        });
29807      }
29808      load(args = {}) {
29809        const self = this;
29810        const elm = self.getElement();
29811        if (self.removed) {
29812          return '';
29813        }
29814        if (elm) {
29815          const loadArgs = {
29816            ...args,
29817            load: true
29818          };
29819          const value = isTextareaOrInput(elm) ? elm.value : elm.innerHTML;
29820          const html = self.setContent(value, loadArgs);
29821          if (!loadArgs.no_events) {
29822            self.dispatch('LoadContent', {
29823              ...loadArgs,
29824              element: elm
29825            });
29826          }
29827          return html;
29828        } else {
29829          return '';
29830        }
29831      }
29832      save(args = {}) {
29833        const self = this;
29834        let elm = self.getElement();
29835        if (!elm || !self.initialized || self.removed) {
29836          return '';
29837        }
29838        const getArgs = {
29839          ...args,
29840          save: true,
29841          element: elm
29842        };
29843        let html = self.getContent(getArgs);
29844        const saveArgs = {
29845          ...getArgs,
29846          content: html
29847        };
29848        if (!saveArgs.no_events) {
29849          self.dispatch('SaveContent', saveArgs);
29850        }
29851        if (saveArgs.format === 'raw') {
29852          self.dispatch('RawSaveContent', saveArgs);
29853        }
29854        html = saveArgs.content;
29855        if (!isTextareaOrInput(elm)) {
29856          if (args.is_removing || !self.inline) {
29857            elm.innerHTML = html;
29858          }
29859          const form = DOM$1.getParent(self.id, 'form');
29860          if (form) {
29861            each$1(form.elements, elm => {
29862              if (elm.name === self.id) {
29863                elm.value = html;
29864                return false;
29865              } else {
29866                return true;
29867              }
29868            });
29869          }
29870        } else {
29871          elm.value = html;
29872        }
29873        saveArgs.element = getArgs.element = elm = null;
29874        if (saveArgs.set_dirty !== false) {
29875          self.setDirty(false);
29876        }
29877        return html;
29878      }
29879      setContent(content, args) {
29880        return setContent(this, content, args);
29881      }
29882      getContent(args) {
29883        return getContent(this, args);
29884      }
29885      insertContent(content, args) {
29886        if (args) {
29887          content = extend({ content }, args);
29888        }
29889        this.execCommand('mceInsertContent', false, content);
29890      }
29891      resetContent(initialContent) {
29892        if (initialContent === undefined) {
29893          setContent(this, this.startContent, { format: 'raw' });
29894        } else {
29895          setContent(this, initialContent);
29896        }
29897        this.undoManager.reset();
29898        this.setDirty(false);
29899        this.nodeChanged();
29900      }
29901      isDirty() {
29902        return !this.isNotDirty;
29903      }
29904      setDirty(state) {
29905        const oldState = !this.isNotDirty;
29906        this.isNotDirty = !state;
29907        if (state && state !== oldState) {
29908          this.dispatch('dirty');
29909        }
29910      }
29911      getContainer() {
29912        const self = this;
29913        if (!self.container) {
29914          self.container = self.editorContainer || DOM$1.get(self.id + '_parent');
29915        }
29916        return self.container;
29917      }
29918      getContentAreaContainer() {
29919        return this.contentAreaContainer;
29920      }
29921      getElement() {
29922        if (!this.targetElm) {
29923          this.targetElm = DOM$1.get(this.id);
29924        }
29925        return this.targetElm;
29926      }
29927      getWin() {
29928        const self = this;
29929        if (!self.contentWindow) {
29930          const elm = self.iframeElement;
29931          if (elm) {
29932            self.contentWindow = elm.contentWindow;
29933          }
29934        }
29935        return self.contentWindow;
29936      }
29937      getDoc() {
29938        const self = this;
29939        if (!self.contentDocument) {
29940          const win = self.getWin();
29941          if (win) {
29942            self.contentDocument = win.document;
29943          }
29944        }
29945        return self.contentDocument;
29946      }
29947      getBody() {
29948        var _a, _b;
29949        const doc = this.getDoc();
29950        return (_b = (_a = this.bodyElement) !== null && _a !== void 0 ? _a : doc === null || doc === void 0 ? void 0 : doc.body) !== null && _b !== void 0 ? _b : null;
29951      }
29952      convertURL(url, name, elm) {
29953        const self = this, getOption = self.options.get;
29954        const urlConverterCallback = getUrlConverterCallback(self);
29955        if (isFunction(urlConverterCallback)) {
29956          return urlConverterCallback.call(self, url, elm, true, name);
29957        }
29958        if (!getOption('convert_urls') || elm === 'link' || isObject(elm) && elm.nodeName === 'LINK' || url.indexOf('file:') === 0 || url.length === 0) {
29959          return url;
29960        }
29961        if (getOption('relative_urls')) {
29962          return self.documentBaseURI.toRelative(url);
29963        }
29964        url = self.documentBaseURI.toAbsolute(url, getOption('remove_script_host'));
29965        return url;
29966      }
29967      addVisual(elm) {
29968        addVisual(this, elm);
29969      }
29970      
vendor: 2,318 bytes, lines 29970-30046
29970remove() {
29971        remove$1(this);
29972      }
29973      destroy(automatic) {
29974        destroy(this, automatic);
29975      }
29976      uploadImages() {
29977        return this.editorUpload.uploadImages();
29978      }
29979      _scanForImages() {
29980        return this.editorUpload.scanForImages();
29981      }
29982    }
29983
29984    const DOM = DOMUtils.DOM;
29985    const each = Tools.each;
29986    let boundGlobalEvents = false;
29987    let beforeUnloadDelegate;
29988    let editors = [];
29989    const globalEventDelegate = e => {
29990      const type = e.type;
29991      each(EditorManager.get(), editor => {
29992        switch (type) {
29993        case 'scroll':
29994          editor.dispatch('ScrollWindow', e);
29995          break;
29996        case 'resize':
29997          editor.dispatch('ResizeWindow', e);
29998          break;
29999        }
30000      });
30001    };
30002    const toggleGlobalEvents = state => {
30003      if (state !== boundGlobalEvents) {
30004        const DOM = DOMUtils.DOM;
30005        if (state) {
30006          DOM.bind(window, 'resize', globalEventDelegate);
30007          DOM.bind(window, 'scroll', globalEventDelegate);
30008        } else {
30009          DOM.unbind(window, 'resize', globalEventDelegate);
30010          DOM.unbind(window, 'scroll', globalEventDelegate);
30011        }
30012        boundGlobalEvents = state;
30013      }
30014    };
30015    const removeEditorFromList = targetEditor => {
30016      const oldEditors = editors;
30017      editors = filter$5(editors, editor => {
30018        return targetEditor !== editor;
30019      });
30020      if (EditorManager.activeEditor === targetEditor) {
30021        EditorManager.activeEditor = editors.length > 0 ? editors[0] : null;
30022      }
30023      if (EditorManager.focusedEditor === targetEditor) {
30024        EditorManager.focusedEditor = null;
30025      }
30026      return oldEditors.length !== editors.length;
30027    };
30028    const purgeDestroyedEditor = editor => {
30029      if (editor && editor.initialized && !(editor.getContainer() || editor.getBody()).parentNode) {
30030        removeEditorFromList(editor);
30031        editor.unbindAllNativeEvents();
30032        editor.destroy(true);
30033        editor.removed = true;
30034      }
30035    };
30036    const isQuirksMode = document.compatMode !== 'CSS1Compat';
30037    const EditorManager = {
30038      ...Observable,
30039      baseURI: null,
30040      baseURL: null,
30041      defaultOptions: {},
30042      documentBaseURL: null,
30043      suffix: null,
30044      majorVersion: '6',
30045      minorVersion: '4.2',
30046      releaseDate: '2023-04-26
vendor: 18,364 bytes, lines 30046-30653
30046',
30047      i18n: I18n,
30048      activeEditor: null,
30049      focusedEditor: null,
30050      setup() {
30051        const self = this;
30052        let baseURL = '';
30053        let suffix = '';
30054        let documentBaseURL = URI.getDocumentBaseUrl(document.location);
30055        if (/^[^:]+:\/\/\/?[^\/]+\//.test(documentBaseURL)) {
30056          documentBaseURL = documentBaseURL.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
30057          if (!/[\/\\]$/.test(documentBaseURL)) {
30058            documentBaseURL += '/';
30059          }
30060        }
30061        const preInit = window.tinymce || window.tinyMCEPreInit;
30062        if (preInit) {
30063          baseURL = preInit.base || preInit.baseURL;
30064          suffix = preInit.suffix;
30065        } else {
30066          const scripts = document.getElementsByTagName('script');
30067          for (let i = 0; i < scripts.length; i++) {
30068            const src = scripts[i].src || '';
30069            if (src === '') {
30070              continue;
30071            }
30072            const srcScript = src.substring(src.lastIndexOf('/'));
30073            if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
30074              if (srcScript.indexOf('.min') !== -1) {
30075                suffix = '.min';
30076              }
30077              baseURL = src.substring(0, src.lastIndexOf('/'));
30078              break;
30079            }
30080          }
30081          if (!baseURL && document.currentScript) {
30082            const src = document.currentScript.src;
30083            if (src.indexOf('.min') !== -1) {
30084              suffix = '.min';
30085            }
30086            baseURL = src.substring(0, src.lastIndexOf('/'));
30087          }
30088        }
30089        self.baseURL = new URI(documentBaseURL).toAbsolute(baseURL);
30090        self.documentBaseURL = documentBaseURL;
30091        self.baseURI = new URI(self.baseURL);
30092        self.suffix = suffix;
30093        setup$v(self);
30094      },
30095      overrideDefaults(defaultOptions) {
30096        const baseUrl = defaultOptions.base_url;
30097        if (baseUrl) {
30098          this._setBaseUrl(baseUrl);
30099        }
30100        const suffix = defaultOptions.suffix;
30101        if (suffix) {
30102          this.suffix = suffix;
30103        }
30104        this.defaultOptions = defaultOptions;
30105        const pluginBaseUrls = defaultOptions.plugin_base_urls;
30106        if (pluginBaseUrls !== undefined) {
30107          each$d(pluginBaseUrls, (pluginBaseUrl, pluginName) => {
30108            AddOnManager.PluginManager.urls[pluginName] = pluginBaseUrl;
30109          });
30110        }
30111      },
30112      init(options) {
30113        const self = this;
30114        let result;
30115        const 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', ' ');
30116        const isInvalidInlineTarget = (options, elm) => options.inline && elm.tagName.toLowerCase() in invalidInlineTargets;
30117        const createId = elm => {
30118          let id = elm.id;
30119          if (!id) {
30120            id = get$a(elm, 'name').filter(name => !DOM.get(name)).getOrThunk(DOM.uniqueId);
30121            elm.setAttribute('id', id);
30122          }
30123          return id;
30124        };
30125        const execCallback = name => {
30126          const callback = options[name];
30127          if (!callback) {
30128            return;
30129          }
30130          return callback.apply(self, []);
30131        };
30132        const findTargets = options => {
30133          if (Env.browser.isIE() || Env.browser.isEdge()) {
30134            initError('TinyMCE does not support the browser you are using. For a list of supported' + ' browsers please see: https://www.tiny.cloud/docs/tinymce/6/support/#supportedwebbrowsers');
30135            return [];
30136          } else if (isQuirksMode) {
30137            initError('Failed to initialize the editor as the document is not in standards mode. ' + 'TinyMCE requires standards mode.');
30138            return [];
30139          } else if (isString(options.selector)) {
30140            return DOM.select(options.selector);
30141          } else if (isNonNullable(options.target)) {
30142            return [options.target];
30143          } else {
30144            return [];
30145          }
30146        };
30147        let provideResults = editors => {
30148          result = editors;
30149        };
30150        const initEditors = () => {
30151          let initCount = 0;
30152          const editors = [];
30153          let targets;
30154          const createEditor = (id, options, targetElm) => {
30155            const editor = new Editor(id, options, self);
30156            editors.push(editor);
30157            editor.on('init', () => {
30158              if (++initCount === targets.length) {
30159                provideResults(editors);
30160              }
30161            });
30162            editor.targetElm = editor.targetElm || targetElm;
30163            editor.render();
30164          };
30165          DOM.unbind(window, 'ready', initEditors);
30166          execCallback('onpageload');
30167          targets = unique$1(findTargets(options));
30168          Tools.each(targets, elm => {
30169            purgeDestroyedEditor(self.get(elm.id));
30170          });
30171          targets = Tools.grep(targets, elm => {
30172            return !self.get(elm.id);
30173          });
30174          if (targets.length === 0) {
30175            provideResults([]);
30176          } else {
30177            each(targets, elm => {
30178              if (isInvalidInlineTarget(options, elm)) {
30179                initError('Could not initialize inline editor on invalid inline target element', elm);
30180              } else {
30181                createEditor(createId(elm), options, elm);
30182              }
30183            });
30184          }
30185        };
30186        DOM.bind(window, 'ready', initEditors);
30187        return new Promise(resolve => {
30188          if (result) {
30189            resolve(result);
30190          } else {
30191            provideResults = editors => {
30192              resolve(editors);
30193            };
30194          }
30195        });
30196      },
30197      get(id) {
30198        if (arguments.length === 0) {
30199          return editors.slice(0);
30200        } else if (isString(id)) {
30201          return find$2(editors, editor => {
30202            return editor.id === id;
30203          }).getOr(null);
30204        } else if (isNumber(id)) {
30205          return editors[id] ? editors[id] : null;
30206        } else {
30207          return null;
30208        }
30209      },
30210      add(editor) {
30211        const self = this;
30212        const existingEditor = self.get(editor.id);
30213        if (existingEditor === editor) {
30214          return editor;
30215        }
30216        if (existingEditor === null) {
30217          editors.push(editor);
30218        }
30219        toggleGlobalEvents(true);
30220        self.activeEditor = editor;
30221        self.dispatch('AddEditor', { editor });
30222        if (!beforeUnloadDelegate) {
30223          beforeUnloadDelegate = e => {
30224            const event = self.dispatch('BeforeUnload');
30225            if (event.returnValue) {
30226              e.preventDefault();
30227              e.returnValue = event.returnValue;
30228              return event.returnValue;
30229            }
30230          };
30231          window.addEventListener('beforeunload', beforeUnloadDelegate);
30232        }
30233        return editor;
30234      },
30235      createEditor(id, options) {
30236        return this.add(new Editor(id, options, this));
30237      },
30238      remove(selector) {
30239        const self = this;
30240        let editor;
30241        if (!selector) {
30242          for (let i = editors.length - 1; i >= 0; i--) {
30243            self.remove(editors[i]);
30244          }
30245          return;
30246        }
30247        if (isString(selector)) {
30248          each(DOM.select(selector), elm => {
30249            editor = self.get(elm.id);
30250            if (editor) {
30251              self.remove(editor);
30252            }
30253          });
30254          return;
30255        }
30256        editor = selector;
30257        if (isNull(self.get(editor.id))) {
30258          return null;
30259        }
30260        if (removeEditorFromList(editor)) {
30261          self.dispatch('RemoveEditor', { editor });
30262        }
30263        if (editors.length === 0) {
30264          window.removeEventListener('beforeunload', beforeUnloadDelegate);
30265        }
30266        editor.remove();
30267        toggleGlobalEvents(editors.length > 0);
30268        return editor;
30269      },
30270      execCommand(cmd, ui, value) {
30271        var _a;
30272        const self = this;
30273        const editorId = isObject(value) ? (_a = value.id) !== null && _a !== void 0 ? _a : value.index : value;
30274        switch (cmd) {
30275        case 'mceAddEditor': {
30276            if (!self.get(editorId)) {
30277              const editorOptions = value.options;
30278              new Editor(editorId, editorOptions, self).render();
30279            }
30280            return true;
30281          }
30282        case 'mceRemoveEditor': {
30283            const editor = self.get(editorId);
30284            if (editor) {
30285              editor.remove();
30286            }
30287            return true;
30288          }
30289        case 'mceToggleEditor': {
30290            const editor = self.get(editorId);
30291            if (!editor) {
30292              self.execCommand('mceAddEditor', false, value);
30293              return true;
30294            }
30295            if (editor.isHidden()) {
30296              editor.show();
30297            } else {
30298              editor.hide();
30299            }
30300            return true;
30301          }
30302        }
30303        if (self.activeEditor) {
30304          return self.activeEditor.execCommand(cmd, ui, value);
30305        }
30306        return false;
30307      },
30308      triggerSave: () => {
30309        each(editors, editor => {
30310          editor.save();
30311        });
30312      },
30313      addI18n: (code, items) => {
30314        I18n.add(code, items);
30315      },
30316      translate: text => {
30317        return I18n.translate(text);
30318      },
30319      setActive(editor) {
30320        const activeEditor = this.activeEditor;
30321        if (this.activeEditor !== editor) {
30322          if (activeEditor) {
30323            activeEditor.dispatch('deactivate', { relatedTarget: editor });
30324          }
30325          editor.dispatch('activate', { relatedTarget: activeEditor });
30326        }
30327        this.activeEditor = editor;
30328      },
30329      _setBaseUrl(baseUrl) {
30330        this.baseURL = new URI(this.documentBaseURL).toAbsolute(baseUrl.replace(/\/+$/, ''));
30331        this.baseURI = new URI(this.baseURL);
30332      }
30333    };
30334    EditorManager.setup();
30335
30336    const setup = () => {
30337      const dataValue = value$2();
30338      const FakeClipboardItem = items => ({
30339        items,
30340        types: keys(items),
30341        getType: type => get$a(items, type).getOrUndefined()
30342      });
30343      const write = data => {
30344        dataValue.set(data);
30345      };
30346      const read = () => dataValue.get().getOrUndefined();
30347      const clear = dataValue.clear;
30348      return {
30349        FakeClipboardItem,
30350        write,
30351        read,
30352        clear
30353      };
30354    };
30355    const FakeClipboard = setup();
30356
30357    const min = Math.min, max = Math.max, round = Math.round;
30358    const relativePosition = (rect, targetRect, rel) => {
30359      let x = targetRect.x;
30360      let y = targetRect.y;
30361      const w = rect.w;
30362      const h = rect.h;
30363      const targetW = targetRect.w;
30364      const targetH = targetRect.h;
30365      const relChars = (rel || '').split('');
30366      if (relChars[0] === 'b') {
30367        y += targetH;
30368      }
30369      if (relChars[1] === 'r') {
30370        x += targetW;
30371      }
30372      if (relChars[0] === 'c') {
30373        y += round(targetH / 2);
30374      }
30375      if (relChars[1] === 'c') {
30376        x += round(targetW / 2);
30377      }
30378      if (relChars[3] === 'b') {
30379        y -= h;
30380      }
30381      if (relChars[4] === 'r') {
30382        x -= w;
30383      }
30384      if (relChars[3] === 'c') {
30385        y -= round(h / 2);
30386      }
30387      if (relChars[4] === 'c') {
30388        x -= round(w / 2);
30389      }
30390      return create$2(x, y, w, h);
30391    };
30392    const findBestRelativePosition = (rect, targetRect, constrainRect, rels) => {
30393      for (let i = 0; i < rels.length; i++) {
30394        const pos = relativePosition(rect, targetRect, rels[i]);
30395        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) {
30396          return rels[i];
30397        }
30398      }
30399      return null;
30400    };
30401    const inflate = (rect, w, h) => {
30402      return create$2(rect.x - w, rect.y - h, rect.w + w * 2, rect.h + h * 2);
30403    };
30404    const intersect = (rect, cropRect) => {
30405      const x1 = max(rect.x, cropRect.x);
30406      const y1 = max(rect.y, cropRect.y);
30407      const x2 = min(rect.x + rect.w, cropRect.x + cropRect.w);
30408      const y2 = min(rect.y + rect.h, cropRect.y + cropRect.h);
30409      if (x2 - x1 < 0 || y2 - y1 < 0) {
30410        return null;
30411      }
30412      return create$2(x1, y1, x2 - x1, y2 - y1);
30413    };
30414    const clamp = (rect, clampRect, fixedSize) => {
30415      let x1 = rect.x;
30416      let y1 = rect.y;
30417      let x2 = rect.x + rect.w;
30418      let y2 = rect.y + rect.h;
30419      const cx2 = clampRect.x + clampRect.w;
30420      const cy2 = clampRect.y + clampRect.h;
30421      const underflowX1 = max(0, clampRect.x - x1);
30422      const underflowY1 = max(0, clampRect.y - y1);
30423      const overflowX2 = max(0, x2 - cx2);
30424      const overflowY2 = max(0, y2 - cy2);
30425      x1 += underflowX1;
30426      y1 += underflowY1;
30427      if (fixedSize) {
30428        x2 += underflowX1;
30429        y2 += underflowY1;
30430        x1 -= overflowX2;
30431        y1 -= overflowY2;
30432      }
30433      x2 -= overflowX2;
30434      y2 -= overflowY2;
30435      return create$2(x1, y1, x2 - x1, y2 - y1);
30436    };
30437    const create$2 = (x, y, w, h) => {
30438      return {
30439        x,
30440        y,
30441        w,
30442        h
30443      };
30444    };
30445    const fromClientRect = clientRect => {
30446      return create$2(clientRect.left, clientRect.top, clientRect.width, clientRect.height);
30447    };
30448    const Rect = {
30449      inflate,
30450      relativePosition,
30451      findBestRelativePosition,
30452      intersect,
30453      clamp,
30454      create: create$2,
30455      fromClientRect
30456    };
30457
30458    const awaiter = (resolveCb, rejectCb, timeout = 1000) => {
30459      let done = false;
30460      let timer = null;
30461      const complete = completer => (...args) => {
30462        if (!done) {
30463          done = true;
30464          if (timer !== null) {
30465            clearTimeout(timer);
30466            timer = null;
30467          }
30468          completer.apply(null, args);
30469        }
30470      };
30471      const resolve = complete(resolveCb);
30472      const reject = complete(rejectCb);
30473      const start = (...args) => {
30474        if (!done && timer === null) {
30475          timer = setTimeout(() => reject.apply(null, args), timeout);
30476        }
30477      };
30478      return {
30479        start,
30480        resolve,
30481        reject
30482      };
30483    };
30484    const create$1 = () => {
30485      const tasks = {};
30486      const resultFns = {};
30487      const load = (id, url) => {
30488        const loadErrMsg = `Script at URL "${ url }" failed to load`;
30489        const runErrMsg = `Script at URL "${ url }" did not call \`tinymce.Resource.add('${ id }', data)\` within 1 second`;
30490        if (tasks[id] !== undefined) {
30491          return tasks[id];
30492        } else {
30493          const task = new Promise((resolve, reject) => {
30494            const waiter = awaiter(resolve, reject);
30495            resultFns[id] = waiter.resolve;
30496            ScriptLoader.ScriptLoader.loadScript(url).then(() => waiter.start(runErrMsg), () => waiter.reject(loadErrMsg));
30497          });
30498          tasks[id] = task;
30499          return task;
30500        }
30501      };
30502      const add = (id, data) => {
30503        if (resultFns[id] !== undefined) {
30504          resultFns[id](data);
30505          delete resultFns[id];
30506        }
30507        tasks[id] = Promise.resolve(data);
30508      };
30509      const unload = id => {
30510        delete tasks[id];
30511      };
30512      return {
30513        load,
30514        add,
30515        unload
30516      };
30517    };
30518    const Resource = create$1();
30519
30520    const create = () => (() => {
30521      let data = {};
30522      let keys = [];
30523      const storage = {
30524        getItem: key => {
30525          const item = data[key];
30526          return item ? item : null;
30527        },
30528        setItem: (key, value) => {
30529          keys.push(key);
30530          data[key] = String(value);
30531        },
30532        key: index => {
30533          return keys[index];
30534        },
30535        removeItem: key => {
30536          keys = keys.filter(k => k === key);
30537          delete data[key];
30538        },
30539        clear: () => {
30540          keys = [];
30541          data = {};
30542        },
30543        length: 0
30544      };
30545      Object.defineProperty(storage, 'length', {
30546        get: () => keys.length,
30547        configurable: false,
30548        enumerable: false
30549      });
30550      return storage;
30551    })();
30552
30553    let localStorage;
30554    try {
30555      const test = '__storage_test__';
30556      localStorage = window.localStorage;
30557      localStorage.setItem(test, test);
30558      localStorage.removeItem(test);
30559    } catch (e) {
30560      localStorage = create();
30561    }
30562    var LocalStorage = localStorage;
30563
30564    const publicApi = {
30565      geom: { Rect },
30566      util: {
30567        Delay,
30568        Tools,
30569        VK,
30570        URI,
30571        EventDispatcher,
30572        Observable,
30573        I18n,
30574        LocalStorage,
30575        ImageUploader
30576      },
30577      dom: {
30578        EventUtils,
30579        TreeWalker: DomTreeWalker,
30580        TextSeeker,
30581        DOMUtils,
30582        ScriptLoader,
30583        RangeUtils,
30584        Serializer: DomSerializer,
30585        StyleSheetLoader,
30586        ControlSelection,
30587        BookmarkManager,
30588        Selection: EditorSelection,
30589        Event: EventUtils.Event
30590      },
30591      html: {
30592        Styles,
30593        Entities,
30594        Node: AstNode,
30595        Schema,
30596        DomParser,
30597        Writer,
30598        Serializer: HtmlSerializer
30599      },
30600      Env,
30601      AddOnManager,
30602      Annotator,
30603      Formatter,
30604      UndoManager,
30605      EditorCommands,
30606      WindowManager,
30607      NotificationManager,
30608      EditorObservable,
30609      Shortcuts,
30610      Editor,
30611      FocusManager,
30612      EditorManager,
30613      DOM: DOMUtils.DOM,
30614      ScriptLoader: ScriptLoader.ScriptLoader,
30615      PluginManager,
30616      ThemeManager,
30617      ModelManager,
30618      IconManager,
30619      Resource,
30620      FakeClipboard,
30621      trim: Tools.trim,
30622      isArray: Tools.isArray,
30623      is: Tools.is,
30624      toArray: Tools.toArray,
30625      makeMap: Tools.makeMap,
30626      each: Tools.each,
30627      map: Tools.map,
30628      grep: Tools.grep,
30629      inArray: Tools.inArray,
30630      extend: Tools.extend,
30631      walk: Tools.walk,
30632      resolve: Tools.resolve,
30633      explode: Tools.explode,
30634      _addCacheSuffix: Tools._addCacheSuffix
30635    };
30636    const tinymce = Tools.extend(EditorManager, publicApi);
30637
30638    const exportToModuleLoaders = tinymce => {
30639      if (typeof module === 'object') {
30640        try {
30641          module.exports = tinymce;
30642        } catch (_) {
30643        }
30644      }
30645    };
30646    const exportToWindowGlobal = tinymce => {
30647      window.tinymce = tinymce;
30648      window.tinyMCE = tinymce;
30649    };
30650    exportToWindowGlobal(tinymce);
30651    exportToModuleLoaders(tinymce);
30652
30653})();
30654
30655
30656

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.