PageSourceSearch

https://www.nickhernbooks.co.uk/assets/260ee9aa/tinymce.js

js nickhernbooks.co.uk collected 2026-10-02 03:46:40 UTC 1,238,261 bytes, 32,258 lines download raw bytes

1/**
2 * TinyMCE version 7.7.1 (2025-03-05
vendor: 10,145 bytes, lines 2-390
2)
3 */
4
5(function () {
6    'use strict';
7
8    var typeOf$1 = function (x) {
9      if (x === null) {
10        return 'null';
11      }
12      if (x === undefined) {
13        return 'undefined';
14      }
15      var t = typeof x;
16      if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
17        return 'array';
18      }
19      if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
20        return 'string';
21      }
22      return t;
23    };
24    var isEquatableType = function (x) {
25      return [
26        'undefined',
27        'boolean',
28        'number',
29        'string',
30        'function',
31        'xml',
32        'null'
33      ].indexOf(x) !== -1;
34    };
35
36    var sort$1 = function (xs, compareFn) {
37      var clone = Array.prototype.slice.call(xs);
38      return clone.sort(compareFn);
39    };
40
41    var contramap = function (eqa, f) {
42      return eq$2(function (x, y) {
43        return eqa.eq(f(x), f(y));
44      });
45    };
46    var eq$2 = function (f) {
47      return { eq: f };
48    };
49    var tripleEq = eq$2(function (x, y) {
50      return x === y;
51    });
52    var eqString = tripleEq;
53    var eqArray = function (eqa) {
54      return eq$2(function (x, y) {
55        if (x.length !== y.length) {
56          return false;
57        }
58        var len = x.length;
59        for (var i = 0; i < len; i++) {
60          if (!eqa.eq(x[i], y[i])) {
61            return false;
62          }
63        }
64        return true;
65      });
66    };
67    var eqSortedArray = function (eqa, compareFn) {
68      return contramap(eqArray(eqa), function (xs) {
69        return sort$1(xs, compareFn);
70      });
71    };
72    var eqRecord = function (eqa) {
73      return eq$2(function (x, y) {
74        var kx = Object.keys(x);
75        var ky = Object.keys(y);
76        if (!eqSortedArray(eqString).eq(kx, ky)) {
77          return false;
78        }
79        var len = kx.length;
80        for (var i = 0; i < len; i++) {
81          var q = kx[i];
82          if (!eqa.eq(x[q], y[q])) {
83            return false;
84          }
85        }
86        return true;
87      });
88    };
89    var eqAny = eq$2(function (x, y) {
90      if (x === y) {
91        return true;
92      }
93      var tx = typeOf$1(x);
94      var ty = typeOf$1(y);
95      if (tx !== ty) {
96        return false;
97      }
98      if (isEquatableType(tx)) {
99        return x === y;
100      } else if (tx === 'array') {
101        return eqArray(eqAny).eq(x, y);
102      } else if (tx === 'object') {
103        return eqRecord(eqAny).eq(x, y);
104      }
105      return false;
106    });
107
108    const getPrototypeOf$2 = Object.getPrototypeOf;
109    const hasProto = (v, constructor, predicate) => {
110      var _a;
111      if (predicate(v, constructor.prototype)) {
112        return true;
113      } else {
114        return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
115      }
116    };
117    const typeOf = x => {
118      const t = typeof x;
119      if (x === null) {
120        return 'null';
121      } else if (t === 'object' && Array.isArray(x)) {
122        return 'array';
123      } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
124        return 'string';
125      } else {
126        return t;
127      }
128    };
129    const isType$1 = type => value => typeOf(value) === type;
130    const isSimpleType = type => value => typeof value === type;
131    const eq$1 = t => a => t === a;
132    const is$4 = (value, constructor) => isObject(value) && hasProto(value, constructor, (o, proto) => getPrototypeOf$2(o) === proto);
133    const isString = isType$1('string');
134    const isObject = isType$1('object');
135    const isPlainObject = value => is$4(value, Object);
136    const isArray$1 = isType$1('array');
137    const isNull = eq$1(null);
138    const isBoolean = isSimpleType('boolean');
139    const isUndefined = eq$1(undefined);
140    const isNullable = a => a === null || a === undefined;
141    const isNonNullable = a => !isNullable(a);
142    const isFunction = isSimpleType('function');
143    const isNumber = isSimpleType('number');
144    const isArrayOf = (value, pred) => {
145      if (isArray$1(value)) {
146        for (let i = 0, len = value.length; i < len; ++i) {
147          if (!pred(value[i])) {
148            return false;
149          }
150        }
151        return true;
152      }
153      return false;
154    };
155
156    const noop = () => {
157    };
158    const compose = (fa, fb) => {
159      return (...args) => {
160        return fa(fb.apply(null, args));
161      };
162    };
163    const compose1 = (fbc, fab) => a => fbc(fab(a));
164    const constant = value => {
165      return () => {
166        return value;
167      };
168    };
169    const identity = x => {
170      return x;
171    };
172    const tripleEquals = (a, b) => {
173      return a === b;
174    };
175    function curry(fn, ...initialArgs) {
176      return (...restArgs) => {
177        const all = initialArgs.concat(restArgs);
178        return fn.apply(null, all);
179      };
180    }
181    const not = f => t => !f(t);
182    const die = msg => {
183      return () => {
184        throw new Error(msg);
185      };
186    };
187    const apply$1 = f => {
188      return f();
189    };
190    const call = f => {
191      f();
192    };
193    const never = constant(false);
194    const always = constant(true);
195
196    class Optional {
197      constructor(tag, value) {
198        this.tag = tag;
199        this.value = value;
200      }
201      static some(value) {
202        return new Optional(true, value);
203      }
204      static none() {
205        return Optional.singletonNone;
206      }
207      fold(onNone, onSome) {
208        if (this.tag) {
209          return onSome(this.value);
210        } else {
211          return onNone();
212        }
213      }
214      isSome() {
215        return this.tag;
216      }
217      isNone() {
218        return !this.tag;
219      }
220      map(mapper) {
221        if (this.tag) {
222          return Optional.some(mapper(this.value));
223        } else {
224          return Optional.none();
225        }
226      }
227      bind(binder) {
228        if (this.tag) {
229          return binder(this.value);
230        } else {
231          return Optional.none();
232        }
233      }
234      exists(predicate) {
235        return this.tag && predicate(this.value);
236      }
237      forall(predicate) {
238        return !this.tag || predicate(this.value);
239      }
240      filter(predicate) {
241        if (!this.tag || predicate(this.value)) {
242          return this;
243        } else {
244          return Optional.none();
245        }
246      }
247      getOr(replacement) {
248        return this.tag ? this.value : replacement;
249      }
250      or(replacement) {
251        return this.tag ? this : replacement;
252      }
253      getOrThunk(thunk) {
254        return this.tag ? this.value : thunk();
255      }
256      orThunk(thunk) {
257        return this.tag ? this : thunk();
258      }
259      getOrDie(message) {
260        if (!this.tag) {
261          throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
262        } else {
263          return this.value;
264        }
265      }
266      static from(value) {
267        return isNonNullable(value) ? Optional.some(value) : Optional.none();
268      }
269      getOrNull() {
270        return this.tag ? this.value : null;
271      }
272      getOrUndefined() {
273        return this.value;
274      }
275      each(worker) {
276        if (this.tag) {
277          worker(this.value);
278        }
279      }
280      toArray() {
281        return this.tag ? [this.value] : [];
282      }
283      toString() {
284        return this.tag ? `some(${ this.value })` : 'none()';
285      }
286    }
287    Optional.singletonNone = new Optional(false);
288
289    const nativeSlice = Array.prototype.slice;
290    const nativeIndexOf = Array.prototype.indexOf;
291    const nativePush = Array.prototype.push;
292    const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
293    const indexOf$1 = (xs, x) => {
294      const r = rawIndexOf(xs, x);
295      return r === -1 ? Optional.none() : Optional.some(r);
296    };
297    const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
298    const exists = (xs, pred) => {
299      for (let i = 0, len = xs.length; i < len; i++) {
300        const x = xs[i];
301        if (pred(x, i)) {
302          return true;
303        }
304      }
305      return false;
306    };
307    const map$3 = (xs, f) => {
308      const len = xs.length;
309      const r = new Array(len);
310      for (let i = 0; i < len; i++) {
311        const x = xs[i];
312        r[i] = f(x, i);
313      }
314      return r;
315    };
316    const each$e = (xs, f) => {
317      for (let i = 0, len = xs.length; i < len; i++) {
318        const x = xs[i];
319        f(x, i);
320      }
321    };
322    const eachr = (xs, f) => {
323      for (let i = xs.length - 1; i >= 0; i--) {
324        const x = xs[i];
325        f(x, i);
326      }
327    };
328    const partition$2 = (xs, pred) => {
329      const pass = [];
330      const fail = [];
331      for (let i = 0, len = xs.length; i < len; i++) {
332        const x = xs[i];
333        const arr = pred(x, i) ? pass : fail;
334        arr.push(x);
335      }
336      return {
337        pass,
338        fail
339      };
340    };
341    const filter$5 = (xs, pred) => {
342      const r = [];
343      for (let i = 0, len = xs.length; i < len; i++) {
344        const x = xs[i];
345        if (pred(x, i)) {
346          r.push(x);
347        }
348      }
349      return r;
350    };
351    const foldr = (xs, f, acc) => {
352      eachr(xs, (x, i) => {
353        acc = f(acc, x, i);
354      });
355      return acc;
356    };
357    const foldl = (xs, f, acc) => {
358      each$e(xs, (x, i) => {
359        acc = f(acc, x, i);
360      });
361      return acc;
362    };
363    const findUntil$1 = (xs, pred, until) => {
364      for (let i = 0, len = xs.length; i < len; i++) {
365        const x = xs[i];
366        if (pred(x, i)) {
367          return Optional.some(x);
368        } else if (until(x, i)) {
369          break;
370        }
371      }
372      return Optional.none();
373    };
374    const find$2 = (xs, pred) => {
375      return findUntil$1(xs, pred, never);
376    };
377    const findIndex$2 = (xs, pred) => {
378      for (let i = 0, len = xs.length; i < len; i++) {
379        const x = xs[i];
380        if (pred(x, i)) {
381          return Optional.some(i);
382        }
383      }
384      return Optional.none();
385    };
386    const flatten = xs => {
387      const r = [];
388      for (let i = 0, len = xs.length; i < len; ++i) {
389        if (!isArray$1(xs[i])) {
390          throw new Error('Arr.flatten item ' + i + ' was not an array, input
vendor: 16,351 bytes, lines 390-958
390: ' + xs);
391        }
392        nativePush.apply(r, xs[i]);
393      }
394      return r;
395    };
396    const bind$3 = (xs, f) => flatten(map$3(xs, f));
397    const forall = (xs, pred) => {
398      for (let i = 0, len = xs.length; i < len; ++i) {
399        const x = xs[i];
400        if (pred(x, i) !== true) {
401          return false;
402        }
403      }
404      return true;
405    };
406    const reverse = xs => {
407      const r = nativeSlice.call(xs, 0);
408      r.reverse();
409      return r;
410    };
411    const difference = (a1, a2) => filter$5(a1, x => !contains$2(a2, x));
412    const mapToObject = (xs, f) => {
413      const r = {};
414      for (let i = 0, len = xs.length; i < len; i++) {
415        const x = xs[i];
416        r[String(x)] = f(x, i);
417      }
418      return r;
419    };
420    const sort = (xs, comparator) => {
421      const copy = nativeSlice.call(xs, 0);
422      copy.sort(comparator);
423      return copy;
424    };
425    const get$b = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
426    const head = xs => get$b(xs, 0);
427    const last$2 = xs => get$b(xs, xs.length - 1);
428    const from = isFunction(Array.from) ? Array.from : x => nativeSlice.call(x);
429    const findMap = (arr, f) => {
430      for (let i = 0; i < arr.length; i++) {
431        const r = f(arr[i], i);
432        if (r.isSome()) {
433          return r;
434        }
435      }
436      return Optional.none();
437    };
438    const unique$1 = (xs, comparator) => {
439      const r = [];
440      const isDuplicated = isFunction(comparator) ? x => exists(r, i => comparator(i, x)) : x => contains$2(r, x);
441      for (let i = 0, len = xs.length; i < len; i++) {
442        const x = xs[i];
443        if (!isDuplicated(x)) {
444          r.push(x);
445        }
446      }
447      return r;
448    };
449
450    const keys = Object.keys;
451    const hasOwnProperty$1 = Object.hasOwnProperty;
452    const each$d = (obj, f) => {
453      const props = keys(obj);
454      for (let k = 0, len = props.length; k < len; k++) {
455        const i = props[k];
456        const x = obj[i];
457        f(x, i);
458      }
459    };
460    const map$2 = (obj, f) => {
461      return tupleMap(obj, (x, i) => ({
462        k: i,
463        v: f(x, i)
464      }));
465    };
466    const tupleMap = (obj, f) => {
467      const r = {};
468      each$d(obj, (x, i) => {
469        const tuple = f(x, i);
470        r[tuple.k] = tuple.v;
471      });
472      return r;
473    };
474    const objAcc = r => (x, i) => {
475      r[i] = x;
476    };
477    const internalFilter = (obj, pred, onTrue, onFalse) => {
478      each$d(obj, (x, i) => {
479        (pred(x, i) ? onTrue : onFalse)(x, i);
480      });
481    };
482    const bifilter = (obj, pred) => {
483      const t = {};
484      const f = {};
485      internalFilter(obj, pred, objAcc(t), objAcc(f));
486      return {
487        t,
488        f
489      };
490    };
491    const filter$4 = (obj, pred) => {
492      const t = {};
493      internalFilter(obj, pred, objAcc(t), noop);
494      return t;
495    };
496    const mapToArray = (obj, f) => {
497      const r = [];
498      each$d(obj, (value, name) => {
499        r.push(f(value, name));
500      });
501      return r;
502    };
503    const values = obj => {
504      return mapToArray(obj, identity);
505    };
506    const get$a = (obj, key) => {
507      return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
508    };
509    const has$2 = (obj, key) => hasOwnProperty$1.call(obj, key);
510    const hasNonNullableKey = (obj, key) => has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
511    const equal$1 = (a1, a2, eq = eqAny) => eqRecord(eq).eq(a1, a2);
512
513    const stringArray = a => {
514      const all = {};
515      each$e(a, key => {
516        all[key] = {};
517      });
518      return keys(all);
519    };
520
521    const isArrayLike = o => o.length !== undefined;
522    const isArray = Array.isArray;
523    const toArray$1 = obj => {
524      if (!isArray(obj)) {
525        const array = [];
526        for (let i = 0, l = obj.length; i < l; i++) {
527          array[i] = obj[i];
528        }
529        return array;
530      } else {
531        return obj;
532      }
533    };
534    const each$c = (o, cb, s) => {
535      if (!o) {
536        return false;
537      }
538      s = s || o;
539      if (isArrayLike(o)) {
540        for (let n = 0, l = o.length; n < l; n++) {
541          if (cb.call(s, o[n], n, o) === false) {
542            return false;
543          }
544        }
545      } else {
546        for (const n in o) {
547          if (has$2(o, n)) {
548            if (cb.call(s, o[n], n, o) === false) {
549              return false;
550            }
551          }
552        }
553      }
554      return true;
555    };
556    const map$1 = (array, callback) => {
557      const out = [];
558      each$c(array, (item, index) => {
559        out.push(callback(item, index, array));
560      });
561      return out;
562    };
563    const filter$3 = (a, f) => {
564      const o = [];
565      each$c(a, (v, index) => {
566        if (!f || f(v, index, a)) {
567          o.push(v);
568        }
569      });
570      return o;
571    };
572    const indexOf = (a, v) => {
573      if (a) {
574        for (let i = 0, l = a.length; i < l; i++) {
575          if (a[i] === v) {
576            return i;
577          }
578        }
579      }
580      return -1;
581    };
582    const reduce = (collection, iteratee, accumulator, thisArg) => {
583      let acc = isUndefined(accumulator) ? collection[0] : accumulator;
584      for (let i = 0; i < collection.length; i++) {
585        acc = iteratee.call(thisArg, acc, collection[i], i);
586      }
587      return acc;
588    };
589    const findIndex$1 = (array, predicate, thisArg) => {
590      for (let i = 0, l = array.length; i < l; i++) {
591        if (predicate.call(thisArg, array[i], i, array)) {
592          return i;
593        }
594      }
595      return -1;
596    };
597    const last$1 = collection => collection[collection.length - 1];
598
599    const cached = f => {
600      let called = false;
601      let r;
602      return (...args) => {
603        if (!called) {
604          called = true;
605          r = f.apply(null, args);
606        }
607        return r;
608      };
609    };
610
611    const DeviceType = (os, browser, userAgent, mediaMatch) => {
612      const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
613      const isiPhone = os.isiOS() && !isiPad;
614      const isMobile = os.isiOS() || os.isAndroid();
615      const isTouch = isMobile || mediaMatch('(pointer:coarse)');
616      const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
617      const isPhone = isiPhone || isMobile && !isTablet;
618      const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
619      const isDesktop = !isPhone && !isTablet && !iOSwebview;
620      return {
621        isiPad: constant(isiPad),
622        isiPhone: constant(isiPhone),
623        isTablet: constant(isTablet),
624        isPhone: constant(isPhone),
625        isTouch: constant(isTouch),
626        isAndroid: os.isAndroid,
627        isiOS: os.isiOS,
628        isWebView: constant(iOSwebview),
629        isDesktop: constant(isDesktop)
630      };
631    };
632
633    const firstMatch = (regexes, s) => {
634      for (let i = 0; i < regexes.length; i++) {
635        const x = regexes[i];
636        if (x.test(s)) {
637          return x;
638        }
639      }
640      return undefined;
641    };
642    const find$1 = (regexes, agent) => {
643      const r = firstMatch(regexes, agent);
644      if (!r) {
645        return {
646          major: 0,
647          minor: 0
648        };
649      }
650      const group = i => {
651        return Number(agent.replace(r, '$' + i));
652      };
653      return nu$3(group(1), group(2));
654    };
655    const detect$4 = (versionRegexes, agent) => {
656      const cleanedAgent = String(agent).toLowerCase();
657      if (versionRegexes.length === 0) {
658        return unknown$2();
659      }
660      return find$1(versionRegexes, cleanedAgent);
661    };
662    const unknown$2 = () => {
663      return nu$3(0, 0);
664    };
665    const nu$3 = (major, minor) => {
666      return {
667        major,
668        minor
669      };
670    };
671    const Version = {
672      nu: nu$3,
673      detect: detect$4,
674      unknown: unknown$2
675    };
676
677    const detectBrowser$1 = (browsers, userAgentData) => {
678      return findMap(userAgentData.brands, uaBrand => {
679        const lcBrand = uaBrand.brand.toLowerCase();
680        return find$2(browsers, browser => {
681          var _a;
682          return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
683        }).map(info => ({
684          current: info.name,
685          version: Version.nu(parseInt(uaBrand.version, 10), 0)
686        }));
687      });
688    };
689
690    const detect$3 = (candidates, userAgent) => {
691      const agent = String(userAgent).toLowerCase();
692      return find$2(candidates, candidate => {
693        return candidate.search(agent);
694      });
695    };
696    const detectBrowser = (browsers, userAgent) => {
697      return detect$3(browsers, userAgent).map(browser => {
698        const version = Version.detect(browser.versionRegexes, userAgent);
699        return {
700          current: browser.name,
701          version
702        };
703      });
704    };
705    const detectOs = (oses, userAgent) => {
706      return detect$3(oses, userAgent).map(os => {
707        const version = Version.detect(os.versionRegexes, userAgent);
708        return {
709          current: os.name,
710          version
711        };
712      });
713    };
714
715    const removeFromStart = (str, numChars) => {
716      return str.substring(numChars);
717    };
718
719    const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
720    const removeLeading = (str, prefix) => {
721      return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str;
722    };
723    const contains$1 = (str, substr, start = 0, end) => {
724      const idx = str.indexOf(substr, start);
725      if (idx !== -1) {
726        return isUndefined(end) ? true : idx + substr.length <= end;
727      } else {
728        return false;
729      }
730    };
731    const startsWith = (str, prefix) => {
732      return checkRange(str, prefix, 0);
733    };
734    const endsWith = (str, suffix) => {
735      return checkRange(str, suffix, str.length - suffix.length);
736    };
737    const blank = r => s => s.replace(r, '');
738    const trim$4 = blank(/^\s+|\s+$/g);
739    const lTrim = blank(/^\s+/g);
740    const rTrim = blank(/\s+$/g);
741    const isNotEmpty = s => s.length > 0;
742    const isEmpty$3 = s => !isNotEmpty(s);
743    const repeat = (s, count) => count <= 0 ? '' : new Array(count + 1).join(s);
744    const toInt = (value, radix = 10) => {
745      const num = parseInt(value, radix);
746      return isNaN(num) ? Optional.none() : Optional.some(num);
747    };
748
749    const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
750    const checkContains = target => {
751      return uastring => {
752        return contains$1(uastring, target);
753      };
754    };
755    const browsers = [
756      {
757        name: 'Edge',
758        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
759        search: uastring => {
760          return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit');
761        }
762      },
763      {
764        name: 'Chromium',
765        brand: 'Chromium',
766        versionRegexes: [
767          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
768          normalVersionRegex
769        ],
770        search: uastring => {
771          return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe');
772        }
773      },
774      {
775        name: 'IE',
776        versionRegexes: [
777          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
778          /.*?rv:([0-9]+)\.([0-9]+).*/
779        ],
780        search: uastring => {
781          return contains$1(uastring, 'msie') || contains$1(uastring, 'trident');
782        }
783      },
784      {
785        name: 'Opera',
786        versionRegexes: [
787          normalVersionRegex,
788          /.*?opera\/([0-9]+)\.([0-9]+).*/
789        ],
790        search: checkContains('opera')
791      },
792      {
793        name: 'Firefox',
794        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
795        search: checkContains('firefox')
796      },
797      {
798        name: 'Safari',
799        versionRegexes: [
800          normalVersionRegex,
801          /.*?cpu os ([0-9]+)_([0-9]+).*/
802        ],
803        search: uastring => {
804          return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit');
805        }
806      }
807    ];
808    const oses = [
809      {
810        name: 'Windows',
811        search: checkContains('win'),
812        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
813      },
814      {
815        name: 'iOS',
816        search: uastring => {
817          return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad');
818        },
819        versionRegexes: [
820          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
821          /.*cpu os ([0-9]+)_([0-9]+).*/,
822          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
823        ]
824      },
825      {
826        name: 'Android',
827        search: checkContains('android'),
828        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
829      },
830      {
831        name: 'macOS',
832        search: checkContains('mac os x'),
833        versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
834      },
835      {
836        name: 'Linux',
837        search: checkContains('linux'),
838        versionRegexes: []
839      },
840      {
841        name: 'Solaris',
842        search: checkContains('sunos'),
843        versionRegexes: []
844      },
845      {
846        name: 'FreeBSD',
847        search: checkContains('freebsd'),
848        versionRegexes: []
849      },
850      {
851        name: 'ChromeOS',
852        search: checkContains('cros'),
853        versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
854      }
855    ];
856    const PlatformInfo = {
857      browsers: constant(browsers),
858      oses: constant(oses)
859    };
860
861    const edge = 'Edge';
862    const chromium = 'Chromium';
863    const ie = 'IE';
864    const opera = 'Opera';
865    const firefox = 'Firefox';
866    const safari = 'Safari';
867    const unknown$1 = () => {
868      return nu$2({
869        current: undefined,
870        version: Version.unknown()
871      });
872    };
873    const nu$2 = info => {
874      const current = info.current;
875      const version = info.version;
876      const isBrowser = name => () => current === name;
877      return {
878        current,
879        version,
880        isEdge: isBrowser(edge),
881        isChromium: isBrowser(chromium),
882        isIE: isBrowser(ie),
883        isOpera: isBrowser(opera),
884        isFirefox: isBrowser(firefox),
885        isSafari: isBrowser(safari)
886      };
887    };
888    const Browser = {
889      unknown: unknown$1,
890      nu: nu$2,
891      edge: constant(edge),
892      chromium: constant(chromium),
893      ie: constant(ie),
894      opera: constant(opera),
895      firefox: constant(firefox),
896      safari: constant(safari)
897    };
898
899    const windows = 'Windows';
900    const ios = 'iOS';
901    const android = 'Android';
902    const linux = 'Linux';
903    const macos = 'macOS';
904    const solaris = 'Solaris';
905    const freebsd = 'FreeBSD';
906    const chromeos = 'ChromeOS';
907    const unknown = () => {
908      return nu$1({
909        current: undefined,
910        version: Version.unknown()
911      });
912    };
913    const nu$1 = info => {
914      const current = info.current;
915      const version = info.version;
916      const isOS = name => () => current === name;
917      return {
918        current,
919        version,
920        isWindows: isOS(windows),
921        isiOS: isOS(ios),
922        isAndroid: isOS(android),
923        isMacOS: isOS(macos),
924        isLinux: isOS(linux),
925        isSolaris: isOS(solaris),
926        isFreeBSD: isOS(freebsd),
927        isChromeOS: isOS(chromeos)
928      };
929    };
930    const OperatingSystem = {
931      unknown,
932      nu: nu$1,
933      windows: constant(windows),
934      ios: constant(ios),
935      android: constant(android),
936      linux: constant(linux),
937      macos: constant(macos),
938      solaris: constant(solaris),
939      freebsd: constant(freebsd),
940      chromeos: constant(chromeos)
941    };
942
943    const detect$2 = (userAgent, userAgentDataOpt, mediaMatch) => {
944      const browsers = PlatformInfo.browsers();
945      const oses = PlatformInfo.oses();
946      const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
947      const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
948      const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
949      return {
950        browser,
951        os,
952        deviceType
953      };
954    };
955    const PlatformDetection = { detect: detect$2 };
956
957    const mediaMatch = query => window.matchMedia(query).matches;
958    let platform$4 = cached(() => PlatformDetection.detect(
vendor: 2,931 bytes, lines 958-1051
958window.navigator.userAgent, Optional.from(window.navigator.userAgentData), mediaMatch));
959    const detect$1 = () => platform$4();
960
961    const userAgent = window.navigator.userAgent;
962    const platform$3 = detect$1();
963    const browser$3 = platform$3.browser;
964    const os$1 = platform$3.os;
965    const deviceType = platform$3.deviceType;
966    const windowsPhone = userAgent.indexOf('Windows Phone') !== -1;
967    const Env = {
968      transparentSrc: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
969      documentMode: browser$3.isIE() ? document.documentMode || 7 : 10,
970      cacheSuffix: null,
971      container: null,
972      canHaveCSP: !browser$3.isIE(),
973      windowsPhone,
974      browser: {
975        current: browser$3.current,
976        version: browser$3.version,
977        isChromium: browser$3.isChromium,
978        isEdge: browser$3.isEdge,
979        isFirefox: browser$3.isFirefox,
980        isIE: browser$3.isIE,
981        isOpera: browser$3.isOpera,
982        isSafari: browser$3.isSafari
983      },
984      os: {
985        current: os$1.current,
986        version: os$1.version,
987        isAndroid: os$1.isAndroid,
988        isChromeOS: os$1.isChromeOS,
989        isFreeBSD: os$1.isFreeBSD,
990        isiOS: os$1.isiOS,
991        isLinux: os$1.isLinux,
992        isMacOS: os$1.isMacOS,
993        isSolaris: os$1.isSolaris,
994        isWindows: os$1.isWindows
995      },
996      deviceType: {
997        isDesktop: deviceType.isDesktop,
998        isiPad: deviceType.isiPad,
999        isiPhone: deviceType.isiPhone,
1000        isPhone: deviceType.isPhone,
1001        isTablet: deviceType.isTablet,
1002        isTouch: deviceType.isTouch,
1003        isWebView: deviceType.isWebView
1004      }
1005    };
1006
1007    const whiteSpaceRegExp$1 = /^\s*|\s*$/g;
1008    const trim$3 = str => {
1009      return isNullable(str) ? '' : ('' + str).replace(whiteSpaceRegExp$1, '');
1010    };
1011    const is$3 = (obj, type) => {
1012      if (!type) {
1013        return obj !== undefined;
1014      }
1015      if (type === 'array' && isArray(obj)) {
1016        return true;
1017      }
1018      return typeof obj === type;
1019    };
1020    const makeMap$4 = (items, delim, map = {}) => {
1021      const resolvedItems = isString(items) ? items.split(delim || ',') : items || [];
1022      let i = resolvedItems.length;
1023      while (i--) {
1024        map[resolvedItems[i]] = {};
1025      }
1026      return map;
1027    };
1028    const hasOwnProperty = has$2;
1029    const extend$3 = (obj, ...exts) => {
1030      for (let i = 0; i < exts.length; i++) {
1031        const ext = exts[i];
1032        for (const name in ext) {
1033          if (has$2(ext, name)) {
1034            const value = ext[name];
1035            if (value !== undefined) {
1036              obj[name] = value;
1037            }
1038          }
1039        }
1040      }
1041      return obj;
1042    };
1043    const walk$4 = function (o, f, n, s) {
1044      s = s || this;
1045      if (o) {
1046        if (n) {
1047          o = o[n];
1048        }
1049        each$c(o, (o, i) => {
1050          if (f.call(s, o, i, n) === false) {
1051            return false;
vendor: 16,632 bytes, lines 1052-1513
1052          } else {
1053            walk$4(o, f, n, s);
1054            return true;
1055          }
1056        });
1057      }
1058    };
1059    const resolve$3 = (n, o = window) => {
1060      const path = n.split('.');
1061      for (let i = 0, l = path.length; i < l; i++) {
1062        o = o[path[i]];
1063        if (!o) {
1064          break;
1065        }
1066      }
1067      return o;
1068    };
1069    const explode$3 = (s, d) => {
1070      if (isArray$1(s)) {
1071        return s;
1072      } else if (s === '') {
1073        return [];
1074      } else {
1075        return map$1(s.split(d || ','), trim$3);
1076      }
1077    };
1078    const _addCacheSuffix = url => {
1079      const cacheSuffix = Env.cacheSuffix;
1080      if (cacheSuffix) {
1081        url += (url.indexOf('?') === -1 ? '?' : '&') + cacheSuffix;
1082      }
1083      return url;
1084    };
1085    const Tools = {
1086      trim: trim$3,
1087      isArray: isArray,
1088      is: is$3,
1089      toArray: toArray$1,
1090      makeMap: makeMap$4,
1091      each: each$c,
1092      map: map$1,
1093      grep: filter$3,
1094      inArray: indexOf,
1095      hasOwn: hasOwnProperty,
1096      extend: extend$3,
1097      walk: walk$4,
1098      resolve: resolve$3,
1099      explode: explode$3,
1100      _addCacheSuffix
1101    };
1102
1103    const is$2 = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
1104    const equals = (lhs, rhs, comparator = tripleEquals) => lift2(lhs, rhs, comparator).getOr(lhs.isNone() && rhs.isNone());
1105    const cat = arr => {
1106      const r = [];
1107      const push = x => {
1108        r.push(x);
1109      };
1110      for (let i = 0; i < arr.length; i++) {
1111        arr[i].each(push);
1112      }
1113      return r;
1114    };
1115    const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
1116    const lift3 = (oa, ob, oc, f) => oa.isSome() && ob.isSome() && oc.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie())) : Optional.none();
1117    const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
1118
1119    const Global = typeof window !== 'undefined' ? window : Function('return this;')();
1120
1121    const path = (parts, scope) => {
1122      let o = scope !== undefined && scope !== null ? scope : Global;
1123      for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
1124        o = o[parts[i]];
1125      }
1126      return o;
1127    };
1128    const resolve$2 = (p, scope) => {
1129      const parts = p.split('.');
1130      return path(parts, scope);
1131    };
1132
1133    const unsafe = (name, scope) => {
1134      return resolve$2(name, scope);
1135    };
1136    const getOrDie = (name, scope) => {
1137      const actual = unsafe(name, scope);
1138      if (actual === undefined || actual === null) {
1139        throw new Error(name + ' not available on this browser');
1140      }
1141      return actual;
1142    };
1143
1144    const getPrototypeOf$1 = Object.getPrototypeOf;
1145    const sandHTMLElement = scope => {
1146      return getOrDie('HTMLElement', scope);
1147    };
1148    const isPrototypeOf = x => {
1149      const scope = resolve$2('ownerDocument.defaultView', x);
1150      return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf$1(x).constructor.name));
1151    };
1152
1153    const COMMENT = 8;
1154    const DOCUMENT = 9;
1155    const DOCUMENT_FRAGMENT = 11;
1156    const ELEMENT = 1;
1157    const TEXT = 3;
1158
1159    const name = element => {
1160      const r = element.dom.nodeName;
1161      return r.toLowerCase();
1162    };
1163    const type$1 = element => element.dom.nodeType;
1164    const isType = t => element => type$1(element) === t;
1165    const isComment$1 = element => type$1(element) === COMMENT || name(element) === '#comment';
1166    const isHTMLElement$1 = element => isElement$7(element) && isPrototypeOf(element.dom);
1167    const isElement$7 = isType(ELEMENT);
1168    const isText$c = isType(TEXT);
1169    const isDocument$2 = isType(DOCUMENT);
1170    const isDocumentFragment$1 = isType(DOCUMENT_FRAGMENT);
1171    const isTag = tag => e => isElement$7(e) && name(e) === tag;
1172
1173    const rawSet = (dom, key, value) => {
1174      if (isString(value) || isBoolean(value) || isNumber(value)) {
1175        dom.setAttribute(key, value + '');
1176      } else {
1177        console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
1178        throw new Error('Attribute value was not simple');
1179      }
1180    };
1181    const set$4 = (element, key, value) => {
1182      rawSet(element.dom, key, value);
1183    };
1184    const setAll$1 = (element, attrs) => {
1185      const dom = element.dom;
1186      each$d(attrs, (v, k) => {
1187        rawSet(dom, k, v);
1188      });
1189    };
1190    const get$9 = (element, key) => {
1191      const v = element.dom.getAttribute(key);
1192      return v === null ? undefined : v;
1193    };
1194    const getOpt = (element, key) => Optional.from(get$9(element, key));
1195    const has$1 = (element, key) => {
1196      const dom = element.dom;
1197      return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
1198    };
1199    const remove$9 = (element, key) => {
1200      element.dom.removeAttribute(key);
1201    };
1202    const hasNone = element => {
1203      const attrs = element.dom.attributes;
1204      return attrs === undefined || attrs === null || attrs.length === 0;
1205    };
1206    const clone$4 = element => foldl(element.dom.attributes, (acc, attr) => {
1207      acc[attr.name] = attr.value;
1208      return acc;
1209    }, {});
1210
1211    const read$4 = (element, attr) => {
1212      const value = get$9(element, attr);
1213      return value === undefined || value === '' ? [] : value.split(' ');
1214    };
1215    const add$4 = (element, attr, id) => {
1216      const old = read$4(element, attr);
1217      const nu = old.concat([id]);
1218      set$4(element, attr, nu.join(' '));
1219      return true;
1220    };
1221    const remove$8 = (element, attr, id) => {
1222      const nu = filter$5(read$4(element, attr), v => v !== id);
1223      if (nu.length > 0) {
1224        set$4(element, attr, nu.join(' '));
1225      } else {
1226        remove$9(element, attr);
1227      }
1228      return false;
1229    };
1230
1231    const supports = element => element.dom.classList !== undefined;
1232    const get$8 = element => read$4(element, 'class');
1233    const add$3 = (element, clazz) => add$4(element, 'class', clazz);
1234    const remove$7 = (element, clazz) => remove$8(element, 'class', clazz);
1235    const toggle$2 = (element, clazz) => {
1236      if (contains$2(get$8(element), clazz)) {
1237        return remove$7(element, clazz);
1238      } else {
1239        return add$3(element, clazz);
1240      }
1241    };
1242
1243    const add$2 = (element, clazz) => {
1244      if (supports(element)) {
1245        element.dom.classList.add(clazz);
1246      } else {
1247        add$3(element, clazz);
1248      }
1249    };
1250    const cleanClass = element => {
1251      const classList = supports(element) ? element.dom.classList : get$8(element);
1252      if (classList.length === 0) {
1253        remove$9(element, 'class');
1254      }
1255    };
1256    const remove$6 = (element, clazz) => {
1257      if (supports(element)) {
1258        const classList = element.dom.classList;
1259        classList.remove(clazz);
1260      } else {
1261        remove$7(element, clazz);
1262      }
1263      cleanClass(element);
1264    };
1265    const toggle$1 = (element, clazz) => {
1266      const result = supports(element) ? element.dom.classList.toggle(clazz) : toggle$2(element, clazz);
1267      cleanClass(element);
1268      return result;
1269    };
1270    const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
1271
1272    const fromHtml$1 = (html, scope) => {
1273      const doc = scope || document;
1274      const div = doc.createElement('div');
1275      div.innerHTML = html;
1276      if (!div.hasChildNodes() || div.childNodes.length > 1) {
1277        const message = 'HTML does not have a single root node';
1278        console.error(message, html);
1279        throw new Error(message);
1280      }
1281      return fromDom$2(div.childNodes[0]);
1282    };
1283    const fromTag = (tag, scope) => {
1284      const doc = scope || document;
1285      const node = doc.createElement(tag);
1286      return fromDom$2(node);
1287    };
1288    const fromText = (text, scope) => {
1289      const doc = scope || document;
1290      const node = doc.createTextNode(text);
1291      return fromDom$2(node);
1292    };
1293    const fromDom$2 = node => {
1294      if (node === null || node === undefined) {
1295        throw new Error('Node cannot be null or undefined');
1296      }
1297      return { dom: node };
1298    };
1299    const fromPoint$2 = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$2);
1300    const SugarElement = {
1301      fromHtml: fromHtml$1,
1302      fromTag,
1303      fromText,
1304      fromDom: fromDom$2,
1305      fromPoint: fromPoint$2
1306    };
1307
1308    const toArray = (target, f) => {
1309      const r = [];
1310      const recurse = e => {
1311        r.push(e);
1312        return f(e);
1313      };
1314      let cur = f(target);
1315      do {
1316        cur = cur.bind(recurse);
1317      } while (cur.isSome());
1318      return r;
1319    };
1320
1321    const is$1 = (element, selector) => {
1322      const dom = element.dom;
1323      if (dom.nodeType !== ELEMENT) {
1324        return false;
1325      } else {
1326        const elem = dom;
1327        if (elem.matches !== undefined) {
1328          return elem.matches(selector);
1329        } else if (elem.msMatchesSelector !== undefined) {
1330          return elem.msMatchesSelector(selector);
1331        } else if (elem.webkitMatchesSelector !== undefined) {
1332          return elem.webkitMatchesSelector(selector);
1333        } else if (elem.mozMatchesSelector !== undefined) {
1334          return elem.mozMatchesSelector(selector);
1335        } else {
1336          throw new Error('Browser lacks native selectors');
1337        }
1338      }
1339    };
1340    const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
1341    const all = (selector, scope) => {
1342      const base = scope === undefined ? document : scope.dom;
1343      return bypassSelector(base) ? [] : map$3(base.querySelectorAll(selector), SugarElement.fromDom);
1344    };
1345    const one = (selector, scope) => {
1346      const base = scope === undefined ? document : scope.dom;
1347      return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
1348    };
1349
1350    const eq = (e1, e2) => e1.dom === e2.dom;
1351    const contains = (e1, e2) => {
1352      const d1 = e1.dom;
1353      const d2 = e2.dom;
1354      return d1 === d2 ? false : d1.contains(d2);
1355    };
1356
1357    const owner$1 = element => SugarElement.fromDom(element.dom.ownerDocument);
1358    const documentOrOwner = dos => isDocument$2(dos) ? dos : owner$1(dos);
1359    const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
1360    const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
1361    const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
1362    const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
1363    const parents$1 = (element, isRoot) => {
1364      const stop = isFunction(isRoot) ? isRoot : never;
1365      let dom = element.dom;
1366      const ret = [];
1367      while (dom.parentNode !== null && dom.parentNode !== undefined) {
1368        const rawParent = dom.parentNode;
1369        const p = SugarElement.fromDom(rawParent);
1370        ret.push(p);
1371        if (stop(p) === true) {
1372          break;
1373        } else {
1374          dom = rawParent;
1375        }
1376      }
1377      return ret;
1378    };
1379    const siblings = element => {
1380      const filterSelf = elements => filter$5(elements, x => !eq(element, x));
1381      return parent(element).map(children$1).map(filterSelf).getOr([]);
1382    };
1383    const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
1384    const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
1385    const prevSiblings = element => reverse(toArray(element, prevSibling));
1386    const nextSiblings = element => toArray(element, nextSibling);
1387    const children$1 = element => map$3(element.dom.childNodes, SugarElement.fromDom);
1388    const child$1 = (element, index) => {
1389      const cs = element.dom.childNodes;
1390      return Optional.from(cs[index]).map(SugarElement.fromDom);
1391    };
1392    const firstChild = element => child$1(element, 0);
1393    const lastChild = element => child$1(element, element.dom.childNodes.length - 1);
1394    const childNodesCount = element => element.dom.childNodes.length;
1395
1396    const getHead = doc => {
1397      const b = doc.dom.head;
1398      if (b === null || b === undefined) {
1399        throw new Error('Head is not available yet');
1400      }
1401      return SugarElement.fromDom(b);
1402    };
1403
1404    const isShadowRoot = dos => isDocumentFragment$1(dos) && isNonNullable(dos.dom.host);
1405    const getRootNode = e => SugarElement.fromDom(e.dom.getRootNode());
1406    const getStyleContainer = dos => isShadowRoot(dos) ? dos : getHead(documentOrOwner(dos));
1407    const getContentContainer = dos => isShadowRoot(dos) ? dos : SugarElement.fromDom(documentOrOwner(dos).dom.body);
1408    const getShadowRoot = e => {
1409      const r = getRootNode(e);
1410      return isShadowRoot(r) ? Optional.some(r) : Optional.none();
1411    };
1412    const getShadowHost = e => SugarElement.fromDom(e.dom.host);
1413    const getOriginalEventTarget = event => {
1414      if (isNonNullable(event.target)) {
1415        const el = SugarElement.fromDom(event.target);
1416        if (isElement$7(el) && isOpenShadowHost(el)) {
1417          if (event.composed && event.composedPath) {
1418            const composedPath = event.composedPath();
1419            if (composedPath) {
1420              return head(composedPath);
1421            }
1422          }
1423        }
1424      }
1425      return Optional.from(event.target);
1426    };
1427    const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
1428
1429    const inBody = element => {
1430      const dom = isText$c(element) ? element.dom.parentNode : element.dom;
1431      if (dom === undefined || dom === null || dom.ownerDocument === null) {
1432        return false;
1433      }
1434      const doc = dom.ownerDocument;
1435      return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
1436    };
1437
1438    var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
1439      if (is(scope, a)) {
1440        return Optional.some(scope);
1441      } else if (isFunction(isRoot) && isRoot(scope)) {
1442        return Optional.none();
1443      } else {
1444        return ancestor(scope, a, isRoot);
1445      }
1446    };
1447
1448    const ancestor$4 = (scope, predicate, isRoot) => {
1449      let element = scope.dom;
1450      const stop = isFunction(isRoot) ? isRoot : never;
1451      while (element.parentNode) {
1452        element = element.parentNode;
1453        const el = SugarElement.fromDom(element);
1454        if (predicate(el)) {
1455          return Optional.some(el);
1456        } else if (stop(el)) {
1457          break;
1458        }
1459      }
1460      return Optional.none();
1461    };
1462    const closest$4 = (scope, predicate, isRoot) => {
1463      const is = (s, test) => test(s);
1464      return ClosestOrAncestor(is, ancestor$4, scope, predicate, isRoot);
1465    };
1466    const sibling$1 = (scope, predicate) => {
1467      const element = scope.dom;
1468      if (!element.parentNode) {
1469        return Optional.none();
1470      }
1471      return child(SugarElement.fromDom(element.parentNode), x => !eq(scope, x) && predicate(x));
1472    };
1473    const child = (scope, predicate) => {
1474      const pred = node => predicate(SugarElement.fromDom(node));
1475      const result = find$2(scope.dom.childNodes, pred);
1476      return result.map(SugarElement.fromDom);
1477    };
1478    const descendant$2 = (scope, predicate) => {
1479      const descend = node => {
1480        for (let i = 0; i < node.childNodes.length; i++) {
1481          const child = SugarElement.fromDom(node.childNodes[i]);
1482          if (predicate(child)) {
1483            return Optional.some(child);
1484          }
1485          const res = descend(node.childNodes[i]);
1486          if (res.isSome()) {
1487            return res;
1488          }
1489        }
1490        return Optional.none();
1491      };
1492      return descend(scope.dom);
1493    };
1494
1495    const ancestor$3 = (scope, selector, isRoot) => ancestor$4(scope, e => is$1(e, selector), isRoot);
1496    const descendant$1 = (scope, selector) => one(selector, scope);
1497    const closest$3 = (scope, selector, isRoot) => {
1498      const is = (element, selector) => is$1(element, selector);
1499      return ClosestOrAncestor(is, ancestor$3, scope, selector, isRoot);
1500    };
1501
1502    const closest$2 = target => closest$3(target, '[contenteditable]');
1503    const isEditable$2 = (element, assumeEditable = false) => {
1504      if (inBody(element)) {
1505        return element.dom.isContentEditable;
1506      } else {
1507        return closest$2(element).fold(constant(assumeEditable), editable => getRaw$1(editable) === 'true');
1508      }
1509    };
1510    const getRaw$1 = element => element.dom.contentEditable;
1511    const set$3 = (element, editable) => {
1512      element.dom.contentEditable = editable ? 'true' : 'false';
1513    }
vendor: 16,462 bytes, lines 1513-2002
1513;
1514
1515    const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
1516
1517    const internalSet = (dom, property, value) => {
1518      if (!isString(value)) {
1519        console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
1520        throw new Error('CSS value must be a string: ' + value);
1521      }
1522      if (isSupported(dom)) {
1523        dom.style.setProperty(property, value);
1524      }
1525    };
1526    const internalRemove = (dom, property) => {
1527      if (isSupported(dom)) {
1528        dom.style.removeProperty(property);
1529      }
1530    };
1531    const set$2 = (element, property, value) => {
1532      const dom = element.dom;
1533      internalSet(dom, property, value);
1534    };
1535    const setAll = (element, css) => {
1536      const dom = element.dom;
1537      each$d(css, (v, k) => {
1538        internalSet(dom, k, v);
1539      });
1540    };
1541    const get$7 = (element, property) => {
1542      const dom = element.dom;
1543      const styles = window.getComputedStyle(dom);
1544      const r = styles.getPropertyValue(property);
1545      return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
1546    };
1547    const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : '';
1548    const getRaw = (element, property) => {
1549      const dom = element.dom;
1550      const raw = getUnsafeProperty(dom, property);
1551      return Optional.from(raw).filter(r => r.length > 0);
1552    };
1553    const getAllRaw = element => {
1554      const css = {};
1555      const dom = element.dom;
1556      if (isSupported(dom)) {
1557        for (let i = 0; i < dom.style.length; i++) {
1558          const ruleName = dom.style.item(i);
1559          css[ruleName] = dom.style[ruleName];
1560        }
1561      }
1562      return css;
1563    };
1564    const remove$5 = (element, property) => {
1565      const dom = element.dom;
1566      internalRemove(dom, property);
1567      if (is$2(getOpt(element, 'style').map(trim$4), '')) {
1568        remove$9(element, 'style');
1569      }
1570    };
1571    const reflow = e => e.dom.offsetWidth;
1572
1573    const before$3 = (marker, element) => {
1574      const parent$1 = parent(marker);
1575      parent$1.each(v => {
1576        v.dom.insertBefore(element.dom, marker.dom);
1577      });
1578    };
1579    const after$4 = (marker, element) => {
1580      const sibling = nextSibling(marker);
1581      sibling.fold(() => {
1582        const parent$1 = parent(marker);
1583        parent$1.each(v => {
1584          append$1(v, element);
1585        });
1586      }, v => {
1587        before$3(v, element);
1588      });
1589    };
1590    const prepend = (parent, element) => {
1591      const firstChild$1 = firstChild(parent);
1592      firstChild$1.fold(() => {
1593        append$1(parent, element);
1594      }, v => {
1595        parent.dom.insertBefore(element.dom, v.dom);
1596      });
1597    };
1598    const append$1 = (parent, element) => {
1599      parent.dom.appendChild(element.dom);
1600    };
1601    const wrap$2 = (element, wrapper) => {
1602      before$3(element, wrapper);
1603      append$1(wrapper, element);
1604    };
1605
1606    const after$3 = (marker, elements) => {
1607      each$e(elements, (x, i) => {
1608        const e = i === 0 ? marker : elements[i - 1];
1609        after$4(e, x);
1610      });
1611    };
1612    const append = (parent, elements) => {
1613      each$e(elements, x => {
1614        append$1(parent, x);
1615      });
1616    };
1617
1618    const empty = element => {
1619      element.dom.textContent = '';
1620      each$e(children$1(element), rogue => {
1621        remove$4(rogue);
1622      });
1623    };
1624    const remove$4 = element => {
1625      const dom = element.dom;
1626      if (dom.parentNode !== null) {
1627        dom.parentNode.removeChild(dom);
1628      }
1629    };
1630    const unwrap = wrapper => {
1631      const children = children$1(wrapper);
1632      if (children.length > 0) {
1633        after$3(wrapper, children);
1634      }
1635      remove$4(wrapper);
1636    };
1637
1638    const fromHtml = (html, scope) => {
1639      const doc = scope || document;
1640      const div = doc.createElement('div');
1641      div.innerHTML = html;
1642      return children$1(SugarElement.fromDom(div));
1643    };
1644    const fromDom$1 = nodes => map$3(nodes, SugarElement.fromDom);
1645
1646    const get$6 = element => element.dom.innerHTML;
1647    const set$1 = (element, content) => {
1648      const owner = owner$1(element);
1649      const docDom = owner.dom;
1650      const fragment = SugarElement.fromDom(docDom.createDocumentFragment());
1651      const contentElements = fromHtml(content, docDom);
1652      append(fragment, contentElements);
1653      empty(element);
1654      append$1(element, fragment);
1655    };
1656    const getOuter = element => {
1657      const container = SugarElement.fromTag('div');
1658      const clone = SugarElement.fromDom(element.dom.cloneNode(true));
1659      append$1(container, clone);
1660      return get$6(container);
1661    };
1662
1663    const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
1664      target,
1665      x,
1666      y,
1667      stop,
1668      prevent,
1669      kill,
1670      raw
1671    });
1672    const fromRawEvent = rawEvent => {
1673      const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
1674      const stop = () => rawEvent.stopPropagation();
1675      const prevent = () => rawEvent.preventDefault();
1676      const kill = compose(prevent, stop);
1677      return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
1678    };
1679    const handle$1 = (filter, handler) => rawEvent => {
1680      if (filter(rawEvent)) {
1681        handler(fromRawEvent(rawEvent));
1682      }
1683    };
1684    const binder = (element, event, filter, handler, useCapture) => {
1685      const wrapped = handle$1(filter, handler);
1686      element.dom.addEventListener(event, wrapped, useCapture);
1687      return { unbind: curry(unbind, element, event, wrapped, useCapture) };
1688    };
1689    const bind$2 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
1690    const unbind = (element, event, handler, useCapture) => {
1691      element.dom.removeEventListener(event, handler, useCapture);
1692    };
1693
1694    const r = (left, top) => {
1695      const translate = (x, y) => r(left + x, top + y);
1696      return {
1697        left,
1698        top,
1699        translate
1700      };
1701    };
1702    const SugarPosition = r;
1703
1704    const boxPosition = dom => {
1705      const box = dom.getBoundingClientRect();
1706      return SugarPosition(box.left, box.top);
1707    };
1708    const firstDefinedOrZero = (a, b) => {
1709      if (a !== undefined) {
1710        return a;
1711      } else {
1712        return b !== undefined ? b : 0;
1713      }
1714    };
1715    const absolute = element => {
1716      const doc = element.dom.ownerDocument;
1717      const body = doc.body;
1718      const win = doc.defaultView;
1719      const html = doc.documentElement;
1720      if (body === element.dom) {
1721        return SugarPosition(body.offsetLeft, body.offsetTop);
1722      }
1723      const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop);
1724      const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft);
1725      const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
1726      const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
1727      return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
1728    };
1729    const viewport = element => {
1730      const dom = element.dom;
1731      const doc = dom.ownerDocument;
1732      const body = doc.body;
1733      if (body === dom) {
1734        return SugarPosition(body.offsetLeft, body.offsetTop);
1735      }
1736      if (!inBody(element)) {
1737        return SugarPosition(0, 0);
1738      }
1739      return boxPosition(dom);
1740    };
1741
1742    const get$5 = _DOC => {
1743      const doc = _DOC !== undefined ? _DOC.dom : document;
1744      const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
1745      const y = doc.body.scrollTop || doc.documentElement.scrollTop;
1746      return SugarPosition(x, y);
1747    };
1748    const to = (x, y, _DOC) => {
1749      const doc = _DOC !== undefined ? _DOC.dom : document;
1750      const win = doc.defaultView;
1751      if (win) {
1752        win.scrollTo(x, y);
1753      }
1754    };
1755    const intoView = (element, alignToTop) => {
1756      const isSafari = detect$1().browser.isSafari();
1757      if (isSafari && isFunction(element.dom.scrollIntoViewIfNeeded)) {
1758        element.dom.scrollIntoViewIfNeeded(false);
1759      } else {
1760        element.dom.scrollIntoView(alignToTop);
1761      }
1762    };
1763
1764    const get$4 = _win => {
1765      const win = _win === undefined ? window : _win;
1766      if (detect$1().browser.isFirefox()) {
1767        return Optional.none();
1768      } else {
1769        return Optional.from(win.visualViewport);
1770      }
1771    };
1772    const bounds = (x, y, width, height) => ({
1773      x,
1774      y,
1775      width,
1776      height,
1777      right: x + width,
1778      bottom: y + height
1779    });
1780    const getBounds = _win => {
1781      const win = _win === undefined ? window : _win;
1782      const doc = win.document;
1783      const scroll = get$5(SugarElement.fromDom(doc));
1784      return get$4(win).fold(() => {
1785        const html = win.document.documentElement;
1786        const width = html.clientWidth;
1787        const height = html.clientHeight;
1788        return bounds(scroll.left, scroll.top, width, height);
1789      }, visualViewport => bounds(Math.max(visualViewport.pageLeft, scroll.left), Math.max(visualViewport.pageTop, scroll.top), visualViewport.width, visualViewport.height));
1790    };
1791
1792    const children = (scope, predicate) => filter$5(children$1(scope), predicate);
1793    const descendants$1 = (scope, predicate) => {
1794      let result = [];
1795      each$e(children$1(scope), x => {
1796        if (predicate(x)) {
1797          result = result.concat([x]);
1798        }
1799        result = result.concat(descendants$1(x, predicate));
1800      });
1801      return result;
1802    };
1803
1804    const descendants = (scope, selector) => all(selector, scope);
1805
1806    const ancestor$2 = (scope, predicate, isRoot) => ancestor$4(scope, predicate, isRoot).isSome();
1807    const sibling = (scope, predicate) => sibling$1(scope, predicate).isSome();
1808    const descendant = (scope, predicate) => descendant$2(scope, predicate).isSome();
1809
1810    class DomTreeWalker {
1811      constructor(startNode, rootNode) {
1812        this.node = startNode;
1813        this.rootNode = rootNode;
1814        this.current = this.current.bind(this);
1815        this.next = this.next.bind(this);
1816        this.prev = this.prev.bind(this);
1817        this.prev2 = this.prev2.bind(this);
1818      }
1819      current() {
1820        return this.node;
1821      }
1822      next(shallow) {
1823        this.node = this.findSibling(this.node, 'firstChild', 'nextSibling', shallow);
1824        return this.node;
1825      }
1826      prev(shallow) {
1827        this.node = this.findSibling(this.node, 'lastChild', 'previousSibling', shallow);
1828        return this.node;
1829      }
1830      prev2(shallow) {
1831        this.node = this.findPreviousNode(this.node, shallow);
1832        return this.node;
1833      }
1834      findSibling(node, startName, siblingName, shallow) {
1835        if (node) {
1836          if (!shallow && node[startName]) {
1837            return node[startName];
1838          }
1839          if (node !== this.rootNode) {
1840            let sibling = node[siblingName];
1841            if (sibling) {
1842              return sibling;
1843            }
1844            for (let parent = node.parentNode; parent && parent !== this.rootNode; parent = parent.parentNode) {
1845              sibling = parent[siblingName];
1846              if (sibling) {
1847                return sibling;
1848              }
1849            }
1850          }
1851        }
1852        return undefined;
1853      }
1854      findPreviousNode(node, shallow) {
1855        if (node) {
1856          const sibling = node.previousSibling;
1857          if (this.rootNode && sibling === this.rootNode) {
1858            return;
1859          }
1860          if (sibling) {
1861            if (!shallow) {
1862              for (let child = sibling.lastChild; child; child = child.lastChild) {
1863                if (!child.lastChild) {
1864                  return child;
1865                }
1866              }
1867            }
1868            return sibling;
1869          }
1870          const parent = node.parentNode;
1871          if (parent && parent !== this.rootNode) {
1872            return parent;
1873          }
1874        }
1875        return undefined;
1876      }
1877    }
1878
1879    const zeroWidth = '\uFEFF';
1880    const nbsp = '\xA0';
1881    const isZwsp$2 = char => char === zeroWidth;
1882    const removeZwsp = s => s.replace(/\uFEFF/g, '');
1883
1884    const whiteSpaceRegExp = /^[ \t\r\n]*$/;
1885    const isWhitespaceText = text => whiteSpaceRegExp.test(text);
1886    const isZwsp$1 = text => {
1887      for (const c of text) {
1888        if (!isZwsp$2(c)) {
1889          return false;
1890        }
1891      }
1892      return true;
1893    };
1894    const isCollapsibleWhitespace$1 = c => ' \f\t\x0B'.indexOf(c) !== -1;
1895    const isNewLineChar = c => c === '\n' || c === '\r';
1896    const isNewline = (text, idx) => idx < text.length && idx >= 0 ? isNewLineChar(text[idx]) : false;
1897    const normalize$4 = (text, tabSpaces = 4, isStartOfContent = true, isEndOfContent = true) => {
1898      const tabSpace = repeat(' ', tabSpaces);
1899      const normalizedText = text.replace(/\t/g, tabSpace);
1900      const result = foldl(normalizedText, (acc, c) => {
1901        if (isCollapsibleWhitespace$1(c) || c === nbsp) {
1902          if (acc.pcIsSpace || acc.str === '' && isStartOfContent || acc.str.length === normalizedText.length - 1 && isEndOfContent || isNewline(normalizedText, acc.str.length + 1)) {
1903            return {
1904              pcIsSpace: false,
1905              str: acc.str + nbsp
1906            };
1907          } else {
1908            return {
1909              pcIsSpace: true,
1910              str: acc.str + ' '
1911            };
1912          }
1913        } else {
1914          return {
1915            pcIsSpace: isNewLineChar(c),
1916            str: acc.str + c
1917          };
1918        }
1919      }, {
1920        pcIsSpace: false,
1921        str: ''
1922      });
1923      return result.str;
1924    };
1925
1926    const isNodeType = type => {
1927      return node => {
1928        return !!node && node.nodeType === type;
1929      };
1930    };
1931    const isRestrictedNode = node => !!node && !Object.getPrototypeOf(node);
1932    const isElement$6 = isNodeType(1);
1933    const isHTMLElement = node => isElement$6(node) && isHTMLElement$1(SugarElement.fromDom(node));
1934    const isSVGElement = node => isElement$6(node) && node.namespaceURI === 'http://www.w3.org/2000/svg';
1935    const matchNodeName = name => {
1936      const lowerCasedName = name.toLowerCase();
1937      return node => isNonNullable(node) && node.nodeName.toLowerCase() === lowerCasedName;
1938    };
1939    const matchNodeNames = names => {
1940      const lowerCasedNames = names.map(s => s.toLowerCase());
1941      return node => {
1942        if (node && node.nodeName) {
1943          const nodeName = node.nodeName.toLowerCase();
1944          return contains$2(lowerCasedNames, nodeName);
1945        }
1946        return false;
1947      };
1948    };
1949    const matchStyleValues = (name, values) => {
1950      const items = values.toLowerCase().split(' ');
1951      return node => {
1952        if (isElement$6(node)) {
1953          const win = node.ownerDocument.defaultView;
1954          if (win) {
1955            for (let i = 0; i < items.length; i++) {
1956              const computed = win.getComputedStyle(node, null);
1957              const cssValue = computed ? computed.getPropertyValue(name) : null;
1958              if (cssValue === items[i]) {
1959                return true;
1960              }
1961            }
1962          }
1963        }
1964        return false;
1965      };
1966    };
1967    const hasAttribute = attrName => {
1968      return node => {
1969        return isElement$6(node) && node.hasAttribute(attrName);
1970      };
1971    };
1972    const isBogus$1 = node => isElement$6(node) && node.hasAttribute('data-mce-bogus');
1973    const isBogusAll = 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 (isHTMLElement(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$b = 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 is
vendor: 17,129 bytes, lines 2002-2453
2002EditingHost = node => isHTMLElement(node) && node.isContentEditable && isNonNullable(node.parentElement) && !node.parentElement.isContentEditable;
2003    const isTableCell$3 = matchNodeNames([
2004      'td',
2005      'th'
2006    ]);
2007    const isTableCellOrCaption = matchNodeNames([
2008      'td',
2009      'th',
2010      'caption'
2011    ]);
2012    const isMedia$2 = matchNodeNames([
2013      'video',
2014      'audio',
2015      'object',
2016      'embed'
2017    ]);
2018    const isListItem$2 = matchNodeName('li');
2019    const isDetails = matchNodeName('details');
2020    const isSummary$1 = matchNodeName('summary');
2021
2022    const defaultOptionValues = {
2023      skipBogus: true,
2024      includeZwsp: false,
2025      checkRootAsContent: false
2026    };
2027    const hasWhitespacePreserveParent = (node, rootNode, schema) => {
2028      const rootElement = SugarElement.fromDom(rootNode);
2029      const startNode = SugarElement.fromDom(node);
2030      const whitespaceElements = schema.getWhitespaceElements();
2031      const predicate = node => has$2(whitespaceElements, name(node));
2032      return ancestor$2(startNode, predicate, curry(eq, rootElement));
2033    };
2034    const isNamedAnchor = node => {
2035      return isElement$6(node) && node.nodeName === 'A' && !node.hasAttribute('href') && (node.hasAttribute('name') || node.hasAttribute('id'));
2036    };
2037    const isNonEmptyElement$1 = (node, schema) => {
2038      return isElement$6(node) && has$2(schema.getNonEmptyElements(), node.nodeName);
2039    };
2040    const isBookmark = hasAttribute('data-mce-bookmark');
2041    const hasNonEditableParent = node => parentElement(SugarElement.fromDom(node)).exists(parent => !isEditable$2(parent));
2042    const isWhitespace$1 = (node, rootNode, schema) => isWhitespaceText(node.data) && !hasWhitespacePreserveParent(node, rootNode, schema);
2043    const isText$a = (node, rootNode, schema, options) => isText$b(node) && !isWhitespace$1(node, rootNode, schema) && (!options.includeZwsp || !isZwsp$1(node.data));
2044    const isContentNode = (schema, node, rootNode, options) => {
2045      return isFunction(options.isContent) && options.isContent(node) || isNonEmptyElement$1(node, schema) || isBookmark(node) || isNamedAnchor(node) || isText$a(node, rootNode, schema, options) || isContentEditableFalse$b(node) || isContentEditableTrue$3(node) && hasNonEditableParent(node);
2046    };
2047    const isEmptyNode = (schema, targetNode, opts) => {
2048      const options = {
2049        ...defaultOptionValues,
2050        ...opts
2051      };
2052      if (options.checkRootAsContent) {
2053        if (isContentNode(schema, targetNode, targetNode, options)) {
2054          return false;
2055        }
2056      }
2057      let node = targetNode.firstChild;
2058      let brCount = 0;
2059      if (!node) {
2060        return true;
2061      }
2062      const walker = new DomTreeWalker(node, targetNode);
2063      do {
2064        if (options.skipBogus && isElement$6(node)) {
2065          const bogusValue = node.getAttribute('data-mce-bogus');
2066          if (bogusValue) {
2067            node = walker.next(bogusValue === 'all');
2068            continue;
2069          }
2070        }
2071        if (isComment(node)) {
2072          node = walker.next(true);
2073          continue;
2074        }
2075        if (isBr$6(node)) {
2076          brCount++;
2077          node = walker.next();
2078          continue;
2079        }
2080        if (isContentNode(schema, node, targetNode, options)) {
2081          return false;
2082        }
2083        node = walker.next();
2084      } while (node);
2085      return brCount <= 1;
2086    };
2087    const isEmpty$2 = (schema, elm, options) => {
2088      return isEmptyNode(schema, elm.dom, {
2089        checkRootAsContent: true,
2090        ...options
2091      });
2092    };
2093    const isContent$1 = (schema, node, options) => {
2094      return isContentNode(schema, node, node, {
2095        includeZwsp: defaultOptionValues.includeZwsp,
2096        ...options
2097      });
2098    };
2099
2100    const Cell = initial => {
2101      let value = initial;
2102      const get = () => {
2103        return value;
2104      };
2105      const set = v => {
2106        value = v;
2107      };
2108      return {
2109        get,
2110        set
2111      };
2112    };
2113
2114    const singleton = doRevoke => {
2115      const subject = Cell(Optional.none());
2116      const revoke = () => subject.get().each(doRevoke);
2117      const clear = () => {
2118        revoke();
2119        subject.set(Optional.none());
2120      };
2121      const isSet = () => subject.get().isSome();
2122      const get = () => subject.get();
2123      const set = s => {
2124        revoke();
2125        subject.set(Optional.some(s));
2126      };
2127      return {
2128        clear,
2129        isSet,
2130        get,
2131        set
2132      };
2133    };
2134    const repeatable = delay => {
2135      const intervalId = Cell(Optional.none());
2136      const revoke = () => intervalId.get().each(id => clearInterval(id));
2137      const clear = () => {
2138        revoke();
2139        intervalId.set(Optional.none());
2140      };
2141      const isSet = () => intervalId.get().isSome();
2142      const get = () => intervalId.get();
2143      const set = functionToRepeat => {
2144        revoke();
2145        intervalId.set(Optional.some(setInterval(functionToRepeat, delay)));
2146      };
2147      return {
2148        clear,
2149        isSet,
2150        get,
2151        set
2152      };
2153    };
2154    const value$2 = () => {
2155      const subject = singleton(noop);
2156      const on = f => subject.get().each(f);
2157      return {
2158        ...subject,
2159        on
2160      };
2161    };
2162
2163    const nodeNameToNamespaceType = name => {
2164      const lowerCaseName = name.toLowerCase();
2165      if (lowerCaseName === 'svg') {
2166        return 'svg';
2167      } else if (lowerCaseName === 'math') {
2168        return 'math';
2169      } else {
2170        return 'html';
2171      }
2172    };
2173    const isNonHtmlElementRootName = name => nodeNameToNamespaceType(name) !== 'html';
2174    const isNonHtmlElementRoot = node => isNonHtmlElementRootName(node.nodeName);
2175    const toScopeType = node => nodeNameToNamespaceType(node.nodeName);
2176    const namespaceElements = [
2177      'svg',
2178      'math'
2179    ];
2180    const createNamespaceTracker = () => {
2181      const currentScope = value$2();
2182      const current = () => currentScope.get().map(toScopeType).getOr('html');
2183      const track = node => {
2184        if (isNonHtmlElementRoot(node)) {
2185          currentScope.set(node);
2186        } else if (currentScope.get().exists(scopeNode => !scopeNode.contains(node))) {
2187          currentScope.clear();
2188        }
2189        return current();
2190      };
2191      const reset = () => {
2192        currentScope.clear();
2193      };
2194      return {
2195        track,
2196        current,
2197        reset
2198      };
2199    };
2200
2201    const transparentBlockAttr = 'data-mce-block';
2202    const elementNames = map => filter$5(keys(map), key => !/[A-Z]/.test(key));
2203    const makeSelectorFromSchemaMap = map => map$3(elementNames(map), name => {
2204      const escapedName = CSS.escape(name);
2205      return `${ escapedName }:` + map$3(namespaceElements, ns => `not(${ ns } ${ escapedName })`).join(':');
2206    }).join(',');
2207    const updateTransparent = (blocksSelector, transparent) => {
2208      if (isNonNullable(transparent.querySelector(blocksSelector))) {
2209        transparent.setAttribute(transparentBlockAttr, 'true');
2210        if (transparent.getAttribute('data-mce-selected') === 'inline-boundary') {
2211          transparent.removeAttribute('data-mce-selected');
2212        }
2213        return true;
2214      } else {
2215        transparent.removeAttribute(transparentBlockAttr);
2216        return false;
2217      }
2218    };
2219    const updateBlockStateOnChildren = (schema, scope) => {
2220      const transparentSelector = makeSelectorFromSchemaMap(schema.getTransparentElements());
2221      const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements());
2222      return filter$5(scope.querySelectorAll(transparentSelector), transparent => updateTransparent(blocksSelector, transparent));
2223    };
2224    const trimEdge = (schema, el, leftSide) => {
2225      var _a;
2226      const childPropertyName = leftSide ? 'lastChild' : 'firstChild';
2227      for (let child = el[childPropertyName]; child; child = child[childPropertyName]) {
2228        if (isEmptyNode(schema, child, { checkRootAsContent: true })) {
2229          (_a = child.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(child);
2230          return;
2231        }
2232      }
2233    };
2234    const split$2 = (schema, parentElm, splitElm) => {
2235      const range = document.createRange();
2236      const parentNode = parentElm.parentNode;
2237      if (parentNode) {
2238        range.setStartBefore(parentElm);
2239        range.setEndBefore(splitElm);
2240        const beforeFragment = range.extractContents();
2241        trimEdge(schema, beforeFragment, true);
2242        range.setStartAfter(splitElm);
2243        range.setEndAfter(parentElm);
2244        const afterFragment = range.extractContents();
2245        trimEdge(schema, afterFragment, false);
2246        if (!isEmptyNode(schema, beforeFragment, { checkRootAsContent: true })) {
2247          parentNode.insertBefore(beforeFragment, parentElm);
2248        }
2249        if (!isEmptyNode(schema, splitElm, { checkRootAsContent: true })) {
2250          parentNode.insertBefore(splitElm, parentElm);
2251        }
2252        if (!isEmptyNode(schema, afterFragment, { checkRootAsContent: true })) {
2253          parentNode.insertBefore(afterFragment, parentElm);
2254        }
2255        parentNode.removeChild(parentElm);
2256      }
2257    };
2258    const splitInvalidChildren = (schema, scope, transparentBlocks) => {
2259      const blocksElements = schema.getBlockElements();
2260      const rootNode = SugarElement.fromDom(scope);
2261      const isBlock = el => name(el) in blocksElements;
2262      const isRoot = el => eq(el, rootNode);
2263      each$e(fromDom$1(transparentBlocks), transparentBlock => {
2264        ancestor$4(transparentBlock, isBlock, isRoot).each(parentBlock => {
2265          const invalidChildren = children(transparentBlock, el => isBlock(el) && !schema.isValidChild(name(parentBlock), name(el)));
2266          if (invalidChildren.length > 0) {
2267            const stateScope = parentElement(parentBlock);
2268            each$e(invalidChildren, child => {
2269              ancestor$4(child, isBlock, isRoot).each(parentBlock => {
2270                split$2(schema, parentBlock.dom, child.dom);
2271              });
2272            });
2273            stateScope.each(scope => updateBlockStateOnChildren(schema, scope.dom));
2274          }
2275        });
2276      });
2277    };
2278    const unwrapInvalidChildren = (schema, scope, transparentBlocks) => {
2279      each$e([
2280        ...transparentBlocks,
2281        ...isTransparentBlock(schema, scope) ? [scope] : []
2282      ], block => each$e(descendants(SugarElement.fromDom(block), block.nodeName.toLowerCase()), elm => {
2283        if (isTransparentInline(schema, elm.dom)) {
2284          unwrap(elm);
2285        }
2286      }));
2287    };
2288    const updateChildren = (schema, scope) => {
2289      const transparentBlocks = updateBlockStateOnChildren(schema, scope);
2290      splitInvalidChildren(schema, scope, transparentBlocks);
2291      unwrapInvalidChildren(schema, scope, transparentBlocks);
2292    };
2293    const updateElement = (schema, target) => {
2294      if (isTransparentElement(schema, target)) {
2295        const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements());
2296        updateTransparent(blocksSelector, target);
2297      }
2298    };
2299    const updateCaret = (schema, root, caretParent) => {
2300      const isRoot = el => eq(el, SugarElement.fromDom(root));
2301      const parents = parents$1(SugarElement.fromDom(caretParent), isRoot);
2302      get$b(parents, parents.length - 2).filter(isElement$7).fold(() => updateChildren(schema, root), scope => updateChildren(schema, scope.dom));
2303    };
2304    const hasBlockAttr = el => el.hasAttribute(transparentBlockAttr);
2305    const isTransparentElementName = (schema, name) => has$2(schema.getTransparentElements(), name);
2306    const isTransparentElement = (schema, node) => isElement$6(node) && isTransparentElementName(schema, node.nodeName);
2307    const isTransparentBlock = (schema, node) => isTransparentElement(schema, node) && hasBlockAttr(node);
2308    const isTransparentInline = (schema, node) => isTransparentElement(schema, node) && !hasBlockAttr(node);
2309    const isTransparentAstBlock = (schema, node) => node.type === 1 && isTransparentElementName(schema, node.name) && isString(node.attr(transparentBlockAttr));
2310
2311    const browser$2 = detect$1().browser;
2312    const firstElement = nodes => find$2(nodes, isElement$7);
2313    const getTableCaptionDeltaY = elm => {
2314      if (browser$2.isFirefox() && name(elm) === 'table') {
2315        return firstElement(children$1(elm)).filter(elm => {
2316          return name(elm) === 'caption';
2317        }).bind(caption => {
2318          return firstElement(nextSiblings(caption)).map(body => {
2319            const bodyTop = body.dom.offsetTop;
2320            const captionTop = caption.dom.offsetTop;
2321            const captionHeight = caption.dom.offsetHeight;
2322            return bodyTop <= captionTop ? -captionHeight : 0;
2323          });
2324        }).getOr(0);
2325      } else {
2326        return 0;
2327      }
2328    };
2329    const hasChild = (elm, child) => elm.children && contains$2(elm.children, child);
2330    const getPos = (body, elm, rootElm) => {
2331      let x = 0, y = 0;
2332      const doc = body.ownerDocument;
2333      rootElm = rootElm ? rootElm : body;
2334      if (elm) {
2335        if (rootElm === body && elm.getBoundingClientRect && get$7(SugarElement.fromDom(body), 'position') === 'static') {
2336          const pos = elm.getBoundingClientRect();
2337          x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - doc.documentElement.clientLeft;
2338          y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - doc.documentElement.clientTop;
2339          return {
2340            x,
2341            y
2342          };
2343        }
2344        let offsetParent = elm;
2345        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType && !hasChild(offsetParent, rootElm)) {
2346          const castOffsetParent = offsetParent;
2347          x += castOffsetParent.offsetLeft || 0;
2348          y += castOffsetParent.offsetTop || 0;
2349          offsetParent = castOffsetParent.offsetParent;
2350        }
2351        offsetParent = elm.parentNode;
2352        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType && !hasChild(offsetParent, rootElm)) {
2353          x -= offsetParent.scrollLeft || 0;
2354          y -= offsetParent.scrollTop || 0;
2355          offsetParent = offsetParent.parentNode;
2356        }
2357        y += getTableCaptionDeltaY(SugarElement.fromDom(elm));
2358      }
2359      return {
2360        x,
2361        y
2362      };
2363    };
2364
2365    const StyleSheetLoader = (documentOrShadowRoot, settings = {}) => {
2366      let idCount = 0;
2367      const loadedStates = {};
2368      const edos = SugarElement.fromDom(documentOrShadowRoot);
2369      const doc = documentOrOwner(edos);
2370      const _setReferrerPolicy = referrerPolicy => {
2371        settings.referrerPolicy = referrerPolicy;
2372      };
2373      const _setContentCssCors = contentCssCors => {
2374        settings.contentCssCors = contentCssCors;
2375      };
2376      const addStyle = element => {
2377        append$1(getStyleContainer(edos), element);
2378      };
2379      const removeStyle = id => {
2380        const styleContainer = getStyleContainer(edos);
2381        descendant$1(styleContainer, '#' + id).each(remove$4);
2382      };
2383      const getOrCreateState = url => get$a(loadedStates, url).getOrThunk(() => ({
2384        id: 'mce-u' + idCount++,
2385        passed: [],
2386        failed: [],
2387        count: 0
2388      }));
2389      const load = url => new Promise((success, failure) => {
2390        let link;
2391        const urlWithSuffix = Tools._addCacheSuffix(url);
2392        const state = getOrCreateState(urlWithSuffix);
2393        loadedStates[urlWithSuffix] = state;
2394        state.count++;
2395        const resolve = (callbacks, status) => {
2396          each$e(callbacks, call);
2397          state.status = status;
2398          state.passed = [];
2399          state.failed = [];
2400          if (link) {
2401            link.onload = null;
2402            link.onerror = null;
2403            link = null;
2404          }
2405        };
2406        const passed = () => resolve(state.passed, 2);
2407        const failed = () => resolve(state.failed, 3);
2408        if (success) {
2409          state.passed.push(success);
2410        }
2411        if (failure) {
2412          state.failed.push(failure);
2413        }
2414        if (state.status === 1) {
2415          return;
2416        }
2417        if (state.status === 2) {
2418          passed();
2419          return;
2420        }
2421        if (state.status === 3) {
2422          failed();
2423          return;
2424        }
2425        state.status = 1;
2426        const linkElem = SugarElement.fromTag('link', doc.dom);
2427        setAll$1(linkElem, {
2428          rel: 'stylesheet',
2429          type: 'text/css',
2430          id: state.id
2431        });
2432        if (settings.contentCssCors) {
2433          set$4(linkElem, 'crossOrigin', 'anonymous');
2434        }
2435        if (settings.referrerPolicy) {
2436          set$4(linkElem, 'referrerpolicy', settings.referrerPolicy);
2437        }
2438        link = linkElem.dom;
2439        link.onload = passed;
2440        link.onerror = failed;
2441        addStyle(linkElem);
2442        set$4(linkElem, 'href', urlWithSuffix);
2443      });
2444      const loadRawCss = (key, css) => {
2445        const state = getOrCreateState(key);
2446        loadedStates[key] = state;
2447        state.count++;
2448        const styleElem = SugarElement.fromTag('style', doc.dom);
2449        setAll$1(styleElem, {
2450          'rel': 'stylesheet',
2451          'type': 'text/css',
2452          'id': state.id,
2453          'data-mce-key': key
vendor: 12,560 bytes, lines 2453-2759
2453
2454        });
2455        styleElem.dom.innerHTML = css;
2456        addStyle(styleElem);
2457      };
2458      const loadAll = urls => {
2459        const loadedUrls = Promise.allSettled(map$3(urls, url => load(url).then(constant(url))));
2460        return loadedUrls.then(results => {
2461          const parts = partition$2(results, r => r.status === 'fulfilled');
2462          if (parts.fail.length > 0) {
2463            return Promise.reject(map$3(parts.fail, result => result.reason));
2464          } else {
2465            return map$3(parts.pass, result => result.value);
2466          }
2467        });
2468      };
2469      const unload = url => {
2470        const urlWithSuffix = Tools._addCacheSuffix(url);
2471        get$a(loadedStates, urlWithSuffix).each(state => {
2472          const count = --state.count;
2473          if (count === 0) {
2474            delete loadedStates[urlWithSuffix];
2475            removeStyle(state.id);
2476          }
2477        });
2478      };
2479      const unloadRawCss = key => {
2480        get$a(loadedStates, key).each(state => {
2481          const count = --state.count;
2482          if (count === 0) {
2483            delete loadedStates[key];
2484            removeStyle(state.id);
2485          }
2486        });
2487      };
2488      const unloadAll = urls => {
2489        each$e(urls, url => {
2490          unload(url);
2491        });
2492      };
2493      return {
2494        load,
2495        loadRawCss,
2496        loadAll,
2497        unload,
2498        unloadRawCss,
2499        unloadAll,
2500        _setReferrerPolicy,
2501        _setContentCssCors
2502      };
2503    };
2504
2505    const create$c = () => {
2506      const map = new WeakMap();
2507      const forElement = (referenceElement, settings) => {
2508        const root = getRootNode(referenceElement);
2509        const rootDom = root.dom;
2510        return Optional.from(map.get(rootDom)).getOrThunk(() => {
2511          const sl = StyleSheetLoader(rootDom, settings);
2512          map.set(rootDom, sl);
2513          return sl;
2514        });
2515      };
2516      return { forElement };
2517    };
2518    const instance = create$c();
2519
2520    const isSpan = node => node.nodeName.toLowerCase() === 'span';
2521    const isInlineContent = (node, schema) => isNonNullable(node) && (isContent$1(schema, node) || schema.isInline(node.nodeName.toLowerCase()));
2522    const surroundedByInlineContent = (node, root, schema) => {
2523      const prev = new DomTreeWalker(node, root).prev(false);
2524      const next = new DomTreeWalker(node, root).next(false);
2525      const prevIsInline = isUndefined(prev) || isInlineContent(prev, schema);
2526      const nextIsInline = isUndefined(next) || isInlineContent(next, schema);
2527      return prevIsInline && nextIsInline;
2528    };
2529    const isBookmarkNode$2 = node => isSpan(node) && node.getAttribute('data-mce-type') === 'bookmark';
2530    const isKeepTextNode = (node, root, schema) => isText$b(node) && node.data.length > 0 && surroundedByInlineContent(node, root, schema);
2531    const isKeepElement = node => isElement$6(node) ? node.childNodes.length > 0 : false;
2532    const isDocument = node => isDocumentFragment(node) || isDocument$1(node);
2533    const trimNode = (dom, node, schema, root) => {
2534      var _a;
2535      const rootNode = root || node;
2536      if (isElement$6(node) && isBookmarkNode$2(node)) {
2537        return node;
2538      }
2539      const children = node.childNodes;
2540      for (let i = children.length - 1; i >= 0; i--) {
2541        trimNode(dom, children[i], schema, rootNode);
2542      }
2543      if (isElement$6(node)) {
2544        const currentChildren = node.childNodes;
2545        if (currentChildren.length === 1 && isBookmarkNode$2(currentChildren[0])) {
2546          (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(currentChildren[0], node);
2547        }
2548      }
2549      if (!isDocument(node) && !isContent$1(schema, node) && !isKeepElement(node) && !isKeepTextNode(node, rootNode, schema)) {
2550        dom.remove(node);
2551      }
2552      return node;
2553    };
2554
2555    const makeMap$3 = Tools.makeMap;
2556    const attrsCharsRegExp = /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
2557    const textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
2558    const rawCharsRegExp = /[<>&\"\']/g;
2559    const entityRegExp = /&#([a-z0-9]+);?|&([a-z0-9]+);/gi;
2560    const asciiMap = {
2561      128: '\u20AC',
2562      130: '\u201A',
2563      131: '\u0192',
2564      132: '\u201E',
2565      133: '\u2026',
2566      134: '\u2020',
2567      135: '\u2021',
2568      136: '\u02c6',
2569      137: '\u2030',
2570      138: '\u0160',
2571      139: '\u2039',
2572      140: '\u0152',
2573      142: '\u017d',
2574      145: '\u2018',
2575      146: '\u2019',
2576      147: '\u201C',
2577      148: '\u201D',
2578      149: '\u2022',
2579      150: '\u2013',
2580      151: '\u2014',
2581      152: '\u02DC',
2582      153: '\u2122',
2583      154: '\u0161',
2584      155: '\u203A',
2585      156: '\u0153',
2586      158: '\u017e',
2587      159: '\u0178'
2588    };
2589    const baseEntities = {
2590      '"': '&quot;',
2591      '\'': '&#39;',
2592      '<': '&lt;',
2593      '>': '&gt;',
2594      '&': '&amp;',
2595      '`': '&#96;'
2596    };
2597    const reverseEntities = {
2598      '&lt;': '<',
2599      '&gt;': '>',
2600      '&amp;': '&',
2601      '&quot;': '"',
2602      '&apos;': `'`
2603    };
2604    const nativeDecode = text => {
2605      const elm = SugarElement.fromTag('div').dom;
2606      elm.innerHTML = text;
2607      return elm.textContent || elm.innerText || text;
2608    };
2609    const buildEntitiesLookup = (items, radix) => {
2610      const lookup = {};
2611      if (items) {
2612        const itemList = items.split(',');
2613        radix = radix || 10;
2614        for (let i = 0; i < itemList.length; i += 2) {
2615          const chr = String.fromCharCode(parseInt(itemList[i], radix));
2616          if (!baseEntities[chr]) {
2617            const entity = '&' + itemList[i + 1] + ';';
2618            lookup[chr] = entity;
2619            lookup[entity] = chr;
2620          }
2621        }
2622        return lookup;
2623      } else {
2624        return undefined;
2625      }
2626    };
2627    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);
2628    const encodeRaw = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2629      return baseEntities[chr] || chr;
2630    });
2631    const encodeAllRaw = text => ('' + text).replace(rawCharsRegExp, chr => {
2632      return baseEntities[chr] || chr;
2633    });
2634    const encodeNumeric = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2635      if (chr.length > 1) {
2636        return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
2637      }
2638      return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
2639    });
2640    const encodeNamed = (text, attr, entities) => {
2641      const resolveEntities = entities || namedEntities;
2642      return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2643        return baseEntities[chr] || resolveEntities[chr] || chr;
2644      });
2645    };
2646    const getEncodeFunc = (name, entities) => {
2647      const entitiesMap = buildEntitiesLookup(entities) || namedEntities;
2648      const encodeNamedAndNumeric = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2649        if (baseEntities[chr] !== undefined) {
2650          return baseEntities[chr];
2651        }
2652        if (entitiesMap[chr] !== undefined) {
2653          return entitiesMap[chr];
2654        }
2655        if (chr.length > 1) {
2656          return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
2657        }
2658        return '&#' + chr.charCodeAt(0) + ';';
2659      });
2660      const encodeCustomNamed = (text, attr) => {
2661        return encodeNamed(text, attr, entitiesMap);
2662      };
2663      const nameMap = makeMap$3(name.replace(/\+/g, ','));
2664      if (nameMap.named && nameMap.numeric) {
2665        return encodeNamedAndNumeric;
2666      }
2667      if (nameMap.named) {
2668        if (entities) {
2669          return encodeCustomNamed;
2670        }
2671        return encodeNamed;
2672      }
2673      if (nameMap.numeric) {
2674        return encodeNumeric;
2675      }
2676      return encodeRaw;
2677    };
2678    const decode = text => text.replace(entityRegExp, (all, numeric) => {
2679      if (numeric) {
2680        if (numeric.charAt(0).toLowerCase() === 'x') {
2681          numeric = parseInt(numeric.substr(1), 16);
2682        } else {
2683          numeric = parseInt(numeric, 10);
2684        }
2685        if (numeric > 65535) {
2686          numeric -= 65536;
2687          return String.fromCharCode(55296 + (numeric >> 10), 56320 + (numeric & 1023));
2688        }
2689        return asciiMap[numeric] || String.fromCharCode(numeric);
2690      }
2691      return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
2692    });
2693    const Entities = {
2694      encodeRaw,
2695      encodeAllRaw,
2696      encodeNumeric,
2697      encodeNamed,
2698      getEncodeFunc,
2699      decode
2700    };
2701
2702    const split$1 = (items, delim) => {
2703      items = Tools.trim(items);
2704      return items ? items.split(delim || ' ') : [];
2705    };
2706    const patternToRegExp = str => new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$');
2707    const isRegExp$1 = obj => isObject(obj) && obj.source && Object.prototype.toString.call(obj) === '[object RegExp]';
2708    const deepCloneElementRule = obj => {
2709      const helper = value => {
2710        if (isArray$1(value)) {
2711          return map$3(value, helper);
2712        } else if (isRegExp$1(value)) {
2713          return new RegExp(value.source, value.flags);
2714        } else if (isObject(value)) {
2715          return map$2(value, helper);
2716        } else {
2717          return value;
2718        }
2719      };
2720      return helper(obj);
2721    };
2722
2723    const parseCustomElementsRules = value => {
2724      const customElementRegExp = /^(~)?(.+)$/;
2725      return bind$3(split$1(value, ','), rule => {
2726        const matches = customElementRegExp.exec(rule);
2727        if (matches) {
2728          const inline = matches[1] === '~';
2729          const cloneName = inline ? 'span' : 'div';
2730          const name = matches[2];
2731          return [{
2732              cloneName,
2733              name
2734            }];
2735        } else {
2736          return [];
2737        }
2738      });
2739    };
2740
2741    const getGlobalAttributeSet = type => {
2742      return Object.freeze([
2743        'id',
2744        'accesskey',
2745        'class',
2746        'dir',
2747        'lang',
2748        'style',
2749        'tabindex',
2750        'title',
2751        'role',
2752        ...type !== 'html4' ? [
2753          'contenteditable',
2754          'contextmenu',
2755          'draggable',
2756          'dropzone',
2757          'hidden',
2758          'spellcheck',
2759          'translate'
vendor: 2,018 bytes, lines 2759-2814
2759,
2760          'itemprop',
2761          'itemscope',
2762          'itemtype'
2763        ] : [],
2764        ...type !== 'html5-strict' ? ['xml:lang'] : []
2765      ]);
2766    };
2767
2768    const getElementSetsAsStrings = type => {
2769      let blockContent;
2770      let phrasingContent;
2771      blockContent = 'address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul';
2772      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';
2773      if (type !== 'html4') {
2774        const transparentContent = 'a ins del canvas map';
2775        blockContent += ' article aside details dialog figure main header footer hgroup section nav ' + transparentContent;
2776        phrasingContent += ' audio canvas command data datalist mark meter output picture ' + 'progress time wbr video ruby bdi keygen svg';
2777      }
2778      if (type !== 'html5-strict') {
2779        const html4PhrasingContent = 'acronym applet basefont big font strike tt';
2780        phrasingContent = [
2781          phrasingContent,
2782          html4PhrasingContent
2783        ].join(' ');
2784        const html4BlockContent = 'center dir isindex noframes';
2785        blockContent = [
2786          blockContent,
2787          html4BlockContent
2788        ].join(' ');
2789      }
2790      const flowContent = [
2791        blockContent,
2792        phrasingContent
2793      ].join(' ');
2794      return {
2795        blockContent,
2796        phrasingContent,
2797        flowContent
2798      };
2799    };
2800    const getElementSets = type => {
2801      const {blockContent, phrasingContent, flowContent} = getElementSetsAsStrings(type);
2802      const toArr = value => {
2803        return Object.freeze(value.split(' '));
2804      };
2805      return Object.freeze({
2806        blockContent: toArr(blockContent),
2807        phrasingContent: toArr(phrasingContent),
2808        flowContent: toArr(flowContent)
2809      });
2810    };
2811
2812    const cachedSets = {
2813      'html4': cached(() => getElementSets('html4')),
2814      'html5'
vendor: 9,727 bytes, lines 2814-3021
2814: cached(() => getElementSets('html5')),
2815      'html5-strict': cached(() => getElementSets('html5-strict'))
2816    };
2817    const getElementsPreset = (type, name) => {
2818      const {blockContent, phrasingContent, flowContent} = cachedSets[type]();
2819      if (name === 'blocks') {
2820        return Optional.some(blockContent);
2821      } else if (name === 'phrasing') {
2822        return Optional.some(phrasingContent);
2823      } else if (name === 'flow') {
2824        return Optional.some(flowContent);
2825      } else {
2826        return Optional.none();
2827      }
2828    };
2829
2830    const makeSchema = type => {
2831      const globalAttributes = getGlobalAttributeSet(type);
2832      const {phrasingContent, flowContent} = getElementSetsAsStrings(type);
2833      const schema = {};
2834      const addElement = (name, attributes, children) => {
2835        schema[name] = {
2836          attributes: mapToObject(attributes, constant({})),
2837          attributesOrder: attributes,
2838          children: mapToObject(children, constant({}))
2839        };
2840      };
2841      const add = (name, attributes = '', children = '') => {
2842        const childNames = split$1(children);
2843        const names = split$1(name);
2844        let ni = names.length;
2845        const allAttributes = [
2846          ...globalAttributes,
2847          ...split$1(attributes)
2848        ];
2849        while (ni--) {
2850          addElement(names[ni], allAttributes.slice(), childNames);
2851        }
2852      };
2853      const addAttrs = (name, attributes) => {
2854        const names = split$1(name);
2855        const attrs = split$1(attributes);
2856        let ni = names.length;
2857        while (ni--) {
2858          const schemaItem = schema[names[ni]];
2859          for (let i = 0, l = attrs.length; i < l; i++) {
2860            schemaItem.attributes[attrs[i]] = {};
2861            schemaItem.attributesOrder.push(attrs[i]);
2862          }
2863        }
2864      };
2865      if (type !== 'html5-strict') {
2866        const html4PhrasingContent = 'acronym applet basefont big font strike tt';
2867        each$e(split$1(html4PhrasingContent), name => {
2868          add(name, '', phrasingContent);
2869        });
2870        const html4BlockContent = 'center dir isindex noframes';
2871        each$e(split$1(html4BlockContent), name => {
2872          add(name, '', flowContent);
2873        });
2874      }
2875      add('html', 'manifest', 'head body');
2876      add('head', '', 'base command link meta noscript script style title');
2877      add('title hr noscript br');
2878      add('base', 'href target');
2879      add('link', 'href rel media hreflang type sizes hreflang');
2880      add('meta', 'name http-equiv content charset');
2881      add('style', 'media type scoped');
2882      add('script', 'src async defer type charset');
2883      add('body', 'onafterprint onbeforeprint onbeforeunload onblur onerror onfocus ' + 'onhashchange onload onmessage onoffline ononline onpagehide onpageshow ' + 'onpopstate onresize onscroll onstorage onunload', flowContent);
2884      add('dd div', '', flowContent);
2885      add('address dt caption', '', type === 'html4' ? phrasingContent : flowContent);
2886      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);
2887      add('blockquote', 'cite', flowContent);
2888      add('ol', 'reversed start type', 'li');
2889      add('ul', '', 'li');
2890      add('li', 'value', flowContent);
2891      add('dl', '', 'dt dd');
2892      add('a', 'href target rel media hreflang type', type === 'html4' ? phrasingContent : flowContent);
2893      add('q', 'cite', phrasingContent);
2894      add('ins del', 'cite datetime', flowContent);
2895      add('img', 'src sizes srcset alt usemap ismap width height');
2896      add('iframe', 'src name width height', flowContent);
2897      add('embed', 'src type width height');
2898      add('object', 'data type typemustmatch name usemap form width height', [
2899        flowContent,
2900        'param'
2901      ].join(' '));
2902      add('param', 'name value');
2903      add('map', 'name', [
2904        flowContent,
2905        'area'
2906      ].join(' '));
2907      add('area', 'alt coords shape href target rel media hreflang type');
2908      add('table', 'border', 'caption colgroup thead tfoot tbody tr' + (type === 'html4' ? ' col' : ''));
2909      add('colgroup', 'span', 'col');
2910      add('col', 'span');
2911      add('tbody thead tfoot', '', 'tr');
2912      add('tr', '', 'td th');
2913      add('td', 'colspan rowspan headers', flowContent);
2914      add('th', 'colspan rowspan headers scope abbr', flowContent);
2915      add('form', 'accept-charset action autocomplete enctype method name novalidate target', flowContent);
2916      add('fieldset', 'disabled form name', [
2917        flowContent,
2918        'legend'
2919      ].join(' '));
2920      add('label', 'form for', phrasingContent);
2921      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');
2922      add('button', 'disabled form formaction formenctype formmethod formnovalidate formtarget name type value', type === 'html4' ? flowContent : phrasingContent);
2923      add('select', 'disabled form multiple name required size', 'option optgroup');
2924      add('optgroup', 'disabled label', 'option');
2925      add('option', 'disabled label selected value');
2926      add('textarea', 'cols dirname disabled form maxlength name readonly required rows wrap');
2927      add('menu', 'type label', [
2928        flowContent,
2929        'li'
2930      ].join(' '));
2931      add('noscript', '', flowContent);
2932      if (type !== 'html4') {
2933        add('wbr');
2934        add('ruby', '', [
2935          phrasingContent,
2936          'rt rp'
2937        ].join(' '));
2938        add('figcaption', '', flowContent);
2939        add('mark rt rp bdi', '', phrasingContent);
2940        add('summary', '', [
2941          phrasingContent,
2942          'h1 h2 h3 h4 h5 h6'
2943        ].join(' '));
2944        add('canvas', 'width height', flowContent);
2945        add('data', 'value', phrasingContent);
2946        add('video', 'src crossorigin poster preload autoplay mediagroup loop ' + 'muted controls width height buffered', [
2947          flowContent,
2948          'track source'
2949        ].join(' '));
2950        add('audio', 'src crossorigin preload autoplay mediagroup loop muted controls ' + 'buffered volume', [
2951          flowContent,
2952          'track source'
2953        ].join(' '));
2954        add('picture', '', 'img source');
2955        add('source', 'src srcset type media sizes');
2956        add('track', 'kind src srclang label default');
2957        add('datalist', '', [
2958          phrasingContent,
2959          'option'
2960        ].join(' '));
2961        add('article section nav aside main header footer', '', flowContent);
2962        add('hgroup', '', 'h1 h2 h3 h4 h5 h6');
2963        add('figure', '', [
2964          flowContent,
2965          'figcaption'
2966        ].join(' '));
2967        add('time', 'datetime', phrasingContent);
2968        add('dialog', 'open', flowContent);
2969        add('command', 'type label icon disabled checked radiogroup command');
2970        add('output', 'for form name', phrasingContent);
2971        add('progress', 'value max', phrasingContent);
2972        add('meter', 'value min max low high optimum', phrasingContent);
2973        add('details', 'open', [
2974          flowContent,
2975          'summary'
2976        ].join(' '));
2977        add('keygen', 'autofocus challenge disabled form keytype name');
2978        addElement('svg', 'id tabindex lang xml:space class style x y width height viewBox preserveAspectRatio zoomAndPan transform'.split(' '), []);
2979      }
2980      if (type !== 'html5-strict') {
2981        addAttrs('script', 'language xml:space');
2982        addAttrs('style', 'xml:space');
2983        addAttrs('object', 'declare classid code codebase codetype archive standby align border hspace vspace');
2984        addAttrs('embed', 'align name hspace vspace');
2985        addAttrs('param', 'valuetype type');
2986        addAttrs('a', 'charset name rev shape coords');
2987        addAttrs('br', 'clear');
2988        addAttrs('applet', 'codebase archive code object alt name width height align hspace vspace');
2989        addAttrs('img', 'name longdesc align border hspace vspace');
2990        addAttrs('iframe', 'longdesc frameborder marginwidth marginheight scrolling align');
2991        addAttrs('font basefont', 'size color face');
2992        addAttrs('input', 'usemap align');
2993        addAttrs('select');
2994        addAttrs('textarea');
2995        addAttrs('h1 h2 h3 h4 h5 h6 div p legend caption', 'align');
2996        addAttrs('ul', 'type compact');
2997        addAttrs('li', 'type');
2998        addAttrs('ol dl menu dir', 'compact');
2999        addAttrs('pre', 'width xml:space');
3000        addAttrs('hr', 'align noshade size width');
3001        addAttrs('isindex', 'prompt');
3002        addAttrs('table', 'summary width frame rules cellspacing cellpadding align bgcolor');
3003        addAttrs('col', 'width align char charoff valign');
3004        addAttrs('colgroup', 'width align char charoff valign');
3005        addAttrs('thead', 'align char charoff valign');
3006        addAttrs('tr', 'align char charoff valign bgcolor');
3007        addAttrs('th', 'axis align char charoff valign nowrap bgcolor width height');
3008        addAttrs('form', 'accept');
3009        addAttrs('td', 'abbr axis scope align char charoff valign nowrap bgcolor width height');
3010        addAttrs('tfoot', 'align char charoff valign');
3011        addAttrs('tbody', 'align char charoff valign');
3012        addAttrs('area', 'nohref');
3013        addAttrs('body', 'background bgcolor text link vlink alink');
3014      }
3015      if (type !== 'html4') {
3016        addAttrs('input button select textarea', 'autofocus');
3017        addAttrs('input textarea', 'placeholder');
3018        addAttrs('a', 'download');
3019        addAttrs('link script img', 'crossorigin');
3020        addAttrs('img', 'loading');
3021        addAttrs('iframe', 'sandbox seamless allow allowfullscreen loading
3021 referrerpolicy
vendor: 21,997 bytes, lines 3021-3569
3021');
3022      }
3023      if (type !== 'html4') {
3024        each$e([
3025          schema.video,
3026          schema.audio
3027        ], item => {
3028          delete item.children.audio;
3029          delete item.children.video;
3030        });
3031      }
3032      each$e(split$1('a form meter progress dfn'), name => {
3033        if (schema[name]) {
3034          delete schema[name].children[name];
3035        }
3036      });
3037      delete schema.caption.children.table;
3038      delete schema.script;
3039      return schema;
3040    };
3041
3042    const prefixToOperation = prefix => prefix === '-' ? 'remove' : 'add';
3043    const parseValidChild = name => {
3044      const validChildRegExp = /^(@?)([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]+)$/;
3045      return Optional.from(validChildRegExp.exec(name)).map(matches => ({
3046        preset: matches[1] === '@',
3047        name: matches[2]
3048      }));
3049    };
3050    const parseValidChildrenRules = value => {
3051      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]+)\[([^\]]+)]$/;
3052      return bind$3(split$1(value, ','), rule => {
3053        const matches = childRuleRegExp.exec(rule);
3054        if (matches) {
3055          const prefix = matches[1];
3056          const operation = prefix ? prefixToOperation(prefix) : 'replace';
3057          const name = matches[2];
3058          const validChildren = bind$3(split$1(matches[3], '|'), validChild => parseValidChild(validChild).toArray());
3059          return [{
3060              operation,
3061              name,
3062              validChildren
3063            }];
3064        } else {
3065          return [];
3066        }
3067      });
3068    };
3069
3070    const parseValidElementsAttrDataIntoElement = (attrData, targetElement) => {
3071      const attrRuleRegExp = /^([!\-])?(\w+[\\:]:\w+|[^=~<]+)?(?:([=~<])(.*))?$/;
3072      const hasPatternsRegExp = /[*?+]/;
3073      const {attributes, attributesOrder} = targetElement;
3074      return each$e(split$1(attrData, '|'), rule => {
3075        const matches = attrRuleRegExp.exec(rule);
3076        if (matches) {
3077          const attr = {};
3078          const attrType = matches[1];
3079          const attrName = matches[2].replace(/[\\:]:/g, ':');
3080          const attrPrefix = matches[3];
3081          const value = matches[4];
3082          if (attrType === '!') {
3083            targetElement.attributesRequired = targetElement.attributesRequired || [];
3084            targetElement.attributesRequired.push(attrName);
3085            attr.required = true;
3086          }
3087          if (attrType === '-') {
3088            delete attributes[attrName];
3089            attributesOrder.splice(Tools.inArray(attributesOrder, attrName), 1);
3090            return;
3091          }
3092          if (attrPrefix) {
3093            if (attrPrefix === '=') {
3094              targetElement.attributesDefault = targetElement.attributesDefault || [];
3095              targetElement.attributesDefault.push({
3096                name: attrName,
3097                value
3098              });
3099              attr.defaultValue = value;
3100            } else if (attrPrefix === '~') {
3101              targetElement.attributesForced = targetElement.attributesForced || [];
3102              targetElement.attributesForced.push({
3103                name: attrName,
3104                value
3105              });
3106              attr.forcedValue = value;
3107            } else if (attrPrefix === '<') {
3108              attr.validValues = Tools.makeMap(value, '?');
3109            }
3110          }
3111          if (hasPatternsRegExp.test(attrName)) {
3112            const attrPattern = attr;
3113            targetElement.attributePatterns = targetElement.attributePatterns || [];
3114            attrPattern.pattern = patternToRegExp(attrName);
3115            targetElement.attributePatterns.push(attrPattern);
3116          } else {
3117            if (!attributes[attrName]) {
3118              attributesOrder.push(attrName);
3119            }
3120            attributes[attrName] = attr;
3121          }
3122        }
3123      });
3124    };
3125    const cloneAttributesInto = (from, to) => {
3126      each$d(from.attributes, (value, key) => {
3127        to.attributes[key] = value;
3128      });
3129      to.attributesOrder.push(...from.attributesOrder);
3130    };
3131    const parseValidElementsRules = (globalElement, validElements) => {
3132      const elementRuleRegExp = /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)])?$/;
3133      return bind$3(split$1(validElements, ','), rule => {
3134        const matches = elementRuleRegExp.exec(rule);
3135        if (matches) {
3136          const prefix = matches[1];
3137          const elementName = matches[2];
3138          const outputName = matches[3];
3139          const attrsPrefix = matches[4];
3140          const attrData = matches[5];
3141          const element = {
3142            attributes: {},
3143            attributesOrder: []
3144          };
3145          globalElement.each(el => cloneAttributesInto(el, element));
3146          if (prefix === '#') {
3147            element.paddEmpty = true;
3148          } else if (prefix === '-') {
3149            element.removeEmpty = true;
3150          }
3151          if (attrsPrefix === '!') {
3152            element.removeEmptyAttrs = true;
3153          }
3154          if (attrData) {
3155            parseValidElementsAttrDataIntoElement(attrData, element);
3156          }
3157          if (outputName) {
3158            element.outputName = elementName;
3159          }
3160          if (elementName === '@') {
3161            if (globalElement.isNone()) {
3162              globalElement = Optional.some(element);
3163            } else {
3164              return [];
3165            }
3166          }
3167          return [outputName ? {
3168              name: elementName,
3169              element,
3170              aliasName: outputName
3171            } : {
3172              name: elementName,
3173              element
3174            }];
3175        } else {
3176          return [];
3177        }
3178      });
3179    };
3180
3181    const mapCache = {};
3182    const makeMap$2 = Tools.makeMap, each$b = Tools.each, extend$2 = Tools.extend, explode$2 = Tools.explode;
3183    const createMap = (defaultValue, extendWith = {}) => {
3184      const value = makeMap$2(defaultValue, ' ', makeMap$2(defaultValue.toUpperCase(), ' '));
3185      return extend$2(value, extendWith);
3186    };
3187    const getTextRootBlockElements = schema => createMap('td th li dt dd figcaption caption details summary', schema.getTextBlockElements());
3188    const compileElementMap = (value, mode) => {
3189      if (value) {
3190        const styles = {};
3191        if (isString(value)) {
3192          value = { '*': value };
3193        }
3194        each$b(value, (value, key) => {
3195          styles[key] = styles[key.toUpperCase()] = mode === 'map' ? makeMap$2(value, /[, ]/) : explode$2(value, /[, ]/);
3196        });
3197        return styles;
3198      } else {
3199        return undefined;
3200      }
3201    };
3202    const Schema = (settings = {}) => {
3203      var _a;
3204      const elements = {};
3205      const children = {};
3206      let patternElements = [];
3207      const customElementsMap = {};
3208      const specialElements = {};
3209      const createLookupTable = (option, defaultValue, extendWith) => {
3210        const value = settings[option];
3211        if (!value) {
3212          let newValue = mapCache[option];
3213          if (!newValue) {
3214            newValue = createMap(defaultValue, extendWith);
3215            mapCache[option] = newValue;
3216          }
3217          return newValue;
3218        } else {
3219          return makeMap$2(value, /[, ]/, makeMap$2(value.toUpperCase(), /[, ]/));
3220        }
3221      };
3222      const schemaType = (_a = settings.schema) !== null && _a !== void 0 ? _a : 'html5';
3223      const schemaItems = makeSchema(schemaType);
3224      if (settings.verify_html === false) {
3225        settings.valid_elements = '*[*]';
3226      }
3227      const validStyles = compileElementMap(settings.valid_styles);
3228      const invalidStyles = compileElementMap(settings.invalid_styles, 'map');
3229      const validClasses = compileElementMap(settings.valid_classes, 'map');
3230      const whitespaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea video audio iframe object code');
3231      const selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
3232      const voidElementsMap = createLookupTable('void_elements', 'area base basefont br col frame hr img input isindex link ' + 'meta param embed source wbr track');
3233      const boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' + 'noshade nowrap readonly selected autoplay loop controls allowfullscreen');
3234      const nonEmptyOrMoveCaretBeforeOnEnter = 'td th iframe video audio object script code';
3235      const nonEmptyElementsMap = createLookupTable('non_empty_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' pre svg textarea summary', voidElementsMap);
3236      const moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' table', voidElementsMap);
3237      const headings = 'h1 h2 h3 h4 h5 h6';
3238      const textBlockElementsMap = createLookupTable('text_block_elements', headings + ' p div address pre form ' + 'blockquote center dir fieldset header footer article section hgroup aside main nav figure');
3239      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 html body multicol listing', textBlockElementsMap);
3240      const textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font s strike u var cite ' + 'dfn code mark q sup sub samp');
3241      const transparentElementsMap = createLookupTable('transparent_elements', 'a ins del canvas map');
3242      const wrapBlockElementsMap = createLookupTable('wrap_block_elements', 'pre ' + headings);
3243      each$b('script noscript iframe noframes noembed title style textarea xmp plaintext'.split(' '), name => {
3244        specialElements[name] = new RegExp('</' + name + '[^>]*>', 'gi');
3245      });
3246      const addValidElements = validElements => {
3247        const globalElement = Optional.from(elements['@']);
3248        const hasPatternsRegExp = /[*?+]/;
3249        each$e(parseValidElementsRules(globalElement, validElements !== null && validElements !== void 0 ? validElements : ''), ({name, element, aliasName}) => {
3250          if (aliasName) {
3251            elements[aliasName] = element;
3252          }
3253          if (hasPatternsRegExp.test(name)) {
3254            const patternElement = element;
3255            patternElement.pattern = patternToRegExp(name);
3256            patternElements.push(patternElement);
3257          } else {
3258            elements[name] = element;
3259          }
3260        });
3261      };
3262      const setValidElements = validElements => {
3263        patternElements = [];
3264        each$e(keys(elements), name => {
3265          delete elements[name];
3266        });
3267        addValidElements(validElements);
3268      };
3269      const addCustomElement = (name, spec) => {
3270        var _a, _b;
3271        delete mapCache.text_block_elements;
3272        delete mapCache.block_elements;
3273        const inline = spec.extends ? !isBlock(spec.extends) : false;
3274        const cloneName = spec.extends;
3275        children[name] = cloneName ? children[cloneName] : {};
3276        customElementsMap[name] = cloneName !== null && cloneName !== void 0 ? cloneName : name;
3277        nonEmptyElementsMap[name.toUpperCase()] = {};
3278        nonEmptyElementsMap[name] = {};
3279        if (!inline) {
3280          blockElementsMap[name.toUpperCase()] = {};
3281          blockElementsMap[name] = {};
3282        }
3283        if (cloneName && !elements[name] && elements[cloneName]) {
3284          const customRule = deepCloneElementRule(elements[cloneName]);
3285          delete customRule.removeEmptyAttrs;
3286          delete customRule.removeEmpty;
3287          elements[name] = customRule;
3288        } else {
3289          elements[name] = {
3290            attributesOrder: [],
3291            attributes: {}
3292          };
3293        }
3294        if (isArray$1(spec.attributes)) {
3295          const processAttrName = name => {
3296            customRule.attributesOrder.push(name);
3297            customRule.attributes[name] = {};
3298          };
3299          const customRule = (_a = elements[name]) !== null && _a !== void 0 ? _a : {};
3300          delete customRule.attributesDefault;
3301          delete customRule.attributesForced;
3302          delete customRule.attributePatterns;
3303          delete customRule.attributesRequired;
3304          customRule.attributesOrder = [];
3305          customRule.attributes = {};
3306          each$e(spec.attributes, attrName => {
3307            const globalAttrs = getGlobalAttributeSet(schemaType);
3308            parseValidChild(attrName).each(({preset, name}) => {
3309              if (preset) {
3310                if (name === 'global') {
3311                  each$e(globalAttrs, processAttrName);
3312                }
3313              } else {
3314                processAttrName(name);
3315              }
3316            });
3317          });
3318          elements[name] = customRule;
3319        }
3320        if (isBoolean(spec.padEmpty)) {
3321          const customRule = (_b = elements[name]) !== null && _b !== void 0 ? _b : {};
3322          customRule.paddEmpty = spec.padEmpty;
3323          elements[name] = customRule;
3324        }
3325        if (isArray$1(spec.children)) {
3326          const customElementChildren = {};
3327          const processNodeName = name => {
3328            customElementChildren[name] = {};
3329          };
3330          const processPreset = name => {
3331            getElementsPreset(schemaType, name).each(names => {
3332              each$e(names, processNodeName);
3333            });
3334          };
3335          each$e(spec.children, child => {
3336            parseValidChild(child).each(({preset, name}) => {
3337              if (preset) {
3338                processPreset(name);
3339              } else {
3340                processNodeName(name);
3341              }
3342            });
3343          });
3344          children[name] = customElementChildren;
3345        }
3346        if (cloneName) {
3347          each$d(children, (element, elmName) => {
3348            if (element[cloneName]) {
3349              children[elmName] = element = extend$2({}, children[elmName]);
3350              element[name] = element[cloneName];
3351            }
3352          });
3353        }
3354      };
3355      const addCustomElementsFromString = customElements => {
3356        each$e(parseCustomElementsRules(customElements !== null && customElements !== void 0 ? customElements : ''), ({name, cloneName}) => {
3357          addCustomElement(name, { extends: cloneName });
3358        });
3359      };
3360      const addCustomElements = customElements => {
3361        if (isObject(customElements)) {
3362          each$d(customElements, (spec, name) => addCustomElement(name, spec));
3363        } else if (isString(customElements)) {
3364          addCustomElementsFromString(customElements);
3365        }
3366      };
3367      const addValidChildren = validChildren => {
3368        each$e(parseValidChildrenRules(validChildren !== null && validChildren !== void 0 ? validChildren : ''), ({operation, name, validChildren}) => {
3369          const parent = operation === 'replace' ? { '#comment': {} } : children[name];
3370          const processNodeName = name => {
3371            if (operation === 'remove') {
3372              delete parent[name];
3373            } else {
3374              parent[name] = {};
3375            }
3376          };
3377          const processPreset = name => {
3378            getElementsPreset(schemaType, name).each(names => {
3379              each$e(names, processNodeName);
3380            });
3381          };
3382          each$e(validChildren, ({preset, name}) => {
3383            if (preset) {
3384              processPreset(name);
3385            } else {
3386              processNodeName(name);
3387            }
3388          });
3389          children[name] = parent;
3390        });
3391      };
3392      const getElementRule = name => {
3393        const element = elements[name];
3394        if (element) {
3395          return element;
3396        }
3397        let i = patternElements.length;
3398        while (i--) {
3399          const patternElement = patternElements[i];
3400          if (patternElement.pattern.test(name)) {
3401            return patternElement;
3402          }
3403        }
3404        return undefined;
3405      };
3406      const setup = () => {
3407        if (!settings.valid_elements) {
3408          each$b(schemaItems, (element, name) => {
3409            elements[name] = {
3410              attributes: element.attributes,
3411              attributesOrder: element.attributesOrder
3412            };
3413            children[name] = element.children;
3414          });
3415          each$b(split$1('strong/b em/i'), item => {
3416            const items = split$1(item, '/');
3417            elements[items[1]].outputName = items[0];
3418          });
3419          each$b(textInlineElementsMap, (_val, name) => {
3420            if (elements[name]) {
3421              if (settings.padd_empty_block_inline_children) {
3422                elements[name].paddInEmptyBlock = true;
3423              }
3424              elements[name].removeEmpty = true;
3425            }
3426          });
3427          each$b(split$1('ol ul blockquote a table tbody'), name => {
3428            if (elements[name]) {
3429              elements[name].removeEmpty = true;
3430            }
3431          });
3432          each$b(split$1('p h1 h2 h3 h4 h5 h6 th td pre div address caption li summary'), name => {
3433            if (elements[name]) {
3434              elements[name].paddEmpty = true;
3435            }
3436          });
3437          each$b(split$1('span'), name => {
3438            elements[name].removeEmptyAttrs = true;
3439          });
3440        } else {
3441          setValidElements(settings.valid_elements);
3442          each$b(schemaItems, (element, name) => {
3443            children[name] = element.children;
3444          });
3445        }
3446        delete elements.svg;
3447        addCustomElements(settings.custom_elements);
3448        addValidChildren(settings.valid_children);
3449        addValidElements(settings.extended_valid_elements);
3450        addValidChildren('+ol[ul|ol],+ul[ul|ol]');
3451        each$b({
3452          dd: 'dl',
3453          dt: 'dl',
3454          li: 'ul ol',
3455          td: 'tr',
3456          th: 'tr',
3457          tr: 'tbody thead tfoot',
3458          tbody: 'table',
3459          thead: 'table',
3460          tfoot: 'table',
3461          legend: 'fieldset',
3462          area: 'map',
3463          param: 'video audio object'
3464        }, (parents, item) => {
3465          if (elements[item]) {
3466            elements[item].parentsRequired = split$1(parents);
3467          }
3468        });
3469        if (settings.invalid_elements) {
3470          each$b(explode$2(settings.invalid_elements), item => {
3471            if (elements[item]) {
3472              delete elements[item];
3473            }
3474          });
3475        }
3476        if (!getElementRule('span')) {
3477          addValidElements('span[!data-mce-type|*]');
3478        }
3479      };
3480      const getValidStyles = constant(validStyles);
3481      const getInvalidStyles = constant(invalidStyles);
3482      const getValidClasses = constant(validClasses);
3483      const getBoolAttrs = constant(boolAttrMap);
3484      const getBlockElements = constant(blockElementsMap);
3485      const getTextBlockElements = constant(textBlockElementsMap);
3486      const getTextInlineElements = constant(textInlineElementsMap);
3487      const getVoidElements = constant(Object.seal(voidElementsMap));
3488      const getSelfClosingElements = constant(selfClosingElementsMap);
3489      const getNonEmptyElements = constant(nonEmptyElementsMap);
3490      const getMoveCaretBeforeOnEnterElements = constant(moveCaretBeforeOnEnterElementsMap);
3491      const getWhitespaceElements = constant(whitespaceElementsMap);
3492      const getTransparentElements = constant(transparentElementsMap);
3493      const getWrapBlockElements = constant(wrapBlockElementsMap);
3494      const getSpecialElements = constant(Object.seal(specialElements));
3495      const isValidChild = (name, child) => {
3496        const parent = children[name.toLowerCase()];
3497        return !!(parent && parent[child.toLowerCase()]);
3498      };
3499      const isValid = (name, attr) => {
3500        const rule = getElementRule(name);
3501        if (rule) {
3502          if (attr) {
3503            if (rule.attributes[attr]) {
3504              return true;
3505            }
3506            const attrPatterns = rule.attributePatterns;
3507            if (attrPatterns) {
3508              let i = attrPatterns.length;
3509              while (i--) {
3510                if (attrPatterns[i].pattern.test(attr)) {
3511                  return true;
3512                }
3513              }
3514            }
3515          } else {
3516            return true;
3517          }
3518        }
3519        return false;
3520      };
3521      const isBlock = name => has$2(getBlockElements(), name);
3522      const isInline = name => !startsWith(name, '#') && isValid(name) && !isBlock(name);
3523      const isWrapper = name => has$2(getWrapBlockElements(), name) || isInline(name);
3524      const getCustomElements = constant(customElementsMap);
3525      setup();
3526      return {
3527        type: schemaType,
3528        children,
3529        elements,
3530        getValidStyles,
3531        getValidClasses,
3532        getBlockElements,
3533        getInvalidStyles,
3534        getVoidElements,
3535        getTextBlockElements,
3536        getTextInlineElements,
3537        getBoolAttrs,
3538        getElementRule,
3539        getSelfClosingElements,
3540        getNonEmptyElements,
3541        getMoveCaretBeforeOnEnterElements,
3542        getWhitespaceElements,
3543        getTransparentElements,
3544        getSpecialElements,
3545        isValidChild,
3546        isValid,
3547        isBlock,
3548        isInline,
3549        isWrapper,
3550        getCustomElements,
3551        addValidElements,
3552        setValidElements,
3553        addCustomElements,
3554        addValidChildren
3555      };
3556    };
3557
3558    const hexColour = value => ({ value: normalizeHex(value) });
3559    const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
3560    const toHex = component => {
3561      const hex = component.toString(16);
3562      return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
3563    };
3564    const fromRgba = rgbaColour => {
3565      const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
3566      return hexColour(value);
3567    };
3568
3569    const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*
vendor: 7,525 bytes, lines 3569-3766
3569[,\s]\s*(\d+)\s*[,\s]\s*(\d+)\s*\)\s*$/i;
3570    const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*[,\s]\s*(\d+)\s*[,\s]\s*(\d+)\s*[,\s]\s*((?:\d?\.\d+|\d+)%?)\s*\)\s*$/i;
3571    const rgbaColour = (red, green, blue, alpha) => ({
3572      red,
3573      green,
3574      blue,
3575      alpha
3576    });
3577    const fromStringValues = (red, green, blue, alpha) => {
3578      const r = parseInt(red, 10);
3579      const g = parseInt(green, 10);
3580      const b = parseInt(blue, 10);
3581      const a = parseFloat(alpha);
3582      return rgbaColour(r, g, b, a);
3583    };
3584    const getColorFormat = colorString => {
3585      if (rgbRegex.test(colorString)) {
3586        return 'rgb';
3587      } else if (rgbaRegex.test(colorString)) {
3588        return 'rgba';
3589      }
3590      return 'other';
3591    };
3592    const fromString = rgbaString => {
3593      const rgbMatch = rgbRegex.exec(rgbaString);
3594      if (rgbMatch !== null) {
3595        return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
3596      }
3597      const rgbaMatch = rgbaRegex.exec(rgbaString);
3598      if (rgbaMatch !== null) {
3599        return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
3600      }
3601      return Optional.none();
3602    };
3603    const toString = rgba => `rgba(${ rgba.red },${ rgba.green },${ rgba.blue },${ rgba.alpha })`;
3604
3605    const rgbaToHexString = color => fromString(color).map(fromRgba).map(h => '#' + h.value).getOr(color);
3606
3607    const Styles = (settings = {}, schema) => {
3608      const urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi;
3609      const styleRegExp = /\s*([^:]+):\s*([^;]+);?/g;
3610      const trimRightRegExp = /\s+$/;
3611      const encodingLookup = {};
3612      let validStyles;
3613      let invalidStyles;
3614      const invisibleChar = zeroWidth;
3615      if (schema) {
3616        validStyles = schema.getValidStyles();
3617        invalidStyles = schema.getInvalidStyles();
3618      }
3619      const encodingItems = (`\\" \\' \\; \\: ; : ` + invisibleChar).split(' ');
3620      for (let i = 0; i < encodingItems.length; i++) {
3621        encodingLookup[encodingItems[i]] = invisibleChar + i;
3622        encodingLookup[invisibleChar + i] = encodingItems[i];
3623      }
3624      const self = {
3625        parse: css => {
3626          const styles = {};
3627          let isEncoded = false;
3628          const urlConverter = settings.url_converter;
3629          const urlConverterScope = settings.url_converter_scope || self;
3630          const compress = (prefix, suffix, noJoin) => {
3631            const top = styles[prefix + '-top' + suffix];
3632            if (!top) {
3633              return;
3634            }
3635            const right = styles[prefix + '-right' + suffix];
3636            if (!right) {
3637              return;
3638            }
3639            const bottom = styles[prefix + '-bottom' + suffix];
3640            if (!bottom) {
3641              return;
3642            }
3643            const left = styles[prefix + '-left' + suffix];
3644            if (!left) {
3645              return;
3646            }
3647            const box = [
3648              top,
3649              right,
3650              bottom,
3651              left
3652            ];
3653            let i = box.length - 1;
3654            while (i--) {
3655              if (box[i] !== box[i + 1]) {
3656                break;
3657              }
3658            }
3659            if (i > -1 && noJoin) {
3660              return;
3661            }
3662            styles[prefix + suffix] = i === -1 ? box[0] : box.join(' ');
3663            delete styles[prefix + '-top' + suffix];
3664            delete styles[prefix + '-right' + suffix];
3665            delete styles[prefix + '-bottom' + suffix];
3666            delete styles[prefix + '-left' + suffix];
3667          };
3668          const canCompress = key => {
3669            const value = styles[key];
3670            if (!value) {
3671              return;
3672            }
3673            const values = value.indexOf(',') > -1 ? [value] : value.split(' ');
3674            let i = values.length;
3675            while (i--) {
3676              if (values[i] !== values[0]) {
3677                return false;
3678              }
3679            }
3680            styles[key] = values[0];
3681            return true;
3682          };
3683          const compress2 = (target, a, b, c) => {
3684            if (!canCompress(a)) {
3685              return;
3686            }
3687            if (!canCompress(b)) {
3688              return;
3689            }
3690            if (!canCompress(c)) {
3691              return;
3692            }
3693            styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c];
3694            delete styles[a];
3695            delete styles[b];
3696            delete styles[c];
3697          };
3698          const encode = str => {
3699            isEncoded = true;
3700            return encodingLookup[str];
3701          };
3702          const decode = (str, keepSlashes) => {
3703            if (isEncoded) {
3704              str = str.replace(/\uFEFF[0-9]/g, str => {
3705                return encodingLookup[str];
3706              });
3707            }
3708            if (!keepSlashes) {
3709              str = str.replace(/\\([\'\";:])/g, '$1');
3710            }
3711            return str;
3712          };
3713          const decodeSingleHexSequence = escSeq => {
3714            return String.fromCharCode(parseInt(escSeq.slice(1), 16));
3715          };
3716          const decodeHexSequences = value => {
3717            return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence);
3718          };
3719          const processUrl = (match, url, url2, url3, str, str2) => {
3720            str = str || str2;
3721            if (str) {
3722              str = decode(str);
3723              return `'` + str.replace(/\'/g, `\\'`) + `'`;
3724            }
3725            url = decode(url || url2 || url3 || '');
3726            if (!settings.allow_script_urls) {
3727              const scriptUrl = url.replace(/[\s\r\n]+/g, '');
3728              if (/(java|vb)script:/i.test(scriptUrl)) {
3729                return '';
3730              }
3731              if (!settings.allow_svg_data_urls && /^data:image\/svg/i.test(scriptUrl)) {
3732                return '';
3733              }
3734            }
3735            if (urlConverter) {
3736              url = urlConverter.call(urlConverterScope, url, 'style');
3737            }
3738            return `url('` + url.replace(/\'/g, `\\'`) + `')`;
3739          };
3740          if (css) {
3741            css = css.replace(/[\u0000-\u001F]/g, '');
3742            css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, str => {
3743              return str.replace(/[;:]/g, encode);
3744            });
3745            let matches;
3746            while (matches = styleRegExp.exec(css)) {
3747              styleRegExp.lastIndex = matches.index + matches[0].length;
3748              let name = matches[1].replace(trimRightRegExp, '').toLowerCase();
3749              let value = matches[2].replace(trimRightRegExp, '');
3750              if (name && value) {
3751                name = decodeHexSequences(name);
3752                value = decodeHexSequences(value);
3753                if (name.indexOf(invisibleChar) !== -1 || name.indexOf('"') !== -1) {
3754                  continue;
3755                }
3756                if (!settings.allow_script_urls && (name === 'behavior' || /expression\s*\(|\/\*|\*\//.test(value))) {
3757                  continue;
3758                }
3759                if (name === 'font-weight' && value === '700') {
3760                  value = 'bold';
3761                } else if (name === 'color' || name === 'background-color') {
3762                  value = value.toLowerCase();
3763                }
3764                if (getColorFormat(value) === 'rgb') {
3765                  fromString(value).each(rgba => {
3766                    value = rgbaToHexString(toString(rgba)).toLowerCase();
vendor: 11,552 bytes, lines 3766-4071
3766
3767                  });
3768                }
3769                value = value.replace(urlOrStrRegExp, processUrl);
3770                styles[name] = isEncoded ? decode(value, true) : value;
3771              }
3772            }
3773            compress('border', '', true);
3774            compress('border', '-width');
3775            compress('border', '-color');
3776            compress('border', '-style');
3777            compress('padding', '');
3778            compress('margin', '');
3779            compress2('border', 'border-width', 'border-style', 'border-color');
3780            if (styles.border === 'medium none') {
3781              delete styles.border;
3782            }
3783            if (styles['border-image'] === 'none') {
3784              delete styles['border-image'];
3785            }
3786          }
3787          return styles;
3788        },
3789        serialize: (styles, elementName) => {
3790          let css = '';
3791          const serializeStyles = (elemName, validStyleList) => {
3792            const styleList = validStyleList[elemName];
3793            if (styleList) {
3794              for (let i = 0, l = styleList.length; i < l; i++) {
3795                const name = styleList[i];
3796                const value = styles[name];
3797                if (value) {
3798                  css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
3799                }
3800              }
3801            }
3802          };
3803          const isValid = (name, elemName) => {
3804            if (!invalidStyles || !elemName) {
3805              return true;
3806            }
3807            let styleMap = invalidStyles['*'];
3808            if (styleMap && styleMap[name]) {
3809              return false;
3810            }
3811            styleMap = invalidStyles[elemName];
3812            return !(styleMap && styleMap[name]);
3813          };
3814          if (elementName && validStyles) {
3815            serializeStyles('*', validStyles);
3816            serializeStyles(elementName, validStyles);
3817          } else {
3818            each$d(styles, (value, name) => {
3819              if (value && isValid(name, elementName)) {
3820                css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
3821              }
3822            });
3823          }
3824          return css;
3825        }
3826      };
3827      return self;
3828    };
3829
3830    const deprecated = {
3831      keyLocation: true,
3832      layerX: true,
3833      layerY: true,
3834      returnValue: true,
3835      webkitMovementX: true,
3836      webkitMovementY: true,
3837      keyIdentifier: true,
3838      mozPressure: true
3839    };
3840    const isNativeEvent = event => event instanceof Event || isFunction(event.initEvent);
3841    const hasIsDefaultPrevented = event => event.isDefaultPrevented === always || event.isDefaultPrevented === never;
3842    const needsNormalizing = event => isNullable(event.preventDefault) || isNativeEvent(event);
3843    const clone$3 = (originalEvent, data) => {
3844      const event = data !== null && data !== void 0 ? data : {};
3845      for (const name in originalEvent) {
3846        if (!has$2(deprecated, name)) {
3847          event[name] = originalEvent[name];
3848        }
3849      }
3850      if (isNonNullable(originalEvent.composedPath)) {
3851        event.composedPath = () => originalEvent.composedPath();
3852      }
3853      if (isNonNullable(originalEvent.getModifierState)) {
3854        event.getModifierState = keyArg => originalEvent.getModifierState(keyArg);
3855      }
3856      if (isNonNullable(originalEvent.getTargetRanges)) {
3857        event.getTargetRanges = () => originalEvent.getTargetRanges();
3858      }
3859      return event;
3860    };
3861    const normalize$3 = (type, originalEvent, fallbackTarget, data) => {
3862      var _a;
3863      const event = clone$3(originalEvent, data);
3864      event.type = type;
3865      if (isNullable(event.target)) {
3866        event.target = (_a = event.srcElement) !== null && _a !== void 0 ? _a : fallbackTarget;
3867      }
3868      if (needsNormalizing(originalEvent)) {
3869        event.preventDefault = () => {
3870          event.defaultPrevented = true;
3871          event.isDefaultPrevented = always;
3872          if (isFunction(originalEvent.preventDefault)) {
3873            originalEvent.preventDefault();
3874          }
3875        };
3876        event.stopPropagation = () => {
3877          event.cancelBubble = true;
3878          event.isPropagationStopped = always;
3879          if (isFunction(originalEvent.stopPropagation)) {
3880            originalEvent.stopPropagation();
3881          }
3882        };
3883        event.stopImmediatePropagation = () => {
3884          event.isImmediatePropagationStopped = always;
3885          event.stopPropagation();
3886        };
3887        if (!hasIsDefaultPrevented(event)) {
3888          event.isDefaultPrevented = event.defaultPrevented === true ? always : never;
3889          event.isPropagationStopped = event.cancelBubble === true ? always : never;
3890          event.isImmediatePropagationStopped = never;
3891        }
3892      }
3893      return event;
3894    };
3895
3896    const eventExpandoPrefix = 'mce-data-';
3897    const mouseEventRe = /^(?:mouse|contextmenu)|click/;
3898    const addEvent = (target, name, callback, capture) => {
3899      target.addEventListener(name, callback, capture || false);
3900    };
3901    const removeEvent = (target, name, callback, capture) => {
3902      target.removeEventListener(name, callback, capture || false);
3903    };
3904    const isMouseEvent = event => isNonNullable(event) && mouseEventRe.test(event.type);
3905    const fix = (originalEvent, data) => {
3906      const event = normalize$3(originalEvent.type, originalEvent, document, data);
3907      if (isMouseEvent(originalEvent) && isUndefined(originalEvent.pageX) && !isUndefined(originalEvent.clientX)) {
3908        const eventDoc = event.target.ownerDocument || document;
3909        const doc = eventDoc.documentElement;
3910        const body = eventDoc.body;
3911        const mouseEvent = event;
3912        mouseEvent.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
3913        mouseEvent.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
3914      }
3915      return event;
3916    };
3917    const bindOnReady = (win, callback, eventUtils) => {
3918      const doc = win.document, event = { type: 'ready' };
3919      if (eventUtils.domLoaded) {
3920        callback(event);
3921        return;
3922      }
3923      const isDocReady = () => {
3924        return doc.readyState === 'complete' || doc.readyState === 'interactive' && doc.body;
3925      };
3926      const readyHandler = () => {
3927        removeEvent(win, 'DOMContentLoaded', readyHandler);
3928        removeEvent(win, 'load', readyHandler);
3929        if (!eventUtils.domLoaded) {
3930          eventUtils.domLoaded = true;
3931          callback(event);
3932        }
3933        win = null;
3934      };
3935      if (isDocReady()) {
3936        readyHandler();
3937      } else {
3938        addEvent(win, 'DOMContentLoaded', readyHandler);
3939      }
3940      if (!eventUtils.domLoaded) {
3941        addEvent(win, 'load', readyHandler);
3942      }
3943    };
3944    class EventUtils {
3945      constructor() {
3946        this.domLoaded = false;
3947        this.events = {};
3948        this.count = 1;
3949        this.expando = eventExpandoPrefix + (+new Date()).toString(32);
3950        this.hasFocusIn = 'onfocusin' in document.documentElement;
3951        this.count = 1;
3952      }
3953      bind(target, names, callback, scope) {
3954        const self = this;
3955        let callbackList;
3956        const win = window;
3957        const defaultNativeHandler = evt => {
3958          self.executeHandlers(fix(evt || win.event), id);
3959        };
3960        if (!target || isText$b(target) || isComment(target)) {
3961          return callback;
3962        }
3963        let id;
3964        if (!target[self.expando]) {
3965          id = self.count++;
3966          target[self.expando] = id;
3967          self.events[id] = {};
3968        } else {
3969          id = target[self.expando];
3970        }
3971        scope = scope || target;
3972        const namesList = names.split(' ');
3973        let i = namesList.length;
3974        while (i--) {
3975          let name = namesList[i];
3976          let nativeHandler = defaultNativeHandler;
3977          let capture = false;
3978          let fakeName = false;
3979          if (name === 'DOMContentLoaded') {
3980            name = 'ready';
3981          }
3982          if (self.domLoaded && name === 'ready' && target.readyState === 'complete') {
3983            callback.call(scope, fix({ type: name }));
3984            continue;
3985          }
3986          if (!self.hasFocusIn && (name === 'focusin' || name === 'focusout')) {
3987            capture = true;
3988            fakeName = name === 'focusin' ? 'focus' : 'blur';
3989            nativeHandler = evt => {
3990              const event = fix(evt || win.event);
3991              event.type = event.type === 'focus' ? 'focusin' : 'focusout';
3992              self.executeHandlers(event, id);
3993            };
3994          }
3995          callbackList = self.events[id][name];
3996          if (!callbackList) {
3997            self.events[id][name] = callbackList = [{
3998                func: callback,
3999                scope
4000              }];
4001            callbackList.fakeName = fakeName;
4002            callbackList.capture = capture;
4003            callbackList.nativeHandler = nativeHandler;
4004            if (name === 'ready') {
4005              bindOnReady(target, nativeHandler, self);
4006            } else {
4007              addEvent(target, fakeName || name, nativeHandler, capture);
4008            }
4009          } else {
4010            if (name === 'ready' && self.domLoaded) {
4011              callback(fix({ type: name }));
4012            } else {
4013              callbackList.push({
4014                func: callback,
4015                scope
4016              });
4017            }
4018          }
4019        }
4020        target = callbackList = null;
4021        return callback;
4022      }
4023      unbind(target, names, callback) {
4024        if (!target || isText$b(target) || isComment(target)) {
4025          return this;
4026        }
4027        const id = target[this.expando];
4028        if (id) {
4029          let eventMap = this.events[id];
4030          if (names) {
4031            const namesList = names.split(' ');
4032            let i = namesList.length;
4033            while (i--) {
4034              const name = namesList[i];
4035              const callbackList = eventMap[name];
4036              if (callbackList) {
4037                if (callback) {
4038                  let ci = callbackList.length;
4039                  while (ci--) {
4040                    if (callbackList[ci].func === callback) {
4041                      const nativeHandler = callbackList.nativeHandler;
4042                      const fakeName = callbackList.fakeName, capture = callbackList.capture;
4043                      const newCallbackList = callbackList.slice(0, ci).concat(callbackList.slice(ci + 1));
4044                      newCallbackList.nativeHandler = nativeHandler;
4045                      newCallbackList.fakeName = fakeName;
4046                      newCallbackList.capture = capture;
4047                      eventMap[name] = newCallbackList;
4048                    }
4049                  }
4050                }
4051                if (!callback || callbackList.length === 0) {
4052                  delete eventMap[name];
4053                  removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
4054                }
4055              }
4056            }
4057          } else {
4058            each$d(eventMap, (callbackList, name) => {
4059              removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
4060            });
4061            eventMap = {};
4062          }
4063          for (const name in eventMap) {
4064            if (has$2(eventMap, name)) {
4065              return this;
4066            }
4067          }
4068          delete this.events[id];
4069          try {
4070            delete target[this.expando];
4071          } catch (_
vendor: 6,220 bytes, lines 4071-4252
4071a) {
4072            target[this.expando] = null;
4073          }
4074        }
4075        return this;
4076      }
4077      fire(target, name, args) {
4078        return this.dispatch(target, name, args);
4079      }
4080      dispatch(target, name, args) {
4081        if (!target || isText$b(target) || isComment(target)) {
4082          return this;
4083        }
4084        const event = fix({
4085          type: name,
4086          target
4087        }, args);
4088        do {
4089          const id = target[this.expando];
4090          if (id) {
4091            this.executeHandlers(event, id);
4092          }
4093          target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow;
4094        } while (target && !event.isPropagationStopped());
4095        return this;
4096      }
4097      clean(target) {
4098        if (!target || isText$b(target) || isComment(target)) {
4099          return this;
4100        }
4101        if (target[this.expando]) {
4102          this.unbind(target);
4103        }
4104        if (!target.getElementsByTagName) {
4105          target = target.document;
4106        }
4107        if (target && target.getElementsByTagName) {
4108          this.unbind(target);
4109          const children = target.getElementsByTagName('*');
4110          let i = children.length;
4111          while (i--) {
4112            target = children[i];
4113            if (target[this.expando]) {
4114              this.unbind(target);
4115            }
4116          }
4117        }
4118        return this;
4119      }
4120      destroy() {
4121        this.events = {};
4122      }
4123      cancel(e) {
4124        if (e) {
4125          e.preventDefault();
4126          e.stopImmediatePropagation();
4127        }
4128        return false;
4129      }
4130      executeHandlers(evt, id) {
4131        const container = this.events[id];
4132        const callbackList = container && container[evt.type];
4133        if (callbackList) {
4134          for (let i = 0, l = callbackList.length; i < l; i++) {
4135            const callback = callbackList[i];
4136            if (callback && callback.func.call(callback.scope, evt) === false) {
4137              evt.preventDefault();
4138            }
4139            if (evt.isImmediatePropagationStopped()) {
4140              return;
4141            }
4142          }
4143        }
4144      }
4145    }
4146    EventUtils.Event = new EventUtils();
4147
4148    const each$a = Tools.each;
4149    const grep = Tools.grep;
4150    const internalStyleName = 'data-mce-style';
4151    const numericalCssMap = Tools.makeMap('fill-opacity font-weight line-height opacity orphans widows z-index zoom', ' ');
4152    const legacySetAttribute = (elm, name, value) => {
4153      if (isNullable(value) || value === '') {
4154        remove$9(elm, name);
4155      } else {
4156        set$4(elm, name, value);
4157      }
4158    };
4159    const camelCaseToHyphens = name => name.replace(/[A-Z]/g, v => '-' + v.toLowerCase());
4160    const findNodeIndex = (node, normalized) => {
4161      let idx = 0;
4162      if (node) {
4163        for (let lastNodeType = node.nodeType, tempNode = node.previousSibling; tempNode; tempNode = tempNode.previousSibling) {
4164          const nodeType = tempNode.nodeType;
4165          if (normalized && isText$b(tempNode)) {
4166            if (nodeType === lastNodeType || !tempNode.data.length) {
4167              continue;
4168            }
4169          }
4170          idx++;
4171          lastNodeType = nodeType;
4172        }
4173      }
4174      return idx;
4175    };
4176    const updateInternalStyleAttr = (styles, elm) => {
4177      const rawValue = get$9(elm, 'style');
4178      const value = styles.serialize(styles.parse(rawValue), name(elm));
4179      legacySetAttribute(elm, internalStyleName, value);
4180    };
4181    const convertStyleToString = (cssValue, cssName) => {
4182      if (isNumber(cssValue)) {
4183        return has$2(numericalCssMap, cssName) ? cssValue + '' : cssValue + 'px';
4184      } else {
4185        return cssValue;
4186      }
4187    };
4188    const applyStyle$1 = ($elm, cssName, cssValue) => {
4189      const normalizedName = camelCaseToHyphens(cssName);
4190      if (isNullable(cssValue) || cssValue === '') {
4191        remove$5($elm, normalizedName);
4192      } else {
4193        set$2($elm, normalizedName, convertStyleToString(cssValue, normalizedName));
4194      }
4195    };
4196    const setupAttrHooks = (styles, settings, getContext) => {
4197      const keepValues = settings.keep_values;
4198      const keepUrlHook = {
4199        set: (elm, value, name) => {
4200          const sugarElm = SugarElement.fromDom(elm);
4201          if (isFunction(settings.url_converter) && isNonNullable(value)) {
4202            value = settings.url_converter.call(settings.url_converter_scope || getContext(), String(value), name, elm);
4203          }
4204          const internalName = 'data-mce-' + name;
4205          legacySetAttribute(sugarElm, internalName, value);
4206          legacySetAttribute(sugarElm, name, value);
4207        },
4208        get: (elm, name) => {
4209          const sugarElm = SugarElement.fromDom(elm);
4210          return get$9(sugarElm, 'data-mce-' + name) || get$9(sugarElm, name);
4211        }
4212      };
4213      const attrHooks = {
4214        style: {
4215          set: (elm, value) => {
4216            const sugarElm = SugarElement.fromDom(elm);
4217            if (keepValues) {
4218              legacySetAttribute(sugarElm, internalStyleName, value);
4219            }
4220            remove$9(sugarElm, 'style');
4221            if (isString(value)) {
4222              setAll(sugarElm, styles.parse(value));
4223            }
4224          },
4225          get: elm => {
4226            const sugarElm = SugarElement.fromDom(elm);
4227            const value = get$9(sugarElm, internalStyleName) || get$9(sugarElm, 'style');
4228            return styles.serialize(styles.parse(value), name(sugarElm));
4229          }
4230        }
4231      };
4232      if (keepValues) {
4233        attrHooks.href = attrHooks.src = keepUrlHook;
4234      }
4235      return attrHooks;
4236    };
4237    const DOMUtils = (doc, settings = {}) => {
4238      const addedStyles = {};
4239      const win = window;
4240      const files = {};
4241      let counter = 0;
4242      const stdMode = true;
4243      const boxModel = true;
4244      const styleSheetLoader = instance.forElement(SugarElement.fromDom(doc), {
4245        contentCssCors: settings.contentCssCors,
4246        referrerPolicy: settings.referrerPolicy
4247      });
4248      const boundEvents = [];
4249      const schema = settings.schema ? settings.schema : Schema({});
4250      const styles = Styles({
4251        url_converter: settings.url_converter,
4252        url_converter_scope: settings.url_converter_scope
vendor: 26,072 bytes, lines 4252-5055
4252
4253      }, settings.schema);
4254      const events = settings.ownEvents ? new EventUtils() : EventUtils.Event;
4255      const blockElementsMap = schema.getBlockElements();
4256      const isBlock = node => {
4257        if (isString(node)) {
4258          return has$2(blockElementsMap, node);
4259        } else {
4260          return isElement$6(node) && (has$2(blockElementsMap, node.nodeName) || isTransparentBlock(schema, node));
4261        }
4262      };
4263      const get = elm => elm && doc && isString(elm) ? doc.getElementById(elm) : elm;
4264      const _get = elm => {
4265        const value = get(elm);
4266        return isNonNullable(value) ? SugarElement.fromDom(value) : null;
4267      };
4268      const getAttrib = (elm, name, defaultVal = '') => {
4269        let value;
4270        const $elm = _get(elm);
4271        if (isNonNullable($elm) && isElement$7($elm)) {
4272          const hook = attrHooks[name];
4273          if (hook && hook.get) {
4274            value = hook.get($elm.dom, name);
4275          } else {
4276            value = get$9($elm, name);
4277          }
4278        }
4279        return isNonNullable(value) ? value : defaultVal;
4280      };
4281      const getAttribs = elm => {
4282        const node = get(elm);
4283        return isNullable(node) ? [] : node.attributes;
4284      };
4285      const setAttrib = (elm, name, value) => {
4286        run(elm, e => {
4287          if (isElement$6(e)) {
4288            const $elm = SugarElement.fromDom(e);
4289            const val = value === '' ? null : value;
4290            const originalValue = get$9($elm, name);
4291            const hook = attrHooks[name];
4292            if (hook && hook.set) {
4293              hook.set($elm.dom, val, name);
4294            } else {
4295              legacySetAttribute($elm, name, val);
4296            }
4297            if (originalValue !== val && settings.onSetAttrib) {
4298              settings.onSetAttrib({
4299                attrElm: $elm.dom,
4300                attrName: name,
4301                attrValue: val
4302              });
4303            }
4304          }
4305        });
4306      };
4307      const clone = (node, deep) => {
4308        return node.cloneNode(deep);
4309      };
4310      const getRoot = () => settings.root_element || doc.body;
4311      const getViewPort = argWin => {
4312        const vp = getBounds(argWin);
4313        return {
4314          x: vp.x,
4315          y: vp.y,
4316          w: vp.width,
4317          h: vp.height
4318        };
4319      };
4320      const getPos$1 = (elm, rootElm) => getPos(doc.body, get(elm), rootElm);
4321      const setStyle = (elm, name, value) => {
4322        run(elm, e => {
4323          const $elm = SugarElement.fromDom(e);
4324          applyStyle$1($elm, name, value);
4325          if (settings.update_styles) {
4326            updateInternalStyleAttr(styles, $elm);
4327          }
4328        });
4329      };
4330      const setStyles = (elm, stylesArg) => {
4331        run(elm, e => {
4332          const $elm = SugarElement.fromDom(e);
4333          each$d(stylesArg, (v, n) => {
4334            applyStyle$1($elm, n, v);
4335          });
4336          if (settings.update_styles) {
4337            updateInternalStyleAttr(styles, $elm);
4338          }
4339        });
4340      };
4341      const getStyle = (elm, name, computed) => {
4342        const $elm = get(elm);
4343        if (isNullable($elm) || !isHTMLElement($elm) && !isSVGElement($elm)) {
4344          return undefined;
4345        }
4346        if (computed) {
4347          return get$7(SugarElement.fromDom($elm), camelCaseToHyphens(name));
4348        } else {
4349          name = name.replace(/-(\D)/g, (a, b) => b.toUpperCase());
4350          if (name === 'float') {
4351            name = 'cssFloat';
4352          }
4353          return $elm.style ? $elm.style[name] : undefined;
4354        }
4355      };
4356      const getSize = elm => {
4357        const $elm = get(elm);
4358        if (!$elm) {
4359          return {
4360            w: 0,
4361            h: 0
4362          };
4363        }
4364        let w = getStyle($elm, 'width');
4365        let h = getStyle($elm, 'height');
4366        if (!w || w.indexOf('px') === -1) {
4367          w = '0';
4368        }
4369        if (!h || h.indexOf('px') === -1) {
4370          h = '0';
4371        }
4372        return {
4373          w: parseInt(w, 10) || $elm.offsetWidth || $elm.clientWidth,
4374          h: parseInt(h, 10) || $elm.offsetHeight || $elm.clientHeight
4375        };
4376      };
4377      const getRect = elm => {
4378        const $elm = get(elm);
4379        const pos = getPos$1($elm);
4380        const size = getSize($elm);
4381        return {
4382          x: pos.x,
4383          y: pos.y,
4384          w: size.w,
4385          h: size.h
4386        };
4387      };
4388      const is = (elm, selector) => {
4389        if (!elm) {
4390          return false;
4391        }
4392        const elms = isArray$1(elm) ? elm : [elm];
4393        return exists(elms, e => {
4394          return is$1(SugarElement.fromDom(e), selector);
4395        });
4396      };
4397      const getParents = (elm, selector, root, collect) => {
4398        const result = [];
4399        let node = get(elm);
4400        collect = collect === undefined;
4401        const resolvedRoot = root || (getRoot().nodeName !== 'BODY' ? getRoot().parentNode : null);
4402        if (isString(selector)) {
4403          if (selector === '*') {
4404            selector = isElement$6;
4405          } else {
4406            const selectorVal = selector;
4407            selector = node => is(node, selectorVal);
4408          }
4409        }
4410        while (node) {
4411          if (node === resolvedRoot || isNullable(node.nodeType) || isDocument$1(node) || isDocumentFragment(node)) {
4412            break;
4413          }
4414          if (!selector || selector(node)) {
4415            if (collect) {
4416              result.push(node);
4417            } else {
4418              return [node];
4419            }
4420          }
4421          node = node.parentNode;
4422        }
4423        return collect ? result : null;
4424      };
4425      const getParent = (node, selector, root) => {
4426        const parents = getParents(node, selector, root, false);
4427        return parents && parents.length > 0 ? parents[0] : null;
4428      };
4429      const _findSib = (node, selector, name) => {
4430        let func = selector;
4431        if (node) {
4432          if (isString(selector)) {
4433            func = node => {
4434              return is(node, selector);
4435            };
4436          }
4437          for (let tempNode = node[name]; tempNode; tempNode = tempNode[name]) {
4438            if (isFunction(func) && func(tempNode)) {
4439              return tempNode;
4440            }
4441          }
4442        }
4443        return null;
4444      };
4445      const getNext = (node, selector) => _findSib(node, selector, 'nextSibling');
4446      const getPrev = (node, selector) => _findSib(node, selector, 'previousSibling');
4447      const isParentNode = node => isFunction(node.querySelectorAll);
4448      const select = (selector, scope) => {
4449        var _a, _b;
4450        const elm = (_b = (_a = get(scope)) !== null && _a !== void 0 ? _a : settings.root_element) !== null && _b !== void 0 ? _b : doc;
4451        return isParentNode(elm) ? from(elm.querySelectorAll(selector)) : [];
4452      };
4453      const run = function (elm, func, scope) {
4454        const context = scope !== null && scope !== void 0 ? scope : this;
4455        if (isArray$1(elm)) {
4456          const result = [];
4457          each$a(elm, (e, i) => {
4458            const node = get(e);
4459            if (node) {
4460              result.push(func.call(context, node, i));
4461            }
4462          });
4463          return result;
4464        } else {
4465          const node = get(elm);
4466          return !node ? false : func.call(context, node);
4467        }
4468      };
4469      const setAttribs = (elm, attrs) => {
4470        run(elm, $elm => {
4471          each$d(attrs, (value, name) => {
4472            setAttrib($elm, name, value);
4473          });
4474        });
4475      };
4476      const setHTML = (elm, html) => {
4477        run(elm, e => {
4478          const $elm = SugarElement.fromDom(e);
4479          set$1($elm, html);
4480        });
4481      };
4482      const add = (parentElm, name, attrs, html, create) => run(parentElm, parentElm => {
4483        const newElm = isString(name) ? doc.createElement(name) : name;
4484        if (isNonNullable(attrs)) {
4485          setAttribs(newElm, attrs);
4486        }
4487        if (html) {
4488          if (!isString(html) && html.nodeType) {
4489            newElm.appendChild(html);
4490          } else if (isString(html)) {
4491            setHTML(newElm, html);
4492          }
4493        }
4494        return !create ? parentElm.appendChild(newElm) : newElm;
4495      });
4496      const create = (name, attrs, html) => add(doc.createElement(name), name, attrs, html, true);
4497      const decode = Entities.decode;
4498      const encode = Entities.encodeAllRaw;
4499      const createHTML = (name, attrs, html = '') => {
4500        let outHtml = '<' + name;
4501        for (const key in attrs) {
4502          if (hasNonNullableKey(attrs, key)) {
4503            outHtml += ' ' + key + '="' + encode(attrs[key]) + '"';
4504          }
4505        }
4506        if (isEmpty$3(html) && has$2(schema.getVoidElements(), name)) {
4507          return outHtml + ' />';
4508        } else {
4509          return outHtml + '>' + html + '</' + name + '>';
4510        }
4511      };
4512      const createFragment = html => {
4513        const container = doc.createElement('div');
4514        const frag = doc.createDocumentFragment();
4515        frag.appendChild(container);
4516        if (html) {
4517          container.innerHTML = html;
4518        }
4519        let node;
4520        while (node = container.firstChild) {
4521          frag.appendChild(node);
4522        }
4523        frag.removeChild(container);
4524        return frag;
4525      };
4526      const remove = (node, keepChildren) => {
4527        return run(node, n => {
4528          const $node = SugarElement.fromDom(n);
4529          if (keepChildren) {
4530            each$e(children$1($node), child => {
4531              if (isText$c(child) && child.dom.length === 0) {
4532                remove$4(child);
4533              } else {
4534                before$3($node, child);
4535              }
4536            });
4537          }
4538          remove$4($node);
4539          return $node.dom;
4540        });
4541      };
4542      const removeAllAttribs = e => run(e, e => {
4543        const attrs = e.attributes;
4544        for (let i = attrs.length - 1; i >= 0; i--) {
4545          e.removeAttributeNode(attrs.item(i));
4546        }
4547      });
4548      const parseStyle = cssText => styles.parse(cssText);
4549      const serializeStyle = (stylesArg, name) => styles.serialize(stylesArg, name);
4550      const addStyle = cssText => {
4551        if (self !== DOMUtils.DOM && doc === document) {
4552          if (addedStyles[cssText]) {
4553            return;
4554          }
4555          addedStyles[cssText] = true;
4556        }
4557        let styleElm = doc.getElementById('mceDefaultStyles');
4558        if (!styleElm) {
4559          styleElm = doc.createElement('style');
4560          styleElm.id = 'mceDefaultStyles';
4561          styleElm.type = 'text/css';
4562          const head = doc.head;
4563          if (head.firstChild) {
4564            head.insertBefore(styleElm, head.firstChild);
4565          } else {
4566            head.appendChild(styleElm);
4567          }
4568        }
4569        if (styleElm.styleSheet) {
4570          styleElm.styleSheet.cssText += cssText;
4571        } else {
4572          styleElm.appendChild(doc.createTextNode(cssText));
4573        }
4574      };
4575      const loadCSS = urls => {
4576        if (!urls) {
4577          urls = '';
4578        }
4579        each$e(urls.split(','), url => {
4580          files[url] = true;
4581          styleSheetLoader.load(url).catch(noop);
4582        });
4583      };
4584      const toggleClass = (elm, cls, state) => {
4585        run(elm, e => {
4586          if (isElement$6(e)) {
4587            const $elm = SugarElement.fromDom(e);
4588            const classes = cls.split(' ');
4589            each$e(classes, c => {
4590              if (isNonNullable(state)) {
4591                const fn = state ? add$2 : remove$6;
4592                fn($elm, c);
4593              } else {
4594                toggle$1($elm, c);
4595              }
4596            });
4597          }
4598        });
4599      };
4600      const addClass = (elm, cls) => {
4601        toggleClass(elm, cls, true);
4602      };
4603      const removeClass = (elm, cls) => {
4604        toggleClass(elm, cls, false);
4605      };
4606      const hasClass = (elm, cls) => {
4607        const $elm = _get(elm);
4608        const classes = cls.split(' ');
4609        return isNonNullable($elm) && forall(classes, c => has($elm, c));
4610      };
4611      const show = elm => {
4612        run(elm, e => remove$5(SugarElement.fromDom(e), 'display'));
4613      };
4614      const hide = elm => {
4615        run(elm, e => set$2(SugarElement.fromDom(e), 'display', 'none'));
4616      };
4617      const isHidden = elm => {
4618        const $elm = _get(elm);
4619        return isNonNullable($elm) && is$2(getRaw($elm, 'display'), 'none');
4620      };
4621      const uniqueId = prefix => (!prefix ? 'mce_' : prefix) + counter++;
4622      const getOuterHTML = elm => {
4623        const $elm = _get(elm);
4624        if (isNonNullable($elm)) {
4625          return isElement$6($elm.dom) ? $elm.dom.outerHTML : getOuter($elm);
4626        } else {
4627          return '';
4628        }
4629      };
4630      const setOuterHTML = (elm, html) => {
4631        run(elm, $elm => {
4632          if (isElement$6($elm)) {
4633            $elm.outerHTML = html;
4634          }
4635        });
4636      };
4637      const insertAfter = (node, reference) => {
4638        const referenceNode = get(reference);
4639        return run(node, node => {
4640          const parent = referenceNode === null || referenceNode === void 0 ? void 0 : referenceNode.parentNode;
4641          const nextSibling = referenceNode === null || referenceNode === void 0 ? void 0 : referenceNode.nextSibling;
4642          if (parent) {
4643            if (nextSibling) {
4644              parent.insertBefore(node, nextSibling);
4645            } else {
4646              parent.appendChild(node);
4647            }
4648          }
4649          return node;
4650        });
4651      };
4652      const replace = (newElm, oldElm, keepChildren) => run(oldElm, elm => {
4653        var _a;
4654        const replacee = isArray$1(oldElm) ? newElm.cloneNode(true) : newElm;
4655        if (keepChildren) {
4656          each$a(grep(elm.childNodes), node => {
4657            replacee.appendChild(node);
4658          });
4659        }
4660        (_a = elm.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(replacee, elm);
4661        return elm;
4662      });
4663      const rename = (elm, name) => {
4664        if (elm.nodeName !== name.toUpperCase()) {
4665          const newElm = create(name);
4666          each$a(getAttribs(elm), attrNode => {
4667            setAttrib(newElm, attrNode.nodeName, getAttrib(elm, attrNode.nodeName));
4668          });
4669          replace(newElm, elm, true);
4670          return newElm;
4671        } else {
4672          return elm;
4673        }
4674      };
4675      const findCommonAncestor = (a, b) => {
4676        let ps = a;
4677        while (ps) {
4678          let pe = b;
4679          while (pe && ps !== pe) {
4680            pe = pe.parentNode;
4681          }
4682          if (ps === pe) {
4683            break;
4684          }
4685          ps = ps.parentNode;
4686        }
4687        if (!ps && a.ownerDocument) {
4688          return a.ownerDocument.documentElement;
4689        } else {
4690          return ps;
4691        }
4692      };
4693      const isEmpty = (node, elements, options) => {
4694        if (isPlainObject(elements)) {
4695          const isContent = node => {
4696            const name = node.nodeName.toLowerCase();
4697            return Boolean(elements[name]);
4698          };
4699          return isEmptyNode(schema, node, {
4700            ...options,
4701            isContent
4702          });
4703        } else {
4704          return isEmptyNode(schema, node, options);
4705        }
4706      };
4707      const createRng = () => doc.createRange();
4708      const split = (parentElm, splitElm, replacementElm) => {
4709        let range = createRng();
4710        let beforeFragment;
4711        let afterFragment;
4712        if (parentElm && splitElm && parentElm.parentNode && splitElm.parentNode) {
4713          const parentNode = parentElm.parentNode;
4714          range.setStart(parentNode, findNodeIndex(parentElm));
4715          range.setEnd(splitElm.parentNode, findNodeIndex(splitElm));
4716          beforeFragment = range.extractContents();
4717          range = createRng();
4718          range.setStart(splitElm.parentNode, findNodeIndex(splitElm) + 1);
4719          range.setEnd(parentNode, findNodeIndex(parentElm) + 1);
4720          afterFragment = range.extractContents();
4721          parentNode.insertBefore(trimNode(self, beforeFragment, schema), parentElm);
4722          if (replacementElm) {
4723            parentNode.insertBefore(replacementElm, parentElm);
4724          } else {
4725            parentNode.insertBefore(splitElm, parentElm);
4726          }
4727          parentNode.insertBefore(trimNode(self, afterFragment, schema), parentElm);
4728          remove(parentElm);
4729          return replacementElm || splitElm;
4730        } else {
4731          return undefined;
4732        }
4733      };
4734      const bind = (target, name, func, scope) => {
4735        if (isArray$1(target)) {
4736          let i = target.length;
4737          const rv = [];
4738          while (i--) {
4739            rv[i] = bind(target[i], name, func, scope);
4740          }
4741          return rv;
4742        } else {
4743          if (settings.collect && (target === doc || target === win)) {
4744            boundEvents.push([
4745              target,
4746              name,
4747              func,
4748              scope
4749            ]);
4750          }
4751          return events.bind(target, name, func, scope || self);
4752        }
4753      };
4754      const unbind = (target, name, func) => {
4755        if (isArray$1(target)) {
4756          let i = target.length;
4757          const rv = [];
4758          while (i--) {
4759            rv[i] = unbind(target[i], name, func);
4760          }
4761          return rv;
4762        } else {
4763          if (boundEvents.length > 0 && (target === doc || target === win)) {
4764            let i = boundEvents.length;
4765            while (i--) {
4766              const [boundTarget, boundName, boundFunc] = boundEvents[i];
4767              if (target === boundTarget && (!name || name === boundName) && (!func || func === boundFunc)) {
4768                events.unbind(boundTarget, boundName, boundFunc);
4769              }
4770            }
4771          }
4772          return events.unbind(target, name, func);
4773        }
4774      };
4775      const dispatch = (target, name, evt) => events.dispatch(target, name, evt);
4776      const fire = (target, name, evt) => events.dispatch(target, name, evt);
4777      const getContentEditable = node => {
4778        if (node && isHTMLElement(node)) {
4779          const contentEditable = node.getAttribute('data-mce-contenteditable');
4780          if (contentEditable && contentEditable !== 'inherit') {
4781            return contentEditable;
4782          }
4783          return node.contentEditable !== 'inherit' ? node.contentEditable : null;
4784        } else {
4785          return null;
4786        }
4787      };
4788      const getContentEditableParent = node => {
4789        const root = getRoot();
4790        let state = null;
4791        for (let tempNode = node; tempNode && tempNode !== root; tempNode = tempNode.parentNode) {
4792          state = getContentEditable(tempNode);
4793          if (state !== null) {
4794            break;
4795          }
4796        }
4797        return state;
4798      };
4799      const isEditable = node => {
4800        if (isNonNullable(node)) {
4801          const scope = isElement$6(node) ? node : node.parentElement;
4802          return isNonNullable(scope) && isHTMLElement(scope) && isEditable$2(SugarElement.fromDom(scope));
4803        } else {
4804          return false;
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;
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(() => {
5045              processQueue(uniqueScripts).then(resolve, reject);
5046            });
5047          });
5048        } else {
5049          return processQueue(uniqueScripts);
5050        }
5051      }
5052    }
5053    ScriptLoader.ScriptLoader = new ScriptLoader();
5054
5055    const 
vendor: 1,774 bytes, lines 5055-5100
5055isDuplicated = (items, item) => {
5056      const firstIndex = items.indexOf(item);
5057      return firstIndex !== -1 && items.indexOf(item, firstIndex + 1) > firstIndex;
5058    };
5059    const isRaw = str => isObject(str) && has$2(str, 'raw');
5060    const isTokenised = str => isArray$1(str) && str.length > 1;
5061    const data = {};
5062    const currentCode = Cell('en');
5063    const getLanguageData = () => get$a(data, currentCode.get());
5064    const getData$1 = () => map$2(data, value => ({ ...value }));
5065    const setCode = newCode => {
5066      if (newCode) {
5067        currentCode.set(newCode);
5068      }
5069    };
5070    const getCode = () => currentCode.get();
5071    const add$1 = (code, items) => {
5072      let langData = data[code];
5073      if (!langData) {
5074        data[code] = langData = {};
5075      }
5076      const lcNames = map$3(keys(items), name => name.toLowerCase());
5077      each$d(items, (translation, name) => {
5078        const lcName = name.toLowerCase();
5079        if (lcName !== name && isDuplicated(lcNames, lcName)) {
5080          if (!has$2(items, lcName)) {
5081            langData[lcName] = translation;
5082          }
5083          langData[name] = translation;
5084        } else {
5085          langData[lcName] = translation;
5086        }
5087      });
5088    };
5089    const translate = text => {
5090      const langData = getLanguageData().getOr({});
5091      const toString = obj => {
5092        if (isFunction(obj)) {
5093          return Object.prototype.toString.call(obj);
5094        }
5095        return !isEmpty(obj) ? '' + obj : '';
5096      };
5097      const isEmpty = text => text === '' || text === null || text === undefined;
5098      const getLangData = text => {
5099        const textStr = toString(text);
5100        return has$2(langData, textStr) ? toString(langData[textStr]) : get$a(langData, textStr.toLowerCase()).map(toString).getOr(textS
vendor: 4,338 bytes, lines 5100-5240
5100tr);
5101      };
5102      const removeContext = str => str.replace(/{context:\w+}$/, '');
5103      if (isEmpty(text)) {
5104        return '';
5105      }
5106      if (isRaw(text)) {
5107        return toString(text.raw);
5108      }
5109      if (isTokenised(text)) {
5110        const values = text.slice(1);
5111        const substitued = getLangData(text[0]).replace(/\{([0-9]+)\}/g, ($1, $2) => has$2(values, $2) ? toString(values[$2]) : $1);
5112        return removeContext(substitued);
5113      }
5114      return removeContext(getLangData(text));
5115    };
5116    const isRtl$1 = () => getLanguageData().bind(items => get$a(items, '_dir')).exists(dir => dir === 'rtl');
5117    const hasCode = code => has$2(data, code);
5118    const I18n = {
5119      getData: getData$1,
5120      setCode,
5121      getCode,
5122      add: add$1,
5123      translate,
5124      isRtl: isRtl$1,
5125      hasCode
5126    };
5127
5128    const AddOnManager = () => {
5129      const items = [];
5130      const urls = {};
5131      const lookup = {};
5132      const _listeners = [];
5133      const runListeners = (name, state) => {
5134        const matchedListeners = filter$5(_listeners, listener => listener.name === name && listener.state === state);
5135        each$e(matchedListeners, listener => listener.resolve());
5136      };
5137      const isLoaded = name => has$2(urls, name);
5138      const isAdded = name => has$2(lookup, name);
5139      const get = name => {
5140        if (lookup[name]) {
5141          return lookup[name].instance;
5142        }
5143        return undefined;
5144      };
5145      const loadLanguagePack = (name, languages) => {
5146        const language = I18n.getCode();
5147        const wrappedLanguages = ',' + (languages || '') + ',';
5148        if (!language || languages && wrappedLanguages.indexOf(',' + language + ',') === -1) {
5149          return;
5150        }
5151        ScriptLoader.ScriptLoader.add(urls[name] + '/langs/' + language + '.js');
5152      };
5153      const requireLangPack = (name, languages) => {
5154        if (AddOnManager.languageLoad !== false) {
5155          if (isLoaded(name)) {
5156            loadLanguagePack(name, languages);
5157          } else {
5158            waitFor(name, 'loaded').then(() => loadLanguagePack(name, languages));
5159          }
5160        }
5161      };
5162      const add = (id, addOn) => {
5163        items.push(addOn);
5164        lookup[id] = { instance: addOn };
5165        runListeners(id, 'added');
5166        return addOn;
5167      };
5168      const remove = name => {
5169        delete urls[name];
5170        delete lookup[name];
5171      };
5172      const createUrl = (baseUrl, dep) => {
5173        if (isString(dep)) {
5174          return isString(baseUrl) ? {
5175            prefix: '',
5176            resource: dep,
5177            suffix: ''
5178          } : {
5179            prefix: baseUrl.prefix,
5180            resource: dep,
5181            suffix: baseUrl.suffix
5182          };
5183        } else {
5184          return dep;
5185        }
5186      };
5187      const load = (name, addOnUrl) => {
5188        if (urls[name]) {
5189          return Promise.resolve();
5190        }
5191        let urlString = isString(addOnUrl) ? addOnUrl : addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
5192        if (urlString.indexOf('/') !== 0 && urlString.indexOf('://') === -1) {
5193          urlString = AddOnManager.baseURL + '/' + urlString;
5194        }
5195        urls[name] = urlString.substring(0, urlString.lastIndexOf('/'));
5196        const done = () => {
5197          runListeners(name, 'loaded');
5198          return Promise.resolve();
5199        };
5200        if (lookup[name]) {
5201          return done();
5202        } else {
5203          return ScriptLoader.ScriptLoader.add(urlString).then(done);
5204        }
5205      };
5206      const waitFor = (name, state = 'added') => {
5207        if (state === 'added' && isAdded(name)) {
5208          return Promise.resolve();
5209        } else if (state === 'loaded' && isLoaded(name)) {
5210          return Promise.resolve();
5211        } else {
5212          return new Promise(resolve => {
5213            _listeners.push({
5214              name,
5215              state,
5216              resolve
5217            });
5218          });
5219        }
5220      };
5221      return {
5222        items,
5223        urls,
5224        lookup,
5225        get,
5226        requireLangPack,
5227        add,
5228        remove,
5229        createUrl,
5230        load,
5231        waitFor
5232      };
5233    };
5234    AddOnManager.languageLoad = true;
5235    AddOnManager.baseURL = '';
5236    AddOnManager.PluginManager = AddOnManager();
5237    AddOnManager.ThemeManager = AddOnManager();
5238    AddOnManager.ModelManager = AddOnManager();
5239
5240    const 
vendor: 13,819 bytes, lines 5240-5663
5240first$1 = (fn, rate) => {
5241      let timer = null;
5242      const cancel = () => {
5243        if (!isNull(timer)) {
5244          clearTimeout(timer);
5245          timer = null;
5246        }
5247      };
5248      const throttle = (...args) => {
5249        if (isNull(timer)) {
5250          timer = setTimeout(() => {
5251            timer = null;
5252            fn.apply(null, args);
5253          }, rate);
5254        }
5255      };
5256      return {
5257        cancel,
5258        throttle
5259      };
5260    };
5261    const last = (fn, rate) => {
5262      let timer = null;
5263      const cancel = () => {
5264        if (!isNull(timer)) {
5265          clearTimeout(timer);
5266          timer = null;
5267        }
5268      };
5269      const throttle = (...args) => {
5270        cancel();
5271        timer = setTimeout(() => {
5272          timer = null;
5273          fn.apply(null, args);
5274        }, rate);
5275      };
5276      return {
5277        cancel,
5278        throttle
5279      };
5280    };
5281
5282    const ancestor$1 = (scope, selector, isRoot) => ancestor$3(scope, selector, isRoot).isSome();
5283
5284    const annotation = constant('mce-annotation');
5285    const dataAnnotation = constant('data-mce-annotation');
5286    const dataAnnotationId = constant('data-mce-annotation-uid');
5287    const dataAnnotationActive = constant('data-mce-annotation-active');
5288    const dataAnnotationClasses = constant('data-mce-annotation-classes');
5289    const dataAnnotationAttributes = constant('data-mce-annotation-attrs');
5290
5291    const isRoot$1 = root => node => eq(node, root);
5292    const identify = (editor, annotationName) => {
5293      const rng = editor.selection.getRng();
5294      const start = SugarElement.fromDom(rng.startContainer);
5295      const root = SugarElement.fromDom(editor.getBody());
5296      const selector = annotationName.fold(() => '.' + annotation(), an => `[${ dataAnnotation() }="${ an }"]`);
5297      const newStart = child$1(start, rng.startOffset).getOr(start);
5298      const closest = closest$3(newStart, selector, isRoot$1(root));
5299      return closest.bind(c => getOpt(c, `${ dataAnnotationId() }`).bind(uid => getOpt(c, `${ dataAnnotation() }`).map(name => {
5300        const elements = findMarkers(editor, uid);
5301        return {
5302          uid,
5303          name,
5304          elements
5305        };
5306      })));
5307    };
5308    const isAnnotation = elem => isElement$7(elem) && has(elem, annotation());
5309    const isBogusElement = (elem, root) => has$1(elem, 'data-mce-bogus') || ancestor$1(elem, '[data-mce-bogus="all"]', isRoot$1(root));
5310    const findMarkers = (editor, uid) => {
5311      const body = SugarElement.fromDom(editor.getBody());
5312      const descendants$1 = descendants(body, `[${ dataAnnotationId() }="${ uid }"]`);
5313      return filter$5(descendants$1, descendant => !isBogusElement(descendant, body));
5314    };
5315    const findAll = (editor, name) => {
5316      const body = SugarElement.fromDom(editor.getBody());
5317      const markers = descendants(body, `[${ dataAnnotation() }="${ name }"]`);
5318      const directory = {};
5319      each$e(markers, m => {
5320        if (!isBogusElement(m, body)) {
5321          const uid = get$9(m, dataAnnotationId());
5322          const nodesAlready = get$a(directory, uid).getOr([]);
5323          directory[uid] = nodesAlready.concat([m]);
5324        }
5325      });
5326      return directory;
5327    };
5328
5329    const setup$y = (editor, registry) => {
5330      const changeCallbacks = Cell({});
5331      const initData = () => ({
5332        listeners: [],
5333        previous: value$2()
5334      });
5335      const withCallbacks = (name, f) => {
5336        updateCallbacks(name, data => {
5337          f(data);
5338          return data;
5339        });
5340      };
5341      const updateCallbacks = (name, f) => {
5342        const callbackMap = changeCallbacks.get();
5343        const data = get$a(callbackMap, name).getOrThunk(initData);
5344        const outputData = f(data);
5345        callbackMap[name] = outputData;
5346        changeCallbacks.set(callbackMap);
5347      };
5348      const fireCallbacks = (name, uid, elements) => {
5349        withCallbacks(name, data => {
5350          each$e(data.listeners, f => f(true, name, {
5351            uid,
5352            nodes: map$3(elements, elem => elem.dom)
5353          }));
5354        });
5355      };
5356      const fireNoAnnotation = name => {
5357        withCallbacks(name, data => {
5358          each$e(data.listeners, f => f(false, name));
5359        });
5360      };
5361      const toggleActiveAttr = (uid, state) => {
5362        each$e(findMarkers(editor, uid), elem => {
5363          if (state) {
5364            set$4(elem, dataAnnotationActive(), 'true');
5365          } else {
5366            remove$9(elem, dataAnnotationActive());
5367          }
5368        });
5369      };
5370      const onNodeChange = last(() => {
5371        const annotations = sort(registry.getNames());
5372        each$e(annotations, name => {
5373          updateCallbacks(name, data => {
5374            const prev = data.previous.get();
5375            identify(editor, Optional.some(name)).fold(() => {
5376              prev.each(uid => {
5377                fireNoAnnotation(name);
5378                data.previous.clear();
5379                toggleActiveAttr(uid, false);
5380              });
5381            }, ({uid, name, elements}) => {
5382              if (!is$2(prev, uid)) {
5383                prev.each(uid => toggleActiveAttr(uid, false));
5384                fireCallbacks(name, uid, elements);
5385                data.previous.set(uid);
5386                toggleActiveAttr(uid, true);
5387              }
5388            });
5389            return {
5390              previous: data.previous,
5391              listeners: data.listeners
5392            };
5393          });
5394        });
5395      }, 30);
5396      editor.on('remove', () => {
5397        onNodeChange.cancel();
5398      });
5399      editor.on('NodeChange', () => {
5400        onNodeChange.throttle();
5401      });
5402      const addListener = (name, f) => {
5403        updateCallbacks(name, data => ({
5404          previous: data.previous,
5405          listeners: data.listeners.concat([f])
5406        }));
5407      };
5408      return { addListener };
5409    };
5410
5411    const setup$x = (editor, registry) => {
5412      const dataAnnotation$1 = dataAnnotation();
5413      const identifyParserNode = node => Optional.from(node.attr(dataAnnotation$1)).bind(registry.lookup);
5414      const removeDirectAnnotation = node => {
5415        var _a, _b;
5416        node.attr(dataAnnotationId(), null);
5417        node.attr(dataAnnotation(), null);
5418        node.attr(dataAnnotationActive(), null);
5419        const customAttrNames = Optional.from(node.attr(dataAnnotationAttributes())).map(names => names.split(',')).getOr([]);
5420        const customClasses = Optional.from(node.attr(dataAnnotationClasses())).map(names => names.split(',')).getOr([]);
5421        each$e(customAttrNames, name => node.attr(name, null));
5422        const classList = (_b = (_a = node.attr('class')) === null || _a === void 0 ? void 0 : _a.split(' ')) !== null && _b !== void 0 ? _b : [];
5423        const newClassList = difference(classList, [annotation()].concat(customClasses));
5424        node.attr('class', newClassList.length > 0 ? newClassList.join(' ') : null);
5425        node.attr(dataAnnotationClasses(), null);
5426        node.attr(dataAnnotationAttributes(), null);
5427      };
5428      editor.serializer.addTempAttr(dataAnnotationActive());
5429      editor.serializer.addAttributeFilter(dataAnnotation$1, nodes => {
5430        for (const node of nodes) {
5431          identifyParserNode(node).each(settings => {
5432            if (settings.persistent === false) {
5433              if (node.name === 'span') {
5434                node.unwrap();
5435              } else {
5436                removeDirectAnnotation(node);
5437              }
5438            }
5439          });
5440        }
5441      });
5442    };
5443
5444    const create$b = () => {
5445      const annotations = {};
5446      const register = (name, settings) => {
5447        annotations[name] = {
5448          name,
5449          settings
5450        };
5451      };
5452      const lookup = name => get$a(annotations, name).map(a => a.settings);
5453      const getNames = () => keys(annotations);
5454      return {
5455        register,
5456        lookup,
5457        getNames
5458      };
5459    };
5460
5461    const clamp$2 = (value, min, max) => Math.min(Math.max(value, min), max);
5462    const random = () => window.crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295;
5463
5464    let unique = 0;
5465    const generate$1 = prefix => {
5466      const date = new Date();
5467      const time = date.getTime();
5468      const random$1 = Math.floor(random() * 1000000000);
5469      unique++;
5470      return prefix + '_' + random$1 + unique + String(time);
5471    };
5472
5473    const add = (element, classes) => {
5474      each$e(classes, x => {
5475        add$2(element, x);
5476      });
5477    };
5478    const remove$3 = (element, classes) => {
5479      each$e(classes, x => {
5480        remove$6(element, x);
5481      });
5482    };
5483
5484    const clone$2 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
5485    const shallow$1 = original => clone$2(original, false);
5486    const deep$1 = original => clone$2(original, true);
5487    const shallowAs = (original, tag) => {
5488      const nu = SugarElement.fromTag(tag);
5489      const attributes = clone$4(original);
5490      setAll$1(nu, attributes);
5491      return nu;
5492    };
5493    const mutate = (original, tag) => {
5494      const nu = shallowAs(original, tag);
5495      after$4(original, nu);
5496      const children = children$1(original);
5497      append(nu, children);
5498      remove$4(original);
5499      return nu;
5500    };
5501
5502    const TextWalker = (startNode, rootNode, isBoundary = never) => {
5503      const walker = new DomTreeWalker(startNode, rootNode);
5504      const walk = direction => {
5505        let next;
5506        do {
5507          next = walker[direction]();
5508        } while (next && !isText$b(next) && !isBoundary(next));
5509        return Optional.from(next).filter(isText$b);
5510      };
5511      return {
5512        current: () => Optional.from(walker.current()).filter(isText$b),
5513        next: () => walk('next'),
5514        prev: () => walk('prev'),
5515        prev2: () => walk('prev2')
5516      };
5517    };
5518
5519    const TextSeeker = (dom, isBoundary) => {
5520      const isBlockBoundary = isBoundary ? isBoundary : node => dom.isBlock(node) || isBr$6(node) || isContentEditableFalse$b(node);
5521      const walk = (node, offset, walker, process) => {
5522        if (isText$b(node)) {
5523          const newOffset = process(node, offset, node.data);
5524          if (newOffset !== -1) {
5525            return Optional.some({
5526              container: node,
5527              offset: newOffset
5528            });
5529          }
5530        }
5531        return walker().bind(next => walk(next.container, next.offset, walker, process));
5532      };
5533      const backwards = (node, offset, process, root) => {
5534        const walker = TextWalker(node, root !== null && root !== void 0 ? root : dom.getRoot(), isBlockBoundary);
5535        return walk(node, offset, () => walker.prev().map(prev => ({
5536          container: prev,
5537          offset: prev.length
5538        })), process).getOrNull();
5539      };
5540      const forwards = (node, offset, process, root) => {
5541        const walker = TextWalker(node, root !== null && root !== void 0 ? root : dom.getRoot(), isBlockBoundary);
5542        return walk(node, offset, () => walker.next().map(next => ({
5543          container: next,
5544          offset: 0
5545        })), process).getOrNull();
5546      };
5547      return {
5548        backwards,
5549        forwards
5550      };
5551    };
5552
5553    const NodeValue = (is, name) => {
5554      const get = element => {
5555        if (!is(element)) {
5556          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
5557        }
5558        return getOption(element).getOr('');
5559      };
5560      const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
5561      const set = (element, value) => {
5562        if (!is(element)) {
5563          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
5564        }
5565        element.dom.nodeValue = value;
5566      };
5567      return {
5568        get,
5569        getOption,
5570        set
5571      };
5572    };
5573
5574    const api$1 = NodeValue(isText$c, 'text');
5575    const get$3 = element => api$1.get(element);
5576    const getOption = element => api$1.getOption(element);
5577    const set = (element, value) => api$1.set(element, value);
5578
5579    const tableCells = [
5580      'td',
5581      'th'
5582    ];
5583    const tableSections = [
5584      'thead',
5585      'tbody',
5586      'tfoot'
5587    ];
5588    const textBlocks = [
5589      'h1',
5590      'h2',
5591      'h3',
5592      'h4',
5593      'h5',
5594      'h6',
5595      'p',
5596      'div',
5597      'address',
5598      'pre',
5599      'form',
5600      'blockquote',
5601      'center',
5602      'dir',
5603      'fieldset',
5604      'header',
5605      'footer',
5606      'article',
5607      'section',
5608      'hgroup',
5609      'aside',
5610      'nav',
5611      'figure'
5612    ];
5613    const listItems$1 = [
5614      'li',
5615      'dd',
5616      'dt'
5617    ];
5618    const lists = [
5619      'ul',
5620      'ol',
5621      'dl'
5622    ];
5623    const wsElements = [
5624      'pre',
5625      'script',
5626      'textarea',
5627      'style'
5628    ];
5629    const lazyLookup = items => {
5630      let lookup;
5631      return node => {
5632        lookup = lookup ? lookup : mapToObject(items, always);
5633        return has$2(lookup, name(node));
5634      };
5635    };
5636    const isTable$1 = node => name(node) === 'table';
5637    const isBr$5 = node => isElement$7(node) && name(node) === 'br';
5638    const isTextBlock$2 = lazyLookup(textBlocks);
5639    const isList = lazyLookup(lists);
5640    const isListItem$1 = lazyLookup(listItems$1);
5641    const isTableSection = lazyLookup(tableSections);
5642    const isTableCell$2 = lazyLookup(tableCells);
5643    const isWsPreserveElement = lazyLookup(wsElements);
5644
5645    const getLastChildren$1 = elm => {
5646      const children = [];
5647      let rawNode = elm.dom;
5648      while (rawNode) {
5649        children.push(SugarElement.fromDom(rawNode));
5650        rawNode = rawNode.lastChild;
5651      }
5652      return children;
5653    };
5654    const removeTrailingBr = elm => {
5655      const allBrs = descendants(elm, 'br');
5656      const brs = filter$5(getLastChildren$1(elm).slice(-1), isBr$5);
5657      if (allBrs.length === brs.length) {
5658        each$e(brs, remove$4);
5659      }
5660    };
5661    const createPaddingBr = () => {
5662      const br = SugarElement.fromTag('br');
5663      set$4
vendor: 33,024 bytes, lines 5663-6498
5663(br, 'data-mce-bogus', '1');
5664      return br;
5665    };
5666    const fillWithPaddingBr = elm => {
5667      empty(elm);
5668      append$1(elm, createPaddingBr());
5669    };
5670    const trimBlockTrailingBr = (elm, schema) => {
5671      lastChild(elm).each(lastChild => {
5672        prevSibling(lastChild).each(lastChildPrevSibling => {
5673          if (schema.isBlock(name(elm)) && isBr$5(lastChild) && schema.isBlock(name(lastChildPrevSibling))) {
5674            remove$4(lastChild);
5675          }
5676        });
5677      });
5678    };
5679
5680    const ZWSP$1 = zeroWidth;
5681    const isZwsp = isZwsp$2;
5682    const trim$2 = removeZwsp;
5683    const insert$5 = editor => editor.insertContent(ZWSP$1, { preserve_zwsp: true });
5684
5685    const isElement$5 = isElement$6;
5686    const isText$9 = isText$b;
5687    const isCaretContainerBlock$1 = node => {
5688      if (isText$9(node)) {
5689        node = node.parentNode;
5690      }
5691      return isElement$5(node) && node.hasAttribute('data-mce-caret');
5692    };
5693    const isCaretContainerInline = node => isText$9(node) && isZwsp(node.data);
5694    const isCaretContainer$2 = node => isCaretContainerBlock$1(node) || isCaretContainerInline(node);
5695    const hasContent = node => node.firstChild !== node.lastChild || !isBr$6(node.firstChild);
5696    const insertInline$1 = (node, before) => {
5697      var _a;
5698      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
5699      const textNode = doc.createTextNode(ZWSP$1);
5700      const parentNode = node.parentNode;
5701      if (!before) {
5702        const sibling = node.nextSibling;
5703        if (isText$9(sibling)) {
5704          if (isCaretContainer$2(sibling)) {
5705            return sibling;
5706          }
5707          if (startsWithCaretContainer$1(sibling)) {
5708            sibling.splitText(1);
5709            return sibling;
5710          }
5711        }
5712        if (node.nextSibling) {
5713          parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(textNode, node.nextSibling);
5714        } else {
5715          parentNode === null || parentNode === void 0 ? void 0 : parentNode.appendChild(textNode);
5716        }
5717      } else {
5718        const sibling = node.previousSibling;
5719        if (isText$9(sibling)) {
5720          if (isCaretContainer$2(sibling)) {
5721            return sibling;
5722          }
5723          if (endsWithCaretContainer$1(sibling)) {
5724            return sibling.splitText(sibling.data.length - 1);
5725          }
5726        }
5727        parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(textNode, node);
5728      }
5729      return textNode;
5730    };
5731    const isBeforeInline = pos => {
5732      const container = pos.container();
5733      if (!isText$b(container)) {
5734        return false;
5735      }
5736      return container.data.charAt(pos.offset()) === ZWSP$1 || pos.isAtStart() && isCaretContainerInline(container.previousSibling);
5737    };
5738    const isAfterInline = pos => {
5739      const container = pos.container();
5740      if (!isText$b(container)) {
5741        return false;
5742      }
5743      return container.data.charAt(pos.offset() - 1) === ZWSP$1 || pos.isAtEnd() && isCaretContainerInline(container.nextSibling);
5744    };
5745    const insertBlock = (blockName, node, before) => {
5746      var _a;
5747      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
5748      const blockNode = doc.createElement(blockName);
5749      blockNode.setAttribute('data-mce-caret', before ? 'before' : 'after');
5750      blockNode.setAttribute('data-mce-bogus', 'all');
5751      blockNode.appendChild(createPaddingBr().dom);
5752      const parentNode = node.parentNode;
5753      if (!before) {
5754        if (node.nextSibling) {
5755          parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(blockNode, node.nextSibling);
5756        } else {
5757          parentNode === null || parentNode === void 0 ? void 0 : parentNode.appendChild(blockNode);
5758        }
5759      } else {
5760        parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(blockNode, node);
5761      }
5762      return blockNode;
5763    };
5764    const startsWithCaretContainer$1 = node => isText$9(node) && node.data[0] === ZWSP$1;
5765    const endsWithCaretContainer$1 = node => isText$9(node) && node.data[node.data.length - 1] === ZWSP$1;
5766    const trimBogusBr = elm => {
5767      var _a;
5768      const brs = elm.getElementsByTagName('br');
5769      const lastBr = brs[brs.length - 1];
5770      if (isBogus$1(lastBr)) {
5771        (_a = lastBr.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(lastBr);
5772      }
5773    };
5774    const showCaretContainerBlock = caretContainer => {
5775      if (caretContainer && caretContainer.hasAttribute('data-mce-caret')) {
5776        trimBogusBr(caretContainer);
5777        caretContainer.removeAttribute('data-mce-caret');
5778        caretContainer.removeAttribute('data-mce-bogus');
5779        caretContainer.removeAttribute('style');
5780        caretContainer.removeAttribute('data-mce-style');
5781        caretContainer.removeAttribute('_moz_abspos');
5782        return caretContainer;
5783      }
5784      return null;
5785    };
5786    const isRangeInCaretContainerBlock = range => isCaretContainerBlock$1(range.startContainer);
5787
5788    const round$2 = Math.round;
5789    const clone$1 = rect => {
5790      if (!rect) {
5791        return {
5792          left: 0,
5793          top: 0,
5794          bottom: 0,
5795          right: 0,
5796          width: 0,
5797          height: 0
5798        };
5799      }
5800      return {
5801        left: round$2(rect.left),
5802        top: round$2(rect.top),
5803        bottom: round$2(rect.bottom),
5804        right: round$2(rect.right),
5805        width: round$2(rect.width),
5806        height: round$2(rect.height)
5807      };
5808    };
5809    const collapse = (rect, toStart) => {
5810      rect = clone$1(rect);
5811      if (toStart) {
5812        rect.right = rect.left;
5813      } else {
5814        rect.left = rect.left + rect.width;
5815        rect.right = rect.left;
5816      }
5817      rect.width = 0;
5818      return rect;
5819    };
5820    const isEqual = (rect1, rect2) => rect1.left === rect2.left && rect1.top === rect2.top && rect1.bottom === rect2.bottom && rect1.right === rect2.right;
5821    const isValidOverflow = (overflowY, rect1, rect2) => overflowY >= 0 && overflowY <= Math.min(rect1.height, rect2.height) / 2;
5822    const isAbove$1 = (rect1, rect2) => {
5823      const halfHeight = Math.min(rect2.height / 2, rect1.height / 2);
5824      if (rect1.bottom - halfHeight < rect2.top) {
5825        return true;
5826      }
5827      if (rect1.top > rect2.bottom) {
5828        return false;
5829      }
5830      return isValidOverflow(rect2.top - rect1.bottom, rect1, rect2);
5831    };
5832    const isBelow$1 = (rect1, rect2) => {
5833      if (rect1.top > rect2.bottom) {
5834        return true;
5835      }
5836      if (rect1.bottom < rect2.top) {
5837        return false;
5838      }
5839      return isValidOverflow(rect2.bottom - rect1.top, rect1, rect2);
5840    };
5841    const containsXY = (rect, clientX, clientY) => clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
5842    const boundingClientRectFromRects = rects => {
5843      return foldl(rects, (acc, rect) => {
5844        return acc.fold(() => Optional.some(rect), prevRect => {
5845          const left = Math.min(rect.left, prevRect.left);
5846          const top = Math.min(rect.top, prevRect.top);
5847          const right = Math.max(rect.right, prevRect.right);
5848          const bottom = Math.max(rect.bottom, prevRect.bottom);
5849          return Optional.some({
5850            top,
5851            right,
5852            bottom,
5853            left,
5854            width: right - left,
5855            height: bottom - top
5856          });
5857        });
5858      }, Optional.none());
5859    };
5860    const distanceToRectEdgeFromXY = (rect, x, y) => {
5861      const cx = Math.max(Math.min(x, rect.left + rect.width), rect.left);
5862      const cy = Math.max(Math.min(y, rect.top + rect.height), rect.top);
5863      return Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
5864    };
5865    const overlapY = (r1, r2) => Math.max(0, Math.min(r1.bottom, r2.bottom) - Math.max(r1.top, r2.top));
5866
5867    const getSelectedNode = range => {
5868      const startContainer = range.startContainer, startOffset = range.startOffset;
5869      if (startContainer === range.endContainer && startContainer.hasChildNodes() && range.endOffset === startOffset + 1) {
5870        return startContainer.childNodes[startOffset];
5871      }
5872      return null;
5873    };
5874    const getNode$1 = (container, offset) => {
5875      if (isElement$6(container) && container.hasChildNodes()) {
5876        const childNodes = container.childNodes;
5877        const safeOffset = clamp$2(offset, 0, childNodes.length - 1);
5878        return childNodes[safeOffset];
5879      } else {
5880        return container;
5881      }
5882    };
5883    const getNodeUnsafe = (container, offset) => {
5884      if (offset < 0 && isElement$6(container) && container.hasChildNodes()) {
5885        return undefined;
5886      } else {
5887        return getNode$1(container, offset);
5888      }
5889    };
5890
5891    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]');
5892    const isExtendingChar = ch => isString(ch) && ch.charCodeAt(0) >= 768 && extendingChars.test(ch);
5893
5894    const or = (...args) => {
5895      return x => {
5896        for (let i = 0; i < args.length; i++) {
5897          if (args[i](x)) {
5898            return true;
5899          }
5900        }
5901        return false;
5902      };
5903    };
5904    const and = (...args) => {
5905      return x => {
5906        for (let i = 0; i < args.length; i++) {
5907          if (!args[i](x)) {
5908            return false;
5909          }
5910        }
5911        return true;
5912      };
5913    };
5914
5915    const isContentEditableTrue$2 = isContentEditableTrue$3;
5916    const isContentEditableFalse$a = isContentEditableFalse$b;
5917    const isBr$4 = isBr$6;
5918    const isText$8 = isText$b;
5919    const isInvalidTextElement = matchNodeNames([
5920      'script',
5921      'style',
5922      'textarea'
5923    ]);
5924    const isAtomicInline = matchNodeNames([
5925      'img',
5926      'input',
5927      'textarea',
5928      'hr',
5929      'iframe',
5930      'video',
5931      'audio',
5932      'object',
5933      'embed'
5934    ]);
5935    const isTable = matchNodeNames(['table']);
5936    const isCaretContainer$1 = isCaretContainer$2;
5937    const isCaretCandidate$3 = node => {
5938      if (isCaretContainer$1(node)) {
5939        return false;
5940      }
5941      if (isText$8(node)) {
5942        return !isInvalidTextElement(node.parentNode);
5943      }
5944      return isAtomicInline(node) || isBr$4(node) || isTable(node) || isNonUiContentEditableFalse(node);
5945    };
5946    const isUnselectable = node => isElement$6(node) && node.getAttribute('unselectable') === 'true';
5947    const isNonUiContentEditableFalse = node => !isUnselectable(node) && isContentEditableFalse$a(node);
5948    const isInEditable = (node, root) => {
5949      for (let tempNode = node.parentNode; tempNode && tempNode !== root; tempNode = tempNode.parentNode) {
5950        if (isNonUiContentEditableFalse(tempNode)) {
5951          return false;
5952        }
5953        if (isContentEditableTrue$2(tempNode)) {
5954          return true;
5955        }
5956      }
5957      return true;
5958    };
5959    const isAtomicContentEditableFalse = node => {
5960      if (!isNonUiContentEditableFalse(node)) {
5961        return false;
5962      }
5963      return !foldl(from(node.getElementsByTagName('*')), (result, elm) => {
5964        return result || isContentEditableTrue$2(elm);
5965      }, false);
5966    };
5967    const isAtomic$1 = node => isAtomicInline(node) || isAtomicContentEditableFalse(node);
5968    const isEditableCaretCandidate$1 = (node, root) => isCaretCandidate$3(node) && isInEditable(node, root);
5969
5970    const isElement$4 = isElement$6;
5971    const isCaretCandidate$2 = isCaretCandidate$3;
5972    const isBlock$2 = matchStyleValues('display', 'block table');
5973    const isFloated = matchStyleValues('float', 'left right');
5974    const isValidElementCaretCandidate = and(isElement$4, isCaretCandidate$2, not(isFloated));
5975    const isNotPre = not(matchStyleValues('white-space', 'pre pre-line pre-wrap'));
5976    const isText$7 = isText$b;
5977    const isBr$3 = isBr$6;
5978    const nodeIndex$1 = DOMUtils.nodeIndex;
5979    const resolveIndex$1 = getNodeUnsafe;
5980    const createRange$1 = doc => doc ? doc.createRange() : DOMUtils.DOM.createRng();
5981    const isWhiteSpace$1 = chr => isString(chr) && /[\r\n\t ]/.test(chr);
5982    const isRange = rng => !!rng.setStart && !!rng.setEnd;
5983    const isHiddenWhiteSpaceRange = range => {
5984      const container = range.startContainer;
5985      const offset = range.startOffset;
5986      if (isWhiteSpace$1(range.toString()) && isNotPre(container.parentNode) && isText$b(container)) {
5987        const text = container.data;
5988        if (isWhiteSpace$1(text[offset - 1]) || isWhiteSpace$1(text[offset + 1])) {
5989          return true;
5990        }
5991      }
5992      return false;
5993    };
5994    const getBrClientRect = brNode => {
5995      const doc = brNode.ownerDocument;
5996      const rng = createRange$1(doc);
5997      const nbsp$1 = doc.createTextNode(nbsp);
5998      const parentNode = brNode.parentNode;
5999      parentNode.insertBefore(nbsp$1, brNode);
6000      rng.setStart(nbsp$1, 0);
6001      rng.setEnd(nbsp$1, 1);
6002      const clientRect = clone$1(rng.getBoundingClientRect());
6003      parentNode.removeChild(nbsp$1);
6004      return clientRect;
6005    };
6006    const getBoundingClientRectWebKitText = rng => {
6007      const sc = rng.startContainer;
6008      const ec = rng.endContainer;
6009      const so = rng.startOffset;
6010      const eo = rng.endOffset;
6011      if (sc === ec && isText$b(ec) && so === 0 && eo === 1) {
6012        const newRng = rng.cloneRange();
6013        newRng.setEndAfter(ec);
6014        return getBoundingClientRect$1(newRng);
6015      } else {
6016        return null;
6017      }
6018    };
6019    const isZeroRect = r => r.left === 0 && r.right === 0 && r.top === 0 && r.bottom === 0;
6020    const getBoundingClientRect$1 = item => {
6021      var _a;
6022      let clientRect;
6023      const clientRects = item.getClientRects();
6024      if (clientRects.length > 0) {
6025        clientRect = clone$1(clientRects[0]);
6026      } else {
6027        clientRect = clone$1(item.getBoundingClientRect());
6028      }
6029      if (!isRange(item) && isBr$3(item) && isZeroRect(clientRect)) {
6030        return getBrClientRect(item);
6031      }
6032      if (isZeroRect(clientRect) && isRange(item)) {
6033        return (_a = getBoundingClientRectWebKitText(item)) !== null && _a !== void 0 ? _a : clientRect;
6034      }
6035      return clientRect;
6036    };
6037    const collapseAndInflateWidth = (clientRect, toStart) => {
6038      const newClientRect = collapse(clientRect, toStart);
6039      newClientRect.width = 1;
6040      newClientRect.right = newClientRect.left + 1;
6041      return newClientRect;
6042    };
6043    const getCaretPositionClientRects = caretPosition => {
6044      const clientRects = [];
6045      const addUniqueAndValidRect = clientRect => {
6046        if (clientRect.height === 0) {
6047          return;
6048        }
6049        if (clientRects.length > 0) {
6050          if (isEqual(clientRect, clientRects[clientRects.length - 1])) {
6051            return;
6052          }
6053        }
6054        clientRects.push(clientRect);
6055      };
6056      const addCharacterOffset = (container, offset) => {
6057        const range = createRange$1(container.ownerDocument);
6058        if (offset < container.data.length) {
6059          if (isExtendingChar(container.data[offset])) {
6060            return;
6061          }
6062          if (isExtendingChar(container.data[offset - 1])) {
6063            range.setStart(container, offset);
6064            range.setEnd(container, offset + 1);
6065            if (!isHiddenWhiteSpaceRange(range)) {
6066              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), false));
6067              return;
6068            }
6069          }
6070        }
6071        if (offset > 0) {
6072          range.setStart(container, offset - 1);
6073          range.setEnd(container, offset);
6074          if (!isHiddenWhiteSpaceRange(range)) {
6075            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), false));
6076          }
6077        }
6078        if (offset < container.data.length) {
6079          range.setStart(container, offset);
6080          range.setEnd(container, offset + 1);
6081          if (!isHiddenWhiteSpaceRange(range)) {
6082            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), true));
6083          }
6084        }
6085      };
6086      const container = caretPosition.container();
6087      const offset = caretPosition.offset();
6088      if (isText$7(container)) {
6089        addCharacterOffset(container, offset);
6090        return clientRects;
6091      }
6092      if (isElement$4(container)) {
6093        if (caretPosition.isAtEnd()) {
6094          const node = resolveIndex$1(container, offset);
6095          if (isText$7(node)) {
6096            addCharacterOffset(node, node.data.length);
6097          }
6098          if (isValidElementCaretCandidate(node) && !isBr$3(node)) {
6099            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), false));
6100          }
6101        } else {
6102          const node = resolveIndex$1(container, offset);
6103          if (isText$7(node)) {
6104            addCharacterOffset(node, 0);
6105          }
6106          if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) {
6107            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), false));
6108            return clientRects;
6109          }
6110          const beforeNode = resolveIndex$1(caretPosition.container(), caretPosition.offset() - 1);
6111          if (isValidElementCaretCandidate(beforeNode) && !isBr$3(beforeNode)) {
6112            if (isBlock$2(beforeNode) || isBlock$2(node) || !isValidElementCaretCandidate(node)) {
6113              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(beforeNode), false));
6114            }
6115          }
6116          if (isValidElementCaretCandidate(node)) {
6117            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), true));
6118          }
6119        }
6120      }
6121      return clientRects;
6122    };
6123    const CaretPosition = (container, offset, clientRects) => {
6124      const isAtStart = () => {
6125        if (isText$7(container)) {
6126          return offset === 0;
6127        }
6128        return offset === 0;
6129      };
6130      const isAtEnd = () => {
6131        if (isText$7(container)) {
6132          return offset >= container.data.length;
6133        }
6134        return offset >= container.childNodes.length;
6135      };
6136      const toRange = () => {
6137        const range = createRange$1(container.ownerDocument);
6138        range.setStart(container, offset);
6139        range.setEnd(container, offset);
6140        return range;
6141      };
6142      const getClientRects = () => {
6143        if (!clientRects) {
6144          clientRects = getCaretPositionClientRects(CaretPosition(container, offset));
6145        }
6146        return clientRects;
6147      };
6148      const isVisible = () => getClientRects().length > 0;
6149      const isEqual = caretPosition => caretPosition && container === caretPosition.container() && offset === caretPosition.offset();
6150      const getNode = before => resolveIndex$1(container, before ? offset - 1 : offset);
6151      return {
6152        container: constant(container),
6153        offset: constant(offset),
6154        toRange,
6155        getClientRects,
6156        isVisible,
6157        isAtStart,
6158        isAtEnd,
6159        isEqual,
6160        getNode
6161      };
6162    };
6163    CaretPosition.fromRangeStart = range => CaretPosition(range.startContainer, range.startOffset);
6164    CaretPosition.fromRangeEnd = range => CaretPosition(range.endContainer, range.endOffset);
6165    CaretPosition.after = node => CaretPosition(node.parentNode, nodeIndex$1(node) + 1);
6166    CaretPosition.before = node => CaretPosition(node.parentNode, nodeIndex$1(node));
6167    CaretPosition.isAbove = (pos1, pos2) => lift2(head(pos2.getClientRects()), last$2(pos1.getClientRects()), isAbove$1).getOr(false);
6168    CaretPosition.isBelow = (pos1, pos2) => lift2(last$2(pos2.getClientRects()), head(pos1.getClientRects()), isBelow$1).getOr(false);
6169    CaretPosition.isAtStart = pos => pos ? pos.isAtStart() : false;
6170    CaretPosition.isAtEnd = pos => pos ? pos.isAtEnd() : false;
6171    CaretPosition.isTextPosition = pos => pos ? isText$b(pos.container()) : false;
6172    CaretPosition.isElementPosition = pos => !CaretPosition.isTextPosition(pos);
6173
6174    const trimEmptyTextNode$1 = (dom, node) => {
6175      if (isText$b(node) && node.data.length === 0) {
6176        dom.remove(node);
6177      }
6178    };
6179    const insertNode = (dom, rng, node) => {
6180      rng.insertNode(node);
6181      trimEmptyTextNode$1(dom, node.previousSibling);
6182      trimEmptyTextNode$1(dom, node.nextSibling);
6183    };
6184    const insertFragment = (dom, rng, frag) => {
6185      const firstChild = Optional.from(frag.firstChild);
6186      const lastChild = Optional.from(frag.lastChild);
6187      rng.insertNode(frag);
6188      firstChild.each(child => trimEmptyTextNode$1(dom, child.previousSibling));
6189      lastChild.each(child => trimEmptyTextNode$1(dom, child.nextSibling));
6190    };
6191    const rangeInsertNode = (dom, rng, node) => {
6192      if (isDocumentFragment(node)) {
6193        insertFragment(dom, rng, node);
6194      } else {
6195        insertNode(dom, rng, node);
6196      }
6197    };
6198
6199    const isText$6 = isText$b;
6200    const isBogus = isBogus$1;
6201    const nodeIndex = DOMUtils.nodeIndex;
6202    const normalizedParent = node => {
6203      const parentNode = node.parentNode;
6204      if (isBogus(parentNode)) {
6205        return normalizedParent(parentNode);
6206      }
6207      return parentNode;
6208    };
6209    const getChildNodes = node => {
6210      if (!node) {
6211        return [];
6212      }
6213      return reduce(node.childNodes, (result, node) => {
6214        if (isBogus(node) && node.nodeName !== 'BR') {
6215          result = result.concat(getChildNodes(node));
6216        } else {
6217          result.push(node);
6218        }
6219        return result;
6220      }, []);
6221    };
6222    const normalizedTextOffset = (node, offset) => {
6223      let tempNode = node;
6224      while (tempNode = tempNode.previousSibling) {
6225        if (!isText$6(tempNode)) {
6226          break;
6227        }
6228        offset += tempNode.data.length;
6229      }
6230      return offset;
6231    };
6232    const equal = a => b => a === b;
6233    const normalizedNodeIndex = node => {
6234      let nodes, index;
6235      nodes = getChildNodes(normalizedParent(node));
6236      index = findIndex$1(nodes, equal(node), node);
6237      nodes = nodes.slice(0, index + 1);
6238      const numTextFragments = reduce(nodes, (result, node, i) => {
6239        if (isText$6(node) && isText$6(nodes[i - 1])) {
6240          result++;
6241        }
6242        return result;
6243      }, 0);
6244      nodes = filter$3(nodes, matchNodeNames([node.nodeName]));
6245      index = findIndex$1(nodes, equal(node), node);
6246      return index - numTextFragments;
6247    };
6248    const createPathItem = node => {
6249      const name = isText$6(node) ? 'text()' : node.nodeName.toLowerCase();
6250      return name + '[' + normalizedNodeIndex(node) + ']';
6251    };
6252    const parentsUntil$1 = (root, node, predicate) => {
6253      const parents = [];
6254      for (let tempNode = node.parentNode; tempNode && tempNode !== root; tempNode = tempNode.parentNode) {
6255        if (predicate && predicate(tempNode)) {
6256          break;
6257        }
6258        parents.push(tempNode);
6259      }
6260      return parents;
6261    };
6262    const create$a = (root, caretPosition) => {
6263      let path = [];
6264      let container = caretPosition.container();
6265      let offset = caretPosition.offset();
6266      let outputOffset;
6267      if (isText$6(container)) {
6268        outputOffset = normalizedTextOffset(container, offset);
6269      } else {
6270        const childNodes = container.childNodes;
6271        if (offset >= childNodes.length) {
6272          outputOffset = 'after';
6273          offset = childNodes.length - 1;
6274        } else {
6275          outputOffset = 'before';
6276        }
6277        container = childNodes[offset];
6278      }
6279      path.push(createPathItem(container));
6280      let parents = parentsUntil$1(root, container);
6281      parents = filter$3(parents, not(isBogus$1));
6282      path = path.concat(map$1(parents, node => {
6283        return createPathItem(node);
6284      }));
6285      return path.reverse().join('/') + ',' + outputOffset;
6286    };
6287    const resolvePathItem = (node, name, index) => {
6288      let nodes = getChildNodes(node);
6289      nodes = filter$3(nodes, (node, index) => {
6290        return !isText$6(node) || !isText$6(nodes[index - 1]);
6291      });
6292      nodes = filter$3(nodes, matchNodeNames([name]));
6293      return nodes[index];
6294    };
6295    const findTextPosition = (container, offset) => {
6296      let node = container;
6297      let targetOffset = 0;
6298      while (isText$6(node)) {
6299        const dataLen = node.data.length;
6300        if (offset >= targetOffset && offset <= targetOffset + dataLen) {
6301          container = node;
6302          offset = offset - targetOffset;
6303          break;
6304        }
6305        if (!isText$6(node.nextSibling)) {
6306          container = node;
6307          offset = dataLen;
6308          break;
6309        }
6310        targetOffset += dataLen;
6311        node = node.nextSibling;
6312      }
6313      if (isText$6(container) && offset > container.data.length) {
6314        offset = container.data.length;
6315      }
6316      return CaretPosition(container, offset);
6317    };
6318    const resolve$1 = (root, path) => {
6319      if (!path) {
6320        return null;
6321      }
6322      const parts = path.split(',');
6323      const paths = parts[0].split('/');
6324      const offset = parts.length > 1 ? parts[1] : 'before';
6325      const container = reduce(paths, (result, value) => {
6326        const match = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value);
6327        if (!match) {
6328          return null;
6329        }
6330        if (match[1] === 'text()') {
6331          match[1] = '#text';
6332        }
6333        return resolvePathItem(result, match[1], parseInt(match[2], 10));
6334      }, root);
6335      if (!container) {
6336        return null;
6337      }
6338      if (!isText$6(container) && container.parentNode) {
6339        let nodeOffset;
6340        if (offset === 'after') {
6341          nodeOffset = nodeIndex(container) + 1;
6342        } else {
6343          nodeOffset = nodeIndex(container);
6344        }
6345        return CaretPosition(container.parentNode, nodeOffset);
6346      }
6347      return findTextPosition(container, parseInt(offset, 10));
6348    };
6349
6350    const isContentEditableFalse$9 = isContentEditableFalse$b;
6351    const getNormalizedTextOffset$1 = (trim, container, offset) => {
6352      let trimmedOffset = trim(container.data.slice(0, offset)).length;
6353      for (let node = container.previousSibling; node && isText$b(node); node = node.previousSibling) {
6354        trimmedOffset += trim(node.data).length;
6355      }
6356      return trimmedOffset;
6357    };
6358    const getPoint = (dom, trim, normalized, rng, start) => {
6359      const container = start ? rng.startContainer : rng.endContainer;
6360      let offset = start ? rng.startOffset : rng.endOffset;
6361      const point = [];
6362      const root = dom.getRoot();
6363      if (isText$b(container)) {
6364        point.push(normalized ? getNormalizedTextOffset$1(trim, container, offset) : offset);
6365      } else {
6366        let after = 0;
6367        const childNodes = container.childNodes;
6368        if (offset >= childNodes.length && childNodes.length) {
6369          after = 1;
6370          offset = Math.max(0, childNodes.length - 1);
6371        }
6372        point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
6373      }
6374      for (let node = container; node && node !== root; node = node.parentNode) {
6375        point.push(dom.nodeIndex(node, normalized));
6376      }
6377      return point;
6378    };
6379    const getLocation = (trim, selection, normalized, rng) => {
6380      const dom = selection.dom;
6381      const start = getPoint(dom, trim, normalized, rng, true);
6382      const forward = selection.isForward();
6383      const fakeCaret = isRangeInCaretContainerBlock(rng) ? { isFakeCaret: true } : {};
6384      if (!selection.isCollapsed()) {
6385        const end = getPoint(dom, trim, normalized, rng, false);
6386        return {
6387          start,
6388          end,
6389          forward,
6390          ...fakeCaret
6391        };
6392      } else {
6393        return {
6394          start,
6395          forward,
6396          ...fakeCaret
6397        };
6398      }
6399    };
6400    const findIndex = (dom, name, element) => {
6401      let count = 0;
6402      Tools.each(dom.select(name), node => {
6403        if (node.getAttribute('data-mce-bogus') === 'all') {
6404          return;
6405        } else if (node === element) {
6406          return false;
6407        } else {
6408          count++;
6409          return;
6410        }
6411      });
6412      return count;
6413    };
6414    const moveEndPoint$1 = (rng, start) => {
6415      let container = start ? rng.startContainer : rng.endContainer;
6416      let offset = start ? rng.startOffset : rng.endOffset;
6417      if (isElement$6(container) && container.nodeName === 'TR') {
6418        const childNodes = container.childNodes;
6419        container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
6420        if (container) {
6421          offset = start ? 0 : container.childNodes.length;
6422          if (start) {
6423            rng.setStart(container, offset);
6424          } else {
6425            rng.setEnd(container, offset);
6426          }
6427        }
6428      }
6429    };
6430    const normalizeTableCellSelection = rng => {
6431      moveEndPoint$1(rng, true);
6432      moveEndPoint$1(rng, false);
6433      return rng;
6434    };
6435    const findSibling = (node, offset) => {
6436      if (isElement$6(node)) {
6437        node = getNode$1(node, offset);
6438        if (isContentEditableFalse$9(node)) {
6439          return node;
6440        }
6441      }
6442      if (isCaretContainer$2(node)) {
6443        if (isText$b(node) && isCaretContainerBlock$1(node)) {
6444          node = node.parentNode;
6445        }
6446        let sibling = node.previousSibling;
6447        if (isContentEditableFalse$9(sibling)) {
6448          return sibling;
6449        }
6450        sibling = node.nextSibling;
6451        if (isContentEditableFalse$9(sibling)) {
6452          return sibling;
6453        }
6454      }
6455      return undefined;
6456    };
6457    const findAdjacentContentEditableFalseElm = rng => {
6458      return findSibling(rng.startContainer, rng.startOffset) || findSibling(rng.endContainer, rng.endOffset);
6459    };
6460    const getOffsetBookmark = (trim, normalized, selection) => {
6461      const element = selection.getNode();
6462      const rng = selection.getRng();
6463      if (element.nodeName === 'IMG' || isContentEditableFalse$9(element)) {
6464        const name = element.nodeName;
6465        return {
6466          name,
6467          index: findIndex(selection.dom, name, element)
6468        };
6469      }
6470      const sibling = findAdjacentContentEditableFalseElm(rng);
6471      if (sibling) {
6472        const name = sibling.tagName;
6473        return {
6474          name,
6475          index: findIndex(selection.dom, name, sibling)
6476        };
6477      }
6478      return getLocation(trim, selection, normalized, rng);
6479    };
6480    const getCaretBookmark = selection => {
6481      const rng = selection.getRng();
6482      return {
6483        start: create$a(selection.dom.getRoot(), CaretPosition.fromRangeStart(rng)),
6484        end: create$a(selection.dom.getRoot(), CaretPosition.fromRangeEnd(rng)),
6485        forward: selection.isForward()
6486      };
6487    };
6488    const getRangeBookmark = selection => {
6489      return {
6490        rng: selection.getRng(),
6491        forward: selection.isForward()
6492      };
6493    };
6494    const createBookmarkSpan = (dom, id, filled) => {
6495      const args = {
6496        'data-mce-type': 'bookmark',
6497        id,
6498        
vendor: 20,636 bytes, lines 6498-7142
6498'style': 'overflow:hidden;line-height:0px'
6499      };
6500      return filled ? dom.create('span', args, '&#xFEFF;') : dom.create('span', args);
6501    };
6502    const getPersistentBookmark = (selection, filled) => {
6503      const dom = selection.dom;
6504      let rng = selection.getRng();
6505      const id = dom.uniqueId();
6506      const collapsed = selection.isCollapsed();
6507      const element = selection.getNode();
6508      const name = element.nodeName;
6509      const forward = selection.isForward();
6510      if (name === 'IMG') {
6511        return {
6512          name,
6513          index: findIndex(dom, name, element)
6514        };
6515      }
6516      const rng2 = normalizeTableCellSelection(rng.cloneRange());
6517      if (!collapsed) {
6518        rng2.collapse(false);
6519        const endBookmarkNode = createBookmarkSpan(dom, id + '_end', filled);
6520        rangeInsertNode(dom, rng2, endBookmarkNode);
6521      }
6522      rng = normalizeTableCellSelection(rng);
6523      rng.collapse(true);
6524      const startBookmarkNode = createBookmarkSpan(dom, id + '_start', filled);
6525      rangeInsertNode(dom, rng, startBookmarkNode);
6526      selection.moveToBookmark({
6527        id,
6528        keep: true,
6529        forward
6530      });
6531      return {
6532        id,
6533        forward
6534      };
6535    };
6536    const getBookmark$3 = (selection, type, normalized = false) => {
6537      if (type === 2) {
6538        return getOffsetBookmark(trim$2, normalized, selection);
6539      } else if (type === 3) {
6540        return getCaretBookmark(selection);
6541      } else if (type) {
6542        return getRangeBookmark(selection);
6543      } else {
6544        return getPersistentBookmark(selection, false);
6545      }
6546    };
6547    const getUndoBookmark = curry(getOffsetBookmark, identity, true);
6548
6549    const value$1 = value => {
6550      const applyHelper = fn => fn(value);
6551      const constHelper = constant(value);
6552      const outputHelper = () => output;
6553      const output = {
6554        tag: true,
6555        inner: value,
6556        fold: (_onError, onValue) => onValue(value),
6557        isValue: always,
6558        isError: never,
6559        map: mapper => Result.value(mapper(value)),
6560        mapError: outputHelper,
6561        bind: applyHelper,
6562        exists: applyHelper,
6563        forall: applyHelper,
6564        getOr: constHelper,
6565        or: outputHelper,
6566        getOrThunk: constHelper,
6567        orThunk: outputHelper,
6568        getOrDie: constHelper,
6569        each: fn => {
6570          fn(value);
6571        },
6572        toOptional: () => Optional.some(value)
6573      };
6574      return output;
6575    };
6576    const error = error => {
6577      const outputHelper = () => output;
6578      const output = {
6579        tag: false,
6580        inner: error,
6581        fold: (onError, _onValue) => onError(error),
6582        isValue: never,
6583        isError: always,
6584        map: outputHelper,
6585        mapError: mapper => Result.error(mapper(error)),
6586        bind: outputHelper,
6587        exists: never,
6588        forall: always,
6589        getOr: identity,
6590        or: identity,
6591        getOrThunk: apply$1,
6592        orThunk: apply$1,
6593        getOrDie: die(String(error)),
6594        each: noop,
6595        toOptional: Optional.none
6596      };
6597      return output;
6598    };
6599    const fromOption = (optional, err) => optional.fold(() => error(err), value$1);
6600    const Result = {
6601      value: value$1,
6602      error,
6603      fromOption
6604    };
6605
6606    const generate = cases => {
6607      if (!isArray$1(cases)) {
6608        throw new Error('cases must be an array');
6609      }
6610      if (cases.length === 0) {
6611        throw new Error('there must be at least one case');
6612      }
6613      const constructors = [];
6614      const adt = {};
6615      each$e(cases, (acase, count) => {
6616        const keys$1 = keys(acase);
6617        if (keys$1.length !== 1) {
6618          throw new Error('one and only one name per case');
6619        }
6620        const key = keys$1[0];
6621        const value = acase[key];
6622        if (adt[key] !== undefined) {
6623          throw new Error('duplicate key detected:' + key);
6624        } else if (key === 'cata') {
6625          throw new Error('cannot have a case named cata (sorry)');
6626        } else if (!isArray$1(value)) {
6627          throw new Error('case arguments must be an array');
6628        }
6629        constructors.push(key);
6630        adt[key] = (...args) => {
6631          const argLength = args.length;
6632          if (argLength !== value.length) {
6633            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
6634          }
6635          const match = branches => {
6636            const branchKeys = keys(branches);
6637            if (constructors.length !== branchKeys.length) {
6638              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
6639            }
6640            const allReqd = forall(constructors, reqKey => {
6641              return contains$2(branchKeys, reqKey);
6642            });
6643            if (!allReqd) {
6644              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
6645            }
6646            return branches[key].apply(null, args);
6647          };
6648          return {
6649            fold: (...foldArgs) => {
6650              if (foldArgs.length !== cases.length) {
6651                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
6652              }
6653              const target = foldArgs[count];
6654              return target.apply(null, args);
6655            },
6656            match,
6657            log: label => {
6658              console.log(label, {
6659                constructors,
6660                constructor: key,
6661                params: args
6662              });
6663            }
6664          };
6665        };
6666      });
6667      return adt;
6668    };
6669    const Adt = { generate };
6670
6671    Adt.generate([
6672      {
6673        bothErrors: [
6674          'error1',
6675          'error2'
6676        ]
6677      },
6678      {
6679        firstError: [
6680          'error1',
6681          'value2'
6682        ]
6683      },
6684      {
6685        secondError: [
6686          'value1',
6687          'error2'
6688        ]
6689      },
6690      {
6691        bothValues: [
6692          'value1',
6693          'value2'
6694        ]
6695      }
6696    ]);
6697    const partition$1 = results => {
6698      const errors = [];
6699      const values = [];
6700      each$e(results, result => {
6701        result.fold(err => {
6702          errors.push(err);
6703        }, value => {
6704          values.push(value);
6705        });
6706      });
6707      return {
6708        errors,
6709        values
6710      };
6711    };
6712
6713    const isInlinePattern = pattern => pattern.type === 'inline-command' || pattern.type === 'inline-format';
6714    const isBlockPattern = pattern => pattern.type === 'block-command' || pattern.type === 'block-format';
6715    const hasBlockTrigger = (pattern, trigger) => (pattern.type === 'block-command' || pattern.type === 'block-format') && pattern.trigger === trigger;
6716    const normalizePattern = pattern => {
6717      var _a;
6718      const err = message => Result.error({
6719        message,
6720        pattern
6721      });
6722      const formatOrCmd = (name, onFormat, onCommand) => {
6723        if (pattern.format !== undefined) {
6724          let formats;
6725          if (isArray$1(pattern.format)) {
6726            if (!forall(pattern.format, isString)) {
6727              return err(name + ' pattern has non-string items in the `format` array');
6728            }
6729            formats = pattern.format;
6730          } else if (isString(pattern.format)) {
6731            formats = [pattern.format];
6732          } else {
6733            return err(name + ' pattern has non-string `format` parameter');
6734          }
6735          return Result.value(onFormat(formats));
6736        } else if (pattern.cmd !== undefined) {
6737          if (!isString(pattern.cmd)) {
6738            return err(name + ' pattern has non-string `cmd` parameter');
6739          }
6740          return Result.value(onCommand(pattern.cmd, pattern.value));
6741        } else {
6742          return err(name + ' pattern is missing both `format` and `cmd` parameters');
6743        }
6744      };
6745      if (!isObject(pattern)) {
6746        return err('Raw pattern is not an object');
6747      }
6748      if (!isString(pattern.start)) {
6749        return err('Raw pattern is missing `start` parameter');
6750      }
6751      if (pattern.end !== undefined) {
6752        if (!isString(pattern.end)) {
6753          return err('Inline pattern has non-string `end` parameter');
6754        }
6755        if (pattern.start.length === 0 && pattern.end.length === 0) {
6756          return err('Inline pattern has empty `start` and `end` parameters');
6757        }
6758        let start = pattern.start;
6759        let end = pattern.end;
6760        if (end.length === 0) {
6761          end = start;
6762          start = '';
6763        }
6764        return formatOrCmd('Inline', format => ({
6765          type: 'inline-format',
6766          start,
6767          end,
6768          format
6769        }), (cmd, value) => ({
6770          type: 'inline-command',
6771          start,
6772          end,
6773          cmd,
6774          value
6775        }));
6776      } else if (pattern.replacement !== undefined) {
6777        if (!isString(pattern.replacement)) {
6778          return err('Replacement pattern has non-string `replacement` parameter');
6779        }
6780        if (pattern.start.length === 0) {
6781          return err('Replacement pattern has empty `start` parameter');
6782        }
6783        return Result.value({
6784          type: 'inline-command',
6785          start: '',
6786          end: pattern.start,
6787          cmd: 'mceInsertContent',
6788          value: pattern.replacement
6789        });
6790      } else {
6791        const trigger = (_a = pattern.trigger) !== null && _a !== void 0 ? _a : 'space';
6792        if (pattern.start.length === 0) {
6793          return err('Block pattern has empty `start` parameter');
6794        }
6795        return formatOrCmd('Block', formats => ({
6796          type: 'block-format',
6797          start: pattern.start,
6798          format: formats[0],
6799          trigger
6800        }), (command, commandValue) => ({
6801          type: 'block-command',
6802          start: pattern.start,
6803          cmd: command,
6804          value: commandValue,
6805          trigger
6806        }));
6807      }
6808    };
6809    const getBlockPatterns = patterns => filter$5(patterns, isBlockPattern);
6810    const getInlinePatterns = patterns => filter$5(patterns, isInlinePattern);
6811    const createPatternSet = (patterns, dynamicPatternsLookup) => ({
6812      inlinePatterns: getInlinePatterns(patterns),
6813      blockPatterns: getBlockPatterns(patterns),
6814      dynamicPatternsLookup
6815    });
6816    const filterByTrigger = (patterns, trigger) => {
6817      return {
6818        ...patterns,
6819        blockPatterns: filter$5(patterns.blockPatterns, pattern => hasBlockTrigger(pattern, trigger))
6820      };
6821    };
6822    const fromRawPatterns = patterns => {
6823      const normalized = partition$1(map$3(patterns, normalizePattern));
6824      each$e(normalized.errors, err => console.error(err.message, err.pattern));
6825      return normalized.values;
6826    };
6827    const fromRawPatternsLookup = lookupFn => {
6828      return ctx => {
6829        const rawPatterns = lookupFn(ctx);
6830        return fromRawPatterns(rawPatterns);
6831      };
6832    };
6833
6834    const firePreProcess = (editor, args) => editor.dispatch('PreProcess', args);
6835    const firePostProcess = (editor, args) => editor.dispatch('PostProcess', args);
6836    const fireRemove = editor => {
6837      editor.dispatch('remove');
6838    };
6839    const fireDetach = editor => {
6840      editor.dispatch('detach');
6841    };
6842    const fireSwitchMode = (editor, mode) => {
6843      editor.dispatch('SwitchMode', { mode });
6844    };
6845    const fireObjectResizeStart = (editor, target, width, height, origin) => {
6846      editor.dispatch('ObjectResizeStart', {
6847        target,
6848        width,
6849        height,
6850        origin
6851      });
6852    };
6853    const fireObjectResized = (editor, target, width, height, origin) => {
6854      editor.dispatch('ObjectResized', {
6855        target,
6856        width,
6857        height,
6858        origin
6859      });
6860    };
6861    const firePreInit = editor => {
6862      editor.dispatch('PreInit');
6863    };
6864    const firePostRender = editor => {
6865      editor.dispatch('PostRender');
6866    };
6867    const fireInit = editor => {
6868      editor.dispatch('Init');
6869    };
6870    const firePlaceholderToggle = (editor, state) => {
6871      editor.dispatch('PlaceholderToggle', { state });
6872    };
6873    const fireError = (editor, errorType, error) => {
6874      editor.dispatch(errorType, error);
6875    };
6876    const fireFormatApply = (editor, format, node, vars) => {
6877      editor.dispatch('FormatApply', {
6878        format,
6879        node,
6880        vars
6881      });
6882    };
6883    const fireFormatRemove = (editor, format, node, vars) => {
6884      editor.dispatch('FormatRemove', {
6885        format,
6886        node,
6887        vars
6888      });
6889    };
6890    const fireBeforeSetContent = (editor, args) => editor.dispatch('BeforeSetContent', args);
6891    const fireSetContent = (editor, args) => editor.dispatch('SetContent', args);
6892    const fireBeforeGetContent = (editor, args) => editor.dispatch('BeforeGetContent', args);
6893    const fireGetContent = (editor, args) => editor.dispatch('GetContent', args);
6894    const fireAutocompleterStart = (editor, args) => {
6895      editor.dispatch('AutocompleterStart', args);
6896    };
6897    const fireAutocompleterUpdate = (editor, args) => {
6898      editor.dispatch('AutocompleterUpdate', args);
6899    };
6900    const fireAutocompleterUpdateActiveRange = (editor, args) => {
6901      editor.dispatch('AutocompleterUpdateActiveRange', args);
6902    };
6903    const fireAutocompleterEnd = editor => {
6904      editor.dispatch('AutocompleterEnd');
6905    };
6906    const firePastePreProcess = (editor, html, internal) => editor.dispatch('PastePreProcess', {
6907      content: html,
6908      internal
6909    });
6910    const firePastePostProcess = (editor, node, internal) => editor.dispatch('PastePostProcess', {
6911      node,
6912      internal
6913    });
6914    const firePastePlainTextToggle = (editor, state) => editor.dispatch('PastePlainTextToggle', { state });
6915    const fireEditableRootStateChange = (editor, state) => editor.dispatch('EditableRootStateChange', { state });
6916    const fireDisabledStateChange = (editor, state) => editor.dispatch('DisabledStateChange', { state });
6917
6918    const deviceDetection$1 = detect$1().deviceType;
6919    const isTouch = deviceDetection$1.isTouch();
6920    const DOM$a = DOMUtils.DOM;
6921    const getHash = value => {
6922      const items = value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(',');
6923      return foldl(items, (output, item) => {
6924        const arr = item.split('=');
6925        const key = arr[0];
6926        const val = arr.length > 1 ? arr[1] : key;
6927        output[trim$4(key)] = trim$4(val);
6928        return output;
6929      }, {});
6930    };
6931    const isRegExp = x => is$4(x, RegExp);
6932    const option = name => editor => editor.options.get(name);
6933    const stringOrObjectProcessor = value => isString(value) || isObject(value);
6934    const bodyOptionProcessor = (editor, defaultValue = '') => value => {
6935      const valid = isString(value);
6936      if (valid) {
6937        if (value.indexOf('=') !== -1) {
6938          const bodyObj = getHash(value);
6939          return {
6940            value: get$a(bodyObj, editor.id).getOr(defaultValue),
6941            valid
6942          };
6943        } else {
6944          return {
6945            value,
6946            valid
6947          };
6948        }
6949      } else {
6950        return {
6951          valid: false,
6952          message: 'Must be a string.'
6953        };
6954      }
6955    };
6956    const register$7 = editor => {
6957      const registerOption = editor.options.register;
6958      registerOption('id', {
6959        processor: 'string',
6960        default: editor.id
6961      });
6962      registerOption('selector', { processor: 'string' });
6963      registerOption('target', { processor: 'object' });
6964      registerOption('suffix', { processor: 'string' });
6965      registerOption('cache_suffix', { processor: 'string' });
6966      registerOption('base_url', { processor: 'string' });
6967      registerOption('referrer_policy', {
6968        processor: 'string',
6969        default: ''
6970      });
6971      registerOption('language_load', {
6972        processor: 'boolean',
6973        default: true
6974      });
6975      registerOption('inline', {
6976        processor: 'boolean',
6977        default: false
6978      });
6979      registerOption('iframe_attrs', {
6980        processor: 'object',
6981        default: {}
6982      });
6983      registerOption('doctype', {
6984        processor: 'string',
6985        default: '<!DOCTYPE html>'
6986      });
6987      registerOption('document_base_url', {
6988        processor: 'string',
6989        default: editor.documentBaseUrl
6990      });
6991      registerOption('body_id', {
6992        processor: bodyOptionProcessor(editor, 'tinymce'),
6993        default: 'tinymce'
6994      });
6995      registerOption('body_class', {
6996        processor: bodyOptionProcessor(editor),
6997        default: ''
6998      });
6999      registerOption('content_security_policy', {
7000        processor: 'string',
7001        default: ''
7002      });
7003      registerOption('br_in_pre', {
7004        processor: 'boolean',
7005        default: true
7006      });
7007      registerOption('forced_root_block', {
7008        processor: value => {
7009          const valid = isString(value) && isNotEmpty(value);
7010          if (valid) {
7011            return {
7012              value,
7013              valid
7014            };
7015          } else {
7016            return {
7017              valid: false,
7018              message: 'Must be a non-empty string.'
7019            };
7020          }
7021        },
7022        default: 'p'
7023      });
7024      registerOption('forced_root_block_attrs', {
7025        processor: 'object',
7026        default: {}
7027      });
7028      registerOption('newline_behavior', {
7029        processor: value => {
7030          const valid = contains$2([
7031            'block',
7032            'linebreak',
7033            'invert',
7034            'default'
7035          ], value);
7036          return valid ? {
7037            value,
7038            valid
7039          } : {
7040            valid: false,
7041            message: 'Must be one of: block, linebreak, invert or default.'
7042          };
7043        },
7044        default: 'default'
7045      });
7046      registerOption('br_newline_selector', {
7047        processor: 'string',
7048        default: '.mce-toc h2,figcaption,caption'
7049      });
7050      registerOption('no_newline_selector', {
7051        processor: 'string',
7052        default: ''
7053      });
7054      registerOption('keep_styles', {
7055        processor: 'boolean',
7056        default: true
7057      });
7058      registerOption('end_container_on_empty_block', {
7059        processor: value => {
7060          if (isBoolean(value)) {
7061            return {
7062              valid: true,
7063              value
7064            };
7065          } else if (isString(value)) {
7066            return {
7067              valid: true,
7068              value
7069            };
7070          } else {
7071            return {
7072              valid: false,
7073              message: 'Must be boolean or a string'
7074            };
7075          }
7076        },
7077        default: 'blockquote'
7078      });
7079      registerOption('font_size_style_values', {
7080        processor: 'string',
7081        default: 'xx-small,x-small,small,medium,large,x-large,xx-large'
7082      });
7083      registerOption('font_size_legacy_values', {
7084        processor: 'string',
7085        default: 'xx-small,small,medium,large,x-large,xx-large,300%'
7086      });
7087      registerOption('font_size_classes', {
7088        processor: 'string',
7089        default: ''
7090      });
7091      registerOption('automatic_uploads', {
7092        processor: 'boolean',
7093        default: true
7094      });
7095      registerOption('images_reuse_filename', {
7096        processor: 'boolean',
7097        default: false
7098      });
7099      registerOption('images_replace_blob_uris', {
7100        processor: 'boolean',
7101        default: true
7102      });
7103      registerOption('icons', {
7104        processor: 'string',
7105        default: ''
7106      });
7107      registerOption('icons_url', {
7108        processor: 'string',
7109        default: ''
7110      });
7111      registerOption('images_upload_url', {
7112        processor: 'string',
7113        default: ''
7114      });
7115      registerOption('images_upload_base_path', {
7116        processor: 'string',
7117        default: ''
7118      });
7119      registerOption('images_upload_credentials', {
7120        processor: 'boolean',
7121        default: false
7122      });
7123      registerOption('images_upload_handler', { processor: 'function' });
7124      registerOption('language', {
7125        processor: 'string',
7126        default: 'en'
7127      });
7128      registerOption('language_url', {
7129        processor: 'string',
7130        default: ''
7131      });
7132      registerOption('entity_encoding', {
7133        processor: 'string',
7134        default: 'named'
7135      });
7136      registerOption('indent', {
7137        processor: 'boolean',
7138        default: true
7139      });
7140      registerOption('indent_before', {
7141        processor: 'string',
7142        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,details,summary,article,hgroup,aside,f
vendor: 7,091 bytes, lines 7142-7368
7142igure,figcaption,option,optgroup,datalist'
7143      });
7144      registerOption('indent_after', {
7145        processor: 'string',
7146        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,details,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist'
7147      });
7148      registerOption('indent_use_margin', {
7149        processor: 'boolean',
7150        default: false
7151      });
7152      registerOption('indentation', {
7153        processor: 'string',
7154        default: '40px'
7155      });
7156      registerOption('content_css', {
7157        processor: value => {
7158          const valid = value === false || isString(value) || isArrayOf(value, isString);
7159          if (valid) {
7160            if (isString(value)) {
7161              return {
7162                value: map$3(value.split(','), trim$4),
7163                valid
7164              };
7165            } else if (isArray$1(value)) {
7166              return {
7167                value,
7168                valid
7169              };
7170            } else if (value === false) {
7171              return {
7172                value: [],
7173                valid
7174              };
7175            } else {
7176              return {
7177                value,
7178                valid
7179              };
7180            }
7181          } else {
7182            return {
7183              valid: false,
7184              message: 'Must be false, a string or an array of strings.'
7185            };
7186          }
7187        },
7188        default: isInline$1(editor) ? [] : ['default']
7189      });
7190      registerOption('content_style', { processor: 'string' });
7191      registerOption('content_css_cors', {
7192        processor: 'boolean',
7193        default: false
7194      });
7195      registerOption('font_css', {
7196        processor: value => {
7197          const valid = isString(value) || isArrayOf(value, isString);
7198          if (valid) {
7199            const newValue = isArray$1(value) ? value : map$3(value.split(','), trim$4);
7200            return {
7201              value: newValue,
7202              valid
7203            };
7204          } else {
7205            return {
7206              valid: false,
7207              message: 'Must be a string or an array of strings.'
7208            };
7209          }
7210        },
7211        default: []
7212      });
7213      registerOption('inline_boundaries', {
7214        processor: 'boolean',
7215        default: true
7216      });
7217      registerOption('inline_boundaries_selector', {
7218        processor: 'string',
7219        default: 'a[href],code,span.mce-annotation'
7220      });
7221      registerOption('object_resizing', {
7222        processor: value => {
7223          const valid = isBoolean(value) || isString(value);
7224          if (valid) {
7225            if (value === false || deviceDetection$1.isiPhone() || deviceDetection$1.isiPad()) {
7226              return {
7227                value: '',
7228                valid
7229              };
7230            } else {
7231              return {
7232                value: value === true ? 'table,img,figure.image,div,video,iframe' : value,
7233                valid
7234              };
7235            }
7236          } else {
7237            return {
7238              valid: false,
7239              message: 'Must be boolean or a string'
7240            };
7241          }
7242        },
7243        default: !isTouch
7244      });
7245      registerOption('resize_img_proportional', {
7246        processor: 'boolean',
7247        default: true
7248      });
7249      registerOption('event_root', { processor: 'string' });
7250      registerOption('service_message', { processor: 'string' });
7251      registerOption('theme', {
7252        processor: value => value === false || isString(value) || isFunction(value),
7253        default: 'silver'
7254      });
7255      registerOption('theme_url', { processor: 'string' });
7256      registerOption('formats', { processor: 'object' });
7257      registerOption('format_empty_lines', {
7258        processor: 'boolean',
7259        default: false
7260      });
7261      registerOption('format_noneditable_selector', {
7262        processor: 'string',
7263        default: ''
7264      });
7265      registerOption('preview_styles', {
7266        processor: value => {
7267          const valid = value === false || isString(value);
7268          if (valid) {
7269            return {
7270              value: value === false ? '' : value,
7271              valid
7272            };
7273          } else {
7274            return {
7275              valid: false,
7276              message: 'Must be false or a string'
7277            };
7278          }
7279        },
7280        default: 'font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow'
7281      });
7282      registerOption('custom_ui_selector', {
7283        processor: 'string',
7284        default: ''
7285      });
7286      registerOption('hidden_input', {
7287        processor: 'boolean',
7288        default: true
7289      });
7290      registerOption('submit_patch', {
7291        processor: 'boolean',
7292        default: true
7293      });
7294      registerOption('encoding', { processor: 'string' });
7295      registerOption('add_form_submit_trigger', {
7296        processor: 'boolean',
7297        default: true
7298      });
7299      registerOption('add_unload_trigger', {
7300        processor: 'boolean',
7301        default: true
7302      });
7303      registerOption('custom_undo_redo_levels', {
7304        processor: 'number',
7305        default: 0
7306      });
7307      registerOption('disable_nodechange', {
7308        processor: 'boolean',
7309        default: false
7310      });
7311      registerOption('disabled', {
7312        processor: value => {
7313          if (isBoolean(value)) {
7314            if (editor.initialized && isDisabled$1(editor) !== value) {
7315              Promise.resolve().then(() => {
7316                fireDisabledStateChange(editor, value);
7317              });
7318            }
7319            return {
7320              valid: true,
7321              value
7322            };
7323          }
7324          return {
7325            valid: false,
7326            message: 'The value must be a boolean.'
7327          };
7328        },
7329        default: false
7330      });
7331      registerOption('readonly', {
7332        processor: 'boolean',
7333        default: false
7334      });
7335      registerOption('editable_root', {
7336        processor: 'boolean',
7337        default: true
7338      });
7339      registerOption('plugins', {
7340        processor: 'string[]',
7341        default: []
7342      });
7343      registerOption('external_plugins', { processor: 'object' });
7344      registerOption('forced_plugins', { processor: 'string[]' });
7345      registerOption('model', {
7346        processor: 'string',
7347        default: editor.hasPlugin('rtc') ? 'plugin' : 'dom'
7348      });
7349      registerOption('model_url', { processor: 'string' });
7350      registerOption('block_unsupported_drop', {
7351        processor: 'boolean',
7352        default: true
7353      });
7354      registerOption('visual', {
7355        processor: 'boolean',
7356        default: true
7357      });
7358      registerOption('visual_table_class', {
7359        processor: 'string',
7360        default: 'mce-item-table'
7361      });
7362      registerOption('visual_anchor_class', {
7363        processor: 'string',
7364        default: 'mce-item-anchor'
7365      });
7366      registerOption('iframe_aria_text', {
7367        processor: 'string',
7368        default: 'Rich Text Area'.concat(editor.hasPlugin('help') ? '. Press ALT
vendor: 15,423 bytes, lines 7368-7825
7368-0 for help.' : '')
7369      });
7370      registerOption('setup', { processor: 'function' });
7371      registerOption('init_instance_callback', { processor: 'function' });
7372      registerOption('url_converter', {
7373        processor: 'function',
7374        default: editor.convertURL
7375      });
7376      registerOption('url_converter_scope', {
7377        processor: 'object',
7378        default: editor
7379      });
7380      registerOption('urlconverter_callback', { processor: 'function' });
7381      registerOption('allow_conditional_comments', {
7382        processor: 'boolean',
7383        default: false
7384      });
7385      registerOption('allow_html_data_urls', {
7386        processor: 'boolean',
7387        default: false
7388      });
7389      registerOption('allow_svg_data_urls', { processor: 'boolean' });
7390      registerOption('allow_html_in_named_anchor', {
7391        processor: 'boolean',
7392        default: false
7393      });
7394      registerOption('allow_script_urls', {
7395        processor: 'boolean',
7396        default: false
7397      });
7398      registerOption('allow_unsafe_link_target', {
7399        processor: 'boolean',
7400        default: false
7401      });
7402      registerOption('allow_mathml_annotation_encodings', {
7403        processor: value => {
7404          const valid = isArrayOf(value, isString);
7405          return valid ? {
7406            value,
7407            valid
7408          } : {
7409            valid: false,
7410            message: 'Must be an array of strings.'
7411          };
7412        },
7413        default: []
7414      });
7415      registerOption('convert_fonts_to_spans', {
7416        processor: 'boolean',
7417        default: true,
7418        deprecated: true
7419      });
7420      registerOption('fix_list_elements', {
7421        processor: 'boolean',
7422        default: false
7423      });
7424      registerOption('preserve_cdata', {
7425        processor: 'boolean',
7426        default: false
7427      });
7428      registerOption('remove_trailing_brs', {
7429        processor: 'boolean',
7430        default: true
7431      });
7432      registerOption('pad_empty_with_br', {
7433        processor: 'boolean',
7434        default: false
7435      });
7436      registerOption('inline_styles', {
7437        processor: 'boolean',
7438        default: true,
7439        deprecated: true
7440      });
7441      registerOption('element_format', {
7442        processor: 'string',
7443        default: 'html'
7444      });
7445      registerOption('entities', { processor: 'string' });
7446      registerOption('schema', {
7447        processor: 'string',
7448        default: 'html5'
7449      });
7450      registerOption('convert_urls', {
7451        processor: 'boolean',
7452        default: true
7453      });
7454      registerOption('relative_urls', {
7455        processor: 'boolean',
7456        default: true
7457      });
7458      registerOption('remove_script_host', {
7459        processor: 'boolean',
7460        default: true
7461      });
7462      registerOption('custom_elements', { processor: stringOrObjectProcessor });
7463      registerOption('extended_valid_elements', { processor: 'string' });
7464      registerOption('invalid_elements', { processor: 'string' });
7465      registerOption('invalid_styles', { processor: stringOrObjectProcessor });
7466      registerOption('valid_children', { processor: 'string' });
7467      registerOption('valid_classes', { processor: stringOrObjectProcessor });
7468      registerOption('valid_elements', { processor: 'string' });
7469      registerOption('valid_styles', { processor: stringOrObjectProcessor });
7470      registerOption('verify_html', {
7471        processor: 'boolean',
7472        default: true
7473      });
7474      registerOption('auto_focus', { processor: value => isString(value) || value === true });
7475      registerOption('browser_spellcheck', {
7476        processor: 'boolean',
7477        default: false
7478      });
7479      registerOption('protect', { processor: 'array' });
7480      registerOption('images_file_types', {
7481        processor: 'string',
7482        default: 'jpeg,jpg,jpe,jfi,jif,jfif,png,gif,bmp,webp'
7483      });
7484      registerOption('deprecation_warnings', {
7485        processor: 'boolean',
7486        default: true
7487      });
7488      registerOption('a11y_advanced_options', {
7489        processor: 'boolean',
7490        default: false
7491      });
7492      registerOption('api_key', { processor: 'string' });
7493      registerOption('license_key', { processor: 'string' });
7494      registerOption('paste_block_drop', {
7495        processor: 'boolean',
7496        default: false
7497      });
7498      registerOption('paste_data_images', {
7499        processor: 'boolean',
7500        default: true
7501      });
7502      registerOption('paste_preprocess', { processor: 'function' });
7503      registerOption('paste_postprocess', { processor: 'function' });
7504      registerOption('paste_webkit_styles', {
7505        processor: 'string',
7506        default: 'none'
7507      });
7508      registerOption('paste_remove_styles_if_webkit', {
7509        processor: 'boolean',
7510        default: true
7511      });
7512      registerOption('paste_merge_formats', {
7513        processor: 'boolean',
7514        default: true
7515      });
7516      registerOption('smart_paste', {
7517        processor: 'boolean',
7518        default: true
7519      });
7520      registerOption('paste_as_text', {
7521        processor: 'boolean',
7522        default: false
7523      });
7524      registerOption('paste_tab_spaces', {
7525        processor: 'number',
7526        default: 4
7527      });
7528      registerOption('text_patterns', {
7529        processor: value => {
7530          if (isArrayOf(value, isObject) || value === false) {
7531            const patterns = value === false ? [] : value;
7532            return {
7533              value: fromRawPatterns(patterns),
7534              valid: true
7535            };
7536          } else {
7537            return {
7538              valid: false,
7539              message: 'Must be an array of objects or false.'
7540            };
7541          }
7542        },
7543        default: [
7544          {
7545            start: '*',
7546            end: '*',
7547            format: 'italic'
7548          },
7549          {
7550            start: '**',
7551            end: '**',
7552            format: 'bold'
7553          },
7554          {
7555            start: '#',
7556            format: 'h1',
7557            trigger: 'space'
7558          },
7559          {
7560            start: '##',
7561            format: 'h2',
7562            trigger: 'space'
7563          },
7564          {
7565            start: '###',
7566            format: 'h3',
7567            trigger: 'space'
7568          },
7569          {
7570            start: '####',
7571            format: 'h4',
7572            trigger: 'space'
7573          },
7574          {
7575            start: '#####',
7576            format: 'h5',
7577            trigger: 'space'
7578          },
7579          {
7580            start: '######',
7581            format: 'h6',
7582            trigger: 'space'
7583          },
7584          {
7585            start: '1.',
7586            cmd: 'InsertOrderedList',
7587            trigger: 'space'
7588          },
7589          {
7590            start: '*',
7591            cmd: 'InsertUnorderedList',
7592            trigger: 'space'
7593          },
7594          {
7595            start: '-',
7596            cmd: 'InsertUnorderedList',
7597            trigger: 'space'
7598          },
7599          {
7600            start: '>',
7601            cmd: 'mceBlockQuote',
7602            trigger: 'space'
7603          },
7604          {
7605            start: '---',
7606            cmd: 'InsertHorizontalRule',
7607            trigger: 'space'
7608          }
7609        ]
7610      });
7611      registerOption('text_patterns_lookup', {
7612        processor: value => {
7613          if (isFunction(value)) {
7614            return {
7615              value: fromRawPatternsLookup(value),
7616              valid: true
7617            };
7618          } else {
7619            return {
7620              valid: false,
7621              message: 'Must be a single function'
7622            };
7623          }
7624        },
7625        default: _ctx => []
7626      });
7627      registerOption('noneditable_class', {
7628        processor: 'string',
7629        default: 'mceNonEditable'
7630      });
7631      registerOption('editable_class', {
7632        processor: 'string',
7633        default: 'mceEditable'
7634      });
7635      registerOption('noneditable_regexp', {
7636        processor: value => {
7637          if (isArrayOf(value, isRegExp)) {
7638            return {
7639              value,
7640              valid: true
7641            };
7642          } else if (isRegExp(value)) {
7643            return {
7644              value: [value],
7645              valid: true
7646            };
7647          } else {
7648            return {
7649              valid: false,
7650              message: 'Must be a RegExp or an array of RegExp.'
7651            };
7652          }
7653        },
7654        default: []
7655      });
7656      registerOption('table_tab_navigation', {
7657        processor: 'boolean',
7658        default: true
7659      });
7660      registerOption('highlight_on_focus', {
7661        processor: 'boolean',
7662        default: true
7663      });
7664      registerOption('xss_sanitization', {
7665        processor: 'boolean',
7666        default: true
7667      });
7668      registerOption('details_initial_state', {
7669        processor: value => {
7670          const valid = contains$2([
7671            'inherited',
7672            'collapsed',
7673            'expanded'
7674          ], value);
7675          return valid ? {
7676            value,
7677            valid
7678          } : {
7679            valid: false,
7680            message: 'Must be one of: inherited, collapsed, or expanded.'
7681          };
7682        },
7683        default: 'inherited'
7684      });
7685      registerOption('details_serialized_state', {
7686        processor: value => {
7687          const valid = contains$2([
7688            'inherited',
7689            'collapsed',
7690            'expanded'
7691          ], value);
7692          return valid ? {
7693            value,
7694            valid
7695          } : {
7696            valid: false,
7697            message: 'Must be one of: inherited, collapsed, or expanded.'
7698          };
7699        },
7700        default: 'inherited'
7701      });
7702      registerOption('init_content_sync', {
7703        processor: 'boolean',
7704        default: false
7705      });
7706      registerOption('newdocument_content', {
7707        processor: 'string',
7708        default: ''
7709      });
7710      registerOption('sandbox_iframes', {
7711        processor: 'boolean',
7712        default: true
7713      });
7714      registerOption('sandbox_iframes_exclusions', {
7715        processor: 'string[]',
7716        default: [
7717          'youtube.com',
7718          'youtu.be',
7719          'vimeo.com',
7720          'player.vimeo.com',
7721          'dailymotion.com',
7722          'embed.music.apple.com',
7723          'open.spotify.com',
7724          'giphy.com',
7725          'dai.ly',
7726          'codepen.io'
7727        ]
7728      });
7729      registerOption('convert_unsafe_embeds', {
7730        processor: 'boolean',
7731        default: true
7732      });
7733      editor.on('ScriptsLoaded', () => {
7734        registerOption('directionality', {
7735          processor: 'string',
7736          default: I18n.isRtl() ? 'rtl' : undefined
7737        });
7738        registerOption('placeholder', {
7739          processor: 'string',
7740          default: DOM$a.getAttrib(editor.getElement(), 'placeholder')
7741        });
7742      });
7743    };
7744    const getIframeAttrs = option('iframe_attrs');
7745    const getDocType = option('doctype');
7746    const getDocumentBaseUrl = option('document_base_url');
7747    const getBodyId = option('body_id');
7748    const getBodyClass = option('body_class');
7749    const getContentSecurityPolicy = option('content_security_policy');
7750    const shouldPutBrInPre$1 = option('br_in_pre');
7751    const getForcedRootBlock = option('forced_root_block');
7752    const getForcedRootBlockAttrs = option('forced_root_block_attrs');
7753    const getNewlineBehavior = option('newline_behavior');
7754    const getBrNewLineSelector = option('br_newline_selector');
7755    const getNoNewLineSelector = option('no_newline_selector');
7756    const shouldKeepStyles = option('keep_styles');
7757    const shouldEndContainerOnEmptyBlock = option('end_container_on_empty_block');
7758    const isAutomaticUploadsEnabled = option('automatic_uploads');
7759    const shouldReuseFileName = option('images_reuse_filename');
7760    const shouldReplaceBlobUris = option('images_replace_blob_uris');
7761    const getIconPackName = option('icons');
7762    const getIconsUrl = option('icons_url');
7763    const getImageUploadUrl = option('images_upload_url');
7764    const getImageUploadBasePath = option('images_upload_base_path');
7765    const getImagesUploadCredentials = option('images_upload_credentials');
7766    const getImagesUploadHandler = option('images_upload_handler');
7767    const shouldUseContentCssCors = option('content_css_cors');
7768    const getReferrerPolicy = option('referrer_policy');
7769    const getLanguageCode = option('language');
7770    const getLanguageUrl = option('language_url');
7771    const shouldIndentUseMargin = option('indent_use_margin');
7772    const getIndentation = option('indentation');
7773    const getContentCss = option('content_css');
7774    const getContentStyle = option('content_style');
7775    const getFontCss = option('font_css');
7776    const getDirectionality = option('directionality');
7777    const getInlineBoundarySelector = option('inline_boundaries_selector');
7778    const getObjectResizing = option('object_resizing');
7779    const getResizeImgProportional = option('resize_img_proportional');
7780    const getPlaceholder = option('placeholder');
7781    const getEventRoot = option('event_root');
7782    const getServiceMessage = option('service_message');
7783    const getTheme = option('theme');
7784    const getThemeUrl = option('theme_url');
7785    const getModel = option('model');
7786    const getModelUrl = option('model_url');
7787    const isInlineBoundariesEnabled = option('inline_boundaries');
7788    const getFormats = option('formats');
7789    const getPreviewStyles = option('preview_styles');
7790    const canFormatEmptyLines = option('format_empty_lines');
7791    const getFormatNoneditableSelector = option('format_noneditable_selector');
7792    const getCustomUiSelector = option('custom_ui_selector');
7793    const isInline$1 = option('inline');
7794    const hasHiddenInput = option('hidden_input');
7795    const shouldPatchSubmit = option('submit_patch');
7796    const shouldAddFormSubmitTrigger = option('add_form_submit_trigger');
7797    const shouldAddUnloadTrigger = option('add_unload_trigger');
7798    const getCustomUndoRedoLevels = option('custom_undo_redo_levels');
7799    const shouldDisableNodeChange = option('disable_nodechange');
7800    const isReadOnly$1 = option('readonly');
7801    const hasEditableRoot$1 = option('editable_root');
7802    const hasContentCssCors = option('content_css_cors');
7803    const getPlugins = option('plugins');
7804    const getExternalPlugins$1 = option('external_plugins');
7805    const shouldBlockUnsupportedDrop = option('block_unsupported_drop');
7806    const isVisualAidsEnabled = option('visual');
7807    const getVisualAidsTableClass = option('visual_table_class');
7808    const getVisualAidsAnchorClass = option('visual_anchor_class');
7809    const getIframeAriaText = option('iframe_aria_text');
7810    const getSetupCallback = option('setup');
7811    const getInitInstanceCallback = option('init_instance_callback');
7812    const getUrlConverterCallback = option('urlconverter_callback');
7813    const getAutoFocus = option('auto_focus');
7814    const shouldBrowserSpellcheck = option('browser_spellcheck');
7815    const getProtect = option('protect');
7816    const shouldPasteBlockDrop = option('paste_block_drop');
7817    const shouldPasteDataImages = option('paste_data_images');
7818    const getPastePreProcess = option('paste_preprocess');
7819    const getPastePostProcess = option('paste_postprocess');
7820    const getNewDocumentContent = option('newdocument_content');
7821    const getPasteWebkitStyles = option('paste_webkit_styles');
7822    const shouldPasteRemoveWebKitStyles = option('paste_remove_styles_if_webkit');
7823    const shouldPasteMergeFormats = option('paste_merge_formats');
7824    const isSmartPasteEnabled = option('smart_paste');
7825    const isPasteAsTextEnabled = option('paste_as_text');
vendor: 12,420 bytes, lines 7826-8124
7826    const getPasteTabSpaces = option('paste_tab_spaces');
7827    const shouldAllowHtmlDataUrls = option('allow_html_data_urls');
7828    const getTextPatterns = option('text_patterns');
7829    const getTextPatternsLookup = option('text_patterns_lookup');
7830    const getNonEditableClass = option('noneditable_class');
7831    const getEditableClass = option('editable_class');
7832    const getNonEditableRegExps = option('noneditable_regexp');
7833    const shouldPreserveCData = option('preserve_cdata');
7834    const shouldHighlightOnFocus = option('highlight_on_focus');
7835    const shouldSanitizeXss = option('xss_sanitization');
7836    const shouldUseDocumentWrite = option('init_content_sync');
7837    const hasTextPatternsLookup = editor => editor.options.isSet('text_patterns_lookup');
7838    const getFontStyleValues = editor => Tools.explode(editor.options.get('font_size_style_values'));
7839    const getFontSizeClasses = editor => Tools.explode(editor.options.get('font_size_classes'));
7840    const isEncodingXml = editor => editor.options.get('encoding') === 'xml';
7841    const getAllowedImageFileTypes = editor => Tools.explode(editor.options.get('images_file_types'));
7842    const hasTableTabNavigation = option('table_tab_navigation');
7843    const getDetailsInitialState = option('details_initial_state');
7844    const getDetailsSerializedState = option('details_serialized_state');
7845    const shouldSandboxIframes = option('sandbox_iframes');
7846    const getSandboxIframesExclusions = editor => editor.options.get('sandbox_iframes_exclusions');
7847    const shouldConvertUnsafeEmbeds = option('convert_unsafe_embeds');
7848    const getLicenseKey = option('license_key');
7849    const getApiKey = option('api_key');
7850    const isDisabled$1 = option('disabled');
7851
7852    const isElement$3 = isElement$6;
7853    const isText$5 = isText$b;
7854    const removeNode$1 = node => {
7855      const parentNode = node.parentNode;
7856      if (parentNode) {
7857        parentNode.removeChild(node);
7858      }
7859    };
7860    const trimCount = text => {
7861      const trimmedText = trim$2(text);
7862      return {
7863        count: text.length - trimmedText.length,
7864        text: trimmedText
7865      };
7866    };
7867    const deleteZwspChars = caretContainer => {
7868      let idx;
7869      while ((idx = caretContainer.data.lastIndexOf(ZWSP$1)) !== -1) {
7870        caretContainer.deleteData(idx, 1);
7871      }
7872    };
7873    const removeUnchanged = (caretContainer, pos) => {
7874      remove$2(caretContainer);
7875      return pos;
7876    };
7877    const removeTextAndReposition = (caretContainer, pos) => {
7878      const before = trimCount(caretContainer.data.substr(0, pos.offset()));
7879      const after = trimCount(caretContainer.data.substr(pos.offset()));
7880      const text = before.text + after.text;
7881      if (text.length > 0) {
7882        deleteZwspChars(caretContainer);
7883        return CaretPosition(caretContainer, pos.offset() - before.count);
7884      } else {
7885        return pos;
7886      }
7887    };
7888    const removeElementAndReposition = (caretContainer, pos) => {
7889      const parentNode = pos.container();
7890      const newPosition = indexOf$1(from(parentNode.childNodes), caretContainer).map(index => {
7891        return index < pos.offset() ? CaretPosition(parentNode, pos.offset() - 1) : pos;
7892      }).getOr(pos);
7893      remove$2(caretContainer);
7894      return newPosition;
7895    };
7896    const removeTextCaretContainer = (caretContainer, pos) => isText$5(caretContainer) && pos.container() === caretContainer ? removeTextAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
7897    const removeElementCaretContainer = (caretContainer, pos) => pos.container() === caretContainer.parentNode ? removeElementAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
7898    const removeAndReposition = (container, pos) => CaretPosition.isTextPosition(pos) ? removeTextCaretContainer(container, pos) : removeElementCaretContainer(container, pos);
7899    const remove$2 = caretContainerNode => {
7900      if (isElement$3(caretContainerNode) && isCaretContainer$2(caretContainerNode)) {
7901        if (hasContent(caretContainerNode)) {
7902          caretContainerNode.removeAttribute('data-mce-caret');
7903        } else {
7904          removeNode$1(caretContainerNode);
7905        }
7906      }
7907      if (isText$5(caretContainerNode)) {
7908        deleteZwspChars(caretContainerNode);
7909        if (caretContainerNode.data.length === 0) {
7910          removeNode$1(caretContainerNode);
7911        }
7912      }
7913    };
7914
7915    const isContentEditableFalse$8 = isContentEditableFalse$b;
7916    const isMedia$1 = isMedia$2;
7917    const isTableCell$1 = isTableCell$3;
7918    const inlineFakeCaretSelector = '*[contentEditable=false],video,audio,embed,object';
7919    const getAbsoluteClientRect = (root, element, before) => {
7920      const clientRect = collapse(element.getBoundingClientRect(), before);
7921      let scrollX;
7922      let scrollY;
7923      if (root.tagName === 'BODY') {
7924        const docElm = root.ownerDocument.documentElement;
7925        scrollX = root.scrollLeft || docElm.scrollLeft;
7926        scrollY = root.scrollTop || docElm.scrollTop;
7927      } else {
7928        const rootRect = root.getBoundingClientRect();
7929        scrollX = root.scrollLeft - rootRect.left;
7930        scrollY = root.scrollTop - rootRect.top;
7931      }
7932      clientRect.left += scrollX;
7933      clientRect.right += scrollX;
7934      clientRect.top += scrollY;
7935      clientRect.bottom += scrollY;
7936      clientRect.width = 1;
7937      let margin = element.offsetWidth - element.clientWidth;
7938      if (margin > 0) {
7939        if (before) {
7940          margin *= -1;
7941        }
7942        clientRect.left += margin;
7943        clientRect.right += margin;
7944      }
7945      return clientRect;
7946    };
7947    const trimInlineCaretContainers = root => {
7948      var _a, _b;
7949      const fakeCaretTargetNodes = descendants(SugarElement.fromDom(root), inlineFakeCaretSelector);
7950      for (let i = 0; i < fakeCaretTargetNodes.length; i++) {
7951        const node = fakeCaretTargetNodes[i].dom;
7952        let sibling = node.previousSibling;
7953        if (endsWithCaretContainer$1(sibling)) {
7954          const data = sibling.data;
7955          if (data.length === 1) {
7956            (_a = sibling.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(sibling);
7957          } else {
7958            sibling.deleteData(data.length - 1, 1);
7959          }
7960        }
7961        sibling = node.nextSibling;
7962        if (startsWithCaretContainer$1(sibling)) {
7963          const data = sibling.data;
7964          if (data.length === 1) {
7965            (_b = sibling.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(sibling);
7966          } else {
7967            sibling.deleteData(0, 1);
7968          }
7969        }
7970      }
7971    };
7972    const FakeCaret = (editor, root, isBlock, hasFocus) => {
7973      const lastVisualCaret = value$2();
7974      let cursorInterval;
7975      let caretContainerNode;
7976      const caretBlock = getForcedRootBlock(editor);
7977      const dom = editor.dom;
7978      const show = (before, element) => {
7979        let rng;
7980        hide();
7981        if (isTableCell$1(element)) {
7982          return null;
7983        }
7984        if (isBlock(element)) {
7985          const caretContainer = insertBlock(caretBlock, element, before);
7986          const clientRect = getAbsoluteClientRect(root, element, before);
7987          dom.setStyle(caretContainer, 'top', clientRect.top);
7988          dom.setStyle(caretContainer, 'caret-color', 'transparent');
7989          caretContainerNode = caretContainer;
7990          const caret = dom.create('div', {
7991            'class': 'mce-visual-caret',
7992            'data-mce-bogus': 'all'
7993          });
7994          dom.setStyles(caret, { ...clientRect });
7995          dom.add(root, caret);
7996          lastVisualCaret.set({
7997            caret,
7998            element,
7999            before
8000          });
8001          if (before) {
8002            dom.addClass(caret, 'mce-visual-caret-before');
8003          }
8004          startBlink();
8005          rng = element.ownerDocument.createRange();
8006          rng.setStart(caretContainer, 0);
8007          rng.setEnd(caretContainer, 0);
8008        } else {
8009          caretContainerNode = insertInline$1(element, before);
8010          rng = element.ownerDocument.createRange();
8011          if (isInlineFakeCaretTarget(caretContainerNode.nextSibling)) {
8012            rng.setStart(caretContainerNode, 0);
8013            rng.setEnd(caretContainerNode, 0);
8014          } else {
8015            rng.setStart(caretContainerNode, 1);
8016            rng.setEnd(caretContainerNode, 1);
8017          }
8018          return rng;
8019        }
8020        return rng;
8021      };
8022      const hide = () => {
8023        trimInlineCaretContainers(root);
8024        if (caretContainerNode) {
8025          remove$2(caretContainerNode);
8026          caretContainerNode = null;
8027        }
8028        lastVisualCaret.on(caretState => {
8029          dom.remove(caretState.caret);
8030          lastVisualCaret.clear();
8031        });
8032        if (cursorInterval) {
8033          clearInterval(cursorInterval);
8034          cursorInterval = undefined;
8035        }
8036      };
8037      const startBlink = () => {
8038        cursorInterval = setInterval(() => {
8039          lastVisualCaret.on(caretState => {
8040            if (hasFocus()) {
8041              dom.toggleClass(caretState.caret, 'mce-visual-caret-hidden');
8042            } else {
8043              dom.addClass(caretState.caret, 'mce-visual-caret-hidden');
8044            }
8045          });
8046        }, 500);
8047      };
8048      const reposition = () => {
8049        lastVisualCaret.on(caretState => {
8050          const clientRect = getAbsoluteClientRect(root, caretState.element, caretState.before);
8051          dom.setStyles(caretState.caret, { ...clientRect });
8052        });
8053      };
8054      const destroy = () => clearInterval(cursorInterval);
8055      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;' + '}';
8056      return {
8057        show,
8058        hide,
8059        getCss,
8060        reposition,
8061        destroy
8062      };
8063    };
8064    const isFakeCaretTableBrowser = () => Env.browser.isFirefox();
8065    const isInlineFakeCaretTarget = node => isContentEditableFalse$8(node) || isMedia$1(node);
8066    const isFakeCaretTarget = node => {
8067      const isTarget = isInlineFakeCaretTarget(node) || isTable$2(node) && isFakeCaretTableBrowser();
8068      return isTarget && parentElement(SugarElement.fromDom(node)).exists(isEditable$2);
8069    };
8070
8071    const isContentEditableTrue$1 = isContentEditableTrue$3;
8072    const isContentEditableFalse$7 = isContentEditableFalse$b;
8073    const isMedia = isMedia$2;
8074    const isBlockLike = matchStyleValues('display', 'block table table-cell table-row table-caption list-item');
8075    const isCaretContainer = isCaretContainer$2;
8076    const isCaretContainerBlock = isCaretContainerBlock$1;
8077    const isElement$2 = isElement$6;
8078    const isText$4 = isText$b;
8079    const isCaretCandidate$1 = isCaretCandidate$3;
8080    const isForwards = direction => direction === 1;
8081    const isBackwards = direction => direction === -1;
8082    const skipCaretContainers = (walk, shallow) => {
8083      let node;
8084      while (node = walk(shallow)) {
8085        if (!isCaretContainerBlock(node)) {
8086          return node;
8087        }
8088      }
8089      return null;
8090    };
8091    const findNode = (node, direction, predicateFn, rootNode, shallow) => {
8092      const walker = new DomTreeWalker(node, rootNode);
8093      const isCefOrCaretContainer = isContentEditableFalse$7(node) || isCaretContainerBlock(node);
8094      let tempNode;
8095      if (isBackwards(direction)) {
8096        if (isCefOrCaretContainer) {
8097          tempNode = skipCaretContainers(walker.prev.bind(walker), true);
8098          if (predicateFn(tempNode)) {
8099            return tempNode;
8100          }
8101        }
8102        while (tempNode = skipCaretContainers(walker.prev.bind(walker), shallow)) {
8103          if (predicateFn(tempNode)) {
8104            return tempNode;
8105          }
8106        }
8107      }
8108      if (isForwards(direction)) {
8109        if (isCefOrCaretContainer) {
8110          tempNode = skipCaretContainers(walker.next.bind(walker), true);
8111          if (predicateFn(tempNode)) {
8112            return tempNode;
8113          }
8114        }
8115        while (tempNode = skipCaretContainers(walker.next.bind(walker), shallow)) {
8116          if (predicateFn(tempNode)) {
8117            return tempNode;
8118          }
8119        }
8120      }
8121      return null;
8122    };
8123    const getEditingHost = (node, rootNode) => {
8124      const isCETrue = node => isContentEditableTrue$1(node.dom);
vendor: 5,993 bytes, lines 8125-8298
8125      const isRoot = node => node.dom === rootNode;
8126      return ancestor$4(SugarElement.fromDom(node), isCETrue, isRoot).map(elm => elm.dom).getOr(rootNode);
8127    };
8128    const getParentBlock$3 = (node, rootNode) => {
8129      while (node && node !== rootNode) {
8130        if (isBlockLike(node)) {
8131          return node;
8132        }
8133        node = node.parentNode;
8134      }
8135      return null;
8136    };
8137    const isInSameBlock = (caretPosition1, caretPosition2, rootNode) => getParentBlock$3(caretPosition1.container(), rootNode) === getParentBlock$3(caretPosition2.container(), rootNode);
8138    const getChildNodeAtRelativeOffset = (relativeOffset, caretPosition) => {
8139      if (!caretPosition) {
8140        return Optional.none();
8141      }
8142      const container = caretPosition.container();
8143      const offset = caretPosition.offset();
8144      if (!isElement$2(container)) {
8145        return Optional.none();
8146      }
8147      return Optional.from(container.childNodes[offset + relativeOffset]);
8148    };
8149    const beforeAfter = (before, node) => {
8150      var _a;
8151      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
8152      const range = doc.createRange();
8153      if (before) {
8154        range.setStartBefore(node);
8155        range.setEndBefore(node);
8156      } else {
8157        range.setStartAfter(node);
8158        range.setEndAfter(node);
8159      }
8160      return range;
8161    };
8162    const isNodesInSameBlock = (root, node1, node2) => getParentBlock$3(node1, root) === getParentBlock$3(node2, root);
8163    const lean = (left, root, node) => {
8164      const siblingName = left ? 'previousSibling' : 'nextSibling';
8165      let tempNode = node;
8166      while (tempNode && tempNode !== root) {
8167        let sibling = tempNode[siblingName];
8168        if (sibling && isCaretContainer(sibling)) {
8169          sibling = sibling[siblingName];
8170        }
8171        if (isContentEditableFalse$7(sibling) || isMedia(sibling)) {
8172          if (isNodesInSameBlock(root, sibling, tempNode)) {
8173            return sibling;
8174          }
8175          break;
8176        }
8177        if (isCaretCandidate$1(sibling)) {
8178          break;
8179        }
8180        tempNode = tempNode.parentNode;
8181      }
8182      return null;
8183    };
8184    const before$2 = curry(beforeAfter, true);
8185    const after$2 = curry(beforeAfter, false);
8186    const normalizeRange = (direction, root, range) => {
8187      let node;
8188      const leanLeft = curry(lean, true, root);
8189      const leanRight = curry(lean, false, root);
8190      const container = range.startContainer;
8191      const offset = range.startOffset;
8192      if (isCaretContainerBlock$1(container)) {
8193        const block = isText$4(container) ? container.parentNode : container;
8194        const location = block.getAttribute('data-mce-caret');
8195        if (location === 'before') {
8196          node = block.nextSibling;
8197          if (isFakeCaretTarget(node)) {
8198            return before$2(node);
8199          }
8200        }
8201        if (location === 'after') {
8202          node = block.previousSibling;
8203          if (isFakeCaretTarget(node)) {
8204            return after$2(node);
8205          }
8206        }
8207      }
8208      if (!range.collapsed) {
8209        return range;
8210      }
8211      if (isText$b(container)) {
8212        if (isCaretContainer(container)) {
8213          if (direction === 1) {
8214            node = leanRight(container);
8215            if (node) {
8216              return before$2(node);
8217            }
8218            node = leanLeft(container);
8219            if (node) {
8220              return after$2(node);
8221            }
8222          }
8223          if (direction === -1) {
8224            node = leanLeft(container);
8225            if (node) {
8226              return after$2(node);
8227            }
8228            node = leanRight(container);
8229            if (node) {
8230              return before$2(node);
8231            }
8232          }
8233          return range;
8234        }
8235        if (endsWithCaretContainer$1(container) && offset >= container.data.length - 1) {
8236          if (direction === 1) {
8237            node = leanRight(container);
8238            if (node) {
8239              return before$2(node);
8240            }
8241          }
8242          return range;
8243        }
8244        if (startsWithCaretContainer$1(container) && offset <= 1) {
8245          if (direction === -1) {
8246            node = leanLeft(container);
8247            if (node) {
8248              return after$2(node);
8249            }
8250          }
8251          return range;
8252        }
8253        if (offset === container.data.length) {
8254          node = leanRight(container);
8255          if (node) {
8256            return before$2(node);
8257          }
8258          return range;
8259        }
8260        if (offset === 0) {
8261          node = leanLeft(container);
8262          if (node) {
8263            return after$2(node);
8264          }
8265          return range;
8266        }
8267      }
8268      return range;
8269    };
8270    const getRelativeCefElm = (forward, caretPosition) => getChildNodeAtRelativeOffset(forward ? 0 : -1, caretPosition).filter(isContentEditableFalse$7);
8271    const getNormalizedRangeEndPoint = (direction, root, range) => {
8272      const normalizedRange = normalizeRange(direction, root, range);
8273      return direction === -1 ? CaretPosition.fromRangeStart(normalizedRange) : CaretPosition.fromRangeEnd(normalizedRange);
8274    };
8275    const getElementFromPosition = pos => Optional.from(pos.getNode()).map(SugarElement.fromDom);
8276    const getElementFromPrevPosition = pos => Optional.from(pos.getNode(true)).map(SugarElement.fromDom);
8277    const getVisualCaretPosition = (walkFn, caretPosition) => {
8278      let pos = caretPosition;
8279      while (pos = walkFn(pos)) {
8280        if (pos.isVisible()) {
8281          return pos;
8282        }
8283      }
8284      return pos;
8285    };
8286    const isMoveInsideSameBlock = (from, to) => {
8287      const inSameBlock = isInSameBlock(from, to);
8288      if (!inSameBlock && isBr$6(from.getNode())) {
8289        return true;
8290      }
8291      return inSameBlock;
8292    };
8293
8294    const isContentEditableFalse$6 = isContentEditableFalse$b;
8295    const isText$3 = isText$b;
8296    const isElement$1 = isElement$6;
8297    const isBr$2 = isBr$6;
8298    const isCaretCandidate = isCaretCandidate$3;
vendor: 4,458 bytes, lines 8299-8420
8299    const isAtomic = isAtomic$1;
8300    const isEditableCaretCandidate = isEditableCaretCandidate$1;
8301    const getParents$3 = (node, root) => {
8302      const parents = [];
8303      let tempNode = node;
8304      while (tempNode && tempNode !== root) {
8305        parents.push(tempNode);
8306        tempNode = tempNode.parentNode;
8307      }
8308      return parents;
8309    };
8310    const nodeAtIndex = (container, offset) => {
8311      if (container.hasChildNodes() && offset < container.childNodes.length) {
8312        return container.childNodes[offset];
8313      }
8314      return null;
8315    };
8316    const getCaretCandidatePosition = (direction, node) => {
8317      if (isForwards(direction)) {
8318        if (isCaretCandidate(node.previousSibling) && !isText$3(node.previousSibling)) {
8319          return CaretPosition.before(node);
8320        }
8321        if (isText$3(node)) {
8322          return CaretPosition(node, 0);
8323        }
8324      }
8325      if (isBackwards(direction)) {
8326        if (isCaretCandidate(node.nextSibling) && !isText$3(node.nextSibling)) {
8327          return CaretPosition.after(node);
8328        }
8329        if (isText$3(node)) {
8330          return CaretPosition(node, node.data.length);
8331        }
8332      }
8333      if (isBackwards(direction)) {
8334        if (isBr$2(node)) {
8335          return CaretPosition.before(node);
8336        }
8337        return CaretPosition.after(node);
8338      }
8339      return CaretPosition.before(node);
8340    };
8341    const moveForwardFromBr = (root, nextNode) => {
8342      const nextSibling = nextNode.nextSibling;
8343      if (nextSibling && isCaretCandidate(nextSibling)) {
8344        if (isText$3(nextSibling)) {
8345          return CaretPosition(nextSibling, 0);
8346        } else {
8347          return CaretPosition.before(nextSibling);
8348        }
8349      } else {
8350        return findCaretPosition$1(1, CaretPosition.after(nextNode), root);
8351      }
8352    };
8353    const findCaretPosition$1 = (direction, startPos, root) => {
8354      let node;
8355      let nextNode;
8356      let innerNode;
8357      let caretPosition;
8358      if (!isElement$1(root) || !startPos) {
8359        return null;
8360      }
8361      if (startPos.isEqual(CaretPosition.after(root)) && root.lastChild) {
8362        caretPosition = CaretPosition.after(root.lastChild);
8363        if (isBackwards(direction) && isCaretCandidate(root.lastChild) && isElement$1(root.lastChild)) {
8364          return isBr$2(root.lastChild) ? CaretPosition.before(root.lastChild) : caretPosition;
8365        }
8366      } else {
8367        caretPosition = startPos;
8368      }
8369      const container = caretPosition.container();
8370      let offset = caretPosition.offset();
8371      if (isText$3(container)) {
8372        if (isBackwards(direction) && offset > 0) {
8373          return CaretPosition(container, --offset);
8374        }
8375        if (isForwards(direction) && offset < container.length) {
8376          return CaretPosition(container, ++offset);
8377        }
8378        node = container;
8379      } else {
8380        if (isBackwards(direction) && offset > 0) {
8381          nextNode = nodeAtIndex(container, offset - 1);
8382          if (isCaretCandidate(nextNode)) {
8383            if (!isAtomic(nextNode)) {
8384              innerNode = findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
8385              if (innerNode) {
8386                if (isText$3(innerNode)) {
8387                  return CaretPosition(innerNode, innerNode.data.length);
8388                }
8389                return CaretPosition.after(innerNode);
8390              }
8391            }
8392            if (isText$3(nextNode)) {
8393              return CaretPosition(nextNode, nextNode.data.length);
8394            }
8395            return CaretPosition.before(nextNode);
8396          }
8397        }
8398        if (isForwards(direction) && offset < container.childNodes.length) {
8399          nextNode = nodeAtIndex(container, offset);
8400          if (isCaretCandidate(nextNode)) {
8401            if (isBr$2(nextNode)) {
8402              return moveForwardFromBr(root, nextNode);
8403            }
8404            if (!isAtomic(nextNode)) {
8405              innerNode = findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
8406              if (innerNode) {
8407                if (isText$3(innerNode)) {
8408                  return CaretPosition(innerNode, 0);
8409                }
8410                return CaretPosition.before(innerNode);
8411              }
8412            }
8413            if (isText$3(nextNode)) {
8414              return CaretPosition(nextNode, 0);
8415            }
8416            return CaretPosition.after(nextNode);
8417          }
8418        }
8419        node = nextNode ? nextNode : caretPosition.getNode();
8420      }
vendor: 1,211 bytes, lines 8421-8447
8421      if (node && (isForwards(direction) && caretPosition.isAtEnd() || isBackwards(direction) && caretPosition.isAtStart())) {
8422        node = findNode(node, direction, always, root, true);
8423        if (isEditableCaretCandidate(node, root)) {
8424          return getCaretCandidatePosition(direction, node);
8425        }
8426      }
8427      nextNode = node ? findNode(node, direction, isEditableCaretCandidate, root) : node;
8428      const rootContentEditableFalseElm = last$1(filter$5(getParents$3(container, root), isContentEditableFalse$6));
8429      if (rootContentEditableFalseElm && (!nextNode || !rootContentEditableFalseElm.contains(nextNode))) {
8430        if (isForwards(direction)) {
8431          caretPosition = CaretPosition.after(rootContentEditableFalseElm);
8432        } else {
8433          caretPosition = CaretPosition.before(rootContentEditableFalseElm);
8434        }
8435        return caretPosition;
8436      }
8437      if (nextNode) {
8438        return getCaretCandidatePosition(direction, nextNode);
8439      }
8440      return null;
8441    };
8442    const CaretWalker = root => ({
8443      next: caretPosition => {
8444        return findCaretPosition$1(1, caretPosition, root);
8445      },
8446      prev: caretPosition => {
8447        return findCaretPosition$1(-1
vendor: 10,714 bytes, lines 8447-8727
8447, caretPosition, root);
8448      }
8449    });
8450
8451    const walkToPositionIn = (forward, root, start) => {
8452      const position = forward ? CaretPosition.before(start) : CaretPosition.after(start);
8453      return fromPosition(forward, root, position);
8454    };
8455    const afterElement = node => isBr$6(node) ? CaretPosition.before(node) : CaretPosition.after(node);
8456    const isBeforeOrStart = position => {
8457      if (CaretPosition.isTextPosition(position)) {
8458        return position.offset() === 0;
8459      } else {
8460        return isCaretCandidate$3(position.getNode());
8461      }
8462    };
8463    const isAfterOrEnd = position => {
8464      if (CaretPosition.isTextPosition(position)) {
8465        const container = position.container();
8466        return position.offset() === container.data.length;
8467      } else {
8468        return isCaretCandidate$3(position.getNode(true));
8469      }
8470    };
8471    const isBeforeAfterSameElement = (from, to) => !CaretPosition.isTextPosition(from) && !CaretPosition.isTextPosition(to) && from.getNode() === to.getNode(true);
8472    const isAtBr = position => !CaretPosition.isTextPosition(position) && isBr$6(position.getNode());
8473    const shouldSkipPosition = (forward, from, to) => {
8474      if (forward) {
8475        return !isBeforeAfterSameElement(from, to) && !isAtBr(from) && isAfterOrEnd(from) && isBeforeOrStart(to);
8476      } else {
8477        return !isBeforeAfterSameElement(to, from) && isBeforeOrStart(from) && isAfterOrEnd(to);
8478      }
8479    };
8480    const fromPosition = (forward, root, pos) => {
8481      const walker = CaretWalker(root);
8482      return Optional.from(forward ? walker.next(pos) : walker.prev(pos));
8483    };
8484    const navigate = (forward, root, from) => fromPosition(forward, root, from).bind(to => {
8485      if (isInSameBlock(from, to, root) && shouldSkipPosition(forward, from, to)) {
8486        return fromPosition(forward, root, to);
8487      } else {
8488        return Optional.some(to);
8489      }
8490    });
8491    const navigateIgnore = (forward, root, from, ignoreFilter) => navigate(forward, root, from).bind(pos => ignoreFilter(pos) ? navigateIgnore(forward, root, pos, ignoreFilter) : Optional.some(pos));
8492    const positionIn = (forward, element) => {
8493      const startNode = forward ? element.firstChild : element.lastChild;
8494      if (isText$b(startNode)) {
8495        return Optional.some(CaretPosition(startNode, forward ? 0 : startNode.data.length));
8496      } else if (startNode) {
8497        if (isCaretCandidate$3(startNode)) {
8498          return Optional.some(forward ? CaretPosition.before(startNode) : afterElement(startNode));
8499        } else {
8500          return walkToPositionIn(forward, element, startNode);
8501        }
8502      } else {
8503        return Optional.none();
8504      }
8505    };
8506    const nextPosition = curry(fromPosition, true);
8507    const prevPosition = curry(fromPosition, false);
8508    const firstPositionIn = curry(positionIn, true);
8509    const lastPositionIn = curry(positionIn, false);
8510
8511    const CARET_ID = '_mce_caret';
8512    const isCaretNode = node => isElement$6(node) && node.id === CARET_ID;
8513    const getParentCaretContainer = (body, node) => {
8514      let currentNode = node;
8515      while (currentNode && currentNode !== body) {
8516        if (isCaretNode(currentNode)) {
8517          return currentNode;
8518        }
8519        currentNode = currentNode.parentNode;
8520      }
8521      return null;
8522    };
8523
8524    const isStringPathBookmark = bookmark => isString(bookmark.start);
8525    const isRangeBookmark = bookmark => has$2(bookmark, 'rng');
8526    const isIdBookmark = bookmark => has$2(bookmark, 'id');
8527    const isIndexBookmark = bookmark => has$2(bookmark, 'name');
8528    const isPathBookmark = bookmark => Tools.isArray(bookmark.start);
8529
8530    const isForwardBookmark = bookmark => !isIndexBookmark(bookmark) && isBoolean(bookmark.forward) ? bookmark.forward : true;
8531    const addBogus = (dom, node) => {
8532      if (isElement$6(node) && dom.isBlock(node) && !node.innerHTML) {
8533        node.innerHTML = '<br data-mce-bogus="1" />';
8534      }
8535      return node;
8536    };
8537    const resolveCaretPositionBookmark = (dom, bookmark) => {
8538      const startPos = Optional.from(resolve$1(dom.getRoot(), bookmark.start));
8539      const endPos = Optional.from(resolve$1(dom.getRoot(), bookmark.end));
8540      return lift2(startPos, endPos, (start, end) => {
8541        const range = dom.createRng();
8542        range.setStart(start.container(), start.offset());
8543        range.setEnd(end.container(), end.offset());
8544        return {
8545          range,
8546          forward: isForwardBookmark(bookmark)
8547        };
8548      });
8549    };
8550    const insertZwsp = (node, rng) => {
8551      var _a;
8552      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
8553      const textNode = doc.createTextNode(ZWSP$1);
8554      node.appendChild(textNode);
8555      rng.setStart(textNode, 0);
8556      rng.setEnd(textNode, 0);
8557    };
8558    const isEmpty$1 = node => !node.hasChildNodes();
8559    const tryFindRangePosition = (node, rng) => lastPositionIn(node).fold(never, pos => {
8560      rng.setStart(pos.container(), pos.offset());
8561      rng.setEnd(pos.container(), pos.offset());
8562      return true;
8563    });
8564    const padEmptyCaretContainer = (root, node, rng) => {
8565      if (isEmpty$1(node) && getParentCaretContainer(root, node)) {
8566        insertZwsp(node, rng);
8567        return true;
8568      } else {
8569        return false;
8570      }
8571    };
8572    const setEndPoint = (dom, start, bookmark, rng) => {
8573      const point = bookmark[start ? 'start' : 'end'];
8574      const root = dom.getRoot();
8575      if (point) {
8576        let node = root;
8577        let offset = point[0];
8578        for (let i = point.length - 1; node && i >= 1; i--) {
8579          const children = node.childNodes;
8580          if (padEmptyCaretContainer(root, node, rng)) {
8581            return true;
8582          }
8583          if (point[i] > children.length - 1) {
8584            if (padEmptyCaretContainer(root, node, rng)) {
8585              return true;
8586            }
8587            return tryFindRangePosition(node, rng);
8588          }
8589          node = children[point[i]];
8590        }
8591        if (isText$b(node)) {
8592          offset = Math.min(point[0], node.data.length);
8593        }
8594        if (isElement$6(node)) {
8595          offset = Math.min(point[0], node.childNodes.length);
8596        }
8597        if (start) {
8598          rng.setStart(node, offset);
8599        } else {
8600          rng.setEnd(node, offset);
8601        }
8602      }
8603      return true;
8604    };
8605    const isValidTextNode = node => isText$b(node) && node.data.length > 0;
8606    const restoreEndPoint = (dom, suffix, bookmark) => {
8607      const marker = dom.get(bookmark.id + '_' + suffix);
8608      const markerParent = marker === null || marker === void 0 ? void 0 : marker.parentNode;
8609      const keep = bookmark.keep;
8610      if (marker && markerParent) {
8611        let container;
8612        let offset;
8613        if (suffix === 'start') {
8614          if (!keep) {
8615            container = markerParent;
8616            offset = dom.nodeIndex(marker);
8617          } else {
8618            if (marker.hasChildNodes()) {
8619              container = marker.firstChild;
8620              offset = 1;
8621            } else if (isValidTextNode(marker.nextSibling)) {
8622              container = marker.nextSibling;
8623              offset = 0;
8624            } else if (isValidTextNode(marker.previousSibling)) {
8625              container = marker.previousSibling;
8626              offset = marker.previousSibling.data.length;
8627            } else {
8628              container = markerParent;
8629              offset = dom.nodeIndex(marker) + 1;
8630            }
8631          }
8632        } else {
8633          if (!keep) {
8634            container = markerParent;
8635            offset = dom.nodeIndex(marker);
8636          } else {
8637            if (marker.hasChildNodes()) {
8638              container = marker.firstChild;
8639              offset = 1;
8640            } else if (isValidTextNode(marker.previousSibling)) {
8641              container = marker.previousSibling;
8642              offset = marker.previousSibling.data.length;
8643            } else {
8644              container = markerParent;
8645              offset = dom.nodeIndex(marker);
8646            }
8647          }
8648        }
8649        if (!keep) {
8650          const prev = marker.previousSibling;
8651          const next = marker.nextSibling;
8652          Tools.each(Tools.grep(marker.childNodes), node => {
8653            if (isText$b(node)) {
8654              node.data = node.data.replace(/\uFEFF/g, '');
8655            }
8656          });
8657          let otherMarker;
8658          while (otherMarker = dom.get(bookmark.id + '_' + suffix)) {
8659            dom.remove(otherMarker, true);
8660          }
8661          if (isText$b(next) && isText$b(prev) && !Env.browser.isOpera()) {
8662            const idx = prev.data.length;
8663            prev.appendData(next.data);
8664            dom.remove(next);
8665            container = prev;
8666            offset = idx;
8667          }
8668        }
8669        return Optional.some(CaretPosition(container, offset));
8670      } else {
8671        return Optional.none();
8672      }
8673    };
8674    const resolvePaths = (dom, bookmark) => {
8675      const range = dom.createRng();
8676      if (setEndPoint(dom, true, bookmark, range) && setEndPoint(dom, false, bookmark, range)) {
8677        return Optional.some({
8678          range,
8679          forward: isForwardBookmark(bookmark)
8680        });
8681      } else {
8682        return Optional.none();
8683      }
8684    };
8685    const resolveId = (dom, bookmark) => {
8686      const startPos = restoreEndPoint(dom, 'start', bookmark);
8687      const endPos = restoreEndPoint(dom, 'end', bookmark);
8688      return lift2(startPos, endPos.or(startPos), (spos, epos) => {
8689        const range = dom.createRng();
8690        range.setStart(addBogus(dom, spos.container()), spos.offset());
8691        range.setEnd(addBogus(dom, epos.container()), epos.offset());
8692        return {
8693          range,
8694          forward: isForwardBookmark(bookmark)
8695        };
8696      });
8697    };
8698    const resolveIndex = (dom, bookmark) => Optional.from(dom.select(bookmark.name)[bookmark.index]).map(elm => {
8699      const range = dom.createRng();
8700      range.selectNode(elm);
8701      return {
8702        range,
8703        forward: true
8704      };
8705    });
8706    const resolve = (selection, bookmark) => {
8707      const dom = selection.dom;
8708      if (bookmark) {
8709        if (isPathBookmark(bookmark)) {
8710          return resolvePaths(dom, bookmark);
8711        } else if (isStringPathBookmark(bookmark)) {
8712          return resolveCaretPositionBookmark(dom, bookmark);
8713        } else if (isIdBookmark(bookmark)) {
8714          return resolveId(dom, bookmark);
8715        } else if (isIndexBookmark(bookmark)) {
8716          return resolveIndex(dom, bookmark);
8717        } else if (isRangeBookmark(bookmark)) {
8718          return Optional.some({
8719            range: bookmark.rng,
8720            forward: isForwardBookmark(bookmark)
8721          });
8722        }
8723      }
8724      return Optional.none();
8725    };
8726
8727    const getBookmark$
87272 = (selection, type, normalized) => {
8728      return getBookmark$3
vendor: 15,457 bytes, lines 8728-9120
8728(selection, type, normalized);
8729    };
8730    const moveToBookmark = (selection, bookmark) => {
8731      resolve(selection, bookmark).each(({range, forward}) => {
8732        selection.setRng(range, forward);
8733      });
8734    };
8735    const isBookmarkNode$1 = node => {
8736      return isElement$6(node) && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
8737    };
8738
8739    const is = expected => actual => expected === actual;
8740    const isNbsp = is(nbsp);
8741    const isWhiteSpace = chr => chr !== '' && ' \f\n\r\t\x0B'.indexOf(chr) !== -1;
8742    const isContent = chr => !isWhiteSpace(chr) && !isNbsp(chr) && !isZwsp$2(chr);
8743
8744    const getRanges$1 = selection => {
8745      const ranges = [];
8746      if (selection) {
8747        for (let i = 0; i < selection.rangeCount; i++) {
8748          ranges.push(selection.getRangeAt(i));
8749        }
8750      }
8751      return ranges;
8752    };
8753    const getSelectedNodes = ranges => {
8754      return bind$3(ranges, range => {
8755        const node = getSelectedNode(range);
8756        return node ? [SugarElement.fromDom(node)] : [];
8757      });
8758    };
8759    const hasMultipleRanges = selection => {
8760      return getRanges$1(selection).length > 1;
8761    };
8762
8763    const getCellsFromRanges = ranges => filter$5(getSelectedNodes(ranges), isTableCell$2);
8764    const getCellsFromElement = elm => descendants(elm, 'td[data-mce-selected],th[data-mce-selected]');
8765    const getCellsFromElementOrRanges = (ranges, element) => {
8766      const selectedCells = getCellsFromElement(element);
8767      return selectedCells.length > 0 ? selectedCells : getCellsFromRanges(ranges);
8768    };
8769    const getCellsFromEditor = editor => getCellsFromElementOrRanges(getRanges$1(editor.selection.getSel()), SugarElement.fromDom(editor.getBody()));
8770    const getClosestTable = (cell, isRoot) => ancestor$3(cell, 'table', isRoot);
8771
8772    const getStartNode = rng => {
8773      const sc = rng.startContainer, so = rng.startOffset;
8774      if (isText$b(sc)) {
8775        return so === 0 ? Optional.some(SugarElement.fromDom(sc)) : Optional.none();
8776      } else {
8777        return Optional.from(sc.childNodes[so]).map(SugarElement.fromDom);
8778      }
8779    };
8780    const getEndNode = rng => {
8781      const ec = rng.endContainer, eo = rng.endOffset;
8782      if (isText$b(ec)) {
8783        return eo === ec.data.length ? Optional.some(SugarElement.fromDom(ec)) : Optional.none();
8784      } else {
8785        return Optional.from(ec.childNodes[eo - 1]).map(SugarElement.fromDom);
8786      }
8787    };
8788    const getFirstChildren = node => {
8789      return firstChild(node).fold(constant([node]), child => {
8790        return [node].concat(getFirstChildren(child));
8791      });
8792    };
8793    const getLastChildren = node => {
8794      return lastChild(node).fold(constant([node]), child => {
8795        if (name(child) === 'br') {
8796          return prevSibling(child).map(sibling => {
8797            return [node].concat(getLastChildren(sibling));
8798          }).getOr([]);
8799        } else {
8800          return [node].concat(getLastChildren(child));
8801        }
8802      });
8803    };
8804    const hasAllContentsSelected = (elm, rng) => {
8805      return lift2(getStartNode(rng), getEndNode(rng), (startNode, endNode) => {
8806        const start = find$2(getFirstChildren(elm), curry(eq, startNode));
8807        const end = find$2(getLastChildren(elm), curry(eq, endNode));
8808        return start.isSome() && end.isSome();
8809      }).getOr(false);
8810    };
8811    const moveEndPoint = (dom, rng, node, start) => {
8812      const root = node;
8813      const walker = new DomTreeWalker(node, root);
8814      const moveCaretBeforeOnEnterElementsMap = filter$4(dom.schema.getMoveCaretBeforeOnEnterElements(), (_, name) => !contains$2([
8815        'td',
8816        'th',
8817        'table'
8818      ], name.toLowerCase()));
8819      let currentNode = node;
8820      do {
8821        if (isText$b(currentNode) && Tools.trim(currentNode.data).length !== 0) {
8822          if (start) {
8823            rng.setStart(currentNode, 0);
8824          } else {
8825            rng.setEnd(currentNode, currentNode.data.length);
8826          }
8827          return;
8828        }
8829        if (moveCaretBeforeOnEnterElementsMap[currentNode.nodeName]) {
8830          if (start) {
8831            rng.setStartBefore(currentNode);
8832          } else {
8833            if (currentNode.nodeName === 'BR') {
8834              rng.setEndBefore(currentNode);
8835            } else {
8836              rng.setEndAfter(currentNode);
8837            }
8838          }
8839          return;
8840        }
8841      } while (currentNode = start ? walker.next() : walker.prev());
8842      if (root.nodeName === 'BODY') {
8843        if (start) {
8844          rng.setStart(root, 0);
8845        } else {
8846          rng.setEnd(root, root.childNodes.length);
8847        }
8848      }
8849    };
8850    const hasAnyRanges = editor => {
8851      const sel = editor.selection.getSel();
8852      return isNonNullable(sel) && sel.rangeCount > 0;
8853    };
8854    const runOnRanges = (editor, executor) => {
8855      const fakeSelectionNodes = getCellsFromEditor(editor);
8856      if (fakeSelectionNodes.length > 0) {
8857        each$e(fakeSelectionNodes, elem => {
8858          const node = elem.dom;
8859          const fakeNodeRng = editor.dom.createRng();
8860          fakeNodeRng.setStartBefore(node);
8861          fakeNodeRng.setEndAfter(node);
8862          executor(fakeNodeRng, true);
8863        });
8864      } else {
8865        executor(editor.selection.getRng(), false);
8866      }
8867    };
8868    const preserve = (selection, fillBookmark, executor) => {
8869      const bookmark = getPersistentBookmark(selection, fillBookmark);
8870      executor(bookmark);
8871      selection.moveToBookmark(bookmark);
8872    };
8873
8874    const isNode = node => isNumber(node === null || node === void 0 ? void 0 : node.nodeType);
8875    const isElementNode$1 = node => isElement$6(node) && !isBookmarkNode$1(node) && !isCaretNode(node) && !isBogus$1(node);
8876    const isElementDirectlySelected = (dom, node) => {
8877      if (isElementNode$1(node) && !/^(TD|TH)$/.test(node.nodeName)) {
8878        const selectedAttr = dom.getAttrib(node, 'data-mce-selected');
8879        const value = parseInt(selectedAttr, 10);
8880        return !isNaN(value) && value > 0;
8881      } else {
8882        return false;
8883      }
8884    };
8885    const preserveSelection = (editor, action, shouldMoveStart) => {
8886      const {selection, dom} = editor;
8887      const selectedNodeBeforeAction = selection.getNode();
8888      const isSelectedBeforeNodeNoneditable = isContentEditableFalse$b(selectedNodeBeforeAction);
8889      preserve(selection, true, () => {
8890        action();
8891      });
8892      const isBeforeNodeStillNoneditable = isSelectedBeforeNodeNoneditable && isContentEditableFalse$b(selectedNodeBeforeAction);
8893      if (isBeforeNodeStillNoneditable && dom.isChildOf(selectedNodeBeforeAction, editor.getBody())) {
8894        editor.selection.select(selectedNodeBeforeAction);
8895      } else if (shouldMoveStart(selection.getStart())) {
8896        moveStartToNearestText(dom, selection);
8897      }
8898    };
8899    const moveStartToNearestText = (dom, selection) => {
8900      var _a, _b;
8901      const rng = selection.getRng();
8902      const {startContainer, startOffset} = rng;
8903      const selectedNode = selection.getNode();
8904      if (isElementDirectlySelected(dom, selectedNode)) {
8905        return;
8906      }
8907      if (isElement$6(startContainer)) {
8908        const nodes = startContainer.childNodes;
8909        const root = dom.getRoot();
8910        let walker;
8911        if (startOffset < nodes.length) {
8912          const startNode = nodes[startOffset];
8913          walker = new DomTreeWalker(startNode, (_a = dom.getParent(startNode, dom.isBlock)) !== null && _a !== void 0 ? _a : root);
8914        } else {
8915          const startNode = nodes[nodes.length - 1];
8916          walker = new DomTreeWalker(startNode, (_b = dom.getParent(startNode, dom.isBlock)) !== null && _b !== void 0 ? _b : root);
8917          walker.next(true);
8918        }
8919        for (let node = walker.current(); node; node = walker.next()) {
8920          if (dom.getContentEditable(node) === 'false') {
8921            return;
8922          } else if (isText$b(node) && !isWhiteSpaceNode$1(node)) {
8923            rng.setStart(node, 0);
8924            selection.setRng(rng);
8925            return;
8926          }
8927        }
8928      }
8929    };
8930    const getNonWhiteSpaceSibling = (node, next, inc) => {
8931      if (node) {
8932        const nextName = next ? 'nextSibling' : 'previousSibling';
8933        for (node = inc ? node : node[nextName]; node; node = node[nextName]) {
8934          if (isElement$6(node) || !isWhiteSpaceNode$1(node)) {
8935            return node;
8936          }
8937        }
8938      }
8939      return undefined;
8940    };
8941    const isTextBlock$1 = (schema, node) => !!schema.getTextBlockElements()[node.nodeName.toLowerCase()] || isTransparentBlock(schema, node);
8942    const isValid = (ed, parent, child) => {
8943      return ed.schema.isValidChild(parent, child);
8944    };
8945    const isWhiteSpaceNode$1 = (node, allowSpaces = false) => {
8946      if (isNonNullable(node) && isText$b(node)) {
8947        const data = allowSpaces ? node.data.replace(/ /g, '\xA0') : node.data;
8948        return isWhitespaceText(data);
8949      } else {
8950        return false;
8951      }
8952    };
8953    const isEmptyTextNode$1 = node => {
8954      return isNonNullable(node) && isText$b(node) && node.length === 0;
8955    };
8956    const isWrapNoneditableTarget = (editor, node) => {
8957      const baseDataSelector = '[data-mce-cef-wrappable]';
8958      const formatNoneditableSelector = getFormatNoneditableSelector(editor);
8959      const selector = isEmpty$3(formatNoneditableSelector) ? baseDataSelector : `${ baseDataSelector },${ formatNoneditableSelector }`;
8960      return is$1(SugarElement.fromDom(node), selector);
8961    };
8962    const isWrappableNoneditable = (editor, node) => {
8963      const dom = editor.dom;
8964      return isElementNode$1(node) && dom.getContentEditable(node) === 'false' && isWrapNoneditableTarget(editor, node) && dom.select('[contenteditable="true"]', node).length === 0;
8965    };
8966    const replaceVars = (value, vars) => {
8967      if (isFunction(value)) {
8968        return value(vars);
8969      } else if (isNonNullable(vars)) {
8970        value = value.replace(/%(\w+)/g, (str, name) => {
8971          return vars[name] || str;
8972        });
8973      }
8974      return value;
8975    };
8976    const isEq$5 = (str1, str2) => {
8977      str1 = str1 || '';
8978      str2 = str2 || '';
8979      str1 = '' + (str1.nodeName || str1);
8980      str2 = '' + (str2.nodeName || str2);
8981      return str1.toLowerCase() === str2.toLowerCase();
8982    };
8983    const normalizeStyleValue = (value, name) => {
8984      if (isNullable(value)) {
8985        return null;
8986      } else {
8987        let strValue = String(value);
8988        if (name === 'color' || name === 'backgroundColor') {
8989          strValue = rgbaToHexString(strValue);
8990        }
8991        if (name === 'fontWeight' && value === 700) {
8992          strValue = 'bold';
8993        }
8994        if (name === 'fontFamily') {
8995          strValue = strValue.replace(/[\'\"]/g, '').replace(/,\s+/g, ',');
8996        }
8997        return strValue;
8998      }
8999    };
9000    const getStyle = (dom, node, name) => {
9001      const style = dom.getStyle(node, name);
9002      return normalizeStyleValue(style, name);
9003    };
9004    const getTextDecoration = (dom, node) => {
9005      let decoration;
9006      dom.getParent(node, n => {
9007        if (isElement$6(n)) {
9008          decoration = dom.getStyle(n, 'text-decoration');
9009          return !!decoration && decoration !== 'none';
9010        } else {
9011          return false;
9012        }
9013      });
9014      return decoration;
9015    };
9016    const getParents$2 = (dom, node, selector) => {
9017      return dom.getParents(node, selector, dom.getRoot());
9018    };
9019    const isFormatPredicate = (editor, formatName, predicate) => {
9020      const formats = editor.formatter.get(formatName);
9021      return isNonNullable(formats) && exists(formats, predicate);
9022    };
9023    const isVariableFormatName = (editor, formatName) => {
9024      const hasVariableValues = format => {
9025        const isVariableValue = val => isFunction(val) || val.length > 1 && val.charAt(0) === '%';
9026        return exists([
9027          'styles',
9028          'attributes'
9029        ], key => get$a(format, key).exists(field => {
9030          const fieldValues = isArray$1(field) ? field : values(field);
9031          return exists(fieldValues, isVariableValue);
9032        }));
9033      };
9034      return isFormatPredicate(editor, formatName, hasVariableValues);
9035    };
9036    const areSimilarFormats = (editor, formatName, otherFormatName) => {
9037      const validKeys = [
9038        'inline',
9039        'block',
9040        'selector',
9041        'attributes',
9042        'styles',
9043        'classes'
9044      ];
9045      const filterObj = format => filter$4(format, (_, key) => exists(validKeys, validKey => validKey === key));
9046      return isFormatPredicate(editor, formatName, fmt1 => {
9047        const filteredFmt1 = filterObj(fmt1);
9048        return isFormatPredicate(editor, otherFormatName, fmt2 => {
9049          const filteredFmt2 = filterObj(fmt2);
9050          return equal$1(filteredFmt1, filteredFmt2);
9051        });
9052      });
9053    };
9054    const isBlockFormat = format => hasNonNullableKey(format, 'block');
9055    const isWrappingBlockFormat = format => isBlockFormat(format) && format.wrapper === true;
9056    const isNonWrappingBlockFormat = format => isBlockFormat(format) && format.wrapper !== true;
9057    const isSelectorFormat = format => hasNonNullableKey(format, 'selector');
9058    const isInlineFormat = format => hasNonNullableKey(format, 'inline');
9059    const isMixedFormat = format => isSelectorFormat(format) && isInlineFormat(format) && is$2(get$a(format, 'mixed'), true);
9060    const shouldExpandToSelector = format => isSelectorFormat(format) && format.expand !== false && !isInlineFormat(format);
9061    const getEmptyCaretContainers = node => {
9062      const nodes = [];
9063      let tempNode = node;
9064      while (tempNode) {
9065        if (isText$b(tempNode) && tempNode.data !== ZWSP$1 || tempNode.childNodes.length > 1) {
9066          return [];
9067        }
9068        if (isElement$6(tempNode)) {
9069          nodes.push(tempNode);
9070        }
9071        tempNode = tempNode.firstChild;
9072      }
9073      return nodes;
9074    };
9075    const isCaretContainerEmpty = node => {
9076      return getEmptyCaretContainers(node).length > 0;
9077    };
9078    const isEmptyCaretFormatElement = element => {
9079      return isCaretNode(element.dom) && isCaretContainerEmpty(element.dom);
9080    };
9081
9082    const isBookmarkNode = isBookmarkNode$1;
9083    const getParents$1 = getParents$2;
9084    const isWhiteSpaceNode = isWhiteSpaceNode$1;
9085    const isTextBlock = isTextBlock$1;
9086    const isBogusBr = node => {
9087      return isBr$6(node) && node.getAttribute('data-mce-bogus') && !node.nextSibling;
9088    };
9089    const findParentContentEditable = (dom, node) => {
9090      let parent = node;
9091      while (parent) {
9092        if (isElement$6(parent) && dom.getContentEditable(parent)) {
9093          return dom.getContentEditable(parent) === 'false' ? parent : node;
9094        }
9095        parent = parent.parentNode;
9096      }
9097      return node;
9098    };
9099    const walkText = (start, node, offset, predicate) => {
9100      const str = node.data;
9101      if (start) {
9102        for (let i = offset; i > 0; i--) {
9103          if (predicate(str.charAt(i - 1))) {
9104            return i;
9105          }
9106        }
9107      } else {
9108        for (let i = offset; i < str.length; i++) {
9109          if (predicate(str.charAt(i))) {
9110            return i;
9111          }
9112        }
9113      }
9114      return -1;
9115    };
9116    const findSpace = (start, node, offset) => walkText(start, node, offset, c => isNbsp(c) || isWhiteSpace(c));
9117    const findContent = (start, node, offset) => walkText(start, node, offset, isContent);
9118    const findWordEndPoint = (dom, body, container, offset, start, includeTrailingSpaces) => {
9119      let lastTextNode;
9120      const 
vendor: 10,118 bytes, lines 9120-9350
9120closestRoot = dom.getParent(container, node => isEditingHost(node) || dom.isBlock(node));
9121      const rootNode = isNonNullable(closestRoot) ? closestRoot : body;
9122      const walk = (container, offset, pred) => {
9123        const textSeeker = TextSeeker(dom);
9124        const walker = start ? textSeeker.backwards : textSeeker.forwards;
9125        return Optional.from(walker(container, offset, (text, textOffset) => {
9126          if (isBookmarkNode(text.parentNode)) {
9127            return -1;
9128          } else {
9129            lastTextNode = text;
9130            return pred(start, text, textOffset);
9131          }
9132        }, rootNode));
9133      };
9134      const spaceResult = walk(container, offset, findSpace);
9135      return spaceResult.bind(result => includeTrailingSpaces ? walk(result.container, result.offset + (start ? -1 : 0), findContent) : Optional.some(result)).orThunk(() => lastTextNode ? Optional.some({
9136        container: lastTextNode,
9137        offset: start ? 0 : lastTextNode.length
9138      }) : Optional.none());
9139    };
9140    const findSelectorEndPoint = (dom, formatList, rng, container, siblingName) => {
9141      const sibling = container[siblingName];
9142      if (isText$b(container) && isEmpty$3(container.data) && sibling) {
9143        container = sibling;
9144      }
9145      const parents = getParents$1(dom, container);
9146      for (let i = 0; i < parents.length; i++) {
9147        for (let y = 0; y < formatList.length; y++) {
9148          const curFormat = formatList[y];
9149          if (isNonNullable(curFormat.collapsed) && curFormat.collapsed !== rng.collapsed) {
9150            continue;
9151          }
9152          if (isSelectorFormat(curFormat) && dom.is(parents[i], curFormat.selector)) {
9153            return parents[i];
9154          }
9155        }
9156      }
9157      return container;
9158    };
9159    const findBlockEndPoint = (dom, formatList, container, siblingName) => {
9160      var _a;
9161      let node = container;
9162      const root = dom.getRoot();
9163      const format = formatList[0];
9164      if (isBlockFormat(format)) {
9165        node = format.wrapper ? null : dom.getParent(container, format.block, root);
9166      }
9167      if (!node) {
9168        const scopeRoot = (_a = dom.getParent(container, 'LI,TD,TH,SUMMARY')) !== null && _a !== void 0 ? _a : root;
9169        node = dom.getParent(isText$b(container) ? container.parentNode : container, node => node !== root && isTextBlock(dom.schema, node), scopeRoot);
9170      }
9171      if (node && isBlockFormat(format) && format.wrapper) {
9172        node = getParents$1(dom, node, 'ul,ol').reverse()[0] || node;
9173      }
9174      if (!node) {
9175        node = container;
9176        while (node && node[siblingName] && !dom.isBlock(node[siblingName])) {
9177          node = node[siblingName];
9178          if (isEq$5(node, 'br')) {
9179            break;
9180          }
9181        }
9182      }
9183      return node || container;
9184    };
9185    const isAtBlockBoundary$1 = (dom, root, container, siblingName) => {
9186      const parent = container.parentNode;
9187      if (isNonNullable(container[siblingName])) {
9188        return false;
9189      } else if (parent === root || isNullable(parent) || dom.isBlock(parent)) {
9190        return true;
9191      } else {
9192        return isAtBlockBoundary$1(dom, root, parent, siblingName);
9193      }
9194    };
9195    const findParentContainer = (dom, formatList, container, offset, start, expandToBlock) => {
9196      let parent = container;
9197      const siblingName = start ? 'previousSibling' : 'nextSibling';
9198      const root = dom.getRoot();
9199      if (isText$b(container) && !isWhiteSpaceNode(container)) {
9200        if (start ? offset > 0 : offset < container.data.length) {
9201          return container;
9202        }
9203      }
9204      while (parent) {
9205        if (isEditingHost(parent)) {
9206          return container;
9207        }
9208        if (!formatList[0].block_expand && dom.isBlock(parent)) {
9209          return expandToBlock ? parent : container;
9210        }
9211        for (let sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
9212          const allowSpaces = isText$b(sibling) && !isAtBlockBoundary$1(dom, root, sibling, siblingName);
9213          if (!isBookmarkNode(sibling) && !isBogusBr(sibling) && !isWhiteSpaceNode(sibling, allowSpaces)) {
9214            return parent;
9215          }
9216        }
9217        if (parent === root || parent.parentNode === root) {
9218          container = parent;
9219          break;
9220        }
9221        parent = parent.parentNode;
9222      }
9223      return container;
9224    };
9225    const isSelfOrParentBookmark = container => isBookmarkNode(container.parentNode) || isBookmarkNode(container);
9226    const expandRng = (dom, rng, formatList, expandOptions = {}) => {
9227      const {includeTrailingSpace = false, expandToBlock = true} = expandOptions;
9228      const editableHost = dom.getParent(rng.commonAncestorContainer, node => isEditingHost(node));
9229      const root = isNonNullable(editableHost) ? editableHost : dom.getRoot();
9230      let {startContainer, startOffset, endContainer, endOffset} = rng;
9231      const format = formatList[0];
9232      if (isElement$6(startContainer) && startContainer.hasChildNodes()) {
9233        startContainer = getNode$1(startContainer, startOffset);
9234        if (isText$b(startContainer)) {
9235          startOffset = 0;
9236        }
9237      }
9238      if (isElement$6(endContainer) && endContainer.hasChildNodes()) {
9239        endContainer = getNode$1(endContainer, rng.collapsed ? endOffset : endOffset - 1);
9240        if (isText$b(endContainer)) {
9241          endOffset = endContainer.data.length;
9242        }
9243      }
9244      startContainer = findParentContentEditable(dom, startContainer);
9245      endContainer = findParentContentEditable(dom, endContainer);
9246      if (isSelfOrParentBookmark(startContainer)) {
9247        startContainer = isBookmarkNode(startContainer) ? startContainer : startContainer.parentNode;
9248        if (rng.collapsed) {
9249          startContainer = startContainer.previousSibling || startContainer;
9250        } else {
9251          startContainer = startContainer.nextSibling || startContainer;
9252        }
9253        if (isText$b(startContainer)) {
9254          startOffset = rng.collapsed ? startContainer.length : 0;
9255        }
9256      }
9257      if (isSelfOrParentBookmark(endContainer)) {
9258        endContainer = isBookmarkNode(endContainer) ? endContainer : endContainer.parentNode;
9259        if (rng.collapsed) {
9260          endContainer = endContainer.nextSibling || endContainer;
9261        } else {
9262          endContainer = endContainer.previousSibling || endContainer;
9263        }
9264        if (isText$b(endContainer)) {
9265          endOffset = rng.collapsed ? 0 : endContainer.length;
9266        }
9267      }
9268      if (rng.collapsed) {
9269        const startPoint = findWordEndPoint(dom, root, startContainer, startOffset, true, includeTrailingSpace);
9270        startPoint.each(({container, offset}) => {
9271          startContainer = container;
9272          startOffset = offset;
9273        });
9274        const endPoint = findWordEndPoint(dom, root, endContainer, endOffset, false, includeTrailingSpace);
9275        endPoint.each(({container, offset}) => {
9276          endContainer = container;
9277          endOffset = offset;
9278        });
9279      }
9280      if (isInlineFormat(format) || format.block_expand) {
9281        if (!isInlineFormat(format) || (!isText$b(startContainer) || startOffset === 0)) {
9282          startContainer = findParentContainer(dom, formatList, startContainer, startOffset, true, expandToBlock);
9283        }
9284        if (!isInlineFormat(format) || (!isText$b(endContainer) || endOffset === endContainer.data.length)) {
9285          endContainer = findParentContainer(dom, formatList, endContainer, endOffset, false, expandToBlock);
9286        }
9287      }
9288      if (shouldExpandToSelector(format)) {
9289        startContainer = findSelectorEndPoint(dom, formatList, rng, startContainer, 'previousSibling');
9290        endContainer = findSelectorEndPoint(dom, formatList, rng, endContainer, 'nextSibling');
9291      }
9292      if (isBlockFormat(format) || isSelectorFormat(format)) {
9293        startContainer = findBlockEndPoint(dom, formatList, startContainer, 'previousSibling');
9294        endContainer = findBlockEndPoint(dom, formatList, endContainer, 'nextSibling');
9295        if (isBlockFormat(format)) {
9296          if (!dom.isBlock(startContainer)) {
9297            startContainer = findParentContainer(dom, formatList, startContainer, startOffset, true, expandToBlock);
9298            if (isText$b(startContainer)) {
9299              startOffset = 0;
9300            }
9301          }
9302          if (!dom.isBlock(endContainer)) {
9303            endContainer = findParentContainer(dom, formatList, endContainer, endOffset, false, expandToBlock);
9304            if (isText$b(endContainer)) {
9305              endOffset = endContainer.data.length;
9306            }
9307          }
9308        }
9309      }
9310      if (isElement$6(startContainer) && startContainer.parentNode) {
9311        startOffset = dom.nodeIndex(startContainer);
9312        startContainer = startContainer.parentNode;
9313      }
9314      if (isElement$6(endContainer) && endContainer.parentNode) {
9315        endOffset = dom.nodeIndex(endContainer) + 1;
9316        endContainer = endContainer.parentNode;
9317      }
9318      return {
9319        startContainer,
9320        startOffset,
9321        endContainer,
9322        endOffset
9323      };
9324    };
9325
9326    const walk$3 = (dom, rng, callback) => {
9327      var _a;
9328      const startOffset = rng.startOffset;
9329      const startContainer = getNode$1(rng.startContainer, startOffset);
9330      const endOffset = rng.endOffset;
9331      const endContainer = getNode$1(rng.endContainer, endOffset - 1);
9332      const exclude = nodes => {
9333        const firstNode = nodes[0];
9334        if (isText$b(firstNode) && firstNode === startContainer && startOffset >= firstNode.data.length) {
9335          nodes.splice(0, 1);
9336        }
9337        const lastNode = nodes[nodes.length - 1];
9338        if (endOffset === 0 && nodes.length > 0 && lastNode === endContainer && isText$b(lastNode)) {
9339          nodes.splice(nodes.length - 1, 1);
9340        }
9341        return nodes;
9342      };
9343      const collectSiblings = (node, name, endNode) => {
9344        const siblings = [];
9345        for (; node && node !== endNode; node = node[name]) {
9346          siblings.push(node);
9347        }
9348        return siblings;
9349      };
9350      const findEndPoint = (node, root) => dom.getParent(node, node =>
vendor: 29,940 bytes, lines 9350-10171
9350 node.parentNode === root, root);
9351      const walkBoundary = (startNode, endNode, next) => {
9352        const siblingName = next ? 'nextSibling' : 'previousSibling';
9353        for (let node = startNode, parent = node.parentNode; node && node !== endNode; node = parent) {
9354          parent = node.parentNode;
9355          const siblings = collectSiblings(node === startNode ? node : node[siblingName], siblingName);
9356          if (siblings.length) {
9357            if (!next) {
9358              siblings.reverse();
9359            }
9360            callback(exclude(siblings));
9361          }
9362        }
9363      };
9364      if (startContainer === endContainer) {
9365        return callback(exclude([startContainer]));
9366      }
9367      const ancestor = (_a = dom.findCommonAncestor(startContainer, endContainer)) !== null && _a !== void 0 ? _a : dom.getRoot();
9368      if (dom.isChildOf(startContainer, endContainer)) {
9369        return walkBoundary(startContainer, ancestor, true);
9370      }
9371      if (dom.isChildOf(endContainer, startContainer)) {
9372        return walkBoundary(endContainer, ancestor);
9373      }
9374      const startPoint = findEndPoint(startContainer, ancestor) || startContainer;
9375      const endPoint = findEndPoint(endContainer, ancestor) || endContainer;
9376      walkBoundary(startContainer, startPoint, true);
9377      const siblings = collectSiblings(startPoint === startContainer ? startPoint : startPoint.nextSibling, 'nextSibling', endPoint === endContainer ? endPoint.nextSibling : endPoint);
9378      if (siblings.length) {
9379        callback(exclude(siblings));
9380      }
9381      walkBoundary(endContainer, endPoint);
9382    };
9383
9384    const validBlocks = [
9385      'pre[class*=language-][contenteditable="false"]',
9386      'figure.image',
9387      'div[data-ephox-embed-iri]',
9388      'div.tiny-pageembed',
9389      'div.mce-toc',
9390      'div[data-mce-toc]'
9391    ];
9392    const isZeroWidth = elem => isText$c(elem) && get$3(elem) === ZWSP$1;
9393    const context = (editor, elem, wrapName, nodeName) => parent(elem).fold(() => 'skipping', parent => {
9394      if (nodeName === 'br' || isZeroWidth(elem)) {
9395        return 'valid';
9396      } else if (isAnnotation(elem)) {
9397        return 'existing';
9398      } else if (isCaretNode(elem.dom)) {
9399        return 'caret';
9400      } else if (exists(validBlocks, selector => is$1(elem, selector))) {
9401        return 'valid-block';
9402      } else if (!isValid(editor, wrapName, nodeName) || !isValid(editor, name(parent), wrapName)) {
9403        return 'invalid-child';
9404      } else {
9405        return 'valid';
9406      }
9407    });
9408
9409    const applyWordGrab = (editor, rng) => {
9410      const r = expandRng(editor.dom, rng, [{ inline: 'span' }]);
9411      rng.setStart(r.startContainer, r.startOffset);
9412      rng.setEnd(r.endContainer, r.endOffset);
9413      editor.selection.setRng(rng);
9414    };
9415    const applyAnnotation = (elem, masterUId, data, annotationName, decorate, directAnnotation) => {
9416      const {uid = masterUId, ...otherData} = data;
9417      add$2(elem, annotation());
9418      set$4(elem, `${ dataAnnotationId() }`, uid);
9419      set$4(elem, `${ dataAnnotation() }`, annotationName);
9420      const {attributes = {}, classes = []} = decorate(uid, otherData);
9421      setAll$1(elem, attributes);
9422      add(elem, classes);
9423      if (directAnnotation) {
9424        if (classes.length > 0) {
9425          set$4(elem, `${ dataAnnotationClasses() }`, classes.join(','));
9426        }
9427        const attributeNames = keys(attributes);
9428        if (attributeNames.length > 0) {
9429          set$4(elem, `${ dataAnnotationAttributes() }`, attributeNames.join(','));
9430        }
9431      }
9432    };
9433    const removeDirectAnnotation = elem => {
9434      remove$6(elem, annotation());
9435      remove$9(elem, `${ dataAnnotationId() }`);
9436      remove$9(elem, `${ dataAnnotation() }`);
9437      remove$9(elem, `${ dataAnnotationActive() }`);
9438      const customAttrNames = getOpt(elem, `${ dataAnnotationAttributes() }`).map(names => names.split(',')).getOr([]);
9439      const customClasses = getOpt(elem, `${ dataAnnotationClasses() }`).map(names => names.split(',')).getOr([]);
9440      each$e(customAttrNames, name => remove$9(elem, name));
9441      remove$3(elem, customClasses);
9442      remove$9(elem, `${ dataAnnotationClasses() }`);
9443      remove$9(elem, `${ dataAnnotationAttributes() }`);
9444    };
9445    const makeAnnotation = (eDoc, uid, data, annotationName, decorate) => {
9446      const master = SugarElement.fromTag('span', eDoc);
9447      applyAnnotation(master, uid, data, annotationName, decorate, false);
9448      return master;
9449    };
9450    const annotate = (editor, rng, uid, annotationName, decorate, data) => {
9451      const newWrappers = [];
9452      const master = makeAnnotation(editor.getDoc(), uid, data, annotationName, decorate);
9453      const wrapper = value$2();
9454      const finishWrapper = () => {
9455        wrapper.clear();
9456      };
9457      const getOrOpenWrapper = () => wrapper.get().getOrThunk(() => {
9458        const nu = shallow$1(master);
9459        newWrappers.push(nu);
9460        wrapper.set(nu);
9461        return nu;
9462      });
9463      const processElements = elems => {
9464        each$e(elems, processElement);
9465      };
9466      const processElement = elem => {
9467        const ctx = context(editor, elem, 'span', name(elem));
9468        switch (ctx) {
9469        case 'invalid-child': {
9470            finishWrapper();
9471            const children = children$1(elem);
9472            processElements(children);
9473            finishWrapper();
9474            break;
9475          }
9476        case 'valid-block': {
9477            finishWrapper();
9478            applyAnnotation(elem, uid, data, annotationName, decorate, true);
9479            break;
9480          }
9481        case 'valid': {
9482            const w = getOrOpenWrapper();
9483            wrap$2(elem, w);
9484            break;
9485          }
9486        }
9487      };
9488      const processNodes = nodes => {
9489        const elems = map$3(nodes, SugarElement.fromDom);
9490        processElements(elems);
9491      };
9492      walk$3(editor.dom, rng, nodes => {
9493        finishWrapper();
9494        processNodes(nodes);
9495      });
9496      return newWrappers;
9497    };
9498    const annotateWithBookmark = (editor, name, settings, data) => {
9499      editor.undoManager.transact(() => {
9500        const selection = editor.selection;
9501        const initialRng = selection.getRng();
9502        const hasFakeSelection = getCellsFromEditor(editor).length > 0;
9503        const masterUid = generate$1('mce-annotation');
9504        if (initialRng.collapsed && !hasFakeSelection) {
9505          applyWordGrab(editor, initialRng);
9506        }
9507        if (selection.getRng().collapsed && !hasFakeSelection) {
9508          const wrapper = makeAnnotation(editor.getDoc(), masterUid, data, name, settings.decorate);
9509          set$1(wrapper, nbsp);
9510          selection.getRng().insertNode(wrapper.dom);
9511          selection.select(wrapper.dom);
9512        } else {
9513          preserve(selection, false, () => {
9514            runOnRanges(editor, selectionRng => {
9515              annotate(editor, selectionRng, masterUid, name, settings.decorate, data);
9516            });
9517          });
9518        }
9519      });
9520    };
9521
9522    const Annotator = editor => {
9523      const registry = create$b();
9524      setup$x(editor, registry);
9525      const changes = setup$y(editor, registry);
9526      const isSpan = isTag('span');
9527      const removeAnnotations = elements => {
9528        each$e(elements, element => {
9529          if (isSpan(element)) {
9530            unwrap(element);
9531          } else {
9532            removeDirectAnnotation(element);
9533          }
9534        });
9535      };
9536      return {
9537        register: (name, settings) => {
9538          registry.register(name, settings);
9539        },
9540        annotate: (name, data) => {
9541          registry.lookup(name).each(settings => {
9542            annotateWithBookmark(editor, name, settings, data);
9543          });
9544        },
9545        annotationChanged: (name, callback) => {
9546          changes.addListener(name, callback);
9547        },
9548        remove: name => {
9549          identify(editor, Optional.some(name)).each(({elements}) => {
9550            const bookmark = editor.selection.getBookmark();
9551            removeAnnotations(elements);
9552            editor.selection.moveToBookmark(bookmark);
9553          });
9554        },
9555        removeAll: name => {
9556          const bookmark = editor.selection.getBookmark();
9557          each$d(findAll(editor, name), (elements, _) => {
9558            removeAnnotations(elements);
9559          });
9560          editor.selection.moveToBookmark(bookmark);
9561        },
9562        getAll: name => {
9563          const directory = findAll(editor, name);
9564          return map$2(directory, elems => map$3(elems, elem => elem.dom));
9565        }
9566      };
9567    };
9568
9569    const BookmarkManager = selection => {
9570      return {
9571        getBookmark: curry(getBookmark$2, selection),
9572        moveToBookmark: curry(moveToBookmark, selection)
9573      };
9574    };
9575    BookmarkManager.isBookmarkNode = isBookmarkNode$1;
9576
9577    const isXYWithinRange = (clientX, clientY, range) => {
9578      if (range.collapsed) {
9579        return false;
9580      } else {
9581        return exists(range.getClientRects(), rect => containsXY(rect, clientX, clientY));
9582      }
9583    };
9584
9585    const getDocument = () => SugarElement.fromDom(document);
9586
9587    const focus$1 = (element, preventScroll = false) => element.dom.focus({ preventScroll });
9588    const hasFocus$1 = element => {
9589      const root = getRootNode(element).dom;
9590      return element.dom === root.activeElement;
9591    };
9592    const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
9593    const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom));
9594
9595    const create$9 = (start, soffset, finish, foffset) => ({
9596      start,
9597      soffset,
9598      finish,
9599      foffset
9600    });
9601    const SimRange = { create: create$9 };
9602
9603    const adt$3 = Adt.generate([
9604      { before: ['element'] },
9605      {
9606        on: [
9607          'element',
9608          'offset'
9609        ]
9610      },
9611      { after: ['element'] }
9612    ]);
9613    const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
9614    const getStart$2 = situ => situ.fold(identity, identity, identity);
9615    const before$1 = adt$3.before;
9616    const on = adt$3.on;
9617    const after$1 = adt$3.after;
9618    const Situ = {
9619      before: before$1,
9620      on,
9621      after: after$1,
9622      cata,
9623      getStart: getStart$2
9624    };
9625
9626    const adt$2 = Adt.generate([
9627      { domRange: ['rng'] },
9628      {
9629        relative: [
9630          'startSitu',
9631          'finishSitu'
9632        ]
9633      },
9634      {
9635        exact: [
9636          'start',
9637          'soffset',
9638          'finish',
9639          'foffset'
9640        ]
9641      }
9642    ]);
9643    const exactFromRange = simRange => adt$2.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
9644    const getStart$1 = selection => selection.match({
9645      domRange: rng => SugarElement.fromDom(rng.startContainer),
9646      relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
9647      exact: (start, _soffset, _finish, _foffset) => start
9648    });
9649    const domRange = adt$2.domRange;
9650    const relative = adt$2.relative;
9651    const exact = adt$2.exact;
9652    const getWin = selection => {
9653      const start = getStart$1(selection);
9654      return defaultView(start);
9655    };
9656    const range = SimRange.create;
9657    const SimSelection = {
9658      domRange,
9659      relative,
9660      exact,
9661      exactFromRange,
9662      getWin,
9663      range
9664    };
9665
9666    const clamp$1 = (offset, element) => {
9667      const max = isText$c(element) ? get$3(element).length : children$1(element).length + 1;
9668      if (offset > max) {
9669        return max;
9670      } else if (offset < 0) {
9671        return 0;
9672      }
9673      return offset;
9674    };
9675    const normalizeRng = rng => SimSelection.range(rng.start, clamp$1(rng.soffset, rng.start), rng.finish, clamp$1(rng.foffset, rng.finish));
9676    const isOrContains = (root, elm) => !isRestrictedNode(elm.dom) && (contains(root, elm) || eq(root, elm));
9677    const isRngInRoot = root => rng => isOrContains(root, rng.start) && isOrContains(root, rng.finish);
9678    const shouldStore = editor => editor.inline || Env.browser.isFirefox();
9679    const nativeRangeToSelectionRange = r => SimSelection.range(SugarElement.fromDom(r.startContainer), r.startOffset, SugarElement.fromDom(r.endContainer), r.endOffset);
9680    const readRange = win => {
9681      const selection = win.getSelection();
9682      const rng = !selection || selection.rangeCount === 0 ? Optional.none() : Optional.from(selection.getRangeAt(0));
9683      return rng.map(nativeRangeToSelectionRange);
9684    };
9685    const getBookmark$1 = root => {
9686      const win = defaultView(root);
9687      return readRange(win.dom).filter(isRngInRoot(root));
9688    };
9689    const validate = (root, bookmark) => Optional.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng);
9690    const bookmarkToNativeRng = bookmark => {
9691      const rng = document.createRange();
9692      try {
9693        rng.setStart(bookmark.start.dom, bookmark.soffset);
9694        rng.setEnd(bookmark.finish.dom, bookmark.foffset);
9695        return Optional.some(rng);
9696      } catch (_a) {
9697        return Optional.none();
9698      }
9699    };
9700    const store = editor => {
9701      const newBookmark = shouldStore(editor) ? getBookmark$1(SugarElement.fromDom(editor.getBody())) : Optional.none();
9702      editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
9703    };
9704    const getRng = editor => {
9705      const bookmark = editor.bookmark ? editor.bookmark : Optional.none();
9706      return bookmark.bind(x => validate(SugarElement.fromDom(editor.getBody()), x)).bind(bookmarkToNativeRng);
9707    };
9708    const restore = editor => {
9709      getRng(editor).each(rng => editor.selection.setRng(rng));
9710    };
9711
9712    const isEditorUIElement$1 = elm => {
9713      const className = elm.className.toString();
9714      return className.indexOf('tox-') !== -1 || className.indexOf('mce-') !== -1;
9715    };
9716    const FocusManager = { isEditorUIElement: isEditorUIElement$1 };
9717
9718    const wrappedSetTimeout = (callback, time) => {
9719      if (!isNumber(time)) {
9720        time = 0;
9721      }
9722      return setTimeout(callback, time);
9723    };
9724    const wrappedSetInterval = (callback, time) => {
9725      if (!isNumber(time)) {
9726        time = 0;
9727      }
9728      return setInterval(callback, time);
9729    };
9730    const Delay = {
9731      setEditorTimeout: (editor, callback, time) => {
9732        return wrappedSetTimeout(() => {
9733          if (!editor.removed) {
9734            callback();
9735          }
9736        }, time);
9737      },
9738      setEditorInterval: (editor, callback, time) => {
9739        const timer = wrappedSetInterval(() => {
9740          if (!editor.removed) {
9741            callback();
9742          } else {
9743            clearInterval(timer);
9744          }
9745        }, time);
9746        return timer;
9747      }
9748    };
9749
9750    const isManualNodeChange = e => {
9751      return e.type === 'nodechange' && e.selectionChange;
9752    };
9753    const registerPageMouseUp = (editor, throttledStore) => {
9754      const mouseUpPage = () => {
9755        throttledStore.throttle();
9756      };
9757      DOMUtils.DOM.bind(document, 'mouseup', mouseUpPage);
9758      editor.on('remove', () => {
9759        DOMUtils.DOM.unbind(document, 'mouseup', mouseUpPage);
9760      });
9761    };
9762    const registerMouseUp = (editor, throttledStore) => {
9763      editor.on('mouseup touchend', _e => {
9764        throttledStore.throttle();
9765      });
9766    };
9767    const registerEditorEvents = (editor, throttledStore) => {
9768      registerMouseUp(editor, throttledStore);
9769      editor.on('keyup NodeChange AfterSetSelectionRange', e => {
9770        if (!isManualNodeChange(e)) {
9771          store(editor);
9772        }
9773      });
9774    };
9775    const register$6 = editor => {
9776      const throttledStore = first$1(() => {
9777        store(editor);
9778      }, 0);
9779      editor.on('init', () => {
9780        if (editor.inline) {
9781          registerPageMouseUp(editor, throttledStore);
9782        }
9783        registerEditorEvents(editor, throttledStore);
9784      });
9785      editor.on('remove', () => {
9786        throttledStore.cancel();
9787      });
9788    };
9789
9790    let documentFocusInHandler;
9791    const DOM$9 = DOMUtils.DOM;
9792    const isEditorUIElement = elm => {
9793      return isElement$6(elm) && FocusManager.isEditorUIElement(elm);
9794    };
9795    const isEditorContentAreaElement = elm => {
9796      const classList = elm.classList;
9797      if (classList !== undefined) {
9798        return classList.contains('tox-edit-area') || classList.contains('tox-edit-area__iframe') || classList.contains('mce-content-body');
9799      } else {
9800        return false;
9801      }
9802    };
9803    const isUIElement = (editor, elm) => {
9804      const customSelector = getCustomUiSelector(editor);
9805      const parent = DOM$9.getParent(elm, elm => {
9806        return isEditorUIElement(elm) || (customSelector ? editor.dom.is(elm, customSelector) : false);
9807      });
9808      return parent !== null;
9809    };
9810    const getActiveElement = editor => {
9811      try {
9812        const root = getRootNode(SugarElement.fromDom(editor.getElement()));
9813        return active$1(root).fold(() => document.body, x => x.dom);
9814      } catch (_a) {
9815        return document.body;
9816      }
9817    };
9818    const registerEvents$1 = (editorManager, e) => {
9819      const editor = e.editor;
9820      register$6(editor);
9821      const toggleContentAreaOnFocus = (editor, fn) => {
9822        if (shouldHighlightOnFocus(editor) && editor.inline !== true) {
9823          const contentArea = SugarElement.fromDom(editor.getContainer());
9824          fn(contentArea, 'tox-edit-focus');
9825        }
9826      };
9827      editor.on('focusin', () => {
9828        const focusedEditor = editorManager.focusedEditor;
9829        if (isEditorContentAreaElement(getActiveElement(editor))) {
9830          toggleContentAreaOnFocus(editor, add$2);
9831        }
9832        if (focusedEditor !== editor) {
9833          if (focusedEditor) {
9834            focusedEditor.dispatch('blur', { focusedEditor: editor });
9835          }
9836          editorManager.setActive(editor);
9837          editorManager.focusedEditor = editor;
9838          editor.dispatch('focus', { blurredEditor: focusedEditor });
9839          editor.focus(true);
9840        }
9841      });
9842      editor.on('focusout', () => {
9843        Delay.setEditorTimeout(editor, () => {
9844          const focusedEditor = editorManager.focusedEditor;
9845          if (!isEditorContentAreaElement(getActiveElement(editor)) || focusedEditor !== editor) {
9846            toggleContentAreaOnFocus(editor, remove$6);
9847          }
9848          if (!isUIElement(editor, getActiveElement(editor)) && focusedEditor === editor) {
9849            editor.dispatch('blur', { focusedEditor: null });
9850            editorManager.focusedEditor = null;
9851          }
9852        });
9853      });
9854      if (!documentFocusInHandler) {
9855        documentFocusInHandler = e => {
9856          const activeEditor = editorManager.activeEditor;
9857          if (activeEditor) {
9858            getOriginalEventTarget(e).each(target => {
9859              const elem = target;
9860              if (elem.ownerDocument === document) {
9861                if (elem !== document.body && !isUIElement(activeEditor, elem) && editorManager.focusedEditor === activeEditor) {
9862                  activeEditor.dispatch('blur', { focusedEditor: null });
9863                  editorManager.focusedEditor = null;
9864                }
9865              }
9866            });
9867          }
9868        };
9869        DOM$9.bind(document, 'focusin', documentFocusInHandler);
9870      }
9871    };
9872    const unregisterDocumentEvents = (editorManager, e) => {
9873      if (editorManager.focusedEditor === e.editor) {
9874        editorManager.focusedEditor = null;
9875      }
9876      if (!editorManager.activeEditor && documentFocusInHandler) {
9877        DOM$9.unbind(document, 'focusin', documentFocusInHandler);
9878        documentFocusInHandler = null;
9879      }
9880    };
9881    const setup$w = editorManager => {
9882      editorManager.on('AddEditor', curry(registerEvents$1, editorManager));
9883      editorManager.on('RemoveEditor', curry(unregisterDocumentEvents, editorManager));
9884    };
9885
9886    const getContentEditableHost = (editor, node) => editor.dom.getParent(node, node => editor.dom.getContentEditable(node) === 'true');
9887    const hasContentEditableFalseParent$1 = (editor, node) => editor.dom.getParent(node, node => editor.dom.getContentEditable(node) === 'false') !== null;
9888    const getCollapsedNode = rng => rng.collapsed ? Optional.from(getNode$1(rng.startContainer, rng.startOffset)).map(SugarElement.fromDom) : Optional.none();
9889    const getFocusInElement = (root, rng) => getCollapsedNode(rng).bind(node => {
9890      if (isTableSection(node)) {
9891        return Optional.some(node);
9892      } else if (!contains(root, node)) {
9893        return Optional.some(root);
9894      } else {
9895        return Optional.none();
9896      }
9897    });
9898    const normalizeSelection = (editor, rng) => {
9899      getFocusInElement(SugarElement.fromDom(editor.getBody()), rng).bind(elm => {
9900        return firstPositionIn(elm.dom);
9901      }).fold(() => {
9902        editor.selection.normalize();
9903      }, caretPos => editor.selection.setRng(caretPos.toRange()));
9904    };
9905    const focusBody = body => {
9906      if (body.setActive) {
9907        try {
9908          body.setActive();
9909        } catch (_a) {
9910          body.focus();
9911        }
9912      } else {
9913        body.focus();
9914      }
9915    };
9916    const hasElementFocus = elm => hasFocus$1(elm) || search(elm).isSome();
9917    const hasIframeFocus = editor => isNonNullable(editor.iframeElement) && hasFocus$1(SugarElement.fromDom(editor.iframeElement));
9918    const hasInlineFocus = editor => {
9919      const rawBody = editor.getBody();
9920      return rawBody && hasElementFocus(SugarElement.fromDom(rawBody));
9921    };
9922    const hasUiFocus = editor => {
9923      const dos = getRootNode(SugarElement.fromDom(editor.getElement()));
9924      return active$1(dos).filter(elem => !isEditorContentAreaElement(elem.dom) && isUIElement(editor, elem.dom)).isSome();
9925    };
9926    const hasFocus = editor => editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor);
9927    const hasEditorOrUiFocus = editor => hasFocus(editor) || hasUiFocus(editor);
9928    const focusEditor = editor => {
9929      const selection = editor.selection;
9930      const body = editor.getBody();
9931      let rng = selection.getRng();
9932      editor.quirks.refreshContentEditable();
9933      const restoreBookmark = editor => {
9934        getRng(editor).each(bookmarkRng => {
9935          editor.selection.setRng(bookmarkRng);
9936          rng = bookmarkRng;
9937        });
9938      };
9939      if (!hasFocus(editor) && editor.hasEditableRoot()) {
9940        restoreBookmark(editor);
9941      }
9942      const contentEditableHost = getContentEditableHost(editor, selection.getNode());
9943      if (contentEditableHost && editor.dom.isChildOf(contentEditableHost, body)) {
9944        if (!hasContentEditableFalseParent$1(editor, contentEditableHost)) {
9945          focusBody(body);
9946        }
9947        focusBody(contentEditableHost);
9948        if (!editor.hasEditableRoot()) {
9949          restoreBookmark(editor);
9950        }
9951        normalizeSelection(editor, rng);
9952        activateEditor(editor);
9953        return;
9954      }
9955      if (!editor.inline) {
9956        if (!Env.browser.isOpera()) {
9957          focusBody(body);
9958        }
9959        editor.getWin().focus();
9960      }
9961      if (Env.browser.isFirefox() || editor.inline) {
9962        focusBody(body);
9963        normalizeSelection(editor, rng);
9964      }
9965      activateEditor(editor);
9966    };
9967    const activateEditor = editor => editor.editorManager.setActive(editor);
9968    const focus = (editor, skipFocus) => {
9969      if (editor.removed) {
9970        return;
9971      }
9972      if (skipFocus) {
9973        activateEditor(editor);
9974      } else {
9975        focusEditor(editor);
9976      }
9977    };
9978
9979    const VK = {
9980      BACKSPACE: 8,
9981      DELETE: 46,
9982      DOWN: 40,
9983      ENTER: 13,
9984      ESC: 27,
9985      LEFT: 37,
9986      RIGHT: 39,
9987      SPACEBAR: 32,
9988      TAB: 9,
9989      UP: 38,
9990      PAGE_UP: 33,
9991      PAGE_DOWN: 34,
9992      END: 35,
9993      HOME: 36,
9994      modifierPressed: e => {
9995        return e.shiftKey || e.ctrlKey || e.altKey || VK.metaKeyPressed(e);
9996      },
9997      metaKeyPressed: e => {
9998        return Env.os.isMacOS() || Env.os.isiOS() ? e.metaKey : e.ctrlKey && !e.altKey;
9999      }
10000    };
10001
10002    const elementSelectionAttr = 'data-mce-selected';
10003    const controlElmSelector = 'table,img,figure.image,hr,video,span.mce-preview-object,details';
10004    const abs = Math.abs;
10005    const round$1 = Math.round;
10006    const resizeHandles = {
10007      nw: [
10008        0,
10009        0,
10010        -1,
10011        -1
10012      ],
10013      ne: [
10014        1,
10015        0,
10016        1,
10017        -1
10018      ],
10019      se: [
10020        1,
10021        1,
10022        1,
10023        1
10024      ],
10025      sw: [
10026        0,
10027        1,
10028        -1,
10029        1
10030      ]
10031    };
10032    const isTouchEvent = evt => evt.type === 'longpress' || evt.type.indexOf('touch') === 0;
10033    const ControlSelection = (selection, editor) => {
10034      const dom = editor.dom;
10035      const editableDoc = editor.getDoc();
10036      const rootDocument = document;
10037      const rootElement = editor.getBody();
10038      let selectedElm, selectedElmGhost, resizeHelper, selectedHandle, resizeBackdrop;
10039      let startX, startY, startW, startH, ratio, resizeStarted;
10040      let width;
10041      let height;
10042      let startScrollWidth;
10043      let startScrollHeight;
10044      const isImage = elm => isNonNullable(elm) && (isImg(elm) || dom.is(elm, 'figure.image'));
10045      const isMedia = elm => isMedia$2(elm) || dom.hasClass(elm, 'mce-preview-object');
10046      const isEventOnImageOutsideRange = (evt, range) => {
10047        if (isTouchEvent(evt)) {
10048          const touch = evt.touches[0];
10049          return isImage(evt.target) && !isXYWithinRange(touch.clientX, touch.clientY, range);
10050        } else {
10051          return isImage(evt.target) && !isXYWithinRange(evt.clientX, evt.clientY, range);
10052        }
10053      };
10054      const contextMenuSelectImage = evt => {
10055        const target = evt.target;
10056        if (isEventOnImageOutsideRange(evt, editor.selection.getRng()) && !evt.isDefaultPrevented()) {
10057          editor.selection.select(target);
10058        }
10059      };
10060      const getResizeTargets = elm => {
10061        if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
10062          return [
10063            elm,
10064            elm.firstElementChild
10065          ];
10066        } else if (dom.is(elm, 'figure.image')) {
10067          return [elm.querySelector('img')];
10068        } else {
10069          return [elm];
10070        }
10071      };
10072      const isResizable = elm => {
10073        const selector = getObjectResizing(editor);
10074        if (!selector || editor.mode.isReadOnly()) {
10075          return false;
10076        }
10077        if (elm.getAttribute('data-mce-resize') === 'false') {
10078          return false;
10079        }
10080        if (elm === editor.getBody()) {
10081          return false;
10082        }
10083        if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
10084          return is$1(SugarElement.fromDom(elm.firstElementChild), selector);
10085        } else {
10086          return is$1(SugarElement.fromDom(elm), selector);
10087        }
10088      };
10089      const createGhostElement = (dom, elm) => {
10090        if (isMedia(elm)) {
10091          return dom.create('img', { src: Env.transparentSrc });
10092        } else if (isTable$2(elm)) {
10093          const isNorth = startsWith(selectedHandle.name, 'n');
10094          const rowSelect = isNorth ? head : last$2;
10095          const tableElm = elm.cloneNode(true);
10096          rowSelect(dom.select('tr', tableElm)).each(tr => {
10097            const cells = dom.select('td,th', tr);
10098            dom.setStyle(tr, 'height', null);
10099            each$e(cells, cell => dom.setStyle(cell, 'height', null));
10100          });
10101          return tableElm;
10102        } else {
10103          return elm.cloneNode(true);
10104        }
10105      };
10106      const setSizeProp = (element, name, value) => {
10107        if (isNonNullable(value)) {
10108          const targets = getResizeTargets(element);
10109          each$e(targets, target => {
10110            if (target.style[name] || !editor.schema.isValid(target.nodeName.toLowerCase(), name)) {
10111              dom.setStyle(target, name, value);
10112            } else {
10113              dom.setAttrib(target, name, '' + value);
10114            }
10115          });
10116        }
10117      };
10118      const setGhostElmSize = (ghostElm, width, height) => {
10119        setSizeProp(ghostElm, 'width', width);
10120        setSizeProp(ghostElm, 'height', height);
10121      };
10122      const resizeGhostElement = e => {
10123        let deltaX, deltaY, proportional;
10124        let resizeHelperX, resizeHelperY;
10125        deltaX = e.screenX - startX;
10126        deltaY = e.screenY - startY;
10127        width = deltaX * selectedHandle[2] + startW;
10128        height = deltaY * selectedHandle[3] + startH;
10129        width = width < 5 ? 5 : width;
10130        height = height < 5 ? 5 : height;
10131        if ((isImage(selectedElm) || isMedia(selectedElm)) && getResizeImgProportional(editor) !== false) {
10132          proportional = !VK.modifierPressed(e);
10133        } else {
10134          proportional = VK.modifierPressed(e);
10135        }
10136        if (proportional) {
10137          if (abs(deltaX) > abs(deltaY)) {
10138            height = round$1(width * ratio);
10139            width = round$1(height / ratio);
10140          } else {
10141            width = round$1(height / ratio);
10142            height = round$1(width * ratio);
10143          }
10144        }
10145        setGhostElmSize(selectedElmGhost, width, height);
10146        resizeHelperX = selectedHandle.startPos.x + deltaX;
10147        resizeHelperY = selectedHandle.startPos.y + deltaY;
10148        resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
10149        resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
10150        dom.setStyles(resizeHelper, {
10151          left: resizeHelperX,
10152          top: resizeHelperY,
10153          display: 'block'
10154        });
10155        resizeHelper.innerHTML = width + ' &times; ' + height;
10156        deltaX = rootElement.scrollWidth - startScrollWidth;
10157        deltaY = rootElement.scrollHeight - startScrollHeight;
10158        if (deltaX + deltaY !== 0) {
10159          dom.setStyles(resizeHelper, {
10160            left: resizeHelperX - deltaX,
10161            top: resizeHelperY - deltaY
10162          });
10163        }
10164        if (!resizeStarted) {
10165          fireObjectResizeStart(editor, selectedElm, startW, startH, 'corner-' + selectedHandle.name);
10166          resizeStarted = true;
10167        }
10168      };
10169      const endGhostResize = () => {
10170        const wasResizeStarted = resizeStarted;
10171        resizeStarted = false;
vendor: 4,776 bytes, lines 10172-10279
10172        if (wasResizeStarted) {
10173          setSizeProp(selectedElm, 'width', width);
10174          setSizeProp(selectedElm, 'height', height);
10175        }
10176        dom.unbind(editableDoc, 'mousemove', resizeGhostElement);
10177        dom.unbind(editableDoc, 'mouseup', endGhostResize);
10178        if (rootDocument !== editableDoc) {
10179          dom.unbind(rootDocument, 'mousemove', resizeGhostElement);
10180          dom.unbind(rootDocument, 'mouseup', endGhostResize);
10181        }
10182        dom.remove(selectedElmGhost);
10183        dom.remove(resizeHelper);
10184        dom.remove(resizeBackdrop);
10185        showResizeRect(selectedElm);
10186        if (wasResizeStarted) {
10187          fireObjectResized(editor, selectedElm, width, height, 'corner-' + selectedHandle.name);
10188          dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
10189        }
10190        editor.nodeChanged();
10191      };
10192      const showResizeRect = targetElm => {
10193        unbindResizeHandleEvents();
10194        const position = dom.getPos(targetElm, rootElement);
10195        const selectedElmX = position.x;
10196        const selectedElmY = position.y;
10197        const rect = targetElm.getBoundingClientRect();
10198        const targetWidth = rect.width || rect.right - rect.left;
10199        const targetHeight = rect.height || rect.bottom - rect.top;
10200        if (selectedElm !== targetElm) {
10201          hideResizeRect();
10202          selectedElm = targetElm;
10203          width = height = 0;
10204        }
10205        const e = editor.dispatch('ObjectSelected', { target: targetElm });
10206        if (isResizable(targetElm) && !e.isDefaultPrevented()) {
10207          each$d(resizeHandles, (handle, name) => {
10208            const startDrag = e => {
10209              const target = getResizeTargets(selectedElm)[0];
10210              startX = e.screenX;
10211              startY = e.screenY;
10212              startW = target.clientWidth;
10213              startH = target.clientHeight;
10214              ratio = startH / startW;
10215              selectedHandle = handle;
10216              selectedHandle.name = name;
10217              selectedHandle.startPos = {
10218                x: targetWidth * handle[0] + selectedElmX,
10219                y: targetHeight * handle[1] + selectedElmY
10220              };
10221              startScrollWidth = rootElement.scrollWidth;
10222              startScrollHeight = rootElement.scrollHeight;
10223              resizeBackdrop = dom.add(rootElement, 'div', {
10224                'class': 'mce-resize-backdrop',
10225                'data-mce-bogus': 'all'
10226              });
10227              dom.setStyles(resizeBackdrop, {
10228                position: 'fixed',
10229                left: '0',
10230                top: '0',
10231                width: '100%',
10232                height: '100%'
10233              });
10234              selectedElmGhost = createGhostElement(dom, selectedElm);
10235              dom.addClass(selectedElmGhost, 'mce-clonedresizable');
10236              dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all');
10237              selectedElmGhost.contentEditable = 'false';
10238              dom.setStyles(selectedElmGhost, {
10239                left: selectedElmX,
10240                top: selectedElmY,
10241                margin: 0
10242              });
10243              setGhostElmSize(selectedElmGhost, targetWidth, targetHeight);
10244              selectedElmGhost.removeAttribute(elementSelectionAttr);
10245              rootElement.appendChild(selectedElmGhost);
10246              dom.bind(editableDoc, 'mousemove', resizeGhostElement);
10247              dom.bind(editableDoc, 'mouseup', endGhostResize);
10248              if (rootDocument !== editableDoc) {
10249                dom.bind(rootDocument, 'mousemove', resizeGhostElement);
10250                dom.bind(rootDocument, 'mouseup', endGhostResize);
10251              }
10252              resizeHelper = dom.add(rootElement, 'div', {
10253                'class': 'mce-resize-helper',
10254                'data-mce-bogus': 'all'
10255              }, startW + ' &times; ' + startH);
10256            };
10257            let handleElm = dom.get('mceResizeHandle' + name);
10258            if (handleElm) {
10259              dom.remove(handleElm);
10260            }
10261            handleElm = dom.add(rootElement, 'div', {
10262              'id': 'mceResizeHandle' + name,
10263              'data-mce-bogus': 'all',
10264              'class': 'mce-resizehandle',
10265              'unselectable': true,
10266              'style': 'cursor:' + name + '-resize; margin:0; padding:0'
10267            });
10268            dom.bind(handleElm, 'mousedown', e => {
10269              e.stopImmediatePropagation();
10270              e.preventDefault();
10271              startDrag(e);
10272            });
10273            handle.elm = handleElm;
10274            dom.setStyles(handleElm, {
10275              left: targetWidth * handle[0] + selectedElmX - handleElm.offsetWidth / 2,
10276              top: targetHeight * handle[1] + selectedElmY - handleElm.offsetHeight / 2
10277            });
10278          });
10279        } else {
vendor: 21,699 bytes, lines 10280-10857
10280          hideResizeRect(false);
10281        }
10282      };
10283      const throttledShowResizeRect = first$1(showResizeRect, 0);
10284      const hideResizeRect = (removeSelected = true) => {
10285        throttledShowResizeRect.cancel();
10286        unbindResizeHandleEvents();
10287        if (selectedElm && removeSelected) {
10288          selectedElm.removeAttribute(elementSelectionAttr);
10289        }
10290        each$d(resizeHandles, (value, name) => {
10291          const handleElm = dom.get('mceResizeHandle' + name);
10292          if (handleElm) {
10293            dom.unbind(handleElm);
10294            dom.remove(handleElm);
10295          }
10296        });
10297      };
10298      const isChildOrEqual = (node, parent) => dom.isChildOf(node, parent);
10299      const updateResizeRect = e => {
10300        if (resizeStarted || editor.removed || editor.composing) {
10301          return;
10302        }
10303        const targetElm = e.type === 'mousedown' ? e.target : selection.getNode();
10304        const controlElm = closest$3(SugarElement.fromDom(targetElm), controlElmSelector).map(e => e.dom).filter(e => dom.isEditable(e.parentElement) || e.nodeName === 'IMG' && dom.isEditable(e)).getOrUndefined();
10305        const selectedValue = isNonNullable(controlElm) ? dom.getAttrib(controlElm, elementSelectionAttr, '1') : '1';
10306        each$e(dom.select(`img[${ elementSelectionAttr }],hr[${ elementSelectionAttr }]`), img => {
10307          img.removeAttribute(elementSelectionAttr);
10308        });
10309        if (isNonNullable(controlElm) && isChildOrEqual(controlElm, rootElement) && hasEditorOrUiFocus(editor)) {
10310          disableGeckoResize();
10311          const startElm = selection.getStart(true);
10312          if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
10313            dom.setAttrib(controlElm, elementSelectionAttr, selectedValue);
10314            throttledShowResizeRect.throttle(controlElm);
10315            return;
10316          }
10317        }
10318        hideResizeRect();
10319      };
10320      const unbindResizeHandleEvents = () => {
10321        each$d(resizeHandles, handle => {
10322          if (handle.elm) {
10323            dom.unbind(handle.elm);
10324            delete handle.elm;
10325          }
10326        });
10327      };
10328      const disableGeckoResize = () => {
10329        try {
10330          editor.getDoc().execCommand('enableObjectResizing', false, 'false');
10331        } catch (_a) {
10332        }
10333      };
10334      editor.on('init', () => {
10335        disableGeckoResize();
10336        editor.on('NodeChange ResizeEditor ResizeWindow ResizeContent drop', updateResizeRect);
10337        editor.on('keyup compositionend', e => {
10338          if (selectedElm && selectedElm.nodeName === 'TABLE') {
10339            updateResizeRect(e);
10340          }
10341        });
10342        editor.on('hide blur', hideResizeRect);
10343        editor.on('contextmenu longpress', contextMenuSelectImage, true);
10344      });
10345      editor.on('remove', unbindResizeHandleEvents);
10346      const destroy = () => {
10347        throttledShowResizeRect.cancel();
10348        selectedElm = selectedElmGhost = resizeBackdrop = null;
10349      };
10350      return {
10351        isResizable,
10352        showResizeRect,
10353        hideResizeRect,
10354        updateResizeRect,
10355        destroy
10356      };
10357    };
10358
10359    const setStart = (rng, situ) => {
10360      situ.fold(e => {
10361        rng.setStartBefore(e.dom);
10362      }, (e, o) => {
10363        rng.setStart(e.dom, o);
10364      }, e => {
10365        rng.setStartAfter(e.dom);
10366      });
10367    };
10368    const setFinish = (rng, situ) => {
10369      situ.fold(e => {
10370        rng.setEndBefore(e.dom);
10371      }, (e, o) => {
10372        rng.setEnd(e.dom, o);
10373      }, e => {
10374        rng.setEndAfter(e.dom);
10375      });
10376    };
10377    const relativeToNative = (win, startSitu, finishSitu) => {
10378      const range = win.document.createRange();
10379      setStart(range, startSitu);
10380      setFinish(range, finishSitu);
10381      return range;
10382    };
10383    const exactToNative = (win, start, soffset, finish, foffset) => {
10384      const rng = win.document.createRange();
10385      rng.setStart(start.dom, soffset);
10386      rng.setEnd(finish.dom, foffset);
10387      return rng;
10388    };
10389
10390    const adt$1 = Adt.generate([
10391      {
10392        ltr: [
10393          'start',
10394          'soffset',
10395          'finish',
10396          'foffset'
10397        ]
10398      },
10399      {
10400        rtl: [
10401          'start',
10402          'soffset',
10403          'finish',
10404          'foffset'
10405        ]
10406      }
10407    ]);
10408    const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
10409    const getRanges = (win, selection) => selection.match({
10410      domRange: rng => {
10411        return {
10412          ltr: constant(rng),
10413          rtl: Optional.none
10414        };
10415      },
10416      relative: (startSitu, finishSitu) => {
10417        return {
10418          ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
10419          rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
10420        };
10421      },
10422      exact: (start, soffset, finish, foffset) => {
10423        return {
10424          ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
10425          rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
10426        };
10427      }
10428    });
10429    const doDiagnose = (win, ranges) => {
10430      const rng = ranges.ltr();
10431      if (rng.collapsed) {
10432        const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
10433        return reversed.map(rev => adt$1.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$1.ltr, rng));
10434      } else {
10435        return fromRange(win, adt$1.ltr, rng);
10436      }
10437    };
10438    const diagnose = (win, selection) => {
10439      const ranges = getRanges(win, selection);
10440      return doDiagnose(win, ranges);
10441    };
10442    adt$1.ltr;
10443    adt$1.rtl;
10444
10445    const caretPositionFromPoint = (doc, x, y) => {
10446      var _a;
10447      return Optional.from((_a = doc.caretPositionFromPoint) === null || _a === void 0 ? void 0 : _a.call(doc, x, y)).bind(pos => {
10448        if (pos.offsetNode === null) {
10449          return Optional.none();
10450        }
10451        const r = doc.createRange();
10452        r.setStart(pos.offsetNode, pos.offset);
10453        r.collapse();
10454        return Optional.some(r);
10455      });
10456    };
10457    const caretRangeFromPoint = (doc, x, y) => {
10458      var _a;
10459      return Optional.from((_a = doc.caretRangeFromPoint) === null || _a === void 0 ? void 0 : _a.call(doc, x, y));
10460    };
10461    const availableSearch = (doc, x, y) => {
10462      if (doc.caretPositionFromPoint) {
10463        return caretPositionFromPoint(doc, x, y);
10464      } else if (doc.caretRangeFromPoint) {
10465        return caretRangeFromPoint(doc, x, y);
10466      } else {
10467        return Optional.none();
10468      }
10469    };
10470    const fromPoint$1 = (win, x, y) => {
10471      const doc = win.document;
10472      return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
10473    };
10474
10475    const beforeSpecial = (element, offset) => {
10476      const name$1 = name(element);
10477      if ('input' === name$1) {
10478        return Situ.after(element);
10479      } else if (!contains$2([
10480          'br',
10481          'img'
10482        ], name$1)) {
10483        return Situ.on(element, offset);
10484      } else {
10485        return offset === 0 ? Situ.before(element) : Situ.after(element);
10486      }
10487    };
10488    const preprocessRelative = (startSitu, finishSitu) => {
10489      const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
10490      const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
10491      return SimSelection.relative(start, finish);
10492    };
10493    const preprocessExact = (start, soffset, finish, foffset) => {
10494      const startSitu = beforeSpecial(start, soffset);
10495      const finishSitu = beforeSpecial(finish, foffset);
10496      return SimSelection.relative(startSitu, finishSitu);
10497    };
10498    const preprocess = selection => selection.match({
10499      domRange: rng => {
10500        const start = SugarElement.fromDom(rng.startContainer);
10501        const finish = SugarElement.fromDom(rng.endContainer);
10502        return preprocessExact(start, rng.startOffset, finish, rng.endOffset);
10503      },
10504      relative: preprocessRelative,
10505      exact: preprocessExact
10506    });
10507
10508    const fromElements = (elements, scope) => {
10509      const doc = scope || document;
10510      const fragment = doc.createDocumentFragment();
10511      each$e(elements, element => {
10512        fragment.appendChild(element.dom);
10513      });
10514      return SugarElement.fromDom(fragment);
10515    };
10516
10517    const toNative = selection => {
10518      const win = SimSelection.getWin(selection).dom;
10519      const getDomRange = (start, soffset, finish, foffset) => exactToNative(win, start, soffset, finish, foffset);
10520      const filtered = preprocess(selection);
10521      return diagnose(win, filtered).match({
10522        ltr: getDomRange,
10523        rtl: getDomRange
10524      });
10525    };
10526    const getAtPoint = (win, x, y) => fromPoint$1(win, x, y);
10527
10528    const fromPoint = (clientX, clientY, doc) => {
10529      const win = defaultView(SugarElement.fromDom(doc));
10530      return getAtPoint(win.dom, clientX, clientY).map(simRange => {
10531        const rng = doc.createRange();
10532        rng.setStart(simRange.start.dom, simRange.soffset);
10533        rng.setEnd(simRange.finish.dom, simRange.foffset);
10534        return rng;
10535      }).getOrUndefined();
10536    };
10537
10538    const isEq$4 = (rng1, rng2) => {
10539      return isNonNullable(rng1) && isNonNullable(rng2) && (rng1.startContainer === rng2.startContainer && rng1.startOffset === rng2.startOffset) && (rng1.endContainer === rng2.endContainer && rng1.endOffset === rng2.endOffset);
10540    };
10541
10542    const findParent = (node, rootNode, predicate) => {
10543      let currentNode = node;
10544      while (currentNode && currentNode !== rootNode) {
10545        if (predicate(currentNode)) {
10546          return currentNode;
10547        }
10548        currentNode = currentNode.parentNode;
10549      }
10550      return null;
10551    };
10552    const hasParent$1 = (node, rootNode, predicate) => findParent(node, rootNode, predicate) !== null;
10553    const hasParentWithName = (node, rootNode, name) => hasParent$1(node, rootNode, node => node.nodeName === name);
10554    const isCeFalseCaretContainer = (node, rootNode) => isCaretContainer$2(node) && !hasParent$1(node, rootNode, isCaretNode);
10555    const hasBrBeforeAfter = (dom, node, left) => {
10556      const parentNode = node.parentNode;
10557      if (parentNode) {
10558        const walker = new DomTreeWalker(node, dom.getParent(parentNode, dom.isBlock) || dom.getRoot());
10559        let currentNode;
10560        while (currentNode = walker[left ? 'prev' : 'next']()) {
10561          if (isBr$6(currentNode)) {
10562            return true;
10563          }
10564        }
10565      }
10566      return false;
10567    };
10568    const isPrevNode = (node, name) => {
10569      var _a;
10570      return ((_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.nodeName) === name;
10571    };
10572    const hasContentEditableFalseParent = (root, node) => {
10573      let currentNode = node;
10574      while (currentNode && currentNode !== root) {
10575        if (isContentEditableFalse$b(currentNode)) {
10576          return true;
10577        }
10578        currentNode = currentNode.parentNode;
10579      }
10580      return false;
10581    };
10582    const findTextNodeRelative = (dom, isAfterNode, collapsed, left, startNode) => {
10583      const body = dom.getRoot();
10584      const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
10585      const parentNode = startNode.parentNode;
10586      let lastInlineElement;
10587      let node;
10588      if (!parentNode) {
10589        return Optional.none();
10590      }
10591      const parentBlockContainer = dom.getParent(parentNode, dom.isBlock) || body;
10592      if (left && isBr$6(startNode) && isAfterNode && dom.isEmpty(parentBlockContainer)) {
10593        return Optional.some(CaretPosition(parentNode, dom.nodeIndex(startNode)));
10594      }
10595      const walker = new DomTreeWalker(startNode, parentBlockContainer);
10596      while (node = walker[left ? 'prev' : 'next']()) {
10597        if (dom.getContentEditableParent(node) === 'false' || isCeFalseCaretContainer(node, body)) {
10598          return Optional.none();
10599        }
10600        if (isText$b(node) && node.data.length > 0) {
10601          if (!hasParentWithName(node, body, 'A')) {
10602            return Optional.some(CaretPosition(node, left ? node.data.length : 0));
10603          }
10604          return Optional.none();
10605        }
10606        if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
10607          return Optional.none();
10608        }
10609        lastInlineElement = node;
10610      }
10611      if (isComment(lastInlineElement)) {
10612        return Optional.none();
10613      }
10614      if (collapsed && lastInlineElement) {
10615        return Optional.some(CaretPosition(lastInlineElement, 0));
10616      }
10617      return Optional.none();
10618    };
10619    const normalizeEndPoint = (dom, collapsed, start, rng) => {
10620      const body = dom.getRoot();
10621      let node;
10622      let normalized = false;
10623      let container = start ? rng.startContainer : rng.endContainer;
10624      let offset = start ? rng.startOffset : rng.endOffset;
10625      const isAfterNode = isElement$6(container) && offset === container.childNodes.length;
10626      const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
10627      let directionLeft = start;
10628      if (isCaretContainer$2(container)) {
10629        return Optional.none();
10630      }
10631      if (isElement$6(container) && offset > container.childNodes.length - 1) {
10632        directionLeft = false;
10633      }
10634      if (isDocument$1(container)) {
10635        container = body;
10636        offset = 0;
10637      }
10638      if (container === body) {
10639        if (directionLeft) {
10640          node = container.childNodes[offset > 0 ? offset - 1 : 0];
10641          if (node) {
10642            if (isCaretContainer$2(node)) {
10643              return Optional.none();
10644            }
10645            if (nonEmptyElementsMap[node.nodeName] || isTable$2(node)) {
10646              return Optional.none();
10647            }
10648          }
10649        }
10650        if (container.hasChildNodes()) {
10651          offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
10652          container = container.childNodes[offset];
10653          offset = isText$b(container) && isAfterNode ? container.data.length : 0;
10654          if (!collapsed && container === body.lastChild && isTable$2(container)) {
10655            return Optional.none();
10656          }
10657          if (hasContentEditableFalseParent(body, container) || isCaretContainer$2(container)) {
10658            return Optional.none();
10659          }
10660          if (isDetails(container)) {
10661            return Optional.none();
10662          }
10663          if (container.hasChildNodes() && !isTable$2(container)) {
10664            node = container;
10665            const walker = new DomTreeWalker(container, body);
10666            do {
10667              if (isContentEditableFalse$b(node) || isCaretContainer$2(node)) {
10668                normalized = false;
10669                break;
10670              }
10671              if (isText$b(node) && node.data.length > 0) {
10672                offset = directionLeft ? 0 : node.data.length;
10673                container = node;
10674                normalized = true;
10675                break;
10676              }
10677              if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCellOrCaption(node)) {
10678                offset = dom.nodeIndex(node);
10679                container = node.parentNode;
10680                if (!directionLeft) {
10681                  offset++;
10682                }
10683                normalized = true;
10684                break;
10685              }
10686            } while (node = directionLeft ? walker.next() : walker.prev());
10687          }
10688        }
10689      }
10690      if (collapsed) {
10691        if (isText$b(container) && offset === 0) {
10692          findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(pos => {
10693            container = pos.container();
10694            offset = pos.offset();
10695            normalized = true;
10696          });
10697        }
10698        if (isElement$6(container)) {
10699          node = container.childNodes[offset];
10700          if (!node) {
10701            node = container.childNodes[offset - 1];
10702          }
10703          if (node && isBr$6(node) && !isPrevNode(node, 'A') && !hasBrBeforeAfter(dom, node, false) && !hasBrBeforeAfter(dom, node, true)) {
10704            findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(pos => {
10705              container = pos.container();
10706              offset = pos.offset();
10707              normalized = true;
10708            });
10709          }
10710        }
10711      }
10712      if (directionLeft && !collapsed && isText$b(container) && offset === container.data.length) {
10713        findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(pos => {
10714          container = pos.container();
10715          offset = pos.offset();
10716          normalized = true;
10717        });
10718      }
10719      return normalized && container ? Optional.some(CaretPosition(container, offset)) : Optional.none();
10720    };
10721    const normalize$2 = (dom, rng) => {
10722      const collapsed = rng.collapsed, normRng = rng.cloneRange();
10723      const startPos = CaretPosition.fromRangeStart(rng);
10724      normalizeEndPoint(dom, collapsed, true, normRng).each(pos => {
10725        if (!collapsed || !CaretPosition.isAbove(startPos, pos)) {
10726          normRng.setStart(pos.container(), pos.offset());
10727        }
10728      });
10729      if (!collapsed) {
10730        normalizeEndPoint(dom, collapsed, false, normRng).each(pos => {
10731          normRng.setEnd(pos.container(), pos.offset());
10732        });
10733      }
10734      if (collapsed) {
10735        normRng.collapse(true);
10736      }
10737      return isEq$4(rng, normRng) ? Optional.none() : Optional.some(normRng);
10738    };
10739
10740    const splitText = (node, offset) => {
10741      return node.splitText(offset);
10742    };
10743    const split = rng => {
10744      let startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset;
10745      if (startContainer === endContainer && isText$b(startContainer)) {
10746        if (startOffset > 0 && startOffset < startContainer.data.length) {
10747          endContainer = splitText(startContainer, startOffset);
10748          startContainer = endContainer.previousSibling;
10749          if (endOffset > startOffset) {
10750            endOffset = endOffset - startOffset;
10751            const newContainer = splitText(endContainer, endOffset).previousSibling;
10752            startContainer = endContainer = newContainer;
10753            endOffset = newContainer.data.length;
10754            startOffset = 0;
10755          } else {
10756            endOffset = 0;
10757          }
10758        }
10759      } else {
10760        if (isText$b(startContainer) && startOffset > 0 && startOffset < startContainer.data.length) {
10761          startContainer = splitText(startContainer, startOffset);
10762          startOffset = 0;
10763        }
10764        if (isText$b(endContainer) && endOffset > 0 && endOffset < endContainer.data.length) {
10765          const newContainer = splitText(endContainer, endOffset).previousSibling;
10766          endContainer = newContainer;
10767          endOffset = newContainer.data.length;
10768        }
10769      }
10770      return {
10771        startContainer,
10772        startOffset,
10773        endContainer,
10774        endOffset
10775      };
10776    };
10777
10778    const RangeUtils = dom => {
10779      const walk = (rng, callback) => {
10780        return walk$3(dom, rng, callback);
10781      };
10782      const split$1 = split;
10783      const normalize = rng => {
10784        return normalize$2(dom, rng).fold(never, normalizedRng => {
10785          rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset);
10786          rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset);
10787          return true;
10788        });
10789      };
10790      const expand = (rng, options = { type: 'word' }) => {
10791        if (options.type === 'word') {
10792          const rangeLike = expandRng(dom, rng, [{ inline: 'span' }], {
10793            includeTrailingSpace: false,
10794            expandToBlock: false
10795          });
10796          const newRange = dom.createRng();
10797          newRange.setStart(rangeLike.startContainer, rangeLike.startOffset);
10798          newRange.setEnd(rangeLike.endContainer, rangeLike.endOffset);
10799          return newRange;
10800        }
10801        return rng;
10802      };
10803      return {
10804        walk,
10805        split: split$1,
10806        expand,
10807        normalize
10808      };
10809    };
10810    RangeUtils.compareRanges = isEq$4;
10811    RangeUtils.getCaretRangeFromPoint = fromPoint;
10812    RangeUtils.getSelectedNode = getSelectedNode;
10813    RangeUtils.getNode = getNode$1;
10814
10815    const Dimension = (name, getOffset) => {
10816      const set = (element, h) => {
10817        if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
10818          throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
10819        }
10820        const dom = element.dom;
10821        if (isSupported(dom)) {
10822          dom.style[name] = h + 'px';
10823        }
10824      };
10825      const get = element => {
10826        const r = getOffset(element);
10827        if (r <= 0 || r === null) {
10828          const css = get$7(element, name);
10829          return parseFloat(css) || 0;
10830        }
10831        return r;
10832      };
10833      const getOuter = get;
10834      const aggregate = (element, properties) => foldl(properties, (acc, property) => {
10835        const val = get$7(element, property);
10836        const value = val === undefined ? 0 : parseInt(val, 10);
10837        return isNaN(value) ? acc : acc + value;
10838      }, 0);
10839      const max = (element, value, properties) => {
10840        const cumulativeInclusions = aggregate(element, properties);
10841        const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
10842        return absoluteMax;
10843      };
10844      return {
10845        set,
10846        get,
10847        getOuter,
10848        aggregate,
10849        max
10850      };
10851    };
10852
10853    const api = Dimension('height', element => {
10854      const dom = element.dom;
10855      return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
10856    });
10857    const get$2 = element => api.get(ele
vendor: 24,320 bytes, lines 10857-11550
10857ment);
10858
10859    const walkUp = (navigation, doc) => {
10860      const frame = navigation.view(doc);
10861      return frame.fold(constant([]), f => {
10862        const parent = navigation.owner(f);
10863        const rest = walkUp(navigation, parent);
10864        return [f].concat(rest);
10865      });
10866    };
10867    const pathTo = (element, navigation) => {
10868      const d = navigation.owner(element);
10869      return walkUp(navigation, d);
10870    };
10871
10872    const view = doc => {
10873      var _a;
10874      const element = doc.dom === document ? Optional.none() : Optional.from((_a = doc.dom.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement);
10875      return element.map(SugarElement.fromDom);
10876    };
10877    const owner = element => documentOrOwner(element);
10878
10879    var Navigation = /*#__PURE__*/Object.freeze({
10880        __proto__: null,
10881        view: view,
10882        owner: owner
10883    });
10884
10885    const find = element => {
10886      const doc = getDocument();
10887      const scroll = get$5(doc);
10888      const frames = pathTo(element, Navigation);
10889      const offset = viewport(element);
10890      const r = foldr(frames, (b, a) => {
10891        const loc = viewport(a);
10892        return {
10893          left: b.left + loc.left,
10894          top: b.top + loc.top
10895        };
10896      }, {
10897        left: 0,
10898        top: 0
10899      });
10900      return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top);
10901    };
10902
10903    const excludeFromDescend = element => name(element) === 'textarea';
10904    const fireScrollIntoViewEvent = (editor, data) => {
10905      const scrollEvent = editor.dispatch('ScrollIntoView', data);
10906      return scrollEvent.isDefaultPrevented();
10907    };
10908    const fireAfterScrollIntoViewEvent = (editor, data) => {
10909      editor.dispatch('AfterScrollIntoView', data);
10910    };
10911    const descend = (element, offset) => {
10912      const children = children$1(element);
10913      if (children.length === 0 || excludeFromDescend(element)) {
10914        return {
10915          element,
10916          offset
10917        };
10918      } else if (offset < children.length && !excludeFromDescend(children[offset])) {
10919        return {
10920          element: children[offset],
10921          offset: 0
10922        };
10923      } else {
10924        const last = children[children.length - 1];
10925        if (excludeFromDescend(last)) {
10926          return {
10927            element,
10928            offset
10929          };
10930        } else {
10931          if (name(last) === 'img') {
10932            return {
10933              element: last,
10934              offset: 1
10935            };
10936          } else if (isText$c(last)) {
10937            return {
10938              element: last,
10939              offset: get$3(last).length
10940            };
10941          } else {
10942            return {
10943              element: last,
10944              offset: children$1(last).length
10945            };
10946          }
10947        }
10948      }
10949    };
10950    const markerInfo = (element, cleanupFun) => {
10951      const pos = absolute(element);
10952      const height = get$2(element);
10953      return {
10954        element,
10955        bottom: pos.top + height,
10956        height,
10957        pos,
10958        cleanup: cleanupFun
10959      };
10960    };
10961    const createMarker$1 = (element, offset) => {
10962      const startPoint = descend(element, offset);
10963      const span = SugarElement.fromHtml('<span data-mce-bogus="all" style="display: inline-block;">' + ZWSP$1 + '</span>');
10964      before$3(startPoint.element, span);
10965      return markerInfo(span, () => remove$4(span));
10966    };
10967    const elementMarker = element => markerInfo(SugarElement.fromDom(element), noop);
10968    const withMarker = (editor, f, rng, alignToTop) => {
10969      preserveWith(editor, (_s, _e) => applyWithMarker(editor, f, rng, alignToTop), rng);
10970    };
10971    const withScrollEvents = (editor, doc, f, marker, alignToTop) => {
10972      const data = {
10973        elm: marker.element.dom,
10974        alignToTop
10975      };
10976      if (fireScrollIntoViewEvent(editor, data)) {
10977        return;
10978      }
10979      const scrollTop = get$5(doc).top;
10980      f(editor, doc, scrollTop, marker, alignToTop);
10981      fireAfterScrollIntoViewEvent(editor, data);
10982    };
10983    const applyWithMarker = (editor, f, rng, alignToTop) => {
10984      const body = SugarElement.fromDom(editor.getBody());
10985      const doc = SugarElement.fromDom(editor.getDoc());
10986      reflow(body);
10987      const marker = createMarker$1(SugarElement.fromDom(rng.startContainer), rng.startOffset);
10988      withScrollEvents(editor, doc, f, marker, alignToTop);
10989      marker.cleanup();
10990    };
10991    const withElement = (editor, element, f, alignToTop) => {
10992      const doc = SugarElement.fromDom(editor.getDoc());
10993      withScrollEvents(editor, doc, f, elementMarker(element), alignToTop);
10994    };
10995    const preserveWith = (editor, f, rng) => {
10996      const startElement = rng.startContainer;
10997      const startOffset = rng.startOffset;
10998      const endElement = rng.endContainer;
10999      const endOffset = rng.endOffset;
11000      f(SugarElement.fromDom(startElement), SugarElement.fromDom(endElement));
11001      const newRng = editor.dom.createRng();
11002      newRng.setStart(startElement, startOffset);
11003      newRng.setEnd(endElement, endOffset);
11004      editor.selection.setRng(rng);
11005    };
11006    const scrollToMarker = (editor, marker, viewHeight, alignToTop, doc) => {
11007      const pos = marker.pos;
11008      if (alignToTop) {
11009        to(pos.left, pos.top, doc);
11010      } else {
11011        const y = pos.top - viewHeight + marker.height;
11012        to(-editor.getBody().getBoundingClientRect().left, y, doc);
11013      }
11014    };
11015    const intoWindowIfNeeded = (editor, doc, scrollTop, viewHeight, marker, alignToTop) => {
11016      const viewportBottom = viewHeight + scrollTop;
11017      const markerTop = marker.pos.top;
11018      const markerBottom = marker.bottom;
11019      const largerThanViewport = markerBottom - markerTop >= viewHeight;
11020      if (markerTop < scrollTop) {
11021        scrollToMarker(editor, marker, viewHeight, alignToTop !== false, doc);
11022      } else if (markerTop > viewportBottom) {
11023        const align = largerThanViewport ? alignToTop !== false : alignToTop === true;
11024        scrollToMarker(editor, marker, viewHeight, align, doc);
11025      } else if (markerBottom > viewportBottom && !largerThanViewport) {
11026        scrollToMarker(editor, marker, viewHeight, alignToTop === true, doc);
11027      }
11028    };
11029    const intoWindow = (editor, doc, scrollTop, marker, alignToTop) => {
11030      const viewHeight = defaultView(doc).dom.innerHeight;
11031      intoWindowIfNeeded(editor, doc, scrollTop, viewHeight, marker, alignToTop);
11032    };
11033    const intoFrame = (editor, doc, scrollTop, marker, alignToTop) => {
11034      const frameViewHeight = defaultView(doc).dom.innerHeight;
11035      intoWindowIfNeeded(editor, doc, scrollTop, frameViewHeight, marker, alignToTop);
11036      const op = find(marker.element);
11037      const viewportBounds = getBounds(window);
11038      if (op.top < viewportBounds.y) {
11039        intoView(marker.element, alignToTop !== false);
11040      } else if (op.top > viewportBounds.bottom) {
11041        intoView(marker.element, alignToTop === true);
11042      }
11043    };
11044    const rangeIntoWindow = (editor, rng, alignToTop) => withMarker(editor, intoWindow, rng, alignToTop);
11045    const elementIntoWindow = (editor, element, alignToTop) => withElement(editor, element, intoWindow, alignToTop);
11046    const rangeIntoFrame = (editor, rng, alignToTop) => withMarker(editor, intoFrame, rng, alignToTop);
11047    const elementIntoFrame = (editor, element, alignToTop) => withElement(editor, element, intoFrame, alignToTop);
11048    const scrollElementIntoView = (editor, element, alignToTop) => {
11049      const scroller = editor.inline ? elementIntoWindow : elementIntoFrame;
11050      scroller(editor, element, alignToTop);
11051    };
11052    const scrollRangeIntoView = (editor, rng, alignToTop) => {
11053      const scroller = editor.inline ? rangeIntoWindow : rangeIntoFrame;
11054      scroller(editor, rng, alignToTop);
11055    };
11056
11057    const isEditableRange = (dom, rng) => {
11058      if (rng.collapsed) {
11059        return dom.isEditable(rng.startContainer);
11060      } else {
11061        return dom.isEditable(rng.startContainer) && dom.isEditable(rng.endContainer);
11062      }
11063    };
11064
11065    const getEndpointElement = (root, rng, start, real, resolve) => {
11066      const container = start ? rng.startContainer : rng.endContainer;
11067      const offset = start ? rng.startOffset : rng.endOffset;
11068      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);
11069    };
11070    const getStart = (root, rng, real = false) => getEndpointElement(root, rng, true, real, (elm, offset) => Math.min(childNodesCount(elm), offset));
11071    const getEnd = (root, rng, real = false) => getEndpointElement(root, rng, false, real, (elm, offset) => offset > 0 ? offset - 1 : offset);
11072    const skipEmptyTextNodes = (node, forwards) => {
11073      const orig = node;
11074      while (node && isText$b(node) && node.length === 0) {
11075        node = forwards ? node.nextSibling : node.previousSibling;
11076      }
11077      return node || orig;
11078    };
11079    const getNode = (root, rng) => {
11080      if (!rng) {
11081        return root;
11082      }
11083      let startContainer = rng.startContainer;
11084      let endContainer = rng.endContainer;
11085      const startOffset = rng.startOffset;
11086      const endOffset = rng.endOffset;
11087      let node = rng.commonAncestorContainer;
11088      if (!rng.collapsed) {
11089        if (startContainer === endContainer) {
11090          if (endOffset - startOffset < 2) {
11091            if (startContainer.hasChildNodes()) {
11092              node = startContainer.childNodes[startOffset];
11093            }
11094          }
11095        }
11096        if (isText$b(startContainer) && isText$b(endContainer)) {
11097          if (startContainer.length === startOffset) {
11098            startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
11099          } else {
11100            startContainer = startContainer.parentNode;
11101          }
11102          if (endOffset === 0) {
11103            endContainer = skipEmptyTextNodes(endContainer.previousSibling, false);
11104          } else {
11105            endContainer = endContainer.parentNode;
11106          }
11107          if (startContainer && startContainer === endContainer) {
11108            node = startContainer;
11109          }
11110        }
11111      }
11112      const elm = isText$b(node) ? node.parentNode : node;
11113      return isHTMLElement(elm) ? elm : root;
11114    };
11115    const getSelectedBlocks = (dom, rng, startElm, endElm) => {
11116      const selectedBlocks = [];
11117      const root = dom.getRoot();
11118      const start = dom.getParent(startElm || getStart(root, rng, rng.collapsed), dom.isBlock);
11119      const end = dom.getParent(endElm || getEnd(root, rng, rng.collapsed), dom.isBlock);
11120      if (start && start !== root) {
11121        selectedBlocks.push(start);
11122      }
11123      if (start && end && start !== end) {
11124        let node;
11125        const walker = new DomTreeWalker(start, root);
11126        while ((node = walker.next()) && node !== end) {
11127          if (dom.isBlock(node)) {
11128            selectedBlocks.push(node);
11129          }
11130        }
11131      }
11132      if (end && start !== end && end !== root) {
11133        selectedBlocks.push(end);
11134      }
11135      return selectedBlocks;
11136    };
11137    const select = (dom, node, content) => Optional.from(node).bind(node => Optional.from(node.parentNode).map(parent => {
11138      const idx = dom.nodeIndex(node);
11139      const rng = dom.createRng();
11140      rng.setStart(parent, idx);
11141      rng.setEnd(parent, idx + 1);
11142      if (content) {
11143        moveEndPoint(dom, rng, node, true);
11144        moveEndPoint(dom, rng, node, false);
11145      }
11146      return rng;
11147    }));
11148
11149    const processRanges = (editor, ranges) => map$3(ranges, range => {
11150      const evt = editor.dispatch('GetSelectionRange', { range });
11151      return evt.range !== range ? evt.range : range;
11152    });
11153
11154    const typeLookup = {
11155      '#text': 3,
11156      '#comment': 8,
11157      '#cdata': 4,
11158      '#pi': 7,
11159      '#doctype': 10,
11160      '#document-fragment': 11
11161    };
11162    const walk$2 = (node, root, prev) => {
11163      const startName = prev ? 'lastChild' : 'firstChild';
11164      const siblingName = prev ? 'prev' : 'next';
11165      if (node[startName]) {
11166        return node[startName];
11167      }
11168      if (node !== root) {
11169        let sibling = node[siblingName];
11170        if (sibling) {
11171          return sibling;
11172        }
11173        for (let parent = node.parent; parent && parent !== root; parent = parent.parent) {
11174          sibling = parent[siblingName];
11175          if (sibling) {
11176            return sibling;
11177          }
11178        }
11179      }
11180      return undefined;
11181    };
11182    const isEmptyTextNode = node => {
11183      var _a;
11184      const text = (_a = node.value) !== null && _a !== void 0 ? _a : '';
11185      if (!isWhitespaceText(text)) {
11186        return false;
11187      }
11188      const parentNode = node.parent;
11189      if (parentNode && (parentNode.name !== 'span' || parentNode.attr('style')) && /^[ ]+$/.test(text)) {
11190        return false;
11191      }
11192      return true;
11193    };
11194    const isNonEmptyElement = node => {
11195      const isNamedAnchor = node.name === 'a' && !node.attr('href') && node.attr('id');
11196      return node.attr('name') || node.attr('id') && !node.firstChild || node.attr('data-mce-bookmark') || isNamedAnchor;
11197    };
11198    class AstNode {
11199      static create(name, attrs) {
11200        const node = new AstNode(name, typeLookup[name] || 1);
11201        if (attrs) {
11202          each$d(attrs, (value, attrName) => {
11203            node.attr(attrName, value);
11204          });
11205        }
11206        return node;
11207      }
11208      constructor(name, type) {
11209        this.name = name;
11210        this.type = type;
11211        if (type === 1) {
11212          this.attributes = [];
11213          this.attributes.map = {};
11214        }
11215      }
11216      replace(node) {
11217        const self = this;
11218        if (node.parent) {
11219          node.remove();
11220        }
11221        self.insert(node, self);
11222        self.remove();
11223        return self;
11224      }
11225      attr(name, value) {
11226        const self = this;
11227        if (!isString(name)) {
11228          if (isNonNullable(name)) {
11229            each$d(name, (value, key) => {
11230              self.attr(key, value);
11231            });
11232          }
11233          return self;
11234        }
11235        const attrs = self.attributes;
11236        if (attrs) {
11237          if (value !== undefined) {
11238            if (value === null) {
11239              if (name in attrs.map) {
11240                delete attrs.map[name];
11241                let i = attrs.length;
11242                while (i--) {
11243                  if (attrs[i].name === name) {
11244                    attrs.splice(i, 1);
11245                    return self;
11246                  }
11247                }
11248              }
11249              return self;
11250            }
11251            if (name in attrs.map) {
11252              let i = attrs.length;
11253              while (i--) {
11254                if (attrs[i].name === name) {
11255                  attrs[i].value = value;
11256                  break;
11257                }
11258              }
11259            } else {
11260              attrs.push({
11261                name,
11262                value
11263              });
11264            }
11265            attrs.map[name] = value;
11266            return self;
11267          }
11268          return attrs.map[name];
11269        }
11270        return undefined;
11271      }
11272      clone() {
11273        const self = this;
11274        const clone = new AstNode(self.name, self.type);
11275        const selfAttrs = self.attributes;
11276        if (selfAttrs) {
11277          const cloneAttrs = [];
11278          cloneAttrs.map = {};
11279          for (let i = 0, l = selfAttrs.length; i < l; i++) {
11280            const selfAttr = selfAttrs[i];
11281            if (selfAttr.name !== 'id') {
11282              cloneAttrs[cloneAttrs.length] = {
11283                name: selfAttr.name,
11284                value: selfAttr.value
11285              };
11286              cloneAttrs.map[selfAttr.name] = selfAttr.value;
11287            }
11288          }
11289          clone.attributes = cloneAttrs;
11290        }
11291        clone.value = self.value;
11292        return clone;
11293      }
11294      wrap(wrapper) {
11295        const self = this;
11296        if (self.parent) {
11297          self.parent.insert(wrapper, self);
11298          wrapper.append(self);
11299        }
11300        return self;
11301      }
11302      unwrap() {
11303        const self = this;
11304        for (let node = self.firstChild; node;) {
11305          const next = node.next;
11306          self.insert(node, self, true);
11307          node = next;
11308        }
11309        self.remove();
11310      }
11311      remove() {
11312        const self = this, parent = self.parent, next = self.next, prev = self.prev;
11313        if (parent) {
11314          if (parent.firstChild === self) {
11315            parent.firstChild = next;
11316            if (next) {
11317              next.prev = null;
11318            }
11319          } else if (prev) {
11320            prev.next = next;
11321          }
11322          if (parent.lastChild === self) {
11323            parent.lastChild = prev;
11324            if (prev) {
11325              prev.next = null;
11326            }
11327          } else if (next) {
11328            next.prev = prev;
11329          }
11330          self.parent = self.next = self.prev = null;
11331        }
11332        return self;
11333      }
11334      append(node) {
11335        const self = this;
11336        if (node.parent) {
11337          node.remove();
11338        }
11339        const last = self.lastChild;
11340        if (last) {
11341          last.next = node;
11342          node.prev = last;
11343          self.lastChild = node;
11344        } else {
11345          self.lastChild = self.firstChild = node;
11346        }
11347        node.parent = self;
11348        return node;
11349      }
11350      insert(node, refNode, before) {
11351        if (node.parent) {
11352          node.remove();
11353        }
11354        const parent = refNode.parent || this;
11355        if (before) {
11356          if (refNode === parent.firstChild) {
11357            parent.firstChild = node;
11358          } else if (refNode.prev) {
11359            refNode.prev.next = node;
11360          }
11361          node.prev = refNode.prev;
11362          node.next = refNode;
11363          refNode.prev = node;
11364        } else {
11365          if (refNode === parent.lastChild) {
11366            parent.lastChild = node;
11367          } else if (refNode.next) {
11368            refNode.next.prev = node;
11369          }
11370          node.next = refNode.next;
11371          node.prev = refNode;
11372          refNode.next = node;
11373        }
11374        node.parent = parent;
11375        return node;
11376      }
11377      getAll(name) {
11378        const self = this;
11379        const collection = [];
11380        for (let node = self.firstChild; node; node = walk$2(node, self)) {
11381          if (node.name === name) {
11382            collection.push(node);
11383          }
11384        }
11385        return collection;
11386      }
11387      children() {
11388        const self = this;
11389        const collection = [];
11390        for (let node = self.firstChild; node; node = node.next) {
11391          collection.push(node);
11392        }
11393        return collection;
11394      }
11395      empty() {
11396        const self = this;
11397        if (self.firstChild) {
11398          const nodes = [];
11399          for (let node = self.firstChild; node; node = walk$2(node, self)) {
11400            nodes.push(node);
11401          }
11402          let i = nodes.length;
11403          while (i--) {
11404            const node = nodes[i];
11405            node.parent = node.firstChild = node.lastChild = node.next = node.prev = null;
11406          }
11407        }
11408        self.firstChild = self.lastChild = null;
11409        return self;
11410      }
11411      isEmpty(elements, whitespace = {}, predicate) {
11412        var _a;
11413        const self = this;
11414        let node = self.firstChild;
11415        if (isNonEmptyElement(self)) {
11416          return false;
11417        }
11418        if (node) {
11419          do {
11420            if (node.type === 1) {
11421              if (node.attr('data-mce-bogus')) {
11422                continue;
11423              }
11424              if (elements[node.name]) {
11425                return false;
11426              }
11427              if (isNonEmptyElement(node)) {
11428                return false;
11429              }
11430            }
11431            if (node.type === 8) {
11432              return false;
11433            }
11434            if (node.type === 3 && !isEmptyTextNode(node)) {
11435              return false;
11436            }
11437            if (node.type === 3 && node.parent && whitespace[node.parent.name] && isWhitespaceText((_a = node.value) !== null && _a !== void 0 ? _a : '')) {
11438              return false;
11439            }
11440            if (predicate && predicate(node)) {
11441              return false;
11442            }
11443          } while (node = walk$2(node, self));
11444        }
11445        return true;
11446      }
11447      walk(prev) {
11448        return walk$2(this, null, prev);
11449      }
11450    }
11451
11452    const unescapedTextParents = Tools.makeMap('NOSCRIPT STYLE SCRIPT XMP IFRAME NOEMBED NOFRAMES PLAINTEXT', ' ');
11453    const containsZwsp = node => isString(node.nodeValue) && node.nodeValue.includes(ZWSP$1);
11454    const getTemporaryNodeSelector = tempAttrs => `${ tempAttrs.length === 0 ? '' : `${ map$3(tempAttrs, attr => `[${ attr }]`).join(',') },` }[data-mce-bogus="all"]`;
11455    const getTemporaryNodes = (tempAttrs, body) => body.querySelectorAll(getTemporaryNodeSelector(tempAttrs));
11456    const createZwspCommentWalker = body => document.createTreeWalker(body, NodeFilter.SHOW_COMMENT, node => containsZwsp(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP);
11457    const createUnescapedZwspTextWalker = body => document.createTreeWalker(body, NodeFilter.SHOW_TEXT, node => {
11458      if (containsZwsp(node)) {
11459        const parent = node.parentNode;
11460        return parent && has$2(unescapedTextParents, parent.nodeName) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
11461      } else {
11462        return NodeFilter.FILTER_SKIP;
11463      }
11464    });
11465    const hasZwspComment = body => createZwspCommentWalker(body).nextNode() !== null;
11466    const hasUnescapedZwspText = body => createUnescapedZwspTextWalker(body).nextNode() !== null;
11467    const hasTemporaryNode = (tempAttrs, body) => body.querySelector(getTemporaryNodeSelector(tempAttrs)) !== null;
11468    const trimTemporaryNodes = (tempAttrs, body) => {
11469      each$e(getTemporaryNodes(tempAttrs, body), elm => {
11470        const element = SugarElement.fromDom(elm);
11471        if (get$9(element, 'data-mce-bogus') === 'all') {
11472          remove$4(element);
11473        } else {
11474          each$e(tempAttrs, attr => {
11475            if (has$1(element, attr)) {
11476              remove$9(element, attr);
11477            }
11478          });
11479        }
11480      });
11481    };
11482    const emptyAllNodeValuesInWalker = walker => {
11483      let curr = walker.nextNode();
11484      while (curr !== null) {
11485        curr.nodeValue = null;
11486        curr = walker.nextNode();
11487      }
11488    };
11489    const emptyZwspComments = compose(emptyAllNodeValuesInWalker, createZwspCommentWalker);
11490    const emptyUnescapedZwspTexts = compose(emptyAllNodeValuesInWalker, createUnescapedZwspTextWalker);
11491    const trim$1 = (body, tempAttrs) => {
11492      const conditionalTrims = [
11493        {
11494          condition: curry(hasTemporaryNode, tempAttrs),
11495          action: curry(trimTemporaryNodes, tempAttrs)
11496        },
11497        {
11498          condition: hasZwspComment,
11499          action: emptyZwspComments
11500        },
11501        {
11502          condition: hasUnescapedZwspText,
11503          action: emptyUnescapedZwspTexts
11504        }
11505      ];
11506      let trimmed = body;
11507      let cloned = false;
11508      each$e(conditionalTrims, ({condition, action}) => {
11509        if (condition(trimmed)) {
11510          if (!cloned) {
11511            trimmed = body.cloneNode(true);
11512            cloned = true;
11513          }
11514          action(trimmed);
11515        }
11516      });
11517      return trimmed;
11518    };
11519
11520    const cleanupBogusElements = parent => {
11521      const bogusElements = descendants(parent, '[data-mce-bogus]');
11522      each$e(bogusElements, elem => {
11523        const bogusValue = get$9(elem, 'data-mce-bogus');
11524        if (bogusValue === 'all') {
11525          remove$4(elem);
11526        } else if (isBr$5(elem)) {
11527          before$3(elem, SugarElement.fromText(zeroWidth));
11528          remove$4(elem);
11529        } else {
11530          unwrap(elem);
11531        }
11532      });
11533    };
11534    const cleanupInputNames = parent => {
11535      const inputs = descendants(parent, 'input');
11536      each$e(inputs, input => {
11537        remove$9(input, 'name');
11538      });
11539    };
11540
11541    const trimEmptyContents = (editor, html) => {
11542      const blockName = getForcedRootBlock(editor);
11543      const emptyRegExp = new RegExp(`^(<${ blockName }[^>]*>(&nbsp;|&#160;|\\s|\u00a0|<br \\/>|)<\\/${ blockName }>[\r\n]*|<br \\/>[\r\n]*)$`);
11544      return html.replace(emptyRegExp, '');
11545    };
11546    const getPlainTextContent = (editor, body) => {
11547      const doc = editor.getDoc();
11548      const dos = getRootNode(SugarElement.fromDom(editor.getBody()));
11549      const offscreenDiv = SugarElement.fromTag('div', doc);
11550      set$
vendor: 10,042 bytes, lines 11550-11840
115504(offscreenDiv, 'data-mce-bogus', 'all');
11551      setAll(offscreenDiv, {
11552        position: 'fixed',
11553        left: '-9999999px',
11554        top: '0'
11555      });
11556      set$1(offscreenDiv, body.innerHTML);
11557      cleanupBogusElements(offscreenDiv);
11558      cleanupInputNames(offscreenDiv);
11559      const root = getContentContainer(dos);
11560      append$1(root, offscreenDiv);
11561      const content = trim$2(offscreenDiv.dom.innerText);
11562      remove$4(offscreenDiv);
11563      return content;
11564    };
11565    const getContentFromBody = (editor, args, body) => {
11566      let content;
11567      if (args.format === 'raw') {
11568        content = Tools.trim(trim$2(trim$1(body, editor.serializer.getTempAttrs()).innerHTML));
11569      } else if (args.format === 'text') {
11570        content = getPlainTextContent(editor, body);
11571      } else if (args.format === 'tree') {
11572        content = editor.serializer.serialize(body, args);
11573      } else {
11574        content = trimEmptyContents(editor, editor.serializer.serialize(body, args));
11575      }
11576      const shouldTrim = args.format !== 'text' && !isWsPreserveElement(SugarElement.fromDom(body));
11577      return shouldTrim && isString(content) ? Tools.trim(content) : content;
11578    };
11579    const getContentInternal = (editor, args) => Optional.from(editor.getBody()).fold(constant(args.format === 'tree' ? new AstNode('body', 11) : ''), body => getContentFromBody(editor, args, body));
11580
11581    const makeMap$1 = Tools.makeMap;
11582    const Writer = settings => {
11583      const html = [];
11584      settings = settings || {};
11585      const indent = settings.indent;
11586      const indentBefore = makeMap$1(settings.indent_before || '');
11587      const indentAfter = makeMap$1(settings.indent_after || '');
11588      const encode = Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities);
11589      const htmlOutput = settings.element_format !== 'xhtml';
11590      return {
11591        start: (name, attrs, empty) => {
11592          if (indent && indentBefore[name] && html.length > 0) {
11593            const value = html[html.length - 1];
11594            if (value.length > 0 && value !== '\n') {
11595              html.push('\n');
11596            }
11597          }
11598          html.push('<', name);
11599          if (attrs) {
11600            for (let i = 0, l = attrs.length; i < l; i++) {
11601              const attr = attrs[i];
11602              html.push(' ', attr.name, '="', encode(attr.value, true), '"');
11603            }
11604          }
11605          if (!empty || htmlOutput) {
11606            html[html.length] = '>';
11607          } else {
11608            html[html.length] = ' />';
11609          }
11610          if (empty && indent && indentAfter[name] && html.length > 0) {
11611            const value = html[html.length - 1];
11612            if (value.length > 0 && value !== '\n') {
11613              html.push('\n');
11614            }
11615          }
11616        },
11617        end: name => {
11618          let value;
11619          html.push('</', name, '>');
11620          if (indent && indentAfter[name] && html.length > 0) {
11621            value = html[html.length - 1];
11622            if (value.length > 0 && value !== '\n') {
11623              html.push('\n');
11624            }
11625          }
11626        },
11627        text: (text, raw) => {
11628          if (text.length > 0) {
11629            html[html.length] = raw ? text : encode(text);
11630          }
11631        },
11632        cdata: text => {
11633          html.push('<![CDATA[', text, ']]>');
11634        },
11635        comment: text => {
11636          html.push('<!--', text, '-->');
11637        },
11638        pi: (name, text) => {
11639          if (text) {
11640            html.push('<?', name, ' ', encode(text), '?>');
11641          } else {
11642            html.push('<?', name, '?>');
11643          }
11644          if (indent) {
11645            html.push('\n');
11646          }
11647        },
11648        doctype: text => {
11649          html.push('<!DOCTYPE', text, '>', indent ? '\n' : '');
11650        },
11651        reset: () => {
11652          html.length = 0;
11653        },
11654        getContent: () => {
11655          return html.join('').replace(/\n$/, '');
11656        }
11657      };
11658    };
11659
11660    const HtmlSerializer = (settings = {}, schema = Schema()) => {
11661      const writer = Writer(settings);
11662      settings.validate = 'validate' in settings ? settings.validate : true;
11663      const serialize = node => {
11664        const validate = settings.validate;
11665        const handlers = {
11666          3: node => {
11667            var _a;
11668            writer.text((_a = node.value) !== null && _a !== void 0 ? _a : '', node.raw);
11669          },
11670          8: node => {
11671            var _a;
11672            writer.comment((_a = node.value) !== null && _a !== void 0 ? _a : '');
11673          },
11674          7: node => {
11675            writer.pi(node.name, node.value);
11676          },
11677          10: node => {
11678            var _a;
11679            writer.doctype((_a = node.value) !== null && _a !== void 0 ? _a : '');
11680          },
11681          4: node => {
11682            var _a;
11683            writer.cdata((_a = node.value) !== null && _a !== void 0 ? _a : '');
11684          },
11685          11: node => {
11686            let tempNode = node;
11687            if (tempNode = tempNode.firstChild) {
11688              do {
11689                walk(tempNode);
11690              } while (tempNode = tempNode.next);
11691            }
11692          }
11693        };
11694        writer.reset();
11695        const walk = node => {
11696          var _a;
11697          const handler = handlers[node.type];
11698          if (!handler) {
11699            const name = node.name;
11700            const isEmpty = name in schema.getVoidElements();
11701            let attrs = node.attributes;
11702            if (validate && attrs && attrs.length > 1) {
11703              const sortedAttrs = [];
11704              sortedAttrs.map = {};
11705              const elementRule = schema.getElementRule(node.name);
11706              if (elementRule) {
11707                for (let i = 0, l = elementRule.attributesOrder.length; i < l; i++) {
11708                  const attrName = elementRule.attributesOrder[i];
11709                  if (attrName in attrs.map) {
11710                    const attrValue = attrs.map[attrName];
11711                    sortedAttrs.map[attrName] = attrValue;
11712                    sortedAttrs.push({
11713                      name: attrName,
11714                      value: attrValue
11715                    });
11716                  }
11717                }
11718                for (let i = 0, l = attrs.length; i < l; i++) {
11719                  const attrName = attrs[i].name;
11720                  if (!(attrName in sortedAttrs.map)) {
11721                    const attrValue = attrs.map[attrName];
11722                    sortedAttrs.map[attrName] = attrValue;
11723                    sortedAttrs.push({
11724                      name: attrName,
11725                      value: attrValue
11726                    });
11727                  }
11728                }
11729                attrs = sortedAttrs;
11730              }
11731            }
11732            writer.start(name, attrs, isEmpty);
11733            if (isNonHtmlElementRootName(name)) {
11734              if (isString(node.value)) {
11735                writer.text(node.value, true);
11736              }
11737              writer.end(name);
11738            } else {
11739              if (!isEmpty) {
11740                let child = node.firstChild;
11741                if (child) {
11742                  if ((name === 'pre' || name === 'textarea') && child.type === 3 && ((_a = child.value) === null || _a === void 0 ? void 0 : _a[0]) === '\n') {
11743                    writer.text('\n', true);
11744                  }
11745                  do {
11746                    walk(child);
11747                  } while (child = child.next);
11748                }
11749                writer.end(name);
11750              }
11751            }
11752          } else {
11753            handler(node);
11754          }
11755        };
11756        if (node.type === 1 && !settings.inner) {
11757          walk(node);
11758        } else if (node.type === 3) {
11759          handlers[3](node);
11760        } else {
11761          handlers[11](node);
11762        }
11763        return writer.getContent();
11764      };
11765      return { serialize };
11766    };
11767
11768    const nonInheritableStyles = new Set();
11769    (() => {
11770      const nonInheritableStylesArr = [
11771        'margin',
11772        'margin-left',
11773        'margin-right',
11774        'margin-top',
11775        'margin-bottom',
11776        'padding',
11777        'padding-left',
11778        'padding-right',
11779        'padding-top',
11780        'padding-bottom',
11781        'border',
11782        'border-width',
11783        'border-style',
11784        'border-color',
11785        'background',
11786        'background-attachment',
11787        'background-clip',
11788        'background-image',
11789        'background-origin',
11790        'background-position',
11791        'background-repeat',
11792        'background-size',
11793        'float',
11794        'position',
11795        'left',
11796        'right',
11797        'top',
11798        'bottom',
11799        'z-index',
11800        'display',
11801        'transform',
11802        'width',
11803        'max-width',
11804        'min-width',
11805        'height',
11806        'max-height',
11807        'min-height',
11808        'overflow',
11809        'overflow-x',
11810        'overflow-y',
11811        'text-overflow',
11812        'vertical-align',
11813        'transition',
11814        'transition-delay',
11815        'transition-duration',
11816        'transition-property',
11817        'transition-timing-function'
11818      ];
11819      each$e(nonInheritableStylesArr, style => {
11820        nonInheritableStyles.add(style);
11821      });
11822    })();
11823    const conditionalNonInheritableStyles = new Set();
11824    (() => {
11825      const conditionalNonInheritableStylesArr = ['background-color'];
11826      each$e(conditionalNonInheritableStylesArr, style => {
11827        conditionalNonInheritableStyles.add(style);
11828      });
11829    })();
11830    const shorthandStyleProps = [
11831      'font',
11832      'text-decoration',
11833      'text-emphasis'
11834    ];
11835    const getStyles$1 = (dom, node) => dom.parseStyle(dom.getAttrib(node, 'style'));
11836    const getStyleProps = (dom, node) => keys(getStyles$1(dom, node));
11837    const isNonInheritableStyle = style => nonInheritableStyles.has(style);
11838    const isConditionalNonInheritableStyle = style => conditionalNonInheritableStyles.has(style);
11839    const hasNonInheritableStyles = (dom, node) => exists(getStyleProps(dom, node), style => isNonInheritableStyle(style));
11840    const hasConditionalNonInheritableStyles = (dom, node) => hasNonInheritableStyles(dom, node) && exists(getStyleProps(dom, node), style => isConditional
vendor: 10,717 bytes, lines 11840-12042
11840NonInheritableStyle(style));
11841    const getLonghandStyleProps = styles => filter$5(styles, style => exists(shorthandStyleProps, prop => startsWith(style, prop)));
11842    const hasStyleConflict = (dom, node, parentNode) => {
11843      const nodeStyleProps = getStyleProps(dom, node);
11844      const parentNodeStyleProps = getStyleProps(dom, parentNode);
11845      const valueMismatch = prop => {
11846        var _a, _b;
11847        const nodeValue = (_a = dom.getStyle(node, prop)) !== null && _a !== void 0 ? _a : '';
11848        const parentValue = (_b = dom.getStyle(parentNode, prop)) !== null && _b !== void 0 ? _b : '';
11849        return isNotEmpty(nodeValue) && isNotEmpty(parentValue) && nodeValue !== parentValue;
11850      };
11851      return exists(nodeStyleProps, nodeStyleProp => {
11852        const propExists = props => exists(props, prop => prop === nodeStyleProp);
11853        if (!propExists(parentNodeStyleProps) && propExists(shorthandStyleProps)) {
11854          const longhandProps = getLonghandStyleProps(parentNodeStyleProps);
11855          return exists(longhandProps, valueMismatch);
11856        } else {
11857          return valueMismatch(nodeStyleProp);
11858        }
11859      });
11860    };
11861
11862    const isChar = (forward, predicate, pos) => Optional.from(pos.container()).filter(isText$b).exists(text => {
11863      const delta = forward ? 0 : -1;
11864      return predicate(text.data.charAt(pos.offset() + delta));
11865    });
11866    const isBeforeSpace = curry(isChar, true, isWhiteSpace);
11867    const isAfterSpace = curry(isChar, false, isWhiteSpace);
11868    const isEmptyText = pos => {
11869      const container = pos.container();
11870      return isText$b(container) && (container.data.length === 0 || isZwsp(container.data) && BookmarkManager.isBookmarkNode(container.parentNode));
11871    };
11872    const matchesElementPosition = (before, predicate) => pos => getChildNodeAtRelativeOffset(before ? 0 : -1, pos).filter(predicate).isSome();
11873    const isImageBlock = node => isImg(node) && get$7(SugarElement.fromDom(node), 'display') === 'block';
11874    const isCefNode = node => isContentEditableFalse$b(node) && !isBogusAll(node);
11875    const isBeforeImageBlock = matchesElementPosition(true, isImageBlock);
11876    const isAfterImageBlock = matchesElementPosition(false, isImageBlock);
11877    const isBeforeMedia = matchesElementPosition(true, isMedia$2);
11878    const isAfterMedia = matchesElementPosition(false, isMedia$2);
11879    const isBeforeTable = matchesElementPosition(true, isTable$2);
11880    const isAfterTable = matchesElementPosition(false, isTable$2);
11881    const isBeforeContentEditableFalse = matchesElementPosition(true, isCefNode);
11882    const isAfterContentEditableFalse = matchesElementPosition(false, isCefNode);
11883
11884    const dropLast = xs => xs.slice(0, -1);
11885    const parentsUntil = (start, root, predicate) => {
11886      if (contains(root, start)) {
11887        return dropLast(parents$1(start, elm => {
11888          return predicate(elm) || eq(elm, root);
11889        }));
11890      } else {
11891        return [];
11892      }
11893    };
11894    const parents = (start, root) => parentsUntil(start, root, never);
11895    const parentsAndSelf = (start, root) => [start].concat(parents(start, root));
11896
11897    const navigateIgnoreEmptyTextNodes = (forward, root, from) => navigateIgnore(forward, root, from, isEmptyText);
11898    const isBlock$1 = schema => el => schema.isBlock(name(el));
11899    const getClosestBlock$1 = (root, pos, schema) => find$2(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$1(schema));
11900    const isAtBeforeAfterBlockBoundary = (forward, root, pos, schema) => navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(newPos => getClosestBlock$1(root, pos, schema).fold(() => !isInSameBlock(newPos, pos, root.dom), fromBlock => !isInSameBlock(newPos, pos, root.dom) && contains(fromBlock, SugarElement.fromDom(newPos.container()))));
11901    const isAtBlockBoundary = (forward, root, pos, schema) => getClosestBlock$1(root, pos, schema).fold(() => navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(newPos => !isInSameBlock(newPos, pos, root.dom)), parent => navigateIgnoreEmptyTextNodes(forward, parent.dom, pos).isNone());
11902    const isAtStartOfBlock = curry(isAtBlockBoundary, false);
11903    const isAtEndOfBlock = curry(isAtBlockBoundary, true);
11904    const isBeforeBlock = curry(isAtBeforeAfterBlockBoundary, false);
11905    const isAfterBlock = curry(isAtBeforeAfterBlockBoundary, true);
11906
11907    const isBr$1 = pos => getElementFromPosition(pos).exists(isBr$5);
11908    const findBr = (forward, root, pos, schema) => {
11909      const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), el => schema.isBlock(name(el)));
11910      const scope = head(parentBlocks).getOr(root);
11911      return fromPosition(forward, scope.dom, pos).filter(isBr$1);
11912    };
11913    const isBeforeBr$1 = (root, pos, schema) => getElementFromPosition(pos).exists(isBr$5) || findBr(true, root, pos, schema).isSome();
11914    const isAfterBr = (root, pos, schema) => getElementFromPrevPosition(pos).exists(isBr$5) || findBr(false, root, pos, schema).isSome();
11915    const findPreviousBr = curry(findBr, false);
11916    const findNextBr = curry(findBr, true);
11917
11918    const isInMiddleOfText = pos => CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd();
11919    const getClosestBlock = (root, pos, schema) => {
11920      const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), el => schema.isBlock(name(el)));
11921      return head(parentBlocks).getOr(root);
11922    };
11923    const hasSpaceBefore = (root, pos, schema) => {
11924      if (isInMiddleOfText(pos)) {
11925        return isAfterSpace(pos);
11926      } else {
11927        return isAfterSpace(pos) || prevPosition(getClosestBlock(root, pos, schema).dom, pos).exists(isAfterSpace);
11928      }
11929    };
11930    const hasSpaceAfter = (root, pos, schema) => {
11931      if (isInMiddleOfText(pos)) {
11932        return isBeforeSpace(pos);
11933      } else {
11934        return isBeforeSpace(pos) || nextPosition(getClosestBlock(root, pos, schema).dom, pos).exists(isBeforeSpace);
11935      }
11936    };
11937    const isPreValue = value => contains$2([
11938      'pre',
11939      'pre-wrap'
11940    ], value);
11941    const isInPre = pos => getElementFromPosition(pos).bind(elm => closest$4(elm, isElement$7)).exists(elm => isPreValue(get$7(elm, 'white-space')));
11942    const isAtBeginningOfBody = (root, pos) => prevPosition(root.dom, pos).isNone();
11943    const isAtEndOfBody = (root, pos) => nextPosition(root.dom, pos).isNone();
11944    const isAtLineBoundary = (root, pos, schema) => isAtBeginningOfBody(root, pos) || isAtEndOfBody(root, pos) || isAtStartOfBlock(root, pos, schema) || isAtEndOfBlock(root, pos, schema) || isAfterBr(root, pos, schema) || isBeforeBr$1(root, pos, schema);
11945    const isCefBlock = node => isNonNullable(node) && isContentEditableFalse$b(node) && isBlockLike(node);
11946    const isSiblingCefBlock = (root, direction) => container => {
11947      return isCefBlock(new DomTreeWalker(container, root)[direction]());
11948    };
11949    const isBeforeCefBlock = (root, pos) => {
11950      const nextPos = nextPosition(root.dom, pos).getOr(pos);
11951      const isNextCefBlock = isSiblingCefBlock(root.dom, 'next');
11952      return pos.isAtEnd() && (isNextCefBlock(pos.container()) || isNextCefBlock(nextPos.container()));
11953    };
11954    const isAfterCefBlock = (root, pos) => {
11955      const prevPos = prevPosition(root.dom, pos).getOr(pos);
11956      const isPrevCefBlock = isSiblingCefBlock(root.dom, 'prev');
11957      return pos.isAtStart() && (isPrevCefBlock(pos.container()) || isPrevCefBlock(prevPos.container()));
11958    };
11959    const needsToHaveNbsp = (root, pos, schema) => {
11960      if (isInPre(pos)) {
11961        return false;
11962      } else {
11963        return isAtLineBoundary(root, pos, schema) || hasSpaceBefore(root, pos, schema) || hasSpaceAfter(root, pos, schema);
11964      }
11965    };
11966    const needsToBeNbspLeft = (root, pos, schema) => {
11967      if (isInPre(pos)) {
11968        return false;
11969      } else {
11970        return isAtStartOfBlock(root, pos, schema) || isBeforeBlock(root, pos, schema) || isAfterBr(root, pos, schema) || hasSpaceBefore(root, pos, schema) || isAfterCefBlock(root, pos);
11971      }
11972    };
11973    const leanRight = pos => {
11974      const container = pos.container();
11975      const offset = pos.offset();
11976      if (isText$b(container) && offset < container.data.length) {
11977        return CaretPosition(container, offset + 1);
11978      } else {
11979        return pos;
11980      }
11981    };
11982    const needsToBeNbspRight = (root, pos, schema) => {
11983      if (isInPre(pos)) {
11984        return false;
11985      } else {
11986        return isAtEndOfBlock(root, pos, schema) || isAfterBlock(root, pos, schema) || isBeforeBr$1(root, pos, schema) || hasSpaceAfter(root, pos, schema) || isBeforeCefBlock(root, pos);
11987      }
11988    };
11989    const needsToBeNbsp = (root, pos, schema) => needsToBeNbspLeft(root, pos, schema) || needsToBeNbspRight(root, leanRight(pos), schema);
11990    const isNbspAt = (text, offset) => isNbsp(text.charAt(offset));
11991    const isWhiteSpaceAt = (text, offset) => isWhiteSpace(text.charAt(offset));
11992    const hasNbsp = pos => {
11993      const container = pos.container();
11994      return isText$b(container) && contains$1(container.data, nbsp);
11995    };
11996    const normalizeNbspMiddle = text => {
11997      const chars = text.split('');
11998      return map$3(chars, (chr, i) => {
11999        if (isNbsp(chr) && i > 0 && i < chars.length - 1 && isContent(chars[i - 1]) && isContent(chars[i + 1])) {
12000          return ' ';
12001        } else {
12002          return chr;
12003        }
12004      }).join('');
12005    };
12006    const normalizeNbspAtStart = (root, node, makeNbsp, schema) => {
12007      const text = node.data;
12008      const firstPos = CaretPosition(node, 0);
12009      if (!makeNbsp && isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos, schema)) {
12010        node.data = ' ' + text.slice(1);
12011        return true;
12012      } else if (makeNbsp && isWhiteSpaceAt(text, 0) && needsToBeNbspLeft(root, firstPos, schema)) {
12013        node.data = nbsp + text.slice(1);
12014        return true;
12015      } else {
12016        return false;
12017      }
12018    };
12019    const normalizeNbspInMiddleOfTextNode = node => {
12020      const text = node.data;
12021      const newText = normalizeNbspMiddle(text);
12022      if (newText !== text) {
12023        node.data = newText;
12024        return true;
12025      } else {
12026        return false;
12027      }
12028    };
12029    const normalizeNbspAtEnd = (root, node, makeNbsp, schema) => {
12030      const text = node.data;
12031      const lastPos = CaretPosition(node, text.length - 1);
12032      if (!makeNbsp && isNbspAt(text, text.length - 1) && !needsToBeNbsp(root, lastPos, schema)) {
12033        node.data = text.slice(0, -1) + ' ';
12034        return true;
12035      } else if (makeNbsp && isWhiteSpaceAt(text, text.length - 1) && needsToBeNbspRight(root, lastPos, schema)) {
12036        node.data = text.slice(0, -1) + nbsp;
12037        return true;
12038      } else {
12039        return false;
12040      }
12041    };
12042    const normalizeNbsps
vendor: 854 bytes, lines 12042-12060
12042$1 = (root, pos, schema) => {
12043      const container = pos.container();
12044      if (!isText$b(container)) {
12045        return Optional.none();
12046      }
12047      if (hasNbsp(pos)) {
12048        const normalized = normalizeNbspAtStart(root, container, false, schema) || normalizeNbspInMiddleOfTextNode(container) || normalizeNbspAtEnd(root, container, false, schema);
12049        return someIf(normalized, pos);
12050      } else if (needsToBeNbsp(root, pos, schema)) {
12051        const normalized = normalizeNbspAtStart(root, container, true, schema) || normalizeNbspAtEnd(root, container, true, schema);
12052        return someIf(normalized, pos);
12053      } else {
12054        return Optional.none();
12055      }
12056    };
12057    const normalizeNbspsInEditor = editor => {
12058      const root = SugarElement.fromDom(editor.getBody());
12059      if (editor.selection.isCollapsed()) {
12060        normalizeNbsps$1
vendor: 21,816 bytes, lines 12060-12495
12060(root, CaretPosition.fromRangeStart(editor.selection.getRng()), editor.schema).each(pos => {
12061          editor.selection.setRng(pos.toRange());
12062        });
12063      }
12064    };
12065
12066    const normalize$1 = (node, offset, count, schema) => {
12067      if (count === 0) {
12068        return;
12069      }
12070      const elm = SugarElement.fromDom(node);
12071      const root = ancestor$4(elm, el => schema.isBlock(name(el))).getOr(elm);
12072      const whitespace = node.data.slice(offset, offset + count);
12073      const isEndOfContent = offset + count >= node.data.length && needsToBeNbspRight(root, CaretPosition(node, node.data.length), schema);
12074      const isStartOfContent = offset === 0 && needsToBeNbspLeft(root, CaretPosition(node, 0), schema);
12075      node.replaceData(offset, count, normalize$4(whitespace, 4, isStartOfContent, isEndOfContent));
12076    };
12077    const normalizeWhitespaceAfter = (node, offset, schema) => {
12078      const content = node.data.slice(offset);
12079      const whitespaceCount = content.length - lTrim(content).length;
12080      normalize$1(node, offset, whitespaceCount, schema);
12081    };
12082    const normalizeWhitespaceBefore = (node, offset, schema) => {
12083      const content = node.data.slice(0, offset);
12084      const whitespaceCount = content.length - rTrim(content).length;
12085      normalize$1(node, offset - whitespaceCount, whitespaceCount, schema);
12086    };
12087    const mergeTextNodes = (prevNode, nextNode, schema, normalizeWhitespace, mergeToPrev = true) => {
12088      const whitespaceOffset = rTrim(prevNode.data).length;
12089      const newNode = mergeToPrev ? prevNode : nextNode;
12090      const removeNode = mergeToPrev ? nextNode : prevNode;
12091      if (mergeToPrev) {
12092        newNode.appendData(removeNode.data);
12093      } else {
12094        newNode.insertData(0, removeNode.data);
12095      }
12096      remove$4(SugarElement.fromDom(removeNode));
12097      if (normalizeWhitespace) {
12098        normalizeWhitespaceAfter(newNode, whitespaceOffset, schema);
12099      }
12100      return newNode;
12101    };
12102
12103    const needsReposition = (pos, elm) => {
12104      const container = pos.container();
12105      const offset = pos.offset();
12106      return !CaretPosition.isTextPosition(pos) && container === elm.parentNode && offset > CaretPosition.before(elm).offset();
12107    };
12108    const reposition = (elm, pos) => needsReposition(pos, elm) ? CaretPosition(pos.container(), pos.offset() - 1) : pos;
12109    const beforeOrStartOf = node => isText$b(node) ? CaretPosition(node, 0) : CaretPosition.before(node);
12110    const afterOrEndOf = node => isText$b(node) ? CaretPosition(node, node.data.length) : CaretPosition.after(node);
12111    const getPreviousSiblingCaretPosition = elm => {
12112      if (isCaretCandidate$3(elm.previousSibling)) {
12113        return Optional.some(afterOrEndOf(elm.previousSibling));
12114      } else {
12115        return elm.previousSibling ? lastPositionIn(elm.previousSibling) : Optional.none();
12116      }
12117    };
12118    const getNextSiblingCaretPosition = elm => {
12119      if (isCaretCandidate$3(elm.nextSibling)) {
12120        return Optional.some(beforeOrStartOf(elm.nextSibling));
12121      } else {
12122        return elm.nextSibling ? firstPositionIn(elm.nextSibling) : Optional.none();
12123      }
12124    };
12125    const findCaretPositionBackwardsFromElm = (rootElement, elm) => {
12126      return Optional.from(elm.previousSibling ? elm.previousSibling : elm.parentNode).bind(node => prevPosition(rootElement, CaretPosition.before(node))).orThunk(() => nextPosition(rootElement, CaretPosition.after(elm)));
12127    };
12128    const findCaretPositionForwardsFromElm = (rootElement, elm) => nextPosition(rootElement, CaretPosition.after(elm)).orThunk(() => prevPosition(rootElement, CaretPosition.before(elm)));
12129    const findCaretPositionBackwards = (rootElement, elm) => getPreviousSiblingCaretPosition(elm).orThunk(() => getNextSiblingCaretPosition(elm)).orThunk(() => findCaretPositionBackwardsFromElm(rootElement, elm));
12130    const findCaretPositionForward = (rootElement, elm) => getNextSiblingCaretPosition(elm).orThunk(() => getPreviousSiblingCaretPosition(elm)).orThunk(() => findCaretPositionForwardsFromElm(rootElement, elm));
12131    const findCaretPosition = (forward, rootElement, elm) => forward ? findCaretPositionForward(rootElement, elm) : findCaretPositionBackwards(rootElement, elm);
12132    const findCaretPosOutsideElmAfterDelete = (forward, rootElement, elm) => findCaretPosition(forward, rootElement, elm).map(curry(reposition, elm));
12133    const setSelection$1 = (editor, forward, pos) => {
12134      pos.fold(() => {
12135        editor.focus();
12136      }, pos => {
12137        editor.selection.setRng(pos.toRange(), forward);
12138      });
12139    };
12140    const eqRawNode = rawNode => elm => elm.dom === rawNode;
12141    const isBlock = (editor, elm) => elm && has$2(editor.schema.getBlockElements(), name(elm));
12142    const paddEmptyBlock = (schema, elm, preserveEmptyCaret) => {
12143      if (isEmpty$2(schema, elm)) {
12144        const br = SugarElement.fromHtml('<br data-mce-bogus="1">');
12145        if (preserveEmptyCaret) {
12146          each$e(children$1(elm), node => {
12147            if (!isEmptyCaretFormatElement(node)) {
12148              remove$4(node);
12149            }
12150          });
12151        } else {
12152          empty(elm);
12153        }
12154        append$1(elm, br);
12155        return Optional.some(CaretPosition.before(br.dom));
12156      } else {
12157        return Optional.none();
12158      }
12159    };
12160    const deleteNormalized = (elm, afterDeletePosOpt, schema, normalizeWhitespace) => {
12161      const prevTextOpt = prevSibling(elm).filter(isText$c);
12162      const nextTextOpt = nextSibling(elm).filter(isText$c);
12163      remove$4(elm);
12164      return lift3(prevTextOpt, nextTextOpt, afterDeletePosOpt, (prev, next, pos) => {
12165        const prevNode = prev.dom, nextNode = next.dom;
12166        const offset = prevNode.data.length;
12167        mergeTextNodes(prevNode, nextNode, schema, normalizeWhitespace);
12168        return pos.container() === nextNode ? CaretPosition(prevNode, offset) : pos;
12169      }).orThunk(() => {
12170        if (normalizeWhitespace) {
12171          prevTextOpt.each(elm => normalizeWhitespaceBefore(elm.dom, elm.dom.length, schema));
12172          nextTextOpt.each(elm => normalizeWhitespaceAfter(elm.dom, 0, schema));
12173        }
12174        return afterDeletePosOpt;
12175      });
12176    };
12177    const isInlineElement = (editor, element) => has$2(editor.schema.getTextInlineElements(), name(element));
12178    const deleteElement$2 = (editor, forward, elm, moveCaret = true, preserveEmptyCaret = false) => {
12179      const afterDeletePos = findCaretPosOutsideElmAfterDelete(forward, editor.getBody(), elm.dom);
12180      const parentBlock = ancestor$4(elm, curry(isBlock, editor), eqRawNode(editor.getBody()));
12181      const normalizedAfterDeletePos = deleteNormalized(elm, afterDeletePos, editor.schema, isInlineElement(editor, elm));
12182      if (editor.dom.isEmpty(editor.getBody())) {
12183        editor.setContent('');
12184        editor.selection.setCursorLocation();
12185      } else {
12186        parentBlock.bind(elm => paddEmptyBlock(editor.schema, elm, preserveEmptyCaret)).fold(() => {
12187          if (moveCaret) {
12188            setSelection$1(editor, forward, normalizedAfterDeletePos);
12189          }
12190        }, paddPos => {
12191          if (moveCaret) {
12192            setSelection$1(editor, forward, Optional.some(paddPos));
12193          }
12194        });
12195      }
12196    };
12197
12198    const strongRtl = /[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/;
12199    const hasStrongRtl = text => strongRtl.test(text);
12200
12201    const isInlineTarget = (editor, elm) => is$1(SugarElement.fromDom(elm), getInlineBoundarySelector(editor)) && !isTransparentBlock(editor.schema, elm) && editor.dom.isEditable(elm);
12202    const isRtl = element => {
12203      var _a;
12204      return DOMUtils.DOM.getStyle(element, 'direction', true) === 'rtl' || hasStrongRtl((_a = element.textContent) !== null && _a !== void 0 ? _a : '');
12205    };
12206    const findInlineParents = (isInlineTarget, rootNode, pos) => filter$5(DOMUtils.DOM.getParents(pos.container(), '*', rootNode), isInlineTarget);
12207    const findRootInline = (isInlineTarget, rootNode, pos) => {
12208      const parents = findInlineParents(isInlineTarget, rootNode, pos);
12209      return Optional.from(parents[parents.length - 1]);
12210    };
12211    const hasSameParentBlock = (rootNode, node1, node2) => {
12212      const block1 = getParentBlock$3(node1, rootNode);
12213      const block2 = getParentBlock$3(node2, rootNode);
12214      return isNonNullable(block1) && block1 === block2;
12215    };
12216    const isAtZwsp = pos => isBeforeInline(pos) || isAfterInline(pos);
12217    const normalizePosition = (forward, pos) => {
12218      const container = pos.container(), offset = pos.offset();
12219      if (forward) {
12220        if (isCaretContainerInline(container)) {
12221          if (isText$b(container.nextSibling)) {
12222            return CaretPosition(container.nextSibling, 0);
12223          } else {
12224            return CaretPosition.after(container);
12225          }
12226        } else {
12227          return isBeforeInline(pos) ? CaretPosition(container, offset + 1) : pos;
12228        }
12229      } else {
12230        if (isCaretContainerInline(container)) {
12231          if (isText$b(container.previousSibling)) {
12232            return CaretPosition(container.previousSibling, container.previousSibling.data.length);
12233          } else {
12234            return CaretPosition.before(container);
12235          }
12236        } else {
12237          return isAfterInline(pos) ? CaretPosition(container, offset - 1) : pos;
12238        }
12239      }
12240    };
12241    const normalizeForwards = curry(normalizePosition, true);
12242    const normalizeBackwards = curry(normalizePosition, false);
12243
12244    const execCommandIgnoreInputEvents = (editor, command) => {
12245      const inputBlocker = e => e.stopImmediatePropagation();
12246      editor.on('beforeinput input', inputBlocker, true);
12247      editor.getDoc().execCommand(command);
12248      editor.off('beforeinput input', inputBlocker);
12249    };
12250    const execEditorDeleteCommand = editor => {
12251      editor.execCommand('delete');
12252    };
12253    const execNativeDeleteCommand = editor => execCommandIgnoreInputEvents(editor, 'Delete');
12254    const execNativeForwardDeleteCommand = editor => execCommandIgnoreInputEvents(editor, 'ForwardDelete');
12255    const isBeforeRoot = rootNode => elm => is$2(parent(elm), rootNode, eq);
12256    const isTextBlockOrListItem = element => isTextBlock$2(element) || isListItem$1(element);
12257    const getParentBlock$2 = (rootNode, elm) => {
12258      if (contains(rootNode, elm)) {
12259        return closest$4(elm, isTextBlockOrListItem, isBeforeRoot(rootNode));
12260      } else {
12261        return Optional.none();
12262      }
12263    };
12264    const paddEmptyBody = (editor, moveSelection = true) => {
12265      if (editor.dom.isEmpty(editor.getBody())) {
12266        editor.setContent('', { no_selection: !moveSelection });
12267      }
12268    };
12269    const willDeleteLastPositionInElement = (forward, fromPos, elm) => lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => {
12270      const normalizedFirstPos = normalizePosition(true, firstPos);
12271      const normalizedLastPos = normalizePosition(false, lastPos);
12272      const normalizedFromPos = normalizePosition(false, fromPos);
12273      if (forward) {
12274        return nextPosition(elm, normalizedFromPos).exists(nextPos => nextPos.isEqual(normalizedLastPos) && fromPos.isEqual(normalizedFirstPos));
12275      } else {
12276        return prevPosition(elm, normalizedFromPos).exists(prevPos => prevPos.isEqual(normalizedFirstPos) && fromPos.isEqual(normalizedLastPos));
12277      }
12278    }).getOr(true);
12279    const freefallRtl = root => {
12280      const child = isComment$1(root) ? prevSibling(root) : lastChild(root);
12281      return child.bind(freefallRtl).orThunk(() => Optional.some(root));
12282    };
12283    const deleteRangeContents = (editor, rng, root, moveSelection = true) => {
12284      var _a;
12285      rng.deleteContents();
12286      const lastNode = freefallRtl(root).getOr(root);
12287      const lastBlock = SugarElement.fromDom((_a = editor.dom.getParent(lastNode.dom, editor.dom.isBlock)) !== null && _a !== void 0 ? _a : root.dom);
12288      if (lastBlock.dom === editor.getBody()) {
12289        paddEmptyBody(editor, moveSelection);
12290      } else if (isEmpty$2(editor.schema, lastBlock, { checkRootAsContent: false })) {
12291        fillWithPaddingBr(lastBlock);
12292        if (moveSelection) {
12293          editor.selection.setCursorLocation(lastBlock.dom, 0);
12294        }
12295      }
12296      if (!eq(root, lastBlock)) {
12297        const additionalCleanupNodes = is$2(parent(lastBlock), root) ? [] : siblings(lastBlock);
12298        each$e(additionalCleanupNodes.concat(children$1(root)), node => {
12299          if (!eq(node, lastBlock) && !contains(node, lastBlock) && isEmpty$2(editor.schema, node)) {
12300            remove$4(node);
12301          }
12302        });
12303      }
12304    };
12305
12306    const isRootFromElement = root => cur => eq(root, cur);
12307    const getTableCells = table => descendants(table, 'td,th');
12308    const getTable$1 = (node, isRoot) => getClosestTable(SugarElement.fromDom(node), isRoot);
12309    const selectionInTableWithNestedTable = details => {
12310      return lift2(details.startTable, details.endTable, (startTable, endTable) => {
12311        const isStartTableParentOfEndTable = descendant(startTable, t => eq(t, endTable));
12312        const isEndTableParentOfStartTable = descendant(endTable, t => eq(t, startTable));
12313        return !isStartTableParentOfEndTable && !isEndTableParentOfStartTable ? details : {
12314          ...details,
12315          startTable: isStartTableParentOfEndTable ? Optional.none() : details.startTable,
12316          endTable: isEndTableParentOfStartTable ? Optional.none() : details.endTable,
12317          isSameTable: false,
12318          isMultiTable: false
12319        };
12320      }).getOr(details);
12321    };
12322    const adjustQuirksInDetails = details => {
12323      return selectionInTableWithNestedTable(details);
12324    };
12325    const getTableDetailsFromRange = (rng, isRoot) => {
12326      const startTable = getTable$1(rng.startContainer, isRoot);
12327      const endTable = getTable$1(rng.endContainer, isRoot);
12328      const isStartInTable = startTable.isSome();
12329      const isEndInTable = endTable.isSome();
12330      const isSameTable = lift2(startTable, endTable, eq).getOr(false);
12331      const isMultiTable = !isSameTable && isStartInTable && isEndInTable;
12332      return adjustQuirksInDetails({
12333        startTable,
12334        endTable,
12335        isStartInTable,
12336        isEndInTable,
12337        isSameTable,
12338        isMultiTable
12339      });
12340    };
12341
12342    const tableCellRng = (start, end) => ({
12343      start,
12344      end
12345    });
12346    const tableSelection = (rng, table, cells) => ({
12347      rng,
12348      table,
12349      cells
12350    });
12351    const deleteAction = Adt.generate([
12352      {
12353        singleCellTable: [
12354          'rng',
12355          'cell'
12356        ]
12357      },
12358      { fullTable: ['table'] },
12359      {
12360        partialTable: [
12361          'cells',
12362          'outsideDetails'
12363        ]
12364      },
12365      {
12366        multiTable: [
12367          'startTableCells',
12368          'endTableCells',
12369          'betweenRng'
12370        ]
12371      }
12372    ]);
12373    const getClosestCell$1 = (container, isRoot) => closest$3(SugarElement.fromDom(container), 'td,th', isRoot);
12374    const isExpandedCellRng = cellRng => !eq(cellRng.start, cellRng.end);
12375    const getTableFromCellRng = (cellRng, isRoot) => getClosestTable(cellRng.start, isRoot).bind(startParentTable => getClosestTable(cellRng.end, isRoot).bind(endParentTable => someIf(eq(startParentTable, endParentTable), startParentTable)));
12376    const isSingleCellTable = (cellRng, isRoot) => !isExpandedCellRng(cellRng) && getTableFromCellRng(cellRng, isRoot).exists(table => {
12377      const rows = table.dom.rows;
12378      return rows.length === 1 && rows[0].cells.length === 1;
12379    });
12380    const getCellRng = (rng, isRoot) => {
12381      const startCell = getClosestCell$1(rng.startContainer, isRoot);
12382      const endCell = getClosestCell$1(rng.endContainer, isRoot);
12383      return lift2(startCell, endCell, tableCellRng);
12384    };
12385    const getCellRangeFromStartTable = isRoot => startCell => getClosestTable(startCell, isRoot).bind(table => last$2(getTableCells(table)).map(endCell => tableCellRng(startCell, endCell)));
12386    const getCellRangeFromEndTable = isRoot => endCell => getClosestTable(endCell, isRoot).bind(table => head(getTableCells(table)).map(startCell => tableCellRng(startCell, endCell)));
12387    const getTableSelectionFromCellRng = isRoot => cellRng => getTableFromCellRng(cellRng, isRoot).map(table => tableSelection(cellRng, table, getTableCells(table)));
12388    const getTableSelections = (cellRng, selectionDetails, rng, isRoot) => {
12389      if (rng.collapsed || !cellRng.forall(isExpandedCellRng)) {
12390        return Optional.none();
12391      } else if (selectionDetails.isSameTable) {
12392        const sameTableSelection = cellRng.bind(getTableSelectionFromCellRng(isRoot));
12393        return Optional.some({
12394          start: sameTableSelection,
12395          end: sameTableSelection
12396        });
12397      } else {
12398        const startCell = getClosestCell$1(rng.startContainer, isRoot);
12399        const endCell = getClosestCell$1(rng.endContainer, isRoot);
12400        const startTableSelection = startCell.bind(getCellRangeFromStartTable(isRoot)).bind(getTableSelectionFromCellRng(isRoot));
12401        const endTableSelection = endCell.bind(getCellRangeFromEndTable(isRoot)).bind(getTableSelectionFromCellRng(isRoot));
12402        return Optional.some({
12403          start: startTableSelection,
12404          end: endTableSelection
12405        });
12406      }
12407    };
12408    const getCellIndex = (cells, cell) => findIndex$2(cells, x => eq(x, cell));
12409    const getSelectedCells = tableSelection => lift2(getCellIndex(tableSelection.cells, tableSelection.rng.start), getCellIndex(tableSelection.cells, tableSelection.rng.end), (startIndex, endIndex) => tableSelection.cells.slice(startIndex, endIndex + 1));
12410    const isSingleCellTableContentSelected = (optCellRng, rng, isRoot) => optCellRng.exists(cellRng => isSingleCellTable(cellRng, isRoot) && hasAllContentsSelected(cellRng.start, rng));
12411    const unselectCells = (rng, selectionDetails) => {
12412      const {startTable, endTable} = selectionDetails;
12413      const otherContentRng = rng.cloneRange();
12414      startTable.each(table => otherContentRng.setStartAfter(table.dom));
12415      endTable.each(table => otherContentRng.setEndBefore(table.dom));
12416      return otherContentRng;
12417    };
12418    const handleSingleTable = (cellRng, selectionDetails, rng, isRoot) => getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(({start, end}) => start.or(end)).bind(tableSelection => {
12419      const {isSameTable} = selectionDetails;
12420      const selectedCells = getSelectedCells(tableSelection).getOr([]);
12421      if (isSameTable && tableSelection.cells.length === selectedCells.length) {
12422        return Optional.some(deleteAction.fullTable(tableSelection.table));
12423      } else if (selectedCells.length > 0) {
12424        if (isSameTable) {
12425          return Optional.some(deleteAction.partialTable(selectedCells, Optional.none()));
12426        } else {
12427          const otherContentRng = unselectCells(rng, selectionDetails);
12428          return Optional.some(deleteAction.partialTable(selectedCells, Optional.some({
12429            ...selectionDetails,
12430            rng: otherContentRng
12431          })));
12432        }
12433      } else {
12434        return Optional.none();
12435      }
12436    });
12437    const handleMultiTable = (cellRng, selectionDetails, rng, isRoot) => getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(({start, end}) => {
12438      const startTableSelectedCells = start.bind(getSelectedCells).getOr([]);
12439      const endTableSelectedCells = end.bind(getSelectedCells).getOr([]);
12440      if (startTableSelectedCells.length > 0 && endTableSelectedCells.length > 0) {
12441        const otherContentRng = unselectCells(rng, selectionDetails);
12442        return Optional.some(deleteAction.multiTable(startTableSelectedCells, endTableSelectedCells, otherContentRng));
12443      } else {
12444        return Optional.none();
12445      }
12446    });
12447    const getActionFromRange = (root, rng) => {
12448      const isRoot = isRootFromElement(root);
12449      const optCellRng = getCellRng(rng, isRoot);
12450      const selectionDetails = getTableDetailsFromRange(rng, isRoot);
12451      if (isSingleCellTableContentSelected(optCellRng, rng, isRoot)) {
12452        return optCellRng.map(cellRng => deleteAction.singleCellTable(rng, cellRng.start));
12453      } else if (selectionDetails.isMultiTable) {
12454        return handleMultiTable(optCellRng, selectionDetails, rng, isRoot);
12455      } else {
12456        return handleSingleTable(optCellRng, selectionDetails, rng, isRoot);
12457      }
12458    };
12459
12460    const cleanCells = cells => each$e(cells, cell => {
12461      remove$9(cell, 'contenteditable');
12462      fillWithPaddingBr(cell);
12463    });
12464    const getOutsideBlock = (editor, container) => Optional.from(editor.dom.getParent(container, editor.dom.isBlock)).map(SugarElement.fromDom);
12465    const handleEmptyBlock = (editor, startInTable, emptyBlock) => {
12466      emptyBlock.each(block => {
12467        if (startInTable) {
12468          remove$4(block);
12469        } else {
12470          fillWithPaddingBr(block);
12471          editor.selection.setCursorLocation(block.dom, 0);
12472        }
12473      });
12474    };
12475    const deleteContentInsideCell = (editor, cell, rng, isFirstCellInSelection) => {
12476      const insideTableRng = rng.cloneRange();
12477      if (isFirstCellInSelection) {
12478        insideTableRng.setStart(rng.startContainer, rng.startOffset);
12479        insideTableRng.setEndAfter(cell.dom.lastChild);
12480      } else {
12481        insideTableRng.setStartBefore(cell.dom.firstChild);
12482        insideTableRng.setEnd(rng.endContainer, rng.endOffset);
12483      }
12484      deleteCellContents(editor, insideTableRng, cell, false).each(action => action());
12485    };
12486    const collapseAndRestoreCellSelection = editor => {
12487      const selectedCells = getCellsFromEditor(editor);
12488      const selectedNode = SugarElement.fromDom(editor.selection.getNode());
12489      if (isTableCell$3(selectedNode.dom) && isEmpty$2(editor.schema, selectedNode)) {
12490        editor.selection.setCursorLocation(selectedNode.dom, 0);
12491      } else {
12492        editor.selection.collapse(true);
12493      }
12494      if (selectedCells.length > 1 && exists(selectedCells, cell => eq(cell, selectedNode))) {
12495        set$
vendor: 5,907 bytes, lines 12495-12567
124954(selectedNode, 'data-mce-selected', '1');
12496      }
12497    };
12498    const emptySingleTableCells = (editor, cells, outsideDetails) => Optional.some(() => {
12499      const editorRng = editor.selection.getRng();
12500      const cellsToClean = outsideDetails.bind(({rng, isStartInTable}) => {
12501        const outsideBlock = getOutsideBlock(editor, isStartInTable ? rng.endContainer : rng.startContainer);
12502        rng.deleteContents();
12503        handleEmptyBlock(editor, isStartInTable, outsideBlock.filter(curry(isEmpty$2, editor.schema)));
12504        const endPointCell = isStartInTable ? cells[0] : cells[cells.length - 1];
12505        deleteContentInsideCell(editor, endPointCell, editorRng, isStartInTable);
12506        if (!isEmpty$2(editor.schema, endPointCell)) {
12507          return Optional.some(isStartInTable ? cells.slice(1) : cells.slice(0, -1));
12508        } else {
12509          return Optional.none();
12510        }
12511      }).getOr(cells);
12512      cleanCells(cellsToClean);
12513      collapseAndRestoreCellSelection(editor);
12514    });
12515    const emptyMultiTableCells = (editor, startTableCells, endTableCells, betweenRng) => Optional.some(() => {
12516      const rng = editor.selection.getRng();
12517      const startCell = startTableCells[0];
12518      const endCell = endTableCells[endTableCells.length - 1];
12519      deleteContentInsideCell(editor, startCell, rng, true);
12520      deleteContentInsideCell(editor, endCell, rng, false);
12521      const startTableCellsToClean = isEmpty$2(editor.schema, startCell) ? startTableCells : startTableCells.slice(1);
12522      const endTableCellsToClean = isEmpty$2(editor.schema, endCell) ? endTableCells : endTableCells.slice(0, -1);
12523      cleanCells(startTableCellsToClean.concat(endTableCellsToClean));
12524      betweenRng.deleteContents();
12525      collapseAndRestoreCellSelection(editor);
12526    });
12527    const deleteCellContents = (editor, rng, cell, moveSelection = true) => Optional.some(() => {
12528      deleteRangeContents(editor, rng, cell, moveSelection);
12529    });
12530    const deleteTableElement = (editor, table) => Optional.some(() => deleteElement$2(editor, false, table));
12531    const deleteCellRange = (editor, rootElm, rng) => getActionFromRange(rootElm, rng).bind(action => action.fold(curry(deleteCellContents, editor), curry(deleteTableElement, editor), curry(emptySingleTableCells, editor), curry(emptyMultiTableCells, editor)));
12532    const deleteCaptionRange = (editor, caption) => emptyElement(editor, caption);
12533    const deleteTableRange = (editor, rootElm, rng, startElm) => getParentCaption(rootElm, startElm).fold(() => deleteCellRange(editor, rootElm, rng), caption => deleteCaptionRange(editor, caption));
12534    const deleteRange$3 = (editor, startElm, selectedCells) => {
12535      const rootNode = SugarElement.fromDom(editor.getBody());
12536      const rng = editor.selection.getRng();
12537      return selectedCells.length !== 0 ? emptySingleTableCells(editor, selectedCells, Optional.none()) : deleteTableRange(editor, rootNode, rng, startElm);
12538    };
12539    const getParentCell = (rootElm, elm) => find$2(parentsAndSelf(elm, rootElm), isTableCell$2);
12540    const getParentCaption = (rootElm, elm) => find$2(parentsAndSelf(elm, rootElm), isTag('caption'));
12541    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)));
12542    const emptyElement = (editor, elm) => Optional.some(() => {
12543      fillWithPaddingBr(elm);
12544      editor.selection.setCursorLocation(elm.dom, 0);
12545    });
12546    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);
12547    const emptyCaretCaption = (editor, elm) => emptyElement(editor, elm);
12548    const validateCaretCaption = (rootElm, fromCaption, to) => getParentCaption(rootElm, SugarElement.fromDom(to.getNode())).fold(() => Optional.some(noop), toCaption => someIf(!eq(toCaption, fromCaption), noop));
12549    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));
12550    const deleteCaretCells = (editor, forward, rootElm, startElm) => {
12551      const from = CaretPosition.fromRangeStart(editor.selection.getRng());
12552      return getParentCell(rootElm, startElm).bind(fromCell => isEmpty$2(editor.schema, fromCell, { checkRootAsContent: false }) ? emptyElement(editor, fromCell) : deleteBetweenCells(editor, rootElm, forward, fromCell, from));
12553    };
12554    const deleteCaretCaption = (editor, forward, rootElm, fromCaption) => {
12555      const from = CaretPosition.fromRangeStart(editor.selection.getRng());
12556      return isEmpty$2(editor.schema, fromCaption) ? emptyElement(editor, fromCaption) : deleteCaretInsideCaption(editor, rootElm, forward, fromCaption, from);
12557    };
12558    const isNearTable = (forward, pos) => forward ? isBeforeTable(pos) : isAfterTable(pos);
12559    const isBeforeOrAfterTable = (editor, forward) => {
12560      const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
12561      return isNearTable(forward, fromPos) || fromPosition(forward, editor.getBody(), fromPos).exists(pos => isNearTable(forward, pos));
12562    };
12563    const deleteCaret$3 = (editor, forward, startElm) => {
12564      const rootElm = SugarElement.fromDom(editor.getBody());
12565      return getParentCaption(rootElm, startElm).fold(() => deleteCaretCells(editor, forward, rootElm, startElm).orThunk(() => someIf(isBeforeOrAfterTable(editor, forward), noop)), fromCaption => deleteCaretCaption(editor, forward, rootElm, fromCaption));
12566    };
12567    const backspaceDelete$b
vendor: 20,531 bytes, lines 12567-13098
12567 = (editor, forward) => {
12568      const startElm = SugarElement.fromDom(editor.selection.getStart(true));
12569      const cells = getCellsFromEditor(editor);
12570      return editor.selection.isCollapsed() && cells.length === 0 ? deleteCaret$3(editor, forward, startElm) : deleteRange$3(editor, startElm, cells);
12571    };
12572
12573    const getContentEditableRoot$1 = (root, node) => {
12574      let tempNode = node;
12575      while (tempNode && tempNode !== root) {
12576        if (isContentEditableTrue$3(tempNode) || isContentEditableFalse$b(tempNode)) {
12577          return tempNode;
12578        }
12579        tempNode = tempNode.parentNode;
12580      }
12581      return null;
12582    };
12583
12584    const internalAttributesPrefixes = [
12585      'data-ephox-',
12586      'data-mce-',
12587      'data-alloy-',
12588      'data-snooker-',
12589      '_'
12590    ];
12591    const each$9 = Tools.each;
12592    const ElementUtils = editor => {
12593      const dom = editor.dom;
12594      const internalAttributes = new Set(editor.serializer.getTempAttrs());
12595      const compare = (node1, node2) => {
12596        if (node1.nodeName !== node2.nodeName || node1.nodeType !== node2.nodeType) {
12597          return false;
12598        }
12599        const getAttribs = node => {
12600          const attribs = {};
12601          each$9(dom.getAttribs(node), attr => {
12602            const name = attr.nodeName.toLowerCase();
12603            if (name !== 'style' && !isAttributeInternal(name)) {
12604              attribs[name] = dom.getAttrib(node, name);
12605            }
12606          });
12607          return attribs;
12608        };
12609        const compareObjects = (obj1, obj2) => {
12610          for (const name in obj1) {
12611            if (has$2(obj1, name)) {
12612              const value = obj2[name];
12613              if (isUndefined(value)) {
12614                return false;
12615              }
12616              if (obj1[name] !== value) {
12617                return false;
12618              }
12619              delete obj2[name];
12620            }
12621          }
12622          for (const name in obj2) {
12623            if (has$2(obj2, name)) {
12624              return false;
12625            }
12626          }
12627          return true;
12628        };
12629        if (isElement$6(node1) && isElement$6(node2)) {
12630          if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
12631            return false;
12632          }
12633          if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) {
12634            return false;
12635          }
12636        }
12637        return !isBookmarkNode$1(node1) && !isBookmarkNode$1(node2);
12638      };
12639      const isAttributeInternal = attributeName => exists(internalAttributesPrefixes, value => startsWith(attributeName, value)) || internalAttributes.has(attributeName);
12640      return {
12641        compare,
12642        isAttributeInternal
12643      };
12644    };
12645
12646    const isHeading = node => [
12647      'h1',
12648      'h2',
12649      'h3',
12650      'h4',
12651      'h5',
12652      'h6'
12653    ].includes(node.name);
12654    const isSummary = node => node.name === 'summary';
12655
12656    const traverse = (root, fn) => {
12657      let node = root;
12658      while (node = node.walk()) {
12659        fn(node);
12660      }
12661    };
12662    const matchNode$1 = (nodeFilters, attributeFilters, node, matches) => {
12663      const name = node.name;
12664      for (let ni = 0, nl = nodeFilters.length; ni < nl; ni++) {
12665        const filter = nodeFilters[ni];
12666        if (filter.name === name) {
12667          const match = matches.nodes[name];
12668          if (match) {
12669            match.nodes.push(node);
12670          } else {
12671            matches.nodes[name] = {
12672              filter,
12673              nodes: [node]
12674            };
12675          }
12676        }
12677      }
12678      if (node.attributes) {
12679        for (let ai = 0, al = attributeFilters.length; ai < al; ai++) {
12680          const filter = attributeFilters[ai];
12681          const attrName = filter.name;
12682          if (attrName in node.attributes.map) {
12683            const match = matches.attributes[attrName];
12684            if (match) {
12685              match.nodes.push(node);
12686            } else {
12687              matches.attributes[attrName] = {
12688                filter,
12689                nodes: [node]
12690              };
12691            }
12692          }
12693        }
12694      }
12695    };
12696    const findMatchingNodes = (nodeFilters, attributeFilters, node) => {
12697      const matches = {
12698        nodes: {},
12699        attributes: {}
12700      };
12701      if (node.firstChild) {
12702        traverse(node, childNode => {
12703          matchNode$1(nodeFilters, attributeFilters, childNode, matches);
12704        });
12705      }
12706      return matches;
12707    };
12708    const runFilters = (matches, args) => {
12709      const run = (matchRecord, filteringAttributes) => {
12710        each$d(matchRecord, match => {
12711          const nodes = from(match.nodes);
12712          each$e(match.filter.callbacks, callback => {
12713            for (let i = nodes.length - 1; i >= 0; i--) {
12714              const node = nodes[i];
12715              const valueMatches = filteringAttributes ? node.attr(match.filter.name) !== undefined : node.name === match.filter.name;
12716              if (!valueMatches || isNullable(node.parent)) {
12717                nodes.splice(i, 1);
12718              }
12719            }
12720            if (nodes.length > 0) {
12721              callback(nodes, match.filter.name, args);
12722            }
12723          });
12724        });
12725      };
12726      run(matches.nodes, false);
12727      run(matches.attributes, true);
12728    };
12729    const filter$2 = (nodeFilters, attributeFilters, node, args = {}) => {
12730      const matches = findMatchingNodes(nodeFilters, attributeFilters, node);
12731      runFilters(matches, args);
12732    };
12733
12734    const paddEmptyNode = (settings, args, isBlock, node) => {
12735      const brPreferred = settings.pad_empty_with_br || args.insert;
12736      if (brPreferred && isBlock(node)) {
12737        const astNode = new AstNode('br', 1);
12738        if (args.insert) {
12739          astNode.attr('data-mce-bogus', '1');
12740        }
12741        node.empty().append(astNode);
12742      } else {
12743        node.empty().append(new AstNode('#text', 3)).value = nbsp;
12744      }
12745    };
12746    const isPaddedWithNbsp = node => {
12747      var _a;
12748      return hasOnlyChild(node, '#text') && ((_a = node === null || node === void 0 ? void 0 : node.firstChild) === null || _a === void 0 ? void 0 : _a.value) === nbsp;
12749    };
12750    const hasOnlyChild = (node, name) => {
12751      const firstChild = node === null || node === void 0 ? void 0 : node.firstChild;
12752      return isNonNullable(firstChild) && firstChild === node.lastChild && firstChild.name === name;
12753    };
12754    const isPadded = (schema, node) => {
12755      const rule = schema.getElementRule(node.name);
12756      return (rule === null || rule === void 0 ? void 0 : rule.paddEmpty) === true;
12757    };
12758    const isEmpty = (schema, nonEmptyElements, whitespaceElements, node) => node.isEmpty(nonEmptyElements, whitespaceElements, node => isPadded(schema, node));
12759    const isLineBreakNode = (node, isBlock) => isNonNullable(node) && (isBlock(node) || node.name === 'br');
12760    const findClosestEditingHost = scope => {
12761      let editableNode;
12762      for (let node = scope; node; node = node.parent) {
12763        const contentEditable = node.attr('contenteditable');
12764        if (contentEditable === 'false') {
12765          break;
12766        } else if (contentEditable === 'true') {
12767          editableNode = node;
12768        }
12769      }
12770      return Optional.from(editableNode);
12771    };
12772
12773    const removeOrUnwrapInvalidNode = (node, schema, originalNodeParent = node.parent) => {
12774      if (schema.getSpecialElements()[node.name]) {
12775        node.empty().remove();
12776      } else {
12777        const children = node.children();
12778        for (const childNode of children) {
12779          if (originalNodeParent && !schema.isValidChild(originalNodeParent.name, childNode.name)) {
12780            removeOrUnwrapInvalidNode(childNode, schema, originalNodeParent);
12781          }
12782        }
12783        node.unwrap();
12784      }
12785    };
12786    const cleanInvalidNodes = (nodes, schema, rootNode, onCreate = noop) => {
12787      const textBlockElements = schema.getTextBlockElements();
12788      const nonEmptyElements = schema.getNonEmptyElements();
12789      const whitespaceElements = schema.getWhitespaceElements();
12790      const nonSplittableElements = Tools.makeMap('tr,td,th,tbody,thead,tfoot,table,summary');
12791      const fixed = new Set();
12792      const isSplittableElement = node => node !== rootNode && !nonSplittableElements[node.name];
12793      for (let ni = 0; ni < nodes.length; ni++) {
12794        const node = nodes[ni];
12795        let parent;
12796        let newParent;
12797        let tempNode;
12798        if (!node.parent || fixed.has(node)) {
12799          continue;
12800        }
12801        if (textBlockElements[node.name] && node.parent.name === 'li') {
12802          let sibling = node.next;
12803          while (sibling) {
12804            if (textBlockElements[sibling.name]) {
12805              sibling.name = 'li';
12806              fixed.add(sibling);
12807              node.parent.insert(sibling, node.parent);
12808            } else {
12809              break;
12810            }
12811            sibling = sibling.next;
12812          }
12813          node.unwrap();
12814          continue;
12815        }
12816        const parents = [node];
12817        for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && isSplittableElement(parent); parent = parent.parent) {
12818          parents.push(parent);
12819        }
12820        if (parent && parents.length > 1) {
12821          if (!isInvalid(schema, node, parent)) {
12822            parents.reverse();
12823            newParent = parents[0].clone();
12824            onCreate(newParent);
12825            let currentNode = newParent;
12826            for (let i = 0; i < parents.length - 1; i++) {
12827              if (schema.isValidChild(currentNode.name, parents[i].name) && i > 0) {
12828                tempNode = parents[i].clone();
12829                onCreate(tempNode);
12830                currentNode.append(tempNode);
12831              } else {
12832                tempNode = currentNode;
12833              }
12834              for (let childNode = parents[i].firstChild; childNode && childNode !== parents[i + 1];) {
12835                const nextNode = childNode.next;
12836                tempNode.append(childNode);
12837                childNode = nextNode;
12838              }
12839              currentNode = tempNode;
12840            }
12841            if (!isEmpty(schema, nonEmptyElements, whitespaceElements, newParent)) {
12842              parent.insert(newParent, parents[0], true);
12843              parent.insert(node, newParent);
12844            } else {
12845              parent.insert(node, parents[0], true);
12846            }
12847            parent = parents[0];
12848            if (isEmpty(schema, nonEmptyElements, whitespaceElements, parent) || hasOnlyChild(parent, 'br')) {
12849              parent.empty().remove();
12850            }
12851          } else {
12852            removeOrUnwrapInvalidNode(node, schema);
12853          }
12854        } else if (node.parent) {
12855          if (node.name === 'li') {
12856            let sibling = node.prev;
12857            if (sibling && (sibling.name === 'ul' || sibling.name === 'ol')) {
12858              sibling.append(node);
12859              continue;
12860            }
12861            sibling = node.next;
12862            if (sibling && (sibling.name === 'ul' || sibling.name === 'ol') && sibling.firstChild) {
12863              sibling.insert(node, sibling.firstChild, true);
12864              continue;
12865            }
12866            const wrapper = new AstNode('ul', 1);
12867            onCreate(wrapper);
12868            node.wrap(wrapper);
12869            continue;
12870          }
12871          if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) {
12872            const wrapper = new AstNode('div', 1);
12873            onCreate(wrapper);
12874            node.wrap(wrapper);
12875          } else {
12876            removeOrUnwrapInvalidNode(node, schema);
12877          }
12878        }
12879      }
12880    };
12881    const hasClosest = (node, parentName) => {
12882      let tempNode = node;
12883      while (tempNode) {
12884        if (tempNode.name === parentName) {
12885          return true;
12886        }
12887        tempNode = tempNode.parent;
12888      }
12889      return false;
12890    };
12891    const isInvalid = (schema, node, parent = node.parent) => {
12892      if (!parent) {
12893        return false;
12894      }
12895      if (schema.children[node.name] && !schema.isValidChild(parent.name, node.name)) {
12896        return true;
12897      }
12898      if (node.name === 'a' && hasClosest(parent, 'a')) {
12899        return true;
12900      }
12901      if (isSummary(parent) && isHeading(node)) {
12902        return !((parent === null || parent === void 0 ? void 0 : parent.firstChild) === node && (parent === null || parent === void 0 ? void 0 : parent.lastChild) === node);
12903      }
12904      return false;
12905    };
12906
12907    const createRange = (sc, so, ec, eo) => {
12908      const rng = document.createRange();
12909      rng.setStart(sc, so);
12910      rng.setEnd(ec, eo);
12911      return rng;
12912    };
12913    const normalizeBlockSelectionRange = rng => {
12914      const startPos = CaretPosition.fromRangeStart(rng);
12915      const endPos = CaretPosition.fromRangeEnd(rng);
12916      const rootNode = rng.commonAncestorContainer;
12917      return fromPosition(false, rootNode, endPos).map(newEndPos => {
12918        if (!isInSameBlock(startPos, endPos, rootNode) && isInSameBlock(startPos, newEndPos, rootNode)) {
12919          return createRange(startPos.container(), startPos.offset(), newEndPos.container(), newEndPos.offset());
12920        } else {
12921          return rng;
12922        }
12923      }).getOr(rng);
12924    };
12925    const normalize = rng => rng.collapsed ? rng : normalizeBlockSelectionRange(rng);
12926
12927    const hasOnlyOneChild$1 = node => {
12928      return isNonNullable(node.firstChild) && node.firstChild === node.lastChild;
12929    };
12930    const isPaddingNode = node => {
12931      return node.name === 'br' || node.value === nbsp;
12932    };
12933    const isPaddedEmptyBlock = (schema, node) => {
12934      const blockElements = schema.getBlockElements();
12935      return blockElements[node.name] && hasOnlyOneChild$1(node) && isPaddingNode(node.firstChild);
12936    };
12937    const isEmptyFragmentElement = (schema, node) => {
12938      const nonEmptyElements = schema.getNonEmptyElements();
12939      return isNonNullable(node) && (node.isEmpty(nonEmptyElements) || isPaddedEmptyBlock(schema, node));
12940    };
12941    const isListFragment = (schema, fragment) => {
12942      let firstChild = fragment.firstChild;
12943      let lastChild = fragment.lastChild;
12944      if (firstChild && firstChild.name === 'meta') {
12945        firstChild = firstChild.next;
12946      }
12947      if (lastChild && lastChild.attr('id') === 'mce_marker') {
12948        lastChild = lastChild.prev;
12949      }
12950      if (isEmptyFragmentElement(schema, lastChild)) {
12951        lastChild = lastChild === null || lastChild === void 0 ? void 0 : lastChild.prev;
12952      }
12953      if (!firstChild || firstChild !== lastChild) {
12954        return false;
12955      }
12956      return firstChild.name === 'ul' || firstChild.name === 'ol';
12957    };
12958    const cleanupDomFragment = domFragment => {
12959      var _a, _b;
12960      const firstChild = domFragment.firstChild;
12961      const lastChild = domFragment.lastChild;
12962      if (firstChild && firstChild.nodeName === 'META') {
12963        (_a = firstChild.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(firstChild);
12964      }
12965      if (lastChild && lastChild.id === 'mce_marker') {
12966        (_b = lastChild.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(lastChild);
12967      }
12968      return domFragment;
12969    };
12970    const toDomFragment = (dom, serializer, fragment) => {
12971      const html = serializer.serialize(fragment);
12972      const domFragment = dom.createFragment(html);
12973      return cleanupDomFragment(domFragment);
12974    };
12975    const listItems = elm => {
12976      var _a;
12977      return filter$5((_a = elm === null || elm === void 0 ? void 0 : elm.childNodes) !== null && _a !== void 0 ? _a : [], child => {
12978        return child.nodeName === 'LI';
12979      });
12980    };
12981    const isPadding = node => {
12982      return node.data === nbsp || isBr$6(node);
12983    };
12984    const isListItemPadded = node => {
12985      return isNonNullable(node === null || node === void 0 ? void 0 : node.firstChild) && node.firstChild === node.lastChild && isPadding(node.firstChild);
12986    };
12987    const isEmptyOrPadded = elm => {
12988      return !elm.firstChild || isListItemPadded(elm);
12989    };
12990    const trimListItems = elms => {
12991      return elms.length > 0 && isEmptyOrPadded(elms[elms.length - 1]) ? elms.slice(0, -1) : elms;
12992    };
12993    const getParentLi = (dom, node) => {
12994      const parentBlock = dom.getParent(node, dom.isBlock);
12995      return parentBlock && parentBlock.nodeName === 'LI' ? parentBlock : null;
12996    };
12997    const isParentBlockLi = (dom, node) => {
12998      return !!getParentLi(dom, node);
12999    };
13000    const getSplit = (parentNode, rng) => {
13001      const beforeRng = rng.cloneRange();
13002      const afterRng = rng.cloneRange();
13003      beforeRng.setStartBefore(parentNode);
13004      afterRng.setEndAfter(parentNode);
13005      return [
13006        beforeRng.cloneContents(),
13007        afterRng.cloneContents()
13008      ];
13009    };
13010    const findFirstIn = (node, rootNode) => {
13011      const caretPos = CaretPosition.before(node);
13012      const caretWalker = CaretWalker(rootNode);
13013      const newCaretPos = caretWalker.next(caretPos);
13014      return newCaretPos ? newCaretPos.toRange() : null;
13015    };
13016    const findLastOf = (node, rootNode) => {
13017      const caretPos = CaretPosition.after(node);
13018      const caretWalker = CaretWalker(rootNode);
13019      const newCaretPos = caretWalker.prev(caretPos);
13020      return newCaretPos ? newCaretPos.toRange() : null;
13021    };
13022    const insertMiddle = (target, elms, rootNode, rng) => {
13023      const parts = getSplit(target, rng);
13024      const parentElm = target.parentNode;
13025      if (parentElm) {
13026        parentElm.insertBefore(parts[0], target);
13027        Tools.each(elms, li => {
13028          parentElm.insertBefore(li, target);
13029        });
13030        parentElm.insertBefore(parts[1], target);
13031        parentElm.removeChild(target);
13032      }
13033      return findLastOf(elms[elms.length - 1], rootNode);
13034    };
13035    const insertBefore$2 = (target, elms, rootNode) => {
13036      const parentElm = target.parentNode;
13037      if (parentElm) {
13038        Tools.each(elms, elm => {
13039          parentElm.insertBefore(elm, target);
13040        });
13041      }
13042      return findFirstIn(target, rootNode);
13043    };
13044    const insertAfter$2 = (target, elms, rootNode, dom) => {
13045      dom.insertAfter(elms.reverse(), target);
13046      return findLastOf(elms[0], rootNode);
13047    };
13048    const insertAtCaret$1 = (serializer, dom, rng, fragment) => {
13049      const domFragment = toDomFragment(dom, serializer, fragment);
13050      const liTarget = getParentLi(dom, rng.startContainer);
13051      const liElms = trimListItems(listItems(domFragment.firstChild));
13052      const BEGINNING = 1, END = 2;
13053      const rootNode = dom.getRoot();
13054      const isAt = location => {
13055        const caretPos = CaretPosition.fromRangeStart(rng);
13056        const caretWalker = CaretWalker(dom.getRoot());
13057        const newPos = location === BEGINNING ? caretWalker.prev(caretPos) : caretWalker.next(caretPos);
13058        const newPosNode = newPos === null || newPos === void 0 ? void 0 : newPos.getNode();
13059        return newPosNode ? getParentLi(dom, newPosNode) !== liTarget : true;
13060      };
13061      if (!liTarget) {
13062        return null;
13063      } else if (isAt(BEGINNING)) {
13064        return insertBefore$2(liTarget, liElms, rootNode);
13065      } else if (isAt(END)) {
13066        return insertAfter$2(liTarget, liElms, rootNode, dom);
13067      } else {
13068        return insertMiddle(liTarget, liElms, rootNode, rng);
13069      }
13070    };
13071
13072    const mergeableWrappedElements = ['pre'];
13073    const shouldPasteContentOnly = (dom, fragment, parentNode, root) => {
13074      var _a;
13075      const firstNode = fragment.firstChild;
13076      const lastNode = fragment.lastChild;
13077      const last = lastNode.attr('data-mce-type') === 'bookmark' ? lastNode.prev : lastNode;
13078      const isPastingSingleElement = firstNode === last;
13079      const isWrappedElement = contains$2(mergeableWrappedElements, firstNode.name);
13080      if (isPastingSingleElement && isWrappedElement) {
13081        const isContentEditable = firstNode.attr('contenteditable') !== 'false';
13082        const isPastingInTheSameBlockTag = ((_a = dom.getParent(parentNode, dom.isBlock)) === null || _a === void 0 ? void 0 : _a.nodeName.toLowerCase()) === firstNode.name;
13083        const isPastingInContentEditable = Optional.from(getContentEditableRoot$1(root, parentNode)).forall(isContentEditableTrue$3);
13084        return isContentEditable && isPastingInTheSameBlockTag && isPastingInContentEditable;
13085      } else {
13086        return false;
13087      }
13088    };
13089    const isTableCell = isTableCell$3;
13090    const isTableCellContentSelected = (dom, rng, cell) => {
13091      if (isNonNullable(cell)) {
13092        const endCell = dom.getParent(rng.endContainer, isTableCell);
13093        return cell === endCell && hasAllContentsSelected(SugarElement.fromDom(cell), rng);
13094      } else {
13095        return false;
13096      }
13097    };
13098    const 
vendor: 14,129 bytes, lines 13098-13420
13098isEditableEmptyBlock = (dom, node) => {
13099      if (dom.isBlock(node) && dom.isEditable(node)) {
13100        const childNodes = node.childNodes;
13101        return childNodes.length === 1 && isBr$6(childNodes[0]) || childNodes.length === 0;
13102      } else {
13103        return false;
13104      }
13105    };
13106    const validInsertion = (editor, value, parentNode) => {
13107      var _a;
13108      if (parentNode.getAttribute('data-mce-bogus') === 'all') {
13109        (_a = parentNode.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(editor.dom.createFragment(value), parentNode);
13110      } else {
13111        if (isEditableEmptyBlock(editor.dom, parentNode)) {
13112          editor.dom.setHTML(parentNode, value);
13113        } else {
13114          editor.selection.setContent(value, { no_events: true });
13115        }
13116      }
13117    };
13118    const trimBrsFromTableCell = (dom, elm, schema) => {
13119      Optional.from(dom.getParent(elm, 'td,th')).map(SugarElement.fromDom).each(el => trimBlockTrailingBr(el, schema));
13120    };
13121    const reduceInlineTextElements = (editor, merge) => {
13122      const textInlineElements = editor.schema.getTextInlineElements();
13123      const dom = editor.dom;
13124      if (merge) {
13125        const root = editor.getBody();
13126        const elementUtils = ElementUtils(editor);
13127        const fragmentSelector = '*[data-mce-fragment]';
13128        const fragments = dom.select(fragmentSelector);
13129        Tools.each(fragments, node => {
13130          const isInline = currentNode => isNonNullable(textInlineElements[currentNode.nodeName.toLowerCase()]);
13131          const hasOneChild = currentNode => currentNode.childNodes.length === 1;
13132          const hasNoNonInheritableStyles = currentNode => !(hasNonInheritableStyles(dom, currentNode) || hasConditionalNonInheritableStyles(dom, currentNode));
13133          if (hasNoNonInheritableStyles(node) && isInline(node) && hasOneChild(node)) {
13134            const styles = getStyleProps(dom, node);
13135            const isOverridden = (oldStyles, newStyles) => forall(oldStyles, style => contains$2(newStyles, style));
13136            const overriddenByAllChildren = childNode => hasOneChild(node) && dom.is(childNode, fragmentSelector) && isInline(childNode) && (childNode.nodeName === node.nodeName && isOverridden(styles, getStyleProps(dom, childNode)) || overriddenByAllChildren(childNode.children[0]));
13137            const identicalToParent = parentNode => isNonNullable(parentNode) && parentNode !== root && (elementUtils.compare(node, parentNode) || identicalToParent(parentNode.parentElement));
13138            const conflictWithInsertedParent = parentNode => isNonNullable(parentNode) && parentNode !== root && dom.is(parentNode, fragmentSelector) && (hasStyleConflict(dom, node, parentNode) || conflictWithInsertedParent(parentNode.parentElement));
13139            if (overriddenByAllChildren(node.children[0]) || identicalToParent(node.parentElement) && !conflictWithInsertedParent(node.parentElement)) {
13140              dom.remove(node, true);
13141            }
13142          }
13143        });
13144      }
13145    };
13146    const markFragmentElements = fragment => {
13147      let node = fragment;
13148      while (node = node.walk()) {
13149        if (node.type === 1) {
13150          node.attr('data-mce-fragment', '1');
13151        }
13152      }
13153    };
13154    const unmarkFragmentElements = elm => {
13155      Tools.each(elm.getElementsByTagName('*'), elm => {
13156        elm.removeAttribute('data-mce-fragment');
13157      });
13158    };
13159    const isPartOfFragment = node => {
13160      return !!node.getAttribute('data-mce-fragment');
13161    };
13162    const canHaveChildren = (editor, node) => {
13163      return isNonNullable(node) && !editor.schema.getVoidElements()[node.nodeName];
13164    };
13165    const moveSelectionToMarker = (editor, marker) => {
13166      var _a, _b, _c;
13167      let nextRng;
13168      const dom = editor.dom;
13169      const selection = editor.selection;
13170      if (!marker) {
13171        return;
13172      }
13173      selection.scrollIntoView(marker);
13174      const parentEditableElm = getContentEditableRoot$1(editor.getBody(), marker);
13175      if (parentEditableElm && dom.getContentEditable(parentEditableElm) === 'false') {
13176        dom.remove(marker);
13177        selection.select(parentEditableElm);
13178        return;
13179      }
13180      let rng = dom.createRng();
13181      const node = marker.previousSibling;
13182      if (isText$b(node)) {
13183        rng.setStart(node, (_b = (_a = node.nodeValue) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0);
13184        const node2 = marker.nextSibling;
13185        if (isText$b(node2)) {
13186          node.appendData(node2.data);
13187          (_c = node2.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(node2);
13188        }
13189      } else {
13190        rng.setStartBefore(marker);
13191        rng.setEndBefore(marker);
13192      }
13193      const findNextCaretRng = rng => {
13194        let caretPos = CaretPosition.fromRangeStart(rng);
13195        const caretWalker = CaretWalker(editor.getBody());
13196        caretPos = caretWalker.next(caretPos);
13197        return caretPos === null || caretPos === void 0 ? void 0 : caretPos.toRange();
13198      };
13199      const parentBlock = dom.getParent(marker, dom.isBlock);
13200      dom.remove(marker);
13201      if (parentBlock && dom.isEmpty(parentBlock)) {
13202        const isCell = isTableCell(parentBlock);
13203        empty(SugarElement.fromDom(parentBlock));
13204        rng.setStart(parentBlock, 0);
13205        rng.setEnd(parentBlock, 0);
13206        if (!isCell && !isPartOfFragment(parentBlock) && (nextRng = findNextCaretRng(rng))) {
13207          rng = nextRng;
13208          dom.remove(parentBlock);
13209        } else {
13210          dom.add(parentBlock, dom.create('br', isCell ? {} : { 'data-mce-bogus': '1' }));
13211        }
13212      }
13213      selection.setRng(rng);
13214    };
13215    const deleteSelectedContent = editor => {
13216      const dom = editor.dom;
13217      const rng = normalize(editor.selection.getRng());
13218      editor.selection.setRng(rng);
13219      const startCell = dom.getParent(rng.startContainer, isTableCell);
13220      if (isTableCellContentSelected(dom, rng, startCell)) {
13221        deleteCellContents(editor, rng, SugarElement.fromDom(startCell));
13222      } else if (rng.startContainer === rng.endContainer && rng.endOffset - rng.startOffset === 1 && isText$b(rng.startContainer.childNodes[rng.startOffset])) {
13223        rng.deleteContents();
13224      } else {
13225        editor.getDoc().execCommand('Delete', false);
13226      }
13227    };
13228    const findMarkerNode = scope => {
13229      for (let markerNode = scope; markerNode; markerNode = markerNode.walk()) {
13230        if (markerNode.attr('id') === 'mce_marker') {
13231          return Optional.some(markerNode);
13232        }
13233      }
13234      return Optional.none();
13235    };
13236    const notHeadingsInSummary = (dom, node, fragment) => {
13237      var _a;
13238      return exists(fragment.children(), isHeading) && ((_a = dom.getParent(node, dom.isBlock)) === null || _a === void 0 ? void 0 : _a.nodeName) === 'SUMMARY';
13239    };
13240    const insertHtmlAtCaret = (editor, value, details) => {
13241      var _a, _b;
13242      const selection = editor.selection;
13243      const dom = editor.dom;
13244      const parser = editor.parser;
13245      const merge = details.merge;
13246      const serializer = HtmlSerializer({ validate: true }, editor.schema);
13247      const bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;</span>';
13248      if (!details.preserve_zwsp) {
13249        value = trim$2(value);
13250      }
13251      if (value.indexOf('{$caret}') === -1) {
13252        value += '{$caret}';
13253      }
13254      value = value.replace(/\{\$caret\}/, bookmarkHtml);
13255      let rng = selection.getRng();
13256      const caretElement = rng.startContainer;
13257      const body = editor.getBody();
13258      if (caretElement === body && selection.isCollapsed()) {
13259        if (dom.isBlock(body.firstChild) && canHaveChildren(editor, body.firstChild) && dom.isEmpty(body.firstChild)) {
13260          rng = dom.createRng();
13261          rng.setStart(body.firstChild, 0);
13262          rng.setEnd(body.firstChild, 0);
13263          selection.setRng(rng);
13264        }
13265      }
13266      if (!selection.isCollapsed()) {
13267        deleteSelectedContent(editor);
13268      }
13269      const parentNode = selection.getNode();
13270      const parserArgs = {
13271        context: parentNode.nodeName.toLowerCase(),
13272        data: details.data,
13273        insert: true
13274      };
13275      const fragment = parser.parse(value, parserArgs);
13276      if (details.paste === true && isListFragment(editor.schema, fragment) && isParentBlockLi(dom, parentNode)) {
13277        rng = insertAtCaret$1(serializer, dom, selection.getRng(), fragment);
13278        if (rng) {
13279          selection.setRng(rng);
13280        }
13281        return value;
13282      }
13283      if (details.paste === true && shouldPasteContentOnly(dom, fragment, parentNode, editor.getBody())) {
13284        (_a = fragment.firstChild) === null || _a === void 0 ? void 0 : _a.unwrap();
13285      }
13286      markFragmentElements(fragment);
13287      let node = fragment.lastChild;
13288      if (node && node.attr('id') === 'mce_marker') {
13289        const marker = node;
13290        for (node = node.prev; node; node = node.walk(true)) {
13291          if (node.name === 'table') {
13292            break;
13293          }
13294          if (node.type === 3 || !dom.isBlock(node.name)) {
13295            if (node.parent && editor.schema.isValidChild(node.parent.name, 'span')) {
13296              node.parent.insert(marker, node, node.name === 'br');
13297            }
13298            break;
13299          }
13300        }
13301      }
13302      editor._selectionOverrides.showBlockCaretContainer(parentNode);
13303      if (!parserArgs.invalid && !notHeadingsInSummary(dom, parentNode, fragment)) {
13304        value = serializer.serialize(fragment);
13305        validInsertion(editor, value, parentNode);
13306      } else {
13307        editor.selection.setContent(bookmarkHtml);
13308        let parentNode = selection.getNode();
13309        let tempNode;
13310        const rootNode = editor.getBody();
13311        if (isDocument$1(parentNode)) {
13312          parentNode = tempNode = rootNode;
13313        } else {
13314          tempNode = parentNode;
13315        }
13316        while (tempNode && tempNode !== rootNode) {
13317          parentNode = tempNode;
13318          tempNode = tempNode.parentNode;
13319        }
13320        value = parentNode === rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode);
13321        const root = parser.parse(value);
13322        const markerNode = findMarkerNode(root);
13323        const editingHost = markerNode.bind(findClosestEditingHost).getOr(root);
13324        markerNode.each(marker => marker.replace(fragment));
13325        const toExtract = fragment.children();
13326        const parent = (_b = fragment.parent) !== null && _b !== void 0 ? _b : root;
13327        fragment.unwrap();
13328        const invalidChildren = filter$5(toExtract, node => isInvalid(editor.schema, node, parent));
13329        cleanInvalidNodes(invalidChildren, editor.schema, editingHost);
13330        filter$2(parser.getNodeFilters(), parser.getAttributeFilters(), root);
13331        value = serializer.serialize(root);
13332        if (parentNode === rootNode) {
13333          dom.setHTML(rootNode, value);
13334        } else {
13335          dom.setOuterHTML(parentNode, value);
13336        }
13337      }
13338      reduceInlineTextElements(editor, merge);
13339      moveSelectionToMarker(editor, dom.get('mce_marker'));
13340      unmarkFragmentElements(editor.getBody());
13341      trimBrsFromTableCell(dom, selection.getStart(), editor.schema);
13342      updateCaret(editor.schema, editor.getBody(), selection.getStart());
13343      return value;
13344    };
13345
13346    const isTreeNode = content => content instanceof AstNode;
13347
13348    const moveSelection = editor => {
13349      if (hasFocus(editor)) {
13350        firstPositionIn(editor.getBody()).each(pos => {
13351          const node = pos.getNode();
13352          const caretPos = isTable$2(node) ? firstPositionIn(node).getOr(pos) : pos;
13353          editor.selection.setRng(caretPos.toRange());
13354        });
13355      }
13356    };
13357    const setEditorHtml = (editor, html, noSelection) => {
13358      editor.dom.setHTML(editor.getBody(), html);
13359      if (noSelection !== true) {
13360        moveSelection(editor);
13361      }
13362    };
13363    const setContentString = (editor, body, content, args) => {
13364      content = trim$2(content);
13365      if (content.length === 0 || /^\s+$/.test(content)) {
13366        const padd = '<br data-mce-bogus="1">';
13367        if (body.nodeName === 'TABLE') {
13368          content = '<tr><td>' + padd + '</td></tr>';
13369        } else if (/^(UL|OL)$/.test(body.nodeName)) {
13370          content = '<li>' + padd + '</li>';
13371        }
13372        const forcedRootBlockName = getForcedRootBlock(editor);
13373        if (editor.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
13374          content = padd;
13375          content = editor.dom.createHTML(forcedRootBlockName, getForcedRootBlockAttrs(editor), content);
13376        } else if (!content) {
13377          content = padd;
13378        }
13379        setEditorHtml(editor, content, args.no_selection);
13380        return {
13381          content,
13382          html: content
13383        };
13384      } else {
13385        if (args.format !== 'raw') {
13386          content = HtmlSerializer({ validate: false }, editor.schema).serialize(editor.parser.parse(content, {
13387            isRootContent: true,
13388            insert: true
13389          }));
13390        }
13391        const trimmedHtml = isWsPreserveElement(SugarElement.fromDom(body)) ? content : Tools.trim(content);
13392        setEditorHtml(editor, trimmedHtml, args.no_selection);
13393        return {
13394          content: trimmedHtml,
13395          html: trimmedHtml
13396        };
13397      }
13398    };
13399    const setContentTree = (editor, body, content, args) => {
13400      filter$2(editor.parser.getNodeFilters(), editor.parser.getAttributeFilters(), content);
13401      const html = HtmlSerializer({ validate: false }, editor.schema).serialize(content);
13402      const trimmedHtml = trim$2(isWsPreserveElement(SugarElement.fromDom(body)) ? html : Tools.trim(html));
13403      setEditorHtml(editor, trimmedHtml, args.no_selection);
13404      return {
13405        content,
13406        html: trimmedHtml
13407      };
13408    };
13409    const setContentInternal = (editor, content, args) => {
13410      return Optional.from(editor.getBody()).map(body => {
13411        if (isTreeNode(content)) {
13412          return setContentTree(editor, body, content, args);
13413        } else {
13414          return setContentString(editor, body, content, args);
13415        }
13416      }).getOr({
13417        content,
13418        html: isTreeNode(args.content) ? '' : args.content
13419      });
13420    }
vendor: 6,822 bytes, lines 13420-13606
13420;
13421
13422    const ensureIsRoot = isRoot => isFunction(isRoot) ? isRoot : never;
13423    const ancestor = (scope, transform, isRoot) => {
13424      let element = scope.dom;
13425      const stop = ensureIsRoot(isRoot);
13426      while (element.parentNode) {
13427        element = element.parentNode;
13428        const el = SugarElement.fromDom(element);
13429        const transformed = transform(el);
13430        if (transformed.isSome()) {
13431          return transformed;
13432        } else if (stop(el)) {
13433          break;
13434        }
13435      }
13436      return Optional.none();
13437    };
13438    const closest$1 = (scope, transform, isRoot) => {
13439      const current = transform(scope);
13440      const stop = ensureIsRoot(isRoot);
13441      return current.orThunk(() => stop(scope) ? Optional.none() : ancestor(scope, transform, stop));
13442    };
13443
13444    const isEq$3 = isEq$5;
13445    const matchesUnInheritedFormatSelector = (ed, node, name) => {
13446      const formatList = ed.formatter.get(name);
13447      if (formatList) {
13448        for (let i = 0; i < formatList.length; i++) {
13449          const format = formatList[i];
13450          if (isSelectorFormat(format) && format.inherit === false && ed.dom.is(node, format.selector)) {
13451            return true;
13452          }
13453        }
13454      }
13455      return false;
13456    };
13457    const matchParents = (editor, node, name, vars, similar) => {
13458      const root = editor.dom.getRoot();
13459      if (node === root) {
13460        return false;
13461      }
13462      const matchedNode = editor.dom.getParent(node, elm => {
13463        if (matchesUnInheritedFormatSelector(editor, elm, name)) {
13464          return true;
13465        }
13466        return elm.parentNode === root || !!matchNode(editor, elm, name, vars, true);
13467      });
13468      return !!matchNode(editor, matchedNode, name, vars, similar);
13469    };
13470    const matchName = (dom, node, format) => {
13471      if (isInlineFormat(format) && isEq$3(node, format.inline)) {
13472        return true;
13473      }
13474      if (isBlockFormat(format) && isEq$3(node, format.block)) {
13475        return true;
13476      }
13477      if (isSelectorFormat(format)) {
13478        return isElement$6(node) && dom.is(node, format.selector);
13479      }
13480      return false;
13481    };
13482    const matchItems = (dom, node, format, itemName, similar, vars) => {
13483      const items = format[itemName];
13484      const matchAttributes = itemName === 'attributes';
13485      if (isFunction(format.onmatch)) {
13486        return format.onmatch(node, format, itemName);
13487      }
13488      if (items) {
13489        if (!isArrayLike(items)) {
13490          for (const key in items) {
13491            if (has$2(items, key)) {
13492              const value = matchAttributes ? dom.getAttrib(node, key) : getStyle(dom, node, key);
13493              const expectedValue = replaceVars(items[key], vars);
13494              const isEmptyValue = isNullable(value) || isEmpty$3(value);
13495              if (isEmptyValue && isNullable(expectedValue)) {
13496                continue;
13497              }
13498              if (similar && isEmptyValue && !format.exact) {
13499                return false;
13500              }
13501              if ((!similar || format.exact) && !isEq$3(value, normalizeStyleValue(expectedValue, key))) {
13502                return false;
13503              }
13504            }
13505          }
13506        } else {
13507          for (let i = 0; i < items.length; i++) {
13508            if (matchAttributes ? dom.getAttrib(node, items[i]) : getStyle(dom, node, items[i])) {
13509              return true;
13510            }
13511          }
13512        }
13513      }
13514      return true;
13515    };
13516    const matchNode = (ed, node, name, vars, similar) => {
13517      const formatList = ed.formatter.get(name);
13518      const dom = ed.dom;
13519      if (formatList && isElement$6(node)) {
13520        for (let i = 0; i < formatList.length; i++) {
13521          const format = formatList[i];
13522          if (matchName(ed.dom, node, format) && matchItems(dom, node, format, 'attributes', similar, vars) && matchItems(dom, node, format, 'styles', similar, vars)) {
13523            const classes = format.classes;
13524            if (classes) {
13525              for (let x = 0; x < classes.length; x++) {
13526                if (!ed.dom.hasClass(node, replaceVars(classes[x], vars))) {
13527                  return;
13528                }
13529              }
13530            }
13531            return format;
13532          }
13533        }
13534      }
13535      return undefined;
13536    };
13537    const match$2 = (editor, name, vars, node, similar) => {
13538      if (node) {
13539        return matchParents(editor, node, name, vars, similar);
13540      }
13541      node = editor.selection.getNode();
13542      if (matchParents(editor, node, name, vars, similar)) {
13543        return true;
13544      }
13545      const startNode = editor.selection.getStart();
13546      if (startNode !== node) {
13547        if (matchParents(editor, startNode, name, vars, similar)) {
13548          return true;
13549        }
13550      }
13551      return false;
13552    };
13553    const matchAll = (editor, names, vars) => {
13554      const matchedFormatNames = [];
13555      const checkedMap = {};
13556      const startElement = editor.selection.getStart();
13557      editor.dom.getParent(startElement, node => {
13558        for (let i = 0; i < names.length; i++) {
13559          const name = names[i];
13560          if (!checkedMap[name] && matchNode(editor, node, name, vars)) {
13561            checkedMap[name] = true;
13562            matchedFormatNames.push(name);
13563          }
13564        }
13565      }, editor.dom.getRoot());
13566      return matchedFormatNames;
13567    };
13568    const closest = (editor, names) => {
13569      const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody()));
13570      const match = (elm, name) => matchNode(editor, elm.dom, name) ? Optional.some(name) : Optional.none();
13571      return Optional.from(editor.selection.getStart(true)).bind(rawElm => closest$1(SugarElement.fromDom(rawElm), elm => findMap(names, name => match(elm, name)), isRoot)).getOrNull();
13572    };
13573    const canApply = (editor, name) => {
13574      const formatList = editor.formatter.get(name);
13575      const dom = editor.dom;
13576      if (formatList && editor.selection.isEditable()) {
13577        const startNode = editor.selection.getStart();
13578        const parents = getParents$2(dom, startNode);
13579        for (let x = formatList.length - 1; x >= 0; x--) {
13580          const format = formatList[x];
13581          if (!isSelectorFormat(format)) {
13582            return true;
13583          }
13584          for (let i = parents.length - 1; i >= 0; i--) {
13585            if (dom.is(parents[i], format.selector)) {
13586              return true;
13587            }
13588          }
13589        }
13590      }
13591      return false;
13592    };
13593    const matchAllOnNode = (editor, node, formatNames) => foldl(formatNames, (acc, name) => {
13594      const matchSimilar = isVariableFormatName(editor, name);
13595      if (editor.formatter.matchNode(node, name, {}, matchSimilar)) {
13596        return acc.concat([name]);
13597      } else {
13598        return acc;
13599      }
13600    }, []);
13601
13602    const ZWSP = ZWSP$1;
13603    const importNode = (ownerDocument, node) => {
13604      return ownerDocument.importNode(node, true);
13605    };
13606    const 
vendor: 6,827 bytes, lines 13606-13770
13606findFirstTextNode = node => {
13607      if (node) {
13608        const walker = new DomTreeWalker(node, node);
13609        for (let tempNode = walker.current(); tempNode; tempNode = walker.next()) {
13610          if (isText$b(tempNode)) {
13611            return tempNode;
13612          }
13613        }
13614      }
13615      return null;
13616    };
13617    const createCaretContainer = fill => {
13618      const caretContainer = SugarElement.fromTag('span');
13619      setAll$1(caretContainer, {
13620        'id': CARET_ID,
13621        'data-mce-bogus': '1',
13622        'data-mce-type': 'format-caret'
13623      });
13624      if (fill) {
13625        append$1(caretContainer, SugarElement.fromText(ZWSP));
13626      }
13627      return caretContainer;
13628    };
13629    const trimZwspFromCaretContainer = caretContainerNode => {
13630      const textNode = findFirstTextNode(caretContainerNode);
13631      if (textNode && textNode.data.charAt(0) === ZWSP) {
13632        textNode.deleteData(0, 1);
13633      }
13634      return textNode;
13635    };
13636    const removeCaretContainerNode = (editor, node, moveCaret) => {
13637      const dom = editor.dom, selection = editor.selection;
13638      if (isCaretContainerEmpty(node)) {
13639        deleteElement$2(editor, false, SugarElement.fromDom(node), moveCaret, true);
13640      } else {
13641        const rng = selection.getRng();
13642        const block = dom.getParent(node, dom.isBlock);
13643        const startContainer = rng.startContainer;
13644        const startOffset = rng.startOffset;
13645        const endContainer = rng.endContainer;
13646        const endOffset = rng.endOffset;
13647        const textNode = trimZwspFromCaretContainer(node);
13648        dom.remove(node, true);
13649        if (startContainer === textNode && startOffset > 0) {
13650          rng.setStart(textNode, startOffset - 1);
13651        }
13652        if (endContainer === textNode && endOffset > 0) {
13653          rng.setEnd(textNode, endOffset - 1);
13654        }
13655        if (block && dom.isEmpty(block)) {
13656          fillWithPaddingBr(SugarElement.fromDom(block));
13657        }
13658        selection.setRng(rng);
13659      }
13660    };
13661    const removeCaretContainer = (editor, node, moveCaret) => {
13662      const dom = editor.dom, selection = editor.selection;
13663      if (!node) {
13664        node = getParentCaretContainer(editor.getBody(), selection.getStart());
13665        if (!node) {
13666          while (node = dom.get(CARET_ID)) {
13667            removeCaretContainerNode(editor, node, moveCaret);
13668          }
13669        }
13670      } else {
13671        removeCaretContainerNode(editor, node, moveCaret);
13672      }
13673    };
13674    const insertCaretContainerNode = (editor, caretContainer, formatNode) => {
13675      var _a, _b;
13676      const dom = editor.dom;
13677      const block = dom.getParent(formatNode, curry(isTextBlock$1, editor.schema));
13678      if (block && dom.isEmpty(block)) {
13679        (_a = formatNode.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(caretContainer, formatNode);
13680      } else {
13681        removeTrailingBr(SugarElement.fromDom(formatNode));
13682        if (dom.isEmpty(formatNode)) {
13683          (_b = formatNode.parentNode) === null || _b === void 0 ? void 0 : _b.replaceChild(caretContainer, formatNode);
13684        } else {
13685          dom.insertAfter(caretContainer, formatNode);
13686        }
13687      }
13688    };
13689    const appendNode = (parentNode, node) => {
13690      parentNode.appendChild(node);
13691      return node;
13692    };
13693    const insertFormatNodesIntoCaretContainer = (formatNodes, caretContainer) => {
13694      var _a;
13695      const innerMostFormatNode = foldr(formatNodes, (parentNode, formatNode) => {
13696        return appendNode(parentNode, formatNode.cloneNode(false));
13697      }, caretContainer);
13698      const doc = (_a = innerMostFormatNode.ownerDocument) !== null && _a !== void 0 ? _a : document;
13699      return appendNode(innerMostFormatNode, doc.createTextNode(ZWSP));
13700    };
13701    const cleanFormatNode = (editor, caretContainer, formatNode, name, vars, similar) => {
13702      const formatter = editor.formatter;
13703      const dom = editor.dom;
13704      const validFormats = filter$5(keys(formatter.get()), formatName => formatName !== name && !contains$1(formatName, 'removeformat'));
13705      const matchedFormats = matchAllOnNode(editor, formatNode, validFormats);
13706      const uniqueFormats = filter$5(matchedFormats, fmtName => !areSimilarFormats(editor, fmtName, name));
13707      if (uniqueFormats.length > 0) {
13708        const clonedFormatNode = formatNode.cloneNode(false);
13709        dom.add(caretContainer, clonedFormatNode);
13710        formatter.remove(name, vars, clonedFormatNode, similar);
13711        dom.remove(clonedFormatNode);
13712        return Optional.some(clonedFormatNode);
13713      } else {
13714        return Optional.none();
13715      }
13716    };
13717    const normalizeNbsps = node => set(node, get$3(node).replace(new RegExp(`${ nbsp }$`), ' '));
13718    const normalizeNbspsBetween = (editor, caretContainer) => {
13719      const handler = () => {
13720        if (caretContainer !== null && !editor.dom.isEmpty(caretContainer)) {
13721          prevSibling(SugarElement.fromDom(caretContainer)).each(node => {
13722            if (isText$c(node)) {
13723              normalizeNbsps(node);
13724            } else {
13725              descendant$2(node, e => isText$c(e)).each(textNode => {
13726                if (isText$c(textNode)) {
13727                  normalizeNbsps(textNode);
13728                }
13729              });
13730            }
13731          });
13732        }
13733      };
13734      editor.once('input', e => {
13735        if (e.data && !isWhiteSpace(e.data)) {
13736          if (!e.isComposing) {
13737            handler();
13738          } else {
13739            editor.once('compositionend', () => {
13740              handler();
13741            });
13742          }
13743        }
13744      });
13745    };
13746    const applyCaretFormat = (editor, name, vars) => {
13747      let caretContainer;
13748      const selection = editor.selection;
13749      const formatList = editor.formatter.get(name);
13750      if (!formatList) {
13751        return;
13752      }
13753      const selectionRng = selection.getRng();
13754      let offset = selectionRng.startOffset;
13755      const container = selectionRng.startContainer;
13756      const text = container.nodeValue;
13757      caretContainer = getParentCaretContainer(editor.getBody(), selection.getStart());
13758      const wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/;
13759      if (text && offset > 0 && offset < text.length && wordcharRegex.test(text.charAt(offset)) && wordcharRegex.test(text.charAt(offset - 1))) {
13760        const bookmark = selection.getBookmark();
13761        selectionRng.collapse(true);
13762        let rng = expandRng(editor.dom, selectionRng, formatList);
13763        rng = split(rng);
13764        editor.formatter.apply(name, vars, rng);
13765        selection.moveToBookmark(bookmark);
13766      } else {
13767        let textNode = caretContainer ? findFirstTextNode(caretContainer) : null;
13768        if (!caretContainer || (textNode === null || textNode === void 0 ? void 0 : textNode.data) !== ZWSP) {
13769          caretContainer = importNode(editor.getDoc(), createCaretContainer(true).dom);
13770          textNode = caretContainer.firstChild;
vendor: 2,650 bytes, lines 13771-13837
13771          selectionRng.insertNode(caretContainer);
13772          offset = 1;
13773          normalizeNbspsBetween(editor, caretContainer);
13774          editor.formatter.apply(name, vars, caretContainer);
13775        } else {
13776          editor.formatter.apply(name, vars, caretContainer);
13777        }
13778        selection.setCursorLocation(textNode, offset);
13779      }
13780    };
13781    const removeCaretFormat = (editor, name, vars, similar) => {
13782      const dom = editor.dom;
13783      const selection = editor.selection;
13784      let hasContentAfter = false;
13785      const formatList = editor.formatter.get(name);
13786      if (!formatList) {
13787        return;
13788      }
13789      const rng = selection.getRng();
13790      const container = rng.startContainer;
13791      const offset = rng.startOffset;
13792      let node = container;
13793      if (isText$b(container)) {
13794        if (offset !== container.data.length) {
13795          hasContentAfter = true;
13796        }
13797        node = node.parentNode;
13798      }
13799      const parents = [];
13800      let formatNode;
13801      while (node) {
13802        if (matchNode(editor, node, name, vars, similar)) {
13803          formatNode = node;
13804          break;
13805        }
13806        if (node.nextSibling) {
13807          hasContentAfter = true;
13808        }
13809        parents.push(node);
13810        node = node.parentNode;
13811      }
13812      if (!formatNode) {
13813        return;
13814      }
13815      if (hasContentAfter) {
13816        const bookmark = selection.getBookmark();
13817        rng.collapse(true);
13818        let expandedRng = expandRng(dom, rng, formatList, { includeTrailingSpace: true });
13819        expandedRng = split(expandedRng);
13820        editor.formatter.remove(name, vars, expandedRng, similar);
13821        selection.moveToBookmark(bookmark);
13822      } else {
13823        const caretContainer = getParentCaretContainer(editor.getBody(), formatNode);
13824        const parentsAfter = isNonNullable(caretContainer) ? dom.getParents(formatNode.parentNode, always, caretContainer) : [];
13825        const newCaretContainer = createCaretContainer(false).dom;
13826        insertCaretContainerNode(editor, newCaretContainer, caretContainer !== null && caretContainer !== void 0 ? caretContainer : formatNode);
13827        const cleanedFormatNode = cleanFormatNode(editor, newCaretContainer, formatNode, name, vars, similar);
13828        const caretTextNode = insertFormatNodesIntoCaretContainer([
13829          ...parents,
13830          ...cleanedFormatNode.toArray(),
13831          ...parentsAfter
13832        ], newCaretContainer);
13833        if (caretContainer) {
13834          removeCaretContainerNode(editor, caretContainer, isNonNullable(caretContainer));
13835        }
13836        selection.setCursorLocation(caretTextNode, 1);
13837        normalizeNbspsBetween(editor, newCaretContainer
vendor: 22,019 bytes, lines 13837-14380
13837);
13838        if (dom.isEmpty(formatNode)) {
13839          dom.remove(formatNode);
13840        }
13841      }
13842    };
13843    const disableCaretContainer = (editor, keyCode, moveCaret) => {
13844      const selection = editor.selection, body = editor.getBody();
13845      removeCaretContainer(editor, null, moveCaret);
13846      if ((keyCode === 8 || keyCode === 46) && selection.isCollapsed() && selection.getStart().innerHTML === ZWSP) {
13847        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()), true);
13848      }
13849      if (keyCode === 37 || keyCode === 39) {
13850        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()), true);
13851      }
13852    };
13853    const endsWithNbsp = element => isText$b(element) && endsWith(element.data, nbsp);
13854    const setup$v = editor => {
13855      editor.on('mouseup keydown', e => {
13856        disableCaretContainer(editor, e.keyCode, endsWithNbsp(editor.selection.getRng().endContainer));
13857      });
13858    };
13859    const createCaretFormat = formatNodes => {
13860      const caretContainer = createCaretContainer(false);
13861      const innerMost = insertFormatNodesIntoCaretContainer(formatNodes, caretContainer.dom);
13862      return {
13863        caretContainer,
13864        caretPosition: CaretPosition(innerMost, 0)
13865      };
13866    };
13867    const replaceWithCaretFormat = (targetNode, formatNodes) => {
13868      const {caretContainer, caretPosition} = createCaretFormat(formatNodes);
13869      before$3(SugarElement.fromDom(targetNode), caretContainer);
13870      remove$4(SugarElement.fromDom(targetNode));
13871      return caretPosition;
13872    };
13873    const createCaretFormatAtStart$1 = (rng, formatNodes) => {
13874      const {caretContainer, caretPosition} = createCaretFormat(formatNodes);
13875      rng.insertNode(caretContainer.dom);
13876      return caretPosition;
13877    };
13878    const isFormatElement = (editor, element) => {
13879      if (isCaretNode(element.dom)) {
13880        return false;
13881      }
13882      const inlineElements = editor.schema.getTextInlineElements();
13883      return has$2(inlineElements, name(element)) && !isCaretNode(element.dom) && !isBogus$1(element.dom);
13884    };
13885
13886    const postProcessHooks = {};
13887    const isPre = matchNodeNames(['pre']);
13888    const addPostProcessHook = (name, hook) => {
13889      const hooks = postProcessHooks[name];
13890      if (!hooks) {
13891        postProcessHooks[name] = [];
13892      }
13893      postProcessHooks[name].push(hook);
13894    };
13895    const postProcess$1 = (name, editor) => {
13896      if (has$2(postProcessHooks, name)) {
13897        each$e(postProcessHooks[name], hook => {
13898          hook(editor);
13899        });
13900      }
13901    };
13902    addPostProcessHook('pre', editor => {
13903      const rng = editor.selection.getRng();
13904      const hasPreSibling = blocks => pre => {
13905        const prev = pre.previousSibling;
13906        return isPre(prev) && contains$2(blocks, prev);
13907      };
13908      const joinPre = (pre1, pre2) => {
13909        const sPre2 = SugarElement.fromDom(pre2);
13910        const doc = documentOrOwner(sPre2).dom;
13911        remove$4(sPre2);
13912        append(SugarElement.fromDom(pre1), [
13913          SugarElement.fromTag('br', doc),
13914          SugarElement.fromTag('br', doc),
13915          ...children$1(sPre2)
13916        ]);
13917      };
13918      if (!rng.collapsed) {
13919        const blocks = editor.selection.getSelectedBlocks();
13920        const preBlocks = filter$5(filter$5(blocks, isPre), hasPreSibling(blocks));
13921        each$e(preBlocks, pre => {
13922          joinPre(pre.previousSibling, pre);
13923        });
13924      }
13925    });
13926
13927    const listItemStyles = [
13928      'fontWeight',
13929      'fontStyle',
13930      'color',
13931      'fontSize',
13932      'fontFamily'
13933    ];
13934    const hasListStyles = fmt => isObject(fmt.styles) && exists(keys(fmt.styles), name => contains$2(listItemStyles, name));
13935    const findExpandedListItemFormat = formats => find$2(formats, fmt => isInlineFormat(fmt) && fmt.inline === 'span' && hasListStyles(fmt));
13936    const getExpandedListItemFormat = (formatter, format) => {
13937      const formatList = formatter.get(format);
13938      return isArray$1(formatList) ? findExpandedListItemFormat(formatList) : Optional.none();
13939    };
13940    const isRngStartAtStartOfElement = (rng, elm) => prevPosition(elm, CaretPosition.fromRangeStart(rng)).isNone();
13941    const isRngEndAtEndOfElement = (rng, elm) => {
13942      return nextPosition(elm, CaretPosition.fromRangeEnd(rng)).exists(pos => !isBr$6(pos.getNode()) || nextPosition(elm, pos).isSome()) === false;
13943    };
13944    const isEditableListItem = dom => elm => isListItem$2(elm) && dom.isEditable(elm);
13945    const getFullySelectedBlocks = selection => {
13946      const blocks = selection.getSelectedBlocks();
13947      const rng = selection.getRng();
13948      if (selection.isCollapsed()) {
13949        return [];
13950      }
13951      if (blocks.length === 1) {
13952        return isRngStartAtStartOfElement(rng, blocks[0]) && isRngEndAtEndOfElement(rng, blocks[0]) ? blocks : [];
13953      } else {
13954        const first = head(blocks).filter(elm => isRngStartAtStartOfElement(rng, elm)).toArray();
13955        const last = last$2(blocks).filter(elm => isRngEndAtEndOfElement(rng, elm)).toArray();
13956        const middle = blocks.slice(1, -1);
13957        return first.concat(middle).concat(last);
13958      }
13959    };
13960    const getFullySelectedListItems = selection => filter$5(getFullySelectedBlocks(selection), isEditableListItem(selection.dom));
13961    const getPartiallySelectedListItems = selection => filter$5(selection.getSelectedBlocks(), isEditableListItem(selection.dom));
13962
13963    const each$8 = Tools.each;
13964    const isElementNode = node => isElement$6(node) && !isBookmarkNode$1(node) && !isCaretNode(node) && !isBogus$1(node);
13965    const findElementSibling = (node, siblingName) => {
13966      for (let sibling = node; sibling; sibling = sibling[siblingName]) {
13967        if (isText$b(sibling) && isNotEmpty(sibling.data)) {
13968          return node;
13969        }
13970        if (isElement$6(sibling) && !isBookmarkNode$1(sibling)) {
13971          return sibling;
13972        }
13973      }
13974      return node;
13975    };
13976    const mergeSiblingsNodes = (editor, prev, next) => {
13977      const elementUtils = ElementUtils(editor);
13978      const isPrevEditable = isHTMLElement(prev) && editor.dom.isEditable(prev);
13979      const isNextEditable = isHTMLElement(next) && editor.dom.isEditable(next);
13980      if (isPrevEditable && isNextEditable) {
13981        const prevSibling = findElementSibling(prev, 'previousSibling');
13982        const nextSibling = findElementSibling(next, 'nextSibling');
13983        if (elementUtils.compare(prevSibling, nextSibling)) {
13984          for (let sibling = prevSibling.nextSibling; sibling && sibling !== nextSibling;) {
13985            const tmpSibling = sibling;
13986            sibling = sibling.nextSibling;
13987            prevSibling.appendChild(tmpSibling);
13988          }
13989          editor.dom.remove(nextSibling);
13990          Tools.each(Tools.grep(nextSibling.childNodes), node => {
13991            prevSibling.appendChild(node);
13992          });
13993          return prevSibling;
13994        }
13995      }
13996      return next;
13997    };
13998    const mergeSiblings = (editor, format, vars, node) => {
13999      var _a;
14000      if (node && format.merge_siblings !== false) {
14001        const newNode = (_a = mergeSiblingsNodes(editor, getNonWhiteSpaceSibling(node), node)) !== null && _a !== void 0 ? _a : node;
14002        mergeSiblingsNodes(editor, newNode, getNonWhiteSpaceSibling(newNode, true));
14003      }
14004    };
14005    const clearChildStyles = (dom, format, node) => {
14006      if (format.clear_child_styles) {
14007        const selector = format.links ? '*:not(a)' : '*';
14008        each$8(dom.select(selector, node), childNode => {
14009          if (isElementNode(childNode) && dom.isEditable(childNode)) {
14010            each$8(format.styles, (_value, name) => {
14011              dom.setStyle(childNode, name, '');
14012            });
14013          }
14014        });
14015      }
14016    };
14017    const processChildElements = (node, filter, process) => {
14018      each$8(node.childNodes, node => {
14019        if (isElementNode(node)) {
14020          if (filter(node)) {
14021            process(node);
14022          }
14023          if (node.hasChildNodes()) {
14024            processChildElements(node, filter, process);
14025          }
14026        }
14027      });
14028    };
14029    const unwrapEmptySpan = (dom, node) => {
14030      if (node.nodeName === 'SPAN' && dom.getAttribs(node).length === 0) {
14031        dom.remove(node, true);
14032      }
14033    };
14034    const hasStyle = (dom, name) => node => !!(node && getStyle(dom, node, name));
14035    const applyStyle = (dom, name, value) => node => {
14036      dom.setStyle(node, name, value);
14037      if (node.getAttribute('style') === '') {
14038        node.removeAttribute('style');
14039      }
14040      unwrapEmptySpan(dom, node);
14041    };
14042
14043    const removeResult = Adt.generate([
14044      { keep: [] },
14045      { rename: ['name'] },
14046      { removed: [] }
14047    ]);
14048    const MCE_ATTR_RE = /^(src|href|style)$/;
14049    const each$7 = Tools.each;
14050    const isEq$2 = isEq$5;
14051    const isTableCellOrRow = node => /^(TR|TH|TD)$/.test(node.nodeName);
14052    const isChildOfInlineParent = (dom, node, parent) => dom.isChildOf(node, parent) && node !== parent && !dom.isBlock(parent);
14053    const getContainer = (ed, rng, start) => {
14054      let container = rng[start ? 'startContainer' : 'endContainer'];
14055      let offset = rng[start ? 'startOffset' : 'endOffset'];
14056      if (isElement$6(container)) {
14057        const lastIdx = container.childNodes.length - 1;
14058        if (!start && offset) {
14059          offset--;
14060        }
14061        container = container.childNodes[offset > lastIdx ? lastIdx : offset];
14062      }
14063      if (isText$b(container) && start && offset >= container.data.length) {
14064        container = new DomTreeWalker(container, ed.getBody()).next() || container;
14065      }
14066      if (isText$b(container) && !start && offset === 0) {
14067        container = new DomTreeWalker(container, ed.getBody()).prev() || container;
14068      }
14069      return container;
14070    };
14071    const normalizeTableSelection = (node, start) => {
14072      const prop = start ? 'firstChild' : 'lastChild';
14073      const childNode = node[prop];
14074      if (isTableCellOrRow(node) && childNode) {
14075        if (node.nodeName === 'TR') {
14076          return childNode[prop] || childNode;
14077        } else {
14078          return childNode;
14079        }
14080      }
14081      return node;
14082    };
14083    const wrap$1 = (dom, node, name, attrs) => {
14084      var _a;
14085      const wrapper = dom.create(name, attrs);
14086      (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(wrapper, node);
14087      wrapper.appendChild(node);
14088      return wrapper;
14089    };
14090    const wrapWithSiblings = (dom, node, next, name, attrs) => {
14091      const start = SugarElement.fromDom(node);
14092      const wrapper = SugarElement.fromDom(dom.create(name, attrs));
14093      const siblings = next ? nextSiblings(start) : prevSiblings(start);
14094      append(wrapper, siblings);
14095      if (next) {
14096        before$3(start, wrapper);
14097        prepend(wrapper, start);
14098      } else {
14099        after$4(start, wrapper);
14100        append$1(wrapper, start);
14101      }
14102      return wrapper.dom;
14103    };
14104    const isColorFormatAndAnchor = (node, format) => format.links && node.nodeName === 'A';
14105    const removeNode = (ed, node, format) => {
14106      const parentNode = node.parentNode;
14107      let rootBlockElm;
14108      const dom = ed.dom;
14109      const forcedRootBlock = getForcedRootBlock(ed);
14110      if (isBlockFormat(format)) {
14111        if (parentNode === dom.getRoot()) {
14112          if (!format.list_block || !isEq$2(node, format.list_block)) {
14113            each$e(from(node.childNodes), node => {
14114              if (isValid(ed, forcedRootBlock, node.nodeName.toLowerCase())) {
14115                if (!rootBlockElm) {
14116                  rootBlockElm = wrap$1(dom, node, forcedRootBlock);
14117                  dom.setAttribs(rootBlockElm, getForcedRootBlockAttrs(ed));
14118                } else {
14119                  rootBlockElm.appendChild(node);
14120                }
14121              } else {
14122                rootBlockElm = null;
14123              }
14124            });
14125          }
14126        }
14127      }
14128      if (isMixedFormat(format) && !isEq$2(format.inline, node)) {
14129        return;
14130      }
14131      dom.remove(node, true);
14132    };
14133    const processFormatAttrOrStyle = (name, value, vars) => {
14134      if (isNumber(name)) {
14135        return {
14136          name: value,
14137          value: null
14138        };
14139      } else {
14140        return {
14141          name,
14142          value: replaceVars(value, vars)
14143        };
14144      }
14145    };
14146    const removeEmptyStyleAttributeIfNeeded = (dom, elm) => {
14147      if (dom.getAttrib(elm, 'style') === '') {
14148        elm.removeAttribute('style');
14149        elm.removeAttribute('data-mce-style');
14150      }
14151    };
14152    const removeStyles = (dom, elm, format, vars, compareNode) => {
14153      let stylesModified = false;
14154      each$7(format.styles, (value, name) => {
14155        const {
14156          name: styleName,
14157          value: styleValue
14158        } = processFormatAttrOrStyle(name, value, vars);
14159        const normalizedStyleValue = normalizeStyleValue(styleValue, styleName);
14160        if (format.remove_similar || isNull(styleValue) || !isElement$6(compareNode) || isEq$2(getStyle(dom, compareNode, styleName), normalizedStyleValue)) {
14161          dom.setStyle(elm, styleName, '');
14162        }
14163        stylesModified = true;
14164      });
14165      if (stylesModified) {
14166        removeEmptyStyleAttributeIfNeeded(dom, elm);
14167      }
14168    };
14169    const removeListStyleFormats = (editor, name, vars) => {
14170      if (name === 'removeformat') {
14171        each$e(getPartiallySelectedListItems(editor.selection), li => {
14172          each$e(listItemStyles, name => editor.dom.setStyle(li, name, ''));
14173          removeEmptyStyleAttributeIfNeeded(editor.dom, li);
14174        });
14175      } else {
14176        getExpandedListItemFormat(editor.formatter, name).each(liFmt => {
14177          each$e(getPartiallySelectedListItems(editor.selection), li => removeStyles(editor.dom, li, liFmt, vars, null));
14178        });
14179      }
14180    };
14181    const removeNodeFormatInternal = (ed, format, vars, node, compareNode) => {
14182      const dom = ed.dom;
14183      const elementUtils = ElementUtils(ed);
14184      const schema = ed.schema;
14185      if (isInlineFormat(format) && isTransparentElementName(schema, format.inline) && isTransparentBlock(schema, node) && node.parentElement === ed.getBody()) {
14186        removeNode(ed, node, format);
14187        return removeResult.removed();
14188      }
14189      if (!format.ceFalseOverride && node && dom.getContentEditableParent(node) === 'false') {
14190        return removeResult.keep();
14191      }
14192      if (node && !matchName(dom, node, format) && !isColorFormatAndAnchor(node, format)) {
14193        return removeResult.keep();
14194      }
14195      const elm = node;
14196      const preserveAttributes = format.preserve_attributes;
14197      if (isInlineFormat(format) && format.remove === 'all' && isArray$1(preserveAttributes)) {
14198        const attrsToPreserve = filter$5(dom.getAttribs(elm), attr => contains$2(preserveAttributes, attr.name.toLowerCase()));
14199        dom.removeAllAttribs(elm);
14200        each$e(attrsToPreserve, attr => dom.setAttrib(elm, attr.name, attr.value));
14201        if (attrsToPreserve.length > 0) {
14202          return removeResult.rename('span');
14203        }
14204      }
14205      if (format.remove !== 'all') {
14206        removeStyles(dom, elm, format, vars, compareNode);
14207        each$7(format.attributes, (value, name) => {
14208          const {
14209            name: attrName,
14210            value: attrValue
14211          } = processFormatAttrOrStyle(name, value, vars);
14212          if (format.remove_similar || isNull(attrValue) || !isElement$6(compareNode) || isEq$2(dom.getAttrib(compareNode, attrName), attrValue)) {
14213            if (attrName === 'class') {
14214              const currentValue = dom.getAttrib(elm, attrName);
14215              if (currentValue) {
14216                let valueOut = '';
14217                each$e(currentValue.split(/\s+/), cls => {
14218                  if (/mce\-\w+/.test(cls)) {
14219                    valueOut += (valueOut ? ' ' : '') + cls;
14220                  }
14221                });
14222                if (valueOut) {
14223                  dom.setAttrib(elm, attrName, valueOut);
14224                  return;
14225                }
14226              }
14227            }
14228            if (MCE_ATTR_RE.test(attrName)) {
14229              elm.removeAttribute('data-mce-' + attrName);
14230            }
14231            if (attrName === 'style' && matchNodeNames(['li'])(elm) && dom.getStyle(elm, 'list-style-type') === 'none') {
14232              elm.removeAttribute(attrName);
14233              dom.setStyle(elm, 'list-style-type', 'none');
14234              return;
14235            }
14236            if (attrName === 'class') {
14237              elm.removeAttribute('className');
14238            }
14239            elm.removeAttribute(attrName);
14240          }
14241        });
14242        each$7(format.classes, value => {
14243          value = replaceVars(value, vars);
14244          if (!isElement$6(compareNode) || dom.hasClass(compareNode, value)) {
14245            dom.removeClass(elm, value);
14246          }
14247        });
14248        const attrs = dom.getAttribs(elm);
14249        for (let i = 0; i < attrs.length; i++) {
14250          const attrName = attrs[i].nodeName;
14251          if (!elementUtils.isAttributeInternal(attrName)) {
14252            return removeResult.keep();
14253          }
14254        }
14255      }
14256      if (format.remove !== 'none') {
14257        removeNode(ed, elm, format);
14258        return removeResult.removed();
14259      }
14260      return removeResult.keep();
14261    };
14262    const findFormatRoot = (editor, container, name, vars, similar) => {
14263      let formatRoot;
14264      if (container.parentNode) {
14265        each$e(getParents$2(editor.dom, container.parentNode).reverse(), parent => {
14266          if (!formatRoot && isElement$6(parent) && parent.id !== '_start' && parent.id !== '_end') {
14267            const format = matchNode(editor, parent, name, vars, similar);
14268            if (format && format.split !== false) {
14269              formatRoot = parent;
14270            }
14271          }
14272        });
14273      }
14274      return formatRoot;
14275    };
14276    const removeNodeFormatFromClone = (editor, format, vars, clone) => removeNodeFormatInternal(editor, format, vars, clone, clone).fold(constant(clone), newName => {
14277      const fragment = editor.dom.createFragment();
14278      fragment.appendChild(clone);
14279      return editor.dom.rename(clone, newName);
14280    }, constant(null));
14281    const wrapAndSplit = (editor, formatList, formatRoot, container, target, split, format, vars) => {
14282      var _a, _b;
14283      let lastClone;
14284      let firstClone;
14285      const dom = editor.dom;
14286      if (formatRoot) {
14287        const formatRootParent = formatRoot.parentNode;
14288        for (let parent = container.parentNode; parent && parent !== formatRootParent; parent = parent.parentNode) {
14289          let clone = dom.clone(parent, false);
14290          for (let i = 0; i < formatList.length; i++) {
14291            clone = removeNodeFormatFromClone(editor, formatList[i], vars, clone);
14292            if (clone === null) {
14293              break;
14294            }
14295          }
14296          if (clone) {
14297            if (lastClone) {
14298              clone.appendChild(lastClone);
14299            }
14300            if (!firstClone) {
14301              firstClone = clone;
14302            }
14303            lastClone = clone;
14304          }
14305        }
14306        if (split && (!format.mixed || !dom.isBlock(formatRoot))) {
14307          container = (_a = dom.split(formatRoot, container)) !== null && _a !== void 0 ? _a : container;
14308        }
14309        if (lastClone && firstClone) {
14310          (_b = target.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(lastClone, target);
14311          firstClone.appendChild(target);
14312          if (isInlineFormat(format)) {
14313            mergeSiblings(editor, format, vars, lastClone);
14314          }
14315        }
14316      }
14317      return container;
14318    };
14319    const removeFormatInternal = (ed, name, vars, node, similar) => {
14320      const formatList = ed.formatter.get(name);
14321      const format = formatList[0];
14322      const dom = ed.dom;
14323      const selection = ed.selection;
14324      const splitToFormatRoot = container => {
14325        const formatRoot = findFormatRoot(ed, container, name, vars, similar);
14326        return wrapAndSplit(ed, formatList, formatRoot, container, container, true, format, vars);
14327      };
14328      const isRemoveBookmarkNode = node => isBookmarkNode$1(node) && isElement$6(node) && (node.id === '_start' || node.id === '_end');
14329      const removeFormatOnNode = node => exists(formatList, fmt => removeNodeFormat(ed, fmt, vars, node, node));
14330      const process = node => {
14331        const children = from(node.childNodes);
14332        const removed = removeFormatOnNode(node);
14333        const currentNodeMatches = removed || exists(formatList, f => matchName(dom, node, f));
14334        const parentNode = node.parentNode;
14335        if (!currentNodeMatches && isNonNullable(parentNode) && shouldExpandToSelector(format)) {
14336          removeFormatOnNode(parentNode);
14337        }
14338        if (format.deep) {
14339          if (children.length) {
14340            for (let i = 0; i < children.length; i++) {
14341              process(children[i]);
14342            }
14343          }
14344        }
14345        const textDecorations = [
14346          'underline',
14347          'line-through',
14348          'overline'
14349        ];
14350        each$e(textDecorations, decoration => {
14351          if (isElement$6(node) && ed.dom.getStyle(node, 'text-decoration') === decoration && node.parentNode && getTextDecoration(dom, node.parentNode) === decoration) {
14352            removeNodeFormat(ed, {
14353              deep: false,
14354              exact: true,
14355              inline: 'span',
14356              styles: { textDecoration: decoration }
14357            }, undefined, node);
14358          }
14359        });
14360      };
14361      const unwrap = start => {
14362        const node = dom.get(start ? '_start' : '_end');
14363        if (node) {
14364          let out = node[start ? 'firstChild' : 'lastChild'];
14365          if (isRemoveBookmarkNode(out)) {
14366            out = out[start ? 'firstChild' : 'lastChild'];
14367          }
14368          if (isText$b(out) && out.data.length === 0) {
14369            out = start ? node.previousSibling || node.nextSibling : node.nextSibling || node.previousSibling;
14370          }
14371          dom.remove(node, true);
14372          return out;
14373        } else {
14374          return null;
14375        }
14376      };
14377      const removeRngStyle = rng => {
14378        let startContainer;
14379        let endContainer;
14380        let expandedRng = expandRng(dom, rng, formatList, 
vendor: 4,723 bytes, lines 14380-14489
14380{ includeTrailingSpace: rng.collapsed });
14381        if (format.split) {
14382          expandedRng = split(expandedRng);
14383          startContainer = getContainer(ed, expandedRng, true);
14384          endContainer = getContainer(ed, expandedRng);
14385          if (startContainer !== endContainer) {
14386            startContainer = normalizeTableSelection(startContainer, true);
14387            endContainer = normalizeTableSelection(endContainer, false);
14388            if (isChildOfInlineParent(dom, startContainer, endContainer)) {
14389              const marker = Optional.from(startContainer.firstChild).getOr(startContainer);
14390              splitToFormatRoot(wrapWithSiblings(dom, marker, true, 'span', {
14391                'id': '_start',
14392                'data-mce-type': 'bookmark'
14393              }));
14394              unwrap(true);
14395              return;
14396            }
14397            if (isChildOfInlineParent(dom, endContainer, startContainer)) {
14398              const marker = Optional.from(endContainer.lastChild).getOr(endContainer);
14399              splitToFormatRoot(wrapWithSiblings(dom, marker, false, 'span', {
14400                'id': '_end',
14401                'data-mce-type': 'bookmark'
14402              }));
14403              unwrap(false);
14404              return;
14405            }
14406            startContainer = wrap$1(dom, startContainer, 'span', {
14407              'id': '_start',
14408              'data-mce-type': 'bookmark'
14409            });
14410            endContainer = wrap$1(dom, endContainer, 'span', {
14411              'id': '_end',
14412              'data-mce-type': 'bookmark'
14413            });
14414            const newRng = dom.createRng();
14415            newRng.setStartAfter(startContainer);
14416            newRng.setEndBefore(endContainer);
14417            walk$3(dom, newRng, nodes => {
14418              each$e(nodes, n => {
14419                if (!isBookmarkNode$1(n) && !isBookmarkNode$1(n.parentNode)) {
14420                  splitToFormatRoot(n);
14421                }
14422              });
14423            });
14424            splitToFormatRoot(startContainer);
14425            splitToFormatRoot(endContainer);
14426            startContainer = unwrap(true);
14427            endContainer = unwrap();
14428          } else {
14429            startContainer = endContainer = splitToFormatRoot(startContainer);
14430          }
14431          expandedRng.startContainer = startContainer.parentNode ? startContainer.parentNode : startContainer;
14432          expandedRng.startOffset = dom.nodeIndex(startContainer);
14433          expandedRng.endContainer = endContainer.parentNode ? endContainer.parentNode : endContainer;
14434          expandedRng.endOffset = dom.nodeIndex(endContainer) + 1;
14435        }
14436        walk$3(dom, expandedRng, nodes => {
14437          each$e(nodes, process);
14438        });
14439      };
14440      if (node) {
14441        if (isNode(node)) {
14442          const rng = dom.createRng();
14443          rng.setStartBefore(node);
14444          rng.setEndAfter(node);
14445          removeRngStyle(rng);
14446        } else {
14447          removeRngStyle(node);
14448        }
14449        fireFormatRemove(ed, name, node, vars);
14450        return;
14451      }
14452      if (!selection.isCollapsed() || !isInlineFormat(format) || getCellsFromEditor(ed).length) {
14453        preserveSelection(ed, () => runOnRanges(ed, removeRngStyle), startNode => isInlineFormat(format) && match$2(ed, name, vars, startNode));
14454        ed.nodeChanged();
14455      } else {
14456        removeCaretFormat(ed, name, vars, similar);
14457      }
14458      removeListStyleFormats(ed, name, vars);
14459      fireFormatRemove(ed, name, node, vars);
14460    };
14461    const removeFormat$1 = (ed, name, vars, node, similar) => {
14462      if (node || ed.selection.isEditable()) {
14463        removeFormatInternal(ed, name, vars, node, similar);
14464      }
14465    };
14466    const removeNodeFormat = (editor, format, vars, node, compareNode) => {
14467      return removeNodeFormatInternal(editor, format, vars, node, compareNode).fold(never, newName => {
14468        editor.dom.rename(node, newName);
14469        return true;
14470      }, always);
14471    };
14472
14473    const each$6 = Tools.each;
14474    const mergeTextDecorationsAndColor = (dom, format, vars, node) => {
14475      const processTextDecorationsAndColor = n => {
14476        if (isHTMLElement(n) && isElement$6(n.parentNode) && dom.isEditable(n)) {
14477          const parentTextDecoration = getTextDecoration(dom, n.parentNode);
14478          if (dom.getStyle(n, 'color') && parentTextDecoration) {
14479            dom.setStyle(n, 'text-decoration', parentTextDecoration);
14480          } else if (dom.getStyle(n, 'text-decoration') === parentTextDecoration) {
14481            dom.setStyle(n, 'text-decoration', null);
14482          }
14483        }
14484      };
14485      if (format.styles && (format.styles.color || format.styles.textDecoration)) {
14486        Tools.walk(node, processTextDecorationsAndColor, 'childNodes');
14487        processTextDecorationsAndColor(node);
14488      }
14489    };
vendor: 10,546 bytes, lines 14490-14737
14490    const mergeBackgroundColorAndFontSize = (dom, format, vars, node) => {
14491      if (format.styles && format.styles.backgroundColor) {
14492        const hasFontSize = hasStyle(dom, 'fontSize');
14493        processChildElements(node, elm => hasFontSize(elm) && dom.isEditable(elm), applyStyle(dom, 'backgroundColor', replaceVars(format.styles.backgroundColor, vars)));
14494      }
14495    };
14496    const mergeSubSup = (dom, format, vars, node) => {
14497      if (isInlineFormat(format) && (format.inline === 'sub' || format.inline === 'sup')) {
14498        const hasFontSize = hasStyle(dom, 'fontSize');
14499        processChildElements(node, elm => hasFontSize(elm) && dom.isEditable(elm), applyStyle(dom, 'fontSize', ''));
14500        const inverseTagDescendants = filter$5(dom.select(format.inline === 'sup' ? 'sub' : 'sup', node), dom.isEditable);
14501        dom.remove(inverseTagDescendants, true);
14502      }
14503    };
14504    const mergeWithChildren = (editor, formatList, vars, node) => {
14505      each$6(formatList, format => {
14506        if (isInlineFormat(format)) {
14507          each$6(editor.dom.select(format.inline, node), child => {
14508            if (isElementNode(child)) {
14509              removeNodeFormat(editor, format, vars, child, format.exact ? child : null);
14510            }
14511          });
14512        }
14513        clearChildStyles(editor.dom, format, node);
14514      });
14515    };
14516    const mergeWithParents = (editor, format, name, vars, node) => {
14517      const parentNode = node.parentNode;
14518      if (matchNode(editor, parentNode, name, vars)) {
14519        if (removeNodeFormat(editor, format, vars, node)) {
14520          return;
14521        }
14522      }
14523      if (format.merge_with_parents && parentNode) {
14524        editor.dom.getParent(parentNode, parent => {
14525          if (matchNode(editor, parent, name, vars)) {
14526            removeNodeFormat(editor, format, vars, node);
14527            return true;
14528          } else {
14529            return false;
14530          }
14531        });
14532      }
14533    };
14534
14535    const each$5 = Tools.each;
14536    const canFormatBR = (editor, format, node, parentName) => {
14537      if (canFormatEmptyLines(editor) && isInlineFormat(format) && node.parentNode) {
14538        const validBRParentElements = getTextRootBlockElements(editor.schema);
14539        const hasCaretNodeSibling = sibling(SugarElement.fromDom(node), sibling => isCaretNode(sibling.dom));
14540        return hasNonNullableKey(validBRParentElements, parentName) && isEmptyNode(editor.schema, node.parentNode, {
14541          skipBogus: false,
14542          includeZwsp: true
14543        }) && !hasCaretNodeSibling;
14544      } else {
14545        return false;
14546      }
14547    };
14548    const applyStyles = (dom, elm, format, vars) => {
14549      each$5(format.styles, (value, name) => {
14550        dom.setStyle(elm, name, replaceVars(value, vars));
14551      });
14552      if (format.styles) {
14553        const styleVal = dom.getAttrib(elm, 'style');
14554        if (styleVal) {
14555          dom.setAttrib(elm, 'data-mce-style', styleVal);
14556        }
14557      }
14558    };
14559    const applyFormatAction = (ed, name, vars, node) => {
14560      const formatList = ed.formatter.get(name);
14561      const format = formatList[0];
14562      const isCollapsed = !node && ed.selection.isCollapsed();
14563      const dom = ed.dom;
14564      const selection = ed.selection;
14565      const setElementFormat = (elm, fmt = format) => {
14566        if (isFunction(fmt.onformat)) {
14567          fmt.onformat(elm, fmt, vars, node);
14568        }
14569        applyStyles(dom, elm, fmt, vars);
14570        each$5(fmt.attributes, (value, name) => {
14571          dom.setAttrib(elm, name, replaceVars(value, vars));
14572        });
14573        each$5(fmt.classes, value => {
14574          const newValue = replaceVars(value, vars);
14575          if (!dom.hasClass(elm, newValue)) {
14576            dom.addClass(elm, newValue);
14577          }
14578        });
14579      };
14580      const applyNodeStyle = (formatList, node) => {
14581        let found = false;
14582        each$5(formatList, format => {
14583          if (!isSelectorFormat(format)) {
14584            return false;
14585          }
14586          if (dom.getContentEditable(node) === 'false' && !format.ceFalseOverride) {
14587            return true;
14588          }
14589          if (isNonNullable(format.collapsed) && format.collapsed !== isCollapsed) {
14590            return true;
14591          }
14592          if (dom.is(node, format.selector) && !isCaretNode(node)) {
14593            setElementFormat(node, format);
14594            found = true;
14595            return false;
14596          }
14597          return true;
14598        });
14599        return found;
14600      };
14601      const createWrapElement = wrapName => {
14602        if (isString(wrapName)) {
14603          const wrapElm = dom.create(wrapName);
14604          setElementFormat(wrapElm);
14605          return wrapElm;
14606        } else {
14607          return null;
14608        }
14609      };
14610      const applyRngStyle = (dom, rng, nodeSpecific) => {
14611        const newWrappers = [];
14612        let contentEditable = true;
14613        const wrapName = format.inline || format.block;
14614        const wrapElm = createWrapElement(wrapName);
14615        const isMatchingWrappingBlock = node => isWrappingBlockFormat(format) && matchNode(ed, node, name, vars);
14616        const canRenameBlock = (node, parentName, isEditableDescendant) => {
14617          const isValidBlockFormatForNode = isNonWrappingBlockFormat(format) && isTextBlock$1(ed.schema, node) && isValid(ed, parentName, wrapName);
14618          return isEditableDescendant && isValidBlockFormatForNode;
14619        };
14620        const canWrapNode = (node, parentName, isEditableDescendant, isWrappableNoneditableElm) => {
14621          const nodeName = node.nodeName.toLowerCase();
14622          const isValidWrapNode = isValid(ed, wrapName, nodeName) && isValid(ed, parentName, wrapName);
14623          const isZwsp$1 = !nodeSpecific && isText$b(node) && isZwsp(node.data);
14624          const isCaret = isCaretNode(node);
14625          const isCorrectFormatForNode = !isInlineFormat(format) || !dom.isBlock(node);
14626          return (isEditableDescendant || isWrappableNoneditableElm) && isValidWrapNode && !isZwsp$1 && !isCaret && isCorrectFormatForNode;
14627        };
14628        walk$3(dom, rng, nodes => {
14629          let currentWrapElm;
14630          const process = node => {
14631            let hasContentEditableState = false;
14632            let lastContentEditable = contentEditable;
14633            let isWrappableNoneditableElm = false;
14634            const parentNode = node.parentNode;
14635            const parentName = parentNode.nodeName.toLowerCase();
14636            const contentEditableValue = dom.getContentEditable(node);
14637            if (isNonNullable(contentEditableValue)) {
14638              lastContentEditable = contentEditable;
14639              contentEditable = contentEditableValue === 'true';
14640              hasContentEditableState = true;
14641              isWrappableNoneditableElm = isWrappableNoneditable(ed, node);
14642            }
14643            const isEditableDescendant = contentEditable && !hasContentEditableState;
14644            if (isBr$6(node) && !canFormatBR(ed, format, node, parentName)) {
14645              currentWrapElm = null;
14646              if (isBlockFormat(format)) {
14647                dom.remove(node);
14648              }
14649              return;
14650            }
14651            if (isMatchingWrappingBlock(node)) {
14652              currentWrapElm = null;
14653              return;
14654            }
14655            if (canRenameBlock(node, parentName, isEditableDescendant)) {
14656              const elm = dom.rename(node, wrapName);
14657              setElementFormat(elm);
14658              newWrappers.push(elm);
14659              currentWrapElm = null;
14660              return;
14661            }
14662            if (isSelectorFormat(format)) {
14663              let found = applyNodeStyle(formatList, node);
14664              if (!found && isNonNullable(parentNode) && shouldExpandToSelector(format)) {
14665                found = applyNodeStyle(formatList, parentNode);
14666              }
14667              if (!isInlineFormat(format) || found) {
14668                currentWrapElm = null;
14669                return;
14670              }
14671            }
14672            if (isNonNullable(wrapElm) && canWrapNode(node, parentName, isEditableDescendant, isWrappableNoneditableElm)) {
14673              if (!currentWrapElm) {
14674                currentWrapElm = dom.clone(wrapElm, false);
14675                parentNode.insertBefore(currentWrapElm, node);
14676                newWrappers.push(currentWrapElm);
14677              }
14678              if (isWrappableNoneditableElm && hasContentEditableState) {
14679                contentEditable = lastContentEditable;
14680              }
14681              currentWrapElm.appendChild(node);
14682            } else {
14683              currentWrapElm = null;
14684              each$e(from(node.childNodes), process);
14685              if (hasContentEditableState) {
14686                contentEditable = lastContentEditable;
14687              }
14688              currentWrapElm = null;
14689            }
14690          };
14691          each$e(nodes, process);
14692        });
14693        if (format.links === true) {
14694          each$e(newWrappers, node => {
14695            const process = node => {
14696              if (node.nodeName === 'A') {
14697                setElementFormat(node, format);
14698              }
14699              each$e(from(node.childNodes), process);
14700            };
14701            process(node);
14702          });
14703        }
14704        each$e(newWrappers, node => {
14705          const getChildCount = node => {
14706            let count = 0;
14707            each$e(node.childNodes, node => {
14708              if (!isEmptyTextNode$1(node) && !isBookmarkNode$1(node)) {
14709                count++;
14710              }
14711            });
14712            return count;
14713          };
14714          const mergeStyles = node => {
14715            const childElement = find$2(node.childNodes, isElementNode$1).filter(child => dom.getContentEditable(child) !== 'false' && matchName(dom, child, format));
14716            return childElement.map(child => {
14717              const clone = dom.clone(child, false);
14718              setElementFormat(clone);
14719              dom.replace(clone, node, true);
14720              dom.remove(child, true);
14721              return clone;
14722            }).getOr(node);
14723          };
14724          const childCount = getChildCount(node);
14725          if ((newWrappers.length > 1 || !dom.isBlock(node)) && childCount === 0) {
14726            dom.remove(node, true);
14727            return;
14728          }
14729          if (isInlineFormat(format) || isBlockFormat(format) && format.wrapper) {
14730            if (!format.exact && childCount === 1) {
14731              node = mergeStyles(node);
14732            }
14733            mergeWithChildren(ed, formatList, vars, node);
14734            mergeWithParents(ed, format, name, vars, node);
14735            mergeBackgroundColorAndFontSize(dom, format, vars, node);
14736            mergeTextDecorationsAndColor(dom, format, vars, node);
14737            mergeSubSup(dom
vendor: 10,930 bytes, lines 14737-15036
14737, format, vars, node);
14738            mergeSiblings(ed, format, vars, node);
14739          }
14740        });
14741      };
14742      const targetNode = isNode(node) ? node : selection.getNode();
14743      if (dom.getContentEditable(targetNode) === 'false' && !isWrappableNoneditable(ed, targetNode)) {
14744        node = targetNode;
14745        applyNodeStyle(formatList, node);
14746        fireFormatApply(ed, name, node, vars);
14747        return;
14748      }
14749      if (format) {
14750        if (node) {
14751          if (isNode(node)) {
14752            if (!applyNodeStyle(formatList, node)) {
14753              const rng = dom.createRng();
14754              rng.setStartBefore(node);
14755              rng.setEndAfter(node);
14756              applyRngStyle(dom, expandRng(dom, rng, formatList), true);
14757            }
14758          } else {
14759            applyRngStyle(dom, node, true);
14760          }
14761        } else {
14762          if (!isCollapsed || !isInlineFormat(format) || getCellsFromEditor(ed).length) {
14763            selection.setRng(normalize(selection.getRng()));
14764            preserveSelection(ed, () => {
14765              runOnRanges(ed, (selectionRng, fake) => {
14766                const expandedRng = fake ? selectionRng : expandRng(dom, selectionRng, formatList);
14767                applyRngStyle(dom, expandedRng, false);
14768              });
14769            }, always);
14770            ed.nodeChanged();
14771          } else {
14772            applyCaretFormat(ed, name, vars);
14773          }
14774          getExpandedListItemFormat(ed.formatter, name).each(liFmt => {
14775            each$e(getFullySelectedListItems(ed.selection), li => applyStyles(dom, li, liFmt, vars));
14776          });
14777        }
14778        postProcess$1(name, ed);
14779      }
14780      fireFormatApply(ed, name, node, vars);
14781    };
14782    const applyFormat$1 = (editor, name, vars, node) => {
14783      if (node || editor.selection.isEditable()) {
14784        applyFormatAction(editor, name, vars, node);
14785      }
14786    };
14787
14788    const hasVars = value => has$2(value, 'vars');
14789    const setup$u = (registeredFormatListeners, editor) => {
14790      registeredFormatListeners.set({});
14791      editor.on('NodeChange', e => {
14792        updateAndFireChangeCallbacks(editor, e.element, registeredFormatListeners.get());
14793      });
14794      editor.on('FormatApply FormatRemove', e => {
14795        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));
14796        updateAndFireChangeCallbacks(editor, element, registeredFormatListeners.get());
14797      });
14798    };
14799    const fallbackElement = editor => editor.selection.getStart();
14800    const matchingNode = (editor, parents, format, similar, vars) => {
14801      const isMatchingNode = node => {
14802        const matchingFormat = editor.formatter.matchNode(node, format, vars !== null && vars !== void 0 ? vars : {}, similar);
14803        return !isUndefined(matchingFormat);
14804      };
14805      const isUnableToMatch = node => {
14806        if (matchesUnInheritedFormatSelector(editor, node, format)) {
14807          return true;
14808        } else {
14809          if (!similar) {
14810            return isNonNullable(editor.formatter.matchNode(node, format, vars, true));
14811          } else {
14812            return false;
14813          }
14814        }
14815      };
14816      return findUntil$1(parents, isMatchingNode, isUnableToMatch);
14817    };
14818    const getParents = (editor, elm) => {
14819      const element = elm !== null && elm !== void 0 ? elm : fallbackElement(editor);
14820      return filter$5(getParents$2(editor.dom, element), node => isElement$6(node) && !isBogus$1(node));
14821    };
14822    const updateAndFireChangeCallbacks = (editor, elm, registeredCallbacks) => {
14823      const parents = getParents(editor, elm);
14824      each$d(registeredCallbacks, (data, format) => {
14825        const runIfChanged = spec => {
14826          const match = matchingNode(editor, parents, format, spec.similar, hasVars(spec) ? spec.vars : undefined);
14827          const isSet = match.isSome();
14828          if (spec.state.get() !== isSet) {
14829            spec.state.set(isSet);
14830            const node = match.getOr(elm);
14831            if (hasVars(spec)) {
14832              spec.callback(isSet, {
14833                node,
14834                format,
14835                parents
14836              });
14837            } else {
14838              each$e(spec.callbacks, callback => callback(isSet, {
14839                node,
14840                format,
14841                parents
14842              }));
14843            }
14844          }
14845        };
14846        each$e([
14847          data.withSimilar,
14848          data.withoutSimilar
14849        ], runIfChanged);
14850        each$e(data.withVars, runIfChanged);
14851      });
14852    };
14853    const addListeners = (editor, registeredFormatListeners, formats, callback, similar, vars) => {
14854      const formatChangeItems = registeredFormatListeners.get();
14855      each$e(formats.split(','), format => {
14856        const group = get$a(formatChangeItems, format).getOrThunk(() => {
14857          const base = {
14858            withSimilar: {
14859              state: Cell(false),
14860              similar: true,
14861              callbacks: []
14862            },
14863            withoutSimilar: {
14864              state: Cell(false),
14865              similar: false,
14866              callbacks: []
14867            },
14868            withVars: []
14869          };
14870          formatChangeItems[format] = base;
14871          return base;
14872        });
14873        const getCurrent = () => {
14874          const parents = getParents(editor);
14875          return matchingNode(editor, parents, format, similar, vars).isSome();
14876        };
14877        if (isUndefined(vars)) {
14878          const toAppendTo = similar ? group.withSimilar : group.withoutSimilar;
14879          toAppendTo.callbacks.push(callback);
14880          if (toAppendTo.callbacks.length === 1) {
14881            toAppendTo.state.set(getCurrent());
14882          }
14883        } else {
14884          group.withVars.push({
14885            state: Cell(getCurrent()),
14886            similar,
14887            vars,
14888            callback
14889          });
14890        }
14891      });
14892      registeredFormatListeners.set(formatChangeItems);
14893    };
14894    const removeListeners = (registeredFormatListeners, formats, callback) => {
14895      const formatChangeItems = registeredFormatListeners.get();
14896      each$e(formats.split(','), format => get$a(formatChangeItems, format).each(group => {
14897        formatChangeItems[format] = {
14898          withSimilar: {
14899            ...group.withSimilar,
14900            callbacks: filter$5(group.withSimilar.callbacks, cb => cb !== callback)
14901          },
14902          withoutSimilar: {
14903            ...group.withoutSimilar,
14904            callbacks: filter$5(group.withoutSimilar.callbacks, cb => cb !== callback)
14905          },
14906          withVars: filter$5(group.withVars, item => item.callback !== callback)
14907        };
14908      }));
14909      registeredFormatListeners.set(formatChangeItems);
14910    };
14911    const formatChangedInternal = (editor, registeredFormatListeners, formats, callback, similar, vars) => {
14912      addListeners(editor, registeredFormatListeners, formats, callback, similar, vars);
14913      return { unbind: () => removeListeners(registeredFormatListeners, formats, callback) };
14914    };
14915
14916    const toggle = (editor, name, vars, node) => {
14917      const fmt = editor.formatter.get(name);
14918      if (fmt) {
14919        if (match$2(editor, name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) {
14920          removeFormat$1(editor, name, vars, node);
14921        } else {
14922          applyFormat$1(editor, name, vars, node);
14923        }
14924      }
14925    };
14926
14927    const explode$1 = Tools.explode;
14928    const create$8 = () => {
14929      const filters = {};
14930      const addFilter = (name, callback) => {
14931        each$e(explode$1(name), name => {
14932          if (!has$2(filters, name)) {
14933            filters[name] = {
14934              name,
14935              callbacks: []
14936            };
14937          }
14938          filters[name].callbacks.push(callback);
14939        });
14940      };
14941      const getFilters = () => values(filters);
14942      const removeFilter = (name, callback) => {
14943        each$e(explode$1(name), name => {
14944          if (has$2(filters, name)) {
14945            if (isNonNullable(callback)) {
14946              const filter = filters[name];
14947              const newCallbacks = filter$5(filter.callbacks, c => c !== callback);
14948              if (newCallbacks.length > 0) {
14949                filter.callbacks = newCallbacks;
14950              } else {
14951                delete filters[name];
14952              }
14953            } else {
14954              delete filters[name];
14955            }
14956          }
14957        });
14958      };
14959      return {
14960        addFilter,
14961        getFilters,
14962        removeFilter
14963      };
14964    };
14965
14966    const removeAttrs = (node, names) => {
14967      each$e(names, name => {
14968        node.attr(name, null);
14969      });
14970    };
14971    const addFontToSpansFilter = (domParser, styles, fontSizes) => {
14972      domParser.addNodeFilter('font', nodes => {
14973        each$e(nodes, node => {
14974          const props = styles.parse(node.attr('style'));
14975          const color = node.attr('color');
14976          const face = node.attr('face');
14977          const size = node.attr('size');
14978          if (color) {
14979            props.color = color;
14980          }
14981          if (face) {
14982            props['font-family'] = face;
14983          }
14984          if (size) {
14985            toInt(size).each(num => {
14986              props['font-size'] = fontSizes[num - 1];
14987            });
14988          }
14989          node.name = 'span';
14990          node.attr('style', styles.serialize(props));
14991          removeAttrs(node, [
14992            'color',
14993            'face',
14994            'size'
14995          ]);
14996        });
14997      });
14998    };
14999    const addStrikeFilter = (domParser, schema, styles) => {
15000      domParser.addNodeFilter('strike', nodes => {
15001        const convertToSTag = schema.type !== 'html4';
15002        each$e(nodes, node => {
15003          if (convertToSTag) {
15004            node.name = 's';
15005          } else {
15006            const props = styles.parse(node.attr('style'));
15007            props['text-decoration'] = 'line-through';
15008            node.name = 'span';
15009            node.attr('style', styles.serialize(props));
15010          }
15011        });
15012      });
15013    };
15014    const addFilters = (domParser, settings, schema) => {
15015      var _a;
15016      const styles = Styles();
15017      if (settings.convert_fonts_to_spans) {
15018        addFontToSpansFilter(domParser, styles, Tools.explode((_a = settings.font_size_legacy_values) !== null && _a !== void 0 ? _a : ''));
15019      }
15020      addStrikeFilter(domParser, schema, styles);
15021    };
15022    const register$5 = (domParser, settings, schema) => {
15023      if (settings.inline_styles) {
15024        addFilters(domParser, settings, schema);
15025      }
15026    };
15027
15028    const blobUriToBlob = url => fetch(url).then(res => res.ok ? res.blob() : Promise.reject()).catch(() => Promise.reject({
15029      message: `Cannot convert ${ url } to Blob. Resource might not exist or is inaccessible.`,
15030      uriType: 'blob'
15031    }));
15032    const extractBase64Data = data => {
15033      const matches = /([a-z0-9+\/=\s]+)/i.exec(data);
15034      return matches ? matches[1] : '';
15035    };
15036    const 
vendor: 885 bytes, lines 15036-15065
15036decodeData = data => {
15037      try {
15038        return decodeURIComponent(data);
15039      } catch (_a) {
15040        return data;
15041      }
15042    };
15043    const parseDataUri = uri => {
15044      const [type, ...rest] = uri.split(',');
15045      const data = rest.join(',');
15046      const matches = /data:([^/]+\/[^;]+)(;.+)?/.exec(type);
15047      if (matches) {
15048        const base64Encoded = matches[2] === ';base64';
15049        const decodedData = decodeData(data);
15050        const extractedData = base64Encoded ? extractBase64Data(decodedData) : decodedData;
15051        return Optional.some({
15052          type: matches[1],
15053          data: extractedData,
15054          base64Encoded
15055        });
15056      } else {
15057        return Optional.none();
15058      }
15059    };
15060    const buildBlob = (type, data, base64Encoded = true) => {
15061      let str = data;
15062      if (base64Encoded) {
15063        try {
15064          str = atob(data);
15065        } catch (_a
vendor: 9,846 bytes, lines 15065-15317
15065) {
15066          return Optional.none();
15067        }
15068      }
15069      const arr = new Uint8Array(str.length);
15070      for (let i = 0; i < arr.length; i++) {
15071        arr[i] = str.charCodeAt(i);
15072      }
15073      return Optional.some(new Blob([arr], { type }));
15074    };
15075    const dataUriToBlob = uri => {
15076      return new Promise((resolve, reject) => {
15077        parseDataUri(uri).bind(({type, data, base64Encoded}) => buildBlob(type, data, base64Encoded)).fold(() => reject('Invalid data URI'), resolve);
15078      });
15079    };
15080    const uriToBlob = url => {
15081      if (startsWith(url, 'blob:')) {
15082        return blobUriToBlob(url);
15083      } else if (startsWith(url, 'data:')) {
15084        return dataUriToBlob(url);
15085      } else {
15086        return Promise.reject('Unknown URI format');
15087      }
15088    };
15089    const blobToDataUri = blob => {
15090      return new Promise((resolve, reject) => {
15091        const reader = new FileReader();
15092        reader.onloadend = () => {
15093          resolve(reader.result);
15094        };
15095        reader.onerror = () => {
15096          var _a;
15097          reject((_a = reader.error) === null || _a === void 0 ? void 0 : _a.message);
15098        };
15099        reader.readAsDataURL(blob);
15100      });
15101    };
15102
15103    let count$1 = 0;
15104    const uniqueId$1 = prefix => {
15105      return (prefix || 'blobid') + count$1++;
15106    };
15107    const processDataUri = (dataUri, base64Only, generateBlobInfo) => {
15108      return parseDataUri(dataUri).bind(({data, type, base64Encoded}) => {
15109        if (base64Only && !base64Encoded) {
15110          return Optional.none();
15111        } else {
15112          const base64 = base64Encoded ? data : btoa(data);
15113          return generateBlobInfo(base64, type);
15114        }
15115      });
15116    };
15117    const createBlobInfo$1 = (blobCache, blob, base64) => {
15118      const blobInfo = blobCache.create(uniqueId$1(), blob, base64);
15119      blobCache.add(blobInfo);
15120      return blobInfo;
15121    };
15122    const dataUriToBlobInfo = (blobCache, dataUri, base64Only = false) => {
15123      return processDataUri(dataUri, base64Only, (base64, type) => Optional.from(blobCache.getByData(base64, type)).orThunk(() => buildBlob(type, base64).map(blob => createBlobInfo$1(blobCache, blob, base64))));
15124    };
15125    const imageToBlobInfo = (blobCache, imageSrc) => {
15126      const invalidDataUri = () => Promise.reject('Invalid data URI');
15127      if (startsWith(imageSrc, 'blob:')) {
15128        const blobInfo = blobCache.getByUri(imageSrc);
15129        if (isNonNullable(blobInfo)) {
15130          return Promise.resolve(blobInfo);
15131        } else {
15132          return uriToBlob(imageSrc).then(blob => {
15133            return blobToDataUri(blob).then(dataUri => {
15134              return processDataUri(dataUri, false, base64 => {
15135                return Optional.some(createBlobInfo$1(blobCache, blob, base64));
15136              }).getOrThunk(invalidDataUri);
15137            });
15138          });
15139        }
15140      } else if (startsWith(imageSrc, 'data:')) {
15141        return dataUriToBlobInfo(blobCache, imageSrc).fold(invalidDataUri, blobInfo => Promise.resolve(blobInfo));
15142      } else {
15143        return Promise.reject('Unknown image data format');
15144      }
15145    };
15146
15147    const hostCaptureRegex = /^(?:(?:(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)([A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*))(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+)?)?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+)?)?)$/;
15148    const extractHost = url => Optional.from(url.match(hostCaptureRegex)).bind(ms => get$b(ms, 1)).map(h => startsWith(h, 'www.') ? h.substring(4) : h);
15149
15150    const sandboxIframe = (iframeNode, exclusions) => {
15151      if (Optional.from(iframeNode.attr('src')).bind(extractHost).forall(host => !contains$2(exclusions, host))) {
15152        iframeNode.attr('sandbox', '');
15153      }
15154    };
15155    const isMimeType = (mime, type) => startsWith(mime, `${ type }/`);
15156    const getEmbedType = type => {
15157      if (isUndefined(type)) {
15158        return 'iframe';
15159      } else if (isMimeType(type, 'image')) {
15160        return 'img';
15161      } else if (isMimeType(type, 'video')) {
15162        return 'video';
15163      } else if (isMimeType(type, 'audio')) {
15164        return 'audio';
15165      } else {
15166        return 'iframe';
15167      }
15168    };
15169    const createSafeEmbed = ({type, src, width, height} = {}, sandboxIframes, sandboxIframesExclusions) => {
15170      const name = getEmbedType(type);
15171      const embed = new AstNode(name, 1);
15172      embed.attr(name === 'audio' ? { src } : {
15173        src,
15174        width,
15175        height
15176      });
15177      if (name === 'audio' || name === 'video') {
15178        embed.attr('controls', '');
15179      }
15180      if (name === 'iframe' && sandboxIframes) {
15181        sandboxIframe(embed, sandboxIframesExclusions);
15182      }
15183      return embed;
15184    };
15185
15186    const isBogusImage = img => isNonNullable(img.attr('data-mce-bogus'));
15187    const isInternalImageSource = img => img.attr('src') === Env.transparentSrc || isNonNullable(img.attr('data-mce-placeholder'));
15188    const registerBase64ImageFilter = (parser, settings) => {
15189      const {blob_cache: blobCache} = settings;
15190      if (blobCache) {
15191        const processImage = img => {
15192          const inputSrc = img.attr('src');
15193          if (isInternalImageSource(img) || isBogusImage(img) || isNullable(inputSrc)) {
15194            return;
15195          }
15196          dataUriToBlobInfo(blobCache, inputSrc, true).each(blobInfo => {
15197            img.attr('src', blobInfo.blobUri());
15198          });
15199        };
15200        parser.addAttributeFilter('src', nodes => each$e(nodes, processImage));
15201      }
15202    };
15203    const register$4 = (parser, settings) => {
15204      var _a, _b;
15205      const schema = parser.schema;
15206      parser.addAttributeFilter('href', nodes => {
15207        let i = nodes.length;
15208        const appendRel = rel => {
15209          const parts = rel.split(' ').filter(p => p.length > 0);
15210          return parts.concat(['noopener']).sort().join(' ');
15211        };
15212        const addNoOpener = rel => {
15213          const newRel = rel ? Tools.trim(rel) : '';
15214          if (!/\b(noopener)\b/g.test(newRel)) {
15215            return appendRel(newRel);
15216          } else {
15217            return newRel;
15218          }
15219        };
15220        if (!settings.allow_unsafe_link_target) {
15221          while (i--) {
15222            const node = nodes[i];
15223            if (node.name === 'a' && node.attr('target') === '_blank') {
15224              node.attr('rel', addNoOpener(node.attr('rel')));
15225            }
15226          }
15227        }
15228      });
15229      if (!settings.allow_html_in_named_anchor) {
15230        parser.addAttributeFilter('id,name', nodes => {
15231          let i = nodes.length, sibling, prevSibling, parent, node;
15232          while (i--) {
15233            node = nodes[i];
15234            if (node.name === 'a' && node.firstChild && !node.attr('href')) {
15235              parent = node.parent;
15236              sibling = node.lastChild;
15237              while (sibling && parent) {
15238                prevSibling = sibling.prev;
15239                parent.insert(sibling, node);
15240                sibling = prevSibling;
15241              }
15242            }
15243          }
15244        });
15245      }
15246      if (settings.fix_list_elements) {
15247        parser.addNodeFilter('ul,ol', nodes => {
15248          let i = nodes.length, node, parentNode;
15249          while (i--) {
15250            node = nodes[i];
15251            parentNode = node.parent;
15252            if (parentNode && (parentNode.name === 'ul' || parentNode.name === 'ol')) {
15253              if (node.prev && node.prev.name === 'li') {
15254                node.prev.append(node);
15255              } else {
15256                const li = new AstNode('li', 1);
15257                li.attr('style', 'list-style-type: none');
15258                node.wrap(li);
15259              }
15260            }
15261          }
15262        });
15263      }
15264      const validClasses = schema.getValidClasses();
15265      if (settings.validate && validClasses) {
15266        parser.addAttributeFilter('class', nodes => {
15267          var _a;
15268          let i = nodes.length;
15269          while (i--) {
15270            const node = nodes[i];
15271            const clazz = (_a = node.attr('class')) !== null && _a !== void 0 ? _a : '';
15272            const classList = Tools.explode(clazz, ' ');
15273            let classValue = '';
15274            for (let ci = 0; ci < classList.length; ci++) {
15275              const className = classList[ci];
15276              let valid = false;
15277              let validClassesMap = validClasses['*'];
15278              if (validClassesMap && validClassesMap[className]) {
15279                valid = true;
15280              }
15281              validClassesMap = validClasses[node.name];
15282              if (!valid && validClassesMap && validClassesMap[className]) {
15283                valid = true;
15284              }
15285              if (valid) {
15286                if (classValue) {
15287                  classValue += ' ';
15288                }
15289                classValue += className;
15290              }
15291            }
15292            if (!classValue.length) {
15293              classValue = null;
15294            }
15295            node.attr('class', classValue);
15296          }
15297        });
15298      }
15299      registerBase64ImageFilter(parser, settings);
15300      const shouldSandboxIframes = (_a = settings.sandbox_iframes) !== null && _a !== void 0 ? _a : false;
15301      const sandboxIframesExclusions = unique$1((_b = settings.sandbox_iframes_exclusions) !== null && _b !== void 0 ? _b : []);
15302      if (settings.convert_unsafe_embeds) {
15303        parser.addNodeFilter('object,embed', nodes => each$e(nodes, node => {
15304          node.replace(createSafeEmbed({
15305            type: node.attr('type'),
15306            src: node.name === 'object' ? node.attr('data') : node.attr('src'),
15307            width: node.attr('width'),
15308            height: node.attr('height')
15309          }, shouldSandboxIframes, sandboxIframesExclusions));
15310        }));
15311      }
15312      if (shouldSandboxIframes) {
15313        parser.addNodeFilter('iframe', nodes => each$e(nodes, node => sandboxIframe(node, sandboxIframesExclusions)));
15314      }
15315    };
15316
15317    /*! @license DOMPurify 3.
153172.4 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.4/LICENSE */
15318
15319    const {
15320      entries,
15321      setPrototypeOf,
15322      isFrozen,
15323      getPrototypeOf,
15324      getOwnPropertyDescriptor
15325    } = Object;
15326    let {
15327      freeze,
15328      seal,
15329      create: create$7
15330    } = Object; // eslint-disable-line import/no-mutable-exports
15331    let {
15332      apply,
15333      construct
15334    } = typeof Reflect !== 'undefined' && Reflect;
15335    if (!freeze) {
15336      freeze = function freeze(x) {
15337        return x;
15338      };
15339    }
15340    if (!seal) {
15341      seal = function seal(x) {
15342        return x;
15343      };
15344    }
15345    if (!apply) {
15346      apply = function apply(fun, thisValue, args) {
15347        return fun.apply(thisValue, args);
15348      };
15349    }
15350    if (!construct) {
15351      construct = function construct(Func, args) {
15352        return new Func(...args);
15353      };
15354    }
15355    const arrayForEach = unapply(Array.prototype.forEach);
15356    const arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
15357    const arrayPop = unapply(Array.prototype.pop);
15358    const arrayPush = unapply(Array.prototype.push);
15359    const arraySplice = unapply(Array.prototype.splice);
15360    const stringToLowerCase = unapply(String.prototype.toLowerCase);
15361    const stringToString = unapply(String.prototype.toString);
15362    const stringMatch = unapply(String.prototype.match);
15363    const stringReplace = unapply(String.prototype.replace);
15364    const stringIndexOf = unapply(String.prototype.indexOf);
15365    const stringTrim = unapply(String.prototype.trim);
15366    const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
15367    const regExpTest = unapply(RegExp.prototype.test);
15368    const typeErrorCreate = unconstruct(TypeError);
15369    /**
15370     * Creates a new function that calls the given function with a specified thisArg and arguments.
15371     *
15372     * @param func - The function to be wrapped and called.
15373     * @returns A new function that calls the given function with a specified thisArg and arguments.
15374     */
15375    function unapply(func) {
15376      return function (thisArg) {
15377        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
15378          args[_key - 1] = arguments[_key];
15379        }
15380        return apply(func, thisArg, args);
15381      };
15382    }
15383    /**
15384     * Creates a new function that constructs an instance of the given constructor function with the provided arguments.
15385     *
15386     * @param func - The constructor function to be wrapped and called.
15387     * @returns A new function that constructs an instance of the given constructor function with the provided arguments.
15388     */
15389    function unconstruct(func) {
15390      return function () {
15391        for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
15392          args[_key2] = arguments[_key2];
15393        }
15394        return construct(func, args);
15395      };
15396    }
15397    /**
15398     * Add properties to a lookup table
15399     *
15400     * @param set - The set to which elements will be added.
15401     * @param array - The array containing elements to be added to the set.
15402     * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.
15403     * @returns The modified set with added elements.
15404     */
15405    function addToSet(set, array) {
vendor: 6,003 bytes, lines 15406-15504
15406      let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;
15407      if (setPrototypeOf) {
15408        // Make 'in' and truthy checks like Boolean(set.constructor)
15409        // independent of any properties defined on Object.prototype.
15410        // Prevent prototype setters from intercepting set as a this value.
15411        setPrototypeOf(set, null);
15412      }
15413      let l = array.length;
15414      while (l--) {
15415        let element = array[l];
15416        if (typeof element === 'string') {
15417          const lcElement = transformCaseFunc(element);
15418          if (lcElement !== element) {
15419            // Config presets (e.g. tags.js, attrs.js) are immutable.
15420            if (!isFrozen(array)) {
15421              array[l] = lcElement;
15422            }
15423            element = lcElement;
15424          }
15425        }
15426        set[element] = true;
15427      }
15428      return set;
15429    }
15430    /**
15431     * Clean up an array to harden against CSPP
15432     *
15433     * @param array - The array to be cleaned.
15434     * @returns The cleaned version of the array
15435     */
15436    function cleanArray(array) {
15437      for (let index = 0; index < array.length; index++) {
15438        const isPropertyExist = objectHasOwnProperty(array, index);
15439        if (!isPropertyExist) {
15440          array[index] = null;
15441        }
15442      }
15443      return array;
15444    }
15445    /**
15446     * Shallow clone an object
15447     *
15448     * @param object - The object to be cloned.
15449     * @returns A new object that copies the original.
15450     */
15451    function clone(object) {
15452      const newObject = create$7(null);
15453      for (const [property, value] of entries(object)) {
15454        const isPropertyExist = objectHasOwnProperty(object, property);
15455        if (isPropertyExist) {
15456          if (Array.isArray(value)) {
15457            newObject[property] = cleanArray(value);
15458          } else if (value && typeof value === 'object' && value.constructor === Object) {
15459            newObject[property] = clone(value);
15460          } else {
15461            newObject[property] = value;
15462          }
15463        }
15464      }
15465      return newObject;
15466    }
15467    /**
15468     * This method automatically checks if the prop is function or getter and behaves accordingly.
15469     *
15470     * @param object - The object to look up the getter function in its prototype chain.
15471     * @param prop - The property name for which to find the getter function.
15472     * @returns The getter function found in the prototype chain or a fallback function.
15473     */
15474    function lookupGetter(object, prop) {
15475      while (object !== null) {
15476        const desc = getOwnPropertyDescriptor(object, prop);
15477        if (desc) {
15478          if (desc.get) {
15479            return unapply(desc.get);
15480          }
15481          if (typeof desc.value === 'function') {
15482            return unapply(desc.value);
15483          }
15484        }
15485        object = getPrototypeOf(object);
15486      }
15487      function fallbackValue() {
15488        return null;
15489      }
15490      return fallbackValue;
15491    }
15492
15493    const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
15494    const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
15495    const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
15496    // List of SVG elements that are disallowed by default.
15497    // We still need to know them so that we can do namespace
15498    // checks properly in case one wants to add them to
15499    // allow-list.
15500    const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
15501    const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);
15502    // Similarly to SVG, we want to know all MathML elements,
15503    // even those that we disallow by default.
15504    const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'n
15504one']);
15505    const text = freeze(['#text']);
15506
15507    const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
15508    const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
15509    const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
15510    const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
15511
15512    // eslint-disable-next-line unicorn/better-regex
15513    const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
15514    const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
15515    const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
15516    const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
15517    const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
vendor: 4,106 bytes, lines 15518-15620
15518    const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
15519    );
15520    const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
15521    const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
15522    );
15523    const DOCTYPE_NAME = seal(/^html$/i);
15524    const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
15525
15526    var EXPRESSIONS = /*#__PURE__*/Object.freeze({
15527      __proto__: null,
15528      ARIA_ATTR: ARIA_ATTR,
15529      ATTR_WHITESPACE: ATTR_WHITESPACE,
15530      CUSTOM_ELEMENT: CUSTOM_ELEMENT,
15531      DATA_ATTR: DATA_ATTR,
15532      DOCTYPE_NAME: DOCTYPE_NAME,
15533      ERB_EXPR: ERB_EXPR,
15534      IS_ALLOWED_URI: IS_ALLOWED_URI,
15535      IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
15536      MUSTACHE_EXPR: MUSTACHE_EXPR,
15537      TMPLIT_EXPR: TMPLIT_EXPR
15538    });
15539
15540    /* eslint-disable @typescript-eslint/indent */
15541    // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
15542    const NODE_TYPE = {
15543      element: 1,
15544      attribute: 2,
15545      text: 3,
15546      cdataSection: 4,
15547      entityReference: 5,
15548      // Deprecated
15549      entityNode: 6,
15550      // Deprecated
15551      progressingInstruction: 7,
15552      comment: 8,
15553      document: 9,
15554      documentType: 10,
15555      documentFragment: 11,
15556      notation: 12 // Deprecated
15557    };
15558    const getGlobal = function getGlobal() {
15559      return typeof window === 'undefined' ? null : window;
15560    };
15561    /**
15562     * Creates a no-op policy for internal use only.
15563     * Don't export this function outside this module!
15564     * @param trustedTypes The policy factory.
15565     * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).
15566     * @return The policy created (or null, if Trusted Types
15567     * are not supported or creating the policy failed).
15568     */
15569    const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {
15570      if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
15571        return null;
15572      }
15573      // Allow the callers to control the unique policy name
15574      // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
15575      // Policy creation with duplicate names throws in Trusted Types.
15576      let suffix = null;
15577      const ATTR_NAME = 'data-tt-policy-suffix';
15578      if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
15579        suffix = purifyHostElement.getAttribute(ATTR_NAME);
15580      }
15581      const policyName = 'dompurify' + (suffix ? '#' + suffix : '');
15582      try {
15583        return trustedTypes.createPolicy(policyName, {
15584          createHTML(html) {
15585            return html;
15586          },
15587          createScriptURL(scriptUrl) {
15588            return scriptUrl;
15589          }
15590        });
15591      } catch (_) {
15592        // Policy creation failed (most likely another DOMPurify script has
15593        // already run). Skip creating the policy, as this will only cause errors
15594        // if TT are enforced.
15595        console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
15596        return null;
15597      }
15598    };
15599    const _createHooksMap = function _createHooksMap() {
15600      return {
15601        afterSanitizeAttributes: [],
15602        afterSanitizeElements: [],
15603        afterSanitizeShadowDOM: [],
15604        beforeSanitizeAttributes: [],
15605        beforeSanitizeElements: [],
15606        beforeSanitizeShadowDOM: [],
15607        uponSanitizeAttribute: [],
15608        uponSanitizeElement: [],
15609        uponSanitizeShadowNode: []
15610      };
15611    };
15612    function createDOMPurify() {
15613      let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
15614      const DOMPurify = root => createDOMPurify(root);
15615      DOMPurify.version = '3.2.4';
15616      DOMPurify.removed = [];
15617      if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
15618        // Not running in a browser, provide a factory function
15619        // so that you can pass your own Window
15620        DOMPurify.isSupported = false;
vendor: 4,492 bytes, lines 15621-15731
15621        return DOMPurify;
15622      }
15623      let {
15624        document
15625      } = window;
15626      const originalDocument = document;
15627      const currentScript = originalDocument.currentScript;
15628      const {
15629        DocumentFragment,
15630        HTMLTemplateElement,
15631        Node,
15632        Element,
15633        NodeFilter,
15634        NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,
15635        HTMLFormElement,
15636        DOMParser,
15637        trustedTypes
15638      } = window;
15639      const ElementPrototype = Element.prototype;
15640      const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
15641      const remove = lookupGetter(ElementPrototype, 'remove');
15642      const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
15643      const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
15644      const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
15645      // As per issue #47, the web-components registry is inherited by a
15646      // new document created via createHTMLDocument. As per the spec
15647      // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
15648      // a new empty registry is used when creating a template contents owner
15649      // document, so we use that as our parent document to ensure nothing
15650      // is inherited.
15651      if (typeof HTMLTemplateElement === 'function') {
15652        const template = document.createElement('template');
15653        if (template.content && template.content.ownerDocument) {
15654          document = template.content.ownerDocument;
15655        }
15656      }
15657      let trustedTypesPolicy;
15658      let emptyHTML = '';
15659      const {
15660        implementation,
15661        createNodeIterator,
15662        createDocumentFragment,
15663        getElementsByTagName
15664      } = document;
15665      const {
15666        importNode
15667      } = originalDocument;
15668      let hooks = _createHooksMap();
15669      /**
15670       * Expose whether this browser supports running the full DOMPurify.
15671       */
15672      DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
15673      const {
15674        MUSTACHE_EXPR,
15675        ERB_EXPR,
15676        TMPLIT_EXPR,
15677        DATA_ATTR,
15678        ARIA_ATTR,
15679        IS_SCRIPT_OR_DATA,
15680        ATTR_WHITESPACE,
15681        CUSTOM_ELEMENT
15682      } = EXPRESSIONS;
15683      let {
15684        IS_ALLOWED_URI: IS_ALLOWED_URI$1
15685      } = EXPRESSIONS;
15686      /**
15687       * We consider the elements and attributes below to be safe. Ideally
15688       * don't add any new ones but feel free to remove unwanted ones.
15689       */
15690      /* allowed element names */
15691      let ALLOWED_TAGS = null;
15692      const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
15693      /* Allowed attribute names */
15694      let ALLOWED_ATTR = null;
15695      const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
15696      /*
15697       * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.
15698       * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
15699       * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
15700       * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
15701       */
15702      let CUSTOM_ELEMENT_HANDLING = Object.seal(create$7(null, {
15703        tagNameCheck: {
15704          writable: true,
15705          configurable: false,
15706          enumerable: true,
15707          value: null
15708        },
15709        attributeNameCheck: {
15710          writable: true,
15711          configurable: false,
15712          enumerable: true,
15713          value: null
15714        },
15715        allowCustomizedBuiltInElements: {
15716          writable: true,
15717          configurable: false,
15718          enumerable: true,
15719          value: false
15720        }
15721      }));
15722      /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
15723      let FORBID_TAGS = null;
15724      /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
15725      let FORBID_ATTR = null;
15726      /* Decide if ARIA attributes are okay */
15727      let ALLOW_ARIA_ATTR = true;
15728      /* Decide if custom data attributes are okay */
15729      let ALLOW_DATA_ATTR = true;
15730      /* Decide if unknown protocols are okay */
15731      let ALLOW_UNKNOWN_PROTOCOLS = false;
15732      /* Decide if self-closing tags in attributes are allowed.
15733       * Usually removed due to a mXSS issue in jQuery 3.0 */
15734      let ALLOW_SELF_CLOSE_IN_ATTR = true;
15735      /* Output should be safe for common template engines.
15736       * This means, DOMPurify removes data attributes, mustaches and ERB
15737       */
15738      let SAFE_FOR_TEMPLATES = false;
15739      /* Output should be safe even for XML used within HTML and alike.
15740       * This means, DOMPurify removes comments when containing risky content.
15741       */
15742      let SAFE_FOR_XML = true;
15743      /* Decide if document with <html>... should be returned */
15744      let WHOLE_DOCUMENT = false;
15745      /* Track whether config is already set on this instance of DOMPurify. */
15746      let SET_CONFIG = false;
15747      /* Decide if all elements (e.g. style, script) must be children of
15748       * document.body. By default, browsers might move them to document.head */
15749      let FORCE_BODY = false;
15750      /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
15751       * string (or a TrustedHTML object if Trusted Types are supported).
15752       * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
15753       */
15754      let RETURN_DOM = false;
15755      /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
15756       * string  (or a TrustedHTML object if Trusted Types are supported) */
15757      let RETURN_DOM_FRAGMENT = false;
15758      /* Try to return a Trusted Type object instead of a string, return a string in
15759       * case Trusted Types are not supported  */
15760      let RETURN_TRUSTED_TYPE = false;
15761      /* Output should be free from DOM clobbering attacks?
15762       * This sanitizes markups named with colliding, clobberable built-in DOM APIs.
15763       */
15764      let SANITIZE_DOM = true;
15765      /* Achieve full DOM Clobbering protection by isolating the namespace of named
15766       * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.
15767       *
15768       * HTML/DOM spec rules that enable DOM Clobbering:
15769       *   - Named Access on Window (§7.3.3)
15770       *   - DOM Tree Accessors (§3.1.5)
15771       *   - Form Element Parent-Child Relations (§4.10.3)
15772       *   - Iframe srcdoc / Nested WindowProxies (§4.8.5)
15773       *   - HTMLCollection (§4.2.10.2)
15774       *
15775       * Namespace isolation is implemented by prefixing `id` and `name` attributes
15776       * with a constant string, i.e., `user-content-`
15777       */
15778      let SANITIZE_NAMED_PROPS = false;
15779      const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
15780      /* Keep element content when removing element? */
15781      let KEEP_CONTENT = true;
15782      /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
15783       * of importing it into a new Document and returning a sanitized copy */
15784      let IN_PLACE = false;
15785      /* Allow usage of profiles like html, svg and mathMl */
15786      let USE_PROFILES = {};
15787      /* Tags to ignore content of when KEEP_CONTENT is true */
15788      let FORBID_CONTENTS = null;
15789      const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'n
vendor: 3,516 bytes, lines 15789-15849
15789oscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
15790      /* Tags that are safe for data: URIs */
15791      let DATA_URI_TAGS = null;
15792      const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
15793      /* Attributes safe for values like "javascript:" */
15794      let URI_SAFE_ATTRIBUTES = null;
15795      const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
15796      const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
15797      const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
15798      const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
15799      /* Document namespace */
15800      let NAMESPACE = HTML_NAMESPACE;
15801      let IS_EMPTY_INPUT = false;
15802      /* Allowed XHTML+XML namespaces */
15803      let ALLOWED_NAMESPACES = null;
15804      const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
15805      let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
15806      let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);
15807      // Certain elements are allowed in both SVG and HTML
15808      // namespace. We need to specify them explicitly
15809      // so that they don't get erroneously deleted from
15810      // HTML namespace.
15811      const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
15812      /* Parsing of strict XHTML documents */
15813      let PARSER_MEDIA_TYPE = null;
15814      const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
15815      const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
15816      let transformCaseFunc = null;
15817      /* Keep a reference to config to pass to hooks */
15818      let CONFIG = null;
15819      /* Ideally, do not touch anything below this line */
15820      /* ______________________________________________ */
15821      const formElement = document.createElement('form');
15822      const isRegexOrFunction = function isRegexOrFunction(testValue) {
15823        return testValue instanceof RegExp || testValue instanceof Function;
15824      };
15825      /**
15826       * _parseConfig
15827       *
15828       * @param cfg optional config literal
15829       */
15830      // eslint-disable-next-line complexity
15831      const _parseConfig = function _parseConfig() {
15832        let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
15833        if (CONFIG && CONFIG === cfg) {
15834          return;
15835        }
15836        /* Shield configuration object from tampering */
15837        if (!cfg || typeof cfg !== 'object') {
15838          cfg = {};
15839        }
15840        /* Shield configuration object from prototype pollution */
15841        cfg = clone(cfg);
15842        PARSER_MEDIA_TYPE =
15843        // eslint-disable-next-line unicorn/prefer-includes
15844        SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
15845        // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
15846        transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
15847        /* Set configuration parameters */
15848        ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
15849        ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
vendor: 4,219 bytes, lines 15850-15915
15850        ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
15851        URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
15852        DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
15853        FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
15854        FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
15855        FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
15856        USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
15857        ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
15858        ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
15859        ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
15860        ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true
15861        SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
15862        SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true
15863        WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
15864        RETURN_DOM = cfg.RETURN_DOM || false; // Default false
15865        RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
15866        RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
15867        FORCE_BODY = cfg.FORCE_BODY || false; // Default false
15868        SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
15869        SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
15870        KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
15871        IN_PLACE = cfg.IN_PLACE || false; // Default false
15872        IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
15873        NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
15874        MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;
15875        HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;
15876        CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
15877        if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
15878          CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
15879        }
15880        if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
15881          CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
15882        }
15883        if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
15884          CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
15885        }
15886        if (SAFE_FOR_TEMPLATES) {
15887          ALLOW_DATA_ATTR = false;
15888        }
15889        if (RETURN_DOM_FRAGMENT) {
15890          RETURN_DOM = true;
15891        }
15892        /* Parse profile info */
15893        if (USE_PROFILES) {
15894          ALLOWED_TAGS = addToSet({}, text);
15895          ALLOWED_ATTR = [];
15896          if (USE_PROFILES.html === true) {
15897            addToSet(ALLOWED_TAGS, html$1);
15898            addToSet(ALLOWED_ATTR, html);
15899          }
15900          if (USE_PROFILES.svg === true) {
15901            addToSet(ALLOWED_TAGS, svg$1);
15902            addToSet(ALLOWED_ATTR, svg);
15903            addToSet(ALLOWED_ATTR, xml);
15904          }
15905          if (USE_PROFILES.svgFilters === true) {
15906            addToSet(ALLOWED_TAGS, svgFilters);
15907            addToSet(ALLOWED_ATTR, svg);
15908            addToSet(ALLOWED_ATTR, xml);
15909          }
15910          if (USE_PROFILES.mathMl === true) {
15911            addToSet(ALLOWED_TAGS, mathMl$1);
15912            addToSet(ALLOWED_ATTR, mathMl);
15913            addToSet(ALLOWED_ATTR, xml);
15914          }
15915        }
vendor: 5,920 bytes, lines 15916-16043
15916        /* Merge configuration parameters */
15917        if (cfg.ADD_TAGS) {
15918          if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
15919            ALLOWED_TAGS = clone(ALLOWED_TAGS);
15920          }
15921          addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
15922        }
15923        if (cfg.ADD_ATTR) {
15924          if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
15925            ALLOWED_ATTR = clone(ALLOWED_ATTR);
15926          }
15927          addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
15928        }
15929        if (cfg.ADD_URI_SAFE_ATTR) {
15930          addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
15931        }
15932        if (cfg.FORBID_CONTENTS) {
15933          if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
15934            FORBID_CONTENTS = clone(FORBID_CONTENTS);
15935          }
15936          addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
15937        }
15938        /* Add #text in case KEEP_CONTENT is set to true */
15939        if (KEEP_CONTENT) {
15940          ALLOWED_TAGS['#text'] = true;
15941        }
15942        /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
15943        if (WHOLE_DOCUMENT) {
15944          addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
15945        }
15946        /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
15947        if (ALLOWED_TAGS.table) {
15948          addToSet(ALLOWED_TAGS, ['tbody']);
15949          delete FORBID_TAGS.tbody;
15950        }
15951        if (cfg.TRUSTED_TYPES_POLICY) {
15952          if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {
15953            throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
15954          }
15955          if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {
15956            throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
15957          }
15958          // Overwrite existing TrustedTypes policy.
15959          trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
15960          // Sign local variables required by `sanitize`.
15961          emptyHTML = trustedTypesPolicy.createHTML('');
15962        } else {
15963          // Uninitialized policy, attempt to initialize the internal dompurify policy.
15964          if (trustedTypesPolicy === undefined) {
15965            trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
15966          }
15967          // If creating the internal policy succeeded sign internal variables.
15968          if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {
15969            emptyHTML = trustedTypesPolicy.createHTML('');
15970          }
15971        }
15972        // Prevent further manipulation of configuration.
15973        // Not available in IE8, Safari 5, etc.
15974        if (freeze) {
15975          freeze(cfg);
15976        }
15977        CONFIG = cfg;
15978      };
15979      /* Keep track of all possible SVG and MathML tags
15980       * so that we can perform the namespace checks
15981       * correctly. */
15982      const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
15983      const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
15984      /**
15985       * @param element a DOM element whose namespace is being checked
15986       * @returns Return false if the element has a
15987       *  namespace that a spec-compliant parser would never
15988       *  return. Return true otherwise.
15989       */
15990      const _checkValidNamespace = function _checkValidNamespace(element) {
15991        let parent = getParentNode(element);
15992        // In JSDOM, if we're inside shadow DOM, then parentNode
15993        // can be null. We just simulate parent in this case.
15994        if (!parent || !parent.tagName) {
15995          parent = {
15996            namespaceURI: NAMESPACE,
15997            tagName: 'template'
15998          };
15999        }
16000        const tagName = stringToLowerCase(element.tagName);
16001        const parentTagName = stringToLowerCase(parent.tagName);
16002        if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
16003          return false;
16004        }
16005        if (element.namespaceURI === SVG_NAMESPACE) {
16006          // The only way to switch from HTML namespace to SVG
16007          // is via <svg>. If it happens via any other tag, then
16008          // it should be killed.
16009          if (parent.namespaceURI === HTML_NAMESPACE) {
16010            return tagName === 'svg';
16011          }
16012          // The only way to switch from MathML to SVG is via`
16013          // svg if parent is either <annotation-xml> or MathML
16014          // text integration points.
16015          if (parent.namespaceURI === MATHML_NAMESPACE) {
16016            return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
16017          }
16018          // We only allow elements that are defined in SVG
16019          // spec. All others are disallowed in SVG namespace.
16020          return Boolean(ALL_SVG_TAGS[tagName]);
16021        }
16022        if (element.namespaceURI === MATHML_NAMESPACE) {
16023          // The only way to switch from HTML namespace to MathML
16024          // is via <math>. If it happens via any other tag, then
16025          // it should be killed.
16026          if (parent.namespaceURI === HTML_NAMESPACE) {
16027            return tagName === 'math';
16028          }
16029          // The only way to switch from SVG to MathML is via
16030          // <math> and HTML integration points
16031          if (parent.namespaceURI === SVG_NAMESPACE) {
16032            return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
16033          }
16034          // We only allow elements that are defined in MathML
16035          // spec. All others are disallowed in MathML namespace.
16036          return Boolean(ALL_MATHML_TAGS[tagName]);
16037        }
16038        if (element.namespaceURI === HTML_NAMESPACE) {
16039          // The only way to switch from SVG to HTML is via
16040          // HTML integration points, and from MathML to HTML
16041          // is via MathML text integration points
16042          if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
16043            return false;
16044          }
16045          if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
16046            return false;
16047          }
16048          // We disallow tags that are specific for MathML
16049          // or SVG and should never appear in HTML namespace
16050          return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
16051        }
16052        // For XHTML and XML documents that support custom namespaces
16053        if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
16054          return true;
16055        }
16056        // The code should never reach this place (this means
16057        // that the element somehow got namespace that is not
16058        // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).
16059        // Return false just in case.
16060        return false;
16061      };
16062      /**
16063       * _forceRemove
16064       *
16065       * @param node a DOM node
16066       */
16067      const _forceRemove = function _forceRemove(node) {
16068        arrayPush(DOMPurify.removed, {
16069          element: node
16070        });
16071        try {
vendor: 12,163 bytes, lines 16072-16316
16072          // eslint-disable-next-line unicorn/prefer-dom-node-remove
16073          getParentNode(node).removeChild(node);
16074        } catch (_) {
16075          remove(node);
16076        }
16077      };
16078      /**
16079       * _removeAttribute
16080       *
16081       * @param name an Attribute name
16082       * @param element a DOM node
16083       */
16084      const _removeAttribute = function _removeAttribute(name, element) {
16085        try {
16086          arrayPush(DOMPurify.removed, {
16087            attribute: element.getAttributeNode(name),
16088            from: element
16089          });
16090        } catch (_) {
16091          arrayPush(DOMPurify.removed, {
16092            attribute: null,
16093            from: element
16094          });
16095        }
16096        element.removeAttribute(name);
16097        // We void attribute values for unremovable "is" attributes
16098        if (name === 'is') {
16099          if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
16100            try {
16101              _forceRemove(element);
16102            } catch (_) {}
16103          } else {
16104            try {
16105              element.setAttribute(name, '');
16106            } catch (_) {}
16107          }
16108        }
16109      };
16110      /**
16111       * _initDocument
16112       *
16113       * @param dirty - a string of dirty markup
16114       * @return a DOM, filled with the dirty markup
16115       */
16116      const _initDocument = function _initDocument(dirty) {
16117        /* Create a HTML document */
16118        let doc = null;
16119        let leadingWhitespace = null;
16120        if (FORCE_BODY) {
16121          dirty = '<remove></remove>' + dirty;
16122        } else {
16123          /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
16124          const matches = stringMatch(dirty, /^[\r\n\t ]+/);
16125          leadingWhitespace = matches && matches[0];
16126        }
16127        if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {
16128          // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
16129          dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
16130        }
16131        const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
16132        /*
16133         * Use the DOMParser API by default, fallback later if needs be
16134         * DOMParser not work for svg when has multiple root element.
16135         */
16136        if (NAMESPACE === HTML_NAMESPACE) {
16137          try {
16138            doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
16139          } catch (_) {}
16140        }
16141        /* Use createHTMLDocument in case DOMParser is not available */
16142        if (!doc || !doc.documentElement) {
16143          doc = implementation.createDocument(NAMESPACE, 'template', null);
16144          try {
16145            doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
16146          } catch (_) {
16147            // Syntax error if dirtyPayload is invalid xml
16148          }
16149        }
16150        const body = doc.body || doc.documentElement;
16151        if (dirty && leadingWhitespace) {
16152          body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
16153        }
16154        /* Work on whole document or just its body */
16155        if (NAMESPACE === HTML_NAMESPACE) {
16156          return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
16157        }
16158        return WHOLE_DOCUMENT ? doc.documentElement : body;
16159      };
16160      /**
16161       * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.
16162       *
16163       * @param root The root element or node to start traversing on.
16164       * @return The created NodeIterator
16165       */
16166      const _createNodeIterator = function _createNodeIterator(root) {
16167        return createNodeIterator.call(root.ownerDocument || root, root,
16168        // eslint-disable-next-line no-bitwise
16169        NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);
16170      };
16171      /**
16172       * _isClobbered
16173       *
16174       * @param element element to check for clobbering attacks
16175       * @return true if clobbered, false if safe
16176       */
16177      const _isClobbered = function _isClobbered(element) {
16178        return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');
16179      };
16180      /**
16181       * Checks whether the given object is a DOM node.
16182       *
16183       * @param value object to check whether it's a DOM node
16184       * @return true is object is a DOM node
16185       */
16186      const _isNode = function _isNode(value) {
16187        return typeof Node === 'function' && value instanceof Node;
16188      };
16189      function _executeHooks(hooks, currentNode, data) {
16190        arrayForEach(hooks, hook => {
16191          hook.call(DOMPurify, currentNode, data, CONFIG);
16192        });
16193      }
16194      /**
16195       * _sanitizeElements
16196       *
16197       * @protect nodeName
16198       * @protect textContent
16199       * @protect removeChild
16200       * @param currentNode to check for permission to exist
16201       * @return true if node was killed, false if left alive
16202       */
16203      const _sanitizeElements = function _sanitizeElements(currentNode) {
16204        let content = null;
16205        /* Execute a hook if present */
16206        _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
16207        /* Check if element is clobbered or can clobber */
16208        if (_isClobbered(currentNode)) {
16209          _forceRemove(currentNode);
16210          return true;
16211        }
16212        /* Now let's check the element's type and name */
16213        const tagName = transformCaseFunc(currentNode.nodeName);
16214        /* Execute a hook if present */
16215        _executeHooks(hooks.uponSanitizeElement, currentNode, {
16216          tagName,
16217          allowedTags: ALLOWED_TAGS
16218        });
16219        /* Detect mXSS attempts abusing namespace confusion */
16220        if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
16221          _forceRemove(currentNode);
16222          return true;
16223        }
16224        /* Remove any occurrence of processing instructions */
16225        if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
16226          _forceRemove(currentNode);
16227          return true;
16228        }
16229        /* Remove any kind of possibly harmful comments */
16230        if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
16231          _forceRemove(currentNode);
16232          return true;
16233        }
16234        /* Remove element if anything forbids its presence */
16235        if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
16236          /* Check if we have a custom element to handle */
16237          if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
16238            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
16239              return false;
16240            }
16241            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
16242              return false;
16243            }
16244          }
16245          /* Keep content except for bad-listed elements */
16246          if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
16247            const parentNode = getParentNode(currentNode) || currentNode.parentNode;
16248            const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
16249            if (childNodes && parentNode) {
16250              const childCount = childNodes.length;
16251              for (let i = childCount - 1; i >= 0; --i) {
16252                const childClone = cloneNode(childNodes[i], true);
16253                childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
16254                parentNode.insertBefore(childClone, getNextSibling(currentNode));
16255              }
16256            }
16257          }
16258          _forceRemove(currentNode);
16259          return true;
16260        }
16261        /* Check whether element has a valid namespace */
16262        if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
16263          _forceRemove(currentNode);
16264          return true;
16265        }
16266        /* Make sure that older browsers don't get fallback-tag mXSS */
16267        if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
16268          _forceRemove(currentNode);
16269          return true;
16270        }
16271        /* Sanitize element content to be template-safe */
16272        if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
16273          /* Get the element's text content */
16274          content = currentNode.textContent;
16275          arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
16276            content = stringReplace(content, expr, ' ');
16277          });
16278          if (currentNode.textContent !== content) {
16279            arrayPush(DOMPurify.removed, {
16280              element: currentNode.cloneNode()
16281            });
16282            currentNode.textContent = content;
16283          }
16284        }
16285        /* Execute a hook if present */
16286        _executeHooks(hooks.afterSanitizeElements, currentNode, null);
16287        return false;
16288      };
16289      /**
16290       * _isValidAttribute
16291       *
16292       * @param lcTag Lowercase tag name of containing element.
16293       * @param lcName Lowercase attribute name.
16294       * @param value Attribute value.
16295       * @return Returns true if `value` is valid, otherwise false.
16296       */
16297      // eslint-disable-next-line complexity
16298      const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
16299        /* Make sure attribute cannot clobber */
16300        if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
16301          return false;
16302        }
16303        /* Allow valid data-* attributes: At least one character after "-"
16304            (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
16305            XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
16306            We don't need to check the value; it's always URI safe. */
16307        if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
16308          if (
16309          // First condition does a very basic check if a) it's basically a valid custom element tagname AND
16310          // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
16311          // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
16312          _isBasicCustomElement(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)) ||
16313          // Alternative, second condition checks if it's an `is`-attribute, AND
16314          // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
16315          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))) ; else {
16316            return false;
vendor: 11,439 bytes, lines 16317-16585
16317          }
16318          /* Check value is safe. First, is attr inert? If so, is safe */
16319        } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {
16320          return false;
16321        } else ;
16322        return true;
16323      };
16324      /**
16325       * _isBasicCustomElement
16326       * checks if at least one dash is included in tagName, and it's not the first char
16327       * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
16328       *
16329       * @param tagName name of the tag of the node to sanitize
16330       * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
16331       */
16332      const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
16333        return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);
16334      };
16335      /**
16336       * _sanitizeAttributes
16337       *
16338       * @protect attributes
16339       * @protect nodeName
16340       * @protect removeAttribute
16341       * @protect setAttribute
16342       *
16343       * @param currentNode to sanitize
16344       */
16345      const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
16346        /* Execute a hook if present */
16347        _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
16348        const {
16349          attributes
16350        } = currentNode;
16351        /* Check if we have attributes; if not we might have a text node */
16352        if (!attributes || _isClobbered(currentNode)) {
16353          return;
16354        }
16355        const hookEvent = {
16356          attrName: '',
16357          attrValue: '',
16358          keepAttr: true,
16359          allowedAttributes: ALLOWED_ATTR,
16360          forceKeepAttr: undefined
16361        };
16362        let l = attributes.length;
16363        /* Go backwards over all attributes; safely remove bad ones */
16364        while (l--) {
16365          const attr = attributes[l];
16366          const {
16367            name,
16368            namespaceURI,
16369            value: attrValue
16370          } = attr;
16371          const lcName = transformCaseFunc(name);
16372          let value = name === 'value' ? attrValue : stringTrim(attrValue);
16373          const initValue = value;
16374          /* Execute a hook if present */
16375          hookEvent.attrName = lcName;
16376          hookEvent.attrValue = value;
16377          hookEvent.keepAttr = true;
16378          hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
16379          _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
16380          value = hookEvent.attrValue;
16381          /* Full DOM Clobbering protection via namespace isolation,
16382           * Prefix id and name attributes with `user-content-`
16383           */
16384          if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
16385            // Remove the attribute with this value
16386            _removeAttribute(name, currentNode);
16387            // Prefix the value and later re-create the attribute with the sanitized value
16388            value = SANITIZE_NAMED_PROPS_PREFIX + value;
16389          }
16390          /* Work around a security issue with comments inside attributes */
16391          if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
16392            _removeAttribute(name, currentNode);
16393            continue;
16394          }
16395          /* Did the hooks approve of the attribute? */
16396          if (hookEvent.forceKeepAttr) {
16397            continue;
16398          }
16399          /* Remove attribute */
16400          /* Did the hooks approve of the attribute? */
16401          if (!hookEvent.keepAttr) {
16402            _removeAttribute(name, currentNode);
16403            continue;
16404          }
16405          /* Work around a security issue in jQuery 3.0 */
16406          if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
16407            _removeAttribute(name, currentNode);
16408            continue;
16409          }
16410          /* Sanitize attribute content to be template-safe */
16411          if (SAFE_FOR_TEMPLATES) {
16412            arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
16413              value = stringReplace(value, expr, ' ');
16414            });
16415          }
16416          /* Is `value` valid for this attribute? */
16417          const lcTag = transformCaseFunc(currentNode.nodeName);
16418          if (!_isValidAttribute(lcTag, lcName, value)) {
16419            _removeAttribute(name, currentNode);
16420            continue;
16421          }
16422          /* Handle attributes that require Trusted Types */
16423          if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {
16424            if (namespaceURI) ; else {
16425              switch (trustedTypes.getAttributeType(lcTag, lcName)) {
16426                case 'TrustedHTML':
16427                  {
16428                    value = trustedTypesPolicy.createHTML(value);
16429                    break;
16430                  }
16431                case 'TrustedScriptURL':
16432                  {
16433                    value = trustedTypesPolicy.createScriptURL(value);
16434                    break;
16435                  }
16436              }
16437            }
16438          }
16439          /* Handle invalid data-* attribute set by try-catching it */
16440          if (value !== initValue) {
16441            try {
16442              if (namespaceURI) {
16443                currentNode.setAttributeNS(namespaceURI, name, value);
16444              } else {
16445                /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
16446                currentNode.setAttribute(name, value);
16447              }
16448              if (_isClobbered(currentNode)) {
16449                _forceRemove(currentNode);
16450              } else {
16451                arrayPop(DOMPurify.removed);
16452              }
16453            } catch (_) {}
16454          }
16455        }
16456        /* Execute a hook if present */
16457        _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
16458      };
16459      /**
16460       * _sanitizeShadowDOM
16461       *
16462       * @param fragment to iterate over recursively
16463       */
16464      const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
16465        let shadowNode = null;
16466        const shadowIterator = _createNodeIterator(fragment);
16467        /* Execute a hook if present */
16468        _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
16469        while (shadowNode = shadowIterator.nextNode()) {
16470          /* Execute a hook if present */
16471          _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
16472          /* Sanitize tags and elements */
16473          _sanitizeElements(shadowNode);
16474          /* Check attributes next */
16475          _sanitizeAttributes(shadowNode);
16476          /* Deep shadow DOM detected */
16477          if (shadowNode.content instanceof DocumentFragment) {
16478            _sanitizeShadowDOM(shadowNode.content);
16479          }
16480        }
16481        /* Execute a hook if present */
16482        _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
16483      };
16484      // eslint-disable-next-line complexity
16485      DOMPurify.sanitize = function (dirty) {
16486        let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
16487        let body = null;
16488        let importedNode = null;
16489        let currentNode = null;
16490        let returnNode = null;
16491        /* Make sure we have a string to sanitize.
16492          DO NOT return early, as this will return the wrong type if
16493          the user has requested a DOM object rather than a string */
16494        IS_EMPTY_INPUT = !dirty;
16495        if (IS_EMPTY_INPUT) {
16496          dirty = '<!-->';
16497        }
16498        /* Stringify, in case dirty is an object */
16499        if (typeof dirty !== 'string' && !_isNode(dirty)) {
16500          if (typeof dirty.toString === 'function') {
16501            dirty = dirty.toString();
16502            if (typeof dirty !== 'string') {
16503              throw typeErrorCreate('dirty is not a string, aborting');
16504            }
16505          } else {
16506            throw typeErrorCreate('toString is not a function');
16507          }
16508        }
16509        /* Return dirty HTML if DOMPurify cannot run */
16510        if (!DOMPurify.isSupported) {
16511          return dirty;
16512        }
16513        /* Assign config vars */
16514        if (!SET_CONFIG) {
16515          _parseConfig(cfg);
16516        }
16517        /* Clean up removed elements */
16518        DOMPurify.removed = [];
16519        /* Check if dirty is correctly typed for IN_PLACE */
16520        if (typeof dirty === 'string') {
16521          IN_PLACE = false;
16522        }
16523        if (IN_PLACE) {
16524          /* Do some early pre-sanitization to avoid unsafe root nodes */
16525          if (dirty.nodeName) {
16526            const tagName = transformCaseFunc(dirty.nodeName);
16527            if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
16528              throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
16529            }
16530          }
16531        } else if (dirty instanceof Node) {
16532          /* If dirty is a DOM element, append to an empty document to avoid
16533             elements being stripped by the parser */
16534          body = _initDocument('<!---->');
16535          importedNode = body.ownerDocument.importNode(dirty, true);
16536          if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {
16537            /* Node is already a body, use as is */
16538            body = importedNode;
16539          } else if (importedNode.nodeName === 'HTML') {
16540            body = importedNode;
16541          } else {
16542            // eslint-disable-next-line unicorn/prefer-dom-node-append
16543            body.appendChild(importedNode);
16544          }
16545        } else {
16546          /* Exit directly if we have nothing to do */
16547          if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
16548          // eslint-disable-next-line unicorn/prefer-includes
16549          dirty.indexOf('<') === -1) {
16550            return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
16551          }
16552          /* Initialize the document to work on */
16553          body = _initDocument(dirty);
16554          /* Check we have a DOM node from the data */
16555          if (!body) {
16556            return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
16557          }
16558        }
16559        /* Remove first element node (ours) if FORCE_BODY is set */
16560        if (body && FORCE_BODY) {
16561          _forceRemove(body.firstChild);
16562        }
16563        /* Get node iterator */
16564        const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);
16565        /* Now start iterating over the created document */
16566        while (currentNode = nodeIterator.nextNode()) {
16567          /* Sanitize tags and elements */
16568          _sanitizeElements(currentNode);
16569          /* Check attributes next */
16570          _sanitizeAttributes(currentNode);
16571          /* Shadow DOM detected, sanitize it */
16572          if (currentNode.content instanceof DocumentFragment) {
16573            _sanitizeShadowDOM(currentNode.content);
16574          }
16575        }
16576        /* If we sanitized `dirty` in-place, return it. */
16577        if (IN_PLACE) {
16578          return dirty;
16579        }
16580        /* Return sanitized string or DOM */
16581        if (RETURN_DOM) {
16582          if (RETURN_DOM_FRAGMENT) {
16583            returnNode = createDocumentFragment.call(body.ownerDocument);
16584            while (body.firstChild) {
16585              // eslint-disable-next-line unicorn/prefer-dom-node
16585-append
16586              returnNode.appendChild(body.firstChild);
16587            }
16588          } else {
16589            returnNode = body;
16590          }
16591          if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {
16592            /*
16593              AdoptNode() is not used because internal state is not reset
16594              (e.g. the past names map of a HTMLFormElement), this is safe
16595              in theory but we would rather not risk another attack vector.
16596              The state that is cloned by importNode() is explicitly defined
16597              by the specs.
16598            */
16599            returnNode = importNode.call(originalDocument, returnNode, true);
16600          }
16601          return returnNode;
16602        }
16603        let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
16604        /* Serialize doctype if allowed */
16605        if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
16606          serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
16607        }
16608        /* Sanitize final string template-safe */
16609        if (SAFE_FOR_TEMPLATES) {
16610          arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
16611            serializedHTML = stringReplace(serializedHTML, expr, ' ');
16612          });
16613        }
16614        return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
16615      };
16616      DOMPurify.setConfig = function () {
16617        let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16618        _parseConfig(cfg);
16619        SET_CONFIG = true;
16620      };
16621      DOMPurify.clearConfig = function () {
16622        CONFIG = null;
16623        SET_CONFIG = false;
16624      };
16625      DOMPurify.isValidAttribute = function (tag, attr, value) {
16626        /* Initialize shared config vars if necessary. */
16627        if (!CONFIG) {
16628          _parseConfig({});
16629        }
16630        const lcTag = transformCaseFunc(tag);
16631        const lcName = transformCaseFunc(attr);
16632        return _isValidAttribute(lcTag, lcName, value);
16633      };
16634      DOMPurify.addHook = function (entryPoint, hookFunction) {
16635        if (typeof hookFunction !== 'function') {
16636          return;
16637        }
16638        arrayPush(hooks[entryPoint], hookFunction);
16639      };
16640      DOMPurify.removeHook = function (entryPoint, hookFunction) {
16641        if (hookFunction !== undefined) {
16642          const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);
16643          return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0];
16644        }
16645        return arrayPop(hooks[entryPoint]);
16646      };
16647      DOMPurify.removeHooks = function (entryPoint) {
16648        hooks[entryPoint] = [];
16649      };
16650      DOMPurify.removeAllHooks = function () {
16651        hooks = _createHooksMap();
16652      };
16653      return DOMPurify;
16654    }
16655    var purify = createDOMPurify();
16656
16657    const each$4 = Tools.each, trim = Tools.trim;
16658    const queryParts = [
16659      'source',
16660      'protocol',
16661      'authority',
16662      'userInfo',
16663      'user',
16664      'password',
16665      'host',
16666      'port',
16667      'relative',
16668      'path',
16669      'directory',
16670      'file',
16671      'query',
16672      'anchor'
16673    ];
16674    const DEFAULT_PORTS = {
16675      ftp: 21,
16676      http: 80,
16677      https: 443,
16678      mailto: 25
16679    };
16680    const safeSvgDataUrlElements = [
16681      'img',
16682      'video'
16683    ];
16684    const blockSvgDataUris = (allowSvgDataUrls, tagName) => {
16685      if (isNonNullable(allowSvgDataUrls)) {
16686        return !allowSvgDataUrls;
16687      } else {
16688        return isNonNullable(tagName) ? !contains$2(safeSvgDataUrlElements, tagName) : true;
16689      }
16690    };
16691    const decodeUri = encodedUri => {
16692      try {
16693        return decodeURIComponent(encodedUri);
16694      } catch (_a) {
16695        return unescape(encodedUri);
16696      }
16697    };
16698    const isInvalidUri = (settings, uri, tagName) => {
16699      const decodedUri = decodeUri(uri).replace(/\s/g, '');
16700      if (settings.allow_script_urls) {
16701        return false;
16702      } else if (/((java|vb)script|mhtml):/i.test(decodedUri)) {
16703        return true;
16704      } else if (settings.allow_html_data_urls) {
16705        return false;
vendor: 5,413 bytes, lines 16706-16850
16706      } else if (/^data:image\//i.test(decodedUri)) {
16707        return blockSvgDataUris(settings.allow_svg_data_urls, tagName) && /^data:image\/svg\+xml/i.test(decodedUri);
16708      } else {
16709        return /^data:/i.test(decodedUri);
16710      }
16711    };
16712    class URI {
16713      static parseDataUri(uri) {
16714        let type;
16715        const uriComponents = decodeURIComponent(uri).split(',');
16716        const matches = /data:([^;]+)/.exec(uriComponents[0]);
16717        if (matches) {
16718          type = matches[1];
16719        }
16720        return {
16721          type,
16722          data: uriComponents[1]
16723        };
16724      }
16725      static isDomSafe(uri, context, options = {}) {
16726        if (options.allow_script_urls) {
16727          return true;
16728        } else {
16729          const decodedUri = Entities.decode(uri).replace(/[\s\u0000-\u001F]+/g, '');
16730          return !isInvalidUri(options, decodedUri, context);
16731        }
16732      }
16733      static getDocumentBaseUrl(loc) {
16734        var _a;
16735        let baseUrl;
16736        if (loc.protocol.indexOf('http') !== 0 && loc.protocol !== 'file:') {
16737          baseUrl = (_a = loc.href) !== null && _a !== void 0 ? _a : '';
16738        } else {
16739          baseUrl = loc.protocol + '//' + loc.host + loc.pathname;
16740        }
16741        if (/^[^:]+:\/\/\/?[^\/]+\//.test(baseUrl)) {
16742          baseUrl = baseUrl.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
16743          if (!/[\/\\]$/.test(baseUrl)) {
16744            baseUrl += '/';
16745          }
16746        }
16747        return baseUrl;
16748      }
16749      constructor(url, settings = {}) {
16750        this.path = '';
16751        this.directory = '';
16752        url = trim(url);
16753        this.settings = settings;
16754        const baseUri = settings.base_uri;
16755        const self = this;
16756        if (/^([\w\-]+):([^\/]{2})/i.test(url) || /^\s*#/.test(url)) {
16757          self.source = url;
16758          return;
16759        }
16760        const isProtocolRelative = url.indexOf('//') === 0;
16761        if (url.indexOf('/') === 0 && !isProtocolRelative) {
16762          url = (baseUri ? baseUri.protocol || 'http' : 'http') + '://mce_host' + url;
16763        }
16764        if (!/^[\w\-]*:?\/\//.test(url)) {
16765          const baseUrl = baseUri ? baseUri.path : new URI(document.location.href).directory;
16766          if ((baseUri === null || baseUri === void 0 ? void 0 : baseUri.protocol) === '') {
16767            url = '//mce_host' + self.toAbsPath(baseUrl, url);
16768          } else {
16769            const match = /([^#?]*)([#?]?.*)/.exec(url);
16770            if (match) {
16771              url = (baseUri && baseUri.protocol || 'http') + '://mce_host' + self.toAbsPath(baseUrl, match[1]) + match[2];
16772            }
16773          }
16774        }
16775        url = url.replace(/@@/g, '(mce_at)');
16776        const urlMatch = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?(\[[a-zA-Z0-9:.%]+\]|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url);
16777        if (urlMatch) {
16778          each$4(queryParts, (v, i) => {
16779            let part = urlMatch[i];
16780            if (part) {
16781              part = part.replace(/\(mce_at\)/g, '@@');
16782            }
16783            self[v] = part;
16784          });
16785        }
16786        if (baseUri) {
16787          if (!self.protocol) {
16788            self.protocol = baseUri.protocol;
16789          }
16790          if (!self.userInfo) {
16791            self.userInfo = baseUri.userInfo;
16792          }
16793          if (!self.port && self.host === 'mce_host') {
16794            self.port = baseUri.port;
16795          }
16796          if (!self.host || self.host === 'mce_host') {
16797            self.host = baseUri.host;
16798          }
16799          self.source = '';
16800        }
16801        if (isProtocolRelative) {
16802          self.protocol = '';
16803        }
16804      }
16805      setPath(path) {
16806        const pathMatch = /^(.*?)\/?(\w+)?$/.exec(path);
16807        if (pathMatch) {
16808          this.path = pathMatch[0];
16809          this.directory = pathMatch[1];
16810          this.file = pathMatch[2];
16811        }
16812        this.source = '';
16813        this.getURI();
16814      }
16815      toRelative(uri) {
16816        if (uri === './') {
16817          return uri;
16818        }
16819        const relativeUri = new URI(uri, { base_uri: this });
16820        if (relativeUri.host !== 'mce_host' && this.host !== relativeUri.host && relativeUri.host || this.port !== relativeUri.port || this.protocol !== relativeUri.protocol && relativeUri.protocol !== '') {
16821          return relativeUri.getURI();
16822        }
16823        const tu = this.getURI(), uu = relativeUri.getURI();
16824        if (tu === uu || tu.charAt(tu.length - 1) === '/' && tu.substr(0, tu.length - 1) === uu) {
16825          return tu;
16826        }
16827        let output = this.toRelPath(this.path, relativeUri.path);
16828        if (relativeUri.query) {
16829          output += '?' + relativeUri.query;
16830        }
16831        if (relativeUri.anchor) {
16832          output += '#' + relativeUri.anchor;
16833        }
16834        return output;
16835      }
16836      toAbsolute(uri, noHost) {
16837        const absoluteUri = new URI(uri, { base_uri: this });
16838        return absoluteUri.getURI(noHost && this.isSameOrigin(absoluteUri));
16839      }
16840      isSameOrigin(uri) {
16841        if (this.host == uri.host && this.protocol == uri.protocol) {
16842          if (this.port == uri.port) {
16843            return true;
16844          }
16845          const defaultPort = this.protocol ? DEFAULT_PORTS[this.protocol] : null;
16846          if (defaultPort && (this.port || defaultPort) == (uri.port || defaultPort)) {
16847            return true;
16848          }
16849        }
16850        return false;
vendor: 5,705 bytes, lines 16851-17023
16851      }
16852      toRelPath(base, path) {
16853        let breakPoint = 0, out = '', i, l;
16854        const normalizedBase = base.substring(0, base.lastIndexOf('/')).split('/');
16855        const items = path.split('/');
16856        if (normalizedBase.length >= items.length) {
16857          for (i = 0, l = normalizedBase.length; i < l; i++) {
16858            if (i >= items.length || normalizedBase[i] !== items[i]) {
16859              breakPoint = i + 1;
16860              break;
16861            }
16862          }
16863        }
16864        if (normalizedBase.length < items.length) {
16865          for (i = 0, l = items.length; i < l; i++) {
16866            if (i >= normalizedBase.length || normalizedBase[i] !== items[i]) {
16867              breakPoint = i + 1;
16868              break;
16869            }
16870          }
16871        }
16872        if (breakPoint === 1) {
16873          return path;
16874        }
16875        for (i = 0, l = normalizedBase.length - (breakPoint - 1); i < l; i++) {
16876          out += '../';
16877        }
16878        for (i = breakPoint - 1, l = items.length; i < l; i++) {
16879          if (i !== breakPoint - 1) {
16880            out += '/' + items[i];
16881          } else {
16882            out += items[i];
16883          }
16884        }
16885        return out;
16886      }
16887      toAbsPath(base, path) {
16888        let nb = 0;
16889        const tr = /\/$/.test(path) ? '/' : '';
16890        const normalizedBase = base.split('/');
16891        const normalizedPath = path.split('/');
16892        const baseParts = [];
16893        each$4(normalizedBase, k => {
16894          if (k) {
16895            baseParts.push(k);
16896          }
16897        });
16898        const pathParts = [];
16899        for (let i = normalizedPath.length - 1; i >= 0; i--) {
16900          if (normalizedPath[i].length === 0 || normalizedPath[i] === '.') {
16901            continue;
16902          }
16903          if (normalizedPath[i] === '..') {
16904            nb++;
16905            continue;
16906          }
16907          if (nb > 0) {
16908            nb--;
16909            continue;
16910          }
16911          pathParts.push(normalizedPath[i]);
16912        }
16913        const i = baseParts.length - nb;
16914        let outPath;
16915        if (i <= 0) {
16916          outPath = reverse(pathParts).join('/');
16917        } else {
16918          outPath = baseParts.slice(0, i).join('/') + '/' + reverse(pathParts).join('/');
16919        }
16920        if (outPath.indexOf('/') !== 0) {
16921          outPath = '/' + outPath;
16922        }
16923        if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) {
16924          outPath += tr;
16925        }
16926        return outPath;
16927      }
16928      getURI(noProtoHost = false) {
16929        let s;
16930        if (!this.source || noProtoHost) {
16931          s = '';
16932          if (!noProtoHost) {
16933            if (this.protocol) {
16934              s += this.protocol + '://';
16935            } else {
16936              s += '//';
16937            }
16938            if (this.userInfo) {
16939              s += this.userInfo + '@';
16940            }
16941            if (this.host) {
16942              s += this.host;
16943            }
16944            if (this.port) {
16945              s += ':' + this.port;
16946            }
16947          }
16948          if (this.path) {
16949            s += this.path;
16950          }
16951          if (this.query) {
16952            s += '?' + this.query;
16953          }
16954          if (this.anchor) {
16955            s += '#' + this.anchor;
16956          }
16957          this.source = s;
16958        }
16959        return this.source;
16960      }
16961    }
16962
16963    const filteredUrlAttrs = Tools.makeMap('src,href,data,background,action,formaction,poster,xlink:href');
16964    const internalElementAttr = 'data-mce-type';
16965    let uid = 0;
16966    const processNode = (node, settings, schema, scope, evt) => {
16967      var _a, _b, _c, _d;
16968      const validate = settings.validate;
16969      const specialElements = schema.getSpecialElements();
16970      if (node.nodeType === COMMENT && !settings.allow_conditional_comments && /^\[if/i.test((_a = node.nodeValue) !== null && _a !== void 0 ? _a : '')) {
16971        node.nodeValue = ' ' + node.nodeValue;
16972      }
16973      const lcTagName = (_b = evt === null || evt === void 0 ? void 0 : evt.tagName) !== null && _b !== void 0 ? _b : node.nodeName.toLowerCase();
16974      if (scope !== 'html' && schema.isValid(scope)) {
16975        if (isNonNullable(evt)) {
16976          evt.allowedTags[lcTagName] = true;
16977        }
16978        return;
16979      }
16980      if (node.nodeType !== ELEMENT || lcTagName === 'body') {
16981        return;
16982      }
16983      const element = SugarElement.fromDom(node);
16984      const isInternalElement = has$1(element, internalElementAttr);
16985      const bogus = get$9(element, 'data-mce-bogus');
16986      if (!isInternalElement && isString(bogus)) {
16987        if (bogus === 'all') {
16988          remove$4(element);
16989        } else {
16990          unwrap(element);
16991        }
16992        return;
16993      }
16994      const rule = schema.getElementRule(lcTagName);
16995      if (validate && !rule) {
16996        if (has$2(specialElements, lcTagName)) {
16997          remove$4(element);
16998        } else {
16999          unwrap(element);
17000        }
17001        return;
17002      } else {
17003        if (isNonNullable(evt)) {
17004          evt.allowedTags[lcTagName] = true;
17005        }
17006      }
17007      if (validate && rule && !isInternalElement) {
17008        each$e((_c = rule.attributesForced) !== null && _c !== void 0 ? _c : [], attr => {
17009          set$4(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
17010        });
17011        each$e((_d = rule.attributesDefault) !== null && _d !== void 0 ? _d : [], attr => {
17012          if (!has$1(element, attr.name)) {
17013            set$4(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
17014          }
17015        });
17016        if (rule.attributesRequired && !exists(rule.attributesRequired, attr => has$1(element, attr))) {
17017          unwrap(element);
17018          return;
17019        }
17020        if (rule.removeEmptyAttrs && hasNone(element)) {
17021          unwrap(element);
17022          return;
17023        }
17024        if (rule.outputName && rule.outputName !== lcTagName) {
17025          mutate(element, rule.outputName);
17026        }
17027      }
17028    };
17029    const processAttr = (ele, settings, schema, scope, evt) => {
17030      const tagName = ele.tagName.toLowerCase();
17031      const {attrName, attrValue} = evt;
17032      evt.keepAttr = shouldKeepAttribute(settings, schema, scope, tagName, attrName, attrValue);
17033      if (evt.keepAttr) {
17034        evt.allowedAttributes[attrName] = true;
17035        if (isBooleanAttribute(attrName, schema)) {
17036          evt.attrValue = attrName;
17037        }
17038        if (settings.allow_svg_data_urls && startsWith(attrValue, 'data:image/svg+xml')) {
17039          evt.forceKeepAttr = true;
17040        }
17041      } else if (isRequiredAttributeOfInternalElement(ele, attrName)) {
17042        evt.forceKeepAttr = true;
17043      }
17044    };
17045    const shouldKeepAttribute = (settings, schema, scope, tagName, attrName, attrValue) => {
17046      if (scope !== 'html' && !isNonHtmlElementRootName(tagName)) {
17047        return true;
17048      }
17049      return !(attrName in filteredUrlAttrs && isInvalidUri(settings, attrValue, tagName)) && (!settings.validate || schema.isValid(tagName, attrName) || startsWith(attrName, 'data-') || startsWith(attrName, 'aria-'));
17050    };
17051    const isRequiredAttributeOfInternalElement = (ele, attrName) => ele.hasAttribute(internalElementAttr) && (attrName === 'id' || attrName === 'class' || attrName === 'style');
17052    const isBooleanAttribute = (attrName, schema) => attrName in schema.getBoolAttrs();
17053    const filterAttributes = (ele, settings, schema, scope) => {
17054      const {attributes} = ele;
17055      for (let i = attributes.length - 1; i >= 0; i--) {
17056        const attr = attributes[i];
17057        const attrName = attr.name;
17058        const attrValue = attr.value;
17059        if (!shouldKeepAttribute(settings, schema, scope, ele.tagName.toLowerCase(), attrName, attrValue) && !isRequiredAttributeOfInternalElement(ele, attrName)) {
17060          ele.removeAttribute(attrName);
17061        } else if (isBooleanAttribute(attrName, schema)) {
17062          ele.setAttribute(attrName, attrName);
17063        }
17064      }
17065    };
17066    const setupPurify = (settings, schema, namespaceTracker) => {
17067      const purify$1 = purify();
17068      purify$1.addHook('uponSanitizeElement', (ele, evt) => {
17069        processNode(ele, settings, schema, namespaceTracker.track(ele), evt);
17070      });
17071      purify$1.addHook('uponSanitizeAttribute', (ele, evt) => {
17072        processAttr(ele, settings, schema, namespaceTracker.current(), evt);
17073      });
17074      return purify$1;
17075    };
17076    const getPurifyConfig = (settings, mimeType) => {
17077      const basePurifyConfig = {
17078        IN_PLACE: true,
17079        ALLOW_UNKNOWN_PROTOCOLS: true,
17080        ALLOWED_TAGS: [
17081          '#comment',
17082          '#cdata-section',
17083          'body'
17084        ],
17085        ALLOWED_ATTR: [],
17086        SAFE_FOR_XML: false
17087      };
17088      const config = { ...basePurifyConfig };
17089      config.PARSER_MEDIA_TYPE = mimeType;
17090      if (settings.allow_script_urls) {
17091        config.ALLOWED_URI_REGEXP = /.*/;
17092      } else if (settings.allow_html_data_urls) {
17093        config.ALLOWED_URI_REGEXP = /^(?!(\w+script|mhtml):)/i;
17094      }
17095      return config;
17096    };
17097    const sanitizeSvgElement = ele => {
17098      const xlinkAttrs = [
17099        'type',
17100        'href',
17101        'role',
17102        'arcrole',
17103        'title',
17104        'show',
17105        'actuate',
17106        'label',
17107        'from',
17108        'to'
17109      ].map(name => `xlink:${ name }`);
17110      const config = {
17111        IN_PLACE: true,
17112        USE_PROFILES: {
17113          html: true,
17114          svg: true,
17115          svgFilters: true
17116        },
17117        ALLOWED_ATTR: xlinkAttrs
17118      };
17119      purify().sanitize(ele, config);
17120    };
17121    const sanitizeMathmlElement = (node, settings) => {
17122      const config = {
17123        IN_PLACE: true,
17124        USE_PROFILES: { mathMl: true }
17125      };
17126      const purify$1 = purify();
17127      const allowedEncodings = settings.allow_mathml_annotation_encodings;
17128      const hasAllowedEncodings = isArray$1(allowedEncodings) && allowedEncodings.length > 0;
17129      const hasValidEncoding = el => {
17130        const encoding = el.getAttribute('encoding');
17131        return hasAllowedEncodings && isString(encoding) && contains$2(allowedEncodings, encoding);
17132      };
17133      purify$1.addHook('uponSanitizeElement', (node, evt) => {
17134        var _a;
17135        const lcTagName = (_a = evt.tagName) !== null && _a !== void 0 ? _a : node.nodeName.toLowerCase();
17136        if (hasAllowedEncodings && lcTagName === 'semantics') {
17137          evt.allowedTags[lcTagName] = true;
17138        }
17139        if (lcTagName === 'annotation') {
17140          const elm = node;
vendor: 9,375 bytes, lines 17141-17372
17141          const keepElement = hasValidEncoding(elm);
17142          evt.allowedTags[lcTagName] = keepElement;
17143          if (!keepElement) {
17144            elm.remove();
17145          }
17146        }
17147      });
17148      purify$1.sanitize(node, config);
17149    };
17150    const mkSanitizeNamespaceElement = settings => ele => {
17151      const namespaceType = toScopeType(ele);
17152      if (namespaceType === 'svg') {
17153        sanitizeSvgElement(ele);
17154      } else if (namespaceType === 'math') {
17155        sanitizeMathmlElement(ele, settings);
17156      } else {
17157        throw new Error('Not a namespace element');
17158      }
17159    };
17160    const getSanitizer = (settings, schema) => {
17161      const namespaceTracker = createNamespaceTracker();
17162      if (settings.sanitize) {
17163        const purify = setupPurify(settings, schema, namespaceTracker);
17164        const sanitizeHtmlElement = (body, mimeType) => {
17165          purify.sanitize(body, getPurifyConfig(settings, mimeType));
17166          purify.removed = [];
17167          namespaceTracker.reset();
17168        };
17169        return {
17170          sanitizeHtmlElement,
17171          sanitizeNamespaceElement: mkSanitizeNamespaceElement(settings)
17172        };
17173      } else {
17174        const sanitizeHtmlElement = (body, _mimeType) => {
17175          const nodeIterator = document.createNodeIterator(body, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT);
17176          let node;
17177          while (node = nodeIterator.nextNode()) {
17178            const currentScope = namespaceTracker.track(node);
17179            processNode(node, settings, schema, currentScope);
17180            if (isElement$6(node)) {
17181              filterAttributes(node, settings, schema, currentScope);
17182            }
17183          }
17184          namespaceTracker.reset();
17185        };
17186        const sanitizeNamespaceElement = noop;
17187        return {
17188          sanitizeHtmlElement,
17189          sanitizeNamespaceElement
17190        };
17191      }
17192    };
17193
17194    const makeMap = Tools.makeMap, extend$1 = Tools.extend;
17195    const transferChildren = (parent, nativeParent, specialElements, nsSanitizer) => {
17196      const parentName = parent.name;
17197      const isSpecial = parentName in specialElements && parentName !== 'title' && parentName !== 'textarea' && parentName !== 'noscript';
17198      const childNodes = nativeParent.childNodes;
17199      for (let ni = 0, nl = childNodes.length; ni < nl; ni++) {
17200        const nativeChild = childNodes[ni];
17201        const child = new AstNode(nativeChild.nodeName.toLowerCase(), nativeChild.nodeType);
17202        if (isElement$6(nativeChild)) {
17203          const attributes = nativeChild.attributes;
17204          for (let ai = 0, al = attributes.length; ai < al; ai++) {
17205            const attr = attributes[ai];
17206            child.attr(attr.name, attr.value);
17207          }
17208          if (isNonHtmlElementRootName(child.name)) {
17209            nsSanitizer(nativeChild);
17210            child.value = nativeChild.innerHTML;
17211          }
17212        } else if (isText$b(nativeChild)) {
17213          child.value = nativeChild.data;
17214          if (isSpecial) {
17215            child.raw = true;
17216          }
17217        } else if (isComment(nativeChild) || isCData(nativeChild) || isPi(nativeChild)) {
17218          child.value = nativeChild.data;
17219        }
17220        if (!isNonHtmlElementRootName(child.name)) {
17221          transferChildren(child, nativeChild, specialElements, nsSanitizer);
17222        }
17223        parent.append(child);
17224      }
17225    };
17226    const walkTree = (root, preprocessors, postprocessors) => {
17227      const traverseOrder = [];
17228      for (let node = root, lastNode = node; node; lastNode = node, node = node.walk()) {
17229        const tempNode = node;
17230        each$e(preprocessors, preprocess => preprocess(tempNode));
17231        if (isNullable(tempNode.parent) && tempNode !== root) {
17232          node = lastNode;
17233        } else {
17234          traverseOrder.push(tempNode);
17235        }
17236      }
17237      for (let i = traverseOrder.length - 1; i >= 0; i--) {
17238        const node = traverseOrder[i];
17239        each$e(postprocessors, postprocess => postprocess(node));
17240      }
17241    };
17242    const whitespaceCleaner = (root, schema, settings, args) => {
17243      const validate = settings.validate;
17244      const nonEmptyElements = schema.getNonEmptyElements();
17245      const whitespaceElements = schema.getWhitespaceElements();
17246      const blockElements = extend$1(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
17247      const textRootBlockElements = getTextRootBlockElements(schema);
17248      const allWhiteSpaceRegExp = /[ \t\r\n]+/g;
17249      const startWhiteSpaceRegExp = /^[ \t\r\n]+/;
17250      const endWhiteSpaceRegExp = /[ \t\r\n]+$/;
17251      const hasWhitespaceParent = node => {
17252        let tempNode = node.parent;
17253        while (isNonNullable(tempNode)) {
17254          if (tempNode.name in whitespaceElements) {
17255            return true;
17256          } else {
17257            tempNode = tempNode.parent;
17258          }
17259        }
17260        return false;
17261      };
17262      const isTextRootBlockEmpty = node => {
17263        let tempNode = node;
17264        while (isNonNullable(tempNode)) {
17265          if (tempNode.name in textRootBlockElements) {
17266            return isEmpty(schema, nonEmptyElements, whitespaceElements, tempNode);
17267          } else {
17268            tempNode = tempNode.parent;
17269          }
17270        }
17271        return false;
17272      };
17273      const isBlock = node => node.name in blockElements || isTransparentAstBlock(schema, node) || isNonHtmlElementRootName(node.name) && node.parent === root;
17274      const isAtEdgeOfBlock = (node, start) => {
17275        const neighbour = start ? node.prev : node.next;
17276        if (isNonNullable(neighbour) || isNullable(node.parent)) {
17277          return false;
17278        }
17279        return isBlock(node.parent) && (node.parent !== root || args.isRootContent === true);
17280      };
17281      const preprocess = node => {
17282        var _a;
17283        if (node.type === 3) {
17284          if (!hasWhitespaceParent(node)) {
17285            let text = (_a = node.value) !== null && _a !== void 0 ? _a : '';
17286            text = text.replace(allWhiteSpaceRegExp, ' ');
17287            if (isLineBreakNode(node.prev, isBlock) || isAtEdgeOfBlock(node, true)) {
17288              text = text.replace(startWhiteSpaceRegExp, '');
17289            }
17290            if (text.length === 0) {
17291              node.remove();
17292            } else if (text === ' ' && node.prev && node.prev.type === COMMENT && node.next && node.next.type === COMMENT) {
17293              node.remove();
17294            } else {
17295              node.value = text;
17296            }
17297          }
17298        }
17299      };
17300      const postprocess = node => {
17301        var _a;
17302        if (node.type === 1) {
17303          const elementRule = schema.getElementRule(node.name);
17304          if (validate && elementRule) {
17305            const isNodeEmpty = isEmpty(schema, nonEmptyElements, whitespaceElements, node);
17306            if (elementRule.paddInEmptyBlock && isNodeEmpty && isTextRootBlockEmpty(node)) {
17307              paddEmptyNode(settings, args, isBlock, node);
17308            } else if (elementRule.removeEmpty && isNodeEmpty) {
17309              if (isBlock(node)) {
17310                node.remove();
17311              } else {
17312                node.unwrap();
17313              }
17314            } else if (elementRule.paddEmpty && (isNodeEmpty || isPaddedWithNbsp(node))) {
17315              paddEmptyNode(settings, args, isBlock, node);
17316            }
17317          }
17318        } else if (node.type === 3) {
17319          if (!hasWhitespaceParent(node)) {
17320            let text = (_a = node.value) !== null && _a !== void 0 ? _a : '';
17321            if (node.next && isBlock(node.next) || isAtEdgeOfBlock(node, false)) {
17322              text = text.replace(endWhiteSpaceRegExp, '');
17323            }
17324            if (text.length === 0) {
17325              node.remove();
17326            } else {
17327              node.value = text;
17328            }
17329          }
17330        }
17331      };
17332      return [
17333        preprocess,
17334        postprocess
17335      ];
17336    };
17337    const getRootBlockName = (settings, args) => {
17338      var _a;
17339      const name = (_a = args.forced_root_block) !== null && _a !== void 0 ? _a : settings.forced_root_block;
17340      if (name === false) {
17341        return '';
17342      } else if (name === true) {
17343        return 'p';
17344      } else {
17345        return name;
17346      }
17347    };
17348    const DomParser = (settings = {}, schema = Schema()) => {
17349      const nodeFilterRegistry = create$8();
17350      const attributeFilterRegistry = create$8();
17351      const defaultedSettings = {
17352        validate: true,
17353        root_name: 'body',
17354        sanitize: true,
17355        ...settings
17356      };
17357      const parser = new DOMParser();
17358      const sanitizer = getSanitizer(defaultedSettings, schema);
17359      const parseAndSanitizeWithContext = (html, rootName, format = 'html') => {
17360        const mimeType = format === 'xhtml' ? 'application/xhtml+xml' : 'text/html';
17361        const isSpecialRoot = has$2(schema.getSpecialElements(), rootName.toLowerCase());
17362        const content = isSpecialRoot ? `<${ rootName }>${ html }</${ rootName }>` : html;
17363        const makeWrap = () => {
17364          if (format === 'xhtml') {
17365            return `<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>${ content }</body></html>`;
17366          } else if (/^[\s]*<head/i.test(html) || /^[\s]*<html/i.test(html) || /^[\s]*<!DOCTYPE/i.test(html)) {
17367            return `<html>${ content }</html>`;
17368          } else {
17369            return `<body>${ content }</body>`;
17370          }
17371        };
17372        const body = parser.parseFromString(makeWrap()
vendor: 15,328 bytes, lines 17372-17755
17372, mimeType).body;
17373        sanitizer.sanitizeHtmlElement(body, mimeType);
17374        return isSpecialRoot ? body.firstChild : body;
17375      };
17376      const addNodeFilter = nodeFilterRegistry.addFilter;
17377      const getNodeFilters = nodeFilterRegistry.getFilters;
17378      const removeNodeFilter = nodeFilterRegistry.removeFilter;
17379      const addAttributeFilter = attributeFilterRegistry.addFilter;
17380      const getAttributeFilters = attributeFilterRegistry.getFilters;
17381      const removeAttributeFilter = attributeFilterRegistry.removeFilter;
17382      const findInvalidChildren = (node, invalidChildren) => {
17383        if (isInvalid(schema, node)) {
17384          invalidChildren.push(node);
17385        }
17386      };
17387      const isWrappableNode = (blockElements, node) => {
17388        const isInternalElement = isString(node.attr(internalElementAttr));
17389        const isInlineElement = node.type === 1 && (!has$2(blockElements, node.name) && !isTransparentAstBlock(schema, node)) && !isNonHtmlElementRootName(node.name);
17390        return node.type === 3 || isInlineElement && !isInternalElement;
17391      };
17392      const addRootBlocks = (rootNode, rootBlockName) => {
17393        const blockElements = extend$1(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
17394        const startWhiteSpaceRegExp = /^[ \t\r\n]+/;
17395        const endWhiteSpaceRegExp = /[ \t\r\n]+$/;
17396        let node = rootNode.firstChild, rootBlockNode = null;
17397        const trim = rootBlock => {
17398          var _a, _b;
17399          if (rootBlock) {
17400            node = rootBlock.firstChild;
17401            if (node && node.type === 3) {
17402              node.value = (_a = node.value) === null || _a === void 0 ? void 0 : _a.replace(startWhiteSpaceRegExp, '');
17403            }
17404            node = rootBlock.lastChild;
17405            if (node && node.type === 3) {
17406              node.value = (_b = node.value) === null || _b === void 0 ? void 0 : _b.replace(endWhiteSpaceRegExp, '');
17407            }
17408          }
17409        };
17410        if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) {
17411          return;
17412        }
17413        while (node) {
17414          const next = node.next;
17415          if (isWrappableNode(blockElements, node)) {
17416            if (!rootBlockNode) {
17417              rootBlockNode = new AstNode(rootBlockName, 1);
17418              rootBlockNode.attr(defaultedSettings.forced_root_block_attrs);
17419              rootNode.insert(rootBlockNode, node);
17420              rootBlockNode.append(node);
17421            } else {
17422              rootBlockNode.append(node);
17423            }
17424          } else {
17425            trim(rootBlockNode);
17426            rootBlockNode = null;
17427          }
17428          node = next;
17429        }
17430        trim(rootBlockNode);
17431      };
17432      const parse = (html, args = {}) => {
17433        var _a;
17434        const validate = defaultedSettings.validate;
17435        const rootName = (_a = args.context) !== null && _a !== void 0 ? _a : defaultedSettings.root_name;
17436        const element = parseAndSanitizeWithContext(html, rootName, args.format);
17437        updateChildren(schema, element);
17438        const rootNode = new AstNode(rootName, 11);
17439        transferChildren(rootNode, element, schema.getSpecialElements(), sanitizer.sanitizeNamespaceElement);
17440        element.innerHTML = '';
17441        const [whitespacePre, whitespacePost] = whitespaceCleaner(rootNode, schema, defaultedSettings, args);
17442        const invalidChildren = [];
17443        const invalidFinder = validate ? node => findInvalidChildren(node, invalidChildren) : noop;
17444        const matches = {
17445          nodes: {},
17446          attributes: {}
17447        };
17448        const matchFinder = node => matchNode$1(getNodeFilters(), getAttributeFilters(), node, matches);
17449        walkTree(rootNode, [
17450          whitespacePre,
17451          matchFinder
17452        ], [
17453          whitespacePost,
17454          invalidFinder
17455        ]);
17456        invalidChildren.reverse();
17457        if (validate && invalidChildren.length > 0) {
17458          if (args.context) {
17459            const {
17460              pass: topLevelChildren,
17461              fail: otherChildren
17462            } = partition$2(invalidChildren, child => child.parent === rootNode);
17463            cleanInvalidNodes(otherChildren, schema, rootNode, matchFinder);
17464            args.invalid = topLevelChildren.length > 0;
17465          } else {
17466            cleanInvalidNodes(invalidChildren, schema, rootNode, matchFinder);
17467          }
17468        }
17469        const rootBlockName = getRootBlockName(defaultedSettings, args);
17470        if (rootBlockName && (rootNode.name === 'body' || args.isRootContent)) {
17471          addRootBlocks(rootNode, rootBlockName);
17472        }
17473        if (!args.invalid) {
17474          runFilters(matches, args);
17475        }
17476        return rootNode;
17477      };
17478      const exports = {
17479        schema,
17480        addAttributeFilter,
17481        getAttributeFilters,
17482        removeAttributeFilter,
17483        addNodeFilter,
17484        getNodeFilters,
17485        removeNodeFilter,
17486        parse
17487      };
17488      register$4(exports, defaultedSettings);
17489      register$5(exports, defaultedSettings, schema);
17490      return exports;
17491    };
17492
17493    const serializeContent = content => isTreeNode(content) ? HtmlSerializer({ validate: false }).serialize(content) : content;
17494    const withSerializedContent = (content, fireEvent, parserSettings) => {
17495      const serializedContent = serializeContent(content);
17496      const eventArgs = fireEvent(serializedContent);
17497      if (eventArgs.isDefaultPrevented()) {
17498        return eventArgs;
17499      } else if (isTreeNode(content)) {
17500        if (eventArgs.content !== serializedContent) {
17501          const rootNode = DomParser({
17502            validate: false,
17503            forced_root_block: false,
17504            ...parserSettings
17505          }).parse(eventArgs.content, { context: content.name });
17506          return {
17507            ...eventArgs,
17508            content: rootNode
17509          };
17510        } else {
17511          return {
17512            ...eventArgs,
17513            content
17514          };
17515        }
17516      } else {
17517        return eventArgs;
17518      }
17519    };
17520    const makeParserSettings = editor => ({
17521      sanitize: shouldSanitizeXss(editor),
17522      sandbox_iframes: shouldSandboxIframes(editor),
17523      sandbox_iframes_exclusions: getSandboxIframesExclusions(editor)
17524    });
17525    const preProcessGetContent = (editor, args) => {
17526      if (args.no_events) {
17527        return Result.value(args);
17528      } else {
17529        const eventArgs = fireBeforeGetContent(editor, args);
17530        if (eventArgs.isDefaultPrevented()) {
17531          return Result.error(fireGetContent(editor, {
17532            content: '',
17533            ...eventArgs
17534          }).content);
17535        } else {
17536          return Result.value(eventArgs);
17537        }
17538      }
17539    };
17540    const postProcessGetContent = (editor, content, args) => {
17541      if (args.no_events) {
17542        return content;
17543      } else {
17544        const processedEventArgs = withSerializedContent(content, content => fireGetContent(editor, {
17545          ...args,
17546          content
17547        }), makeParserSettings(editor));
17548        return processedEventArgs.content;
17549      }
17550    };
17551    const preProcessSetContent = (editor, args) => {
17552      if (args.no_events) {
17553        return Result.value(args);
17554      } else {
17555        const processedEventArgs = withSerializedContent(args.content, content => fireBeforeSetContent(editor, {
17556          ...args,
17557          content
17558        }), makeParserSettings(editor));
17559        if (processedEventArgs.isDefaultPrevented()) {
17560          fireSetContent(editor, processedEventArgs);
17561          return Result.error(undefined);
17562        } else {
17563          return Result.value(processedEventArgs);
17564        }
17565      }
17566    };
17567    const postProcessSetContent = (editor, content, args) => {
17568      if (!args.no_events) {
17569        fireSetContent(editor, {
17570          ...args,
17571          content
17572        });
17573      }
17574    };
17575
17576    const tableModel = (element, width, rows) => ({
17577      element,
17578      width,
17579      rows
17580    });
17581    const tableRow = (element, cells) => ({
17582      element,
17583      cells
17584    });
17585    const cellPosition = (x, y) => ({
17586      x,
17587      y
17588    });
17589    const getSpan = (td, key) => {
17590      return getOpt(td, key).bind(toInt).getOr(1);
17591    };
17592    const fillout = (table, x, y, tr, td) => {
17593      const rowspan = getSpan(td, 'rowspan');
17594      const colspan = getSpan(td, 'colspan');
17595      const rows = table.rows;
17596      for (let y2 = y; y2 < y + rowspan; y2++) {
17597        if (!rows[y2]) {
17598          rows[y2] = tableRow(deep$1(tr), []);
17599        }
17600        for (let x2 = x; x2 < x + colspan; x2++) {
17601          const cells = rows[y2].cells;
17602          cells[x2] = y2 === y && x2 === x ? td : shallow$1(td);
17603        }
17604      }
17605    };
17606    const cellExists = (table, x, y) => {
17607      const rows = table.rows;
17608      const cells = rows[y] ? rows[y].cells : [];
17609      return !!cells[x];
17610    };
17611    const skipCellsX = (table, x, y) => {
17612      while (cellExists(table, x, y)) {
17613        x++;
17614      }
17615      return x;
17616    };
17617    const getWidth = rows => {
17618      return foldl(rows, (acc, row) => {
17619        return row.cells.length > acc ? row.cells.length : acc;
17620      }, 0);
17621    };
17622    const findElementPos = (table, element) => {
17623      const rows = table.rows;
17624      for (let y = 0; y < rows.length; y++) {
17625        const cells = rows[y].cells;
17626        for (let x = 0; x < cells.length; x++) {
17627          if (eq(cells[x], element)) {
17628            return Optional.some(cellPosition(x, y));
17629          }
17630        }
17631      }
17632      return Optional.none();
17633    };
17634    const extractRows = (table, sx, sy, ex, ey) => {
17635      const newRows = [];
17636      const rows = table.rows;
17637      for (let y = sy; y <= ey; y++) {
17638        const cells = rows[y].cells;
17639        const slice = sx < ex ? cells.slice(sx, ex + 1) : cells.slice(ex, sx + 1);
17640        newRows.push(tableRow(rows[y].element, slice));
17641      }
17642      return newRows;
17643    };
17644    const subTable = (table, startPos, endPos) => {
17645      const sx = startPos.x, sy = startPos.y;
17646      const ex = endPos.x, ey = endPos.y;
17647      const newRows = sy < ey ? extractRows(table, sx, sy, ex, ey) : extractRows(table, sx, ey, ex, sy);
17648      return tableModel(table.element, getWidth(newRows), newRows);
17649    };
17650    const createDomTable = (table, rows) => {
17651      const tableElement = shallow$1(table.element);
17652      const tableBody = SugarElement.fromTag('tbody');
17653      append(tableBody, rows);
17654      append$1(tableElement, tableBody);
17655      return tableElement;
17656    };
17657    const modelRowsToDomRows = table => {
17658      return map$3(table.rows, row => {
17659        const cells = map$3(row.cells, cell => {
17660          const td = deep$1(cell);
17661          remove$9(td, 'colspan');
17662          remove$9(td, 'rowspan');
17663          return td;
17664        });
17665        const tr = shallow$1(row.element);
17666        append(tr, cells);
17667        return tr;
17668      });
17669    };
17670    const fromDom = tableElm => {
17671      const table = tableModel(shallow$1(tableElm), 0, []);
17672      each$e(descendants(tableElm, 'tr'), (tr, y) => {
17673        each$e(descendants(tr, 'td,th'), (td, x) => {
17674          fillout(table, skipCellsX(table, x, y), y, tr, td);
17675        });
17676      });
17677      return tableModel(table.element, getWidth(table.rows), table.rows);
17678    };
17679    const toDom = table => {
17680      return createDomTable(table, modelRowsToDomRows(table));
17681    };
17682    const subsection = (table, startElement, endElement) => {
17683      return findElementPos(table, startElement).bind(startPos => {
17684        return findElementPos(table, endElement).map(endPos => {
17685          return subTable(table, startPos, endPos);
17686        });
17687      });
17688    };
17689
17690    const findParentListContainer = parents => find$2(parents, elm => name(elm) === 'ul' || name(elm) === 'ol');
17691    const getFullySelectedListWrappers = (parents, rng) => find$2(parents, elm => name(elm) === 'li' && hasAllContentsSelected(elm, rng)).fold(constant([]), _li => findParentListContainer(parents).map(listCont => {
17692      const listElm = SugarElement.fromTag(name(listCont));
17693      const listStyles = filter$4(getAllRaw(listCont), (_style, name) => startsWith(name, 'list-style'));
17694      setAll(listElm, listStyles);
17695      return [
17696        SugarElement.fromTag('li'),
17697        listElm
17698      ];
17699    }).getOr([]));
17700    const wrap = (innerElm, elms) => {
17701      const wrapped = foldl(elms, (acc, elm) => {
17702        append$1(elm, acc);
17703        return elm;
17704      }, innerElm);
17705      return elms.length > 0 ? fromElements([wrapped]) : wrapped;
17706    };
17707    const directListWrappers = commonAnchorContainer => {
17708      if (isListItem$1(commonAnchorContainer)) {
17709        return parent(commonAnchorContainer).filter(isList).fold(constant([]), listElm => [
17710          commonAnchorContainer,
17711          listElm
17712        ]);
17713      } else {
17714        return isList(commonAnchorContainer) ? [commonAnchorContainer] : [];
17715      }
17716    };
17717    const getWrapElements = (rootNode, rng, schema) => {
17718      const commonAnchorContainer = SugarElement.fromDom(rng.commonAncestorContainer);
17719      const parents = parentsAndSelf(commonAnchorContainer, rootNode);
17720      const wrapElements = filter$5(parents, el => schema.isWrapper(name(el)));
17721      const listWrappers = getFullySelectedListWrappers(parents, rng);
17722      const allWrappers = wrapElements.concat(listWrappers.length ? listWrappers : directListWrappers(commonAnchorContainer));
17723      return map$3(allWrappers, shallow$1);
17724    };
17725    const emptyFragment = () => fromElements([]);
17726    const getFragmentFromRange = (rootNode, rng, schema) => wrap(SugarElement.fromDom(rng.cloneContents()), getWrapElements(rootNode, rng, schema));
17727    const getParentTable = (rootElm, cell) => ancestor$3(cell, 'table', curry(eq, rootElm));
17728    const getTableFragment = (rootNode, selectedTableCells) => getParentTable(rootNode, selectedTableCells[0]).bind(tableElm => {
17729      const firstCell = selectedTableCells[0];
17730      const lastCell = selectedTableCells[selectedTableCells.length - 1];
17731      const fullTableModel = fromDom(tableElm);
17732      return subsection(fullTableModel, firstCell, lastCell).map(sectionedTableModel => fromElements([toDom(sectionedTableModel)]));
17733    }).getOrThunk(emptyFragment);
17734    const getSelectionFragment = (rootNode, ranges, schema) => ranges.length > 0 && ranges[0].collapsed ? emptyFragment() : getFragmentFromRange(rootNode, ranges[0], schema);
17735    const read$3 = (rootNode, ranges, schema) => {
17736      const selectedCells = getCellsFromElementOrRanges(ranges, rootNode);
17737      return selectedCells.length > 0 ? getTableFragment(rootNode, selectedCells) : getSelectionFragment(rootNode, ranges, schema);
17738    };
17739
17740    const isCollapsibleWhitespace = (text, index) => index >= 0 && index < text.length && isWhiteSpace(text.charAt(index));
17741    const getInnerText = bin => {
17742      return trim$2(bin.innerText);
17743    };
17744    const getContextNodeName = parentBlockOpt => parentBlockOpt.map(block => block.nodeName).getOr('div').toLowerCase();
17745    const getTextContent = editor => Optional.from(editor.selection.getRng()).map(rng => {
17746      var _a;
17747      const parentBlockOpt = Optional.from(editor.dom.getParent(rng.commonAncestorContainer, editor.dom.isBlock));
17748      const body = editor.getBody();
17749      const contextNodeName = getContextNodeName(parentBlockOpt);
17750      const rangeContentClone = SugarElement.fromDom(rng.cloneContents());
17751      cleanupBogusElements(rangeContentClone);
17752      cleanupInputNames(rangeContentClone);
17753      const bin = editor.dom.add(body, contextNodeName, {
17754        'data-mce-bogus': 'all',
17755        
17755'style'
vendor: 10,233 bytes, lines 17755-18042
17755: 'overflow: hidden; opacity: 0;'
17756      }, rangeContentClone.dom);
17757      const text = getInnerText(bin);
17758      const nonRenderedText = trim$2((_a = bin.textContent) !== null && _a !== void 0 ? _a : '');
17759      editor.dom.remove(bin);
17760      if (isCollapsibleWhitespace(nonRenderedText, 0) || isCollapsibleWhitespace(nonRenderedText, nonRenderedText.length - 1)) {
17761        const parentBlock = parentBlockOpt.getOr(body);
17762        const parentBlockText = getInnerText(parentBlock);
17763        const textIndex = parentBlockText.indexOf(text);
17764        if (textIndex === -1) {
17765          return text;
17766        } else {
17767          const hasProceedingSpace = isCollapsibleWhitespace(parentBlockText, textIndex - 1);
17768          const hasTrailingSpace = isCollapsibleWhitespace(parentBlockText, textIndex + text.length);
17769          return (hasProceedingSpace ? ' ' : '') + text + (hasTrailingSpace ? ' ' : '');
17770        }
17771      } else {
17772        return text;
17773      }
17774    }).getOr('');
17775    const getSerializedContent = (editor, args) => {
17776      const rng = editor.selection.getRng(), tmpElm = editor.dom.create('body');
17777      const sel = editor.selection.getSel();
17778      const ranges = processRanges(editor, getRanges$1(sel));
17779      const fragment = args.contextual ? read$3(SugarElement.fromDom(editor.getBody()), ranges, editor.schema).dom : rng.cloneContents();
17780      if (fragment) {
17781        tmpElm.appendChild(fragment);
17782      }
17783      return editor.selection.serializer.serialize(tmpElm, args);
17784    };
17785    const extractSelectedContent = (editor, args) => {
17786      if (args.format === 'text') {
17787        return getTextContent(editor);
17788      } else {
17789        const content = getSerializedContent(editor, args);
17790        if (args.format === 'tree') {
17791          return content;
17792        } else {
17793          return editor.selection.isCollapsed() ? '' : content;
17794        }
17795      }
17796    };
17797    const setupArgs$3 = (args, format) => ({
17798      ...args,
17799      format,
17800      get: true,
17801      selection: true,
17802      getInner: true
17803    });
17804    const getSelectedContentInternal = (editor, format, args = {}) => {
17805      const defaultedArgs = setupArgs$3(args, format);
17806      return preProcessGetContent(editor, defaultedArgs).fold(identity, updatedArgs => {
17807        const content = extractSelectedContent(editor, updatedArgs);
17808        return postProcessGetContent(editor, content, updatedArgs);
17809      });
17810    };
17811
17812    const KEEP = 0, INSERT = 1, DELETE = 2;
17813    const diff = (left, right) => {
17814      const size = left.length + right.length + 2;
17815      const vDown = new Array(size);
17816      const vUp = new Array(size);
17817      const snake = (start, end, diag) => {
17818        return {
17819          start,
17820          end,
17821          diag
17822        };
17823      };
17824      const buildScript = (start1, end1, start2, end2, script) => {
17825        const middle = getMiddleSnake(start1, end1, start2, end2);
17826        if (middle === null || middle.start === end1 && middle.diag === end1 - end2 || middle.end === start1 && middle.diag === start1 - start2) {
17827          let i = start1;
17828          let j = start2;
17829          while (i < end1 || j < end2) {
17830            if (i < end1 && j < end2 && left[i] === right[j]) {
17831              script.push([
17832                KEEP,
17833                left[i]
17834              ]);
17835              ++i;
17836              ++j;
17837            } else {
17838              if (end1 - start1 > end2 - start2) {
17839                script.push([
17840                  DELETE,
17841                  left[i]
17842                ]);
17843                ++i;
17844              } else {
17845                script.push([
17846                  INSERT,
17847                  right[j]
17848                ]);
17849                ++j;
17850              }
17851            }
17852          }
17853        } else {
17854          buildScript(start1, middle.start, start2, middle.start - middle.diag, script);
17855          for (let i2 = middle.start; i2 < middle.end; ++i2) {
17856            script.push([
17857              KEEP,
17858              left[i2]
17859            ]);
17860          }
17861          buildScript(middle.end, end1, middle.end - middle.diag, end2, script);
17862        }
17863      };
17864      const buildSnake = (start, diag, end1, end2) => {
17865        let end = start;
17866        while (end - diag < end2 && end < end1 && left[end] === right[end - diag]) {
17867          ++end;
17868        }
17869        return snake(start, end, diag);
17870      };
17871      const getMiddleSnake = (start1, end1, start2, end2) => {
17872        const m = end1 - start1;
17873        const n = end2 - start2;
17874        if (m === 0 || n === 0) {
17875          return null;
17876        }
17877        const delta = m - n;
17878        const sum = n + m;
17879        const offset = (sum % 2 === 0 ? sum : sum + 1) / 2;
17880        vDown[1 + offset] = start1;
17881        vUp[1 + offset] = end1 + 1;
17882        let d, k, i, x, y;
17883        for (d = 0; d <= offset; ++d) {
17884          for (k = -d; k <= d; k += 2) {
17885            i = k + offset;
17886            if (k === -d || k !== d && vDown[i - 1] < vDown[i + 1]) {
17887              vDown[i] = vDown[i + 1];
17888            } else {
17889              vDown[i] = vDown[i - 1] + 1;
17890            }
17891            x = vDown[i];
17892            y = x - start1 + start2 - k;
17893            while (x < end1 && y < end2 && left[x] === right[y]) {
17894              vDown[i] = ++x;
17895              ++y;
17896            }
17897            if (delta % 2 !== 0 && delta - d <= k && k <= delta + d) {
17898              if (vUp[i - delta] <= vDown[i]) {
17899                return buildSnake(vUp[i - delta], k + start1 - start2, end1, end2);
17900              }
17901            }
17902          }
17903          for (k = delta - d; k <= delta + d; k += 2) {
17904            i = k + offset - delta;
17905            if (k === delta - d || k !== delta + d && vUp[i + 1] <= vUp[i - 1]) {
17906              vUp[i] = vUp[i + 1] - 1;
17907            } else {
17908              vUp[i] = vUp[i - 1];
17909            }
17910            x = vUp[i] - 1;
17911            y = x - start1 + start2 - k;
17912            while (x >= start1 && y >= start2 && left[x] === right[y]) {
17913              vUp[i] = x--;
17914              y--;
17915            }
17916            if (delta % 2 === 0 && -d <= k && k <= d) {
17917              if (vUp[i] <= vDown[i + delta]) {
17918                return buildSnake(vUp[i], k + start1 - start2, end1, end2);
17919              }
17920            }
17921          }
17922        }
17923        return null;
17924      };
17925      const script = [];
17926      buildScript(0, left.length, 0, right.length, script);
17927      return script;
17928    };
17929
17930    const getOuterHtml = elm => {
17931      if (isElement$6(elm)) {
17932        return elm.outerHTML;
17933      } else if (isText$b(elm)) {
17934        return Entities.encodeRaw(elm.data, false);
17935      } else if (isComment(elm)) {
17936        return '<!--' + elm.data + '-->';
17937      }
17938      return '';
17939    };
17940    const createFragment = html => {
17941      let node;
17942      const container = document.createElement('div');
17943      const frag = document.createDocumentFragment();
17944      if (html) {
17945        container.innerHTML = html;
17946      }
17947      while (node = container.firstChild) {
17948        frag.appendChild(node);
17949      }
17950      return frag;
17951    };
17952    const insertAt = (elm, html, index) => {
17953      const fragment = createFragment(html);
17954      if (elm.hasChildNodes() && index < elm.childNodes.length) {
17955        const target = elm.childNodes[index];
17956        elm.insertBefore(fragment, target);
17957      } else {
17958        elm.appendChild(fragment);
17959      }
17960    };
17961    const removeAt = (elm, index) => {
17962      if (elm.hasChildNodes() && index < elm.childNodes.length) {
17963        const target = elm.childNodes[index];
17964        elm.removeChild(target);
17965      }
17966    };
17967    const applyDiff = (diff, elm) => {
17968      let index = 0;
17969      each$e(diff, action => {
17970        if (action[0] === KEEP) {
17971          index++;
17972        } else if (action[0] === INSERT) {
17973          insertAt(elm, action[1], index);
17974          index++;
17975        } else if (action[0] === DELETE) {
17976          removeAt(elm, index);
17977        }
17978      });
17979    };
17980    const read$2 = (elm, trimZwsp) => filter$5(map$3(from(elm.childNodes), trimZwsp ? compose(trim$2, getOuterHtml) : getOuterHtml), item => {
17981      return item.length > 0;
17982    });
17983    const write = (fragments, elm) => {
17984      const currentFragments = map$3(from(elm.childNodes), getOuterHtml);
17985      applyDiff(diff(currentFragments, fragments), elm);
17986      return elm;
17987    };
17988
17989    const lazyTempDocument = cached(() => document.implementation.createHTMLDocument('undo'));
17990    const hasIframes = body => body.querySelector('iframe') !== null;
17991    const createFragmentedLevel = fragments => {
17992      return {
17993        type: 'fragmented',
17994        fragments,
17995        content: '',
17996        bookmark: null,
17997        beforeBookmark: null
17998      };
17999    };
18000    const createCompleteLevel = content => {
18001      return {
18002        type: 'complete',
18003        fragments: null,
18004        content,
18005        bookmark: null,
18006        beforeBookmark: null
18007      };
18008    };
18009    const createFromEditor = editor => {
18010      const tempAttrs = editor.serializer.getTempAttrs();
18011      const body = trim$1(editor.getBody(), tempAttrs);
18012      return hasIframes(body) ? createFragmentedLevel(read$2(body, true)) : createCompleteLevel(trim$2(body.innerHTML));
18013    };
18014    const applyToEditor = (editor, level, before) => {
18015      const bookmark = before ? level.beforeBookmark : level.bookmark;
18016      if (level.type === 'fragmented') {
18017        write(level.fragments, editor.getBody());
18018      } else {
18019        editor.setContent(level.content, {
18020          format: 'raw',
18021          no_selection: isNonNullable(bookmark) && isPathBookmark(bookmark) ? !bookmark.isFakeCaret : true
18022        });
18023      }
18024      if (bookmark) {
18025        editor.selection.moveToBookmark(bookmark);
18026        editor.selection.scrollIntoView();
18027      }
18028    };
18029    const getLevelContent = level => {
18030      return level.type === 'fragmented' ? level.fragments.join('') : level.content;
18031    };
18032    const getCleanLevelContent = level => {
18033      const elm = SugarElement.fromTag('body', lazyTempDocument());
18034      set$1(elm, getLevelContent(level));
18035      each$e(descendants(elm, '*[data-mce-bogus]'), unwrap);
18036      return get$6(elm);
18037    };
18038    const hasEqualContent = (level1, level2) => getLevelContent(level1) === getLevelContent(level2);
18039    const hasEqualCleanedContent = (level1, level2) => getCleanLevelContent(level1) === getCleanLevelContent(level2);
18040    const isEq$1 = (level1, level2) => {
18041      if (!level1 || !level2) {
18042        return false;
vendor: 4,404 bytes, lines 18043-18175
18043      } else if (hasEqualContent(level1, level2)) {
18044        return true;
18045      } else {
18046        return hasEqualCleanedContent(level1, level2);
18047      }
18048    };
18049
18050    const isUnlocked = locks => locks.get() === 0;
18051
18052    const setTyping = (undoManager, typing, locks) => {
18053      if (isUnlocked(locks)) {
18054        undoManager.typing = typing;
18055      }
18056    };
18057    const endTyping = (undoManager, locks) => {
18058      if (undoManager.typing) {
18059        setTyping(undoManager, false, locks);
18060        undoManager.add();
18061      }
18062    };
18063    const endTypingLevelIgnoreLocks = undoManager => {
18064      if (undoManager.typing) {
18065        undoManager.typing = false;
18066        undoManager.add();
18067      }
18068    };
18069
18070    const beforeChange$1 = (editor, locks, beforeBookmark) => {
18071      if (isUnlocked(locks)) {
18072        beforeBookmark.set(getUndoBookmark(editor.selection));
18073      }
18074    };
18075    const addUndoLevel$1 = (editor, undoManager, index, locks, beforeBookmark, level, event) => {
18076      const currentLevel = createFromEditor(editor);
18077      const newLevel = Tools.extend(level || {}, currentLevel);
18078      if (!isUnlocked(locks) || editor.removed) {
18079        return null;
18080      }
18081      const lastLevel = undoManager.data[index.get()];
18082      if (editor.dispatch('BeforeAddUndo', {
18083          level: newLevel,
18084          lastLevel,
18085          originalEvent: event
18086        }).isDefaultPrevented()) {
18087        return null;
18088      }
18089      if (lastLevel && isEq$1(lastLevel, newLevel)) {
18090        return null;
18091      }
18092      if (undoManager.data[index.get()]) {
18093        beforeBookmark.get().each(bm => {
18094          undoManager.data[index.get()].beforeBookmark = bm;
18095        });
18096      }
18097      const customUndoRedoLevels = getCustomUndoRedoLevels(editor);
18098      if (customUndoRedoLevels) {
18099        if (undoManager.data.length > customUndoRedoLevels) {
18100          for (let i = 0; i < undoManager.data.length - 1; i++) {
18101            undoManager.data[i] = undoManager.data[i + 1];
18102          }
18103          undoManager.data.length--;
18104          index.set(undoManager.data.length);
18105        }
18106      }
18107      newLevel.bookmark = getUndoBookmark(editor.selection);
18108      if (index.get() < undoManager.data.length - 1) {
18109        undoManager.data.length = index.get() + 1;
18110      }
18111      undoManager.data.push(newLevel);
18112      index.set(undoManager.data.length - 1);
18113      const args = {
18114        level: newLevel,
18115        lastLevel,
18116        originalEvent: event
18117      };
18118      if (index.get() > 0) {
18119        editor.setDirty(true);
18120        editor.dispatch('AddUndo', args);
18121        editor.dispatch('change', args);
18122      } else {
18123        editor.dispatch('AddUndo', args);
18124      }
18125      return newLevel;
18126    };
18127    const clear$1 = (editor, undoManager, index) => {
18128      undoManager.data = [];
18129      index.set(0);
18130      undoManager.typing = false;
18131      editor.dispatch('ClearUndos');
18132    };
18133    const extra$1 = (editor, undoManager, index, callback1, callback2) => {
18134      if (undoManager.transact(callback1)) {
18135        const bookmark = undoManager.data[index.get()].bookmark;
18136        const lastLevel = undoManager.data[index.get() - 1];
18137        applyToEditor(editor, lastLevel, true);
18138        if (undoManager.transact(callback2)) {
18139          undoManager.data[index.get() - 1].beforeBookmark = bookmark;
18140        }
18141      }
18142    };
18143    const redo$1 = (editor, index, data) => {
18144      let level;
18145      if (index.get() < data.length - 1) {
18146        index.set(index.get() + 1);
18147        level = data[index.get()];
18148        applyToEditor(editor, level, false);
18149        editor.setDirty(true);
18150        editor.dispatch('Redo', { level });
18151      }
18152      return level;
18153    };
18154    const undo$1 = (editor, undoManager, locks, index) => {
18155      let level;
18156      if (undoManager.typing) {
18157        undoManager.add();
18158        undoManager.typing = false;
18159        setTyping(undoManager, false, locks);
18160      }
18161      if (index.get() > 0) {
18162        index.set(index.get() - 1);
18163        level = undoManager.data[index.get()];
18164        applyToEditor(editor, level, true);
18165        editor.setDirty(true);
18166        editor.dispatch('Undo', { level });
18167      }
18168      return level;
18169    };
18170    const reset$1 = undoManager => {
18171      undoManager.clear();
18172      undoManager.add();
18173    };
18174    const hasUndo$1 = (editor, undoManager, index) => index.get() > 0 || undoManager.typing && undoManager.data[0] && !isEq$1(createFromEditor(editor), undoManager.data[0]);
18175    const hasRedo$1 = (undoManager, index) =>
vendor: 20,423 bytes, lines 18175-18638
18175 index.get() < undoManager.data.length - 1 && !undoManager.typing;
18176    const transact$1 = (undoManager, locks, callback) => {
18177      endTyping(undoManager, locks);
18178      undoManager.beforeChange();
18179      undoManager.ignore(callback);
18180      return undoManager.add();
18181    };
18182    const ignore$1 = (locks, callback) => {
18183      try {
18184        locks.set(locks.get() + 1);
18185        callback();
18186      } finally {
18187        locks.set(locks.get() - 1);
18188      }
18189    };
18190
18191    const addVisualInternal = (editor, elm) => {
18192      const dom = editor.dom;
18193      const scope = isNonNullable(elm) ? elm : editor.getBody();
18194      each$e(dom.select('table,a', scope), matchedElm => {
18195        switch (matchedElm.nodeName) {
18196        case 'TABLE':
18197          const cls = getVisualAidsTableClass(editor);
18198          const value = dom.getAttrib(matchedElm, 'border');
18199          if ((!value || value === '0') && editor.hasVisual) {
18200            dom.addClass(matchedElm, cls);
18201          } else {
18202            dom.removeClass(matchedElm, cls);
18203          }
18204          break;
18205        case 'A':
18206          if (!dom.getAttrib(matchedElm, 'href')) {
18207            const value = dom.getAttrib(matchedElm, 'name') || matchedElm.id;
18208            const cls = getVisualAidsAnchorClass(editor);
18209            if (value && editor.hasVisual) {
18210              dom.addClass(matchedElm, cls);
18211            } else {
18212              dom.removeClass(matchedElm, cls);
18213            }
18214          }
18215          break;
18216        }
18217      });
18218      editor.dispatch('VisualAid', {
18219        element: elm,
18220        hasVisual: editor.hasVisual
18221      });
18222    };
18223
18224    const makePlainAdaptor = editor => ({
18225      init: { bindEvents: noop },
18226      undoManager: {
18227        beforeChange: (locks, beforeBookmark) => beforeChange$1(editor, locks, beforeBookmark),
18228        add: (undoManager, index, locks, beforeBookmark, level, event) => addUndoLevel$1(editor, undoManager, index, locks, beforeBookmark, level, event),
18229        undo: (undoManager, locks, index) => undo$1(editor, undoManager, locks, index),
18230        redo: (index, data) => redo$1(editor, index, data),
18231        clear: (undoManager, index) => clear$1(editor, undoManager, index),
18232        reset: undoManager => reset$1(undoManager),
18233        hasUndo: (undoManager, index) => hasUndo$1(editor, undoManager, index),
18234        hasRedo: (undoManager, index) => hasRedo$1(undoManager, index),
18235        transact: (undoManager, locks, callback) => transact$1(undoManager, locks, callback),
18236        ignore: (locks, callback) => ignore$1(locks, callback),
18237        extra: (undoManager, index, callback1, callback2) => extra$1(editor, undoManager, index, callback1, callback2)
18238      },
18239      formatter: {
18240        match: (name, vars, node, similar) => match$2(editor, name, vars, node, similar),
18241        matchAll: (names, vars) => matchAll(editor, names, vars),
18242        matchNode: (node, name, vars, similar) => matchNode(editor, node, name, vars, similar),
18243        canApply: name => canApply(editor, name),
18244        closest: names => closest(editor, names),
18245        apply: (name, vars, node) => applyFormat$1(editor, name, vars, node),
18246        remove: (name, vars, node, similar) => removeFormat$1(editor, name, vars, node, similar),
18247        toggle: (name, vars, node) => toggle(editor, name, vars, node),
18248        formatChanged: (registeredFormatListeners, formats, callback, similar, vars) => formatChangedInternal(editor, registeredFormatListeners, formats, callback, similar, vars)
18249      },
18250      editor: {
18251        getContent: args => getContentInternal(editor, args),
18252        setContent: (content, args) => setContentInternal(editor, content, args),
18253        insertContent: (value, details) => insertHtmlAtCaret(editor, value, details),
18254        addVisual: elm => addVisualInternal(editor, elm)
18255      },
18256      selection: { getContent: (format, args) => getSelectedContentInternal(editor, format, args) },
18257      autocompleter: {
18258        addDecoration: noop,
18259        removeDecoration: noop
18260      },
18261      raw: { getModel: () => Optional.none() }
18262    });
18263    const makeRtcAdaptor = rtcEditor => {
18264      const defaultVars = vars => isObject(vars) ? vars : {};
18265      const {init, undoManager, formatter, editor, selection, autocompleter, raw} = rtcEditor;
18266      return {
18267        init: { bindEvents: init.bindEvents },
18268        undoManager: {
18269          beforeChange: undoManager.beforeChange,
18270          add: undoManager.add,
18271          undo: undoManager.undo,
18272          redo: undoManager.redo,
18273          clear: undoManager.clear,
18274          reset: undoManager.reset,
18275          hasUndo: undoManager.hasUndo,
18276          hasRedo: undoManager.hasRedo,
18277          transact: (_undoManager, _locks, fn) => undoManager.transact(fn),
18278          ignore: (_locks, callback) => undoManager.ignore(callback),
18279          extra: (_undoManager, _index, callback1, callback2) => undoManager.extra(callback1, callback2)
18280        },
18281        formatter: {
18282          match: (name, vars, _node, similar) => formatter.match(name, defaultVars(vars), similar),
18283          matchAll: formatter.matchAll,
18284          matchNode: formatter.matchNode,
18285          canApply: name => formatter.canApply(name),
18286          closest: names => formatter.closest(names),
18287          apply: (name, vars, _node) => formatter.apply(name, defaultVars(vars)),
18288          remove: (name, vars, _node, _similar) => formatter.remove(name, defaultVars(vars)),
18289          toggle: (name, vars, _node) => formatter.toggle(name, defaultVars(vars)),
18290          formatChanged: (_rfl, formats, callback, similar, vars) => formatter.formatChanged(formats, callback, similar, vars)
18291        },
18292        editor: {
18293          getContent: args => editor.getContent(args),
18294          setContent: (content, args) => {
18295            return {
18296              content: editor.setContent(content, args),
18297              html: ''
18298            };
18299          },
18300          insertContent: (content, _details) => {
18301            editor.insertContent(content);
18302            return '';
18303          },
18304          addVisual: editor.addVisual
18305        },
18306        selection: { getContent: (_format, args) => selection.getContent(args) },
18307        autocompleter: {
18308          addDecoration: autocompleter.addDecoration,
18309          removeDecoration: autocompleter.removeDecoration
18310        },
18311        raw: { getModel: () => Optional.some(raw.getRawModel()) }
18312      };
18313    };
18314    const makeNoopAdaptor = () => {
18315      const nul = constant(null);
18316      const empty = constant('');
18317      return {
18318        init: { bindEvents: noop },
18319        undoManager: {
18320          beforeChange: noop,
18321          add: nul,
18322          undo: nul,
18323          redo: nul,
18324          clear: noop,
18325          reset: noop,
18326          hasUndo: never,
18327          hasRedo: never,
18328          transact: nul,
18329          ignore: noop,
18330          extra: noop
18331        },
18332        formatter: {
18333          match: never,
18334          matchAll: constant([]),
18335          matchNode: constant(undefined),
18336          canApply: never,
18337          closest: empty,
18338          apply: noop,
18339          remove: noop,
18340          toggle: noop,
18341          formatChanged: constant({ unbind: noop })
18342        },
18343        editor: {
18344          getContent: empty,
18345          setContent: constant({
18346            content: '',
18347            html: ''
18348          }),
18349          insertContent: constant(''),
18350          addVisual: noop
18351        },
18352        selection: { getContent: empty },
18353        autocompleter: {
18354          addDecoration: noop,
18355          removeDecoration: noop
18356        },
18357        raw: { getModel: constant(Optional.none()) }
18358      };
18359    };
18360    const isRtc = editor => has$2(editor.plugins, 'rtc');
18361    const getRtcSetup = editor => get$a(editor.plugins, 'rtc').bind(rtcPlugin => Optional.from(rtcPlugin.setup));
18362    const setup$t = editor => {
18363      const editorCast = editor;
18364      return getRtcSetup(editor).fold(() => {
18365        editorCast.rtcInstance = makePlainAdaptor(editor);
18366        return Optional.none();
18367      }, setup => {
18368        editorCast.rtcInstance = makeNoopAdaptor();
18369        return Optional.some(() => setup().then(rtcEditor => {
18370          editorCast.rtcInstance = makeRtcAdaptor(rtcEditor);
18371          return rtcEditor.rtc.isRemote;
18372        }));
18373      });
18374    };
18375    const getRtcInstanceWithFallback = editor => editor.rtcInstance ? editor.rtcInstance : makePlainAdaptor(editor);
18376    const getRtcInstanceWithError = editor => {
18377      const rtcInstance = editor.rtcInstance;
18378      if (!rtcInstance) {
18379        throw new Error('Failed to get RTC instance not yet initialized.');
18380      } else {
18381        return rtcInstance;
18382      }
18383    };
18384    const beforeChange = (editor, locks, beforeBookmark) => {
18385      getRtcInstanceWithError(editor).undoManager.beforeChange(locks, beforeBookmark);
18386    };
18387    const addUndoLevel = (editor, undoManager, index, locks, beforeBookmark, level, event) => getRtcInstanceWithError(editor).undoManager.add(undoManager, index, locks, beforeBookmark, level, event);
18388    const undo = (editor, undoManager, locks, index) => getRtcInstanceWithError(editor).undoManager.undo(undoManager, locks, index);
18389    const redo = (editor, index, data) => getRtcInstanceWithError(editor).undoManager.redo(index, data);
18390    const clear = (editor, undoManager, index) => {
18391      getRtcInstanceWithError(editor).undoManager.clear(undoManager, index);
18392    };
18393    const reset = (editor, undoManager) => {
18394      getRtcInstanceWithError(editor).undoManager.reset(undoManager);
18395    };
18396    const hasUndo = (editor, undoManager, index) => getRtcInstanceWithError(editor).undoManager.hasUndo(undoManager, index);
18397    const hasRedo = (editor, undoManager, index) => getRtcInstanceWithError(editor).undoManager.hasRedo(undoManager, index);
18398    const transact = (editor, undoManager, locks, callback) => getRtcInstanceWithError(editor).undoManager.transact(undoManager, locks, callback);
18399    const ignore = (editor, locks, callback) => {
18400      getRtcInstanceWithError(editor).undoManager.ignore(locks, callback);
18401    };
18402    const extra = (editor, undoManager, index, callback1, callback2) => {
18403      getRtcInstanceWithError(editor).undoManager.extra(undoManager, index, callback1, callback2);
18404    };
18405    const matchFormat = (editor, name, vars, node, similar) => getRtcInstanceWithError(editor).formatter.match(name, vars, node, similar);
18406    const matchAllFormats = (editor, names, vars) => getRtcInstanceWithError(editor).formatter.matchAll(names, vars);
18407    const matchNodeFormat = (editor, node, name, vars, similar) => getRtcInstanceWithError(editor).formatter.matchNode(node, name, vars, similar);
18408    const canApplyFormat = (editor, name) => getRtcInstanceWithError(editor).formatter.canApply(name);
18409    const closestFormat = (editor, names) => getRtcInstanceWithError(editor).formatter.closest(names);
18410    const applyFormat = (editor, name, vars, node) => {
18411      getRtcInstanceWithError(editor).formatter.apply(name, vars, node);
18412    };
18413    const removeFormat = (editor, name, vars, node, similar) => {
18414      getRtcInstanceWithError(editor).formatter.remove(name, vars, node, similar);
18415    };
18416    const toggleFormat = (editor, name, vars, node) => {
18417      getRtcInstanceWithError(editor).formatter.toggle(name, vars, node);
18418    };
18419    const formatChanged = (editor, registeredFormatListeners, formats, callback, similar, vars) => getRtcInstanceWithError(editor).formatter.formatChanged(registeredFormatListeners, formats, callback, similar, vars);
18420    const getContent$2 = (editor, args) => getRtcInstanceWithFallback(editor).editor.getContent(args);
18421    const setContent$2 = (editor, content, args) => getRtcInstanceWithFallback(editor).editor.setContent(content, args);
18422    const insertContent$1 = (editor, value, details) => getRtcInstanceWithFallback(editor).editor.insertContent(value, details);
18423    const getSelectedContent = (editor, format, args) => getRtcInstanceWithError(editor).selection.getContent(format, args);
18424    const addVisual$1 = (editor, elm) => getRtcInstanceWithError(editor).editor.addVisual(elm);
18425    const bindEvents = editor => getRtcInstanceWithError(editor).init.bindEvents();
18426
18427    const getContent$1 = (editor, args = {}) => {
18428      const format = args.format ? args.format : 'html';
18429      return getSelectedContent(editor, format, args);
18430    };
18431
18432    const removeEmpty = text => {
18433      if (text.dom.length === 0) {
18434        remove$4(text);
18435        return Optional.none();
18436      } else {
18437        return Optional.some(text);
18438      }
18439    };
18440    const walkPastBookmark = (node, start) => node.filter(elm => BookmarkManager.isBookmarkNode(elm.dom)).bind(start ? nextSibling : prevSibling);
18441    const merge$1 = (outer, inner, rng, start, schema) => {
18442      const outerElm = outer.dom;
18443      const innerElm = inner.dom;
18444      const oldLength = start ? outerElm.length : innerElm.length;
18445      if (start) {
18446        mergeTextNodes(outerElm, innerElm, schema, false, !start);
18447        rng.setStart(innerElm, oldLength);
18448      } else {
18449        mergeTextNodes(innerElm, outerElm, schema, false, !start);
18450        rng.setEnd(innerElm, oldLength);
18451      }
18452    };
18453    const normalizeTextIfRequired = (inner, start, schema) => {
18454      parent(inner).each(root => {
18455        const text = inner.dom;
18456        if (start && needsToBeNbspLeft(root, CaretPosition(text, 0), schema)) {
18457          normalizeWhitespaceAfter(text, 0, schema);
18458        } else if (!start && needsToBeNbspRight(root, CaretPosition(text, text.length), schema)) {
18459          normalizeWhitespaceBefore(text, text.length, schema);
18460        }
18461      });
18462    };
18463    const mergeAndNormalizeText = (outerNode, innerNode, rng, start, schema) => {
18464      outerNode.bind(outer => {
18465        const normalizer = start ? normalizeWhitespaceBefore : normalizeWhitespaceAfter;
18466        normalizer(outer.dom, start ? outer.dom.length : 0, schema);
18467        return innerNode.filter(isText$c).map(inner => merge$1(outer, inner, rng, start, schema));
18468      }).orThunk(() => {
18469        const innerTextNode = walkPastBookmark(innerNode, start).or(innerNode).filter(isText$c);
18470        return innerTextNode.map(inner => normalizeTextIfRequired(inner, start, schema));
18471      });
18472    };
18473    const rngSetContent = (rng, fragment, schema) => {
18474      const firstChild = Optional.from(fragment.firstChild).map(SugarElement.fromDom);
18475      const lastChild = Optional.from(fragment.lastChild).map(SugarElement.fromDom);
18476      rng.deleteContents();
18477      rng.insertNode(fragment);
18478      const prevText = firstChild.bind(prevSibling).filter(isText$c).bind(removeEmpty);
18479      const nextText = lastChild.bind(nextSibling).filter(isText$c).bind(removeEmpty);
18480      mergeAndNormalizeText(prevText, firstChild, rng, true, schema);
18481      mergeAndNormalizeText(nextText, lastChild, rng, false, schema);
18482      rng.collapse(false);
18483    };
18484    const setupArgs$2 = (args, content) => ({
18485      format: 'html',
18486      ...args,
18487      set: true,
18488      selection: true,
18489      content
18490    });
18491    const cleanContent = (editor, args) => {
18492      if (args.format !== 'raw') {
18493        const rng = editor.selection.getRng();
18494        const contextBlock = editor.dom.getParent(rng.commonAncestorContainer, editor.dom.isBlock);
18495        const contextArgs = contextBlock ? { context: contextBlock.nodeName.toLowerCase() } : {};
18496        const node = editor.parser.parse(args.content, {
18497          forced_root_block: false,
18498          ...contextArgs,
18499          ...args
18500        });
18501        return HtmlSerializer({ validate: false }, editor.schema).serialize(node);
18502      } else {
18503        return args.content;
18504      }
18505    };
18506    const setContent$1 = (editor, content, args = {}) => {
18507      const defaultedArgs = setupArgs$2(args, content);
18508      preProcessSetContent(editor, defaultedArgs).each(updatedArgs => {
18509        const cleanedContent = cleanContent(editor, updatedArgs);
18510        const rng = editor.selection.getRng();
18511        rngSetContent(rng, rng.createContextualFragment(cleanedContent), editor.schema);
18512        editor.selection.setRng(rng);
18513        scrollRangeIntoView(editor, rng);
18514        postProcessSetContent(editor, cleanedContent, updatedArgs);
18515      });
18516    };
18517
18518    const deleteFromCallbackMap = (callbackMap, selector, callback) => {
18519      if (has$2(callbackMap, selector)) {
18520        const newCallbacks = filter$5(callbackMap[selector], cb => cb !== callback);
18521        if (newCallbacks.length === 0) {
18522          delete callbackMap[selector];
18523        } else {
18524          callbackMap[selector] = newCallbacks;
18525        }
18526      }
18527    };
18528    var SelectorChanged = (dom, editor) => {
18529      let selectorChangedData;
18530      let currentSelectors;
18531      const findMatchingNode = (selector, nodes) => find$2(nodes, node => dom.is(node, selector));
18532      const getParents = elem => dom.getParents(elem, undefined, dom.getRoot());
18533      const setup = () => {
18534        selectorChangedData = {};
18535        currentSelectors = {};
18536        editor.on('NodeChange', e => {
18537          const node = e.element;
18538          const parents = getParents(node);
18539          const matchedSelectors = {};
18540          each$d(selectorChangedData, (callbacks, selector) => {
18541            findMatchingNode(selector, parents).each(node => {
18542              if (!currentSelectors[selector]) {
18543                each$e(callbacks, callback => {
18544                  callback(true, {
18545                    node,
18546                    selector,
18547                    parents
18548                  });
18549                });
18550                currentSelectors[selector] = callbacks;
18551              }
18552              matchedSelectors[selector] = callbacks;
18553            });
18554          });
18555          each$d(currentSelectors, (callbacks, selector) => {
18556            if (!matchedSelectors[selector]) {
18557              delete currentSelectors[selector];
18558              each$e(callbacks, callback => {
18559                callback(false, {
18560                  node,
18561                  selector,
18562                  parents
18563                });
18564              });
18565            }
18566          });
18567        });
18568      };
18569      return {
18570        selectorChangedWithUnbind: (selector, callback) => {
18571          if (!selectorChangedData) {
18572            setup();
18573          }
18574          if (!selectorChangedData[selector]) {
18575            selectorChangedData[selector] = [];
18576          }
18577          selectorChangedData[selector].push(callback);
18578          findMatchingNode(selector, getParents(editor.selection.getStart())).each(() => {
18579            currentSelectors[selector] = selectorChangedData[selector];
18580          });
18581          return {
18582            unbind: () => {
18583              deleteFromCallbackMap(selectorChangedData, selector, callback);
18584              deleteFromCallbackMap(currentSelectors, selector, callback);
18585            }
18586          };
18587        }
18588      };
18589    };
18590
18591    const isAttachedToDom = node => {
18592      return !!(node && node.ownerDocument) && contains(SugarElement.fromDom(node.ownerDocument), SugarElement.fromDom(node));
18593    };
18594    const isValidRange = rng => {
18595      if (!rng) {
18596        return false;
18597      } else {
18598        return isAttachedToDom(rng.startContainer) && isAttachedToDom(rng.endContainer);
18599      }
18600    };
18601    const EditorSelection = (dom, win, serializer, editor) => {
18602      let selectedRange;
18603      let explicitRange;
18604      const {selectorChangedWithUnbind} = SelectorChanged(dom, editor);
18605      const setCursorLocation = (node, offset) => {
18606        const rng = dom.createRng();
18607        if (isNonNullable(node) && isNonNullable(offset)) {
18608          rng.setStart(node, offset);
18609          rng.setEnd(node, offset);
18610          setRng(rng);
18611          collapse(false);
18612        } else {
18613          moveEndPoint(dom, rng, editor.getBody(), true);
18614          setRng(rng);
18615        }
18616      };
18617      const getContent = args => getContent$1(editor, args);
18618      const setContent = (content, args) => setContent$1(editor, content, args);
18619      const getStart$1 = real => getStart(editor.getBody(), getRng$1(), real);
18620      const getEnd$1 = real => getEnd(editor.getBody(), getRng$1(), real);
18621      const getBookmark = (type, normalized) => bookmarkManager.getBookmark(type, normalized);
18622      const moveToBookmark = bookmark => bookmarkManager.moveToBookmark(bookmark);
18623      const select$1 = (node, content) => {
18624        select(dom, node, content).each(setRng);
18625        return node;
18626      };
18627      const isCollapsed = () => {
18628        const rng = getRng$1(), sel = getSel();
18629        if (!rng || rng.item) {
18630          return false;
18631        }
18632        if (rng.compareEndPoints) {
18633          return rng.compareEndPoints('StartToEnd', rng) === 0;
18634        }
18635        return !sel || rng.collapsed;
18636      };
18637      const isEditable = () => {
18638        
vendor: 5,378 bytes, lines 18638-18782
18638if (editor.mode.isReadOnly()) {
18639          return false;
18640        }
18641        const rng = getRng$1();
18642        const fakeSelectedElements = editor.getBody().querySelectorAll('[data-mce-selected="1"]');
18643        if (fakeSelectedElements.length > 0) {
18644          return forall(fakeSelectedElements, el => dom.isEditable(el.parentElement));
18645        } else {
18646          return isEditableRange(dom, rng);
18647        }
18648      };
18649      const collapse = toStart => {
18650        const rng = getRng$1();
18651        rng.collapse(!!toStart);
18652        setRng(rng);
18653      };
18654      const getSel = () => win.getSelection ? win.getSelection() : win.document.selection;
18655      const getRng$1 = () => {
18656        let rng;
18657        const tryCompareBoundaryPoints = (how, sourceRange, destinationRange) => {
18658          try {
18659            return sourceRange.compareBoundaryPoints(how, destinationRange);
18660          } catch (_a) {
18661            return -1;
18662          }
18663        };
18664        const doc = win.document;
18665        if (isNonNullable(editor.bookmark) && !hasFocus(editor)) {
18666          const bookmark = getRng(editor);
18667          if (bookmark.isSome()) {
18668            return bookmark.map(r => processRanges(editor, [r])[0]).getOr(doc.createRange());
18669          }
18670        }
18671        try {
18672          const selection = getSel();
18673          if (selection && !isRestrictedNode(selection.anchorNode)) {
18674            if (selection.rangeCount > 0) {
18675              rng = selection.getRangeAt(0);
18676            } else {
18677              rng = doc.createRange();
18678            }
18679            rng = processRanges(editor, [rng])[0];
18680          }
18681        } catch (_a) {
18682        }
18683        if (!rng) {
18684          rng = doc.createRange();
18685        }
18686        if (isDocument$1(rng.startContainer) && rng.collapsed) {
18687          const elm = dom.getRoot();
18688          rng.setStart(elm, 0);
18689          rng.setEnd(elm, 0);
18690        }
18691        if (selectedRange && explicitRange) {
18692          if (tryCompareBoundaryPoints(rng.START_TO_START, rng, selectedRange) === 0 && tryCompareBoundaryPoints(rng.END_TO_END, rng, selectedRange) === 0) {
18693            rng = explicitRange;
18694          } else {
18695            selectedRange = null;
18696            explicitRange = null;
18697          }
18698        }
18699        return rng;
18700      };
18701      const setRng = (rng, forward) => {
18702        if (!isValidRange(rng)) {
18703          return;
18704        }
18705        const sel = getSel();
18706        const evt = editor.dispatch('SetSelectionRange', {
18707          range: rng,
18708          forward
18709        });
18710        rng = evt.range;
18711        if (sel) {
18712          explicitRange = rng;
18713          try {
18714            sel.removeAllRanges();
18715            sel.addRange(rng);
18716          } catch (_a) {
18717          }
18718          if (forward === false && sel.extend) {
18719            sel.collapse(rng.endContainer, rng.endOffset);
18720            sel.extend(rng.startContainer, rng.startOffset);
18721          }
18722          selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
18723        }
18724        if (!rng.collapsed && rng.startContainer === rng.endContainer && (sel === null || sel === void 0 ? void 0 : sel.setBaseAndExtent)) {
18725          if (rng.endOffset - rng.startOffset < 2) {
18726            if (rng.startContainer.hasChildNodes()) {
18727              const node = rng.startContainer.childNodes[rng.startOffset];
18728              if (node && node.nodeName === 'IMG') {
18729                sel.setBaseAndExtent(rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset);
18730                if (sel.anchorNode !== rng.startContainer || sel.focusNode !== rng.endContainer) {
18731                  sel.setBaseAndExtent(node, 0, node, 1);
18732                }
18733              }
18734            }
18735          }
18736        }
18737        editor.dispatch('AfterSetSelectionRange', {
18738          range: rng,
18739          forward
18740        });
18741      };
18742      const setNode = elm => {
18743        setContent(dom.getOuterHTML(elm));
18744        return elm;
18745      };
18746      const getNode$1 = () => getNode(editor.getBody(), getRng$1());
18747      const getSelectedBlocks$1 = (startElm, endElm) => getSelectedBlocks(dom, getRng$1(), startElm, endElm);
18748      const isForward = () => {
18749        const sel = getSel();
18750        const anchorNode = sel === null || sel === void 0 ? void 0 : sel.anchorNode;
18751        const focusNode = sel === null || sel === void 0 ? void 0 : sel.focusNode;
18752        if (!sel || !anchorNode || !focusNode || isRestrictedNode(anchorNode) || isRestrictedNode(focusNode)) {
18753          return true;
18754        }
18755        const anchorRange = dom.createRng();
18756        const focusRange = dom.createRng();
18757        try {
18758          anchorRange.setStart(anchorNode, sel.anchorOffset);
18759          anchorRange.collapse(true);
18760          focusRange.setStart(focusNode, sel.focusOffset);
18761          focusRange.collapse(true);
18762        } catch (_a) {
18763          return true;
18764        }
18765        return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
18766      };
18767      const normalize = () => {
18768        const rng = getRng$1();
18769        const sel = getSel();
18770        if (!hasMultipleRanges(sel) && hasAnyRanges(editor)) {
18771          const normRng = normalize$2(dom, rng);
18772          normRng.each(normRng => {
18773            setRng(normRng, isForward());
18774          });
18775          return normRng.getOr(rng);
18776        }
18777        return rng;
18778      };
18779      const selectorChanged = (selector, callback) => {
18780        selectorChangedWithUnbind(selector, callback);
18781        return exports;
18782      };
vendor: 12,091 bytes, lines 18783-19114
18783      const getScrollContainer = () => {
18784        let scrollContainer;
18785        let node = dom.getRoot();
18786        while (node && node.nodeName !== 'BODY') {
18787          if (node.scrollHeight > node.clientHeight) {
18788            scrollContainer = node;
18789            break;
18790          }
18791          node = node.parentNode;
18792        }
18793        return scrollContainer;
18794      };
18795      const scrollIntoView = (elm, alignToTop) => {
18796        if (isNonNullable(elm)) {
18797          scrollElementIntoView(editor, elm, alignToTop);
18798        } else {
18799          scrollRangeIntoView(editor, getRng$1(), alignToTop);
18800        }
18801      };
18802      const placeCaretAt = (clientX, clientY) => setRng(fromPoint(clientX, clientY, editor.getDoc()));
18803      const getBoundingClientRect = () => {
18804        const rng = getRng$1();
18805        return rng.collapsed ? CaretPosition.fromRangeStart(rng).getClientRects()[0] : rng.getBoundingClientRect();
18806      };
18807      const destroy = () => {
18808        win = selectedRange = explicitRange = null;
18809        controlSelection.destroy();
18810      };
18811      const expand = (options = { type: 'word' }) => setRng(RangeUtils(dom).expand(getRng$1(), options));
18812      const exports = {
18813        dom,
18814        win,
18815        serializer,
18816        editor,
18817        expand,
18818        collapse,
18819        setCursorLocation,
18820        getContent,
18821        setContent,
18822        getBookmark,
18823        moveToBookmark,
18824        select: select$1,
18825        isCollapsed,
18826        isEditable,
18827        isForward,
18828        setNode,
18829        getNode: getNode$1,
18830        getSel,
18831        setRng,
18832        getRng: getRng$1,
18833        getStart: getStart$1,
18834        getEnd: getEnd$1,
18835        getSelectedBlocks: getSelectedBlocks$1,
18836        normalize,
18837        selectorChanged,
18838        selectorChangedWithUnbind,
18839        getScrollContainer,
18840        scrollIntoView,
18841        placeCaretAt,
18842        getBoundingClientRect,
18843        destroy
18844      };
18845      const bookmarkManager = BookmarkManager(exports);
18846      const controlSelection = ControlSelection(exports, editor);
18847      exports.bookmarkManager = bookmarkManager;
18848      exports.controlSelection = controlSelection;
18849      return exports;
18850    };
18851
18852    const addNodeFilter = (settings, htmlParser, schema) => {
18853      htmlParser.addNodeFilter('br', (nodes, _, args) => {
18854        const blockElements = Tools.extend({}, schema.getBlockElements());
18855        const nonEmptyElements = schema.getNonEmptyElements();
18856        const whitespaceElements = schema.getWhitespaceElements();
18857        blockElements.body = 1;
18858        const isBlock = node => node.name in blockElements || isTransparentAstBlock(schema, node);
18859        for (let i = 0, l = nodes.length; i < l; i++) {
18860          let node = nodes[i];
18861          let parent = node.parent;
18862          if (parent && isBlock(parent) && node === parent.lastChild) {
18863            let prev = node.prev;
18864            while (prev) {
18865              const prevName = prev.name;
18866              if (prevName !== 'span' || prev.attr('data-mce-type') !== 'bookmark') {
18867                if (prevName === 'br') {
18868                  node = null;
18869                }
18870                break;
18871              }
18872              prev = prev.prev;
18873            }
18874            if (node) {
18875              node.remove();
18876              if (isEmpty(schema, nonEmptyElements, whitespaceElements, parent)) {
18877                const elementRule = schema.getElementRule(parent.name);
18878                if (elementRule) {
18879                  if (elementRule.removeEmpty) {
18880                    parent.remove();
18881                  } else if (elementRule.paddEmpty) {
18882                    paddEmptyNode(settings, args, isBlock, parent);
18883                  }
18884                }
18885              }
18886            }
18887          } else {
18888            let lastParent = node;
18889            while (parent && parent.firstChild === lastParent && parent.lastChild === lastParent) {
18890              lastParent = parent;
18891              if (blockElements[parent.name]) {
18892                break;
18893              }
18894              parent = parent.parent;
18895            }
18896            if (lastParent === parent) {
18897              const textNode = new AstNode('#text', 3);
18898              textNode.value = nbsp;
18899              node.replace(textNode);
18900            }
18901          }
18902        }
18903      });
18904    };
18905
18906    const register$3 = (htmlParser, settings, dom) => {
18907      htmlParser.addAttributeFilter('data-mce-tabindex', (nodes, name) => {
18908        let i = nodes.length;
18909        while (i--) {
18910          const node = nodes[i];
18911          node.attr('tabindex', node.attr('data-mce-tabindex'));
18912          node.attr(name, null);
18913        }
18914      });
18915      htmlParser.addAttributeFilter('src,href,style', (nodes, name) => {
18916        const internalName = 'data-mce-' + name;
18917        const urlConverter = settings.url_converter;
18918        const urlConverterScope = settings.url_converter_scope;
18919        let i = nodes.length;
18920        while (i--) {
18921          const node = nodes[i];
18922          let value = node.attr(internalName);
18923          if (value !== undefined) {
18924            node.attr(name, value.length > 0 ? value : null);
18925            node.attr(internalName, null);
18926          } else {
18927            value = node.attr(name);
18928            if (name === 'style') {
18929              value = dom.serializeStyle(dom.parseStyle(value), node.name);
18930            } else if (urlConverter) {
18931              value = urlConverter.call(urlConverterScope, value, name, node.name);
18932            }
18933            node.attr(name, value.length > 0 ? value : null);
18934          }
18935        }
18936      });
18937      htmlParser.addAttributeFilter('class', nodes => {
18938        let i = nodes.length;
18939        while (i--) {
18940          const node = nodes[i];
18941          let value = node.attr('class');
18942          if (value) {
18943            value = value.replace(/(?:^|\s)mce-item-\w+(?!\S)/g, '');
18944            node.attr('class', value.length > 0 ? value : null);
18945          }
18946        }
18947      });
18948      htmlParser.addAttributeFilter('data-mce-type', (nodes, name, args) => {
18949        let i = nodes.length;
18950        while (i--) {
18951          const node = nodes[i];
18952          if (node.attr('data-mce-type') === 'bookmark' && !args.cleanup) {
18953            const hasChildren = Optional.from(node.firstChild).exists(firstChild => {
18954              var _a;
18955              return !isZwsp((_a = firstChild.value) !== null && _a !== void 0 ? _a : '');
18956            });
18957            if (hasChildren) {
18958              node.unwrap();
18959            } else {
18960              node.remove();
18961            }
18962          }
18963        }
18964      });
18965      htmlParser.addNodeFilter('script,style', (nodes, name) => {
18966        var _a;
18967        const trim = value => {
18968          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, '');
18969        };
18970        let i = nodes.length;
18971        while (i--) {
18972          const node = nodes[i];
18973          const firstChild = node.firstChild;
18974          const value = (_a = firstChild === null || firstChild === void 0 ? void 0 : firstChild.value) !== null && _a !== void 0 ? _a : '';
18975          if (name === 'script') {
18976            const type = node.attr('type');
18977            if (type) {
18978              node.attr('type', type === 'mce-no/type' ? null : type.replace(/^mce\-/, ''));
18979            }
18980            if (settings.element_format === 'xhtml' && firstChild && value.length > 0) {
18981              firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>';
18982            }
18983          } else {
18984            if (settings.element_format === 'xhtml' && firstChild && value.length > 0) {
18985              firstChild.value = '<!--\n' + trim(value) + '\n-->';
18986            }
18987          }
18988        }
18989      });
18990      htmlParser.addNodeFilter('#comment', nodes => {
18991        let i = nodes.length;
18992        while (i--) {
18993          const node = nodes[i];
18994          const value = node.value;
18995          if (settings.preserve_cdata && (value === null || value === void 0 ? void 0 : value.indexOf('[CDATA[')) === 0) {
18996            node.name = '#cdata';
18997            node.type = 4;
18998            node.value = dom.decode(value.replace(/^\[CDATA\[|\]\]$/g, ''));
18999          } else if ((value === null || value === void 0 ? void 0 : value.indexOf('mce:protected ')) === 0) {
19000            node.name = '#text';
19001            node.type = 3;
19002            node.raw = true;
19003            node.value = unescape(value).substr(14);
19004          }
19005        }
19006      });
19007      htmlParser.addNodeFilter('xml:namespace,input', (nodes, name) => {
19008        let i = nodes.length;
19009        while (i--) {
19010          const node = nodes[i];
19011          if (node.type === 7) {
19012            node.remove();
19013          } else if (node.type === 1) {
19014            if (name === 'input' && !node.attr('type')) {
19015              node.attr('type', 'text');
19016            }
19017          }
19018        }
19019      });
19020      htmlParser.addAttributeFilter('data-mce-type', nodes => {
19021        each$e(nodes, node => {
19022          if (node.attr('data-mce-type') === 'format-caret') {
19023            if (node.isEmpty(htmlParser.schema.getNonEmptyElements())) {
19024              node.remove();
19025            } else {
19026              node.unwrap();
19027            }
19028          }
19029        });
19030      });
19031      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) => {
19032        let i = nodes.length;
19033        while (i--) {
19034          nodes[i].attr(name, null);
19035        }
19036      });
19037      if (settings.remove_trailing_brs) {
19038        addNodeFilter(settings, htmlParser, htmlParser.schema);
19039      }
19040    };
19041    const trimTrailingBr = rootNode => {
19042      const isBr = node => {
19043        return (node === null || node === void 0 ? void 0 : node.name) === 'br';
19044      };
19045      const brNode1 = rootNode.lastChild;
19046      if (isBr(brNode1)) {
19047        const brNode2 = brNode1.prev;
19048        if (isBr(brNode2)) {
19049          brNode1.remove();
19050          brNode2.remove();
19051        }
19052      }
19053    };
19054
19055    const preProcess$1 = (editor, node, args) => {
19056      let oldDoc;
19057      const dom = editor.dom;
19058      let clonedNode = node.cloneNode(true);
19059      const impl = document.implementation;
19060      if (impl.createHTMLDocument) {
19061        const doc = impl.createHTMLDocument('');
19062        Tools.each(clonedNode.nodeName === 'BODY' ? clonedNode.childNodes : [clonedNode], node => {
19063          doc.body.appendChild(doc.importNode(node, true));
19064        });
19065        if (clonedNode.nodeName !== 'BODY') {
19066          clonedNode = doc.body.firstChild;
19067        } else {
19068          clonedNode = doc.body;
19069        }
19070        oldDoc = dom.doc;
19071        dom.doc = doc;
19072      }
19073      firePreProcess(editor, {
19074        ...args,
19075        node: clonedNode
19076      });
19077      if (oldDoc) {
19078        dom.doc = oldDoc;
19079      }
19080      return clonedNode;
19081    };
19082    const shouldFireEvent = (editor, args) => {
19083      return isNonNullable(editor) && editor.hasEventListeners('PreProcess') && !args.no_events;
19084    };
19085    const process$1 = (editor, node, args) => {
19086      return shouldFireEvent(editor, args) ? preProcess$1(editor, node, args) : node;
19087    };
19088
19089    const addTempAttr = (htmlParser, tempAttrs, name) => {
19090      if (Tools.inArray(tempAttrs, name) === -1) {
19091        htmlParser.addAttributeFilter(name, (nodes, name) => {
19092          let i = nodes.length;
19093          while (i--) {
19094            nodes[i].attr(name, null);
19095          }
19096        });
19097        tempAttrs.push(name);
19098      }
19099    };
19100    const postProcess = (editor, args, content) => {
19101      if (!args.no_events && editor) {
19102        const outArgs = firePostProcess(editor, {
19103          ...args,
19104          content
19105        });
19106        return outArgs.content;
19107      } else {
19108        return content;
19109      }
19110    };
19111    const getHtmlFromNode = (dom, node, args) => {
19112      const html = trim$2(args.getInner ? node.innerHTML : dom.getOuterHTML(node));
19113      return args.selection || isWsPreserveElement(SugarElement.fromDom(node)) ? html : Tools.trim(html);
19114    };
vendor: 13,863 bytes, lines 19115-19418
19115    const parseHtml = (htmlParser, html, args) => {
19116      const parserArgs = args.selection ? {
19117        forced_root_block: false,
19118        ...args
19119      } : args;
19120      const rootNode = htmlParser.parse(html, parserArgs);
19121      trimTrailingBr(rootNode);
19122      return rootNode;
19123    };
19124    const serializeNode = (settings, schema, node) => {
19125      const htmlSerializer = HtmlSerializer(settings, schema);
19126      return htmlSerializer.serialize(node);
19127    };
19128    const toHtml = (editor, settings, schema, rootNode, args) => {
19129      const content = serializeNode(settings, schema, rootNode);
19130      return postProcess(editor, args, content);
19131    };
19132    const DomSerializerImpl = (settings, editor) => {
19133      const tempAttrs = ['data-mce-selected'];
19134      const defaultedSettings = {
19135        entity_encoding: 'named',
19136        remove_trailing_brs: true,
19137        pad_empty_with_br: false,
19138        ...settings
19139      };
19140      const dom = editor && editor.dom ? editor.dom : DOMUtils.DOM;
19141      const schema = editor && editor.schema ? editor.schema : Schema(defaultedSettings);
19142      const htmlParser = DomParser(defaultedSettings, schema);
19143      register$3(htmlParser, defaultedSettings, dom);
19144      const serialize = (node, parserArgs = {}) => {
19145        const args = {
19146          format: 'html',
19147          ...parserArgs
19148        };
19149        const targetNode = process$1(editor, node, args);
19150        const html = getHtmlFromNode(dom, targetNode, args);
19151        const rootNode = parseHtml(htmlParser, html, args);
19152        return args.format === 'tree' ? rootNode : toHtml(editor, defaultedSettings, schema, rootNode, args);
19153      };
19154      return {
19155        schema,
19156        addNodeFilter: htmlParser.addNodeFilter,
19157        addAttributeFilter: htmlParser.addAttributeFilter,
19158        serialize: serialize,
19159        addRules: schema.addValidElements,
19160        setRules: schema.setValidElements,
19161        addTempAttr: curry(addTempAttr, htmlParser, tempAttrs),
19162        getTempAttrs: constant(tempAttrs),
19163        getNodeFilters: htmlParser.getNodeFilters,
19164        getAttributeFilters: htmlParser.getAttributeFilters,
19165        removeNodeFilter: htmlParser.removeNodeFilter,
19166        removeAttributeFilter: htmlParser.removeAttributeFilter
19167      };
19168    };
19169
19170    const DomSerializer = (settings, editor) => {
19171      const domSerializer = DomSerializerImpl(settings, editor);
19172      return {
19173        schema: domSerializer.schema,
19174        addNodeFilter: domSerializer.addNodeFilter,
19175        addAttributeFilter: domSerializer.addAttributeFilter,
19176        serialize: domSerializer.serialize,
19177        addRules: domSerializer.addRules,
19178        setRules: domSerializer.setRules,
19179        addTempAttr: domSerializer.addTempAttr,
19180        getTempAttrs: domSerializer.getTempAttrs,
19181        getNodeFilters: domSerializer.getNodeFilters,
19182        getAttributeFilters: domSerializer.getAttributeFilters,
19183        removeNodeFilter: domSerializer.removeNodeFilter,
19184        removeAttributeFilter: domSerializer.removeAttributeFilter
19185      };
19186    };
19187
19188    const defaultFormat$1 = 'html';
19189    const setupArgs$1 = (args, format) => ({
19190      ...args,
19191      format,
19192      get: true,
19193      getInner: true
19194    });
19195    const getContent = (editor, args = {}) => {
19196      const format = args.format ? args.format : defaultFormat$1;
19197      const defaultedArgs = setupArgs$1(args, format);
19198      return preProcessGetContent(editor, defaultedArgs).fold(identity, updatedArgs => {
19199        const content = getContent$2(editor, updatedArgs);
19200        return postProcessGetContent(editor, content, updatedArgs);
19201      });
19202    };
19203
19204    const defaultFormat = 'html';
19205    const setupArgs = (args, content) => ({
19206      format: defaultFormat,
19207      ...args,
19208      set: true,
19209      content
19210    });
19211    const setContent = (editor, content, args = {}) => {
19212      const defaultedArgs = setupArgs(args, content);
19213      return preProcessSetContent(editor, defaultedArgs).map(updatedArgs => {
19214        const result = setContent$2(editor, updatedArgs.content, updatedArgs);
19215        postProcessSetContent(editor, result.html, updatedArgs);
19216        return result.content;
19217      }).getOr(content);
19218    };
19219
19220    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,' + '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(',');
19221    const deprecatedOptions = [];
19222    const removedPlugins = 'bbcode,colorpicker,contextmenu,fullpage,legacyoutput,spellchecker,template,textcolor,rtc'.split(',');
19223    const deprecatedPlugins = [];
19224    const getMatchingOptions = (options, searchingFor) => {
19225      const settingNames = filter$5(searchingFor, setting => has$2(options, setting));
19226      return sort(settingNames);
19227    };
19228    const getRemovedOptions = options => {
19229      const settingNames = getMatchingOptions(options, removedOptions);
19230      const forcedRootBlock = options.forced_root_block;
19231      if (forcedRootBlock === false || forcedRootBlock === '') {
19232        settingNames.push('forced_root_block (false only)');
19233      }
19234      return sort(settingNames);
19235    };
19236    const getDeprecatedOptions = options => getMatchingOptions(options, deprecatedOptions);
19237    const getMatchingPlugins = (options, searchingFor) => {
19238      const plugins = Tools.makeMap(options.plugins, ' ');
19239      const hasPlugin = plugin => has$2(plugins, plugin);
19240      const pluginNames = filter$5(searchingFor, hasPlugin);
19241      return sort(pluginNames);
19242    };
19243    const getRemovedPlugins = options => getMatchingPlugins(options, removedPlugins);
19244    const getDeprecatedPlugins = options => getMatchingPlugins(options, deprecatedPlugins.map(entry => entry.name));
19245    const logRemovedWarnings = (rawOptions, normalizedOptions) => {
19246      const removedOptions = getRemovedOptions(rawOptions);
19247      const removedPlugins = getRemovedPlugins(normalizedOptions);
19248      const hasRemovedPlugins = removedPlugins.length > 0;
19249      const hasRemovedOptions = removedOptions.length > 0;
19250      const isLegacyMobileTheme = normalizedOptions.theme === 'mobile';
19251      if (hasRemovedPlugins || hasRemovedOptions || isLegacyMobileTheme) {
19252        const listJoiner = '\n- ';
19253        const themesMessage = isLegacyMobileTheme ? `\n\nThemes:${ listJoiner }mobile` : '';
19254        const pluginsMessage = hasRemovedPlugins ? `\n\nPlugins:${ listJoiner }${ removedPlugins.join(listJoiner) }` : '';
19255        const optionsMessage = hasRemovedOptions ? `\n\nOptions:${ listJoiner }${ removedOptions.join(listJoiner) }` : '';
19256        console.warn('The following deprecated features are currently enabled and have been removed in TinyMCE 7.0. These features will no longer work and should be removed from the TinyMCE configuration. ' + 'See https://www.tiny.cloud/docs/tinymce/7/migration-from-6x/ for more information.' + themesMessage + pluginsMessage + optionsMessage);
19257      }
19258    };
19259    const getPluginDescription = name => find$2(deprecatedPlugins, entry => entry.name === name).fold(() => name, entry => {
19260      if (entry.replacedWith) {
19261        return `${ name }, replaced by ${ entry.replacedWith }`;
19262      } else {
19263        return name;
19264      }
19265    });
19266    const logDeprecatedWarnings = (rawOptions, normalizedOptions) => {
19267      const deprecatedOptions = getDeprecatedOptions(rawOptions);
19268      const deprecatedPlugins = getDeprecatedPlugins(normalizedOptions);
19269      const hasDeprecatedPlugins = deprecatedPlugins.length > 0;
19270      const hasDeprecatedOptions = deprecatedOptions.length > 0;
19271      if (hasDeprecatedPlugins || hasDeprecatedOptions) {
19272        const listJoiner = '\n- ';
19273        const pluginsMessage = hasDeprecatedPlugins ? `\n\nPlugins:${ listJoiner }${ deprecatedPlugins.map(getPluginDescription).join(listJoiner) }` : '';
19274        const optionsMessage = hasDeprecatedOptions ? `\n\nOptions:${ listJoiner }${ deprecatedOptions.join(listJoiner) }` : '';
19275        console.warn('The following deprecated features are currently enabled but will be removed soon.' + pluginsMessage + optionsMessage);
19276      }
19277    };
19278    const logWarnings = (rawOptions, normalizedOptions) => {
19279      logRemovedWarnings(rawOptions, normalizedOptions);
19280      logDeprecatedWarnings(rawOptions, normalizedOptions);
19281    };
19282
19283    const DOM$8 = DOMUtils.DOM;
19284    const restoreOriginalStyles = editor => {
19285      DOM$8.setStyle(editor.id, 'display', editor.orgDisplay);
19286    };
19287    const safeDestroy = x => Optional.from(x).each(x => x.destroy());
19288    const clearDomReferences = editor => {
19289      const ed = editor;
19290      ed.contentAreaContainer = ed.formElement = ed.container = ed.editorContainer = null;
19291      ed.bodyElement = ed.contentDocument = ed.contentWindow = null;
19292      ed.iframeElement = ed.targetElm = null;
19293      const selection = editor.selection;
19294      if (selection) {
19295        const dom = selection.dom;
19296        ed.selection = selection.win = selection.dom = dom.doc = null;
19297      }
19298    };
19299    const restoreForm = editor => {
19300      const form = editor.formElement;
19301      if (form) {
19302        if (form._mceOldSubmit) {
19303          form.submit = form._mceOldSubmit;
19304          delete form._mceOldSubmit;
19305        }
19306        DOM$8.unbind(form, 'submit reset', editor.formEventDelegate);
19307      }
19308    };
19309    const remove$1 = editor => {
19310      if (!editor.removed) {
19311        const {_selectionOverrides, editorUpload} = editor;
19312        const body = editor.getBody();
19313        const element = editor.getElement();
19314        if (body) {
19315          editor.save({ is_removing: true });
19316        }
19317        editor.removed = true;
19318        editor.unbindAllNativeEvents();
19319        if (editor.hasHiddenInput && isNonNullable(element === null || element === void 0 ? void 0 : element.nextSibling)) {
19320          DOM$8.remove(element.nextSibling);
19321        }
19322        fireRemove(editor);
19323        editor.editorManager.remove(editor);
19324        if (!editor.inline && body) {
19325          restoreOriginalStyles(editor);
19326        }
19327        fireDetach(editor);
19328        DOM$8.remove(editor.getContainer());
19329        safeDestroy(_selectionOverrides);
19330        safeDestroy(editorUpload);
19331        editor.destroy();
19332      }
19333    };
19334    const destroy = (editor, automatic) => {
19335      const {selection, dom} = editor;
19336      if (editor.destroyed) {
19337        return;
19338      }
19339      if (!automatic && !editor.removed) {
19340        editor.remove();
19341        return;
19342      }
19343      if (!automatic) {
19344        editor.editorManager.off('beforeunload', editor._beforeUnload);
19345        if (editor.theme && editor.theme.destroy) {
19346          editor.theme.destroy();
19347        }
19348        safeDestroy(selection);
19349        safeDestroy(dom);
19350      }
19351      restoreForm(editor);
19352      clearDomReferences(editor);
19353      editor.destroyed = true;
19354    };
19355
19356    const CreateIconManager = () => {
19357      const lookup = {};
19358      const add = (id, iconPack) => {
19359        lookup[id] = iconPack;
19360      };
19361      const get = id => {
19362        if (lookup[id]) {
19363          return lookup[id];
19364        } else {
19365          return { icons: {} };
19366        }
19367      };
19368      const has = id => has$2(lookup, id);
19369      return {
19370        add,
19371        get,
19372        has
19373      };
19374    };
19375    const IconManager = CreateIconManager();
19376
19377    const ModelManager = AddOnManager.ModelManager;
19378
19379    const getProp = (propName, elm) => {
19380      const rawElm = elm.dom;
19381      return rawElm[propName];
19382    };
19383    const getComputedSizeProp = (propName, elm) => parseInt(get$7(elm, propName), 10);
19384    const getClientWidth = curry(getProp, 'clientWidth');
19385    const getClientHeight = curry(getProp, 'clientHeight');
19386    const getMarginTop = curry(getComputedSizeProp, 'margin-top');
19387    const getMarginLeft = curry(getComputedSizeProp, 'margin-left');
19388    const getBoundingClientRect = elm => elm.dom.getBoundingClientRect();
19389    const isInsideElementContentArea = (bodyElm, clientX, clientY) => {
19390      const clientWidth = getClientWidth(bodyElm);
19391      const clientHeight = getClientHeight(bodyElm);
19392      return clientX >= 0 && clientY >= 0 && clientX <= clientWidth && clientY <= clientHeight;
19393    };
19394    const transpose = (inline, elm, clientX, clientY) => {
19395      const clientRect = getBoundingClientRect(elm);
19396      const deltaX = inline ? clientRect.left + elm.dom.clientLeft + getMarginLeft(elm) : 0;
19397      const deltaY = inline ? clientRect.top + elm.dom.clientTop + getMarginTop(elm) : 0;
19398      const x = clientX - deltaX;
19399      const y = clientY - deltaY;
19400      return {
19401        x,
19402        y
19403      };
19404    };
19405    const isXYInContentArea = (editor, clientX, clientY) => {
19406      const bodyElm = SugarElement.fromDom(editor.getBody());
19407      const targetElm = editor.inline ? bodyElm : documentElement(bodyElm);
19408      const transposedPoint = transpose(editor.inline, targetElm, clientX, clientY);
19409      return isInsideElementContentArea(targetElm, transposedPoint.x, transposedPoint.y);
19410    };
19411    const fromDomSafe = node => Optional.from(node).map(SugarElement.fromDom);
19412    const isEditorAttachedToDom = editor => {
19413      const rawContainer = editor.inline ? editor.getBody() : editor.getContentAreaContainer();
19414      return fromDomSafe(rawContainer).map(inBody).getOr(false);
19415    };
19416
19417    var NotificationManagerImpl = () => {
19418      const unimplemented = () => {
vendor: 5,830 bytes, lines 19419-19586
19419        throw new Error('Theme did not provide a NotificationManager implementation.');
19420      };
19421      return {
19422        open: unimplemented,
19423        close: unimplemented,
19424        getArgs: unimplemented
19425      };
19426    };
19427
19428    const NotificationManager = editor => {
19429      const notifications = [];
19430      const getImplementation = () => {
19431        const theme = editor.theme;
19432        return theme && theme.getNotificationManagerImpl ? theme.getNotificationManagerImpl() : NotificationManagerImpl();
19433      };
19434      const getTopNotification = () => {
19435        return Optional.from(notifications[0]);
19436      };
19437      const isEqual = (a, b) => {
19438        return a.type === b.type && a.text === b.text && !a.progressBar && !a.timeout && !b.progressBar && !b.timeout;
19439      };
19440      const reposition = () => {
19441        getTopNotification().each(notification => {
19442          notification.reposition();
19443        });
19444      };
19445      const addNotification = notification => {
19446        notifications.push(notification);
19447      };
19448      const closeNotification = notification => {
19449        findIndex$2(notifications, otherNotification => {
19450          return otherNotification === notification;
19451        }).each(index => {
19452          notifications.splice(index, 1);
19453        });
19454      };
19455      const open = (spec, fireEvent = true) => {
19456        if (editor.removed || !isEditorAttachedToDom(editor)) {
19457          return {};
19458        }
19459        if (fireEvent) {
19460          editor.dispatch('BeforeOpenNotification', { notification: spec });
19461        }
19462        return find$2(notifications, notification => {
19463          return isEqual(getImplementation().getArgs(notification), spec);
19464        }).getOrThunk(() => {
19465          editor.editorManager.setActive(editor);
19466          const notification = getImplementation().open(spec, () => {
19467            closeNotification(notification);
19468          }, () => hasEditorOrUiFocus(editor));
19469          addNotification(notification);
19470          reposition();
19471          editor.dispatch('OpenNotification', { notification: { ...notification } });
19472          return notification;
19473        });
19474      };
19475      const close = () => {
19476        getTopNotification().each(notification => {
19477          getImplementation().close(notification);
19478          closeNotification(notification);
19479          reposition();
19480        });
19481      };
19482      const getNotifications = constant(notifications);
19483      const registerEvents = editor => {
19484        editor.on('SkinLoaded', () => {
19485          const serviceMessage = getServiceMessage(editor);
19486          if (serviceMessage) {
19487            open({
19488              text: serviceMessage,
19489              type: 'warning',
19490              timeout: 0
19491            }, false);
19492          }
19493          reposition();
19494        });
19495        editor.on('show ResizeEditor ResizeWindow NodeChange ToggleView FullscreenStateChanged', () => {
19496          requestAnimationFrame(reposition);
19497        });
19498        editor.on('remove', () => {
19499          each$e(notifications.slice(), notification => {
19500            getImplementation().close(notification);
19501          });
19502        });
19503        editor.on('keydown', e => {
19504          var _a;
19505          const isF12 = ((_a = e.key) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'f12' || e.keyCode === 123;
19506          if (e.altKey && isF12) {
19507            e.preventDefault();
19508            getTopNotification().map(notificationApi => SugarElement.fromDom(notificationApi.getEl())).each(elm => focus$1(elm));
19509          }
19510        });
19511      };
19512      registerEvents(editor);
19513      return {
19514        open,
19515        close,
19516        getNotifications
19517      };
19518    };
19519
19520    const PluginManager = AddOnManager.PluginManager;
19521
19522    const ThemeManager = AddOnManager.ThemeManager;
19523
19524    var WindowManagerImpl = () => {
19525      const unimplemented = () => {
19526        throw new Error('Theme did not provide a WindowManager implementation.');
19527      };
19528      return {
19529        open: unimplemented,
19530        openUrl: unimplemented,
19531        alert: unimplemented,
19532        confirm: unimplemented,
19533        close: unimplemented
19534      };
19535    };
19536
19537    const WindowManager = editor => {
19538      let dialogs = [];
19539      const getImplementation = () => {
19540        const theme = editor.theme;
19541        return theme && theme.getWindowManagerImpl ? theme.getWindowManagerImpl() : WindowManagerImpl();
19542      };
19543      const funcBind = (scope, f) => {
19544        return (...args) => {
19545          return f ? f.apply(scope, args) : undefined;
19546        };
19547      };
19548      const fireOpenEvent = dialog => {
19549        editor.dispatch('OpenWindow', { dialog });
19550      };
19551      const fireCloseEvent = dialog => {
19552        editor.dispatch('CloseWindow', { dialog });
19553      };
19554      const addDialog = dialog => {
19555        dialogs.push(dialog);
19556        fireOpenEvent(dialog);
19557      };
19558      const closeDialog = dialog => {
19559        fireCloseEvent(dialog);
19560        dialogs = filter$5(dialogs, otherDialog => {
19561          return otherDialog !== dialog;
19562        });
19563        if (dialogs.length === 0) {
19564          editor.focus();
19565        }
19566      };
19567      const getTopDialog = () => {
19568        return Optional.from(dialogs[dialogs.length - 1]);
19569      };
19570      const storeSelectionAndOpenDialog = openDialog => {
19571        editor.editorManager.setActive(editor);
19572        store(editor);
19573        editor.ui.show();
19574        const dialog = openDialog();
19575        addDialog(dialog);
19576        return dialog;
19577      };
19578      const open = (args, params) => {
19579        return storeSelectionAndOpenDialog(() => getImplementation().open(args, params, closeDialog));
19580      };
19581      const openUrl = args => {
19582        return storeSelectionAndOpenDialog(() => getImplementation().openUrl(args, closeDialog));
19583      };
19584      const alert = (message, callback, scope) => {
19585        const windowManagerImpl = getImplementation();
19586        windowManagerImpl.alert(message, funcBind(scope ? scope : windowManagerImpl, 
vendor: 12,329 bytes, lines 19586-19948
19586callback));
19587      };
19588      const confirm = (message, callback, scope) => {
19589        const windowManagerImpl = getImplementation();
19590        windowManagerImpl.confirm(message, funcBind(scope ? scope : windowManagerImpl, callback));
19591      };
19592      const close = () => {
19593        getTopDialog().each(dialog => {
19594          getImplementation().close(dialog);
19595          closeDialog(dialog);
19596        });
19597      };
19598      editor.on('remove', () => {
19599        each$e(dialogs, dialog => {
19600          getImplementation().close(dialog);
19601        });
19602      });
19603      return {
19604        open,
19605        openUrl,
19606        alert,
19607        confirm,
19608        close
19609      };
19610    };
19611
19612    const displayNotification = (editor, message) => {
19613      editor.notificationManager.open({
19614        type: 'error',
19615        text: message
19616      });
19617    };
19618    const displayError = (editor, message) => {
19619      if (editor._skinLoaded) {
19620        displayNotification(editor, message);
19621      } else {
19622        editor.on('SkinLoaded', () => {
19623          displayNotification(editor, message);
19624        });
19625      }
19626    };
19627    const uploadError = (editor, message) => {
19628      displayError(editor, I18n.translate([
19629        'Failed to upload image: {0}',
19630        message
19631      ]));
19632    };
19633    const logError = (editor, errorType, msg) => {
19634      fireError(editor, errorType, { message: msg });
19635      console.error(msg);
19636    };
19637    const createLoadError = (type, url, name) => name ? `Failed to load ${ type }: ${ name } from url ${ url }` : `Failed to load ${ type } url: ${ url }`;
19638    const pluginLoadError = (editor, url, name) => {
19639      logError(editor, 'PluginLoadError', createLoadError('plugin', url, name));
19640    };
19641    const iconsLoadError = (editor, url, name) => {
19642      logError(editor, 'IconsLoadError', createLoadError('icons', url, name));
19643    };
19644    const languageLoadError = (editor, url, name) => {
19645      logError(editor, 'LanguageLoadError', createLoadError('language', url, name));
19646    };
19647    const themeLoadError = (editor, url, name) => {
19648      logError(editor, 'ThemeLoadError', createLoadError('theme', url, name));
19649    };
19650    const modelLoadError = (editor, url, name) => {
19651      logError(editor, 'ModelLoadError', createLoadError('model', url, name));
19652    };
19653    const pluginInitError = (editor, name, err) => {
19654      const message = I18n.translate([
19655        'Failed to initialize plugin: {0}',
19656        name
19657      ]);
19658      fireError(editor, 'PluginLoadError', { message });
19659      initError(message, err);
19660      displayError(editor, message);
19661    };
19662    const initError = (message, ...x) => {
19663      const console = window.console;
19664      if (console) {
19665        if (console.error) {
19666          console.error(message, ...x);
19667        } else {
19668          console.log(message, ...x);
19669        }
19670      }
19671    };
19672
19673    const removeFakeSelection = editor => {
19674      Optional.from(editor.selection.getNode()).each(elm => {
19675        elm.removeAttribute('data-mce-selected');
19676      });
19677    };
19678    const setEditorCommandState = (editor, cmd, state) => {
19679      try {
19680        editor.getDoc().execCommand(cmd, false, String(state));
19681      } catch (_a) {
19682      }
19683    };
19684    const setCommonEditorCommands = (editor, state) => {
19685      setEditorCommandState(editor, 'StyleWithCSS', state);
19686      setEditorCommandState(editor, 'enableInlineTableEditing', state);
19687      setEditorCommandState(editor, 'enableObjectResizing', state);
19688    };
19689    const restoreFakeSelection = editor => {
19690      editor.selection.setRng(editor.selection.getRng());
19691    };
19692    const toggleClass = (elm, cls, state) => {
19693      if (has(elm, cls) && !state) {
19694        remove$6(elm, cls);
19695      } else if (state) {
19696        add$2(elm, cls);
19697      }
19698    };
19699    const disableEditor = editor => {
19700      const body = SugarElement.fromDom(editor.getBody());
19701      toggleClass(body, 'mce-content-readonly', true);
19702      editor.selection.controlSelection.hideResizeRect();
19703      editor._selectionOverrides.hideFakeCaret();
19704      removeFakeSelection(editor);
19705    };
19706    const enableEditor = editor => {
19707      const body = SugarElement.fromDom(editor.getBody());
19708      toggleClass(body, 'mce-content-readonly', false);
19709      if (editor.hasEditableRoot()) {
19710        set$3(body, true);
19711      }
19712      setCommonEditorCommands(editor, false);
19713      if (hasEditorOrUiFocus(editor)) {
19714        editor.focus();
19715      }
19716      restoreFakeSelection(editor);
19717      editor.nodeChanged();
19718    };
19719
19720    const isDisabled = editor => isDisabled$1(editor);
19721    const internalContentEditableAttr = 'data-mce-contenteditable';
19722    const switchOffContentEditableTrue = elm => {
19723      each$e(descendants(elm, '*[contenteditable="true"]'), elm => {
19724        set$4(elm, internalContentEditableAttr, 'true');
19725        set$3(elm, false);
19726      });
19727    };
19728    const switchOnContentEditableTrue = elm => {
19729      each$e(descendants(elm, `*[${ internalContentEditableAttr }="true"]`), elm => {
19730        remove$9(elm, internalContentEditableAttr);
19731        set$3(elm, true);
19732      });
19733    };
19734    const toggleDisabled = (editor, state) => {
19735      const body = SugarElement.fromDom(editor.getBody());
19736      if (state) {
19737        disableEditor(editor);
19738        set$3(body, false);
19739        switchOffContentEditableTrue(body);
19740      } else {
19741        switchOnContentEditableTrue(body);
19742        enableEditor(editor);
19743      }
19744    };
19745    const registerDisabledContentFilters = editor => {
19746      if (editor.serializer) {
19747        registerFilters(editor);
19748      } else {
19749        editor.on('PreInit', () => {
19750          registerFilters(editor);
19751        });
19752      }
19753    };
19754    const registerFilters = editor => {
19755      editor.parser.addAttributeFilter('contenteditable', nodes => {
19756        if (isDisabled(editor)) {
19757          each$e(nodes, node => {
19758            node.attr(internalContentEditableAttr, node.attr('contenteditable'));
19759            node.attr('contenteditable', 'false');
19760          });
19761        }
19762      });
19763      editor.serializer.addAttributeFilter(internalContentEditableAttr, nodes => {
19764        if (isDisabled(editor)) {
19765          each$e(nodes, node => {
19766            node.attr('contenteditable', node.attr(internalContentEditableAttr));
19767          });
19768        }
19769      });
19770      editor.serializer.addTempAttr(internalContentEditableAttr);
19771    };
19772    const isClickEvent = e => e.type === 'click';
19773    const allowedEvents = ['copy'];
19774    const isAllowedEventInDisabledMode = e => contains$2(allowedEvents, e.type);
19775    const getAnchorHrefOpt = (editor, elm) => {
19776      const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody()));
19777      return closest$3(elm, 'a', isRoot).bind(a => getOpt(a, 'href'));
19778    };
19779    const processDisabledEvents = (editor, e) => {
19780      if (isClickEvent(e) && !VK.metaKeyPressed(e)) {
19781        const elm = SugarElement.fromDom(e.target);
19782        getAnchorHrefOpt(editor, elm).each(href => {
19783          e.preventDefault();
19784          if (/^#/.test(href)) {
19785            const targetEl = editor.dom.select(`${ href },[name="${ removeLeading(href, '#') }"]`);
19786            if (targetEl.length) {
19787              editor.selection.scrollIntoView(targetEl[0], true);
19788            }
19789          } else {
19790            window.open(href, '_blank', 'rel=noopener noreferrer,menubar=yes,toolbar=yes,location=yes,status=yes,resizable=yes,scrollbars=yes');
19791          }
19792        });
19793      } else if (isAllowedEventInDisabledMode(e)) {
19794        editor.dispatch(e.type, e);
19795      }
19796    };
19797    const registerDisabledModeEventHandlers = editor => {
19798      editor.on('ShowCaret ObjectSelected', e => {
19799        if (isDisabled(editor)) {
19800          e.preventDefault();
19801        }
19802      });
19803      editor.on('DisabledStateChange', e => {
19804        if (!e.isDefaultPrevented()) {
19805          toggleDisabled(editor, e.state);
19806        }
19807      });
19808    };
19809    const registerEventsAndFilters$1 = editor => {
19810      registerDisabledContentFilters(editor);
19811      registerDisabledModeEventHandlers(editor);
19812    };
19813
19814    const isContentCssSkinName = url => /^[a-z0-9\-]+$/i.test(url);
19815    const toContentSkinResourceName = url => 'content/' + url + '/content.css';
19816    const isBundledCssSkinName = url => tinymce.Resource.has(toContentSkinResourceName(url));
19817    const getContentCssUrls = editor => {
19818      return transformToUrls(editor, getContentCss(editor));
19819    };
19820    const getFontCssUrls = editor => {
19821      return transformToUrls(editor, getFontCss(editor));
19822    };
19823    const transformToUrls = (editor, cssLinks) => {
19824      const skinUrl = editor.editorManager.baseURL + '/skins/content';
19825      const suffix = editor.editorManager.suffix;
19826      const contentCssFile = `content${ suffix }.css`;
19827      return map$3(cssLinks, url => {
19828        if (isBundledCssSkinName(url)) {
19829          return url;
19830        } else if (isContentCssSkinName(url) && !editor.inline) {
19831          return `${ skinUrl }/${ url }/${ contentCssFile }`;
19832        } else {
19833          return editor.documentBaseURI.toAbsolute(url);
19834        }
19835      });
19836    };
19837    const appendContentCssFromSettings = editor => {
19838      editor.contentCSS = editor.contentCSS.concat(getContentCssUrls(editor), getFontCssUrls(editor));
19839    };
19840
19841    const getAllImages = elm => {
19842      return elm ? from(elm.getElementsByTagName('img')) : [];
19843    };
19844    const ImageScanner = (uploadStatus, blobCache) => {
19845      const cachedPromises = {};
19846      const findAll = (elm, predicate = always) => {
19847        const images = filter$5(getAllImages(elm), img => {
19848          const src = img.src;
19849          if (img.hasAttribute('data-mce-bogus')) {
19850            return false;
19851          }
19852          if (img.hasAttribute('data-mce-placeholder')) {
19853            return false;
19854          }
19855          if (!src || src === Env.transparentSrc) {
19856            return false;
19857          }
19858          if (startsWith(src, 'blob:')) {
19859            return !uploadStatus.isUploaded(src) && predicate(img);
19860          }
19861          if (startsWith(src, 'data:')) {
19862            return predicate(img);
19863          }
19864          return false;
19865        });
19866        const promises = map$3(images, img => {
19867          const imageSrc = img.src;
19868          if (has$2(cachedPromises, imageSrc)) {
19869            return cachedPromises[imageSrc].then(imageInfo => {
19870              if (isString(imageInfo)) {
19871                return imageInfo;
19872              } else {
19873                return {
19874                  image: img,
19875                  blobInfo: imageInfo.blobInfo
19876                };
19877              }
19878            });
19879          } else {
19880            const newPromise = imageToBlobInfo(blobCache, imageSrc).then(blobInfo => {
19881              delete cachedPromises[imageSrc];
19882              return {
19883                image: img,
19884                blobInfo
19885              };
19886            }).catch(error => {
19887              delete cachedPromises[imageSrc];
19888              return error;
19889            });
19890            cachedPromises[imageSrc] = newPromise;
19891            return newPromise;
19892          }
19893        });
19894        return Promise.all(promises);
19895      };
19896      return { findAll };
19897    };
19898
19899    const UploadStatus = () => {
19900      const PENDING = 1, UPLOADED = 2;
19901      let blobUriStatuses = {};
19902      const createStatus = (status, resultUri) => {
19903        return {
19904          status,
19905          resultUri
19906        };
19907      };
19908      const hasBlobUri = blobUri => {
19909        return blobUri in blobUriStatuses;
19910      };
19911      const getResultUri = blobUri => {
19912        const result = blobUriStatuses[blobUri];
19913        return result ? result.resultUri : null;
19914      };
19915      const isPending = blobUri => {
19916        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === PENDING : false;
19917      };
19918      const isUploaded = blobUri => {
19919        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === UPLOADED : false;
19920      };
19921      const markPending = blobUri => {
19922        blobUriStatuses[blobUri] = createStatus(PENDING, null);
19923      };
19924      const markUploaded = (blobUri, resultUri) => {
19925        blobUriStatuses[blobUri] = createStatus(UPLOADED, resultUri);
19926      };
19927      const removeFailed = blobUri => {
19928        delete blobUriStatuses[blobUri];
19929      };
19930      const destroy = () => {
19931        blobUriStatuses = {};
19932      };
19933      return {
19934        hasBlobUri,
19935        getResultUri,
19936        isPending,
19937        isUploaded,
19938        markPending,
19939        markUploaded,
19940        removeFailed,
19941        destroy
19942      };
19943    };
19944
19945    let count = 0;
19946    const seed = () => {
19947      const rnd = () => {
19948        return Math.round(
vendor: 11,181 bytes, lines 19948-20238
19948random() * 4294967295).toString(36);
19949      };
19950      const now = new Date().getTime();
19951      return 's' + now.toString(36) + rnd() + rnd() + rnd();
19952    };
19953    const uuid = prefix => {
19954      return prefix + count++ + seed();
19955    };
19956
19957    const BlobCache = () => {
19958      let cache = [];
19959      const mimeToExt = mime => {
19960        const mimes = {
19961          'image/jpeg': 'jpg',
19962          'image/jpg': 'jpg',
19963          'image/gif': 'gif',
19964          'image/png': 'png',
19965          'image/apng': 'apng',
19966          'image/avif': 'avif',
19967          'image/svg+xml': 'svg',
19968          'image/webp': 'webp',
19969          'image/bmp': 'bmp',
19970          'image/tiff': 'tiff'
19971        };
19972        return mimes[mime.toLowerCase()] || 'dat';
19973      };
19974      const create = (o, blob, base64, name, filename) => {
19975        if (isString(o)) {
19976          const id = o;
19977          return toBlobInfo({
19978            id,
19979            name,
19980            filename,
19981            blob: blob,
19982            base64: base64
19983          });
19984        } else if (isObject(o)) {
19985          return toBlobInfo(o);
19986        } else {
19987          throw new Error('Unknown input type');
19988        }
19989      };
19990      const toBlobInfo = o => {
19991        if (!o.blob || !o.base64) {
19992          throw new Error('blob and base64 representations of the image are required for BlobInfo to be created');
19993        }
19994        const id = o.id || uuid('blobid');
19995        const name = o.name || id;
19996        const blob = o.blob;
19997        return {
19998          id: constant(id),
19999          name: constant(name),
20000          filename: constant(o.filename || name + '.' + mimeToExt(blob.type)),
20001          blob: constant(blob),
20002          base64: constant(o.base64),
20003          blobUri: constant(o.blobUri || URL.createObjectURL(blob)),
20004          uri: constant(o.uri)
20005        };
20006      };
20007      const add = blobInfo => {
20008        if (!get(blobInfo.id())) {
20009          cache.push(blobInfo);
20010        }
20011      };
20012      const findFirst = predicate => find$2(cache, predicate).getOrUndefined();
20013      const get = id => findFirst(cachedBlobInfo => cachedBlobInfo.id() === id);
20014      const getByUri = blobUri => findFirst(blobInfo => blobInfo.blobUri() === blobUri);
20015      const getByData = (base64, type) => findFirst(blobInfo => blobInfo.base64() === base64 && blobInfo.blob().type === type);
20016      const removeByUri = blobUri => {
20017        cache = filter$5(cache, blobInfo => {
20018          if (blobInfo.blobUri() === blobUri) {
20019            URL.revokeObjectURL(blobInfo.blobUri());
20020            return false;
20021          }
20022          return true;
20023        });
20024      };
20025      const destroy = () => {
20026        each$e(cache, cachedBlobInfo => {
20027          URL.revokeObjectURL(cachedBlobInfo.blobUri());
20028        });
20029        cache = [];
20030      };
20031      return {
20032        create,
20033        add,
20034        get,
20035        getByUri,
20036        getByData,
20037        findFirst,
20038        removeByUri,
20039        destroy
20040      };
20041    };
20042
20043    const Uploader = (uploadStatus, settings) => {
20044      const pendingPromises = {};
20045      const pathJoin = (path1, path2) => {
20046        if (path1) {
20047          return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '');
20048        }
20049        return path2;
20050      };
20051      const defaultHandler = (blobInfo, progress) => new Promise((success, failure) => {
20052        const xhr = new XMLHttpRequest();
20053        xhr.open('POST', settings.url);
20054        xhr.withCredentials = settings.credentials;
20055        xhr.upload.onprogress = e => {
20056          progress(e.loaded / e.total * 100);
20057        };
20058        xhr.onerror = () => {
20059          failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
20060        };
20061        xhr.onload = () => {
20062          if (xhr.status < 200 || xhr.status >= 300) {
20063            failure('HTTP Error: ' + xhr.status);
20064            return;
20065          }
20066          const json = JSON.parse(xhr.responseText);
20067          if (!json || !isString(json.location)) {
20068            failure('Invalid JSON: ' + xhr.responseText);
20069            return;
20070          }
20071          success(pathJoin(settings.basePath, json.location));
20072        };
20073        const formData = new FormData();
20074        formData.append('file', blobInfo.blob(), blobInfo.filename());
20075        xhr.send(formData);
20076      });
20077      const uploadHandler = isFunction(settings.handler) ? settings.handler : defaultHandler;
20078      const noUpload = () => new Promise(resolve => {
20079        resolve([]);
20080      });
20081      const handlerSuccess = (blobInfo, url) => ({
20082        url,
20083        blobInfo,
20084        status: true
20085      });
20086      const handlerFailure = (blobInfo, error) => ({
20087        url: '',
20088        blobInfo,
20089        status: false,
20090        error
20091      });
20092      const resolvePending = (blobUri, result) => {
20093        Tools.each(pendingPromises[blobUri], resolve => {
20094          resolve(result);
20095        });
20096        delete pendingPromises[blobUri];
20097      };
20098      const uploadBlobInfo = (blobInfo, handler, openNotification) => {
20099        uploadStatus.markPending(blobInfo.blobUri());
20100        return new Promise(resolve => {
20101          let notification;
20102          let progress;
20103          try {
20104            const closeNotification = () => {
20105              if (notification) {
20106                notification.close();
20107                progress = noop;
20108              }
20109            };
20110            const success = url => {
20111              closeNotification();
20112              uploadStatus.markUploaded(blobInfo.blobUri(), url);
20113              resolvePending(blobInfo.blobUri(), handlerSuccess(blobInfo, url));
20114              resolve(handlerSuccess(blobInfo, url));
20115            };
20116            const failure = error => {
20117              closeNotification();
20118              uploadStatus.removeFailed(blobInfo.blobUri());
20119              resolvePending(blobInfo.blobUri(), handlerFailure(blobInfo, error));
20120              resolve(handlerFailure(blobInfo, error));
20121            };
20122            progress = percent => {
20123              if (percent < 0 || percent > 100) {
20124                return;
20125              }
20126              Optional.from(notification).orThunk(() => Optional.from(openNotification).map(apply$1)).each(n => {
20127                notification = n;
20128                n.progressBar.value(percent);
20129              });
20130            };
20131            handler(blobInfo, progress).then(success, err => {
20132              failure(isString(err) ? { message: err } : err);
20133            });
20134          } catch (ex) {
20135            resolve(handlerFailure(blobInfo, ex));
20136          }
20137        });
20138      };
20139      const isDefaultHandler = handler => handler === defaultHandler;
20140      const pendingUploadBlobInfo = blobInfo => {
20141        const blobUri = blobInfo.blobUri();
20142        return new Promise(resolve => {
20143          pendingPromises[blobUri] = pendingPromises[blobUri] || [];
20144          pendingPromises[blobUri].push(resolve);
20145        });
20146      };
20147      const uploadBlobs = (blobInfos, openNotification) => {
20148        blobInfos = Tools.grep(blobInfos, blobInfo => !uploadStatus.isUploaded(blobInfo.blobUri()));
20149        return Promise.all(Tools.map(blobInfos, blobInfo => uploadStatus.isPending(blobInfo.blobUri()) ? pendingUploadBlobInfo(blobInfo) : uploadBlobInfo(blobInfo, uploadHandler, openNotification)));
20150      };
20151      const upload = (blobInfos, openNotification) => !settings.url && isDefaultHandler(uploadHandler) ? noUpload() : uploadBlobs(blobInfos, openNotification);
20152      return { upload };
20153    };
20154
20155    const openNotification = editor => () => editor.notificationManager.open({
20156      text: editor.translate('Image uploading...'),
20157      type: 'info',
20158      timeout: -1,
20159      progressBar: true
20160    });
20161    const createUploader = (editor, uploadStatus) => Uploader(uploadStatus, {
20162      url: getImageUploadUrl(editor),
20163      basePath: getImageUploadBasePath(editor),
20164      credentials: getImagesUploadCredentials(editor),
20165      handler: getImagesUploadHandler(editor)
20166    });
20167    const ImageUploader = editor => {
20168      const uploadStatus = UploadStatus();
20169      const uploader = createUploader(editor, uploadStatus);
20170      return { upload: (blobInfos, showNotification = true) => uploader.upload(blobInfos, showNotification ? openNotification(editor) : undefined) };
20171    };
20172
20173    const isEmptyForPadding = (editor, element) => editor.dom.isEmpty(element.dom) && isNonNullable(editor.schema.getTextBlockElements()[name(element)]);
20174    const addPaddingToEmpty = editor => element => {
20175      if (isEmptyForPadding(editor, element)) {
20176        append$1(element, SugarElement.fromHtml('<br data-mce-bogus="1" />'));
20177      }
20178    };
20179    const EditorUpload = editor => {
20180      const blobCache = BlobCache();
20181      let uploader, imageScanner;
20182      const uploadStatus = UploadStatus();
20183      const urlFilters = [];
20184      const aliveGuard = callback => {
20185        return result => {
20186          if (editor.selection) {
20187            return callback(result);
20188          }
20189          return [];
20190        };
20191      };
20192      const cacheInvalidator = url => url + (url.indexOf('?') === -1 ? '?' : '&') + new Date().getTime();
20193      const replaceString = (content, search, replace) => {
20194        let index = 0;
20195        do {
20196          index = content.indexOf(search, index);
20197          if (index !== -1) {
20198            content = content.substring(0, index) + replace + content.substr(index + search.length);
20199            index += replace.length - search.length + 1;
20200          }
20201        } while (index !== -1);
20202        return content;
20203      };
20204      const replaceImageUrl = (content, targetUrl, replacementUrl) => {
20205        const replacementString = `src="${ replacementUrl }"${ replacementUrl === Env.transparentSrc ? ' data-mce-placeholder="1"' : '' }`;
20206        content = replaceString(content, `src="${ targetUrl }"`, replacementString);
20207        content = replaceString(content, 'data-mce-src="' + targetUrl + '"', 'data-mce-src="' + replacementUrl + '"');
20208        return content;
20209      };
20210      const replaceUrlInUndoStack = (targetUrl, replacementUrl) => {
20211        each$e(editor.undoManager.data, level => {
20212          if (level.type === 'fragmented') {
20213            level.fragments = map$3(level.fragments, fragment => replaceImageUrl(fragment, targetUrl, replacementUrl));
20214          } else {
20215            level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
20216          }
20217        });
20218      };
20219      const replaceImageUriInView = (image, resultUri) => {
20220        const src = editor.convertURL(resultUri, 'src');
20221        replaceUrlInUndoStack(image.src, resultUri);
20222        setAll$1(SugarElement.fromDom(image), {
20223          'src': shouldReuseFileName(editor) ? cacheInvalidator(resultUri) : resultUri,
20224          'data-mce-src': src
20225        });
20226      };
20227      const uploadImages = () => {
20228        if (!uploader) {
20229          uploader = createUploader(editor, uploadStatus);
20230        }
20231        return scanForImages().then(aliveGuard(imageInfos => {
20232          const blobInfos = map$3(imageInfos, imageInfo => imageInfo.blobInfo);
20233          return uploader.upload(blobInfos, openNotification(editor)).then(aliveGuard(result => {
20234            const imagesToRemove = [];
20235            let shouldDispatchChange = false;
20236            const filteredResult = map$3(result, (uploadInfo, index) => {
20237              const {blobInfo, image} = imageInfos[index];
20238              let removed = false;
vendor: 5,955 bytes, lines 20239-20410
20239              if (uploadInfo.status && shouldReplaceBlobUris(editor)) {
20240                if (uploadInfo.url && !contains$1(image.src, uploadInfo.url)) {
20241                  shouldDispatchChange = true;
20242                }
20243                blobCache.removeByUri(image.src);
20244                if (isRtc(editor)) ; else {
20245                  replaceImageUriInView(image, uploadInfo.url);
20246                }
20247              } else if (uploadInfo.error) {
20248                if (uploadInfo.error.remove) {
20249                  replaceUrlInUndoStack(image.src, Env.transparentSrc);
20250                  imagesToRemove.push(image);
20251                  removed = true;
20252                }
20253                uploadError(editor, uploadInfo.error.message);
20254              }
20255              return {
20256                element: image,
20257                status: uploadInfo.status,
20258                uploadUri: uploadInfo.url,
20259                blobInfo,
20260                removed
20261              };
20262            });
20263            if (imagesToRemove.length > 0 && !isRtc(editor)) {
20264              editor.undoManager.transact(() => {
20265                each$e(fromDom$1(imagesToRemove), sugarElement => {
20266                  const parentOpt = parent(sugarElement);
20267                  remove$4(sugarElement);
20268                  parentOpt.each(addPaddingToEmpty(editor));
20269                  blobCache.removeByUri(sugarElement.dom.src);
20270                });
20271              });
20272            } else if (shouldDispatchChange) {
20273              editor.undoManager.dispatchChange();
20274            }
20275            return filteredResult;
20276          }));
20277        }));
20278      };
20279      const uploadImagesAuto = () => isAutomaticUploadsEnabled(editor) ? uploadImages() : Promise.resolve([]);
20280      const isValidDataUriImage = imgElm => forall(urlFilters, filter => filter(imgElm));
20281      const addFilter = filter => {
20282        urlFilters.push(filter);
20283      };
20284      const scanForImages = () => {
20285        if (!imageScanner) {
20286          imageScanner = ImageScanner(uploadStatus, blobCache);
20287        }
20288        return imageScanner.findAll(editor.getBody(), isValidDataUriImage).then(aliveGuard(result => {
20289          const filteredResult = filter$5(result, resultItem => {
20290            if (isString(resultItem)) {
20291              displayError(editor, resultItem);
20292              return false;
20293            } else if (resultItem.uriType === 'blob') {
20294              return false;
20295            } else {
20296              return true;
20297            }
20298          });
20299          if (isRtc(editor)) ; else {
20300            each$e(filteredResult, resultItem => {
20301              replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
20302              resultItem.image.src = resultItem.blobInfo.blobUri();
20303              resultItem.image.removeAttribute('data-mce-src');
20304            });
20305          }
20306          return filteredResult;
20307        }));
20308      };
20309      const destroy = () => {
20310        blobCache.destroy();
20311        uploadStatus.destroy();
20312        imageScanner = uploader = null;
20313      };
20314      const replaceBlobUris = content => {
20315        return content.replace(/src="(blob:[^"]+)"/g, (match, blobUri) => {
20316          const resultUri = uploadStatus.getResultUri(blobUri);
20317          if (resultUri) {
20318            return 'src="' + resultUri + '"';
20319          }
20320          let blobInfo = blobCache.getByUri(blobUri);
20321          if (!blobInfo) {
20322            blobInfo = foldl(editor.editorManager.get(), (result, editor) => {
20323              return result || editor.editorUpload && editor.editorUpload.blobCache.getByUri(blobUri);
20324            }, undefined);
20325          }
20326          if (blobInfo) {
20327            const blob = blobInfo.blob();
20328            return 'src="data:' + blob.type + ';base64,' + blobInfo.base64() + '"';
20329          }
20330          return match;
20331        });
20332      };
20333      editor.on('SetContent', () => {
20334        if (isAutomaticUploadsEnabled(editor)) {
20335          uploadImagesAuto();
20336        } else {
20337          scanForImages();
20338        }
20339      });
20340      editor.on('RawSaveContent', e => {
20341        e.content = replaceBlobUris(e.content);
20342      });
20343      editor.on('GetContent', e => {
20344        if (e.source_view || e.format === 'raw' || e.format === 'tree') {
20345          return;
20346        }
20347        e.content = replaceBlobUris(e.content);
20348      });
20349      editor.on('PostRender', () => {
20350        editor.parser.addNodeFilter('img', images => {
20351          each$e(images, img => {
20352            const src = img.attr('src');
20353            if (!src || blobCache.getByUri(src)) {
20354              return;
20355            }
20356            const resultUri = uploadStatus.getResultUri(src);
20357            if (resultUri) {
20358              img.attr('src', resultUri);
20359            }
20360          });
20361        });
20362      });
20363      return {
20364        blobCache,
20365        addFilter,
20366        uploadImages,
20367        uploadImagesAuto,
20368        scanForImages,
20369        destroy
20370      };
20371    };
20372
20373    const get$1 = editor => {
20374      const dom = editor.dom;
20375      const schemaType = editor.schema.type;
20376      const formats = {
20377        valigntop: [{
20378            selector: 'td,th',
20379            styles: { verticalAlign: 'top' }
20380          }],
20381        valignmiddle: [{
20382            selector: 'td,th',
20383            styles: { verticalAlign: 'middle' }
20384          }],
20385        valignbottom: [{
20386            selector: 'td,th',
20387            styles: { verticalAlign: 'bottom' }
20388          }],
20389        alignleft: [
20390          {
20391            selector: 'figure.image',
20392            collapsed: false,
20393            classes: 'align-left',
20394            ceFalseOverride: true,
20395            preview: 'font-family font-size'
20396          },
20397          {
20398            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
20399            styles: { textAlign: 'left' },
20400            inherit: false,
20401            preview: false
20402          },
20403          {
20404            selector: 'img,audio,video',
20405            collapsed: false,
20406            styles: { float: 'left' },
20407            preview: 'font-family font-size'
20408          },
20409          {
20410            selector: '
vendor: 3,137 bytes, lines 20410-20520
20410.mce-placeholder',
20411            styles: { float: 'left' },
20412            ceFalseOverride: true
20413          },
20414          {
20415            selector: 'table',
20416            collapsed: false,
20417            styles: {
20418              marginLeft: '0px',
20419              marginRight: 'auto'
20420            },
20421            onformat: table => {
20422              dom.setStyle(table, 'float', null);
20423            },
20424            preview: 'font-family font-size'
20425          },
20426          {
20427            selector: '.mce-preview-object,[data-ephox-embed-iri]',
20428            ceFalseOverride: true,
20429            styles: { float: 'left' }
20430          }
20431        ],
20432        aligncenter: [
20433          {
20434            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
20435            styles: { textAlign: 'center' },
20436            inherit: false,
20437            preview: 'font-family font-size'
20438          },
20439          {
20440            selector: 'figure.image',
20441            collapsed: false,
20442            classes: 'align-center',
20443            ceFalseOverride: true,
20444            preview: 'font-family font-size'
20445          },
20446          {
20447            selector: 'img,audio,video',
20448            collapsed: false,
20449            styles: {
20450              display: 'block',
20451              marginLeft: 'auto',
20452              marginRight: 'auto'
20453            },
20454            preview: false
20455          },
20456          {
20457            selector: '.mce-placeholder',
20458            styles: {
20459              display: 'block',
20460              marginLeft: 'auto',
20461              marginRight: 'auto'
20462            },
20463            ceFalseOverride: true
20464          },
20465          {
20466            selector: 'table',
20467            collapsed: false,
20468            styles: {
20469              marginLeft: 'auto',
20470              marginRight: 'auto'
20471            },
20472            preview: 'font-family font-size'
20473          },
20474          {
20475            selector: '.mce-preview-object',
20476            ceFalseOverride: true,
20477            styles: {
20478              display: 'table',
20479              marginLeft: 'auto',
20480              marginRight: 'auto'
20481            },
20482            preview: false
20483          },
20484          {
20485            selector: '[data-ephox-embed-iri]',
20486            ceFalseOverride: true,
20487            styles: {
20488              marginLeft: 'auto',
20489              marginRight: 'auto'
20490            },
20491            preview: false
20492          }
20493        ],
20494        alignright: [
20495          {
20496            selector: 'figure.image',
20497            collapsed: false,
20498            classes: 'align-right',
20499            ceFalseOverride: true,
20500            preview: 'font-family font-size'
20501          },
20502          {
20503            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
20504            styles: { textAlign: 'right' },
20505            inherit: false,
20506            preview: 'font-family font-size'
20507          },
20508          {
20509            selector: 'img,audio,video',
20510            collapsed: false,
20511            styles: { float: 'right' },
20512            preview: 'font-family font-size'
20513          },
20514          {
20515            selector: '.mce-placeholder',
20516            styles: { float: 'right' },
20517            ceFalseOverride: true
20518          },
20519          {
20520            selector: 'table',
vendor: 5,600 bytes, lines 20521-20737
20521            collapsed: false,
20522            styles: {
20523              marginRight: '0px',
20524              marginLeft: 'auto'
20525            },
20526            onformat: table => {
20527              dom.setStyle(table, 'float', null);
20528            },
20529            preview: 'font-family font-size'
20530          },
20531          {
20532            selector: '.mce-preview-object,[data-ephox-embed-iri]',
20533            ceFalseOverride: true,
20534            styles: { float: 'right' },
20535            preview: false
20536          }
20537        ],
20538        alignjustify: [{
20539            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
20540            styles: { textAlign: 'justify' },
20541            inherit: false,
20542            preview: 'font-family font-size'
20543          }],
20544        bold: [
20545          {
20546            inline: 'strong',
20547            remove: 'all',
20548            preserve_attributes: [
20549              'class',
20550              'style'
20551            ]
20552          },
20553          {
20554            inline: 'span',
20555            styles: { fontWeight: 'bold' }
20556          },
20557          {
20558            inline: 'b',
20559            remove: 'all',
20560            preserve_attributes: [
20561              'class',
20562              'style'
20563            ]
20564          }
20565        ],
20566        italic: [
20567          {
20568            inline: 'em',
20569            remove: 'all',
20570            preserve_attributes: [
20571              'class',
20572              'style'
20573            ]
20574          },
20575          {
20576            inline: 'span',
20577            styles: { fontStyle: 'italic' }
20578          },
20579          {
20580            inline: 'i',
20581            remove: 'all',
20582            preserve_attributes: [
20583              'class',
20584              'style'
20585            ]
20586          }
20587        ],
20588        underline: [
20589          {
20590            inline: 'span',
20591            styles: { textDecoration: 'underline' },
20592            exact: true
20593          },
20594          {
20595            inline: 'u',
20596            remove: 'all',
20597            preserve_attributes: [
20598              'class',
20599              'style'
20600            ]
20601          }
20602        ],
20603        strikethrough: (() => {
20604          const span = {
20605            inline: 'span',
20606            styles: { textDecoration: 'line-through' },
20607            exact: true
20608          };
20609          const strike = {
20610            inline: 'strike',
20611            remove: 'all',
20612            preserve_attributes: [
20613              'class',
20614              'style'
20615            ]
20616          };
20617          const s = {
20618            inline: 's',
20619            remove: 'all',
20620            preserve_attributes: [
20621              'class',
20622              'style'
20623            ]
20624          };
20625          return schemaType !== 'html4' ? [
20626            s,
20627            span,
20628            strike
20629          ] : [
20630            span,
20631            s,
20632            strike
20633          ];
20634        })(),
20635        forecolor: {
20636          inline: 'span',
20637          styles: { color: '%value' },
20638          links: true,
20639          remove_similar: true,
20640          clear_child_styles: true
20641        },
20642        hilitecolor: {
20643          inline: 'span',
20644          styles: { backgroundColor: '%value' },
20645          links: true,
20646          remove_similar: true,
20647          clear_child_styles: true
20648        },
20649        fontname: {
20650          inline: 'span',
20651          toggle: false,
20652          styles: { fontFamily: '%value' },
20653          clear_child_styles: true
20654        },
20655        fontsize: {
20656          inline: 'span',
20657          toggle: false,
20658          styles: { fontSize: '%value' },
20659          clear_child_styles: true
20660        },
20661        lineheight: {
20662          selector: 'h1,h2,h3,h4,h5,h6,p,li,td,th,div',
20663          styles: { lineHeight: '%value' }
20664        },
20665        fontsize_class: {
20666          inline: 'span',
20667          attributes: { class: '%value' }
20668        },
20669        blockquote: {
20670          block: 'blockquote',
20671          wrapper: true,
20672          remove: 'all'
20673        },
20674        subscript: { inline: 'sub' },
20675        superscript: { inline: 'sup' },
20676        code: { inline: 'code' },
20677        samp: { inline: 'samp' },
20678        link: {
20679          inline: 'a',
20680          selector: 'a',
20681          remove: 'all',
20682          split: true,
20683          deep: true,
20684          onmatch: (node, _fmt, _itemName) => {
20685            return isElement$6(node) && node.hasAttribute('href');
20686          },
20687          onformat: (elm, _fmt, vars) => {
20688            Tools.each(vars, (value, key) => {
20689              dom.setAttrib(elm, key, value);
20690            });
20691          }
20692        },
20693        lang: {
20694          inline: 'span',
20695          clear_child_styles: true,
20696          remove_similar: true,
20697          attributes: {
20698            'lang': '%value',
20699            'data-mce-lang': vars => {
20700              var _a;
20701              return (_a = vars === null || vars === void 0 ? void 0 : vars.customValue) !== null && _a !== void 0 ? _a : null;
20702            }
20703          }
20704        },
20705        removeformat: [
20706          {
20707            selector: 'b,strong,em,i,font,u,strike,s,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins,small',
20708            remove: 'all',
20709            split: true,
20710            expand: false,
20711            block_expand: true,
20712            deep: true
20713          },
20714          {
20715            selector: 'span',
20716            attributes: [
20717              'style',
20718              'class'
20719            ],
20720            remove: 'empty',
20721            split: true,
20722            expand: false,
20723            deep: true
20724          },
20725          {
20726            selector: '*',
20727            attributes: [
20728              'style',
20729              'class'
20730            ],
20731            split: false,
20732            expand: false,
20733            deep: true
20734          }
20735        ]
20736      };
20737      Tools.each('p h1 h2 h3 h4 h5 h6 div address pre dt dd
vendor: 10,296 bytes, lines 20737-21057
20737'.split(/\s/), name => {
20738        formats[name] = {
20739          block: name,
20740          remove: 'all'
20741        };
20742      });
20743      return formats;
20744    };
20745
20746    const genericBase = {
20747      remove_similar: true,
20748      inherit: false
20749    };
20750    const cellBase = {
20751      selector: 'td,th',
20752      ...genericBase
20753    };
20754    const cellFormats = {
20755      tablecellbackgroundcolor: {
20756        styles: { backgroundColor: '%value' },
20757        ...cellBase
20758      },
20759      tablecellverticalalign: {
20760        styles: { 'vertical-align': '%value' },
20761        ...cellBase
20762      },
20763      tablecellbordercolor: {
20764        styles: { borderColor: '%value' },
20765        ...cellBase
20766      },
20767      tablecellclass: {
20768        classes: ['%value'],
20769        ...cellBase
20770      },
20771      tableclass: {
20772        selector: 'table',
20773        classes: ['%value'],
20774        ...genericBase
20775      },
20776      tablecellborderstyle: {
20777        styles: { borderStyle: '%value' },
20778        ...cellBase
20779      },
20780      tablecellborderwidth: {
20781        styles: { borderWidth: '%value' },
20782        ...cellBase
20783      }
20784    };
20785    const get = constant(cellFormats);
20786
20787    const FormatRegistry = editor => {
20788      const formats = {};
20789      const get$2 = name => isNonNullable(name) ? formats[name] : formats;
20790      const has = name => has$2(formats, name);
20791      const register = (name, format) => {
20792        if (name) {
20793          if (!isString(name)) {
20794            each$d(name, (format, name) => {
20795              register(name, format);
20796            });
20797          } else {
20798            if (!isArray$1(format)) {
20799              format = [format];
20800            }
20801            each$e(format, format => {
20802              if (isUndefined(format.deep)) {
20803                format.deep = !isSelectorFormat(format);
20804              }
20805              if (isUndefined(format.split)) {
20806                format.split = !isSelectorFormat(format) || isInlineFormat(format);
20807              }
20808              if (isUndefined(format.remove) && isSelectorFormat(format) && !isInlineFormat(format)) {
20809                format.remove = 'none';
20810              }
20811              if (isSelectorFormat(format) && isInlineFormat(format)) {
20812                format.mixed = true;
20813                format.block_expand = true;
20814              }
20815              if (isString(format.classes)) {
20816                format.classes = format.classes.split(/\s+/);
20817              }
20818            });
20819            formats[name] = format;
20820          }
20821        }
20822      };
20823      const unregister = name => {
20824        if (name && formats[name]) {
20825          delete formats[name];
20826        }
20827        return formats;
20828      };
20829      register(get$1(editor));
20830      register(get());
20831      register(getFormats(editor));
20832      return {
20833        get: get$2,
20834        has,
20835        register,
20836        unregister
20837      };
20838    };
20839
20840    const each$3 = Tools.each;
20841    const dom = DOMUtils.DOM;
20842    const isPreviewItem = item => isNonNullable(item) && isObject(item);
20843    const parsedSelectorToHtml = (ancestry, editor) => {
20844      const schema = editor && editor.schema || Schema({});
20845      const decorate = (elm, item) => {
20846        if (item.classes.length > 0) {
20847          dom.addClass(elm, item.classes.join(' '));
20848        }
20849        dom.setAttribs(elm, item.attrs);
20850      };
20851      const createElement = sItem => {
20852        const item = isString(sItem) ? {
20853          name: sItem,
20854          classes: [],
20855          attrs: {}
20856        } : sItem;
20857        const elm = dom.create(item.name);
20858        decorate(elm, item);
20859        return elm;
20860      };
20861      const getRequiredParent = (elm, candidate) => {
20862        const elmRule = schema.getElementRule(elm.nodeName.toLowerCase());
20863        const parentsRequired = elmRule === null || elmRule === void 0 ? void 0 : elmRule.parentsRequired;
20864        if (parentsRequired && parentsRequired.length) {
20865          return candidate && contains$2(parentsRequired, candidate) ? candidate : parentsRequired[0];
20866        } else {
20867          return false;
20868        }
20869      };
20870      const wrapInHtml = (elm, ancestors, siblings) => {
20871        let parentCandidate;
20872        const ancestor = ancestors[0];
20873        const ancestorName = isPreviewItem(ancestor) ? ancestor.name : undefined;
20874        const parentRequired = getRequiredParent(elm, ancestorName);
20875        if (parentRequired) {
20876          if (ancestorName === parentRequired) {
20877            parentCandidate = ancestor;
20878            ancestors = ancestors.slice(1);
20879          } else {
20880            parentCandidate = parentRequired;
20881          }
20882        } else if (ancestor) {
20883          parentCandidate = ancestor;
20884          ancestors = ancestors.slice(1);
20885        } else if (!siblings) {
20886          return elm;
20887        }
20888        const parent = parentCandidate ? createElement(parentCandidate) : dom.create('div');
20889        parent.appendChild(elm);
20890        if (siblings) {
20891          Tools.each(siblings, sibling => {
20892            const siblingElm = createElement(sibling);
20893            parent.insertBefore(siblingElm, elm);
20894          });
20895        }
20896        const parentSiblings = isPreviewItem(parentCandidate) ? parentCandidate.siblings : undefined;
20897        return wrapInHtml(parent, ancestors, parentSiblings);
20898      };
20899      const fragment = dom.create('div');
20900      if (ancestry.length > 0) {
20901        const item = ancestry[0];
20902        const elm = createElement(item);
20903        const siblings = isPreviewItem(item) ? item.siblings : undefined;
20904        fragment.appendChild(wrapInHtml(elm, ancestry.slice(1), siblings));
20905      }
20906      return fragment;
20907    };
20908    const parseSelectorItem = item => {
20909      item = Tools.trim(item);
20910      let tagName = 'div';
20911      const obj = {
20912        name: tagName,
20913        classes: [],
20914        attrs: {},
20915        selector: item
20916      };
20917      if (item !== '*') {
20918        tagName = item.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g, ($0, $1, $2, $3, $4) => {
20919          switch ($1) {
20920          case '#':
20921            obj.attrs.id = $2;
20922            break;
20923          case '.':
20924            obj.classes.push($2);
20925            break;
20926          case ':':
20927            if (Tools.inArray('checked disabled enabled read-only required'.split(' '), $2) !== -1) {
20928              obj.attrs[$2] = $2;
20929            }
20930            break;
20931          }
20932          if ($3 === '[') {
20933            const m = $4.match(/([\w\-]+)(?:\=\"([^\"]+))?/);
20934            if (m) {
20935              obj.attrs[m[1]] = m[2];
20936            }
20937          }
20938          return '';
20939        });
20940      }
20941      obj.name = tagName || 'div';
20942      return obj;
20943    };
20944    const parseSelector = selector => {
20945      if (!isString(selector)) {
20946        return [];
20947      }
20948      selector = selector.split(/\s*,\s*/)[0];
20949      selector = selector.replace(/\s*(~\+|~|\+|>)\s*/g, '$1');
20950      return Tools.map(selector.split(/(?:>|\s+(?![^\[\]]+\]))/), item => {
20951        const siblings = Tools.map(item.split(/(?:~\+|~|\+)/), parseSelectorItem);
20952        const obj = siblings.pop();
20953        if (siblings.length) {
20954          obj.siblings = siblings;
20955        }
20956        return obj;
20957      }).reverse();
20958    };
20959    const getCssText = (editor, format) => {
20960      let previewCss = '';
20961      let previewStyles = getPreviewStyles(editor);
20962      if (previewStyles === '') {
20963        return '';
20964      }
20965      const removeVars = val => {
20966        return isString(val) ? val.replace(/%(\w+)/g, '') : '';
20967      };
20968      const getComputedStyle = (name, elm) => {
20969        return dom.getStyle(elm !== null && elm !== void 0 ? elm : editor.getBody(), name, true);
20970      };
20971      if (isString(format)) {
20972        const formats = editor.formatter.get(format);
20973        if (!formats) {
20974          return '';
20975        }
20976        format = formats[0];
20977      }
20978      if ('preview' in format) {
20979        const preview = format.preview;
20980        if (preview === false) {
20981          return '';
20982        } else {
20983          previewStyles = preview || previewStyles;
20984        }
20985      }
20986      let name = format.block || format.inline || 'span';
20987      let previewFrag;
20988      const items = parseSelector(format.selector);
20989      if (items.length > 0) {
20990        if (!items[0].name) {
20991          items[0].name = name;
20992        }
20993        name = format.selector;
20994        previewFrag = parsedSelectorToHtml(items, editor);
20995      } else {
20996        previewFrag = parsedSelectorToHtml([name], editor);
20997      }
20998      const previewElm = dom.select(name, previewFrag)[0] || previewFrag.firstChild;
20999      each$3(format.styles, (value, name) => {
21000        const newValue = removeVars(value);
21001        if (newValue) {
21002          dom.setStyle(previewElm, name, newValue);
21003        }
21004      });
21005      each$3(format.attributes, (value, name) => {
21006        const newValue = removeVars(value);
21007        if (newValue) {
21008          dom.setAttrib(previewElm, name, newValue);
21009        }
21010      });
21011      each$3(format.classes, value => {
21012        const newValue = removeVars(value);
21013        if (!dom.hasClass(previewElm, newValue)) {
21014          dom.addClass(previewElm, newValue);
21015        }
21016      });
21017      editor.dispatch('PreviewFormats');
21018      dom.setStyles(previewFrag, {
21019        position: 'absolute',
21020        left: -65535
21021      });
21022      editor.getBody().appendChild(previewFrag);
21023      const rawParentFontSize = getComputedStyle('fontSize');
21024      const parentFontSize = /px$/.test(rawParentFontSize) ? parseInt(rawParentFontSize, 10) : 0;
21025      each$3(previewStyles.split(' '), name => {
21026        let value = getComputedStyle(name, previewElm);
21027        if (name === 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) {
21028          value = getComputedStyle(name);
21029          if (rgbaToHexString(value).toLowerCase() === '#ffffff') {
21030            return;
21031          }
21032        }
21033        if (name === 'color') {
21034          if (rgbaToHexString(value).toLowerCase() === '#000000') {
21035            return;
21036          }
21037        }
21038        if (name === 'font-size') {
21039          if (/em|%$/.test(value)) {
21040            if (parentFontSize === 0) {
21041              return;
21042            }
21043            const numValue = parseFloat(value) / (/%$/.test(value) ? 100 : 1);
21044            value = numValue * parentFontSize + 'px';
21045          }
21046        }
21047        if (name === 'border' && value) {
21048          previewCss += 'padding:0 2px;';
21049        }
21050        previewCss += name + ':' + value + ';';
21051      });
21052      editor.dispatch('AfterPreviewFormats');
21053      dom.remove(previewFrag);
21054      return previewCss;
21055    };
21056
21057    const setup$
vendor: 868 bytes, lines 21057-21091
21057s = editor => {
21058      editor.addShortcut('meta+b', '', 'Bold');
21059      editor.addShortcut('meta+i', '', 'Italic');
21060      editor.addShortcut('meta+u', '', 'Underline');
21061      for (let i = 1; i <= 6; i++) {
21062        editor.addShortcut('access+' + i, '', [
21063          'FormatBlock',
21064          false,
21065          'h' + i
21066        ]);
21067      }
21068      editor.addShortcut('access+7', '', [
21069        'FormatBlock',
21070        false,
21071        'p'
21072      ]);
21073      editor.addShortcut('access+8', '', [
21074        'FormatBlock',
21075        false,
21076        'div'
21077      ]);
21078      editor.addShortcut('access+9', '', [
21079        'FormatBlock',
21080        false,
21081        'address'
21082      ]);
21083    };
21084
21085    const Formatter = editor => {
21086      const formats = FormatRegistry(editor);
21087      const formatChangeState = Cell({});
21088      setup$s(editor);
21089      setup$v(editor);
21090      if (!isRtc(editor)) {
21091        setup$u
vendor: 7,773 bytes, lines 21091-21321
21091(formatChangeState, editor);
21092      }
21093      return {
21094        get: formats.get,
21095        has: formats.has,
21096        register: formats.register,
21097        unregister: formats.unregister,
21098        apply: (name, vars, node) => {
21099          applyFormat(editor, name, vars, node);
21100        },
21101        remove: (name, vars, node, similar) => {
21102          removeFormat(editor, name, vars, node, similar);
21103        },
21104        toggle: (name, vars, node) => {
21105          toggleFormat(editor, name, vars, node);
21106        },
21107        match: (name, vars, node, similar) => matchFormat(editor, name, vars, node, similar),
21108        closest: names => closestFormat(editor, names),
21109        matchAll: (names, vars) => matchAllFormats(editor, names, vars),
21110        matchNode: (node, name, vars, similar) => matchNodeFormat(editor, node, name, vars, similar),
21111        canApply: name => canApplyFormat(editor, name),
21112        formatChanged: (formats, callback, similar, vars) => formatChanged(editor, formatChangeState, formats, callback, similar, vars),
21113        getCssText: curry(getCssText, editor)
21114      };
21115    };
21116
21117    const shouldIgnoreCommand = cmd => {
21118      switch (cmd.toLowerCase()) {
21119      case 'undo':
21120      case 'redo':
21121      case 'mcefocus':
21122        return true;
21123      default:
21124        return false;
21125      }
21126    };
21127    const registerEvents = (editor, undoManager, locks) => {
21128      const isFirstTypedCharacter = Cell(false);
21129      const addNonTypingUndoLevel = e => {
21130        setTyping(undoManager, false, locks);
21131        undoManager.add({}, e);
21132      };
21133      editor.on('init', () => {
21134        undoManager.add();
21135      });
21136      editor.on('BeforeExecCommand', e => {
21137        const cmd = e.command;
21138        if (!shouldIgnoreCommand(cmd)) {
21139          endTyping(undoManager, locks);
21140          undoManager.beforeChange();
21141        }
21142      });
21143      editor.on('ExecCommand', e => {
21144        const cmd = e.command;
21145        if (!shouldIgnoreCommand(cmd)) {
21146          addNonTypingUndoLevel(e);
21147        }
21148      });
21149      editor.on('ObjectResizeStart cut', () => {
21150        undoManager.beforeChange();
21151      });
21152      editor.on('SaveContent ObjectResized blur', addNonTypingUndoLevel);
21153      editor.on('dragend', addNonTypingUndoLevel);
21154      editor.on('keyup', e => {
21155        const keyCode = e.keyCode;
21156        if (e.isDefaultPrevented()) {
21157          return;
21158        }
21159        const isMeta = Env.os.isMacOS() && e.key === 'Meta';
21160        if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45 || e.ctrlKey || isMeta) {
21161          addNonTypingUndoLevel();
21162          editor.nodeChanged();
21163        }
21164        if (keyCode === 46 || keyCode === 8) {
21165          editor.nodeChanged();
21166        }
21167        if (isFirstTypedCharacter.get() && undoManager.typing && !isEq$1(createFromEditor(editor), undoManager.data[0])) {
21168          if (!editor.isDirty()) {
21169            editor.setDirty(true);
21170          }
21171          editor.dispatch('TypingUndo');
21172          isFirstTypedCharacter.set(false);
21173          editor.nodeChanged();
21174        }
21175      });
21176      editor.on('keydown', e => {
21177        const keyCode = e.keyCode;
21178        if (e.isDefaultPrevented()) {
21179          return;
21180        }
21181        if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45) {
21182          if (undoManager.typing) {
21183            addNonTypingUndoLevel(e);
21184          }
21185          return;
21186        }
21187        const modKey = e.ctrlKey && !e.altKey || e.metaKey;
21188        if ((keyCode < 16 || keyCode > 20) && keyCode !== 224 && keyCode !== 91 && !undoManager.typing && !modKey) {
21189          undoManager.beforeChange();
21190          setTyping(undoManager, true, locks);
21191          undoManager.add({}, e);
21192          isFirstTypedCharacter.set(true);
21193          return;
21194        }
21195        const hasOnlyMetaOrCtrlModifier = Env.os.isMacOS() ? e.metaKey : e.ctrlKey && !e.altKey;
21196        if (hasOnlyMetaOrCtrlModifier) {
21197          undoManager.beforeChange();
21198        }
21199      });
21200      editor.on('mousedown', e => {
21201        if (undoManager.typing) {
21202          addNonTypingUndoLevel(e);
21203        }
21204      });
21205      const isInsertReplacementText = event => event.inputType === 'insertReplacementText';
21206      const isInsertTextDataNull = event => event.inputType === 'insertText' && event.data === null;
21207      const isInsertFromPasteOrDrop = event => event.inputType === 'insertFromPaste' || event.inputType === 'insertFromDrop';
21208      editor.on('input', e => {
21209        if (e.inputType && (isInsertReplacementText(e) || isInsertTextDataNull(e) || isInsertFromPasteOrDrop(e))) {
21210          addNonTypingUndoLevel(e);
21211        }
21212      });
21213      editor.on('AddUndo Undo Redo ClearUndos', e => {
21214        if (!e.isDefaultPrevented()) {
21215          editor.nodeChanged();
21216        }
21217      });
21218    };
21219    const addKeyboardShortcuts = editor => {
21220      editor.addShortcut('meta+z', '', 'Undo');
21221      editor.addShortcut('meta+y,meta+shift+z', '', 'Redo');
21222    };
21223
21224    const UndoManager = editor => {
21225      const beforeBookmark = value$2();
21226      const locks = Cell(0);
21227      const index = Cell(0);
21228      const undoManager = {
21229        data: [],
21230        typing: false,
21231        beforeChange: () => {
21232          beforeChange(editor, locks, beforeBookmark);
21233        },
21234        add: (level, event) => {
21235          return addUndoLevel(editor, undoManager, index, locks, beforeBookmark, level, event);
21236        },
21237        dispatchChange: () => {
21238          editor.setDirty(true);
21239          const level = createFromEditor(editor);
21240          level.bookmark = getUndoBookmark(editor.selection);
21241          editor.dispatch('change', {
21242            level,
21243            lastLevel: get$b(undoManager.data, index.get()).getOrUndefined()
21244          });
21245        },
21246        undo: () => {
21247          return undo(editor, undoManager, locks, index);
21248        },
21249        redo: () => {
21250          return redo(editor, index, undoManager.data);
21251        },
21252        clear: () => {
21253          clear(editor, undoManager, index);
21254        },
21255        reset: () => {
21256          reset(editor, undoManager);
21257        },
21258        hasUndo: () => {
21259          return hasUndo(editor, undoManager, index);
21260        },
21261        hasRedo: () => {
21262          return hasRedo(editor, undoManager, index);
21263        },
21264        transact: callback => {
21265          return transact(editor, undoManager, locks, callback);
21266        },
21267        ignore: callback => {
21268          ignore(editor, locks, callback);
21269        },
21270        extra: (callback1, callback2) => {
21271          extra(editor, undoManager, index, callback1, callback2);
21272        }
21273      };
21274      if (!isRtc(editor)) {
21275        registerEvents(editor, undoManager, locks);
21276      }
21277      addKeyboardShortcuts(editor);
21278      return undoManager;
21279    };
21280
21281    const nonTypingKeycodes = [
21282      9,
21283      27,
21284      VK.HOME,
21285      VK.END,
21286      19,
21287      20,
21288      44,
21289      144,
21290      145,
21291      33,
21292      34,
21293      45,
21294      16,
21295      17,
21296      18,
21297      91,
21298      92,
21299      93,
21300      VK.DOWN,
21301      VK.UP,
21302      VK.LEFT,
21303      VK.RIGHT
21304    ].concat(Env.browser.isFirefox() ? [224] : []);
21305    const placeholderAttr = 'data-mce-placeholder';
21306    const isKeyboardEvent = e => e.type === 'keydown' || e.type === 'keyup';
21307    const isDeleteEvent = e => {
21308      const keyCode = e.keyCode;
21309      return keyCode === VK.BACKSPACE || keyCode === VK.DELETE;
21310    };
21311    const isNonTypingKeyboardEvent = e => {
21312      if (isKeyboardEvent(e)) {
21313        const keyCode = e.keyCode;
21314        return !isDeleteEvent(e) && (VK.metaKeyPressed(e) || e.altKey || keyCode >= 112 && keyCode <= 123 || contains$2(nonTypingKeycodes, keyCode));
21315      } else {
21316        return false;
21317      }
21318    };
21319    const isTypingKeyboardEvent = e => isKeyboardEvent(e) && !(isDeleteEvent(e) || e.type === 'keyup' && e.keyCode === 229);
21320    const isVisuallyEmpty = (dom, rootElm, forcedRootBlock) => {
21321      if (
vendor: 2,533 bytes, lines 21321-21380
21321dom.isEmpty(rootElm, undefined, {
21322          skipBogus: false,
21323          includeZwsp: true
21324        })) {
21325        const firstElement = rootElm.firstElementChild;
21326        if (!firstElement) {
21327          return true;
21328        } else if (dom.getStyle(rootElm.firstElementChild, 'padding-left') || dom.getStyle(rootElm.firstElementChild, 'padding-right')) {
21329          return false;
21330        } else {
21331          return forcedRootBlock === firstElement.nodeName.toLowerCase();
21332        }
21333      } else {
21334        return false;
21335      }
21336    };
21337    const setup$r = editor => {
21338      var _a;
21339      const dom = editor.dom;
21340      const rootBlock = getForcedRootBlock(editor);
21341      const placeholder = (_a = getPlaceholder(editor)) !== null && _a !== void 0 ? _a : '';
21342      const updatePlaceholder = (e, initial) => {
21343        if (isNonTypingKeyboardEvent(e)) {
21344          return;
21345        }
21346        const body = editor.getBody();
21347        const showPlaceholder = isTypingKeyboardEvent(e) ? false : isVisuallyEmpty(dom, body, rootBlock);
21348        const isPlaceholderShown = dom.getAttrib(body, placeholderAttr) !== '';
21349        if (isPlaceholderShown !== showPlaceholder || initial) {
21350          dom.setAttrib(body, placeholderAttr, showPlaceholder ? placeholder : null);
21351          firePlaceholderToggle(editor, showPlaceholder);
21352          editor.on(showPlaceholder ? 'keydown' : 'keyup', updatePlaceholder);
21353          editor.off(showPlaceholder ? 'keyup' : 'keydown', updatePlaceholder);
21354        }
21355      };
21356      if (isNotEmpty(placeholder)) {
21357        editor.on('init', e => {
21358          updatePlaceholder(e, true);
21359          editor.on('change SetContent ExecCommand', updatePlaceholder);
21360          editor.on('paste', e => Delay.setEditorTimeout(editor, () => updatePlaceholder(e)));
21361        });
21362      }
21363    };
21364
21365    const blockPosition = (block, position) => ({
21366      block,
21367      position
21368    });
21369    const blockBoundary = (from, to) => ({
21370      from,
21371      to
21372    });
21373    const getBlockPosition = (rootNode, pos) => {
21374      const rootElm = SugarElement.fromDom(rootNode);
21375      const containerElm = SugarElement.fromDom(pos.container());
21376      return getParentBlock$2(rootElm, containerElm).map(block => blockPosition(block, pos));
21377    };
21378    const isNotAncestorial = blockBoundary => !(contains(blockBoundary.to.block, blockBoundary.from.block) || contains(blockBoundary.from.block, blockBoundary.to.block));
21379    const isDifferentBlocks = blockBoundary => !eq(blockBoundary.from.block, blockBoundary.to.block);
21380    const getClosestHost = (root, scope) => {
vendor: 16,490 bytes, lines 21381-21682
21381      const isRoot = node => eq(node, root);
21382      const isHost = node => isTableCell$2(node) || isContentEditableTrue$3(node.dom);
21383      return closest$4(scope, isHost, isRoot).filter(isElement$7).getOr(root);
21384    };
21385    const hasSameHost = (rootNode, blockBoundary) => {
21386      const root = SugarElement.fromDom(rootNode);
21387      return eq(getClosestHost(root, blockBoundary.from.block), getClosestHost(root, blockBoundary.to.block));
21388    };
21389    const isEditable$1 = blockBoundary => isContentEditableFalse$b(blockBoundary.from.block.dom) === false && isContentEditableFalse$b(blockBoundary.to.block.dom) === false;
21390    const hasValidBlocks = blockBoundary => {
21391      const isValidBlock = block => isTextBlock$2(block) || hasBlockAttr(block.dom) || isListItem$1(block);
21392      return isValidBlock(blockBoundary.from.block) && isValidBlock(blockBoundary.to.block);
21393    };
21394    const skipLastBr = (schema, rootNode, forward, blockPosition) => {
21395      if (isBr$6(blockPosition.position.getNode()) && !isEmpty$2(schema, blockPosition.block)) {
21396        return positionIn(false, blockPosition.block.dom).bind(lastPositionInBlock => {
21397          if (lastPositionInBlock.isEqual(blockPosition.position)) {
21398            return fromPosition(forward, rootNode, lastPositionInBlock).bind(to => getBlockPosition(rootNode, to));
21399          } else {
21400            return Optional.some(blockPosition);
21401          }
21402        }).getOr(blockPosition);
21403      } else {
21404        return blockPosition;
21405      }
21406    };
21407    const readFromRange = (schema, rootNode, forward, rng) => {
21408      const fromBlockPos = getBlockPosition(rootNode, CaretPosition.fromRangeStart(rng));
21409      const toBlockPos = fromBlockPos.bind(blockPos => fromPosition(forward, rootNode, blockPos.position).bind(to => getBlockPosition(rootNode, to).map(blockPos => skipLastBr(schema, rootNode, forward, blockPos))));
21410      return lift2(fromBlockPos, toBlockPos, blockBoundary).filter(blockBoundary => isDifferentBlocks(blockBoundary) && hasSameHost(rootNode, blockBoundary) && isEditable$1(blockBoundary) && hasValidBlocks(blockBoundary) && isNotAncestorial(blockBoundary));
21411    };
21412    const read$1 = (schema, rootNode, forward, rng) => rng.collapsed ? readFromRange(schema, rootNode, forward, rng) : Optional.none();
21413
21414    const getChildrenUntilBlockBoundary = (block, schema) => {
21415      const children = children$1(block);
21416      return findIndex$2(children, el => schema.isBlock(name(el))).fold(constant(children), index => children.slice(0, index));
21417    };
21418    const extractChildren = (block, schema) => {
21419      const children = getChildrenUntilBlockBoundary(block, schema);
21420      each$e(children, remove$4);
21421      return children;
21422    };
21423    const removeEmptyRoot = (schema, rootNode, block) => {
21424      const parents = parentsAndSelf(block, rootNode);
21425      return find$2(parents.reverse(), element => isEmpty$2(schema, element)).each(remove$4);
21426    };
21427    const isEmptyBefore = (schema, el) => filter$5(prevSiblings(el), el => !isEmpty$2(schema, el)).length === 0;
21428    const nestedBlockMerge = (rootNode, fromBlock, toBlock, schema, insertionPoint) => {
21429      if (isEmpty$2(schema, toBlock)) {
21430        fillWithPaddingBr(toBlock);
21431        return firstPositionIn(toBlock.dom);
21432      }
21433      if (isEmptyBefore(schema, insertionPoint) && isEmpty$2(schema, fromBlock)) {
21434        before$3(insertionPoint, SugarElement.fromTag('br'));
21435      }
21436      const position = prevPosition(toBlock.dom, CaretPosition.before(insertionPoint.dom));
21437      each$e(extractChildren(fromBlock, schema), child => {
21438        before$3(insertionPoint, child);
21439      });
21440      removeEmptyRoot(schema, rootNode, fromBlock);
21441      return position;
21442    };
21443    const isInline = (schema, node) => schema.isInline(name(node));
21444    const sidelongBlockMerge = (rootNode, fromBlock, toBlock, schema) => {
21445      if (isEmpty$2(schema, toBlock)) {
21446        if (isEmpty$2(schema, fromBlock)) {
21447          const getInlineToBlockDescendants = el => {
21448            const helper = (node, elements) => firstChild(node).fold(() => elements, child => isInline(schema, child) ? helper(child, elements.concat(shallow$1(child))) : elements);
21449            return helper(el, []);
21450          };
21451          const newFromBlockDescendants = foldr(getInlineToBlockDescendants(toBlock), (element, descendant) => {
21452            wrap$2(element, descendant);
21453            return descendant;
21454          }, createPaddingBr());
21455          empty(fromBlock);
21456          append$1(fromBlock, newFromBlockDescendants);
21457        }
21458        remove$4(toBlock);
21459        return firstPositionIn(fromBlock.dom);
21460      }
21461      const position = lastPositionIn(toBlock.dom);
21462      each$e(extractChildren(fromBlock, schema), child => {
21463        append$1(toBlock, child);
21464      });
21465      removeEmptyRoot(schema, rootNode, fromBlock);
21466      return position;
21467    };
21468    const findInsertionPoint = (toBlock, block) => {
21469      const parentsAndSelf$1 = parentsAndSelf(block, toBlock);
21470      return Optional.from(parentsAndSelf$1[parentsAndSelf$1.length - 1]);
21471    };
21472    const getInsertionPoint = (fromBlock, toBlock) => contains(toBlock, fromBlock) ? findInsertionPoint(toBlock, fromBlock) : Optional.none();
21473    const trimBr = (first, block) => {
21474      positionIn(first, block.dom).bind(position => Optional.from(position.getNode())).map(SugarElement.fromDom).filter(isBr$5).each(remove$4);
21475    };
21476    const mergeBlockInto = (rootNode, fromBlock, toBlock, schema) => {
21477      trimBr(true, fromBlock);
21478      trimBr(false, toBlock);
21479      return getInsertionPoint(fromBlock, toBlock).fold(curry(sidelongBlockMerge, rootNode, fromBlock, toBlock, schema), curry(nestedBlockMerge, rootNode, fromBlock, toBlock, schema));
21480    };
21481    const mergeBlocks = (rootNode, forward, block1, block2, schema) => forward ? mergeBlockInto(rootNode, block2, block1, schema) : mergeBlockInto(rootNode, block1, block2, schema);
21482
21483    const backspaceDelete$a = (editor, forward) => {
21484      const rootNode = SugarElement.fromDom(editor.getBody());
21485      const position = read$1(editor.schema, rootNode.dom, forward, editor.selection.getRng()).map(blockBoundary => () => {
21486        mergeBlocks(rootNode, forward, blockBoundary.from.block, blockBoundary.to.block, editor.schema).each(pos => {
21487          editor.selection.setRng(pos.toRange());
21488        });
21489      });
21490      return position;
21491    };
21492
21493    const deleteRangeMergeBlocks = (rootNode, selection, schema) => {
21494      const rng = selection.getRng();
21495      return lift2(getParentBlock$2(rootNode, SugarElement.fromDom(rng.startContainer)), getParentBlock$2(rootNode, SugarElement.fromDom(rng.endContainer)), (block1, block2) => {
21496        if (!eq(block1, block2)) {
21497          return Optional.some(() => {
21498            rng.deleteContents();
21499            mergeBlocks(rootNode, true, block1, block2, schema).each(pos => {
21500              selection.setRng(pos.toRange());
21501            });
21502          });
21503        } else {
21504          return Optional.none();
21505        }
21506      }).getOr(Optional.none());
21507    };
21508    const isRawNodeInTable = (root, rawNode) => {
21509      const node = SugarElement.fromDom(rawNode);
21510      const isRoot = curry(eq, root);
21511      return ancestor$4(node, isTableCell$2, isRoot).isSome();
21512    };
21513    const isSelectionInTable = (root, rng) => isRawNodeInTable(root, rng.startContainer) || isRawNodeInTable(root, rng.endContainer);
21514    const isEverythingSelected = (root, rng) => {
21515      const noPrevious = prevPosition(root.dom, CaretPosition.fromRangeStart(rng)).isNone();
21516      const noNext = nextPosition(root.dom, CaretPosition.fromRangeEnd(rng)).isNone();
21517      return !isSelectionInTable(root, rng) && noPrevious && noNext;
21518    };
21519    const emptyEditor = editor => {
21520      return Optional.some(() => {
21521        editor.setContent('');
21522        editor.selection.setCursorLocation();
21523      });
21524    };
21525    const deleteRange$2 = editor => {
21526      const rootNode = SugarElement.fromDom(editor.getBody());
21527      const rng = editor.selection.getRng();
21528      return isEverythingSelected(rootNode, rng) ? emptyEditor(editor) : deleteRangeMergeBlocks(rootNode, editor.selection, editor.schema);
21529    };
21530    const backspaceDelete$9 = (editor, _forward) => editor.selection.isCollapsed() ? Optional.none() : deleteRange$2(editor);
21531
21532    const showCaret = (direction, editor, node, before, scrollIntoView) => Optional.from(editor._selectionOverrides.showCaret(direction, node, before, scrollIntoView));
21533    const getNodeRange = node => {
21534      const rng = node.ownerDocument.createRange();
21535      rng.selectNode(node);
21536      return rng;
21537    };
21538    const selectNode = (editor, node) => {
21539      const e = editor.dispatch('BeforeObjectSelected', { target: node });
21540      if (e.isDefaultPrevented()) {
21541        return Optional.none();
21542      }
21543      return Optional.some(getNodeRange(node));
21544    };
21545    const renderCaretAtRange = (editor, range, scrollIntoView) => {
21546      const normalizedRange = normalizeRange(1, editor.getBody(), range);
21547      const caretPosition = CaretPosition.fromRangeStart(normalizedRange);
21548      const caretPositionNode = caretPosition.getNode();
21549      if (isInlineFakeCaretTarget(caretPositionNode)) {
21550        return showCaret(1, editor, caretPositionNode, !caretPosition.isAtEnd(), false);
21551      }
21552      const caretPositionBeforeNode = caretPosition.getNode(true);
21553      if (isInlineFakeCaretTarget(caretPositionBeforeNode)) {
21554        return showCaret(1, editor, caretPositionBeforeNode, false, false);
21555      }
21556      const ceRoot = getContentEditableRoot$1(editor.dom.getRoot(), caretPosition.getNode());
21557      if (isInlineFakeCaretTarget(ceRoot)) {
21558        return showCaret(1, editor, ceRoot, false, scrollIntoView);
21559      }
21560      return Optional.none();
21561    };
21562    const renderRangeCaret = (editor, range, scrollIntoView) => range.collapsed ? renderCaretAtRange(editor, range, scrollIntoView).getOr(range) : range;
21563
21564    const isBeforeBoundary = pos => isBeforeContentEditableFalse(pos) || isBeforeMedia(pos);
21565    const isAfterBoundary = pos => isAfterContentEditableFalse(pos) || isAfterMedia(pos);
21566    const trimEmptyTextNode = (dom, node) => {
21567      if (isText$b(node) && node.data.length === 0) {
21568        dom.remove(node);
21569      }
21570    };
21571    const deleteContentAndShowCaret = (editor, range, node, direction, forward, peekCaretPosition) => {
21572      showCaret(direction, editor, peekCaretPosition.getNode(!forward), forward, true).each(caretRange => {
21573        if (range.collapsed) {
21574          const deleteRange = range.cloneRange();
21575          if (forward) {
21576            deleteRange.setEnd(caretRange.startContainer, caretRange.startOffset);
21577          } else {
21578            deleteRange.setStart(caretRange.endContainer, caretRange.endOffset);
21579          }
21580          deleteRange.deleteContents();
21581        } else {
21582          range.deleteContents();
21583        }
21584        editor.selection.setRng(caretRange);
21585      });
21586      trimEmptyTextNode(editor.dom, node);
21587    };
21588    const deleteBoundaryText = (editor, forward) => {
21589      const range = editor.selection.getRng();
21590      if (!isText$b(range.commonAncestorContainer)) {
21591        return Optional.none();
21592      }
21593      const direction = forward ? 1 : -1;
21594      const caretWalker = CaretWalker(editor.getBody());
21595      const getNextPosFn = curry(getVisualCaretPosition, forward ? caretWalker.next : caretWalker.prev);
21596      const isBeforeFn = forward ? isBeforeBoundary : isAfterBoundary;
21597      const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
21598      const nextCaretPosition = getNextPosFn(caretPosition);
21599      const normalizedNextCaretPosition = nextCaretPosition ? normalizePosition(forward, nextCaretPosition) : nextCaretPosition;
21600      if (!normalizedNextCaretPosition || !isMoveInsideSameBlock(caretPosition, normalizedNextCaretPosition)) {
21601        return Optional.none();
21602      } else if (isBeforeFn(normalizedNextCaretPosition)) {
21603        return Optional.some(() => deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, normalizedNextCaretPosition));
21604      }
21605      const peekCaretPosition = getNextPosFn(normalizedNextCaretPosition);
21606      if (peekCaretPosition && isBeforeFn(peekCaretPosition)) {
21607        if (isMoveInsideSameBlock(normalizedNextCaretPosition, peekCaretPosition)) {
21608          return Optional.some(() => deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, peekCaretPosition));
21609        }
21610      }
21611      return Optional.none();
21612    };
21613    const backspaceDelete$8 = (editor, forward) => deleteBoundaryText(editor, forward);
21614
21615    const getEdgeCefPosition = (editor, atStart) => {
21616      const root = editor.getBody();
21617      return atStart ? firstPositionIn(root).filter(isBeforeContentEditableFalse) : lastPositionIn(root).filter(isAfterContentEditableFalse);
21618    };
21619    const isCefAtEdgeSelected = editor => {
21620      const rng = editor.selection.getRng();
21621      return !rng.collapsed && (getEdgeCefPosition(editor, true).exists(pos => pos.isEqual(CaretPosition.fromRangeStart(rng))) || getEdgeCefPosition(editor, false).exists(pos => pos.isEqual(CaretPosition.fromRangeEnd(rng))));
21622    };
21623
21624    const isCompoundElement = node => isNonNullable(node) && (isTableCell$2(SugarElement.fromDom(node)) || isListItem$1(SugarElement.fromDom(node)));
21625    const DeleteAction = Adt.generate([
21626      { remove: ['element'] },
21627      { moveToElement: ['element'] },
21628      { moveToPosition: ['position'] }
21629    ]);
21630    const isAtContentEditableBlockCaret = (forward, from) => {
21631      const elm = from.getNode(!forward);
21632      const caretLocation = forward ? 'after' : 'before';
21633      return isElement$6(elm) && elm.getAttribute('data-mce-caret') === caretLocation;
21634    };
21635    const isDeleteFromCefDifferentBlocks = (root, forward, from, to, schema) => {
21636      const inSameBlock = elm => schema.isInline(elm.nodeName.toLowerCase()) && !isInSameBlock(from, to, root);
21637      return getRelativeCefElm(!forward, from).fold(() => getRelativeCefElm(forward, to).fold(never, inSameBlock), inSameBlock);
21638    };
21639    const deleteEmptyBlockOrMoveToCef = (schema, root, forward, from, to) => {
21640      const toCefElm = to.getNode(!forward);
21641      return getParentBlock$2(SugarElement.fromDom(root), SugarElement.fromDom(from.getNode())).map(blockElm => isEmpty$2(schema, blockElm) ? DeleteAction.remove(blockElm.dom) : DeleteAction.moveToElement(toCefElm)).orThunk(() => Optional.some(DeleteAction.moveToElement(toCefElm)));
21642    };
21643    const findCefPosition = (root, forward, from, schema) => fromPosition(forward, root, from).bind(to => {
21644      if (isCompoundElement(to.getNode())) {
21645        return Optional.none();
21646      } else if (isDeleteFromCefDifferentBlocks(root, forward, from, to, schema)) {
21647        return Optional.none();
21648      } else if (forward && isContentEditableFalse$b(to.getNode())) {
21649        return deleteEmptyBlockOrMoveToCef(schema, root, forward, from, to);
21650      } else if (!forward && isContentEditableFalse$b(to.getNode(true))) {
21651        return deleteEmptyBlockOrMoveToCef(schema, root, forward, from, to);
21652      } else if (forward && isAfterContentEditableFalse(from)) {
21653        return Optional.some(DeleteAction.moveToPosition(to));
21654      } else if (!forward && isBeforeContentEditableFalse(from)) {
21655        return Optional.some(DeleteAction.moveToPosition(to));
21656      } else {
21657        return Optional.none();
21658      }
21659    });
21660    const getContentEditableBlockAction = (forward, elm) => {
21661      if (isNullable(elm)) {
21662        return Optional.none();
21663      } else if (forward && isContentEditableFalse$b(elm.nextSibling)) {
21664        return Optional.some(DeleteAction.moveToElement(elm.nextSibling));
21665      } else if (!forward && isContentEditableFalse$b(elm.previousSibling)) {
21666        return Optional.some(DeleteAction.moveToElement(elm.previousSibling));
21667      } else {
21668        return Optional.none();
21669      }
21670    };
21671    const skipMoveToActionFromInlineCefToContent = (root, from, deleteAction) => deleteAction.fold(elm => Optional.some(DeleteAction.remove(elm)), elm => Optional.some(DeleteAction.moveToElement(elm)), to => {
21672      if (isInSameBlock(from, to, root)) {
21673        return Optional.none();
21674      } else {
21675        return Optional.some(DeleteAction.moveToPosition(to));
21676      }
21677    });
21678    const getContentEditableAction = (root, forward, from, schema) => {
21679      if (isAtContentEditableBlockCaret(forward, from)) {
21680        return getContentEditableBlockAction(forward, from.getNode(!forward)).orThunk(() => findCefPosition(root, forward, from, schema));
21681      } else {
21682        return findCefPosition(root, forward, from, schema).bind(deleteAction =>
21682 skipMoveToActionFromInlineCefToContent(root, from, deleteAction));
21683      }
21684    };
21685    const read = (root, forward, rng, schema) => {
21686      const normalizedRange = normalizeRange(forward ? 1 : -1, root, rng);
21687      const from = CaretPosition.fromRangeStart(normalizedRange);
21688      const rootElement = SugarElement.fromDom(root);
21689      if (!forward && isAfterContentEditableFalse(from)) {
21690        return Optional.some(DeleteAction.remove(from.getNode(true)));
21691      } else if (forward && isBeforeContentEditableFalse(from)) {
21692        return Optional.some(DeleteAction.remove(from.getNode()));
21693      } else if (!forward && isBeforeContentEditableFalse(from) && isAfterBr(rootElement, from, schema)) {
21694        return findPreviousBr(rootElement, from, schema).map(br => DeleteAction.remove(br.getNode()));
21695      } else if (forward && isAfterContentEditableFalse(from) && isBeforeBr$1(rootElement, from, schema)) {
21696        return findNextBr(rootElement, from, schema).map(br => DeleteAction.remove(br.getNode()));
21697      } else {
21698        return getContentEditableAction(root, forward, from, schema);
21699      }
21700    };
21701
21702    const deleteElement$1 = (editor, forward) => element => {
21703      editor._selectionOverrides.hideFakeCaret();
21704      deleteElement$2(editor, forward, SugarElement.fromDom(element));
21705      return true;
21706    };
21707    const moveToElement = (editor, forward) => element => {
21708      const pos = forward ? CaretPosition.before(element) : CaretPosition.after(element);
21709      editor.selection.setRng(pos.toRange());
21710      return true;
21711    };
21712    const moveToPosition = editor => pos => {
21713      editor.selection.setRng(pos.toRange());
21714      return true;
21715    };
21716    const getAncestorCe = (editor, node) => Optional.from(getContentEditableRoot$1(editor.getBody(), node));
21717    const backspaceDeleteCaret = (editor, forward) => {
21718      const selectedNode = editor.selection.getNode();
21719      return getAncestorCe(editor, selectedNode).filter(isContentEditableFalse$b).fold(() => read(editor.getBody(), forward, editor.selection.getRng(), editor.schema).map(deleteAction => () => deleteAction.fold(deleteElement$1(editor, forward), moveToElement(editor, forward), moveToPosition(editor))), () => Optional.some(noop));
21720    };
21721    const deleteOffscreenSelection = rootElement => {
21722      each$e(descendants(rootElement, '.mce-offscreen-selection'), remove$4);
21723    };
21724    const backspaceDeleteRange = (editor, forward) => {
21725      const selectedNode = editor.selection.getNode();
21726      if (isContentEditableFalse$b(selectedNode) && !isTableCell$3(selectedNode)) {
21727        const hasCefAncestor = getAncestorCe(editor, selectedNode.parentNode).filter(isContentEditableFalse$b);
21728        return hasCefAncestor.fold(() => Optional.some(() => {
21729          deleteOffscreenSelection(SugarElement.fromDom(editor.getBody()));
21730          deleteElement$2(editor, forward, SugarElement.fromDom(editor.selection.getNode()));
21731          paddEmptyBody(editor);
21732        }), () => Optional.some(noop));
21733      }
21734      if (isCefAtEdgeSelected(editor)) {
21735        return Optional.some(() => {
21736          deleteRangeContents(editor, editor.selection.getRng(), SugarElement.fromDom(editor.getBody()));
21737        });
21738      }
21739      return Optional.none();
21740    };
21741    const paddEmptyElement = editor => {
21742      const dom = editor.dom, selection = editor.selection;
21743      const ceRoot = getContentEditableRoot$1(editor.getBody(), selection.getNode());
21744      if (isContentEditableTrue$3(ceRoot) && dom.isBlock(ceRoot) && dom.isEmpty(ceRoot)) {
21745        const br = dom.create('br', { 'data-mce-bogus': '1' });
21746        dom.setHTML(ceRoot, '');
21747        ceRoot.appendChild(br);
21748        selection.setRng(CaretPosition.before(br).toRange());
21749      }
21750      return true;
21751    };
21752    const backspaceDelete$7 = (editor, forward) => {
21753      if (editor.selection.isCollapsed()) {
21754        return backspaceDeleteCaret(editor, forward);
21755      } else {
21756        return backspaceDeleteRange(editor, forward);
21757      }
21758    };
21759
21760    const isTextEndpoint = endpoint => endpoint.hasOwnProperty('text');
21761    const isElementEndpoint = endpoint => endpoint.hasOwnProperty('marker');
21762    const getBookmark = (range, createMarker) => {
21763      const getEndpoint = (container, offset) => {
21764        if (isText$b(container)) {
21765          return {
21766            text: container,
21767            offset
21768          };
21769        } else {
21770          const marker = createMarker();
21771          const children = container.childNodes;
21772          if (offset < children.length) {
21773            container.insertBefore(marker, children[offset]);
21774            return {
21775              marker,
21776              before: true
21777            };
21778          } else {
21779            container.appendChild(marker);
21780            return {
21781              marker,
21782              before: false
21783            };
21784          }
21785        }
21786      };
21787      const end = getEndpoint(range.endContainer, range.endOffset);
21788      const start = getEndpoint(range.startContainer, range.startOffset);
21789      return {
21790        start,
21791        end
21792      };
21793    };
21794    const resolveBookmark = bm => {
21795      var _a, _b;
21796      const {start, end} = bm;
21797      const rng = new window.Range();
21798      if (isTextEndpoint(start)) {
21799        rng.setStart(start.text, start.offset);
21800      } else {
21801        if (isElementEndpoint(start)) {
21802          if (start.before) {
21803            rng.setStartBefore(start.marker);
21804          } else {
21805            rng.setStartAfter(start.marker);
21806          }
21807          (_a = start.marker.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(start.marker);
21808        }
21809      }
21810      if (isTextEndpoint(end)) {
21811        rng.setEnd(end.text, end.offset);
21812      } else {
21813        if (isElementEndpoint(end)) {
21814          if (end.before) {
21815            rng.setEndBefore(end.marker);
21816          } else {
21817            rng.setEndAfter(end.marker);
21818          }
21819          (_b = end.marker.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(end.marker);
21820        }
21821      }
21822      return rng;
21823    };
21824
21825    const backspaceDelete$6 = (editor, forward) => {
21826      var _a;
21827      const dom = editor.dom;
21828      const startBlock = dom.getParent(editor.selection.getStart(), dom.isBlock);
21829      const endBlock = dom.getParent(editor.selection.getEnd(), dom.isBlock);
21830      const body = editor.getBody();
21831      const startBlockName = (_a = startBlock === null || startBlock === void 0 ? void 0 : startBlock.nodeName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
21832      if (startBlockName === 'div' && startBlock && endBlock && startBlock === body.firstChild && endBlock === body.lastChild && !dom.isEmpty(body)) {
21833        const wrapper = startBlock.cloneNode(false);
21834        const deleteAction = () => {
21835          if (forward) {
21836            execNativeForwardDeleteCommand(editor);
21837          } else {
21838            execNativeDeleteCommand(editor);
21839          }
21840          if (body.firstChild !== startBlock) {
21841            const bookmark = getBookmark(editor.selection.getRng(), () => document.createElement('span'));
vendor: 20,843 bytes, lines 21842-22312
21842            Array.from(body.childNodes).forEach(node => wrapper.appendChild(node));
21843            body.appendChild(wrapper);
21844            editor.selection.setRng(resolveBookmark(bookmark));
21845          }
21846        };
21847        return Optional.some(deleteAction);
21848      }
21849      return Optional.none();
21850    };
21851
21852    const deleteCaret$2 = (editor, forward) => {
21853      const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
21854      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));
21855    };
21856    const backspaceDelete$5 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret$2(editor, forward) : Optional.none();
21857
21858    const isText$2 = isText$b;
21859    const startsWithCaretContainer = node => isText$2(node) && node.data[0] === ZWSP$1;
21860    const endsWithCaretContainer = node => isText$2(node) && node.data[node.data.length - 1] === ZWSP$1;
21861    const createZwsp = node => {
21862      var _a;
21863      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
21864      return doc.createTextNode(ZWSP$1);
21865    };
21866    const insertBefore$1 = node => {
21867      var _a;
21868      if (isText$2(node.previousSibling)) {
21869        if (endsWithCaretContainer(node.previousSibling)) {
21870          return node.previousSibling;
21871        } else {
21872          node.previousSibling.appendData(ZWSP$1);
21873          return node.previousSibling;
21874        }
21875      } else if (isText$2(node)) {
21876        if (startsWithCaretContainer(node)) {
21877          return node;
21878        } else {
21879          node.insertData(0, ZWSP$1);
21880          return node;
21881        }
21882      } else {
21883        const newNode = createZwsp(node);
21884        (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newNode, node);
21885        return newNode;
21886      }
21887    };
21888    const insertAfter$1 = node => {
21889      var _a, _b;
21890      if (isText$2(node.nextSibling)) {
21891        if (startsWithCaretContainer(node.nextSibling)) {
21892          return node.nextSibling;
21893        } else {
21894          node.nextSibling.insertData(0, ZWSP$1);
21895          return node.nextSibling;
21896        }
21897      } else if (isText$2(node)) {
21898        if (endsWithCaretContainer(node)) {
21899          return node;
21900        } else {
21901          node.appendData(ZWSP$1);
21902          return node;
21903        }
21904      } else {
21905        const newNode = createZwsp(node);
21906        if (node.nextSibling) {
21907          (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newNode, node.nextSibling);
21908        } else {
21909          (_b = node.parentNode) === null || _b === void 0 ? void 0 : _b.appendChild(newNode);
21910        }
21911        return newNode;
21912      }
21913    };
21914    const insertInline = (before, node) => before ? insertBefore$1(node) : insertAfter$1(node);
21915    const insertInlineBefore = curry(insertInline, true);
21916    const insertInlineAfter = curry(insertInline, false);
21917
21918    const insertInlinePos = (pos, before) => {
21919      if (isText$b(pos.container())) {
21920        return insertInline(before, pos.container());
21921      } else {
21922        return insertInline(before, pos.getNode());
21923      }
21924    };
21925    const isPosCaretContainer = (pos, caret) => {
21926      const caretNode = caret.get();
21927      return caretNode && pos.container() === caretNode && isCaretContainerInline(caretNode);
21928    };
21929    const renderCaret = (caret, location) => location.fold(element => {
21930      remove$2(caret.get());
21931      const text = insertInlineBefore(element);
21932      caret.set(text);
21933      return Optional.some(CaretPosition(text, text.length - 1));
21934    }, element => firstPositionIn(element).map(pos => {
21935      if (!isPosCaretContainer(pos, caret)) {
21936        remove$2(caret.get());
21937        const text = insertInlinePos(pos, true);
21938        caret.set(text);
21939        return CaretPosition(text, 1);
21940      } else {
21941        const node = caret.get();
21942        return CaretPosition(node, 1);
21943      }
21944    }), element => lastPositionIn(element).map(pos => {
21945      if (!isPosCaretContainer(pos, caret)) {
21946        remove$2(caret.get());
21947        const text = insertInlinePos(pos, false);
21948        caret.set(text);
21949        return CaretPosition(text, text.length - 1);
21950      } else {
21951        const node = caret.get();
21952        return CaretPosition(node, node.length - 1);
21953      }
21954    }), element => {
21955      remove$2(caret.get());
21956      const text = insertInlineAfter(element);
21957      caret.set(text);
21958      return Optional.some(CaretPosition(text, 1));
21959    });
21960
21961    const evaluateUntil = (fns, args) => {
21962      for (let i = 0; i < fns.length; i++) {
21963        const result = fns[i].apply(null, args);
21964        if (result.isSome()) {
21965          return result;
21966        }
21967      }
21968      return Optional.none();
21969    };
21970
21971    const Location = Adt.generate([
21972      { before: ['element'] },
21973      { start: ['element'] },
21974      { end: ['element'] },
21975      { after: ['element'] }
21976    ]);
21977    const rescope$1 = (rootNode, node) => {
21978      const parentBlock = getParentBlock$3(node, rootNode);
21979      return parentBlock ? parentBlock : rootNode;
21980    };
21981    const before = (isInlineTarget, rootNode, pos) => {
21982      const nPos = normalizeForwards(pos);
21983      const scope = rescope$1(rootNode, nPos.container());
21984      return findRootInline(isInlineTarget, scope, nPos).fold(() => nextPosition(scope, nPos).bind(curry(findRootInline, isInlineTarget, scope)).map(inline => Location.before(inline)), Optional.none);
21985    };
21986    const isNotInsideFormatCaretContainer = (rootNode, elm) => getParentCaretContainer(rootNode, elm) === null;
21987    const findInsideRootInline = (isInlineTarget, rootNode, pos) => findRootInline(isInlineTarget, rootNode, pos).filter(curry(isNotInsideFormatCaretContainer, rootNode));
21988    const start$1 = (isInlineTarget, rootNode, pos) => {
21989      const nPos = normalizeBackwards(pos);
21990      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(inline => {
21991        const prevPos = prevPosition(inline, nPos);
21992        return prevPos.isNone() ? Optional.some(Location.start(inline)) : Optional.none();
21993      });
21994    };
21995    const end = (isInlineTarget, rootNode, pos) => {
21996      const nPos = normalizeForwards(pos);
21997      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(inline => {
21998        const nextPos = nextPosition(inline, nPos);
21999        return nextPos.isNone() ? Optional.some(Location.end(inline)) : Optional.none();
22000      });
22001    };
22002    const after = (isInlineTarget, rootNode, pos) => {
22003      const nPos = normalizeBackwards(pos);
22004      const scope = rescope$1(rootNode, nPos.container());
22005      return findRootInline(isInlineTarget, scope, nPos).fold(() => prevPosition(scope, nPos).bind(curry(findRootInline, isInlineTarget, scope)).map(inline => Location.after(inline)), Optional.none);
22006    };
22007    const isValidLocation = location => !isRtl(getElement(location));
22008    const readLocation = (isInlineTarget, rootNode, pos) => {
22009      const location = evaluateUntil([
22010        before,
22011        start$1,
22012        end,
22013        after
22014      ], [
22015        isInlineTarget,
22016        rootNode,
22017        pos
22018      ]);
22019      return location.filter(isValidLocation);
22020    };
22021    const getElement = location => location.fold(identity, identity, identity, identity);
22022    const getName = location => location.fold(constant('before'), constant('start'), constant('end'), constant('after'));
22023    const outside = location => location.fold(Location.before, Location.before, Location.after, Location.after);
22024    const inside = location => location.fold(Location.start, Location.start, Location.end, Location.end);
22025    const isEq = (location1, location2) => getName(location1) === getName(location2) && getElement(location1) === getElement(location2);
22026    const betweenInlines = (forward, isInlineTarget, rootNode, from, to, location) => lift2(findRootInline(isInlineTarget, rootNode, from), findRootInline(isInlineTarget, rootNode, to), (fromInline, toInline) => {
22027      if (fromInline !== toInline && hasSameParentBlock(rootNode, fromInline, toInline)) {
22028        return Location.after(forward ? fromInline : toInline);
22029      } else {
22030        return location;
22031      }
22032    }).getOr(location);
22033    const skipNoMovement = (fromLocation, toLocation) => fromLocation.fold(always, fromLocation => !isEq(fromLocation, toLocation));
22034    const findLocationTraverse = (forward, isInlineTarget, rootNode, fromLocation, pos) => {
22035      const from = normalizePosition(forward, pos);
22036      const to = fromPosition(forward, rootNode, from).map(curry(normalizePosition, forward));
22037      const location = to.fold(() => fromLocation.map(outside), to => readLocation(isInlineTarget, rootNode, to).map(curry(betweenInlines, forward, isInlineTarget, rootNode, from, to)).filter(curry(skipNoMovement, fromLocation)));
22038      return location.filter(isValidLocation);
22039    };
22040    const findLocationSimple = (forward, location) => {
22041      if (forward) {
22042        return location.fold(compose(Optional.some, Location.start), Optional.none, compose(Optional.some, Location.after), Optional.none);
22043      } else {
22044        return location.fold(Optional.none, compose(Optional.some, Location.before), Optional.none, compose(Optional.some, Location.end));
22045      }
22046    };
22047    const findLocation$1 = (forward, isInlineTarget, rootNode, pos) => {
22048      const from = normalizePosition(forward, pos);
22049      const fromLocation = readLocation(isInlineTarget, rootNode, from);
22050      return readLocation(isInlineTarget, rootNode, from).bind(curry(findLocationSimple, forward)).orThunk(() => findLocationTraverse(forward, isInlineTarget, rootNode, fromLocation, pos));
22051    };
22052
22053    const hasSelectionModifyApi = editor => {
22054      return isFunction(editor.selection.getSel().modify);
22055    };
22056    const moveRel = (forward, selection, pos) => {
22057      const delta = forward ? 1 : -1;
22058      selection.setRng(CaretPosition(pos.container(), pos.offset() + delta).toRange());
22059      selection.getSel().modify('move', forward ? 'forward' : 'backward', 'word');
22060      return true;
22061    };
22062    const moveByWord = (forward, editor) => {
22063      const rng = editor.selection.getRng();
22064      const pos = forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng);
22065      if (!hasSelectionModifyApi(editor)) {
22066        return false;
22067      } else if (forward && isBeforeInline(pos)) {
22068        return moveRel(true, editor.selection, pos);
22069      } else if (!forward && isAfterInline(pos)) {
22070        return moveRel(false, editor.selection, pos);
22071      } else {
22072        return false;
22073      }
22074    };
22075
22076    var BreakType;
22077    (function (BreakType) {
22078      BreakType[BreakType['Br'] = 0] = 'Br';
22079      BreakType[BreakType['Block'] = 1] = 'Block';
22080      BreakType[BreakType['Wrap'] = 2] = 'Wrap';
22081      BreakType[BreakType['Eol'] = 3] = 'Eol';
22082    }(BreakType || (BreakType = {})));
22083    const flip = (direction, positions) => direction === -1 ? reverse(positions) : positions;
22084    const walk$1 = (direction, caretWalker, pos) => direction === 1 ? caretWalker.next(pos) : caretWalker.prev(pos);
22085    const getBreakType = (scope, direction, currentPos, nextPos) => {
22086      if (isBr$6(nextPos.getNode(direction === 1))) {
22087        return BreakType.Br;
22088      } else if (isInSameBlock(currentPos, nextPos) === false) {
22089        return BreakType.Block;
22090      } else {
22091        return BreakType.Wrap;
22092      }
22093    };
22094    const getPositionsUntil = (predicate, direction, scope, start) => {
22095      const caretWalker = CaretWalker(scope);
22096      let currentPos = start;
22097      const positions = [];
22098      while (currentPos) {
22099        const nextPos = walk$1(direction, caretWalker, currentPos);
22100        if (!nextPos) {
22101          break;
22102        }
22103        if (isBr$6(nextPos.getNode(false))) {
22104          if (direction === 1) {
22105            return {
22106              positions: flip(direction, positions).concat([nextPos]),
22107              breakType: BreakType.Br,
22108              breakAt: Optional.some(nextPos)
22109            };
22110          } else {
22111            return {
22112              positions: flip(direction, positions),
22113              breakType: BreakType.Br,
22114              breakAt: Optional.some(nextPos)
22115            };
22116          }
22117        }
22118        if (!nextPos.isVisible()) {
22119          currentPos = nextPos;
22120          continue;
22121        }
22122        if (predicate(currentPos, nextPos)) {
22123          const breakType = getBreakType(scope, direction, currentPos, nextPos);
22124          return {
22125            positions: flip(direction, positions),
22126            breakType,
22127            breakAt: Optional.some(nextPos)
22128          };
22129        }
22130        positions.push(nextPos);
22131        currentPos = nextPos;
22132      }
22133      return {
22134        positions: flip(direction, positions),
22135        breakType: BreakType.Eol,
22136        breakAt: Optional.none()
22137      };
22138    };
22139    const getAdjacentLinePositions = (direction, getPositionsUntilBreak, scope, start) => getPositionsUntilBreak(scope, start).breakAt.map(pos => {
22140      const positions = getPositionsUntilBreak(scope, pos).positions;
22141      return direction === -1 ? positions.concat(pos) : [pos].concat(positions);
22142    }).getOr([]);
22143    const findClosestHorizontalPositionFromPoint = (positions, x) => foldl(positions, (acc, newPos) => acc.fold(() => Optional.some(newPos), lastPos => lift2(head(lastPos.getClientRects()), head(newPos.getClientRects()), (lastRect, newRect) => {
22144      const lastDist = Math.abs(x - lastRect.left);
22145      const newDist = Math.abs(x - newRect.left);
22146      return newDist <= lastDist ? newPos : lastPos;
22147    }).or(acc)), Optional.none());
22148    const findClosestHorizontalPosition = (positions, pos) => head(pos.getClientRects()).bind(targetRect => findClosestHorizontalPositionFromPoint(positions, targetRect.left));
22149    const getPositionsUntilPreviousLine = curry(getPositionsUntil, CaretPosition.isAbove, -1);
22150    const getPositionsUntilNextLine = curry(getPositionsUntil, CaretPosition.isBelow, 1);
22151    const getPositionsAbove = curry(getAdjacentLinePositions, -1, getPositionsUntilPreviousLine);
22152    const getPositionsBelow = curry(getAdjacentLinePositions, 1, getPositionsUntilNextLine);
22153    const isAtFirstLine = (scope, pos) => getPositionsUntilPreviousLine(scope, pos).breakAt.isNone();
22154    const isAtLastLine = (scope, pos) => getPositionsUntilNextLine(scope, pos).breakAt.isNone();
22155    const getFirstLinePositions = scope => firstPositionIn(scope).map(pos => [pos].concat(getPositionsUntilNextLine(scope, pos).positions)).getOr([]);
22156    const getLastLinePositions = scope => lastPositionIn(scope).map(pos => getPositionsUntilPreviousLine(scope, pos).positions.concat(pos)).getOr([]);
22157    const getClosestPositionAbove = (scope, pos) => findClosestHorizontalPosition(getPositionsAbove(scope, pos), pos);
22158    const getClosestPositionBelow = (scope, pos) => findClosestHorizontalPosition(getPositionsBelow(scope, pos), pos);
22159
22160    const isContentEditableFalse$5 = isContentEditableFalse$b;
22161    const distanceToRectLeft$1 = (clientRect, clientX) => Math.abs(clientRect.left - clientX);
22162    const distanceToRectRight$1 = (clientRect, clientX) => Math.abs(clientRect.right - clientX);
22163    const isNodeClientRect = rect => hasNonNullableKey(rect, 'node');
22164    const findClosestClientRect = (clientRects, clientX) => reduce(clientRects, (oldClientRect, clientRect) => {
22165      const oldDistance = Math.min(distanceToRectLeft$1(oldClientRect, clientX), distanceToRectRight$1(oldClientRect, clientX));
22166      const newDistance = Math.min(distanceToRectLeft$1(clientRect, clientX), distanceToRectRight$1(clientRect, clientX));
22167      if (newDistance === oldDistance && isNodeClientRect(clientRect) && isContentEditableFalse$5(clientRect.node)) {
22168        return clientRect;
22169      }
22170      if (newDistance < oldDistance) {
22171        return clientRect;
22172      }
22173      return oldClientRect;
22174    });
22175
22176    const getNodeClientRects = node => {
22177      const toArrayWithNode = clientRects => {
22178        return map$3(clientRects, rect => {
22179          const clientRect = clone$1(rect);
22180          clientRect.node = node;
22181          return clientRect;
22182        });
22183      };
22184      if (isElement$6(node)) {
22185        return toArrayWithNode(node.getClientRects());
22186      } else if (isText$b(node)) {
22187        const rng = node.ownerDocument.createRange();
22188        rng.setStart(node, 0);
22189        rng.setEnd(node, node.data.length);
22190        return toArrayWithNode(rng.getClientRects());
22191      } else {
22192        return [];
22193      }
22194    };
22195    const getClientRects = nodes => bind$3(nodes, getNodeClientRects);
22196
22197    var VDirection;
22198    (function (VDirection) {
22199      VDirection[VDirection['Up'] = -1] = 'Up';
22200      VDirection[VDirection['Down'] = 1] = 'Down';
22201    }(VDirection || (VDirection = {})));
22202    const findUntil = (direction, root, predicateFn, node) => {
22203      let currentNode = node;
22204      while (currentNode = findNode(currentNode, direction, isEditableCaretCandidate$1, root)) {
22205        if (predicateFn(currentNode)) {
22206          return;
22207        }
22208      }
22209    };
22210    const walkUntil = (direction, isAboveFn, isBeflowFn, root, predicateFn, caretPosition) => {
22211      let line = 0;
22212      const result = [];
22213      const add = node => {
22214        let clientRects = getClientRects([node]);
22215        if (direction === VDirection.Up) {
22216          clientRects = clientRects.reverse();
22217        }
22218        for (let i = 0; i < clientRects.length; i++) {
22219          const clientRect = clientRects[i];
22220          if (isBeflowFn(clientRect, targetClientRect)) {
22221            continue;
22222          }
22223          if (result.length > 0 && isAboveFn(clientRect, last$1(result))) {
22224            line++;
22225          }
22226          clientRect.line = line;
22227          if (predicateFn(clientRect)) {
22228            return true;
22229          }
22230          result.push(clientRect);
22231        }
22232        return false;
22233      };
22234      const targetClientRect = last$1(caretPosition.getClientRects());
22235      if (!targetClientRect) {
22236        return result;
22237      }
22238      const node = caretPosition.getNode();
22239      if (node) {
22240        add(node);
22241        findUntil(direction, root, add, node);
22242      }
22243      return result;
22244    };
22245    const aboveLineNumber = (lineNumber, clientRect) => clientRect.line > lineNumber;
22246    const isLineNumber = (lineNumber, clientRect) => clientRect.line === lineNumber;
22247    const upUntil = curry(walkUntil, VDirection.Up, isAbove$1, isBelow$1);
22248    const downUntil = curry(walkUntil, VDirection.Down, isBelow$1, isAbove$1);
22249    const getLastClientRect = caretPosition => {
22250      return last$1(caretPosition.getClientRects());
22251    };
22252    const positionsUntil = (direction, root, predicateFn, node) => {
22253      const caretWalker = CaretWalker(root);
22254      let walkFn;
22255      let isBelowFn;
22256      let isAboveFn;
22257      let caretPosition;
22258      const result = [];
22259      let line = 0;
22260      if (direction === VDirection.Down) {
22261        walkFn = caretWalker.next;
22262        isBelowFn = isBelow$1;
22263        isAboveFn = isAbove$1;
22264        caretPosition = CaretPosition.after(node);
22265      } else {
22266        walkFn = caretWalker.prev;
22267        isBelowFn = isAbove$1;
22268        isAboveFn = isBelow$1;
22269        caretPosition = CaretPosition.before(node);
22270      }
22271      const targetClientRect = getLastClientRect(caretPosition);
22272      do {
22273        if (!caretPosition.isVisible()) {
22274          continue;
22275        }
22276        const rect = getLastClientRect(caretPosition);
22277        if (isAboveFn(rect, targetClientRect)) {
22278          continue;
22279        }
22280        if (result.length > 0 && isBelowFn(rect, last$1(result))) {
22281          line++;
22282        }
22283        const clientRect = clone$1(rect);
22284        clientRect.position = caretPosition;
22285        clientRect.line = line;
22286        if (predicateFn(clientRect)) {
22287          return result;
22288        }
22289        result.push(clientRect);
22290      } while (caretPosition = walkFn(caretPosition));
22291      return result;
22292    };
22293    const isAboveLine = lineNumber => clientRect => aboveLineNumber(lineNumber, clientRect);
22294    const isLine = lineNumber => clientRect => isLineNumber(lineNumber, clientRect);
22295
22296    const moveToRange = (editor, rng) => {
22297      editor.selection.setRng(rng);
22298      scrollRangeIntoView(editor, editor.selection.getRng());
22299    };
22300    const renderRangeCaretOpt = (editor, range, scrollIntoView) => Optional.some(renderRangeCaret(editor, range, scrollIntoView));
22301    const moveHorizontally = (editor, direction, range, isBefore, isAfter, isElement) => {
22302      const forwards = direction === 1;
22303      const caretWalker = CaretWalker(editor.getBody());
22304      const getNextPosFn = curry(getVisualCaretPosition, forwards ? caretWalker.next : caretWalker.prev);
22305      const isBeforeFn = forwards ? isBefore : isAfter;
22306      if (!range.collapsed) {
22307        const node = getSelectedNode(range);
22308        if (isElement(node)) {
22309          return showCaret(direction, editor, node, direction === -1, false);
22310        } else if (isCefAtEdgeSelected(editor)) {
22311          const newRange = range.cloneRange();
22312          newRange.collapse(direction === -1
vendor: 18,279 bytes, lines 22312-22678
22312);
22313          return Optional.from(newRange);
22314        }
22315      }
22316      const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
22317      if (isBeforeFn(caretPosition)) {
22318        return selectNode(editor, caretPosition.getNode(!forwards));
22319      }
22320      let nextCaretPosition = getNextPosFn(caretPosition);
22321      const rangeIsInContainerBlock = isRangeInCaretContainerBlock(range);
22322      if (!nextCaretPosition) {
22323        return rangeIsInContainerBlock ? Optional.some(range) : Optional.none();
22324      } else {
22325        nextCaretPosition = normalizePosition(forwards, nextCaretPosition);
22326      }
22327      if (isBeforeFn(nextCaretPosition)) {
22328        return showCaret(direction, editor, nextCaretPosition.getNode(!forwards), forwards, false);
22329      }
22330      const peekCaretPosition = getNextPosFn(nextCaretPosition);
22331      if (peekCaretPosition && isBeforeFn(peekCaretPosition)) {
22332        if (isMoveInsideSameBlock(nextCaretPosition, peekCaretPosition)) {
22333          return showCaret(direction, editor, peekCaretPosition.getNode(!forwards), forwards, false);
22334        }
22335      }
22336      if (rangeIsInContainerBlock) {
22337        return renderRangeCaretOpt(editor, nextCaretPosition.toRange(), false);
22338      }
22339      return Optional.none();
22340    };
22341    const moveVertically = (editor, direction, range, isBefore, isAfter, isElement) => {
22342      const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
22343      const caretClientRect = last$1(caretPosition.getClientRects());
22344      const forwards = direction === VDirection.Down;
22345      const root = editor.getBody();
22346      if (!caretClientRect) {
22347        return Optional.none();
22348      }
22349      if (isCefAtEdgeSelected(editor)) {
22350        const caretPosition = forwards ? CaretPosition.fromRangeEnd(range) : CaretPosition.fromRangeStart(range);
22351        const getClosestFn = !forwards ? getClosestPositionAbove : getClosestPositionBelow;
22352        return getClosestFn(root, caretPosition).orThunk(() => Optional.from(caretPosition)).map(pos => pos.toRange());
22353      }
22354      const walkerFn = forwards ? downUntil : upUntil;
22355      const linePositions = walkerFn(root, isAboveLine(1), caretPosition);
22356      const nextLinePositions = filter$5(linePositions, isLine(1));
22357      const clientX = caretClientRect.left;
22358      const nextLineRect = findClosestClientRect(nextLinePositions, clientX);
22359      if (nextLineRect && isElement(nextLineRect.node)) {
22360        const dist1 = Math.abs(clientX - nextLineRect.left);
22361        const dist2 = Math.abs(clientX - nextLineRect.right);
22362        return showCaret(direction, editor, nextLineRect.node, dist1 < dist2, false);
22363      }
22364      let currentNode;
22365      if (isBefore(caretPosition)) {
22366        currentNode = caretPosition.getNode();
22367      } else if (isAfter(caretPosition)) {
22368        currentNode = caretPosition.getNode(true);
22369      } else {
22370        currentNode = getSelectedNode(range);
22371      }
22372      if (currentNode) {
22373        const caretPositions = positionsUntil(direction, root, isAboveLine(1), currentNode);
22374        let closestNextLineRect = findClosestClientRect(filter$5(caretPositions, isLine(1)), clientX);
22375        if (closestNextLineRect) {
22376          return renderRangeCaretOpt(editor, closestNextLineRect.position.toRange(), false);
22377        }
22378        closestNextLineRect = last$1(filter$5(caretPositions, isLine(0)));
22379        if (closestNextLineRect) {
22380          return renderRangeCaretOpt(editor, closestNextLineRect.position.toRange(), false);
22381        }
22382      }
22383      if (nextLinePositions.length === 0) {
22384        return getLineEndPoint(editor, forwards).filter(forwards ? isAfter : isBefore).map(pos => renderRangeCaret(editor, pos.toRange(), false));
22385      }
22386      return Optional.none();
22387    };
22388    const getLineEndPoint = (editor, forward) => {
22389      const rng = editor.selection.getRng();
22390      const from = forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng);
22391      const host = getEditingHost(from.container(), editor.getBody());
22392      if (forward) {
22393        const lineInfo = getPositionsUntilNextLine(host, from);
22394        return last$2(lineInfo.positions);
22395      } else {
22396        const lineInfo = getPositionsUntilPreviousLine(host, from);
22397        return head(lineInfo.positions);
22398      }
22399    };
22400    const moveToLineEndPoint$3 = (editor, forward, isElementPosition) => getLineEndPoint(editor, forward).filter(isElementPosition).exists(pos => {
22401      editor.selection.setRng(pos.toRange());
22402      return true;
22403    });
22404
22405    const setCaretPosition = (editor, pos) => {
22406      const rng = editor.dom.createRng();
22407      rng.setStart(pos.container(), pos.offset());
22408      rng.setEnd(pos.container(), pos.offset());
22409      editor.selection.setRng(rng);
22410    };
22411    const setSelected = (state, elm) => {
22412      if (state) {
22413        elm.setAttribute('data-mce-selected', 'inline-boundary');
22414      } else {
22415        elm.removeAttribute('data-mce-selected');
22416      }
22417    };
22418    const renderCaretLocation = (editor, caret, location) => renderCaret(caret, location).map(pos => {
22419      setCaretPosition(editor, pos);
22420      return location;
22421    });
22422    const getPositionFromRange = (range, root, forward) => {
22423      const start = CaretPosition.fromRangeStart(range);
22424      if (range.collapsed) {
22425        return start;
22426      } else {
22427        const end = CaretPosition.fromRangeEnd(range);
22428        return forward ? prevPosition(root, end).getOr(end) : nextPosition(root, start).getOr(start);
22429      }
22430    };
22431    const findLocation = (editor, caret, forward) => {
22432      const rootNode = editor.getBody();
22433      const from = getPositionFromRange(editor.selection.getRng(), rootNode, forward);
22434      const isInlineTarget$1 = curry(isInlineTarget, editor);
22435      const location = findLocation$1(forward, isInlineTarget$1, rootNode, from);
22436      return location.bind(location => renderCaretLocation(editor, caret, location));
22437    };
22438    const toggleInlines = (isInlineTarget, dom, elms) => {
22439      const inlineBoundaries = map$3(descendants(SugarElement.fromDom(dom.getRoot()), '*[data-mce-selected="inline-boundary"]'), e => e.dom);
22440      const selectedInlines = filter$5(inlineBoundaries, isInlineTarget);
22441      const targetInlines = filter$5(elms, isInlineTarget);
22442      each$e(difference(selectedInlines, targetInlines), curry(setSelected, false));
22443      each$e(difference(targetInlines, selectedInlines), curry(setSelected, true));
22444    };
22445    const safeRemoveCaretContainer = (editor, caret) => {
22446      const caretValue = caret.get();
22447      if (editor.selection.isCollapsed() && !editor.composing && caretValue) {
22448        const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
22449        if (CaretPosition.isTextPosition(pos) && !isAtZwsp(pos)) {
22450          setCaretPosition(editor, removeAndReposition(caretValue, pos));
22451          caret.set(null);
22452        }
22453      }
22454    };
22455    const renderInsideInlineCaret = (isInlineTarget, editor, caret, elms) => {
22456      if (editor.selection.isCollapsed()) {
22457        const inlines = filter$5(elms, isInlineTarget);
22458        each$e(inlines, _inline => {
22459          const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
22460          readLocation(isInlineTarget, editor.getBody(), pos).bind(location => renderCaretLocation(editor, caret, location));
22461        });
22462      }
22463    };
22464    const move$3 = (editor, caret, forward) => isInlineBoundariesEnabled(editor) ? findLocation(editor, caret, forward).isSome() : false;
22465    const moveWord = (forward, editor, _caret) => isInlineBoundariesEnabled(editor) ? moveByWord(forward, editor) : false;
22466    const setupSelectedState = editor => {
22467      const caret = Cell(null);
22468      const isInlineTarget$1 = curry(isInlineTarget, editor);
22469      editor.on('NodeChange', e => {
22470        if (isInlineBoundariesEnabled(editor)) {
22471          toggleInlines(isInlineTarget$1, editor.dom, e.parents);
22472          safeRemoveCaretContainer(editor, caret);
22473          renderInsideInlineCaret(isInlineTarget$1, editor, caret, e.parents);
22474        }
22475      });
22476      return caret;
22477    };
22478    const moveNextWord = curry(moveWord, true);
22479    const movePrevWord = curry(moveWord, false);
22480    const moveToLineEndPoint$2 = (editor, forward, caret) => {
22481      if (isInlineBoundariesEnabled(editor)) {
22482        const linePoint = getLineEndPoint(editor, forward).getOrThunk(() => {
22483          const rng = editor.selection.getRng();
22484          return forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng);
22485        });
22486        return readLocation(curry(isInlineTarget, editor), editor.getBody(), linePoint).exists(loc => {
22487          const outsideLoc = outside(loc);
22488          return renderCaret(caret, outsideLoc).exists(pos => {
22489            setCaretPosition(editor, pos);
22490            return true;
22491          });
22492        });
22493      } else {
22494        return false;
22495      }
22496    };
22497
22498    const rangeFromPositions = (from, to) => {
22499      const range = document.createRange();
22500      range.setStart(from.container(), from.offset());
22501      range.setEnd(to.container(), to.offset());
22502      return range;
22503    };
22504    const hasOnlyTwoOrLessPositionsLeft = elm => lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => {
22505      const normalizedFirstPos = normalizePosition(true, firstPos);
22506      const normalizedLastPos = normalizePosition(false, lastPos);
22507      return nextPosition(elm, normalizedFirstPos).forall(pos => pos.isEqual(normalizedLastPos));
22508    }).getOr(true);
22509    const setCaretLocation = (editor, caret) => location => renderCaret(caret, location).map(pos => () => setCaretPosition(editor, pos));
22510    const deleteFromTo = (editor, caret, from, to) => {
22511      const rootNode = editor.getBody();
22512      const isInlineTarget$1 = curry(isInlineTarget, editor);
22513      editor.undoManager.ignore(() => {
22514        editor.selection.setRng(rangeFromPositions(from, to));
22515        execNativeDeleteCommand(editor);
22516        readLocation(isInlineTarget$1, rootNode, CaretPosition.fromRangeStart(editor.selection.getRng())).map(inside).bind(setCaretLocation(editor, caret)).each(call);
22517      });
22518      editor.nodeChanged();
22519    };
22520    const rescope = (rootNode, node) => {
22521      const parentBlock = getParentBlock$3(node, rootNode);
22522      return parentBlock ? parentBlock : rootNode;
22523    };
22524    const backspaceDeleteCollapsed = (editor, caret, forward, from) => {
22525      const rootNode = rescope(editor.getBody(), from.container());
22526      const isInlineTarget$1 = curry(isInlineTarget, editor);
22527      const fromLocation = readLocation(isInlineTarget$1, rootNode, from);
22528      const location = fromLocation.bind(location => {
22529        if (forward) {
22530          return location.fold(constant(Optional.some(inside(location))), Optional.none, constant(Optional.some(outside(location))), Optional.none);
22531        } else {
22532          return location.fold(Optional.none, constant(Optional.some(outside(location))), Optional.none, constant(Optional.some(inside(location))));
22533        }
22534      });
22535      return location.map(setCaretLocation(editor, caret)).getOrThunk(() => {
22536        const toPosition = navigate(forward, rootNode, from);
22537        const toLocation = toPosition.bind(pos => readLocation(isInlineTarget$1, rootNode, pos));
22538        return lift2(fromLocation, toLocation, () => findRootInline(isInlineTarget$1, rootNode, from).bind(elm => {
22539          if (hasOnlyTwoOrLessPositionsLeft(elm)) {
22540            return Optional.some(() => {
22541              deleteElement$2(editor, forward, SugarElement.fromDom(elm));
22542            });
22543          } else {
22544            return Optional.none();
22545          }
22546        })).getOrThunk(() => toLocation.bind(() => toPosition.map(to => {
22547          return () => {
22548            if (forward) {
22549              deleteFromTo(editor, caret, from, to);
22550            } else {
22551              deleteFromTo(editor, caret, to, from);
22552            }
22553          };
22554        })));
22555      });
22556    };
22557    const backspaceDelete$4 = (editor, caret, forward) => {
22558      if (editor.selection.isCollapsed() && isInlineBoundariesEnabled(editor)) {
22559        const from = CaretPosition.fromRangeStart(editor.selection.getRng());
22560        return backspaceDeleteCollapsed(editor, caret, forward, from);
22561      }
22562      return Optional.none();
22563    };
22564
22565    const hasMultipleChildren = elm => childNodesCount(elm) > 1;
22566    const getParentsUntil = (editor, pred) => {
22567      const rootElm = SugarElement.fromDom(editor.getBody());
22568      const startElm = SugarElement.fromDom(editor.selection.getStart());
22569      const parents = parentsAndSelf(startElm, rootElm);
22570      return findIndex$2(parents, pred).fold(constant(parents), index => parents.slice(0, index));
22571    };
22572    const hasOnlyOneChild = elm => childNodesCount(elm) === 1;
22573    const getParentInlinesUntilMultichildInline = editor => getParentsUntil(editor, elm => editor.schema.isBlock(name(elm)) || hasMultipleChildren(elm));
22574    const getParentInlines = editor => getParentsUntil(editor, el => editor.schema.isBlock(name(el)));
22575    const getFormatNodes = (editor, parentInlines) => {
22576      const isFormatElement$1 = curry(isFormatElement, editor);
22577      return bind$3(parentInlines, elm => isFormatElement$1(elm) ? [elm.dom] : []);
22578    };
22579    const getFormatNodesAtStart = editor => {
22580      const parentInlines = getParentInlines(editor);
22581      return getFormatNodes(editor, parentInlines);
22582    };
22583    const deleteLastPosition = (forward, editor, target, parentInlines) => {
22584      const formatNodes = getFormatNodes(editor, parentInlines);
22585      if (formatNodes.length === 0) {
22586        deleteElement$2(editor, forward, target);
22587      } else {
22588        const pos = replaceWithCaretFormat(target.dom, formatNodes);
22589        editor.selection.setRng(pos.toRange());
22590      }
22591    };
22592    const deleteCaret$1 = (editor, forward) => {
22593      const parentInlines = filter$5(getParentInlinesUntilMultichildInline(editor), hasOnlyOneChild);
22594      return last$2(parentInlines).bind(target => {
22595        const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
22596        if (willDeleteLastPositionInElement(forward, fromPos, target.dom) && !isEmptyCaretFormatElement(target)) {
22597          return Optional.some(() => deleteLastPosition(forward, editor, target, parentInlines));
22598        } else {
22599          return Optional.none();
22600        }
22601      });
22602    };
22603    const isBrInEmptyElement = (editor, elm) => {
22604      const parentElm = elm.parentElement;
22605      return isBr$6(elm) && !isNull(parentElm) && editor.dom.isEmpty(parentElm);
22606    };
22607    const isEmptyCaret = elm => isEmptyCaretFormatElement(SugarElement.fromDom(elm));
22608    const createCaretFormatAtStart = (editor, formatNodes) => {
22609      const startElm = editor.selection.getStart();
22610      const pos = isBrInEmptyElement(editor, startElm) || isEmptyCaret(startElm) ? replaceWithCaretFormat(startElm, formatNodes) : createCaretFormatAtStart$1(editor.selection.getRng(), formatNodes);
22611      editor.selection.setRng(pos.toRange());
22612    };
22613    const updateCaretFormat = (editor, updateFormats) => {
22614      const missingFormats = difference(updateFormats, getFormatNodesAtStart(editor));
22615      if (missingFormats.length > 0) {
22616        createCaretFormatAtStart(editor, missingFormats);
22617      }
22618    };
22619    const rangeStartsAtTextContainer = rng => isText$b(rng.startContainer);
22620    const rangeStartsAtStartOfTextContainer = rng => rng.startOffset === 0 && rangeStartsAtTextContainer(rng);
22621    const rangeStartParentIsFormatElement = (editor, rng) => {
22622      const startParent = rng.startContainer.parentElement;
22623      return !isNull(startParent) && isFormatElement(editor, SugarElement.fromDom(startParent));
22624    };
22625    const rangeStartAndEndHaveSameParent = rng => {
22626      const startParent = rng.startContainer.parentNode;
22627      const endParent = rng.endContainer.parentNode;
22628      return !isNull(startParent) && !isNull(endParent) && startParent.isEqualNode(endParent);
22629    };
22630    const rangeEndsAtEndOfEndContainer = rng => {
22631      const endContainer = rng.endContainer;
22632      return rng.endOffset === (isText$b(endContainer) ? endContainer.length : endContainer.childNodes.length);
22633    };
22634    const rangeEndsAtEndOfStartContainer = rng => rangeStartAndEndHaveSameParent(rng) && rangeEndsAtEndOfEndContainer(rng);
22635    const rangeEndsAfterEndOfStartContainer = rng => !rng.endContainer.isEqualNode(rng.commonAncestorContainer);
22636    const rangeEndsAtOrAfterEndOfStartContainer = rng => rangeEndsAtEndOfStartContainer(rng) || rangeEndsAfterEndOfStartContainer(rng);
22637    const requiresDeleteRangeOverride = editor => {
22638      const rng = editor.selection.getRng();
22639      return rangeStartsAtStartOfTextContainer(rng) && rangeStartParentIsFormatElement(editor, rng) && rangeEndsAtOrAfterEndOfStartContainer(rng);
22640    };
22641    const deleteRange$1 = editor => {
22642      if (requiresDeleteRangeOverride(editor)) {
22643        const formatNodes = getFormatNodesAtStart(editor);
22644        return Optional.some(() => {
22645          execNativeDeleteCommand(editor);
22646          updateCaretFormat(editor, formatNodes);
22647        });
22648      } else {
22649        return Optional.none();
22650      }
22651    };
22652    const backspaceDelete$3 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret$1(editor, forward) : deleteRange$1(editor);
22653    const hasAncestorInlineCaret = (elm, schema) => ancestor$2(elm, node => isCaretNode(node.dom), el => schema.isBlock(name(el)));
22654    const hasAncestorInlineCaretAtStart = editor => hasAncestorInlineCaret(SugarElement.fromDom(editor.selection.getStart()), editor.schema);
22655    const requiresRefreshCaretOverride = editor => {
22656      const rng = editor.selection.getRng();
22657      return rng.collapsed && (rangeStartsAtTextContainer(rng) || editor.dom.isEmpty(rng.startContainer)) && !hasAncestorInlineCaretAtStart(editor);
22658    };
22659    const refreshCaret = editor => {
22660      if (requiresRefreshCaretOverride(editor)) {
22661        createCaretFormatAtStart(editor, []);
22662      }
22663      return true;
22664    };
22665
22666    const deleteElement = (editor, forward, element) => {
22667      if (isNonNullable(element)) {
22668        return Optional.some(() => {
22669          editor._selectionOverrides.hideFakeCaret();
22670          deleteElement$2(editor, forward, SugarElement.fromDom(element));
22671        });
22672      } else {
22673        return Optional.none();
22674      }
22675    };
22676    const deleteCaret = (editor, forward) => {
22677      const isNearMedia = forward ? isBeforeMedia : isAfterMedia;
22678      const direction = forward ? 
vendor: 7,769 bytes, lines 22678-22865
226781 : -1;
22679      const fromPos = getNormalizedRangeEndPoint(direction, editor.getBody(), editor.selection.getRng());
22680      if (isNearMedia(fromPos)) {
22681        return deleteElement(editor, forward, fromPos.getNode(!forward));
22682      } else {
22683        return Optional.from(normalizePosition(forward, fromPos)).filter(pos => isNearMedia(pos) && isMoveInsideSameBlock(fromPos, pos)).bind(pos => deleteElement(editor, forward, pos.getNode(!forward)));
22684      }
22685    };
22686    const deleteRange = (editor, forward) => {
22687      const selectedNode = editor.selection.getNode();
22688      return isMedia$2(selectedNode) ? deleteElement(editor, forward, selectedNode) : Optional.none();
22689    };
22690    const backspaceDelete$2 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret(editor, forward) : deleteRange(editor, forward);
22691
22692    const isEditable = target => closest$4(target, elm => isContentEditableTrue$3(elm.dom) || isContentEditableFalse$b(elm.dom)).exists(elm => isContentEditableTrue$3(elm.dom));
22693    const parseIndentValue = value => toInt(value !== null && value !== void 0 ? value : '').getOr(0);
22694    const getIndentStyleName = (useMargin, element) => {
22695      const indentStyleName = useMargin || isTable$1(element) ? 'margin' : 'padding';
22696      const suffix = get$7(element, 'direction') === 'rtl' ? '-right' : '-left';
22697      return indentStyleName + suffix;
22698    };
22699    const indentElement = (dom, command, useMargin, value, unit, element) => {
22700      const indentStyleName = getIndentStyleName(useMargin, SugarElement.fromDom(element));
22701      const parsedValue = parseIndentValue(dom.getStyle(element, indentStyleName));
22702      if (command === 'outdent') {
22703        const styleValue = Math.max(0, parsedValue - value);
22704        dom.setStyle(element, indentStyleName, styleValue ? styleValue + unit : '');
22705      } else {
22706        const styleValue = parsedValue + value + unit;
22707        dom.setStyle(element, indentStyleName, styleValue);
22708      }
22709    };
22710    const validateBlocks = (editor, blocks) => forall(blocks, block => {
22711      const indentStyleName = getIndentStyleName(shouldIndentUseMargin(editor), block);
22712      const intentValue = getRaw(block, indentStyleName).map(parseIndentValue).getOr(0);
22713      const contentEditable = editor.dom.getContentEditable(block.dom);
22714      return contentEditable !== 'false' && intentValue > 0;
22715    });
22716    const canOutdent = editor => {
22717      const blocks = getBlocksToIndent(editor);
22718      return !editor.mode.isReadOnly() && (blocks.length > 1 || validateBlocks(editor, blocks));
22719    };
22720    const isListComponent = el => isList(el) || isListItem$1(el);
22721    const parentIsListComponent = el => parent(el).exists(isListComponent);
22722    const getBlocksToIndent = editor => filter$5(fromDom$1(editor.selection.getSelectedBlocks()), el => !isListComponent(el) && !parentIsListComponent(el) && isEditable(el));
22723    const handle = (editor, command) => {
22724      var _a, _b;
22725      if (editor.mode.isReadOnly()) {
22726        return;
22727      }
22728      const {dom} = editor;
22729      const indentation = getIndentation(editor);
22730      const indentUnit = (_b = (_a = /[a-z%]+$/i.exec(indentation)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 'px';
22731      const indentValue = parseIndentValue(indentation);
22732      const useMargin = shouldIndentUseMargin(editor);
22733      each$e(getBlocksToIndent(editor), block => {
22734        indentElement(dom, command, useMargin, indentValue, indentUnit, block.dom);
22735      });
22736    };
22737    const indent = editor => handle(editor, 'indent');
22738    const outdent = editor => handle(editor, 'outdent');
22739
22740    const backspaceDelete$1 = editor => {
22741      if (editor.selection.isCollapsed() && canOutdent(editor)) {
22742        const dom = editor.dom;
22743        const rng = editor.selection.getRng();
22744        const pos = CaretPosition.fromRangeStart(rng);
22745        const block = dom.getParent(rng.startContainer, dom.isBlock);
22746        if (block !== null && isAtStartOfBlock(SugarElement.fromDom(block), pos, editor.schema)) {
22747          return Optional.some(() => outdent(editor));
22748        }
22749      }
22750      return Optional.none();
22751    };
22752
22753    const findAction = (editor, caret, forward) => findMap([
22754      backspaceDelete$1,
22755      backspaceDelete$7,
22756      backspaceDelete$8,
22757      (editor, forward) => backspaceDelete$4(editor, caret, forward),
22758      backspaceDelete$a,
22759      backspaceDelete$b,
22760      backspaceDelete$5,
22761      backspaceDelete$2,
22762      backspaceDelete$9,
22763      backspaceDelete$3,
22764      backspaceDelete$6
22765    ], item => item(editor, forward)).filter(_ => editor.selection.isEditable());
22766    const deleteCommand = (editor, caret) => {
22767      const result = findAction(editor, caret, false);
22768      result.fold(() => {
22769        if (editor.selection.isEditable()) {
22770          execNativeDeleteCommand(editor);
22771          paddEmptyBody(editor);
22772        }
22773      }, call);
22774    };
22775    const forwardDeleteCommand = (editor, caret) => {
22776      const result = findAction(editor, caret, true);
22777      result.fold(() => {
22778        if (editor.selection.isEditable()) {
22779          execNativeForwardDeleteCommand(editor);
22780        }
22781      }, call);
22782    };
22783    const setup$q = (editor, caret) => {
22784      editor.addCommand('delete', () => {
22785        deleteCommand(editor, caret);
22786      });
22787      editor.addCommand('forwardDelete', () => {
22788        forwardDeleteCommand(editor, caret);
22789      });
22790    };
22791
22792    const SIGNIFICANT_MOVE = 5;
22793    const LONGPRESS_DELAY = 400;
22794    const getTouch = event => {
22795      if (event.touches === undefined || event.touches.length !== 1) {
22796        return Optional.none();
22797      }
22798      return Optional.some(event.touches[0]);
22799    };
22800    const isFarEnough = (touch, data) => {
22801      const distX = Math.abs(touch.clientX - data.x);
22802      const distY = Math.abs(touch.clientY - data.y);
22803      return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
22804    };
22805    const setup$p = editor => {
22806      const startData = value$2();
22807      const longpressFired = Cell(false);
22808      const debounceLongpress = last(e => {
22809        editor.dispatch('longpress', {
22810          ...e,
22811          type: 'longpress'
22812        });
22813        longpressFired.set(true);
22814      }, LONGPRESS_DELAY);
22815      editor.on('touchstart', e => {
22816        getTouch(e).each(touch => {
22817          debounceLongpress.cancel();
22818          const data = {
22819            x: touch.clientX,
22820            y: touch.clientY,
22821            target: e.target
22822          };
22823          debounceLongpress.throttle(e);
22824          longpressFired.set(false);
22825          startData.set(data);
22826        });
22827      }, true);
22828      editor.on('touchmove', e => {
22829        debounceLongpress.cancel();
22830        getTouch(e).each(touch => {
22831          startData.on(data => {
22832            if (isFarEnough(touch, data)) {
22833              startData.clear();
22834              longpressFired.set(false);
22835              editor.dispatch('longpresscancel');
22836            }
22837          });
22838        });
22839      }, true);
22840      editor.on('touchend touchcancel', e => {
22841        debounceLongpress.cancel();
22842        if (e.type === 'touchcancel') {
22843          return;
22844        }
22845        startData.get().filter(data => data.target.isEqualNode(e.target)).each(() => {
22846          if (longpressFired.get()) {
22847            e.preventDefault();
22848          } else {
22849            editor.dispatch('tap', {
22850              ...e,
22851              type: 'tap'
22852            });
22853          }
22854        });
22855      }, true);
22856    };
22857
22858    const isBlockElement = (blockElements, node) => has$2(blockElements, node.nodeName);
22859    const isValidTarget = (schema, node) => {
22860      if (isText$b(node)) {
22861        return true;
22862      } else if (isElement$6(node)) {
22863        return !isBlockElement(schema.getBlockElements(), node) && !isBookmarkNode$1(node) && !isTransparentBlock(schema, node) && !isNonHtmlElementRoot(node);
22864      } else {
22865        return false;
vendor: 4,968 bytes, lines 22866-22995
22866      }
22867    };
22868    const hasBlockParent = (blockElements, root, node) => {
22869      return exists(parents(SugarElement.fromDom(node), SugarElement.fromDom(root)), elm => {
22870        return isBlockElement(blockElements, elm.dom);
22871      });
22872    };
22873    const shouldRemoveTextNode = (blockElements, node) => {
22874      if (isText$b(node)) {
22875        if (node.data.length === 0) {
22876          return true;
22877        } else if (/^\s+$/.test(node.data)) {
22878          return !node.nextSibling || isBlockElement(blockElements, node.nextSibling) || isNonHtmlElementRoot(node.nextSibling);
22879        }
22880      }
22881      return false;
22882    };
22883    const createRootBlock = editor => editor.dom.create(getForcedRootBlock(editor), getForcedRootBlockAttrs(editor));
22884    const addRootBlocks = editor => {
22885      const dom = editor.dom, selection = editor.selection;
22886      const schema = editor.schema;
22887      const blockElements = schema.getBlockElements();
22888      const startNode = selection.getStart();
22889      const rootNode = editor.getBody();
22890      let rootBlockNode;
22891      let tempNode;
22892      let bm = null;
22893      const forcedRootBlock = getForcedRootBlock(editor);
22894      if (!startNode || !isElement$6(startNode)) {
22895        return;
22896      }
22897      const rootNodeName = rootNode.nodeName.toLowerCase();
22898      if (!schema.isValidChild(rootNodeName, forcedRootBlock.toLowerCase()) || hasBlockParent(blockElements, rootNode, startNode)) {
22899        return;
22900      }
22901      if (rootNode.firstChild === rootNode.lastChild && isBr$6(rootNode.firstChild)) {
22902        rootBlockNode = createRootBlock(editor);
22903        rootBlockNode.appendChild(createPaddingBr().dom);
22904        rootNode.replaceChild(rootBlockNode, rootNode.firstChild);
22905        editor.selection.setCursorLocation(rootBlockNode, 0);
22906        editor.nodeChanged();
22907        return;
22908      }
22909      let node = rootNode.firstChild;
22910      while (node) {
22911        if (isElement$6(node)) {
22912          updateElement(schema, node);
22913        }
22914        if (isValidTarget(schema, node)) {
22915          if (shouldRemoveTextNode(blockElements, node)) {
22916            tempNode = node;
22917            node = node.nextSibling;
22918            dom.remove(tempNode);
22919            continue;
22920          }
22921          if (!rootBlockNode) {
22922            if (!bm && editor.hasFocus()) {
22923              bm = getBookmark(editor.selection.getRng(), () => document.createElement('span'));
22924            }
22925            if (!node.parentNode) {
22926              node = null;
22927              break;
22928            }
22929            rootBlockNode = createRootBlock(editor);
22930            rootNode.insertBefore(rootBlockNode, node);
22931          }
22932          tempNode = node;
22933          node = node.nextSibling;
22934          rootBlockNode.appendChild(tempNode);
22935        } else {
22936          rootBlockNode = null;
22937          node = node.nextSibling;
22938        }
22939      }
22940      if (bm) {
22941        editor.selection.setRng(resolveBookmark(bm));
22942        editor.nodeChanged();
22943      }
22944    };
22945    const insertEmptyLine = (editor, root, insertBlock) => {
22946      const block = SugarElement.fromDom(createRootBlock(editor));
22947      const br = createPaddingBr();
22948      append$1(block, br);
22949      insertBlock(root, block);
22950      const rng = document.createRange();
22951      rng.setStartBefore(br.dom);
22952      rng.setEndBefore(br.dom);
22953      return rng;
22954    };
22955    const setup$o = editor => {
22956      editor.on('NodeChange', () => addRootBlocks(editor));
22957    };
22958
22959    const hasClass = checkClassName => node => (' ' + node.attr('class') + ' ').indexOf(checkClassName) !== -1;
22960    const replaceMatchWithSpan = (editor, content, cls) => {
22961      return function (match) {
22962        const args = arguments, index = args[args.length - 2];
22963        const prevChar = index > 0 ? content.charAt(index - 1) : '';
22964        if (prevChar === '"') {
22965          return match;
22966        }
22967        if (prevChar === '>') {
22968          const findStartTagIndex = content.lastIndexOf('<', index);
22969          if (findStartTagIndex !== -1) {
22970            const tagHtml = content.substring(findStartTagIndex, index);
22971            if (tagHtml.indexOf('contenteditable="false"') !== -1) {
22972              return match;
22973            }
22974          }
22975        }
22976        return '<span class="' + cls + '" data-mce-content="' + editor.dom.encode(args[0]) + '">' + editor.dom.encode(typeof args[1] === 'string' ? args[1] : args[0]) + '</span>';
22977      };
22978    };
22979    const convertRegExpsToNonEditable = (editor, nonEditableRegExps, e) => {
22980      let i = nonEditableRegExps.length, content = e.content;
22981      if (e.format === 'raw') {
22982        return;
22983      }
22984      while (i--) {
22985        content = content.replace(nonEditableRegExps[i], replaceMatchWithSpan(editor, content, getNonEditableClass(editor)));
22986      }
22987      e.content = content;
22988    };
22989    const isValidContent = (nonEditableRegExps, content) => {
22990      return forall(nonEditableRegExps, re => {
22991        const matches = content.match(re);
22992        return matches !== null && matches[0].length === content.length;
22993      });
22994    };
22995    const setup$n = editor => {
vendor: 10,089 bytes, lines 22996-23231
22996      const contentEditableAttrName = 'contenteditable';
22997      const editClass = ' ' + Tools.trim(getEditableClass(editor)) + ' ';
22998      const nonEditClass = ' ' + Tools.trim(getNonEditableClass(editor)) + ' ';
22999      const hasEditClass = hasClass(editClass);
23000      const hasNonEditClass = hasClass(nonEditClass);
23001      const nonEditableRegExps = getNonEditableRegExps(editor);
23002      if (nonEditableRegExps.length > 0) {
23003        editor.on('BeforeSetContent', e => {
23004          convertRegExpsToNonEditable(editor, nonEditableRegExps, e);
23005        });
23006      }
23007      editor.parser.addAttributeFilter('class', nodes => {
23008        let i = nodes.length;
23009        while (i--) {
23010          const node = nodes[i];
23011          if (hasEditClass(node)) {
23012            node.attr(contentEditableAttrName, 'true');
23013          } else if (hasNonEditClass(node)) {
23014            node.attr(contentEditableAttrName, 'false');
23015          }
23016        }
23017      });
23018      editor.serializer.addAttributeFilter(contentEditableAttrName, nodes => {
23019        let i = nodes.length;
23020        while (i--) {
23021          const node = nodes[i];
23022          if (!hasEditClass(node) && !hasNonEditClass(node)) {
23023            continue;
23024          }
23025          const content = node.attr('data-mce-content');
23026          if (nonEditableRegExps.length > 0 && content) {
23027            if (isValidContent(nonEditableRegExps, content)) {
23028              node.name = '#text';
23029              node.type = 3;
23030              node.raw = true;
23031              node.value = content;
23032            } else {
23033              node.remove();
23034            }
23035          } else {
23036            node.attr(contentEditableAttrName, null);
23037          }
23038        }
23039      });
23040    };
23041
23042    const findBlockCaretContainer = editor => descendant$1(SugarElement.fromDom(editor.getBody()), '*[data-mce-caret]').map(elm => elm.dom).getOrNull();
23043    const showBlockCaretContainer = (editor, blockCaretContainer) => {
23044      if (blockCaretContainer.hasAttribute('data-mce-caret')) {
23045        showCaretContainerBlock(blockCaretContainer);
23046        editor.selection.setRng(editor.selection.getRng());
23047        editor.selection.scrollIntoView(blockCaretContainer);
23048      }
23049    };
23050    const handleBlockContainer = (editor, e) => {
23051      const blockCaretContainer = findBlockCaretContainer(editor);
23052      if (!blockCaretContainer) {
23053        return;
23054      }
23055      if (e.type === 'compositionstart') {
23056        e.preventDefault();
23057        e.stopPropagation();
23058        showBlockCaretContainer(editor, blockCaretContainer);
23059        return;
23060      }
23061      if (hasContent(blockCaretContainer)) {
23062        showBlockCaretContainer(editor, blockCaretContainer);
23063        editor.undoManager.add();
23064      }
23065    };
23066    const setup$m = editor => {
23067      editor.on('keyup compositionstart', curry(handleBlockContainer, editor));
23068    };
23069
23070    const isContentEditableFalse$4 = isContentEditableFalse$b;
23071    const moveToCeFalseHorizontally = (direction, editor, range) => moveHorizontally(editor, direction, range, isBeforeContentEditableFalse, isAfterContentEditableFalse, isContentEditableFalse$4);
23072    const moveToCeFalseVertically = (direction, editor, range) => {
23073      const isBefore = caretPosition => isBeforeContentEditableFalse(caretPosition) || isBeforeTable(caretPosition);
23074      const isAfter = caretPosition => isAfterContentEditableFalse(caretPosition) || isAfterTable(caretPosition);
23075      return moveVertically(editor, direction, range, isBefore, isAfter, isContentEditableFalse$4);
23076    };
23077    const createTextBlock = editor => {
23078      const textBlock = editor.dom.create(getForcedRootBlock(editor));
23079      textBlock.innerHTML = '<br data-mce-bogus="1">';
23080      return textBlock;
23081    };
23082    const exitPreBlock = (editor, direction, range) => {
23083      const caretWalker = CaretWalker(editor.getBody());
23084      const getVisualCaretPosition$1 = curry(getVisualCaretPosition, direction === 1 ? caretWalker.next : caretWalker.prev);
23085      if (range.collapsed) {
23086        const pre = editor.dom.getParent(range.startContainer, 'PRE');
23087        if (!pre) {
23088          return;
23089        }
23090        const caretPos = getVisualCaretPosition$1(CaretPosition.fromRangeStart(range));
23091        if (!caretPos) {
23092          const newBlock = SugarElement.fromDom(createTextBlock(editor));
23093          if (direction === 1) {
23094            after$4(SugarElement.fromDom(pre), newBlock);
23095          } else {
23096            before$3(SugarElement.fromDom(pre), newBlock);
23097          }
23098          editor.selection.select(newBlock.dom, true);
23099          editor.selection.collapse();
23100        }
23101      }
23102    };
23103    const getHorizontalRange = (editor, forward) => {
23104      const direction = forward ? 1 : -1;
23105      const range = editor.selection.getRng();
23106      return moveToCeFalseHorizontally(direction, editor, range).orThunk(() => {
23107        exitPreBlock(editor, direction, range);
23108        return Optional.none();
23109      });
23110    };
23111    const getVerticalRange = (editor, down) => {
23112      const direction = down ? 1 : -1;
23113      const range = editor.selection.getRng();
23114      return moveToCeFalseVertically(direction, editor, range).orThunk(() => {
23115        exitPreBlock(editor, direction, range);
23116        return Optional.none();
23117      });
23118    };
23119    const flipDirection = (selection, forward) => {
23120      const elm = forward ? selection.getEnd(true) : selection.getStart(true);
23121      return isRtl(elm) ? !forward : forward;
23122    };
23123    const moveH$2 = (editor, forward) => getHorizontalRange(editor, flipDirection(editor.selection, forward)).exists(newRange => {
23124      moveToRange(editor, newRange);
23125      return true;
23126    });
23127    const moveV$4 = (editor, down) => getVerticalRange(editor, down).exists(newRange => {
23128      moveToRange(editor, newRange);
23129      return true;
23130    });
23131    const moveToLineEndPoint$1 = (editor, forward) => {
23132      const isCefPosition = forward ? isAfterContentEditableFalse : isBeforeContentEditableFalse;
23133      return moveToLineEndPoint$3(editor, forward, isCefPosition);
23134    };
23135    const selectToEndPoint = (editor, forward) => getEdgeCefPosition(editor, !forward).map(pos => {
23136      const rng = pos.toRange();
23137      const curRng = editor.selection.getRng();
23138      if (forward) {
23139        rng.setStart(curRng.startContainer, curRng.startOffset);
23140      } else {
23141        rng.setEnd(curRng.endContainer, curRng.endOffset);
23142      }
23143      return rng;
23144    }).exists(rng => {
23145      moveToRange(editor, rng);
23146      return true;
23147    });
23148
23149    const isTarget = node => contains$2(['figcaption'], name(node));
23150    const getClosestTargetBlock = (pos, root, schema) => {
23151      const isRoot = curry(eq, root);
23152      return closest$4(SugarElement.fromDom(pos.container()), el => schema.isBlock(name(el)), isRoot).filter(isTarget);
23153    };
23154    const isAtFirstOrLastLine = (root, forward, pos) => forward ? isAtLastLine(root.dom, pos) : isAtFirstLine(root.dom, pos);
23155    const moveCaretToNewEmptyLine = (editor, forward) => {
23156      const root = SugarElement.fromDom(editor.getBody());
23157      const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
23158      return getClosestTargetBlock(pos, root, editor.schema).exists(() => {
23159        if (isAtFirstOrLastLine(root, forward, pos)) {
23160          const insertFn = forward ? append$1 : prepend;
23161          const rng = insertEmptyLine(editor, root, insertFn);
23162          editor.selection.setRng(rng);
23163          return true;
23164        } else {
23165          return false;
23166        }
23167      });
23168    };
23169    const moveV$3 = (editor, forward) => {
23170      if (editor.selection.isCollapsed()) {
23171        return moveCaretToNewEmptyLine(editor, forward);
23172      } else {
23173        return false;
23174      }
23175    };
23176
23177    const moveUp = (editor, details, summary) => {
23178      const rng = editor.selection.getRng();
23179      const pos = CaretPosition.fromRangeStart(rng);
23180      const root = editor.getBody();
23181      if (root.firstChild === details && isAtFirstLine(summary, pos)) {
23182        editor.execCommand('InsertNewBlockBefore');
23183        return true;
23184      } else {
23185        return false;
23186      }
23187    };
23188    const moveDown = (editor, details) => {
23189      const rng = editor.selection.getRng();
23190      const pos = CaretPosition.fromRangeStart(rng);
23191      const root = editor.getBody();
23192      if (root.lastChild === details && isAtLastLine(details, pos)) {
23193        editor.execCommand('InsertNewBlockAfter');
23194        return true;
23195      } else {
23196        return false;
23197      }
23198    };
23199    const move$2 = (editor, forward) => {
23200      if (forward) {
23201        return Optional.from(editor.dom.getParent(editor.selection.getNode(), 'details')).map(details => moveDown(editor, details)).getOr(false);
23202      } else {
23203        return Optional.from(editor.dom.getParent(editor.selection.getNode(), 'summary')).bind(summary => Optional.from(editor.dom.getParent(summary, 'details')).map(details => moveUp(editor, details, summary))).getOr(false);
23204      }
23205    };
23206    const moveV$2 = (editor, forward) => move$2(editor, forward);
23207
23208    const baseKeyPattern = {
23209      shiftKey: false,
23210      altKey: false,
23211      ctrlKey: false,
23212      metaKey: false,
23213      keyCode: 0
23214    };
23215    const defaultPatterns = patterns => map$3(patterns, pattern => ({
23216      ...baseKeyPattern,
23217      ...pattern
23218    }));
23219    const defaultDelayedPatterns = patterns => map$3(patterns, pattern => ({
23220      ...baseKeyPattern,
23221      ...pattern
23222    }));
23223    const matchesEvent = (pattern, evt) => evt.keyCode === pattern.keyCode && evt.shiftKey === pattern.shiftKey && evt.altKey === pattern.altKey && evt.ctrlKey === pattern.ctrlKey && evt.metaKey === pattern.metaKey;
23224    const match$1 = (patterns, evt) => bind$3(defaultPatterns(patterns), pattern => matchesEvent(pattern, evt) ? [pattern] : []);
23225    const matchDelayed = (patterns, evt) => bind$3(defaultDelayedPatterns(patterns), pattern => matchesEvent(pattern, evt) ? [pattern] : []);
23226    const action = (f, ...x) => () => f.apply(null, x);
23227    const execute = (patterns, evt) => find$2(match$1(patterns, evt), pattern => pattern.action());
23228    const executeWithDelayedAction = (patterns, evt) => findMap(matchDelayed(patterns, evt), pattern => pattern.action());
23229
23230    const moveH$1 = (editor, forward) => {
23231      const direction = forward ? 1 : -1
vendor: 10,719 bytes, lines 23231-23467
23231;
23232      const range = editor.selection.getRng();
23233      return moveHorizontally(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists(newRange => {
23234        moveToRange(editor, newRange);
23235        return true;
23236      });
23237    };
23238    const moveV$1 = (editor, down) => {
23239      const direction = down ? 1 : -1;
23240      const range = editor.selection.getRng();
23241      return moveVertically(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists(newRange => {
23242        moveToRange(editor, newRange);
23243        return true;
23244      });
23245    };
23246    const moveToLineEndPoint = (editor, forward) => {
23247      const isNearMedia = forward ? isAfterMedia : isBeforeMedia;
23248      return moveToLineEndPoint$3(editor, forward, isNearMedia);
23249    };
23250
23251    const adt = Adt.generate([
23252      { none: ['current'] },
23253      { first: ['current'] },
23254      {
23255        middle: [
23256          'current',
23257          'target'
23258        ]
23259      },
23260      { last: ['current'] }
23261    ]);
23262    const none = current => adt.none(current);
23263    const CellLocation = {
23264      ...adt,
23265      none
23266    };
23267
23268    const firstLayer = (scope, selector) => {
23269      return filterFirstLayer(scope, selector, always);
23270    };
23271    const filterFirstLayer = (scope, selector, predicate) => {
23272      return bind$3(children$1(scope), x => {
23273        if (is$1(x, selector)) {
23274          return predicate(x) ? [x] : [];
23275        } else {
23276          return filterFirstLayer(x, selector, predicate);
23277        }
23278      });
23279    };
23280
23281    const lookup$1 = (tags, element, isRoot = never) => {
23282      if (isRoot(element)) {
23283        return Optional.none();
23284      }
23285      if (contains$2(tags, name(element))) {
23286        return Optional.some(element);
23287      }
23288      const isRootOrUpperTable = elm => is$1(elm, 'table') || isRoot(elm);
23289      return ancestor$3(element, tags.join(','), isRootOrUpperTable);
23290    };
23291    const cell = (element, isRoot) => lookup$1([
23292      'td',
23293      'th'
23294    ], element, isRoot);
23295    const cells = ancestor => firstLayer(ancestor, 'th,td');
23296    const table = (element, isRoot) => closest$3(element, 'table', isRoot);
23297
23298    const walk = (all, current, index, direction, isEligible = always) => {
23299      const forwards = direction === 1;
23300      if (!forwards && index <= 0) {
23301        return CellLocation.first(all[0]);
23302      } else if (forwards && index >= all.length - 1) {
23303        return CellLocation.last(all[all.length - 1]);
23304      } else {
23305        const newIndex = index + direction;
23306        const elem = all[newIndex];
23307        return isEligible(elem) ? CellLocation.middle(current, elem) : walk(all, current, newIndex, direction, isEligible);
23308      }
23309    };
23310    const detect = (current, isRoot) => {
23311      return table(current, isRoot).bind(table => {
23312        const all = cells(table);
23313        const index = findIndex$2(all, x => eq(current, x));
23314        return index.map(index => ({
23315          index,
23316          all
23317        }));
23318      });
23319    };
23320    const next = (current, isEligible, isRoot) => {
23321      const detection = detect(current, isRoot);
23322      return detection.fold(() => {
23323        return CellLocation.none(current);
23324      }, info => {
23325        return walk(info.all, current, info.index, 1, isEligible);
23326      });
23327    };
23328    const prev = (current, isEligible, isRoot) => {
23329      const detection = detect(current, isRoot);
23330      return detection.fold(() => {
23331        return CellLocation.none();
23332      }, info => {
23333        return walk(info.all, current, info.index, -1, isEligible);
23334      });
23335    };
23336
23337    const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome();
23338    const isContentEditableFalse$3 = elem => isHTMLElement$1(elem) && get$9(elem, 'contenteditable') === 'false';
23339    const elementsWithCursorPosition = [
23340      'img',
23341      'br'
23342    ];
23343    const isCursorPosition = elem => {
23344      const hasCursorPosition = isTextNodeWithCursorPosition(elem);
23345      return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse$3(elem);
23346    };
23347
23348    const first = element => descendant$2(element, isCursorPosition);
23349
23350    const deflate = (rect, delta) => ({
23351      left: rect.left - delta,
23352      top: rect.top - delta,
23353      right: rect.right + delta * 2,
23354      bottom: rect.bottom + delta * 2,
23355      width: rect.width + delta,
23356      height: rect.height + delta
23357    });
23358    const getCorners = (getYAxisValue, tds) => bind$3(tds, td => {
23359      const rect = deflate(clone$1(td.getBoundingClientRect()), -1);
23360      return [
23361        {
23362          x: rect.left,
23363          y: getYAxisValue(rect),
23364          cell: td
23365        },
23366        {
23367          x: rect.right,
23368          y: getYAxisValue(rect),
23369          cell: td
23370        }
23371      ];
23372    });
23373    const findClosestCorner = (corners, x, y) => foldl(corners, (acc, newCorner) => acc.fold(() => Optional.some(newCorner), oldCorner => {
23374      const oldDist = Math.sqrt(Math.abs(oldCorner.x - x) + Math.abs(oldCorner.y - y));
23375      const newDist = Math.sqrt(Math.abs(newCorner.x - x) + Math.abs(newCorner.y - y));
23376      return Optional.some(newDist < oldDist ? newCorner : oldCorner);
23377    }), Optional.none());
23378    const getClosestCell = (getYAxisValue, isTargetCorner, table, x, y) => {
23379      const cells = descendants(SugarElement.fromDom(table), 'td,th,caption').map(e => e.dom);
23380      const corners = filter$5(getCorners(getYAxisValue, cells), corner => isTargetCorner(corner, y));
23381      return findClosestCorner(corners, x, y).map(corner => corner.cell);
23382    };
23383    const getBottomValue = rect => rect.bottom;
23384    const getTopValue = rect => rect.top;
23385    const isAbove = (corner, y) => corner.y < y;
23386    const isBelow = (corner, y) => corner.y > y;
23387    const getClosestCellAbove = curry(getClosestCell, getBottomValue, isAbove);
23388    const getClosestCellBelow = curry(getClosestCell, getTopValue, isBelow);
23389    const findClosestPositionInAboveCell = (table, pos) => head(pos.getClientRects()).bind(rect => getClosestCellAbove(table, rect.left, rect.top)).bind(cell => findClosestHorizontalPosition(getLastLinePositions(cell), pos));
23390    const findClosestPositionInBelowCell = (table, pos) => last$2(pos.getClientRects()).bind(rect => getClosestCellBelow(table, rect.left, rect.top)).bind(cell => findClosestHorizontalPosition(getFirstLinePositions(cell), pos));
23391
23392    const hasNextBreak = (getPositionsUntil, scope, lineInfo) => lineInfo.breakAt.exists(breakPos => getPositionsUntil(scope, breakPos).breakAt.isSome());
23393    const startsWithWrapBreak = lineInfo => lineInfo.breakType === BreakType.Wrap && lineInfo.positions.length === 0;
23394    const startsWithBrBreak = lineInfo => lineInfo.breakType === BreakType.Br && lineInfo.positions.length === 1;
23395    const isAtTableCellLine = (getPositionsUntil, scope, pos) => {
23396      const lineInfo = getPositionsUntil(scope, pos);
23397      if (startsWithWrapBreak(lineInfo) || !isBr$6(pos.getNode()) && startsWithBrBreak(lineInfo)) {
23398        return !hasNextBreak(getPositionsUntil, scope, lineInfo);
23399      } else {
23400        return lineInfo.breakAt.isNone();
23401      }
23402    };
23403    const isAtFirstTableCellLine = curry(isAtTableCellLine, getPositionsUntilPreviousLine);
23404    const isAtLastTableCellLine = curry(isAtTableCellLine, getPositionsUntilNextLine);
23405    const isCaretAtStartOrEndOfTable = (forward, rng, table) => {
23406      const caretPos = CaretPosition.fromRangeStart(rng);
23407      return positionIn(!forward, table).exists(pos => pos.isEqual(caretPos));
23408    };
23409    const navigateHorizontally = (editor, forward, table, _td) => {
23410      const rng = editor.selection.getRng();
23411      const direction = forward ? 1 : -1;
23412      if (isFakeCaretTableBrowser() && isCaretAtStartOrEndOfTable(forward, rng, table)) {
23413        showCaret(direction, editor, table, !forward, false).each(newRng => {
23414          moveToRange(editor, newRng);
23415        });
23416        return true;
23417      }
23418      return false;
23419    };
23420    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));
23421    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));
23422    const getTable = (previous, pos) => {
23423      const node = pos.getNode(previous);
23424      return isTable$2(node) ? Optional.some(node) : Optional.none();
23425    };
23426    const renderBlock = (down, editor, table) => {
23427      editor.undoManager.transact(() => {
23428        const insertFn = down ? after$4 : before$3;
23429        const rng = insertEmptyLine(editor, SugarElement.fromDom(table), insertFn);
23430        moveToRange(editor, rng);
23431      });
23432    };
23433    const moveCaret = (editor, down, pos) => {
23434      const table = down ? getTable(true, pos) : getTable(false, pos);
23435      const last = down === false;
23436      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)));
23437    };
23438    const navigateVertically = (editor, down, table, td) => {
23439      const rng = editor.selection.getRng();
23440      const pos = CaretPosition.fromRangeStart(rng);
23441      const root = editor.getBody();
23442      if (!down && isAtFirstTableCellLine(td, pos)) {
23443        const newPos = getClosestAbovePosition(root, table, pos);
23444        moveCaret(editor, down, newPos);
23445        return true;
23446      } else if (down && isAtLastTableCellLine(td, pos)) {
23447        const newPos = getClosestBelowPosition(root, table, pos);
23448        moveCaret(editor, down, newPos);
23449        return true;
23450      } else {
23451        return false;
23452      }
23453    };
23454    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);
23455    const moveH = (editor, forward) => move$1(editor, forward, navigateHorizontally);
23456    const moveV = (editor, forward) => move$1(editor, forward, navigateVertically);
23457    const getCellFirstCursorPosition = cell => {
23458      const selection = SimSelection.exact(cell, 0, cell, 0);
23459      return toNative(selection);
23460    };
23461    const tabGo = (editor, isRoot, cell) => {
23462      return cell.fold(Optional.none, Optional.none, (_current, next) => {
23463        return first(next).map(cell => {
23464          return getCellFirstCursorPosition(cell);
23465        });
23466      }, current => {
23467        
vendor: 8,704 bytes, lines 23467-23733
23467if (editor.mode.isReadOnly()) {
23468          return Optional.none();
23469        }
23470        editor.execCommand('mceTableInsertRowAfter');
23471        return tabForward(editor, isRoot, current);
23472      });
23473    };
23474    const tabForward = (editor, isRoot, cell) => tabGo(editor, isRoot, next(cell, isEditable$2));
23475    const tabBackward = (editor, isRoot, cell) => tabGo(editor, isRoot, prev(cell, isEditable$2));
23476    const handleTab = (editor, forward) => {
23477      const rootElements = [
23478        'table',
23479        'li',
23480        'dl'
23481      ];
23482      const body = SugarElement.fromDom(editor.getBody());
23483      const isRoot = element => {
23484        const name$1 = name(element);
23485        return eq(element, body) || contains$2(rootElements, name$1);
23486      };
23487      const rng = editor.selection.getRng();
23488      const container = SugarElement.fromDom(!forward ? rng.startContainer : rng.endContainer);
23489      return cell(container, isRoot).map(cell => {
23490        table(cell, isRoot).each(table => {
23491          editor.model.table.clearSelectedCells(table.dom);
23492        });
23493        editor.selection.collapse(!forward);
23494        const navigation = !forward ? tabBackward : tabForward;
23495        const rng = navigation(editor, isRoot, cell);
23496        rng.each(range => {
23497          editor.selection.setRng(range);
23498        });
23499        return true;
23500      }).getOr(false);
23501    };
23502
23503    const executeKeydownOverride$4 = (editor, caret, evt) => {
23504      const isMac = Env.os.isMacOS() || Env.os.isiOS();
23505      execute([
23506        {
23507          keyCode: VK.RIGHT,
23508          action: action(moveH$2, editor, true)
23509        },
23510        {
23511          keyCode: VK.LEFT,
23512          action: action(moveH$2, editor, false)
23513        },
23514        {
23515          keyCode: VK.UP,
23516          action: action(moveV$4, editor, false)
23517        },
23518        {
23519          keyCode: VK.DOWN,
23520          action: action(moveV$4, editor, true)
23521        },
23522        ...isMac ? [
23523          {
23524            keyCode: VK.UP,
23525            action: action(selectToEndPoint, editor, false),
23526            metaKey: true,
23527            shiftKey: true
23528          },
23529          {
23530            keyCode: VK.DOWN,
23531            action: action(selectToEndPoint, editor, true),
23532            metaKey: true,
23533            shiftKey: true
23534          }
23535        ] : [],
23536        {
23537          keyCode: VK.RIGHT,
23538          action: action(moveH, editor, true)
23539        },
23540        {
23541          keyCode: VK.LEFT,
23542          action: action(moveH, editor, false)
23543        },
23544        {
23545          keyCode: VK.UP,
23546          action: action(moveV, editor, false)
23547        },
23548        {
23549          keyCode: VK.DOWN,
23550          action: action(moveV, editor, true)
23551        },
23552        {
23553          keyCode: VK.UP,
23554          action: action(moveV, editor, false)
23555        },
23556        {
23557          keyCode: VK.UP,
23558          action: action(moveV$2, editor, false)
23559        },
23560        {
23561          keyCode: VK.DOWN,
23562          action: action(moveV$2, editor, true)
23563        },
23564        {
23565          keyCode: VK.RIGHT,
23566          action: action(moveH$1, editor, true)
23567        },
23568        {
23569          keyCode: VK.LEFT,
23570          action: action(moveH$1, editor, false)
23571        },
23572        {
23573          keyCode: VK.UP,
23574          action: action(moveV$1, editor, false)
23575        },
23576        {
23577          keyCode: VK.DOWN,
23578          action: action(moveV$1, editor, true)
23579        },
23580        {
23581          keyCode: VK.RIGHT,
23582          action: action(move$3, editor, caret, true)
23583        },
23584        {
23585          keyCode: VK.LEFT,
23586          action: action(move$3, editor, caret, false)
23587        },
23588        {
23589          keyCode: VK.RIGHT,
23590          ctrlKey: !isMac,
23591          altKey: isMac,
23592          action: action(moveNextWord, editor, caret)
23593        },
23594        {
23595          keyCode: VK.LEFT,
23596          ctrlKey: !isMac,
23597          altKey: isMac,
23598          action: action(movePrevWord, editor, caret)
23599        },
23600        {
23601          keyCode: VK.UP,
23602          action: action(moveV$3, editor, false)
23603        },
23604        {
23605          keyCode: VK.DOWN,
23606          action: action(moveV$3, editor, true)
23607        }
23608      ], evt).each(_ => {
23609        evt.preventDefault();
23610      });
23611    };
23612    const setup$l = (editor, caret) => {
23613      editor.on('keydown', evt => {
23614        if (!evt.isDefaultPrevented()) {
23615          executeKeydownOverride$4(editor, caret, evt);
23616        }
23617      });
23618    };
23619
23620    const point = (container, offset) => ({
23621      container,
23622      offset
23623    });
23624
23625    const DOM$7 = DOMUtils.DOM;
23626    const alwaysNext = startNode => node => startNode === node ? -1 : 0;
23627    const isBoundary = dom => node => dom.isBlock(node) || contains$2([
23628      'BR',
23629      'IMG',
23630      'HR',
23631      'INPUT'
23632    ], node.nodeName) || dom.getContentEditable(node) === 'false';
23633    const textBefore = (node, offset, rootNode) => {
23634      if (isText$b(node) && offset >= 0) {
23635        return Optional.some(point(node, offset));
23636      } else {
23637        const textSeeker = TextSeeker(DOM$7);
23638        return Optional.from(textSeeker.backwards(node, offset, alwaysNext(node), rootNode)).map(prev => point(prev.container, prev.container.data.length));
23639      }
23640    };
23641    const textAfter = (node, offset, rootNode) => {
23642      if (isText$b(node) && offset >= node.length) {
23643        return Optional.some(point(node, offset));
23644      } else {
23645        const textSeeker = TextSeeker(DOM$7);
23646        return Optional.from(textSeeker.forwards(node, offset, alwaysNext(node), rootNode)).map(prev => point(prev.container, 0));
23647      }
23648    };
23649    const scanLeft = (node, offset, rootNode) => {
23650      if (!isText$b(node)) {
23651        return Optional.none();
23652      }
23653      const text = node.data;
23654      if (offset >= 0 && offset <= text.length) {
23655        return Optional.some(point(node, offset));
23656      } else {
23657        const textSeeker = TextSeeker(DOM$7);
23658        return Optional.from(textSeeker.backwards(node, offset, alwaysNext(node), rootNode)).bind(prev => {
23659          const prevText = prev.container.data;
23660          return scanLeft(prev.container, offset + prevText.length, rootNode);
23661        });
23662      }
23663    };
23664    const scanRight = (node, offset, rootNode) => {
23665      if (!isText$b(node)) {
23666        return Optional.none();
23667      }
23668      const text = node.data;
23669      if (offset <= text.length) {
23670        return Optional.some(point(node, offset));
23671      } else {
23672        const textSeeker = TextSeeker(DOM$7);
23673        return Optional.from(textSeeker.forwards(node, offset, alwaysNext(node), rootNode)).bind(next => scanRight(next.container, offset - text.length, rootNode));
23674      }
23675    };
23676    const repeatLeft = (dom, node, offset, process, rootNode) => {
23677      const search = TextSeeker(dom, isBoundary(dom));
23678      return Optional.from(search.backwards(node, offset, process, rootNode));
23679    };
23680
23681    const isValidTextRange = rng => rng.collapsed && isText$b(rng.startContainer);
23682    const getText = rng => trim$2(rng.toString().replace(/\u00A0/g, ' '));
23683    const isWhitespace = chr => chr !== '' && ' \xA0\uFEFF\f\n\r\t\x0B'.indexOf(chr) !== -1;
23684
23685    const stripTrigger = (text, trigger) => text.substring(trigger.length);
23686    const findTrigger = (text, index, trigger, includeWhitespace = false) => {
23687      let i;
23688      const firstChar = trigger.charAt(0);
23689      for (i = index - 1; i >= 0; i--) {
23690        const char = text.charAt(i);
23691        if (!includeWhitespace && isWhitespace(char)) {
23692          return Optional.none();
23693        }
23694        if (firstChar === char && contains$1(text, trigger, i, index)) {
23695          break;
23696        }
23697      }
23698      return Optional.some(i);
23699    };
23700    const getContext = (dom, initRange, trigger, includeWhitespace = false) => {
23701      if (!isValidTextRange(initRange)) {
23702        return Optional.none();
23703      }
23704      const buffer = {
23705        text: '',
23706        offset: 0
23707      };
23708      const findTriggerIndex = (element, offset, text) => {
23709        buffer.text = text + buffer.text;
23710        buffer.offset += offset;
23711        return findTrigger(buffer.text, buffer.offset, trigger, includeWhitespace).getOr(offset);
23712      };
23713      const root = dom.getParent(initRange.startContainer, dom.isBlock) || dom.getRoot();
23714      return repeatLeft(dom, initRange.startContainer, initRange.startOffset, findTriggerIndex, root).bind(spot => {
23715        const range = initRange.cloneRange();
23716        range.setStart(spot.container, spot.offset);
23717        range.setEnd(initRange.endContainer, initRange.endOffset);
23718        if (range.collapsed) {
23719          return Optional.none();
23720        }
23721        const text = getText(range);
23722        const triggerIndex = text.lastIndexOf(trigger);
23723        if (triggerIndex !== 0) {
23724          return Optional.none();
23725        } else {
23726          return Optional.some({
23727            text: stripTrigger(text, trigger),
23728            range,
23729            trigger
23730          });
23731        }
23732      });
23733    }
vendor: 12,204 bytes, lines 23733-24073
23733;
23734
23735    const isText$1 = node => node.nodeType === TEXT;
23736    const isElement = node => node.nodeType === ELEMENT;
23737    const toLast = node => {
23738      if (isText$1(node)) {
23739        return point(node, node.data.length);
23740      } else {
23741        const children = node.childNodes;
23742        return children.length > 0 ? toLast(children[children.length - 1]) : point(node, children.length);
23743      }
23744    };
23745    const toLeaf = (node, offset) => {
23746      const children = node.childNodes;
23747      if (children.length > 0 && offset < children.length) {
23748        return toLeaf(children[offset], 0);
23749      } else if (children.length > 0 && isElement(node) && children.length === offset) {
23750        return toLast(children[children.length - 1]);
23751      } else {
23752        return point(node, offset);
23753      }
23754    };
23755
23756    const isPreviousCharContent = (dom, leaf) => {
23757      var _a;
23758      const root = (_a = dom.getParent(leaf.container, dom.isBlock)) !== null && _a !== void 0 ? _a : dom.getRoot();
23759      return repeatLeft(dom, leaf.container, leaf.offset, (_element, offset) => offset === 0 ? -1 : offset, root).filter(spot => {
23760        const char = spot.container.data.charAt(spot.offset - 1);
23761        return !isWhitespace(char);
23762      }).isSome();
23763    };
23764    const isStartOfWord = dom => rng => {
23765      const leaf = toLeaf(rng.startContainer, rng.startOffset);
23766      return !isPreviousCharContent(dom, leaf);
23767    };
23768    const getTriggerContext = (dom, initRange, database) => findMap(database.triggers, trigger => getContext(dom, initRange, trigger));
23769    const lookup = (editor, getDatabase) => {
23770      const database = getDatabase();
23771      const rng = editor.selection.getRng();
23772      return getTriggerContext(editor.dom, rng, database).bind(context => lookupWithContext(editor, getDatabase, context));
23773    };
23774    const lookupWithContext = (editor, getDatabase, context, fetchOptions = {}) => {
23775      var _a;
23776      const database = getDatabase();
23777      const rng = editor.selection.getRng();
23778      const startText = (_a = rng.startContainer.nodeValue) !== null && _a !== void 0 ? _a : '';
23779      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));
23780      if (autocompleters.length === 0) {
23781        return Optional.none();
23782      }
23783      const lookupData = Promise.all(map$3(autocompleters, ac => {
23784        const fetchResult = ac.fetch(context.text, ac.maxResults, fetchOptions);
23785        return fetchResult.then(results => ({
23786          matchText: context.text,
23787          items: results,
23788          columns: ac.columns,
23789          onAction: ac.onAction,
23790          highlightOn: ac.highlightOn
23791        }));
23792      }));
23793      return Optional.some({
23794        lookupData,
23795        context
23796      });
23797    };
23798
23799    var SimpleResultType;
23800    (function (SimpleResultType) {
23801      SimpleResultType[SimpleResultType['Error'] = 0] = 'Error';
23802      SimpleResultType[SimpleResultType['Value'] = 1] = 'Value';
23803    }(SimpleResultType || (SimpleResultType = {})));
23804    const fold$1 = (res, onError, onValue) => res.stype === SimpleResultType.Error ? onError(res.serror) : onValue(res.svalue);
23805    const partition = results => {
23806      const values = [];
23807      const errors = [];
23808      each$e(results, obj => {
23809        fold$1(obj, err => errors.push(err), val => values.push(val));
23810      });
23811      return {
23812        values,
23813        errors
23814      };
23815    };
23816    const mapError = (res, f) => {
23817      if (res.stype === SimpleResultType.Error) {
23818        return {
23819          stype: SimpleResultType.Error,
23820          serror: f(res.serror)
23821        };
23822      } else {
23823        return res;
23824      }
23825    };
23826    const map = (res, f) => {
23827      if (res.stype === SimpleResultType.Value) {
23828        return {
23829          stype: SimpleResultType.Value,
23830          svalue: f(res.svalue)
23831        };
23832      } else {
23833        return res;
23834      }
23835    };
23836    const bind$1 = (res, f) => {
23837      if (res.stype === SimpleResultType.Value) {
23838        return f(res.svalue);
23839      } else {
23840        return res;
23841      }
23842    };
23843    const bindError = (res, f) => {
23844      if (res.stype === SimpleResultType.Error) {
23845        return f(res.serror);
23846      } else {
23847        return res;
23848      }
23849    };
23850    const svalue = v => ({
23851      stype: SimpleResultType.Value,
23852      svalue: v
23853    });
23854    const serror = e => ({
23855      stype: SimpleResultType.Error,
23856      serror: e
23857    });
23858    const toResult = res => fold$1(res, Result.error, Result.value);
23859    const fromResult = res => res.fold(serror, svalue);
23860    const SimpleResult = {
23861      fromResult,
23862      toResult,
23863      svalue,
23864      partition,
23865      serror,
23866      bind: bind$1,
23867      bindError,
23868      map,
23869      mapError,
23870      fold: fold$1
23871    };
23872
23873    const formatObj = input => {
23874      return isObject(input) && keys(input).length > 100 ? ' removed due to size' : JSON.stringify(input, null, 2);
23875    };
23876    const formatErrors = errors => {
23877      const es = errors.length > 10 ? errors.slice(0, 10).concat([{
23878          path: [],
23879          getErrorInfo: constant('... (only showing first ten failures)')
23880        }]) : errors;
23881      return map$3(es, e => {
23882        return 'Failed path: (' + e.path.join(' > ') + ')\n' + e.getErrorInfo();
23883      });
23884    };
23885
23886    const nu = (path, getErrorInfo) => {
23887      return SimpleResult.serror([{
23888          path,
23889          getErrorInfo
23890        }]);
23891    };
23892    const missingRequired = (path, key, obj) => nu(path, () => 'Could not find valid *required* value for "' + key + '" in ' + formatObj(obj));
23893    const missingKey = (path, key) => nu(path, () => 'Choice schema did not contain choice key: "' + key + '"');
23894    const missingBranch = (path, branches, branch) => nu(path, () => 'The chosen schema: "' + branch + '" did not exist in branches: ' + formatObj(branches));
23895    const custom = (path, err) => nu(path, constant(err));
23896
23897    const chooseFrom = (path, input, branches, ch) => {
23898      const fields = get$a(branches, ch);
23899      return fields.fold(() => missingBranch(path, branches, ch), vp => vp.extract(path.concat(['branch: ' + ch]), input));
23900    };
23901    const choose$1 = (key, branches) => {
23902      const extract = (path, input) => {
23903        const choice = get$a(input, key);
23904        return choice.fold(() => missingKey(path, key), chosen => chooseFrom(path, input, branches, chosen));
23905      };
23906      const toString = () => 'chooseOn(' + key + '). Possible values: ' + keys(branches);
23907      return {
23908        extract,
23909        toString
23910      };
23911    };
23912
23913    const shallow = (old, nu) => {
23914      return nu;
23915    };
23916    const deep = (old, nu) => {
23917      const bothObjects = isPlainObject(old) && isPlainObject(nu);
23918      return bothObjects ? deepMerge(old, nu) : nu;
23919    };
23920    const baseMerge = merger => {
23921      return (...objects) => {
23922        if (objects.length === 0) {
23923          throw new Error(`Can't merge zero objects`);
23924        }
23925        const ret = {};
23926        for (let j = 0; j < objects.length; j++) {
23927          const curObject = objects[j];
23928          for (const key in curObject) {
23929            if (has$2(curObject, key)) {
23930              ret[key] = merger(ret[key], curObject[key]);
23931            }
23932          }
23933        }
23934        return ret;
23935      };
23936    };
23937    const deepMerge = baseMerge(deep);
23938    const merge = baseMerge(shallow);
23939
23940    const required = () => ({
23941      tag: 'required',
23942      process: {}
23943    });
23944    const defaultedThunk = fallbackThunk => ({
23945      tag: 'defaultedThunk',
23946      process: fallbackThunk
23947    });
23948    const defaulted$1 = fallback => defaultedThunk(constant(fallback));
23949    const asOption = () => ({
23950      tag: 'option',
23951      process: {}
23952    });
23953
23954    const mergeValues = (values, base) => values.length > 0 ? SimpleResult.svalue(deepMerge(base, merge.apply(undefined, values))) : SimpleResult.svalue(base);
23955    const mergeErrors = errors => compose(SimpleResult.serror, flatten)(errors);
23956    const consolidateObj = (objects, base) => {
23957      const partition = SimpleResult.partition(objects);
23958      return partition.errors.length > 0 ? mergeErrors(partition.errors) : mergeValues(partition.values, base);
23959    };
23960    const consolidateArr = objects => {
23961      const partitions = SimpleResult.partition(objects);
23962      return partitions.errors.length > 0 ? mergeErrors(partitions.errors) : SimpleResult.svalue(partitions.values);
23963    };
23964    const ResultCombine = {
23965      consolidateObj,
23966      consolidateArr
23967    };
23968
23969    const field$1 = (key, newKey, presence, prop) => ({
23970      tag: 'field',
23971      key,
23972      newKey,
23973      presence,
23974      prop
23975    });
23976    const customField$1 = (newKey, instantiator) => ({
23977      tag: 'custom',
23978      newKey,
23979      instantiator
23980    });
23981    const fold = (value, ifField, ifCustom) => {
23982      switch (value.tag) {
23983      case 'field':
23984        return ifField(value.key, value.newKey, value.presence, value.prop);
23985      case 'custom':
23986        return ifCustom(value.newKey, value.instantiator);
23987      }
23988    };
23989
23990    const value = validator => {
23991      const extract = (path, val) => {
23992        return SimpleResult.bindError(validator(val), err => custom(path, err));
23993      };
23994      const toString = constant('val');
23995      return {
23996        extract,
23997        toString
23998      };
23999    };
24000    const anyValue$1 = value(SimpleResult.svalue);
24001
24002    const requiredAccess = (path, obj, key, bundle) => get$a(obj, key).fold(() => missingRequired(path, key, obj), bundle);
24003    const fallbackAccess = (obj, key, fallback, bundle) => {
24004      const v = get$a(obj, key).getOrThunk(() => fallback(obj));
24005      return bundle(v);
24006    };
24007    const optionAccess = (obj, key, bundle) => bundle(get$a(obj, key));
24008    const optionDefaultedAccess = (obj, key, fallback, bundle) => {
24009      const opt = get$a(obj, key).map(val => val === true ? fallback(obj) : val);
24010      return bundle(opt);
24011    };
24012    const extractField = (field, path, obj, key, prop) => {
24013      const bundle = av => prop.extract(path.concat([key]), av);
24014      const bundleAsOption = optValue => optValue.fold(() => SimpleResult.svalue(Optional.none()), ov => {
24015        const result = prop.extract(path.concat([key]), ov);
24016        return SimpleResult.map(result, Optional.some);
24017      });
24018      switch (field.tag) {
24019      case 'required':
24020        return requiredAccess(path, obj, key, bundle);
24021      case 'defaultedThunk':
24022        return fallbackAccess(obj, key, field.process, bundle);
24023      case 'option':
24024        return optionAccess(obj, key, bundleAsOption);
24025      case 'defaultedOptionThunk':
24026        return optionDefaultedAccess(obj, key, field.process, bundleAsOption);
24027      case 'mergeWithThunk': {
24028          return fallbackAccess(obj, key, constant({}), v => {
24029            const result = deepMerge(field.process(obj), v);
24030            return bundle(result);
24031          });
24032        }
24033      }
24034    };
24035    const extractFields = (path, obj, fields) => {
24036      const success = {};
24037      const errors = [];
24038      for (const field of fields) {
24039        fold(field, (key, newKey, presence, prop) => {
24040          const result = extractField(presence, path, obj, key, prop);
24041          SimpleResult.fold(result, err => {
24042            errors.push(...err);
24043          }, res => {
24044            success[newKey] = res;
24045          });
24046        }, (newKey, instantiator) => {
24047          success[newKey] = instantiator(obj);
24048        });
24049      }
24050      return errors.length > 0 ? SimpleResult.serror(errors) : SimpleResult.svalue(success);
24051    };
24052    const objOf = values => {
24053      const extract = (path, o) => extractFields(path, o, values);
24054      const toString = () => {
24055        const fieldStrings = map$3(values, value => fold(value, (key, _okey, _presence, prop) => key + ' -> ' + prop.toString(), (newKey, _instantiator) => 'state(' + newKey + ')'));
24056        return 'obj{\n' + fieldStrings.join('\n') + '}';
24057      };
24058      return {
24059        extract,
24060        toString
24061      };
24062    };
24063    const arrOf = prop => {
24064      const extract = (path, array) => {
24065        const results = map$3(array, (a, i) => prop.extract(path.concat(['[' + i + ']']), a));
24066        return ResultCombine.consolidateArr(results);
24067      };
24068      const toString = () => 'array(' + prop.toString() + ')';
24069      return {
24070        extract,
24071        toString
24072      };
24073    };
vendor: 1,298 bytes, lines 24074-24109
24074    const oneOf = (props, rawF) => {
24075      const f = rawF !== undefined ? rawF : identity;
24076      const extract = (path, val) => {
24077        const errors = [];
24078        for (const prop of props) {
24079          const res = prop.extract(path, val);
24080          if (res.stype === SimpleResultType.Value) {
24081            return {
24082              stype: SimpleResultType.Value,
24083              svalue: f(res.svalue)
24084            };
24085          }
24086          errors.push(res);
24087        }
24088        return ResultCombine.consolidateArr(errors);
24089      };
24090      const toString = () => 'oneOf(' + map$3(props, prop => prop.toString()).join(', ') + ')';
24091      return {
24092        extract,
24093        toString
24094      };
24095    };
24096    const arrOfObj = compose(arrOf, objOf);
24097
24098    const valueOf = validator => value(v => validator(v).fold(SimpleResult.serror, SimpleResult.svalue));
24099    const extractValue = (label, prop, obj) => {
24100      const res = prop.extract([label], obj);
24101      return SimpleResult.mapError(res, errs => ({
24102        input: obj,
24103        errors: errs
24104      }));
24105    };
24106    const asRaw = (label, prop, obj) => SimpleResult.toResult(extractValue(label, prop, obj));
24107    const formatError = errInfo => {
24108      return 'Errors: \n' + formatErrors(errInfo.errors).join('\n') + '\n\nInput object: ' + formatObj(errInfo.input);
24109    };
24110    const choose = (key, branches) => choose$1(key, map$2(branches, objOf));
24111
24112    const anyValue = constant(anyValue$1);
24113    const typedValue = (validator, expectedType) => value(a => {
24114      const actualType = typeof a;
24115      return validator(a) ? SimpleResult.svalue(a) : SimpleResult.serror(`Expected type: ${ expectedType } but got: ${ actualType }`);
24116    });
24117    const number = typedValue(isNumber, 'number');
24118    const string = typedValue(isString, 'string');
24119    const boolean = typedValue(isBoolean, 'boolean');
24120    const functionProcessor = typedValue(isFunction, 'function');
24121
24122    const field = field$1;
24123    const customField = customField$1;
24124    const validateEnum = values => valueOf(value => contains$2(values, value) ? Result.value(value) : Result.error(`Unsupported value: "${ value }", choose one of "${ values.join(', ') }".`));
24125    const requiredOf = (key, schema) => field(key, key, required(), schema);
24126    const requiredString = key => requiredOf(key, string);
24127    const requiredStringEnum = (key, values) => field(key, key, required(), validateEnum(values));
24128    const requiredFunction = key => requiredOf(key, functionProcessor);
24129    const requiredArrayOf = (key, schema) => field(key, key, required(), arrOf(schema));
24130    const optionOf = (key, schema) => field(key, key, asOption(), schema);
24131    const optionString = key => optionOf(key, string);
24132    const optionFunction = key => optionOf(key, functionProcessor);
24133    const defaulted = (key, fallback) => field(key, key, defaulted$1(fallback), anyValue());
24134    const defaultedOf = (key, fallback, schema) => field(key, key, defaulted$1(fallback), schema);
24135    const defaultedNumber = (key, fallback) => defaultedOf(key, fallback, number);
24136    const defaultedString = (key, fallback) => defaultedOf(key, fallback, string);
24137    const defaultedStringEnum = (key, fallback, values) => defaultedOf(key, fallback, validateEnum(values));
24138    const defaultedBoolean = (key, fallback) => defaultedOf(key, fallback, boolean);
24139    const defaultedFunction = (key, fallback) => defaultedOf(key, fallback, functionProcessor);
24140    const defaultedArrayOf = (key, fallback, schema) => defaultedOf(key, fallback, arrOf(schema));
24141
24142    const type = requiredString('type');
24143    const fetch$1 = requiredFunction('fetch');
24144    const onAction = requiredFunction('onAction');
24145    const onSetup = defaultedFunction('onSetup', () => noop);
24146    const optionalText = optionString('text');
24147    const optionalIcon = optionString('icon');
24148    const optionalTooltip = optionString('tooltip');
24149    const optionalLabel = optionString('label');
24150    const active = defaultedBoolean('active', false);
24151    const enabled = defaultedBoolean('enabled', true);
24152    const primary = defaultedBoolean('primary', false);
24153    const defaultedColumns = num => defaulted('columns', num);
24154    const defaultedType = type => defaultedString('type', type);
24155
24156    const autocompleterSchema = objOf([
24157      type,
24158      requiredString('trigger'),
24159      defaultedNumber('minChars', 1),
24160      defaultedColumns(1),
24161      defaultedNumber('maxResults', 10),
24162      optionFunction('matches'),
24163      fetch$1,
24164      onAction,
24165      defaultedArrayOf('highlightOn', [], string)
24166    ]);
24167    const createAutocompleter = spec => asRaw('Autocompleter', autocompleterSchema, spec);
24168
24169    const baseToolbarButtonFields = [
24170      enabled,
24171      optionalTooltip,
24172      optionalIcon,
24173      optionalText,
24174      onSetup,
24175      defaultedString('context', 'mode:design')
24176    ];
24177
24178    const baseToolbarToggleButtonFields = [active].concat(baseToolbarButtonFields);
24179
24180    const contextBarFields = [
24181      defaultedFunction('predicate', never),
24182      defaultedStringEnum('scope', 'node', [
24183        'node',
24184        'editor'
24185      ]),
24186      defaultedStringEnum('position', 'selection', [
24187        'node',
24188        'selection',
24189        'line'
24190      ])
24191    ];
24192
24193    const contextButtonFields = baseToolbarButtonFields.concat([
24194      defaultedType('contextformbutton'),
24195      defaultedString('align', 'end'),
24196      primary,
24197      onAction,
24198      customField('original', identity)
24199    ]);
24200    const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([
24201      defaultedType('contextformbutton'),
24202      defaultedString('align', 'end'),
24203      primary,
24204      onAction,
24205      customField('original', identity)
24206    ]);
24207    const launchButtonFields = baseToolbarButtonFields.concat([defaultedType('contextformbutton')]);
24208    const launchToggleButtonFields = baseToolbarToggleButtonFields.concat([defaultedType('contextformtogglebutton')]);
24209    const toggleOrNormal = choose('type', {
24210      contextformbutton: contextButtonFields,
24211      contextformtogglebutton: contextToggleButtonFields
24212    });
24213    const baseContextFormFields = [
24214      optionalLabel,
24215      requiredArrayOf('commands', toggleOrNormal),
24216      optionOf('launch', choose('type', {
24217        contextformbutton: launchButtonFields,
24218        contextformtogglebutton: launchToggleButtonFields
24219      })),
24220      defaultedFunction('onInput', noop),
24221      defaultedFunction('onSetup', noop)
24222    ];
24223    const contextFormFields = [
24224      ...contextBarFields,
24225      ...baseContextFormFields,
24226      requiredStringEnum('type', ['contextform']),
24227      defaultedFunction('initValue', constant('')),
24228      optionString('placeholder')
24229    ];
24230    const contextSliderFormFields = [
24231      ...contextBarFields,
24232      ...baseContextFormFields,
24233      requiredStringEnum('type', ['contextsliderform']),
24234      defaultedFunction('initValue', constant(0)),
24235      defaultedFunction('min', constant(0)),
24236      defaultedFunction('max', constant(100))
24237    ];
24238    const contextSizeInputFormFields = [
24239      ...contextBarFields,
24240      ...baseContextFormFields,
24241      requiredStringEnum('type', ['contextsizeinputform']),
24242      defaultedFunction('initValue', constant({
24243        width: '',
24244        height: ''
24245      }))
24246    ];
24247    choose('type', {
24248      contextform: contextFormFields,
24249      contextsliderform: contextSliderFormFields,
24250      contextsizeinputform: contextSizeInputFormFields
24251    });
24252
24253    objOf([
24254      defaultedType('contexttoolbar'),
24255      requiredOf('items', oneOf([
24256        string,
24257        arrOfObj([
24258          optionString('name'),
24259          optionString('label'),
24260          requiredArrayOf('items', string)
24261        ])
24262      ]))
24263    ].concat(contextBarFields));
24264
24265    const register$2 = editor => {
24266      const popups = editor.ui.registry.getAll().popups;
24267      const dataset = map$2(popups, popup => createAutocompleter(popup).fold(err => {
24268        throw new Error(formatError(err));
24269      }, identity));
24270      const triggers = stringArray(mapToArray(dataset, v => v.trigger));
24271      const datasetValues = values(dataset);
24272      const lookupByTrigger = trigger => filter$5(datasetValues, dv => dv.trigger === trigger);
24273      return {
24274        dataset,
24275        triggers,
24276        lookupByTrigger
24277      };
24278    };
24279
24280    const setupEditorInput = (editor, api) => {
24281      const update = last(api.load, 50);
24282      editor.on('input', e => {
24283        if (e.inputType === 'insertCompositionText' && !editor.composing) {
24284          return;
24285        }
24286        update.throttle();
24287      });
24288      editor.on('keydown', e => {
24289        const keyCode = e.which;
24290        if (keyCode === 8) {
24291          update.throttle();
24292        } else if (keyCode === 27) {
24293          update.cancel();
24294          api.cancelIfNecessary();
24295        } else if (keyCode === 38 || keyCode === 40) {
24296          update.cancel();
24297        }
24298      }, true);
24299      editor.on('remove', update.cancel);
24300    };
24301    const setup$k = editor => {
24302      const activeAutocompleter = value$2();
24303      const uiActive = Cell(false);
24304      const isActive = activeAutocompleter.isSet;
24305      const cancelIfNecessary = () => {
24306        if (isActive()) {
24307          fireAutocompleterEnd(editor);
24308          uiActive.set(false);
24309          activeAutocompleter.clear();
24310        }
24311      };
24312      const commenceIfNecessary = context => {
24313        if (!isActive()) {
24314          activeAutocompleter.set({
24315            trigger: context.trigger,
24316            matchLength: context.text.length
24317          });
24318        }
24319      };
24320      const getAutocompleters = cached(() => register$2(editor));
24321      const doLookup = fetchOptions => activeAutocompleter.get().map(ac => getContext(editor.dom, editor.selection.getRng(), ac.trigger, true).bind(newContext => lookupWithContext(editor, getAutocompleters, newContext, fetchOptions))).getOrThunk(() => lookup(editor, getAutocompleters));
24322      const load = fetchOptions => {
24323        doLookup(fetchOptions).fold(cancelIfNecessary, lookupInfo => {
24324          commenceIfNecessary(lookupInfo.context);
24325          lookupInfo.lookupData.then(lookupData => {
24326            activeAutocompleter.get().map(ac => {
24327              const context = lookupInfo.context;
24328              if (ac.trigger !== context.trigger) {
24329                return;
24330              }
24331              activeAutocompleter.set({
24332                ...ac,
24333                matchLength: context.text.length
24334              });
24335              if (uiActive.get()) {
24336                fireAutocompleterUpdateActiveRange(editor, { range: context.range });
24337                fireAutocompleterUpdate(editor, { lookupData });
24338              } else {
24339                uiActive.set(true);
24340                fireAutocompleterUpdateActiveRange(editor, { range: context.range });
24341                fireAutocompleterStart(editor, { lookupData });
vendor: 12,939 bytes, lines 24341-24606
24341
24342              }
24343            });
24344          });
24345        });
24346      };
24347      const isRangeInsideOrEqual = (innerRange, outerRange) => {
24348        const startComparison = innerRange.compareBoundaryPoints(window.Range.START_TO_START, outerRange);
24349        const endComparison = innerRange.compareBoundaryPoints(window.Range.END_TO_END, outerRange);
24350        return startComparison >= 0 && endComparison <= 0;
24351      };
24352      const readActiveRange = () => {
24353        return activeAutocompleter.get().bind(({trigger}) => {
24354          const selRange = editor.selection.getRng();
24355          return getContext(editor.dom, selRange, trigger, uiActive.get()).filter(({range}) => isRangeInsideOrEqual(selRange, range)).map(({range}) => range);
24356        });
24357      };
24358      editor.addCommand('mceAutocompleterReload', (_ui, value) => {
24359        const fetchOptions = isObject(value) ? value.fetchOptions : {};
24360        load(fetchOptions);
24361      });
24362      editor.addCommand('mceAutocompleterClose', cancelIfNecessary);
24363      editor.addCommand('mceAutocompleterRefreshActiveRange', () => {
24364        readActiveRange().each(range => {
24365          fireAutocompleterUpdateActiveRange(editor, { range });
24366        });
24367      });
24368      editor.editorCommands.addQueryStateHandler('mceAutoCompleterInRange', () => readActiveRange().isSome());
24369      setupEditorInput(editor, {
24370        cancelIfNecessary,
24371        load
24372      });
24373    };
24374
24375    const browser$1 = detect$1().browser;
24376    const isSafari = browser$1.isSafari();
24377    const emptyNodeContents = node => fillWithPaddingBr(SugarElement.fromDom(node));
24378    const isEntireNodeSelected = (rng, node) => {
24379      var _a;
24380      return rng.startOffset === 0 && rng.endOffset === ((_a = node.textContent) === null || _a === void 0 ? void 0 : _a.length);
24381    };
24382    const getParentDetailsElementAtPos = (dom, pos) => Optional.from(dom.getParent(pos.container(), 'details'));
24383    const isInDetailsElement = (dom, pos) => getParentDetailsElementAtPos(dom, pos).isSome();
24384    const getDetailsElements = (dom, rng) => {
24385      const startDetails = Optional.from(dom.getParent(rng.startContainer, 'details'));
24386      const endDetails = Optional.from(dom.getParent(rng.endContainer, 'details'));
24387      if (startDetails.isSome() || endDetails.isSome()) {
24388        const startSummary = startDetails.bind(details => Optional.from(dom.select('summary', details)[0]));
24389        return Optional.some({
24390          startSummary,
24391          startDetails,
24392          endDetails
24393        });
24394      } else {
24395        return Optional.none();
24396      }
24397    };
24398    const isCaretInTheBeginningOf = (caretPos, element) => firstPositionIn(element).exists(pos => pos.isEqual(caretPos));
24399    const isCaretInTheEndOf = (caretPos, element) => {
24400      return lastPositionIn(element).exists(pos => {
24401        if (isBr$6(pos.getNode())) {
24402          return prevPosition(element, pos).exists(pos2 => pos2.isEqual(caretPos)) || pos.isEqual(caretPos);
24403        } else {
24404          return pos.isEqual(caretPos);
24405        }
24406      });
24407    };
24408    const isCaretAtStartOfSummary = (caretPos, detailsElements) => detailsElements.startSummary.exists(summary => isCaretInTheBeginningOf(caretPos, summary));
24409    const isCaretAtEndOfSummary = (caretPos, detailsElements) => detailsElements.startSummary.exists(summary => isCaretInTheEndOf(caretPos, summary));
24410    const isCaretInFirstPositionInBody = (caretPos, detailsElements) => detailsElements.startDetails.exists(details => prevPosition(details, caretPos).forall(pos => detailsElements.startSummary.exists(summary => !summary.contains(caretPos.container()) && summary.contains(pos.container()))));
24411    const isCaretInLastPositionInBody = (root, caretPos, detailsElements) => detailsElements.startDetails.exists(details => nextPosition(root, caretPos).forall(pos => !details.contains(pos.container())));
24412    const setCaretToPosition = (editor, position) => {
24413      const node = position.getNode();
24414      if (!isUndefined(node)) {
24415        editor.selection.setCursorLocation(node, position.offset());
24416      }
24417    };
24418    const moveCaretToDetailsPos = (editor, pos, forward) => {
24419      const details = editor.dom.getParent(pos.container(), 'details');
24420      if (details && !details.open) {
24421        const summary = editor.dom.select('summary', details)[0];
24422        if (summary) {
24423          const newPos = forward ? firstPositionIn(summary) : lastPositionIn(summary);
24424          newPos.each(pos => setCaretToPosition(editor, pos));
24425        }
24426      } else {
24427        setCaretToPosition(editor, pos);
24428      }
24429    };
24430    const isPartialDelete = (rng, detailsElements) => {
24431      const containsStart = element => element.contains(rng.startContainer);
24432      const containsEnd = element => element.contains(rng.endContainer);
24433      const startInSummary = detailsElements.startSummary.exists(containsStart);
24434      const endInSummary = detailsElements.startSummary.exists(containsEnd);
24435      const isPartiallySelectedDetailsElements = detailsElements.startDetails.forall(startDetails => detailsElements.endDetails.forall(endDetails => startDetails !== endDetails));
24436      const isInPartiallySelectedSummary = (startInSummary || endInSummary) && !(startInSummary && endInSummary);
24437      return isInPartiallySelectedSummary || isPartiallySelectedDetailsElements;
24438    };
24439    const shouldPreventDeleteIntoDetails = (editor, forward, granularity) => {
24440      const {dom, selection} = editor;
24441      const root = editor.getBody();
24442      if (granularity === 'character') {
24443        const caretPos = CaretPosition.fromRangeStart(selection.getRng());
24444        const parentBlock = dom.getParent(caretPos.container(), dom.isBlock);
24445        const parentDetailsAtCaret = getParentDetailsElementAtPos(dom, caretPos);
24446        const inEmptyParentBlock = parentBlock && dom.isEmpty(parentBlock);
24447        const isFirstBlock = isNull(parentBlock === null || parentBlock === void 0 ? void 0 : parentBlock.previousSibling);
24448        const isLastBlock = isNull(parentBlock === null || parentBlock === void 0 ? void 0 : parentBlock.nextSibling);
24449        if (inEmptyParentBlock) {
24450          const firstOrLast = forward ? isLastBlock : isFirstBlock;
24451          if (firstOrLast) {
24452            const isBeforeAfterDetails = navigate(!forward, root, caretPos).exists(pos => {
24453              return isInDetailsElement(dom, pos) && !equals(parentDetailsAtCaret, getParentDetailsElementAtPos(dom, pos));
24454            });
24455            if (isBeforeAfterDetails) {
24456              return true;
24457            }
24458          }
24459        }
24460        return navigate(forward, root, caretPos).fold(never, pos => {
24461          const parentDetailsAtNewPos = getParentDetailsElementAtPos(dom, pos);
24462          if (isInDetailsElement(dom, pos) && !equals(parentDetailsAtCaret, parentDetailsAtNewPos)) {
24463            if (!forward) {
24464              moveCaretToDetailsPos(editor, pos, false);
24465            }
24466            if (parentBlock && inEmptyParentBlock) {
24467              if (forward && isFirstBlock) {
24468                return true;
24469              } else if (!forward && isLastBlock) {
24470                return true;
24471              }
24472              moveCaretToDetailsPos(editor, pos, forward);
24473              editor.dom.remove(parentBlock);
24474            }
24475            return true;
24476          } else {
24477            return false;
24478          }
24479        });
24480      } else {
24481        return false;
24482      }
24483    };
24484    const shouldPreventDeleteSummaryAction = (editor, detailElements, forward, granularity) => {
24485      const selection = editor.selection;
24486      const rng = selection.getRng();
24487      const caretPos = CaretPosition.fromRangeStart(rng);
24488      const root = editor.getBody();
24489      if (granularity === 'selection') {
24490        return isPartialDelete(rng, detailElements);
24491      } else if (forward) {
24492        return isCaretAtEndOfSummary(caretPos, detailElements) || isCaretInLastPositionInBody(root, caretPos, detailElements);
24493      } else {
24494        return isCaretAtStartOfSummary(caretPos, detailElements) || isCaretInFirstPositionInBody(caretPos, detailElements);
24495      }
24496    };
24497    const shouldPreventDeleteAction = (editor, forward, granularity) => getDetailsElements(editor.dom, editor.selection.getRng()).fold(() => shouldPreventDeleteIntoDetails(editor, forward, granularity), detailsElements => shouldPreventDeleteSummaryAction(editor, detailsElements, forward, granularity) || shouldPreventDeleteIntoDetails(editor, forward, granularity));
24498    const handleDeleteActionSafari = (editor, forward, granularity) => {
24499      const selection = editor.selection;
24500      const node = selection.getNode();
24501      const rng = selection.getRng();
24502      const caretPos = CaretPosition.fromRangeStart(rng);
24503      if (isSummary$1(node)) {
24504        if (granularity === 'selection' && isEntireNodeSelected(rng, node) || willDeleteLastPositionInElement(forward, caretPos, node)) {
24505          emptyNodeContents(node);
24506        } else {
24507          editor.undoManager.transact(() => {
24508            const sel = selection.getSel();
24509            let {anchorNode, anchorOffset, focusNode, focusOffset} = sel !== null && sel !== void 0 ? sel : {};
24510            const applySelection = () => {
24511              if (isNonNullable(anchorNode) && isNonNullable(anchorOffset) && isNonNullable(focusNode) && isNonNullable(focusOffset)) {
24512                sel === null || sel === void 0 ? void 0 : sel.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
24513              }
24514            };
24515            const updateSelection = () => {
24516              anchorNode = sel === null || sel === void 0 ? void 0 : sel.anchorNode;
24517              anchorOffset = sel === null || sel === void 0 ? void 0 : sel.anchorOffset;
24518              focusNode = sel === null || sel === void 0 ? void 0 : sel.focusNode;
24519              focusOffset = sel === null || sel === void 0 ? void 0 : sel.focusOffset;
24520            };
24521            const appendAllChildNodes = (from, to) => {
24522              each$e(from.childNodes, child => {
24523                if (isNode(child)) {
24524                  to.appendChild(child);
24525                }
24526              });
24527            };
24528            const container = editor.dom.create('span', { 'data-mce-bogus': '1' });
24529            appendAllChildNodes(node, container);
24530            node.appendChild(container);
24531            applySelection();
24532            if (granularity === 'word' || granularity === 'line') {
24533              sel === null || sel === void 0 ? void 0 : sel.modify('extend', forward ? 'right' : 'left', granularity);
24534            }
24535            if (!selection.isCollapsed() && isEntireNodeSelected(selection.getRng(), container)) {
24536              emptyNodeContents(node);
24537            } else {
24538              editor.execCommand(forward ? 'ForwardDelete' : 'Delete');
24539              updateSelection();
24540              appendAllChildNodes(container, node);
24541              applySelection();
24542            }
24543            editor.dom.remove(container);
24544          });
24545        }
24546        return true;
24547      } else {
24548        return false;
24549      }
24550    };
24551    const backspaceDelete = (editor, forward, granularity) => shouldPreventDeleteAction(editor, forward, granularity) || isSafari && handleDeleteActionSafari(editor, forward, granularity) ? Optional.some(noop) : Optional.none();
24552
24553    const createAndFireInputEvent = eventType => (editor, inputType, specifics = {}) => {
24554      const target = editor.getBody();
24555      const overrides = {
24556        bubbles: true,
24557        composed: true,
24558        data: null,
24559        isComposing: false,
24560        detail: 0,
24561        view: null,
24562        target,
24563        currentTarget: target,
24564        eventPhase: Event.AT_TARGET,
24565        originalTarget: target,
24566        explicitOriginalTarget: target,
24567        isTrusted: false,
24568        srcElement: target,
24569        cancelable: false,
24570        preventDefault: noop,
24571        inputType
24572      };
24573      const input = clone$3(new InputEvent(eventType));
24574      return editor.dispatch(eventType, {
24575        ...input,
24576        ...overrides,
24577        ...specifics
24578      });
24579    };
24580    const fireInputEvent = createAndFireInputEvent('input');
24581    const fireBeforeInputEvent = createAndFireInputEvent('beforeinput');
24582
24583    const platform$2 = detect$1();
24584    const os = platform$2.os;
24585    const isMacOSOriOS = os.isMacOS() || os.isiOS();
24586    const browser = platform$2.browser;
24587    const isFirefox = browser.isFirefox();
24588    const executeKeydownOverride$3 = (editor, caret, evt) => {
24589      const inputType = evt.keyCode === VK.BACKSPACE ? 'deleteContentBackward' : 'deleteContentForward';
24590      const isCollapsed = editor.selection.isCollapsed();
24591      const unmodifiedGranularity = isCollapsed ? 'character' : 'selection';
24592      const getModifiedGranularity = isWord => {
24593        if (isCollapsed) {
24594          return isWord ? 'word' : 'line';
24595        } else {
24596          return 'selection';
24597        }
24598      };
24599      executeWithDelayedAction([
24600        {
24601          keyCode: VK.BACKSPACE,
24602          action: action(backspaceDelete$1, editor)
24603        },
24604        {
24605          keyCode: VK.BACKSPACE,
24606          action: action(backspaceDelete$
vendor: 3,309 bytes, lines 24606-24718
246067, editor, false)
24607        },
24608        {
24609          keyCode: VK.DELETE,
24610          action: action(backspaceDelete$7, editor, true)
24611        },
24612        {
24613          keyCode: VK.BACKSPACE,
24614          action: action(backspaceDelete$8, editor, false)
24615        },
24616        {
24617          keyCode: VK.DELETE,
24618          action: action(backspaceDelete$8, editor, true)
24619        },
24620        {
24621          keyCode: VK.BACKSPACE,
24622          action: action(backspaceDelete$4, editor, caret, false)
24623        },
24624        {
24625          keyCode: VK.DELETE,
24626          action: action(backspaceDelete$4, editor, caret, true)
24627        },
24628        {
24629          keyCode: VK.BACKSPACE,
24630          action: action(backspaceDelete$b, editor, false)
24631        },
24632        {
24633          keyCode: VK.DELETE,
24634          action: action(backspaceDelete$b, editor, true)
24635        },
24636        {
24637          keyCode: VK.BACKSPACE,
24638          action: action(backspaceDelete, editor, false, unmodifiedGranularity)
24639        },
24640        {
24641          keyCode: VK.DELETE,
24642          action: action(backspaceDelete, editor, true, unmodifiedGranularity)
24643        },
24644        ...isMacOSOriOS ? [
24645          {
24646            keyCode: VK.BACKSPACE,
24647            altKey: true,
24648            action: action(backspaceDelete, editor, false, getModifiedGranularity(true))
24649          },
24650          {
24651            keyCode: VK.DELETE,
24652            altKey: true,
24653            action: action(backspaceDelete, editor, true, getModifiedGranularity(true))
24654          },
24655          {
24656            keyCode: VK.BACKSPACE,
24657            metaKey: true,
24658            action: action(backspaceDelete, editor, false, getModifiedGranularity(false))
24659          }
24660        ] : [
24661          {
24662            keyCode: VK.BACKSPACE,
24663            ctrlKey: true,
24664            action: action(backspaceDelete, editor, false, getModifiedGranularity(true))
24665          },
24666          {
24667            keyCode: VK.DELETE,
24668            ctrlKey: true,
24669            action: action(backspaceDelete, editor, true, getModifiedGranularity(true))
24670          }
24671        ],
24672        {
24673          keyCode: VK.BACKSPACE,
24674          action: action(backspaceDelete$5, editor, false)
24675        },
24676        {
24677          keyCode: VK.DELETE,
24678          action: action(backspaceDelete$5, editor, true)
24679        },
24680        {
24681          keyCode: VK.BACKSPACE,
24682          action: action(backspaceDelete$2, editor, false)
24683        },
24684        {
24685          keyCode: VK.DELETE,
24686          action: action(backspaceDelete$2, editor, true)
24687        },
24688        {
24689          keyCode: VK.BACKSPACE,
24690          action: action(backspaceDelete$9, editor, false)
24691        },
24692        {
24693          keyCode: VK.DELETE,
24694          action: action(backspaceDelete$9, editor, true)
24695        },
24696        {
24697          keyCode: VK.BACKSPACE,
24698          action: action(backspaceDelete$a, editor, false)
24699        },
24700        {
24701          keyCode: VK.DELETE,
24702          action: action(backspaceDelete$a, editor, true)
24703        },
24704        {
24705          keyCode: VK.BACKSPACE,
24706          action: action(backspaceDelete$3, editor, false)
24707        },
24708        {
24709          keyCode: VK.DELETE,
24710          action: action(backspaceDelete$3, editor, true)
24711        },
24712        {
24713          keyCode: VK.BACKSPACE,
24714          action: action(backspaceDelete$6, editor, false)
24715        },
24716        {
24717          keyCode: VK.DELETE,
24718          action: action(backspaceDelete$6
vendor: 14,095 bytes, lines 24718-25081
24718, editor, true)
24719        }
24720      ], evt).filter(_ => editor.selection.isEditable()).each(applyAction => {
24721        evt.preventDefault();
24722        const beforeInput = fireBeforeInputEvent(editor, inputType);
24723        if (!beforeInput.isDefaultPrevented()) {
24724          applyAction();
24725          fireInputEvent(editor, inputType);
24726        }
24727      });
24728    };
24729    const executeKeyupOverride = (editor, evt, isBackspaceKeydown) => execute([
24730      {
24731        keyCode: VK.BACKSPACE,
24732        action: action(paddEmptyElement, editor)
24733      },
24734      {
24735        keyCode: VK.DELETE,
24736        action: action(paddEmptyElement, editor)
24737      },
24738      ...isMacOSOriOS ? [
24739        {
24740          keyCode: VK.BACKSPACE,
24741          altKey: true,
24742          action: action(refreshCaret, editor)
24743        },
24744        {
24745          keyCode: VK.DELETE,
24746          altKey: true,
24747          action: action(refreshCaret, editor)
24748        },
24749        ...isBackspaceKeydown ? [{
24750            keyCode: isFirefox ? 224 : 91,
24751            action: action(refreshCaret, editor)
24752          }] : []
24753      ] : [
24754        {
24755          keyCode: VK.BACKSPACE,
24756          ctrlKey: true,
24757          action: action(refreshCaret, editor)
24758        },
24759        {
24760          keyCode: VK.DELETE,
24761          ctrlKey: true,
24762          action: action(refreshCaret, editor)
24763        }
24764      ]
24765    ], evt);
24766    const setup$j = (editor, caret) => {
24767      let isBackspaceKeydown = false;
24768      editor.on('keydown', evt => {
24769        isBackspaceKeydown = evt.keyCode === VK.BACKSPACE;
24770        if (!evt.isDefaultPrevented()) {
24771          executeKeydownOverride$3(editor, caret, evt);
24772        }
24773      });
24774      editor.on('keyup', evt => {
24775        if (!evt.isDefaultPrevented()) {
24776          executeKeyupOverride(editor, evt, isBackspaceKeydown);
24777        }
24778        isBackspaceKeydown = false;
24779      });
24780    };
24781
24782    const firstNonWhiteSpaceNodeSibling = node => {
24783      while (node) {
24784        if (isElement$6(node) || isText$b(node) && node.data && /[\r\n\s]/.test(node.data)) {
24785          return node;
24786        }
24787        node = node.nextSibling;
24788      }
24789      return null;
24790    };
24791    const moveToCaretPosition = (editor, root) => {
24792      const dom = editor.dom;
24793      const moveCaretBeforeOnEnterElementsMap = editor.schema.getMoveCaretBeforeOnEnterElements();
24794      if (!root) {
24795        return;
24796      }
24797      if (/^(LI|DT|DD)$/.test(root.nodeName)) {
24798        const firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
24799        if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) {
24800          root.insertBefore(dom.doc.createTextNode(nbsp), root.firstChild);
24801        }
24802      }
24803      const rng = dom.createRng();
24804      root.normalize();
24805      if (root.hasChildNodes()) {
24806        const walker = new DomTreeWalker(root, root);
24807        let lastNode = root;
24808        let node;
24809        while (node = walker.current()) {
24810          if (isText$b(node)) {
24811            rng.setStart(node, 0);
24812            rng.setEnd(node, 0);
24813            break;
24814          }
24815          if (moveCaretBeforeOnEnterElementsMap[node.nodeName.toLowerCase()]) {
24816            rng.setStartBefore(node);
24817            rng.setEndBefore(node);
24818            break;
24819          }
24820          lastNode = node;
24821          node = walker.next();
24822        }
24823        if (!node) {
24824          rng.setStart(lastNode, 0);
24825          rng.setEnd(lastNode, 0);
24826        }
24827      } else {
24828        if (isBr$6(root)) {
24829          if (root.nextSibling && dom.isBlock(root.nextSibling)) {
24830            rng.setStartBefore(root);
24831            rng.setEndBefore(root);
24832          } else {
24833            rng.setStartAfter(root);
24834            rng.setEndAfter(root);
24835          }
24836        } else {
24837          rng.setStart(root, 0);
24838          rng.setEnd(root, 0);
24839        }
24840      }
24841      editor.selection.setRng(rng);
24842      scrollRangeIntoView(editor, rng);
24843    };
24844    const getEditableRoot = (dom, node) => {
24845      const root = dom.getRoot();
24846      let editableRoot;
24847      let parent = node;
24848      while (parent !== root && parent && dom.getContentEditable(parent) !== 'false') {
24849        if (dom.getContentEditable(parent) === 'true') {
24850          editableRoot = parent;
24851          break;
24852        }
24853        parent = parent.parentNode;
24854      }
24855      return parent !== root ? editableRoot : root;
24856    };
24857    const getParentBlock$1 = editor => {
24858      return Optional.from(editor.dom.getParent(editor.selection.getStart(true), editor.dom.isBlock));
24859    };
24860    const getParentBlockName = editor => {
24861      return getParentBlock$1(editor).fold(constant(''), parentBlock => {
24862        return parentBlock.nodeName.toUpperCase();
24863      });
24864    };
24865    const isListItemParentBlock = editor => {
24866      return getParentBlock$1(editor).filter(elm => {
24867        return isListItem$1(SugarElement.fromDom(elm));
24868      }).isSome();
24869    };
24870    const emptyBlock = elm => {
24871      elm.innerHTML = '<br data-mce-bogus="1">';
24872    };
24873    const applyAttributes = (editor, node, forcedRootBlockAttrs) => {
24874      const dom = editor.dom;
24875      Optional.from(forcedRootBlockAttrs.style).map(dom.parseStyle).each(attrStyles => {
24876        const currentStyles = getAllRaw(SugarElement.fromDom(node));
24877        const newStyles = {
24878          ...currentStyles,
24879          ...attrStyles
24880        };
24881        dom.setStyles(node, newStyles);
24882      });
24883      const attrClassesOpt = Optional.from(forcedRootBlockAttrs.class).map(attrClasses => attrClasses.split(/\s+/));
24884      const currentClassesOpt = Optional.from(node.className).map(currentClasses => filter$5(currentClasses.split(/\s+/), clazz => clazz !== ''));
24885      lift2(attrClassesOpt, currentClassesOpt, (attrClasses, currentClasses) => {
24886        const filteredClasses = filter$5(currentClasses, clazz => !contains$2(attrClasses, clazz));
24887        const newClasses = [
24888          ...attrClasses,
24889          ...filteredClasses
24890        ];
24891        dom.setAttrib(node, 'class', newClasses.join(' '));
24892      });
24893      const appliedAttrs = [
24894        'style',
24895        'class'
24896      ];
24897      const remainingAttrs = filter$4(forcedRootBlockAttrs, (_, attrs) => !contains$2(appliedAttrs, attrs));
24898      dom.setAttribs(node, remainingAttrs);
24899    };
24900    const setForcedBlockAttrs = (editor, node) => {
24901      const forcedRootBlockName = getForcedRootBlock(editor);
24902      if (forcedRootBlockName.toLowerCase() === node.tagName.toLowerCase()) {
24903        const forcedRootBlockAttrs = getForcedRootBlockAttrs(editor);
24904        applyAttributes(editor, node, forcedRootBlockAttrs);
24905      }
24906    };
24907    const createNewBlock = (editor, container, parentBlock, editableRoot, keepStyles = true, name, styles) => {
24908      const dom = editor.dom;
24909      const schema = editor.schema;
24910      const newBlockName = getForcedRootBlock(editor);
24911      const parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : '';
24912      let node = container;
24913      const textInlineElements = schema.getTextInlineElements();
24914      let block;
24915      if (name || parentBlockName === 'TABLE' || parentBlockName === 'HR') {
24916        block = dom.create(name || newBlockName, styles || {});
24917      } else {
24918        block = parentBlock.cloneNode(false);
24919      }
24920      let caretNode = block;
24921      if (!keepStyles) {
24922        dom.setAttrib(block, 'style', null);
24923        dom.setAttrib(block, 'class', null);
24924      } else {
24925        do {
24926          if (textInlineElements[node.nodeName]) {
24927            if (isCaretNode(node) || isBookmarkNode$1(node)) {
24928              continue;
24929            }
24930            const clonedNode = node.cloneNode(false);
24931            dom.setAttrib(clonedNode, 'id', '');
24932            if (block.hasChildNodes()) {
24933              clonedNode.appendChild(block.firstChild);
24934              block.appendChild(clonedNode);
24935            } else {
24936              caretNode = clonedNode;
24937              block.appendChild(clonedNode);
24938            }
24939          }
24940        } while ((node = node.parentNode) && node !== editableRoot);
24941      }
24942      setForcedBlockAttrs(editor, block);
24943      emptyBlock(caretNode);
24944      return block;
24945    };
24946
24947    const getDetailsRoot = (editor, element) => editor.dom.getParent(element, isDetails);
24948    const isAtDetailsEdge = (root, element, isTextBlock) => {
24949      let node = element;
24950      while (node && node !== root && isNull(node.nextSibling)) {
24951        const parent = node.parentElement;
24952        if (!parent || !isTextBlock(parent)) {
24953          return isDetails(parent);
24954        }
24955        node = parent;
24956      }
24957      return false;
24958    };
24959    const isLastEmptyBlockInDetails = (editor, shiftKey, element) => !shiftKey && element.nodeName.toLowerCase() === getForcedRootBlock(editor) && editor.dom.isEmpty(element) && isAtDetailsEdge(editor.getBody(), element, el => has$2(editor.schema.getTextBlockElements(), el.nodeName.toLowerCase()));
24960    const insertNewLine = (editor, createNewBlock, parentBlock) => {
24961      var _a, _b, _c;
24962      const newBlock = createNewBlock(getForcedRootBlock(editor));
24963      const root = getDetailsRoot(editor, parentBlock);
24964      if (!root) {
24965        return;
24966      }
24967      editor.dom.insertAfter(newBlock, root);
24968      moveToCaretPosition(editor, newBlock);
24969      if (((_c = (_b = (_a = parentBlock.parentElement) === null || _a === void 0 ? void 0 : _a.childNodes) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) > 1) {
24970        editor.dom.remove(parentBlock);
24971      }
24972    };
24973
24974    const hasFirstChild = (elm, name) => {
24975      return elm.firstChild && elm.firstChild.nodeName === name;
24976    };
24977    const isFirstChild = elm => {
24978      var _a;
24979      return ((_a = elm.parentNode) === null || _a === void 0 ? void 0 : _a.firstChild) === elm;
24980    };
24981    const hasParent = (elm, parentName) => {
24982      const parentNode = elm === null || elm === void 0 ? void 0 : elm.parentNode;
24983      return isNonNullable(parentNode) && parentNode.nodeName === parentName;
24984    };
24985    const isListBlock = elm => {
24986      return isNonNullable(elm) && /^(OL|UL|LI)$/.test(elm.nodeName);
24987    };
24988    const isListItem = elm => {
24989      return isNonNullable(elm) && /^(LI|DT|DD)$/.test(elm.nodeName);
24990    };
24991    const isNestedList = elm => {
24992      return isListBlock(elm) && isListBlock(elm.parentNode);
24993    };
24994    const getContainerBlock = containerBlock => {
24995      const containerBlockParent = containerBlock.parentNode;
24996      return isListItem(containerBlockParent) ? containerBlockParent : containerBlock;
24997    };
24998    const isFirstOrLastLi = (containerBlock, parentBlock, first) => {
24999      let node = containerBlock[first ? 'firstChild' : 'lastChild'];
25000      while (node) {
25001        if (isElement$6(node)) {
25002          break;
25003        }
25004        node = node[first ? 'nextSibling' : 'previousSibling'];
25005      }
25006      return node === parentBlock;
25007    };
25008    const getStyles = elm => foldl(mapToArray(getAllRaw(SugarElement.fromDom(elm)), (style, styleName) => `${ styleName }: ${ style };`), (acc, s) => acc + s, '');
25009    const insert$4 = (editor, createNewBlock, containerBlock, parentBlock, newBlockName) => {
25010      const dom = editor.dom;
25011      const rng = editor.selection.getRng();
25012      const containerParent = containerBlock.parentNode;
25013      if (containerBlock === editor.getBody() || !containerParent) {
25014        return;
25015      }
25016      if (isNestedList(containerBlock)) {
25017        newBlockName = 'LI';
25018      }
25019      const parentBlockStyles = isListItem(parentBlock) ? getStyles(parentBlock) : undefined;
25020      let newBlock = isListItem(parentBlock) && parentBlockStyles ? createNewBlock(newBlockName, { style: getStyles(parentBlock) }) : createNewBlock(newBlockName);
25021      if (isFirstOrLastLi(containerBlock, parentBlock, true) && isFirstOrLastLi(containerBlock, parentBlock, false)) {
25022        if (hasParent(containerBlock, 'LI')) {
25023          const containerBlockParent = getContainerBlock(containerBlock);
25024          dom.insertAfter(newBlock, containerBlockParent);
25025          if (isFirstChild(containerBlock)) {
25026            dom.remove(containerBlockParent);
25027          } else {
25028            dom.remove(containerBlock);
25029          }
25030        } else {
25031          dom.replace(newBlock, containerBlock);
25032        }
25033      } else if (isFirstOrLastLi(containerBlock, parentBlock, true)) {
25034        if (hasParent(containerBlock, 'LI')) {
25035          dom.insertAfter(newBlock, getContainerBlock(containerBlock));
25036          newBlock.appendChild(dom.doc.createTextNode(' '));
25037          newBlock.appendChild(containerBlock);
25038        } else {
25039          containerParent.insertBefore(newBlock, containerBlock);
25040        }
25041        dom.remove(parentBlock);
25042      } else if (isFirstOrLastLi(containerBlock, parentBlock, false)) {
25043        dom.insertAfter(newBlock, getContainerBlock(containerBlock));
25044        dom.remove(parentBlock);
25045      } else {
25046        containerBlock = getContainerBlock(containerBlock);
25047        const tmpRng = rng.cloneRange();
25048        tmpRng.setStartAfter(parentBlock);
25049        tmpRng.setEndAfter(containerBlock);
25050        const fragment = tmpRng.extractContents();
25051        if (newBlockName === 'LI' && hasFirstChild(fragment, 'LI')) {
25052          const previousChildren = filter$5(map$3(newBlock.children, SugarElement.fromDom), not(isTag('br')));
25053          newBlock = fragment.firstChild;
25054          dom.insertAfter(fragment, containerBlock);
25055          each$e(previousChildren, child => prepend(SugarElement.fromDom(newBlock), child));
25056          if (parentBlockStyles) {
25057            newBlock.setAttribute('style', parentBlockStyles);
25058          }
25059        } else {
25060          dom.insertAfter(fragment, containerBlock);
25061          dom.insertAfter(newBlock, containerBlock);
25062        }
25063        dom.remove(parentBlock);
25064      }
25065      moveToCaretPosition(editor, newBlock);
25066    };
25067
25068    const trimZwsp = fragment => {
25069      each$e(descendants$1(SugarElement.fromDom(fragment), isText$c), text => {
25070        const rawNode = text.dom;
25071        rawNode.nodeValue = trim$2(rawNode.data);
25072      });
25073    };
25074    const isWithinNonEditableList = (editor, node) => {
25075      const parentList = editor.dom.getParent(node, 'ol,ul,dl');
25076      return parentList !== null && editor.dom.getContentEditableParent(parentList) === 'false';
25077    };
25078    const isEmptyAnchor = (dom, elm) => {
25079      return elm && elm.nodeName === 'A' && dom.isEmpty(elm);
25080    };
25081    const containerAnd
vendor: 7,404 bytes, lines 25081-25248
25081PreviousSiblingName = (container, nodeName) => {
25082      return container.nodeName === nodeName || container.previousSibling && container.previousSibling.nodeName === nodeName;
25083    };
25084    const containerAndNextSiblingName = (container, nodeName) => {
25085      return container.nodeName === nodeName || container.nextSibling && container.nextSibling.nodeName === nodeName;
25086    };
25087    const canSplitBlock = (dom, node) => {
25088      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';
25089    };
25090    const trimInlineElementsOnLeftSideOfBlock = (dom, nonEmptyElementsMap, block) => {
25091      var _a;
25092      const firstChilds = [];
25093      if (!block) {
25094        return;
25095      }
25096      let currentNode = block;
25097      while (currentNode = currentNode.firstChild) {
25098        if (dom.isBlock(currentNode)) {
25099          return;
25100        }
25101        if (isElement$6(currentNode) && !nonEmptyElementsMap[currentNode.nodeName.toLowerCase()]) {
25102          firstChilds.push(currentNode);
25103        }
25104      }
25105      let i = firstChilds.length;
25106      while (i--) {
25107        currentNode = firstChilds[i];
25108        if (!currentNode.hasChildNodes() || currentNode.firstChild === currentNode.lastChild && ((_a = currentNode.firstChild) === null || _a === void 0 ? void 0 : _a.nodeValue) === '') {
25109          dom.remove(currentNode);
25110        } else {
25111          if (isEmptyAnchor(dom, currentNode)) {
25112            dom.remove(currentNode);
25113          }
25114        }
25115      }
25116    };
25117    const normalizeZwspOffset = (start, container, offset) => {
25118      if (!isText$b(container)) {
25119        return offset;
25120      } else if (start) {
25121        return offset === 1 && container.data.charAt(offset - 1) === ZWSP$1 ? 0 : offset;
25122      } else {
25123        return offset === container.data.length - 1 && container.data.charAt(offset) === ZWSP$1 ? container.data.length : offset;
25124      }
25125    };
25126    const includeZwspInRange = rng => {
25127      const newRng = rng.cloneRange();
25128      newRng.setStart(rng.startContainer, normalizeZwspOffset(true, rng.startContainer, rng.startOffset));
25129      newRng.setEnd(rng.endContainer, normalizeZwspOffset(false, rng.endContainer, rng.endOffset));
25130      return newRng;
25131    };
25132    const trimLeadingLineBreaks = node => {
25133      let currentNode = node;
25134      do {
25135        if (isText$b(currentNode)) {
25136          currentNode.data = currentNode.data.replace(/^[\r\n]+/, '');
25137        }
25138        currentNode = currentNode.firstChild;
25139      } while (currentNode);
25140    };
25141    const wrapSelfAndSiblingsInDefaultBlock = (editor, newBlockName, rng, container, offset) => {
25142      var _a, _b;
25143      const dom = editor.dom;
25144      const editableRoot = (_a = getEditableRoot(dom, container)) !== null && _a !== void 0 ? _a : dom.getRoot();
25145      let parentBlock = dom.getParent(container, dom.isBlock);
25146      if (!parentBlock || !canSplitBlock(dom, parentBlock)) {
25147        parentBlock = parentBlock || editableRoot;
25148        if (!parentBlock.hasChildNodes()) {
25149          const newBlock = dom.create(newBlockName);
25150          setForcedBlockAttrs(editor, newBlock);
25151          parentBlock.appendChild(newBlock);
25152          rng.setStart(newBlock, 0);
25153          rng.setEnd(newBlock, 0);
25154          return newBlock;
25155        }
25156        let node = container;
25157        while (node && node.parentNode !== parentBlock) {
25158          node = node.parentNode;
25159        }
25160        let startNode;
25161        while (node && !dom.isBlock(node)) {
25162          startNode = node;
25163          node = node.previousSibling;
25164        }
25165        const startNodeName = (_b = startNode === null || startNode === void 0 ? void 0 : startNode.parentElement) === null || _b === void 0 ? void 0 : _b.nodeName;
25166        if (startNode && startNodeName && editor.schema.isValidChild(startNodeName, newBlockName.toLowerCase())) {
25167          const startNodeParent = startNode.parentNode;
25168          const newBlock = dom.create(newBlockName);
25169          setForcedBlockAttrs(editor, newBlock);
25170          startNodeParent.insertBefore(newBlock, startNode);
25171          node = startNode;
25172          while (node && !dom.isBlock(node)) {
25173            const next = node.nextSibling;
25174            newBlock.appendChild(node);
25175            node = next;
25176          }
25177          rng.setStart(container, offset);
25178          rng.setEnd(container, offset);
25179        }
25180      }
25181      return container;
25182    };
25183    const addBrToBlockIfNeeded = (dom, block) => {
25184      block.normalize();
25185      const lastChild = block.lastChild;
25186      if (!lastChild || isElement$6(lastChild) && /^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true))) {
25187        dom.add(block, 'br');
25188      }
25189    };
25190    const shouldEndContainer = (editor, container) => {
25191      const optionValue = shouldEndContainerOnEmptyBlock(editor);
25192      if (isNullable(container)) {
25193        return false;
25194      } else if (isString(optionValue)) {
25195        return contains$2(Tools.explode(optionValue), container.nodeName.toLowerCase());
25196      } else {
25197        return optionValue;
25198      }
25199    };
25200    const insert$3 = (editor, evt) => {
25201      let container;
25202      let offset;
25203      let parentBlockName;
25204      let containerBlock;
25205      let isAfterLastNodeInContainer = false;
25206      const dom = editor.dom;
25207      const schema = editor.schema, nonEmptyElementsMap = schema.getNonEmptyElements();
25208      const rng = editor.selection.getRng();
25209      const newBlockName = getForcedRootBlock(editor);
25210      const start = SugarElement.fromDom(rng.startContainer);
25211      const child = child$1(start, rng.startOffset);
25212      const isCef = child.exists(element => isHTMLElement$1(element) && !isEditable$2(element));
25213      const collapsedAndCef = rng.collapsed && isCef;
25214      const createNewBlock$1 = (name, styles) => {
25215        return createNewBlock(editor, container, parentBlock, editableRoot, shouldKeepStyles(editor), name, styles);
25216      };
25217      const isCaretAtStartOrEndOfBlock = start => {
25218        const normalizedOffset = normalizeZwspOffset(start, container, offset);
25219        if (isText$b(container) && (start ? normalizedOffset > 0 : normalizedOffset < container.data.length)) {
25220          return false;
25221        }
25222        if ((container.parentNode === parentBlock || container === parentBlock) && isAfterLastNodeInContainer && !start) {
25223          return true;
25224        }
25225        if (start && isElement$6(container) && container === parentBlock.firstChild) {
25226          return true;
25227        }
25228        if (containerAndPreviousSiblingName(container, 'TABLE') || containerAndPreviousSiblingName(container, 'HR')) {
25229          if (containerAndNextSiblingName(container, 'BR')) {
25230            return !start;
25231          }
25232          return isAfterLastNodeInContainer && !start || !isAfterLastNodeInContainer && start;
25233        }
25234        const walker = new DomTreeWalker(container, parentBlock);
25235        if (isText$b(container)) {
25236          if (start && normalizedOffset === 0) {
25237            walker.prev();
25238          } else if (!start && normalizedOffset === container.data.length) {
25239            walker.next();
25240          }
25241        }
25242        let node;
25243        while (node = walker.current()) {
25244          if (isElement$6(node)) {
25245            if (!node.getAttribute('data-mce-bogus')) {
25246              const name = node.nodeName.toLowerCase();
25247              if (nonEmptyElementsMap[name] && name !== 'br') {
25248                return false;
vendor: 4,723 bytes, lines 25249-25350
25249              }
25250            }
25251          } else if (isText$b(node) && !isWhitespaceText(node.data)) {
25252            return false;
25253          }
25254          if (start) {
25255            walker.prev();
25256          } else {
25257            walker.next();
25258          }
25259        }
25260        return true;
25261      };
25262      const insertNewBlockAfter = () => {
25263        let block;
25264        if (/^(H[1-6]|PRE|FIGURE)$/.test(parentBlockName) && containerBlockName !== 'HGROUP') {
25265          block = createNewBlock$1(newBlockName);
25266        } else {
25267          block = createNewBlock$1();
25268        }
25269        if (shouldEndContainer(editor, containerBlock) && canSplitBlock(dom, containerBlock) && dom.isEmpty(parentBlock, undefined, { includeZwsp: true })) {
25270          block = dom.split(containerBlock, parentBlock);
25271        } else {
25272          dom.insertAfter(block, parentBlock);
25273        }
25274        moveToCaretPosition(editor, block);
25275        return block;
25276      };
25277      normalize$2(dom, rng).each(normRng => {
25278        rng.setStart(normRng.startContainer, normRng.startOffset);
25279        rng.setEnd(normRng.endContainer, normRng.endOffset);
25280      });
25281      container = rng.startContainer;
25282      offset = rng.startOffset;
25283      const shiftKey = !!(evt && evt.shiftKey);
25284      const ctrlKey = !!(evt && evt.ctrlKey);
25285      if (isElement$6(container) && container.hasChildNodes() && !collapsedAndCef) {
25286        isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
25287        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
25288        if (isAfterLastNodeInContainer && isText$b(container)) {
25289          offset = container.data.length;
25290        } else {
25291          offset = 0;
25292        }
25293      }
25294      const editableRoot = getEditableRoot(dom, container);
25295      if (!editableRoot || isWithinNonEditableList(editor, container)) {
25296        return;
25297      }
25298      if (!shiftKey) {
25299        container = wrapSelfAndSiblingsInDefaultBlock(editor, newBlockName, rng, container, offset);
25300      }
25301      let parentBlock = dom.getParent(container, dom.isBlock) || dom.getRoot();
25302      containerBlock = isNonNullable(parentBlock === null || parentBlock === void 0 ? void 0 : parentBlock.parentNode) ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
25303      parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : '';
25304      const containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
25305      if (containerBlockName === 'LI' && !ctrlKey) {
25306        const liBlock = containerBlock;
25307        parentBlock = liBlock;
25308        containerBlock = liBlock.parentNode;
25309        parentBlockName = containerBlockName;
25310      }
25311      if (isElement$6(containerBlock) && isLastEmptyBlockInDetails(editor, shiftKey, parentBlock)) {
25312        return insertNewLine(editor, createNewBlock$1, parentBlock);
25313      }
25314      if (/^(LI|DT|DD)$/.test(parentBlockName) && isElement$6(containerBlock)) {
25315        if (dom.isEmpty(parentBlock)) {
25316          insert$4(editor, createNewBlock$1, containerBlock, parentBlock, newBlockName);
25317          return;
25318        }
25319      }
25320      if (!collapsedAndCef && (parentBlock === editor.getBody() || !canSplitBlock(dom, parentBlock))) {
25321        return;
25322      }
25323      const parentBlockParent = parentBlock.parentNode;
25324      let newBlock;
25325      if (collapsedAndCef) {
25326        newBlock = createNewBlock$1(newBlockName);
25327        child.fold(() => {
25328          append$1(start, SugarElement.fromDom(newBlock));
25329        }, child => {
25330          before$3(child, SugarElement.fromDom(newBlock));
25331        });
25332        editor.selection.setCursorLocation(newBlock, 0);
25333      } else if (isCaretContainerBlock$1(parentBlock)) {
25334        newBlock = showCaretContainerBlock(parentBlock);
25335        if (dom.isEmpty(parentBlock)) {
25336          emptyBlock(parentBlock);
25337        }
25338        setForcedBlockAttrs(editor, newBlock);
25339        moveToCaretPosition(editor, newBlock);
25340      } else if (isCaretAtStartOrEndOfBlock(false)) {
25341        newBlock = insertNewBlockAfter();
25342      } else if (isCaretAtStartOrEndOfBlock(true) && parentBlockParent) {
25343        const caretPos = CaretPosition.fromRangeStart(rng);
25344        const afterTable = isAfterTable(caretPos);
25345        const parentBlockSugar = SugarElement.fromDom(parentBlock);
25346        const afterBr = isAfterBr(parentBlockSugar, caretPos, editor.schema);
25347        const prevBrOpt = afterBr ? findPreviousBr(parentBlockSugar, caretPos, editor.schema).bind(pos => Optional.from(pos.getNode())) : Optional.none();
25348        newBlock = parentBlockParent.insertBefore(createNewBlock$1(), parentBlock);
25349        const root = containerAndPreviousSiblingName(parentBlock, 'HR') || afterTable ? newBlock : prevBrOpt.getOr(parentBlock);
25350        moveToCaretPosition(editor, root
vendor: 9,600 bytes, lines 25350-25609
25350);
25351      } else {
25352        const tmpRng = includeZwspInRange(rng).cloneRange();
25353        tmpRng.setEndAfter(parentBlock);
25354        const fragment = tmpRng.extractContents();
25355        trimZwsp(fragment);
25356        trimLeadingLineBreaks(fragment);
25357        newBlock = fragment.firstChild;
25358        dom.insertAfter(fragment, parentBlock);
25359        trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock);
25360        addBrToBlockIfNeeded(dom, parentBlock);
25361        if (dom.isEmpty(parentBlock)) {
25362          emptyBlock(parentBlock);
25363        }
25364        newBlock.normalize();
25365        if (dom.isEmpty(newBlock)) {
25366          dom.remove(newBlock);
25367          insertNewBlockAfter();
25368        } else {
25369          setForcedBlockAttrs(editor, newBlock);
25370          moveToCaretPosition(editor, newBlock);
25371        }
25372      }
25373      dom.setAttrib(newBlock, 'id', '');
25374      editor.dispatch('NewBlock', { newBlock });
25375    };
25376    const fakeEventName$1 = 'insertParagraph';
25377    const blockbreak = {
25378      insert: insert$3,
25379      fakeEventName: fakeEventName$1
25380    };
25381
25382    const hasRightSideContent = (schema, container, parentBlock) => {
25383      const walker = new DomTreeWalker(container, parentBlock);
25384      let node;
25385      const nonEmptyElementsMap = schema.getNonEmptyElements();
25386      while (node = walker.next()) {
25387        if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || isText$b(node) && node.length > 0) {
25388          return true;
25389        }
25390      }
25391      return false;
25392    };
25393    const moveSelectionToBr = (editor, brElm, extraBr) => {
25394      const rng = editor.dom.createRng();
25395      if (!extraBr) {
25396        rng.setStartAfter(brElm);
25397        rng.setEndAfter(brElm);
25398      } else {
25399        rng.setStartBefore(brElm);
25400        rng.setEndBefore(brElm);
25401      }
25402      editor.selection.setRng(rng);
25403      scrollRangeIntoView(editor, rng);
25404    };
25405    const insertBrAtCaret = (editor, evt) => {
25406      const selection = editor.selection;
25407      const dom = editor.dom;
25408      const rng = selection.getRng();
25409      let brElm;
25410      let extraBr = false;
25411      normalize$2(dom, rng).each(normRng => {
25412        rng.setStart(normRng.startContainer, normRng.startOffset);
25413        rng.setEnd(normRng.endContainer, normRng.endOffset);
25414      });
25415      let offset = rng.startOffset;
25416      let container = rng.startContainer;
25417      if (isElement$6(container) && container.hasChildNodes()) {
25418        const isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
25419        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
25420        if (isAfterLastNodeInContainer && isText$b(container)) {
25421          offset = container.data.length;
25422        } else {
25423          offset = 0;
25424        }
25425      }
25426      let parentBlock = dom.getParent(container, dom.isBlock);
25427      const containerBlock = parentBlock && parentBlock.parentNode ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
25428      const containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
25429      const isControlKey = !!(evt && evt.ctrlKey);
25430      if (containerBlockName === 'LI' && !isControlKey) {
25431        parentBlock = containerBlock;
25432      }
25433      if (isText$b(container) && offset >= container.data.length) {
25434        if (!hasRightSideContent(editor.schema, container, parentBlock || dom.getRoot())) {
25435          brElm = dom.create('br');
25436          rng.insertNode(brElm);
25437          rng.setStartAfter(brElm);
25438          rng.setEndAfter(brElm);
25439          extraBr = true;
25440        }
25441      }
25442      brElm = dom.create('br');
25443      rangeInsertNode(dom, rng, brElm);
25444      moveSelectionToBr(editor, brElm, extraBr);
25445      editor.undoManager.add();
25446    };
25447    const insertBrBefore = (editor, inline) => {
25448      const br = SugarElement.fromTag('br');
25449      before$3(SugarElement.fromDom(inline), br);
25450      editor.undoManager.add();
25451    };
25452    const insertBrAfter = (editor, inline) => {
25453      if (!hasBrAfter(editor.getBody(), inline)) {
25454        after$4(SugarElement.fromDom(inline), SugarElement.fromTag('br'));
25455      }
25456      const br = SugarElement.fromTag('br');
25457      after$4(SugarElement.fromDom(inline), br);
25458      moveSelectionToBr(editor, br.dom, false);
25459      editor.undoManager.add();
25460    };
25461    const isBeforeBr = pos => {
25462      return isBr$6(pos.getNode());
25463    };
25464    const hasBrAfter = (rootNode, startNode) => {
25465      if (isBeforeBr(CaretPosition.after(startNode))) {
25466        return true;
25467      } else {
25468        return nextPosition(rootNode, CaretPosition.after(startNode)).map(pos => {
25469          return isBr$6(pos.getNode());
25470        }).getOr(false);
25471      }
25472    };
25473    const isAnchorLink = elm => {
25474      return elm && elm.nodeName === 'A' && 'href' in elm;
25475    };
25476    const isInsideAnchor = location => {
25477      return location.fold(never, isAnchorLink, isAnchorLink, never);
25478    };
25479    const readInlineAnchorLocation = editor => {
25480      const isInlineTarget$1 = curry(isInlineTarget, editor);
25481      const position = CaretPosition.fromRangeStart(editor.selection.getRng());
25482      return readLocation(isInlineTarget$1, editor.getBody(), position).filter(isInsideAnchor);
25483    };
25484    const insertBrOutsideAnchor = (editor, location) => {
25485      location.fold(noop, curry(insertBrBefore, editor), curry(insertBrAfter, editor), noop);
25486    };
25487    const insert$2 = (editor, evt) => {
25488      const anchorLocation = readInlineAnchorLocation(editor);
25489      if (anchorLocation.isSome()) {
25490        anchorLocation.each(curry(insertBrOutsideAnchor, editor));
25491      } else {
25492        insertBrAtCaret(editor, evt);
25493      }
25494    };
25495    const fakeEventName = 'insertLineBreak';
25496    const linebreak = {
25497      insert: insert$2,
25498      fakeEventName
25499    };
25500
25501    const matchesSelector = (editor, selector) => {
25502      return getParentBlock$1(editor).filter(parentBlock => {
25503        return selector.length > 0 && is$1(SugarElement.fromDom(parentBlock), selector);
25504      }).isSome();
25505    };
25506    const shouldInsertBr = editor => {
25507      return matchesSelector(editor, getBrNewLineSelector(editor));
25508    };
25509    const shouldBlockNewLine$1 = editor => {
25510      return matchesSelector(editor, getNoNewLineSelector(editor));
25511    };
25512
25513    const newLineAction = Adt.generate([
25514      { br: [] },
25515      { block: [] },
25516      { none: [] }
25517    ]);
25518    const shouldBlockNewLine = (editor, _shiftKey) => {
25519      return shouldBlockNewLine$1(editor);
25520    };
25521    const inListBlock = requiredState => {
25522      return (editor, _shiftKey) => {
25523        return isListItemParentBlock(editor) === requiredState;
25524      };
25525    };
25526    const inBlock = (blockName, requiredState) => (editor, _shiftKey) => {
25527      const state = getParentBlockName(editor) === blockName.toUpperCase();
25528      return state === requiredState;
25529    };
25530    const inCefBlock = editor => {
25531      const editableRoot = getEditableRoot(editor.dom, editor.selection.getStart());
25532      return isNullable(editableRoot);
25533    };
25534    const inPreBlock = requiredState => inBlock('pre', requiredState);
25535    const inSummaryBlock = () => inBlock('summary', true);
25536    const shouldPutBrInPre = requiredState => {
25537      return (editor, _shiftKey) => {
25538        return shouldPutBrInPre$1(editor) === requiredState;
25539      };
25540    };
25541    const inBrContext = (editor, _shiftKey) => {
25542      return shouldInsertBr(editor);
25543    };
25544    const hasShiftKey = (_editor, shiftKey) => {
25545      return shiftKey;
25546    };
25547    const canInsertIntoEditableRoot = editor => {
25548      const forcedRootBlock = getForcedRootBlock(editor);
25549      const rootEditable = getEditableRoot(editor.dom, editor.selection.getStart());
25550      return isNonNullable(rootEditable) && editor.schema.isValidChild(rootEditable.nodeName, forcedRootBlock);
25551    };
25552    const isInRootWithEmptyOrCEF = editor => {
25553      const rng = editor.selection.getRng();
25554      const start = SugarElement.fromDom(rng.startContainer);
25555      const child = child$1(start, rng.startOffset);
25556      const isCefOpt = child.map(element => isHTMLElement$1(element) && !isEditable$2(element));
25557      return rng.collapsed && isCefOpt.getOr(true);
25558    };
25559    const match = (predicates, action) => {
25560      return (editor, shiftKey) => {
25561        const isMatch = foldl(predicates, (res, p) => {
25562          return res && p(editor, shiftKey);
25563        }, true);
25564        return isMatch ? Optional.some(action) : Optional.none();
25565      };
25566    };
25567    const getAction = (editor, evt) => {
25568      return evaluateUntil([
25569        match([shouldBlockNewLine], newLineAction.none()),
25570        match([
25571          inPreBlock(true),
25572          inCefBlock
25573        ], newLineAction.none()),
25574        match([inSummaryBlock()], newLineAction.br()),
25575        match([
25576          inPreBlock(true),
25577          shouldPutBrInPre(false),
25578          hasShiftKey
25579        ], newLineAction.br()),
25580        match([
25581          inPreBlock(true),
25582          shouldPutBrInPre(false)
25583        ], newLineAction.block()),
25584        match([
25585          inPreBlock(true),
25586          shouldPutBrInPre(true),
25587          hasShiftKey
25588        ], newLineAction.block()),
25589        match([
25590          inPreBlock(true),
25591          shouldPutBrInPre(true)
25592        ], newLineAction.br()),
25593        match([
25594          inListBlock(true),
25595          hasShiftKey
25596        ], newLineAction.br()),
25597        match([inListBlock(true)], newLineAction.block()),
25598        match([inBrContext], newLineAction.br()),
25599        match([hasShiftKey], newLineAction.br()),
25600        match([canInsertIntoEditableRoot], newLineAction.block()),
25601        match([isInRootWithEmptyOrCEF], newLineAction.block())
25602      ], [
25603        editor,
25604        !!(evt && evt.shiftKey)
25605      ]).getOr(newLineAction.none());
25606    };
25607
25608    const insertBreak = (breakType, editor, evt) => {
25609      if (
vendor: 6,635 bytes, lines 25609-25816
25609editor.mode.isReadOnly()) {
25610        return;
25611      }
25612      if (!editor.selection.isCollapsed()) {
25613        execEditorDeleteCommand(editor);
25614      }
25615      if (isNonNullable(evt)) {
25616        const event = fireBeforeInputEvent(editor, breakType.fakeEventName);
25617        if (event.isDefaultPrevented()) {
25618          return;
25619        }
25620      }
25621      breakType.insert(editor, evt);
25622      if (isNonNullable(evt)) {
25623        fireInputEvent(editor, breakType.fakeEventName);
25624      }
25625    };
25626    const insert$1 = (editor, evt) => {
25627      if (editor.mode.isReadOnly()) {
25628        return;
25629      }
25630      const br = () => insertBreak(linebreak, editor, evt);
25631      const block = () => insertBreak(blockbreak, editor, evt);
25632      const logicalAction = getAction(editor, evt);
25633      switch (getNewlineBehavior(editor)) {
25634      case 'linebreak':
25635        logicalAction.fold(br, br, noop);
25636        break;
25637      case 'block':
25638        logicalAction.fold(block, block, noop);
25639        break;
25640      case 'invert':
25641        logicalAction.fold(block, br, noop);
25642        break;
25643      default:
25644        logicalAction.fold(br, block, noop);
25645        break;
25646      }
25647    };
25648
25649    const platform$1 = detect$1();
25650    const isIOSSafari = platform$1.os.isiOS() && platform$1.browser.isSafari();
25651    const handleEnterKeyEvent = (editor, event) => {
25652      if (event.isDefaultPrevented()) {
25653        return;
25654      }
25655      event.preventDefault();
25656      endTypingLevelIgnoreLocks(editor.undoManager);
25657      editor.undoManager.transact(() => {
25658        insert$1(editor, event);
25659      });
25660    };
25661    const isCaretAfterKoreanCharacter = rng => {
25662      if (!rng.collapsed) {
25663        return false;
25664      }
25665      const startContainer = rng.startContainer;
25666      if (isText$b(startContainer)) {
25667        const koreanCharRegex = /^[\uAC00-\uD7AF\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uD7B0-\uD7FF]$/;
25668        const char = startContainer.data.charAt(rng.startOffset - 1);
25669        return koreanCharRegex.test(char);
25670      } else {
25671        return false;
25672      }
25673    };
25674    const setup$i = editor => {
25675      let iOSSafariKeydownBookmark = Optional.none();
25676      const iOSSafariKeydownOverride = editor => {
25677        iOSSafariKeydownBookmark = Optional.some(editor.selection.getBookmark());
25678        editor.undoManager.add();
25679      };
25680      const iOSSafariKeyupOverride = (editor, event) => {
25681        editor.undoManager.undo();
25682        iOSSafariKeydownBookmark.fold(noop, b => editor.selection.moveToBookmark(b));
25683        handleEnterKeyEvent(editor, event);
25684        iOSSafariKeydownBookmark = Optional.none();
25685      };
25686      editor.on('keydown', event => {
25687        if (event.keyCode === VK.ENTER) {
25688          if (isIOSSafari && isCaretAfterKoreanCharacter(editor.selection.getRng())) {
25689            iOSSafariKeydownOverride(editor);
25690          } else {
25691            handleEnterKeyEvent(editor, event);
25692          }
25693        }
25694      });
25695      editor.on('keyup', event => {
25696        if (event.keyCode === VK.ENTER) {
25697          iOSSafariKeydownBookmark.each(() => iOSSafariKeyupOverride(editor, event));
25698        }
25699      });
25700    };
25701
25702    const executeKeydownOverride$2 = (editor, caret, evt) => {
25703      const isMac = Env.os.isMacOS() || Env.os.isiOS();
25704      execute([
25705        {
25706          keyCode: VK.END,
25707          action: action(moveToLineEndPoint$1, editor, true)
25708        },
25709        {
25710          keyCode: VK.HOME,
25711          action: action(moveToLineEndPoint$1, editor, false)
25712        },
25713        ...!isMac ? [
25714          {
25715            keyCode: VK.HOME,
25716            action: action(selectToEndPoint, editor, false),
25717            ctrlKey: true,
25718            shiftKey: true
25719          },
25720          {
25721            keyCode: VK.END,
25722            action: action(selectToEndPoint, editor, true),
25723            ctrlKey: true,
25724            shiftKey: true
25725          }
25726        ] : [],
25727        {
25728          keyCode: VK.END,
25729          action: action(moveToLineEndPoint, editor, true)
25730        },
25731        {
25732          keyCode: VK.HOME,
25733          action: action(moveToLineEndPoint, editor, false)
25734        },
25735        {
25736          keyCode: VK.END,
25737          action: action(moveToLineEndPoint$2, editor, true, caret)
25738        },
25739        {
25740          keyCode: VK.HOME,
25741          action: action(moveToLineEndPoint$2, editor, false, caret)
25742        }
25743      ], evt).each(_ => {
25744        evt.preventDefault();
25745      });
25746    };
25747    const setup$h = (editor, caret) => {
25748      editor.on('keydown', evt => {
25749        if (!evt.isDefaultPrevented()) {
25750          executeKeydownOverride$2(editor, caret, evt);
25751        }
25752      });
25753    };
25754
25755    const setup$g = editor => {
25756      editor.on('input', e => {
25757        if (!e.isComposing) {
25758          normalizeNbspsInEditor(editor);
25759        }
25760      });
25761    };
25762
25763    const platform = detect$1();
25764    const executeKeyupAction = (editor, caret, evt) => {
25765      execute([
25766        {
25767          keyCode: VK.PAGE_UP,
25768          action: action(moveToLineEndPoint$2, editor, false, caret)
25769        },
25770        {
25771          keyCode: VK.PAGE_DOWN,
25772          action: action(moveToLineEndPoint$2, editor, true, caret)
25773        }
25774      ], evt);
25775    };
25776    const stopImmediatePropagation = e => e.stopImmediatePropagation();
25777    const isPageUpDown = evt => evt.keyCode === VK.PAGE_UP || evt.keyCode === VK.PAGE_DOWN;
25778    const setNodeChangeBlocker = (blocked, editor, block) => {
25779      if (block && !blocked.get()) {
25780        editor.on('NodeChange', stopImmediatePropagation, true);
25781      } else if (!block && blocked.get()) {
25782        editor.off('NodeChange', stopImmediatePropagation);
25783      }
25784      blocked.set(block);
25785    };
25786    const setup$f = (editor, caret) => {
25787      if (platform.os.isMacOS()) {
25788        return;
25789      }
25790      const blocked = Cell(false);
25791      editor.on('keydown', evt => {
25792        if (isPageUpDown(evt)) {
25793          setNodeChangeBlocker(blocked, editor, true);
25794        }
25795      });
25796      editor.on('keyup', evt => {
25797        if (!evt.isDefaultPrevented()) {
25798          executeKeyupAction(editor, caret, evt);
25799        }
25800        if (isPageUpDown(evt) && blocked.get()) {
25801          setNodeChangeBlocker(blocked, editor, false);
25802          editor.nodeChanged();
25803        }
25804      });
25805    };
25806
25807    const isValidContainer = (root, container) => root === container || root.contains(container);
25808    const isInEditableRange = (editor, range) => {
25809      if (!isValidContainer(editor.getBody(), range.startContainer) || !isValidContainer(editor.getBody(), range.endContainer)) {
25810        return true;
25811      }
25812      return isEditableRange(editor.dom, range);
25813    };
25814    const setup$e = editor => {
25815      editor.on('beforeinput', e => {
25816        if (!editor.selection.isEditable() || exists(e.getTargetRanges(), rng => !isInEditableRange(editor
vendor: 6,792 bytes, lines 25816-25999
25816, rng))) {
25817          e.preventDefault();
25818        }
25819      });
25820    };
25821
25822    const insertTextAtPosition = (text, pos) => {
25823      const container = pos.container();
25824      const offset = pos.offset();
25825      if (isText$b(container)) {
25826        container.insertData(offset, text);
25827        return Optional.some(CaretPosition(container, offset + text.length));
25828      } else {
25829        return getElementFromPosition(pos).map(elm => {
25830          const textNode = SugarElement.fromText(text);
25831          if (pos.isAtEnd()) {
25832            after$4(elm, textNode);
25833          } else {
25834            before$3(elm, textNode);
25835          }
25836          return CaretPosition(textNode.dom, text.length);
25837        });
25838      }
25839    };
25840    const insertNbspAtPosition = curry(insertTextAtPosition, nbsp);
25841    const insertSpaceAtPosition = curry(insertTextAtPosition, ' ');
25842
25843    const insertSpaceOrNbspAtPosition = (root, pos, schema) => needsToHaveNbsp(root, pos, schema) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
25844    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)));
25845    const insertInlineBoundarySpaceOrNbsp = (root, pos, schema) => checkPos => needsToHaveNbsp(root, checkPos, schema) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
25846    const setSelection = editor => pos => {
25847      editor.selection.setRng(pos.toRange());
25848      editor.nodeChanged();
25849    };
25850    const isInsideSummary = (domUtils, node) => domUtils.isEditable(domUtils.getParent(node, 'summary'));
25851    const insertSpaceOrNbspAtSelection = editor => {
25852      const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
25853      const root = SugarElement.fromDom(editor.getBody());
25854      if (editor.selection.isCollapsed()) {
25855        const isInlineTarget$1 = curry(isInlineTarget, editor);
25856        const caretPosition = CaretPosition.fromRangeStart(editor.selection.getRng());
25857        return readLocation(isInlineTarget$1, editor.getBody(), caretPosition).bind(locationToCaretPosition(root)).map(checkPos => () => insertInlineBoundarySpaceOrNbsp(root, pos, editor.schema)(checkPos).each(setSelection(editor)));
25858      } else {
25859        return Optional.none();
25860      }
25861    };
25862    const insertSpaceInSummaryAtSelectionOnFirefox = editor => {
25863      const insertSpaceThunk = () => {
25864        const root = SugarElement.fromDom(editor.getBody());
25865        if (!editor.selection.isCollapsed()) {
25866          editor.getDoc().execCommand('Delete');
25867        }
25868        const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
25869        insertSpaceOrNbspAtPosition(root, pos, editor.schema).each(setSelection(editor));
25870      };
25871      return someIf(Env.browser.isFirefox() && editor.selection.isEditable() && isInsideSummary(editor.dom, editor.selection.getRng().startContainer), insertSpaceThunk);
25872    };
25873
25874    const executeKeydownOverride$1 = (editor, evt) => {
25875      executeWithDelayedAction([
25876        {
25877          keyCode: VK.SPACEBAR,
25878          action: action(insertSpaceOrNbspAtSelection, editor)
25879        },
25880        {
25881          keyCode: VK.SPACEBAR,
25882          action: action(insertSpaceInSummaryAtSelectionOnFirefox, editor)
25883        }
25884      ], evt).each(applyAction => {
25885        evt.preventDefault();
25886        const event = fireBeforeInputEvent(editor, 'insertText', { data: ' ' });
25887        if (!event.isDefaultPrevented()) {
25888          applyAction();
25889          fireInputEvent(editor, 'insertText', { data: ' ' });
25890        }
25891      });
25892    };
25893    const setup$d = editor => {
25894      editor.on('keydown', evt => {
25895        if (!evt.isDefaultPrevented()) {
25896          executeKeydownOverride$1(editor, evt);
25897        }
25898      });
25899    };
25900
25901    const tableTabNavigation = editor => {
25902      if (hasTableTabNavigation(editor)) {
25903        return [
25904          {
25905            keyCode: VK.TAB,
25906            action: action(handleTab, editor, true)
25907          },
25908          {
25909            keyCode: VK.TAB,
25910            shiftKey: true,
25911            action: action(handleTab, editor, false)
25912          }
25913        ];
25914      } else {
25915        return [];
25916      }
25917    };
25918    const executeKeydownOverride = (editor, evt) => {
25919      execute([...tableTabNavigation(editor)], evt).each(_ => {
25920        evt.preventDefault();
25921      });
25922    };
25923    const setup$c = editor => {
25924      editor.on('keydown', evt => {
25925        if (!evt.isDefaultPrevented()) {
25926          executeKeydownOverride(editor, evt);
25927        }
25928      });
25929    };
25930
25931    const setup$b = editor => {
25932      editor.addShortcut('Meta+P', '', 'mcePrint');
25933      setup$k(editor);
25934      if (isRtc(editor)) {
25935        return Cell(null);
25936      } else {
25937        const caret = setupSelectedState(editor);
25938        setup$e(editor);
25939        setup$m(editor);
25940        setup$l(editor, caret);
25941        setup$j(editor, caret);
25942        setup$i(editor);
25943        setup$d(editor);
25944        setup$g(editor);
25945        setup$c(editor);
25946        setup$h(editor, caret);
25947        setup$f(editor, caret);
25948        return caret;
25949      }
25950    };
25951
25952    class NodeChange {
25953      constructor(editor) {
25954        this.lastPath = [];
25955        this.editor = editor;
25956        let lastRng;
25957        const self = this;
25958        if (!('onselectionchange' in editor.getDoc())) {
25959          editor.on('NodeChange click mouseup keyup focus', e => {
25960            const nativeRng = editor.selection.getRng();
25961            const fakeRng = {
25962              startContainer: nativeRng.startContainer,
25963              startOffset: nativeRng.startOffset,
25964              endContainer: nativeRng.endContainer,
25965              endOffset: nativeRng.endOffset
25966            };
25967            if (e.type === 'nodechange' || !isEq$4(fakeRng, lastRng)) {
25968              editor.dispatch('SelectionChange');
25969            }
25970            lastRng = fakeRng;
25971          });
25972        }
25973        editor.on('contextmenu', () => {
25974          store(editor);
25975          editor.dispatch('SelectionChange');
25976        });
25977        editor.on('SelectionChange', () => {
25978          const startElm = editor.selection.getStart(true);
25979          if (!startElm) {
25980            return;
25981          }
25982          if (hasAnyRanges(editor) && !self.isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
25983            editor.nodeChanged({ selectionChange: true });
25984          }
25985        });
25986        editor.on('mouseup', e => {
25987          if (!e.isDefaultPrevented() && hasAnyRanges(editor)) {
25988            if (editor.selection.getNode().nodeName === 'IMG') {
25989              Delay.setEditorTimeout(editor, () => {
25990                editor.nodeChanged();
25991              });
25992            } else {
25993              editor.nodeChanged();
25994            }
25995          }
25996        });
25997      }
25998      nodeChanged(args = {}) {
25999        const 
vendor: 5,103 bytes, lines 25999-26174
25999editor = this.editor;
26000        const selection = editor.selection;
26001        let node;
26002        if (editor.initialized && selection && !shouldDisableNodeChange(editor) && !isDisabled$1(editor)) {
26003          const root = editor.getBody();
26004          node = selection.getStart(true) || root;
26005          if (node.ownerDocument !== editor.getDoc() || !editor.dom.isChildOf(node, root)) {
26006            node = root;
26007          }
26008          const parents = [];
26009          editor.dom.getParent(node, node => {
26010            if (node === root) {
26011              return true;
26012            } else {
26013              parents.push(node);
26014              return false;
26015            }
26016          });
26017          editor.dispatch('NodeChange', {
26018            ...args,
26019            element: node,
26020            parents
26021          });
26022        }
26023      }
26024      isSameElementPath(startElm) {
26025        let i;
26026        const editor = this.editor;
26027        const currentPath = reverse(editor.dom.getParents(startElm, always, editor.getBody()));
26028        if (currentPath.length === this.lastPath.length) {
26029          for (i = currentPath.length; i >= 0; i--) {
26030            if (currentPath[i] !== this.lastPath[i]) {
26031              break;
26032            }
26033          }
26034          if (i === -1) {
26035            this.lastPath = currentPath;
26036            return true;
26037          }
26038        }
26039        this.lastPath = currentPath;
26040        return false;
26041      }
26042    }
26043
26044    const imageId = generate$1('image');
26045    const getDragImage = transfer => {
26046      const dt = transfer;
26047      return Optional.from(dt[imageId]);
26048    };
26049    const setDragImage = (transfer, imageData) => {
26050      const dt = transfer;
26051      dt[imageId] = imageData;
26052    };
26053
26054    const eventId = generate$1('event');
26055    const getEvent = transfer => {
26056      const dt = transfer;
26057      return Optional.from(dt[eventId]);
26058    };
26059    const mkSetEventFn = type => transfer => {
26060      const dt = transfer;
26061      dt[eventId] = type;
26062    };
26063    const setEvent = (transfer, type) => mkSetEventFn(type)(transfer);
26064    const setDragstartEvent = mkSetEventFn(0);
26065    const setDropEvent = mkSetEventFn(2);
26066    const setDragendEvent = mkSetEventFn(1);
26067    const checkEvent = expectedType => transfer => {
26068      const dt = transfer;
26069      return Optional.from(dt[eventId]).exists(type => type === expectedType);
26070    };
26071    const isInDragStartEvent = checkEvent(0);
26072
26073    const createEmptyFileList = () => Object.freeze({
26074      length: 0,
26075      item: _ => null
26076    });
26077
26078    const modeId = generate$1('mode');
26079    const getMode = transfer => {
26080      const dt = transfer;
26081      return Optional.from(dt[modeId]);
26082    };
26083    const mkSetModeFn = mode => transfer => {
26084      const dt = transfer;
26085      dt[modeId] = mode;
26086    };
26087    const setMode$1 = (transfer, mode) => mkSetModeFn(mode)(transfer);
26088    const setReadWriteMode = mkSetModeFn(0);
26089    const setReadOnlyMode = mkSetModeFn(2);
26090    const setProtectedMode = mkSetModeFn(1);
26091    const checkMode = expectedMode => transfer => {
26092      const dt = transfer;
26093      return Optional.from(dt[modeId]).exists(mode => mode === expectedMode);
26094    };
26095    const isInReadWriteMode = checkMode(0);
26096    const isInProtectedMode = checkMode(1);
26097
26098    const normalizeItems = (dataTransfer, itemsImpl) => ({
26099      ...itemsImpl,
26100      get length() {
26101        return itemsImpl.length;
26102      },
26103      add: (data, type) => {
26104        if (isInReadWriteMode(dataTransfer)) {
26105          if (isString(data)) {
26106            if (!isUndefined(type)) {
26107              return itemsImpl.add(data, type);
26108            }
26109          } else {
26110            return itemsImpl.add(data);
26111          }
26112        }
26113        return null;
26114      },
26115      remove: idx => {
26116        if (isInReadWriteMode(dataTransfer)) {
26117          itemsImpl.remove(idx);
26118        }
26119      },
26120      clear: () => {
26121        if (isInReadWriteMode(dataTransfer)) {
26122          itemsImpl.clear();
26123        }
26124      }
26125    });
26126
26127    const validDropEffects = [
26128      'none',
26129      'copy',
26130      'link',
26131      'move'
26132    ];
26133    const validEffectAlloweds = [
26134      'none',
26135      'copy',
26136      'copyLink',
26137      'copyMove',
26138      'link',
26139      'linkMove',
26140      'move',
26141      'all',
26142      'uninitialized'
26143    ];
26144    const createDataTransfer = () => {
26145      const dataTransferImpl = new window.DataTransfer();
26146      let dropEffect = 'move';
26147      let effectAllowed = 'all';
26148      const dataTransfer = {
26149        get dropEffect() {
26150          return dropEffect;
26151        },
26152        set dropEffect(effect) {
26153          if (contains$2(validDropEffects, effect)) {
26154            dropEffect = effect;
26155          }
26156        },
26157        get effectAllowed() {
26158          return effectAllowed;
26159        },
26160        set effectAllowed(allowed) {
26161          if (isInDragStartEvent(dataTransfer) && contains$2(validEffectAlloweds, allowed)) {
26162            effectAllowed = allowed;
26163          }
26164        },
26165        get items() {
26166          return normalizeItems(dataTransfer, dataTransferImpl.items);
26167        },
26168        get files() {
26169          if (isInProtectedMode(dataTransfer)) {
26170            return createEmptyFileList();
26171          } else {
26172            return dataTransferImpl.files;
26173          }
26174        },
vendor: 7,829 bytes, lines 26175-26403
26175        get types() {
26176          return dataTransferImpl.types;
26177        },
26178        setDragImage: (image, x, y) => {
26179          if (isInReadWriteMode(dataTransfer)) {
26180            setDragImage(dataTransfer, {
26181              image,
26182              x,
26183              y
26184            });
26185            dataTransferImpl.setDragImage(image, x, y);
26186          }
26187        },
26188        getData: format => {
26189          if (isInProtectedMode(dataTransfer)) {
26190            return '';
26191          } else {
26192            return dataTransferImpl.getData(format);
26193          }
26194        },
26195        setData: (format, data) => {
26196          if (isInReadWriteMode(dataTransfer)) {
26197            dataTransferImpl.setData(format, data);
26198          }
26199        },
26200        clearData: format => {
26201          if (isInReadWriteMode(dataTransfer)) {
26202            dataTransferImpl.clearData(format);
26203          }
26204        }
26205      };
26206      setReadWriteMode(dataTransfer);
26207      return dataTransfer;
26208    };
26209    const cloneDataTransfer = original => {
26210      const clone = createDataTransfer();
26211      const originalMode = getMode(original);
26212      setReadOnlyMode(original);
26213      setDragstartEvent(clone);
26214      clone.dropEffect = original.dropEffect;
26215      clone.effectAllowed = original.effectAllowed;
26216      getDragImage(original).each(imageData => clone.setDragImage(imageData.image, imageData.x, imageData.y));
26217      each$e(original.types, type => {
26218        if (type !== 'Files') {
26219          clone.setData(type, original.getData(type));
26220        }
26221      });
26222      each$e(original.files, file => clone.items.add(file));
26223      getEvent(original).each(type => {
26224        setEvent(clone, type);
26225      });
26226      originalMode.each(mode => {
26227        setMode$1(original, mode);
26228        setMode$1(clone, mode);
26229      });
26230      return clone;
26231    };
26232
26233    const getHtmlData = dataTransfer => {
26234      const html = dataTransfer.getData('text/html');
26235      return html === '' ? Optional.none() : Optional.some(html);
26236    };
26237    const setHtmlData = (dataTransfer, html) => dataTransfer.setData('text/html', html);
26238
26239    const internalMimeType = 'x-tinymce/html';
26240    const internalHtmlMime = constant(internalMimeType);
26241    const internalMark = '<!-- ' + internalMimeType + ' -->';
26242    const mark = html => internalMark + html;
26243    const unmark = html => html.replace(internalMark, '');
26244    const isMarked = html => html.indexOf(internalMark) !== -1;
26245
26246    const isPlainText = text => {
26247      return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text);
26248    };
26249    const openContainer = (rootTag, rootAttrs) => {
26250      let tag = '<' + rootTag;
26251      const attrs = mapToArray(rootAttrs, (value, key) => key + '="' + Entities.encodeAllRaw(value) + '"');
26252      if (attrs.length) {
26253        tag += ' ' + attrs.join(' ');
26254      }
26255      return tag + '>';
26256    };
26257    const toBlockElements = (text, rootTag, rootAttrs) => {
26258      const blocks = text.split(/\n\n/);
26259      const tagOpen = openContainer(rootTag, rootAttrs);
26260      const tagClose = '</' + rootTag + '>';
26261      const paragraphs = map$3(blocks, p => {
26262        return p.split(/\n/).join('<br />');
26263      });
26264      const stitch = p => {
26265        return tagOpen + p + tagClose;
26266      };
26267      return paragraphs.length === 1 ? paragraphs[0] : map$3(paragraphs, stitch).join('');
26268    };
26269
26270    const pasteBinDefaultContent = '%MCEPASTEBIN%';
26271    const create$6 = (editor, lastRngCell) => {
26272      const {dom, selection} = editor;
26273      const body = editor.getBody();
26274      lastRngCell.set(selection.getRng());
26275      const pasteBinElm = dom.add(editor.getBody(), 'div', {
26276        'id': 'mcepastebin',
26277        'class': 'mce-pastebin',
26278        'contentEditable': true,
26279        'data-mce-bogus': 'all',
26280        'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0'
26281      }, pasteBinDefaultContent);
26282      if (Env.browser.isFirefox()) {
26283        dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535);
26284      }
26285      dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', e => {
26286        e.stopPropagation();
26287      });
26288      pasteBinElm.focus();
26289      selection.select(pasteBinElm, true);
26290    };
26291    const remove = (editor, lastRngCell) => {
26292      const dom = editor.dom;
26293      if (getEl(editor)) {
26294        let pasteBinClone;
26295        const lastRng = lastRngCell.get();
26296        while (pasteBinClone = getEl(editor)) {
26297          dom.remove(pasteBinClone);
26298          dom.unbind(pasteBinClone);
26299        }
26300        if (lastRng) {
26301          editor.selection.setRng(lastRng);
26302        }
26303      }
26304      lastRngCell.set(null);
26305    };
26306    const getEl = editor => editor.dom.get('mcepastebin');
26307    const isPasteBin = elm => isNonNullable(elm) && elm.id === 'mcepastebin';
26308    const getHtml = editor => {
26309      const dom = editor.dom;
26310      const copyAndRemove = (toElm, fromElm) => {
26311        toElm.appendChild(fromElm);
26312        dom.remove(fromElm, true);
26313      };
26314      const [pasteBinElm, ...pasteBinClones] = filter$5(editor.getBody().childNodes, isPasteBin);
26315      each$e(pasteBinClones, pasteBinClone => {
26316        copyAndRemove(pasteBinElm, pasteBinClone);
26317      });
26318      const dirtyWrappers = dom.select('div[id=mcepastebin]', pasteBinElm);
26319      for (let i = dirtyWrappers.length - 1; i >= 0; i--) {
26320        const cleanWrapper = dom.create('div');
26321        pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]);
26322        copyAndRemove(cleanWrapper, dirtyWrappers[i]);
26323      }
26324      return pasteBinElm ? pasteBinElm.innerHTML : '';
26325    };
26326    const isDefaultPasteBinContent = content => content === pasteBinDefaultContent;
26327    const PasteBin = editor => {
26328      const lastRng = Cell(null);
26329      return {
26330        create: () => create$6(editor, lastRng),
26331        remove: () => remove(editor, lastRng),
26332        getEl: () => getEl(editor),
26333        getHtml: () => getHtml(editor),
26334        getLastRng: lastRng.get
26335      };
26336    };
26337
26338    const filter$1 = (content, items) => {
26339      Tools.each(items, v => {
26340        if (is$4(v, RegExp)) {
26341          content = content.replace(v, '');
26342        } else {
26343          content = content.replace(v[0], v[1]);
26344        }
26345      });
26346      return content;
26347    };
26348    const innerText = html => {
26349      const schema = Schema();
26350      const domParser = DomParser({}, schema);
26351      let text = '';
26352      const voidElements = schema.getVoidElements();
26353      const ignoreElements = Tools.makeMap('script noscript style textarea video audio iframe object', ' ');
26354      const blockElements = schema.getBlockElements();
26355      const walk = node => {
26356        const name = node.name, currentNode = node;
26357        if (name === 'br') {
26358          text += '\n';
26359          return;
26360        }
26361        if (name === 'wbr') {
26362          return;
26363        }
26364        if (voidElements[name]) {
26365          text += ' ';
26366        }
26367        if (ignoreElements[name]) {
26368          text += ' ';
26369          return;
26370        }
26371        if (node.type === 3) {
26372          text += node.value;
26373        }
26374        if (!(node.name in schema.getVoidElements())) {
26375          let currentNode = node.firstChild;
26376          if (currentNode) {
26377            do {
26378              walk(currentNode);
26379            } while (currentNode = currentNode.next);
26380          }
26381        }
26382        if (blockElements[name] && currentNode.next) {
26383          text += '\n';
26384          if (name === 'p') {
26385            text += '\n';
26386          }
26387        }
26388      };
26389      html = filter$1(html, [/<!\[[^\]]+\]>/g]);
26390      walk(domParser.parse(html));
26391      return text;
26392    };
26393    const trimHtml = html => {
26394      const trimSpaces = (all, s1, s2) => {
26395        if (!s1 && !s2) {
26396          return ' ';
26397        }
26398        return nbsp;
26399      };
26400      html = filter$1(html, [
26401        /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig,
26402        /<!--StartFragment-->|<!--EndFragment-->/g,
26403        [
vendor: 7,665 bytes, lines 26404-26591
26404          /( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g,
26405          trimSpaces
26406        ],
26407        /<br class="Apple-interchange-newline">/g,
26408        /<br>$/i
26409      ]);
26410      return html;
26411    };
26412    const createIdGenerator = prefix => {
26413      let count = 0;
26414      return () => {
26415        return prefix + count++;
26416      };
26417    };
26418    const getImageMimeType = ext => {
26419      const lowerExt = ext.toLowerCase();
26420      const mimeOverrides = {
26421        jpg: 'jpeg',
26422        jpe: 'jpeg',
26423        jfi: 'jpeg',
26424        jif: 'jpeg',
26425        jfif: 'jpeg',
26426        pjpeg: 'jpeg',
26427        pjp: 'jpeg',
26428        svg: 'svg+xml'
26429      };
26430      return Tools.hasOwn(mimeOverrides, lowerExt) ? 'image/' + mimeOverrides[lowerExt] : 'image/' + lowerExt;
26431    };
26432
26433    const preProcess = (editor, html) => {
26434      const parser = DomParser({
26435        sanitize: shouldSanitizeXss(editor),
26436        sandbox_iframes: shouldSandboxIframes(editor),
26437        sandbox_iframes_exclusions: getSandboxIframesExclusions(editor),
26438        convert_unsafe_embeds: shouldConvertUnsafeEmbeds(editor)
26439      }, editor.schema);
26440      parser.addNodeFilter('meta', nodes => {
26441        Tools.each(nodes, node => {
26442          node.remove();
26443        });
26444      });
26445      const fragment = parser.parse(html, {
26446        forced_root_block: false,
26447        isRootContent: true
26448      });
26449      return HtmlSerializer({ validate: true }, editor.schema).serialize(fragment);
26450    };
26451    const processResult = (content, cancelled) => ({
26452      content,
26453      cancelled
26454    });
26455    const postProcessFilter = (editor, html, internal) => {
26456      const tempBody = editor.dom.create('div', { style: 'display:none' }, html);
26457      const postProcessArgs = firePastePostProcess(editor, tempBody, internal);
26458      return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented());
26459    };
26460    const filterContent = (editor, content, internal) => {
26461      const preProcessArgs = firePastePreProcess(editor, content, internal);
26462      const filteredContent = preProcess(editor, preProcessArgs.content);
26463      if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) {
26464        return postProcessFilter(editor, filteredContent, internal);
26465      } else {
26466        return processResult(filteredContent, preProcessArgs.isDefaultPrevented());
26467      }
26468    };
26469    const process = (editor, html, internal) => {
26470      return filterContent(editor, html, internal);
26471    };
26472
26473    const pasteHtml$1 = (editor, html) => {
26474      editor.insertContent(html, {
26475        merge: shouldPasteMergeFormats(editor),
26476        paste: true
26477      });
26478      return true;
26479    };
26480    const isAbsoluteUrl = url => /^https?:\/\/[\w\-\/+=.,!;:&%@^~(){}?#]+$/i.test(url);
26481    const isImageUrl = (editor, url) => {
26482      return isAbsoluteUrl(url) && exists(getAllowedImageFileTypes(editor), type => endsWith(url.toLowerCase(), `.${ type.toLowerCase() }`));
26483    };
26484    const createImage = (editor, url, pasteHtmlFn) => {
26485      editor.undoManager.extra(() => {
26486        pasteHtmlFn(editor, url);
26487      }, () => {
26488        editor.insertContent('<img src="' + url + '">');
26489      });
26490      return true;
26491    };
26492    const createLink = (editor, url, pasteHtmlFn) => {
26493      editor.undoManager.extra(() => {
26494        pasteHtmlFn(editor, url);
26495      }, () => {
26496        editor.execCommand('mceInsertLink', false, url);
26497      });
26498      return true;
26499    };
26500    const linkSelection = (editor, html, pasteHtmlFn) => !editor.selection.isCollapsed() && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false;
26501    const insertImage = (editor, html, pasteHtmlFn) => isImageUrl(editor, html) ? createImage(editor, html, pasteHtmlFn) : false;
26502    const smartInsertContent = (editor, html) => {
26503      Tools.each([
26504        linkSelection,
26505        insertImage,
26506        pasteHtml$1
26507      ], action => {
26508        return !action(editor, html, pasteHtml$1);
26509      });
26510    };
26511    const insertContent = (editor, html, pasteAsText) => {
26512      if (pasteAsText || !isSmartPasteEnabled(editor)) {
26513        pasteHtml$1(editor, html);
26514      } else {
26515        smartInsertContent(editor, html);
26516      }
26517    };
26518
26519    const uniqueId = createIdGenerator('mceclip');
26520    const createPasteDataTransfer = html => {
26521      const dataTransfer = createDataTransfer();
26522      setHtmlData(dataTransfer, html);
26523      setReadOnlyMode(dataTransfer);
26524      return dataTransfer;
26525    };
26526    const doPaste = (editor, content, internal, pasteAsText, shouldSimulateInputEvent) => {
26527      const res = process(editor, content, internal);
26528      if (!res.cancelled) {
26529        const content = res.content;
26530        const doPasteAction = () => insertContent(editor, content, pasteAsText);
26531        if (shouldSimulateInputEvent) {
26532          const args = fireBeforeInputEvent(editor, 'insertFromPaste', { dataTransfer: createPasteDataTransfer(content) });
26533          if (!args.isDefaultPrevented()) {
26534            doPasteAction();
26535            fireInputEvent(editor, 'insertFromPaste');
26536          }
26537        } else {
26538          doPasteAction();
26539        }
26540      }
26541    };
26542    const pasteHtml = (editor, html, internalFlag, shouldSimulateInputEvent) => {
26543      const internal = internalFlag ? internalFlag : isMarked(html);
26544      doPaste(editor, unmark(html), internal, false, shouldSimulateInputEvent);
26545    };
26546    const pasteText = (editor, text, shouldSimulateInputEvent) => {
26547      const encodedText = editor.dom.encode(text).replace(/\r\n/g, '\n');
26548      const normalizedText = normalize$4(encodedText, getPasteTabSpaces(editor));
26549      const html = toBlockElements(normalizedText, getForcedRootBlock(editor), getForcedRootBlockAttrs(editor));
26550      doPaste(editor, html, false, true, shouldSimulateInputEvent);
26551    };
26552    const getDataTransferItems = dataTransfer => {
26553      const items = {};
26554      if (dataTransfer && dataTransfer.types) {
26555        for (let i = 0; i < dataTransfer.types.length; i++) {
26556          const contentType = dataTransfer.types[i];
26557          try {
26558            items[contentType] = dataTransfer.getData(contentType);
26559          } catch (_a) {
26560            items[contentType] = '';
26561          }
26562        }
26563      }
26564      return items;
26565    };
26566    const hasContentType = (clipboardContent, mimeType) => mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
26567    const hasHtmlOrText = content => hasContentType(content, 'text/html') || hasContentType(content, 'text/plain');
26568    const extractFilename = (editor, str) => {
26569      const m = str.match(/([\s\S]+?)(?:\.[a-z0-9.]+)$/i);
26570      return isNonNullable(m) ? editor.dom.encode(m[1]) : undefined;
26571    };
26572    const createBlobInfo = (editor, blobCache, file, base64) => {
26573      const id = uniqueId();
26574      const useFileName = shouldReuseFileName(editor) && isNonNullable(file.name);
26575      const name = useFileName ? extractFilename(editor, file.name) : id;
26576      const filename = useFileName ? file.name : undefined;
26577      const blobInfo = blobCache.create(id, file, base64, name, filename);
26578      blobCache.add(blobInfo);
26579      return blobInfo;
26580    };
26581    const pasteImage = (editor, imageItem) => {
26582      parseDataUri(imageItem.uri).each(({data, type, base64Encoded}) => {
26583        const base64 = base64Encoded ? data : btoa(data);
26584        const file = imageItem.file;
26585        const blobCache = editor.editorUpload.blobCache;
26586        const existingBlobInfo = blobCache.getByData(base64, type);
26587        const blobInfo = existingBlobInfo !== null && existingBlobInfo !== void 0 ? existingBlobInfo : createBlobInfo(editor, blobCache, file, base64);
26588        pasteHtml(editor, `<img src="${ blobInfo.blobUri() }">`, false, true);
26589      });
26590    };
26591    const isClipboardEvent = event => event.type === 'paste';
vendor: 6,684 bytes, lines 26592-26753
26592    const readFilesAsDataUris = items => Promise.all(map$3(items, file => {
26593      return blobToDataUri(file).then(uri => ({
26594        file,
26595        uri
26596      }));
26597    }));
26598    const isImage = editor => {
26599      const allowedExtensions = getAllowedImageFileTypes(editor);
26600      return file => startsWith(file.type, 'image/') && exists(allowedExtensions, extension => {
26601        return getImageMimeType(extension) === file.type;
26602      });
26603    };
26604    const getImagesFromDataTransfer = (editor, dataTransfer) => {
26605      const items = dataTransfer.items ? bind$3(from(dataTransfer.items), item => {
26606        return item.kind === 'file' ? [item.getAsFile()] : [];
26607      }) : [];
26608      const files = dataTransfer.files ? from(dataTransfer.files) : [];
26609      return filter$5(items.length > 0 ? items : files, isImage(editor));
26610    };
26611    const pasteImageData = (editor, e, rng) => {
26612      const dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer;
26613      if (shouldPasteDataImages(editor) && dataTransfer) {
26614        const images = getImagesFromDataTransfer(editor, dataTransfer);
26615        if (images.length > 0) {
26616          e.preventDefault();
26617          readFilesAsDataUris(images).then(fileResults => {
26618            if (rng) {
26619              editor.selection.setRng(rng);
26620            }
26621            each$e(fileResults, result => {
26622              pasteImage(editor, result);
26623            });
26624          });
26625          return true;
26626        }
26627      }
26628      return false;
26629    };
26630    const isBrokenAndroidClipboardEvent = e => {
26631      var _a, _b;
26632      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;
26633    };
26634    const isKeyboardPasteEvent = e => VK.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45;
26635    const insertClipboardContent = (editor, clipboardContent, html, plainTextMode, shouldSimulateInputEvent) => {
26636      let content = trimHtml(html);
26637      const isInternal = hasContentType(clipboardContent, internalHtmlMime()) || isMarked(html);
26638      const isPlainTextHtml = !isInternal && isPlainText(content);
26639      const isAbsoluteUrl$1 = isAbsoluteUrl(content);
26640      if (isDefaultPasteBinContent(content) || !content.length || isPlainTextHtml && !isAbsoluteUrl$1) {
26641        plainTextMode = true;
26642      }
26643      if (plainTextMode || isAbsoluteUrl$1) {
26644        if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) {
26645          content = clipboardContent['text/plain'];
26646        } else {
26647          content = innerText(content);
26648        }
26649      }
26650      if (isDefaultPasteBinContent(content)) {
26651        return;
26652      }
26653      if (plainTextMode) {
26654        pasteText(editor, content, shouldSimulateInputEvent);
26655      } else {
26656        pasteHtml(editor, content, isInternal, shouldSimulateInputEvent);
26657      }
26658    };
26659    const registerEventHandlers = (editor, pasteBin, pasteFormat) => {
26660      let keyboardPastePlainTextState;
26661      const getLastRng = () => pasteBin.getLastRng() || editor.selection.getRng();
26662      editor.on('keydown', e => {
26663        if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
26664          keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86;
26665        }
26666      });
26667      editor.on('paste', e => {
26668        if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
26669          return;
26670        }
26671        const plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState;
26672        keyboardPastePlainTextState = false;
26673        const clipboardContent = getDataTransferItems(e.clipboardData);
26674        if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) {
26675          return;
26676        }
26677        if (hasContentType(clipboardContent, 'text/html')) {
26678          e.preventDefault();
26679          insertClipboardContent(editor, clipboardContent, clipboardContent['text/html'], plainTextMode, true);
26680        } else if (hasContentType(clipboardContent, 'text/plain') && hasContentType(clipboardContent, 'text/uri-list')) {
26681          e.preventDefault();
26682          insertClipboardContent(editor, clipboardContent, clipboardContent['text/plain'], plainTextMode, true);
26683        } else {
26684          pasteBin.create();
26685          Delay.setEditorTimeout(editor, () => {
26686            const html = pasteBin.getHtml();
26687            pasteBin.remove();
26688            insertClipboardContent(editor, clipboardContent, html, plainTextMode, false);
26689          }, 0);
26690        }
26691      });
26692    };
26693    const registerDataImageFilter = editor => {
26694      const isWebKitFakeUrl = src => startsWith(src, 'webkit-fake-url');
26695      const isDataUri = src => startsWith(src, 'data:');
26696      const isPasteInsert = args => {
26697        var _a;
26698        return ((_a = args.data) === null || _a === void 0 ? void 0 : _a.paste) === true;
26699      };
26700      editor.parser.addNodeFilter('img', (nodes, name, args) => {
26701        if (!shouldPasteDataImages(editor) && isPasteInsert(args)) {
26702          for (const node of nodes) {
26703            const src = node.attr('src');
26704            if (isString(src) && !node.attr('data-mce-object') && src !== Env.transparentSrc) {
26705              if (isWebKitFakeUrl(src)) {
26706                node.remove();
26707              } else if (!shouldAllowHtmlDataUrls(editor) && isDataUri(src)) {
26708                node.remove();
26709              }
26710            }
26711          }
26712        }
26713      });
26714    };
26715    const registerEventsAndFilters = (editor, pasteBin, pasteFormat) => {
26716      registerEventHandlers(editor, pasteBin, pasteFormat);
26717      registerDataImageFilter(editor);
26718    };
26719
26720    const togglePlainTextPaste = (editor, pasteFormat) => {
26721      if (pasteFormat.get() === 'text') {
26722        pasteFormat.set('html');
26723        firePastePlainTextToggle(editor, false);
26724      } else {
26725        pasteFormat.set('text');
26726        firePastePlainTextToggle(editor, true);
26727      }
26728      editor.focus();
26729    };
26730    const register$1 = (editor, pasteFormat) => {
26731      editor.addCommand('mceTogglePlainTextPaste', () => {
26732        togglePlainTextPaste(editor, pasteFormat);
26733      });
26734      editor.addCommand('mceInsertClipboardContent', (ui, value) => {
26735        if (value.html) {
26736          pasteHtml(editor, value.html, value.internal, false);
26737        }
26738        if (value.text) {
26739          pasteText(editor, value.text, false);
26740        }
26741      });
26742    };
26743
26744    const setHtml5Clipboard = (clipboardData, html, text) => {
26745      if (clipboardData) {
26746        try {
26747          clipboardData.clearData();
26748          clipboardData.setData('text/html', html);
26749          clipboardData.setData('text/plain', text);
26750          clipboardData.setData(internalHtmlMime(), html);
26751          return true;
26752        } catch (_a) {
26753          return false;
vendor: 10,044 bytes, lines 26754-27007
26754        }
26755      } else {
26756        return false;
26757      }
26758    };
26759    const setClipboardData = (evt, data, fallback, done) => {
26760      if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) {
26761        evt.preventDefault();
26762        done();
26763      } else {
26764        fallback(data.html, done);
26765      }
26766    };
26767    const fallback = editor => (html, done) => {
26768      const {dom, selection} = editor;
26769      const outer = dom.create('div', {
26770        'contenteditable': 'false',
26771        'data-mce-bogus': 'all'
26772      });
26773      const inner = dom.create('div', { contenteditable: 'true' }, html);
26774      dom.setStyles(outer, {
26775        position: 'fixed',
26776        top: '0',
26777        left: '-3000px',
26778        width: '1000px',
26779        overflow: 'hidden'
26780      });
26781      outer.appendChild(inner);
26782      dom.add(editor.getBody(), outer);
26783      const range = selection.getRng();
26784      inner.focus();
26785      const offscreenRange = dom.createRng();
26786      offscreenRange.selectNodeContents(inner);
26787      selection.setRng(offscreenRange);
26788      Delay.setEditorTimeout(editor, () => {
26789        selection.setRng(range);
26790        dom.remove(outer);
26791        done();
26792      }, 0);
26793    };
26794    const getData = editor => ({
26795      html: mark(editor.selection.getContent({ contextual: true })),
26796      text: editor.selection.getContent({ format: 'text' })
26797    });
26798    const isTableSelection = editor => !!editor.dom.getParent(editor.selection.getStart(), 'td[data-mce-selected],th[data-mce-selected]', editor.getBody());
26799    const hasSelectedContent = editor => !editor.selection.isCollapsed() || isTableSelection(editor);
26800    const cut = editor => evt => {
26801      if (!evt.isDefaultPrevented() && hasSelectedContent(editor) && editor.selection.isEditable()) {
26802        setClipboardData(evt, getData(editor), fallback(editor), () => {
26803          if (Env.browser.isChromium() || Env.browser.isFirefox()) {
26804            const rng = editor.selection.getRng();
26805            Delay.setEditorTimeout(editor, () => {
26806              editor.selection.setRng(rng);
26807              editor.execCommand('Delete');
26808            }, 0);
26809          } else {
26810            editor.execCommand('Delete');
26811          }
26812        });
26813      }
26814    };
26815    const copy = editor => evt => {
26816      if (!evt.isDefaultPrevented() && hasSelectedContent(editor)) {
26817        setClipboardData(evt, getData(editor), fallback(editor), noop);
26818      }
26819    };
26820    const register = editor => {
26821      editor.on('cut', cut(editor));
26822      editor.on('copy', copy(editor));
26823    };
26824
26825    const getCaretRangeFromEvent = (editor, e) => {
26826      var _a, _b;
26827      return RangeUtils.getCaretRangeFromPoint((_a = e.clientX) !== null && _a !== void 0 ? _a : 0, (_b = e.clientY) !== null && _b !== void 0 ? _b : 0, editor.getDoc());
26828    };
26829    const isPlainTextFileUrl = content => {
26830      const plainTextContent = content['text/plain'];
26831      return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false;
26832    };
26833    const setFocusedRange = (editor, rng) => {
26834      editor.focus();
26835      if (rng) {
26836        editor.selection.setRng(rng);
26837      }
26838    };
26839    const hasImage = dataTransfer => exists(dataTransfer.files, file => /^image\//.test(file.type));
26840    const needsCustomInternalDrop = (dom, schema, target, dropContent) => {
26841      const parentTransparent = dom.getParent(target, node => isTransparentBlock(schema, node));
26842      const inSummary = !isNull(dom.getParent(target, 'summary'));
26843      if (inSummary) {
26844        return true;
26845      } else if (parentTransparent && has$2(dropContent, 'text/html')) {
26846        const fragment = new DOMParser().parseFromString(dropContent['text/html'], 'text/html').body;
26847        return !isNull(fragment.querySelector(parentTransparent.nodeName.toLowerCase()));
26848      } else {
26849        return false;
26850      }
26851    };
26852    const setupSummaryDeleteByDragFix = editor => {
26853      editor.on('input', e => {
26854        const hasNoSummary = el => isNull(el.querySelector('summary'));
26855        if (e.inputType === 'deleteByDrag') {
26856          const brokenDetailElements = filter$5(editor.dom.select('details'), hasNoSummary);
26857          each$e(brokenDetailElements, details => {
26858            if (isBr$6(details.firstChild)) {
26859              details.firstChild.remove();
26860            }
26861            const summary = editor.dom.create('summary');
26862            summary.appendChild(createPaddingBr().dom);
26863            details.prepend(summary);
26864          });
26865        }
26866      });
26867    };
26868    const setup$a = (editor, draggingInternallyState) => {
26869      if (shouldPasteBlockDrop(editor)) {
26870        editor.on('dragend dragover draggesture dragdrop drop drag', e => {
26871          e.preventDefault();
26872          e.stopPropagation();
26873        });
26874      }
26875      if (!shouldPasteDataImages(editor)) {
26876        editor.on('drop', e => {
26877          const dataTransfer = e.dataTransfer;
26878          if (dataTransfer && hasImage(dataTransfer)) {
26879            e.preventDefault();
26880          }
26881        });
26882      }
26883      editor.on('drop', e => {
26884        if (e.isDefaultPrevented()) {
26885          return;
26886        }
26887        const rng = getCaretRangeFromEvent(editor, e);
26888        if (isNullable(rng)) {
26889          return;
26890        }
26891        const dropContent = getDataTransferItems(e.dataTransfer);
26892        const internal = hasContentType(dropContent, internalHtmlMime());
26893        if ((!hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && pasteImageData(editor, e, rng)) {
26894          return;
26895        }
26896        const internalContent = dropContent[internalHtmlMime()];
26897        const content = internalContent || dropContent['text/html'] || dropContent['text/plain'];
26898        const needsInternalDrop = needsCustomInternalDrop(editor.dom, editor.schema, rng.startContainer, dropContent);
26899        const isInternalDrop = draggingInternallyState.get();
26900        if (isInternalDrop && !needsInternalDrop) {
26901          return;
26902        }
26903        if (content) {
26904          e.preventDefault();
26905          Delay.setEditorTimeout(editor, () => {
26906            editor.undoManager.transact(() => {
26907              if (internalContent || isInternalDrop && needsInternalDrop) {
26908                editor.execCommand('Delete');
26909              }
26910              setFocusedRange(editor, rng);
26911              const trimmedContent = trimHtml(content);
26912              if (dropContent['text/html']) {
26913                pasteHtml(editor, trimmedContent, internal, true);
26914              } else {
26915                pasteText(editor, trimmedContent, true);
26916              }
26917            });
26918          });
26919        }
26920      });
26921      editor.on('dragstart', _e => {
26922        draggingInternallyState.set(true);
26923      });
26924      editor.on('dragover dragend', e => {
26925        if (shouldPasteDataImages(editor) && !draggingInternallyState.get()) {
26926          e.preventDefault();
26927          setFocusedRange(editor, getCaretRangeFromEvent(editor, e));
26928        }
26929        if (e.type === 'dragend') {
26930          draggingInternallyState.set(false);
26931        }
26932      });
26933      setupSummaryDeleteByDragFix(editor);
26934    };
26935
26936    const setup$9 = editor => {
26937      const processEvent = f => e => {
26938        f(editor, e);
26939      };
26940      const preProcess = getPastePreProcess(editor);
26941      if (isFunction(preProcess)) {
26942        editor.on('PastePreProcess', processEvent(preProcess));
26943      }
26944      const postProcess = getPastePostProcess(editor);
26945      if (isFunction(postProcess)) {
26946        editor.on('PastePostProcess', processEvent(postProcess));
26947      }
26948    };
26949
26950    const addPreProcessFilter = (editor, filterFunc) => {
26951      editor.on('PastePreProcess', e => {
26952        e.content = filterFunc(editor, e.content, e.internal);
26953      });
26954    };
26955    const rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi;
26956    const rgbToHex = value => Tools.trim(value).replace(rgbRegExp, rgbaToHexString).toLowerCase();
26957    const removeWebKitStyles = (editor, content, internal) => {
26958      const webKitStylesOption = getPasteWebkitStyles(editor);
26959      if (internal || webKitStylesOption === 'all' || !shouldPasteRemoveWebKitStyles(editor)) {
26960        return content;
26961      }
26962      const webKitStyles = webKitStylesOption ? webKitStylesOption.split(/[, ]/) : [];
26963      if (webKitStyles && webKitStylesOption !== 'none') {
26964        const dom = editor.dom, node = editor.selection.getNode();
26965        content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, (all, before, value, after) => {
26966          const inputStyles = dom.parseStyle(dom.decode(value));
26967          const outputStyles = {};
26968          for (let i = 0; i < webKitStyles.length; i++) {
26969            const inputValue = inputStyles[webKitStyles[i]];
26970            let compareInput = inputValue;
26971            let currentValue = dom.getStyle(node, webKitStyles[i], true);
26972            if (/color/.test(webKitStyles[i])) {
26973              compareInput = rgbToHex(compareInput);
26974              currentValue = rgbToHex(currentValue);
26975            }
26976            if (currentValue !== compareInput) {
26977              outputStyles[webKitStyles[i]] = inputValue;
26978            }
26979          }
26980          const outputStyle = dom.serializeStyle(outputStyles, 'span');
26981          if (outputStyle) {
26982            return before + ' style="' + outputStyle + '"' + after;
26983          }
26984          return before + after;
26985        });
26986      } else {
26987        content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3');
26988      }
26989      content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, (all, before, value, after) => {
26990        return before + ' style="' + value + '"' + after;
26991      });
26992      return content;
26993    };
26994    const setup$8 = editor => {
26995      if (Env.browser.isChromium() || Env.browser.isSafari()) {
26996        addPreProcessFilter(editor, removeWebKitStyles);
26997      }
26998    };
26999
27000    const setup$7 = editor => {
27001      const draggingInternallyState = Cell(false);
27002      const pasteFormat = Cell(isPasteAsTextEnabled(editor) ? 'text' : 'html');
27003      const pasteBin = PasteBin(editor);
27004      setup$8(editor);
27005      register$1(editor, pasteFormat);
27006      setup$9(editor);
27007      editor.addQueryStateHandler('mceTogglePlainTextPaste', () => pasteFormat.get() === 'text'
vendor: 12,057 bytes, lines 27007-27291
27007);
27008      editor.on('PreInit', () => {
27009        register(editor);
27010        setup$a(editor, draggingInternallyState);
27011        registerEventsAndFilters(editor, pasteBin, pasteFormat);
27012      });
27013    };
27014
27015    const preventSummaryToggle = editor => {
27016      editor.on('click', e => {
27017        if (editor.dom.getParent(e.target, 'details')) {
27018          e.preventDefault();
27019        }
27020      });
27021    };
27022    const filterDetails = editor => {
27023      editor.parser.addNodeFilter('details', elms => {
27024        const initialStateOption = getDetailsInitialState(editor);
27025        each$e(elms, details => {
27026          if (initialStateOption === 'expanded') {
27027            details.attr('open', 'open');
27028          } else if (initialStateOption === 'collapsed') {
27029            details.attr('open', null);
27030          }
27031        });
27032      });
27033      editor.serializer.addNodeFilter('details', elms => {
27034        const serializedStateOption = getDetailsSerializedState(editor);
27035        each$e(elms, details => {
27036          if (serializedStateOption === 'expanded') {
27037            details.attr('open', 'open');
27038          } else if (serializedStateOption === 'collapsed') {
27039            details.attr('open', null);
27040          }
27041        });
27042      });
27043    };
27044    const setup$6 = editor => {
27045      preventSummaryToggle(editor);
27046      filterDetails(editor);
27047    };
27048
27049    const isBr = isBr$6;
27050    const isText = isText$b;
27051    const isContentEditableFalse$2 = elm => isContentEditableFalse$b(elm.dom);
27052    const isContentEditableTrue = elm => isContentEditableTrue$3(elm.dom);
27053    const isRoot = rootNode => elm => eq(SugarElement.fromDom(rootNode), elm);
27054    const getClosestScope = (node, rootNode, schema) => closest$4(SugarElement.fromDom(node), elm => isContentEditableTrue(elm) || schema.isBlock(name(elm)), isRoot(rootNode)).getOr(SugarElement.fromDom(rootNode)).dom;
27055    const getClosestCef = (node, rootNode) => closest$4(SugarElement.fromDom(node), isContentEditableFalse$2, isRoot(rootNode));
27056    const findEdgeCaretCandidate = (startNode, scope, forward) => {
27057      const walker = new DomTreeWalker(startNode, scope);
27058      const next = forward ? walker.next.bind(walker) : walker.prev.bind(walker);
27059      let result = startNode;
27060      for (let current = forward ? startNode : next(); current && !isBr(current); current = next()) {
27061        if (isCaretCandidate$3(current)) {
27062          result = current;
27063        }
27064      }
27065      return result;
27066    };
27067    const findClosestBlockRange = (startRng, rootNode, schema) => {
27068      const startPos = CaretPosition.fromRangeStart(startRng);
27069      const clickNode = startPos.getNode();
27070      const scope = getClosestScope(clickNode, rootNode, schema);
27071      const startNode = findEdgeCaretCandidate(clickNode, scope, false);
27072      const endNode = findEdgeCaretCandidate(clickNode, scope, true);
27073      const rng = document.createRange();
27074      getClosestCef(startNode, scope).fold(() => {
27075        if (isText(startNode)) {
27076          rng.setStart(startNode, 0);
27077        } else {
27078          rng.setStartBefore(startNode);
27079        }
27080      }, cef => rng.setStartBefore(cef.dom));
27081      getClosestCef(endNode, scope).fold(() => {
27082        if (isText(endNode)) {
27083          rng.setEnd(endNode, endNode.data.length);
27084        } else {
27085          rng.setEndAfter(endNode);
27086        }
27087      }, cef => rng.setEndAfter(cef.dom));
27088      return rng;
27089    };
27090    const onTripleClickSelect = editor => {
27091      const rng = findClosestBlockRange(editor.selection.getRng(), editor.getBody(), editor.schema);
27092      editor.selection.setRng(normalize(rng));
27093    };
27094    const setup$5 = editor => {
27095      editor.on('mousedown', e => {
27096        if (e.detail >= 3) {
27097          e.preventDefault();
27098          onTripleClickSelect(editor);
27099        }
27100      });
27101    };
27102
27103    var FakeCaretPosition;
27104    (function (FakeCaretPosition) {
27105      FakeCaretPosition['Before'] = 'before';
27106      FakeCaretPosition['After'] = 'after';
27107    }(FakeCaretPosition || (FakeCaretPosition = {})));
27108    const distanceToRectLeft = (clientRect, clientX) => Math.abs(clientRect.left - clientX);
27109    const distanceToRectRight = (clientRect, clientX) => Math.abs(clientRect.right - clientX);
27110    const isInsideY = (clientY, clientRect) => clientY >= clientRect.top && clientY <= clientRect.bottom;
27111    const collidesY = (r1, r2) => r1.top < r2.bottom && r1.bottom > r2.top;
27112    const isOverlapping = (r1, r2) => {
27113      const overlap = overlapY(r1, r2) / Math.min(r1.height, r2.height);
27114      return collidesY(r1, r2) && overlap > 0.5;
27115    };
27116    const splitRectsPerAxis = (rects, y) => {
27117      const intersectingRects = filter$5(rects, rect => isInsideY(y, rect));
27118      return boundingClientRectFromRects(intersectingRects).fold(() => [
27119        [],
27120        rects
27121      ], boundingRect => {
27122        const {
27123          pass: horizontal,
27124          fail: vertical
27125        } = partition$2(rects, rect => isOverlapping(rect, boundingRect));
27126        return [
27127          horizontal,
27128          vertical
27129        ];
27130      });
27131    };
27132    const clientInfo = (rect, clientX) => {
27133      return {
27134        node: rect.node,
27135        position: distanceToRectLeft(rect, clientX) < distanceToRectRight(rect, clientX) ? FakeCaretPosition.Before : FakeCaretPosition.After
27136      };
27137    };
27138    const horizontalDistance = (rect, x, _y) => x > rect.left && x < rect.right ? 0 : Math.min(Math.abs(rect.left - x), Math.abs(rect.right - x));
27139    const closestChildCaretCandidateNodeRect = (children, clientX, clientY, findCloserTextNode) => {
27140      const caretCandidateRect = rect => {
27141        if (isCaretCandidate$3(rect.node)) {
27142          return Optional.some(rect);
27143        } else if (isElement$6(rect.node)) {
27144          return closestChildCaretCandidateNodeRect(from(rect.node.childNodes), clientX, clientY, false);
27145        } else {
27146          return Optional.none();
27147        }
27148      };
27149      const tryFindSecondBestTextNode = (closest, sndClosest, distance) => {
27150        return caretCandidateRect(sndClosest).filter(rect => {
27151          const deltaDistance = Math.abs(distance(closest, clientX, clientY) - distance(rect, clientX, clientY));
27152          return deltaDistance < 2 && isText$b(rect.node);
27153        });
27154      };
27155      const findClosestCaretCandidateNodeRect = (rects, distance) => {
27156        const sortedRects = sort(rects, (r1, r2) => distance(r1, clientX, clientY) - distance(r2, clientX, clientY));
27157        return findMap(sortedRects, caretCandidateRect).map(closest => {
27158          if (findCloserTextNode && !isText$b(closest.node) && sortedRects.length > 1) {
27159            return tryFindSecondBestTextNode(closest, sortedRects[1], distance).getOr(closest);
27160          } else {
27161            return closest;
27162          }
27163        });
27164      };
27165      const [horizontalRects, verticalRects] = splitRectsPerAxis(getClientRects(children), clientY);
27166      const {
27167        pass: above,
27168        fail: below
27169      } = partition$2(verticalRects, rect => rect.top < clientY);
27170      return findClosestCaretCandidateNodeRect(horizontalRects, horizontalDistance).orThunk(() => findClosestCaretCandidateNodeRect(below, distanceToRectEdgeFromXY)).orThunk(() => findClosestCaretCandidateNodeRect(above, distanceToRectEdgeFromXY));
27171    };
27172    const traverseUp = (rootElm, scope, clientX, clientY) => {
27173      const helper = (scope, prevScope) => {
27174        const isDragGhostContainer = node => isElement$6(node) && node.classList.contains('mce-drag-container');
27175        const childNodesWithoutGhost = filter$5(scope.dom.childNodes, not(isDragGhostContainer));
27176        return prevScope.fold(() => closestChildCaretCandidateNodeRect(childNodesWithoutGhost, clientX, clientY, true), prevScope => {
27177          const uncheckedChildren = filter$5(childNodesWithoutGhost, node => node !== prevScope.dom);
27178          return closestChildCaretCandidateNodeRect(uncheckedChildren, clientX, clientY, true);
27179        }).orThunk(() => {
27180          const parent = eq(scope, rootElm) ? Optional.none() : parentElement(scope);
27181          return parent.bind(newScope => helper(newScope, Optional.some(scope)));
27182        });
27183      };
27184      return helper(scope, Optional.none());
27185    };
27186    const closestCaretCandidateNodeRect = (root, clientX, clientY) => {
27187      const rootElm = SugarElement.fromDom(root);
27188      const ownerDoc = documentOrOwner(rootElm);
27189      const elementAtPoint = SugarElement.fromPoint(ownerDoc, clientX, clientY).filter(elm => contains(rootElm, elm));
27190      const element = elementAtPoint.getOr(rootElm);
27191      return traverseUp(rootElm, element, clientX, clientY);
27192    };
27193    const closestFakeCaretCandidate = (root, clientX, clientY) => closestCaretCandidateNodeRect(root, clientX, clientY).filter(rect => isFakeCaretTarget(rect.node)).map(rect => clientInfo(rect, clientX));
27194
27195    const getAbsolutePosition = elm => {
27196      var _a, _b;
27197      const clientRect = elm.getBoundingClientRect();
27198      const doc = elm.ownerDocument;
27199      const docElem = doc.documentElement;
27200      const win = doc.defaultView;
27201      return {
27202        top: clientRect.top + ((_a = win === null || win === void 0 ? void 0 : win.scrollY) !== null && _a !== void 0 ? _a : 0) - docElem.clientTop,
27203        left: clientRect.left + ((_b = win === null || win === void 0 ? void 0 : win.scrollX) !== null && _b !== void 0 ? _b : 0) - docElem.clientLeft
27204      };
27205    };
27206    const getBodyPosition = editor => editor.inline ? getAbsolutePosition(editor.getBody()) : {
27207      left: 0,
27208      top: 0
27209    };
27210    const getScrollPosition = editor => {
27211      const body = editor.getBody();
27212      return editor.inline ? {
27213        left: body.scrollLeft,
27214        top: body.scrollTop
27215      } : {
27216        left: 0,
27217        top: 0
27218      };
27219    };
27220    const getBodyScroll = editor => {
27221      const body = editor.getBody(), docElm = editor.getDoc().documentElement;
27222      const inlineScroll = {
27223        left: body.scrollLeft,
27224        top: body.scrollTop
27225      };
27226      const iframeScroll = {
27227        left: body.scrollLeft || docElm.scrollLeft,
27228        top: body.scrollTop || docElm.scrollTop
27229      };
27230      return editor.inline ? inlineScroll : iframeScroll;
27231    };
27232    const getMousePosition = (editor, event) => {
27233      if (event.target.ownerDocument !== editor.getDoc()) {
27234        const iframePosition = getAbsolutePosition(editor.getContentAreaContainer());
27235        const scrollPosition = getBodyScroll(editor);
27236        return {
27237          left: event.pageX - iframePosition.left + scrollPosition.left,
27238          top: event.pageY - iframePosition.top + scrollPosition.top
27239        };
27240      }
27241      return {
27242        left: event.pageX,
27243        top: event.pageY
27244      };
27245    };
27246    const calculatePosition = (bodyPosition, scrollPosition, mousePosition) => ({
27247      pageX: mousePosition.left - bodyPosition.left + scrollPosition.left,
27248      pageY: mousePosition.top - bodyPosition.top + scrollPosition.top
27249    });
27250    const calc = (editor, event) => calculatePosition(getBodyPosition(editor), getScrollPosition(editor), getMousePosition(editor, event));
27251
27252    const getTargetProps = target => ({
27253      target,
27254      srcElement: target
27255    });
27256    const makeDndEventFromMouseEvent = (type, mouseEvent, target, dataTransfer) => ({
27257      ...mouseEvent,
27258      dataTransfer,
27259      type,
27260      ...getTargetProps(target)
27261    });
27262    const makeDndEvent = (type, target, dataTransfer) => {
27263      const fail = die('Function not supported on simulated event.');
27264      const event = {
27265        bubbles: true,
27266        cancelBubble: false,
27267        cancelable: true,
27268        composed: false,
27269        currentTarget: null,
27270        defaultPrevented: false,
27271        eventPhase: 0,
27272        isTrusted: true,
27273        returnValue: false,
27274        timeStamp: 0,
27275        type,
27276        composedPath: fail,
27277        initEvent: fail,
27278        preventDefault: noop,
27279        stopImmediatePropagation: noop,
27280        stopPropagation: noop,
27281        AT_TARGET: window.Event.AT_TARGET,
27282        BUBBLING_PHASE: window.Event.BUBBLING_PHASE,
27283        CAPTURING_PHASE: window.Event.CAPTURING_PHASE,
27284        NONE: window.Event.NONE,
27285        altKey: false,
27286        button: 0,
27287        buttons: 0,
27288        clientX: 0,
27289        clientY: 0,
27290        ctrlKey: false,
27291        
27291layerX: 0,
27292        layerY: 0
vendor: 7,989 bytes, lines 27292-27486
27292,
27293        metaKey: false,
27294        movementX: 0,
27295        movementY: 0,
27296        offsetX: 0,
27297        offsetY: 0,
27298        pageX: 0,
27299        pageY: 0,
27300        relatedTarget: null,
27301        screenX: 0,
27302        screenY: 0,
27303        shiftKey: false,
27304        x: 0,
27305        y: 0,
27306        detail: 0,
27307        view: null,
27308        which: 0,
27309        initUIEvent: fail,
27310        initMouseEvent: fail,
27311        getModifierState: fail,
27312        dataTransfer,
27313        ...getTargetProps(target)
27314      };
27315      return event;
27316    };
27317    const makeDataTransferCopyForDragEvent = (dataTransfer, eventType) => {
27318      const copy = cloneDataTransfer(dataTransfer);
27319      if (eventType === 'dragstart') {
27320        setDragstartEvent(copy);
27321        setReadWriteMode(copy);
27322      } else if (eventType === 'drop') {
27323        setDropEvent(copy);
27324        setReadOnlyMode(copy);
27325      } else {
27326        setDragendEvent(copy);
27327        setProtectedMode(copy);
27328      }
27329      return copy;
27330    };
27331    const makeDragEvent = (type, target, dataTransfer, mouseEvent) => {
27332      const dataTransferForDispatch = makeDataTransferCopyForDragEvent(dataTransfer, type);
27333      return isUndefined(mouseEvent) ? makeDndEvent(type, target, dataTransferForDispatch) : makeDndEventFromMouseEvent(type, mouseEvent, target, dataTransferForDispatch);
27334    };
27335
27336    const scrollPixelsPerInterval = 32;
27337    const scrollIntervalValue = 100;
27338    const mouseRangeToTriggerScrollInsideEditor = 8;
27339    const mouseRangeToTriggerScrollOutsideEditor = 16;
27340    const isContentEditableFalse$1 = isContentEditableFalse$b;
27341    const isContentEditable = or(isContentEditableFalse$1, isContentEditableTrue$3);
27342    const isDraggable = (dom, rootElm, elm) => isContentEditableFalse$1(elm) && elm !== rootElm && dom.isEditable(elm.parentElement);
27343    const isValidDropTarget = (editor, targetElement, dragElement) => {
27344      if (isNullable(targetElement)) {
27345        return false;
27346      } else if (targetElement === dragElement || editor.dom.isChildOf(targetElement, dragElement)) {
27347        return false;
27348      } else {
27349        return editor.dom.isEditable(targetElement);
27350      }
27351    };
27352    const createGhost = (editor, elm, width, height) => {
27353      const dom = editor.dom;
27354      const clonedElm = elm.cloneNode(true);
27355      dom.setStyles(clonedElm, {
27356        width,
27357        height
27358      });
27359      dom.setAttrib(clonedElm, 'data-mce-selected', null);
27360      const ghostElm = dom.create('div', {
27361        'class': 'mce-drag-container',
27362        'data-mce-bogus': 'all',
27363        'unselectable': 'on',
27364        'contenteditable': 'false'
27365      });
27366      dom.setStyles(ghostElm, {
27367        position: 'absolute',
27368        opacity: 0.5,
27369        overflow: 'hidden',
27370        border: 0,
27371        padding: 0,
27372        margin: 0,
27373        width,
27374        height
27375      });
27376      dom.setStyles(clonedElm, {
27377        margin: 0,
27378        boxSizing: 'border-box'
27379      });
27380      ghostElm.appendChild(clonedElm);
27381      return ghostElm;
27382    };
27383    const appendGhostToBody = (ghostElm, bodyElm) => {
27384      if (ghostElm.parentNode !== bodyElm) {
27385        bodyElm.appendChild(ghostElm);
27386      }
27387    };
27388    const scrollEditor = (direction, amount) => win => () => {
27389      const current = direction === 'left' ? win.scrollX : win.scrollY;
27390      win.scroll({
27391        [direction]: current + amount,
27392        behavior: 'smooth'
27393      });
27394    };
27395    const scrollLeft = scrollEditor('left', -scrollPixelsPerInterval);
27396    const scrollRight = scrollEditor('left', scrollPixelsPerInterval);
27397    const scrollUp = scrollEditor('top', -scrollPixelsPerInterval);
27398    const scrollDown = scrollEditor('top', scrollPixelsPerInterval);
27399    const moveGhost = (ghostElm, position, width, height, maxX, maxY, mouseY, mouseX, contentAreaContainer, win, state, mouseEventOriginatedFromWithinTheEditor) => {
27400      let overflowX = 0, overflowY = 0;
27401      ghostElm.style.left = position.pageX + 'px';
27402      ghostElm.style.top = position.pageY + 'px';
27403      if (position.pageX + width > maxX) {
27404        overflowX = position.pageX + width - maxX;
27405      }
27406      if (position.pageY + height > maxY) {
27407        overflowY = position.pageY + height - maxY;
27408      }
27409      ghostElm.style.width = width - overflowX + 'px';
27410      ghostElm.style.height = height - overflowY + 'px';
27411      const clientHeight = contentAreaContainer.clientHeight;
27412      const clientWidth = contentAreaContainer.clientWidth;
27413      const outerMouseY = mouseY + contentAreaContainer.getBoundingClientRect().top;
27414      const outerMouseX = mouseX + contentAreaContainer.getBoundingClientRect().left;
27415      state.on(state => {
27416        state.intervalId.clear();
27417        if (state.dragging && mouseEventOriginatedFromWithinTheEditor) {
27418          if (mouseY + mouseRangeToTriggerScrollInsideEditor >= clientHeight) {
27419            state.intervalId.set(scrollDown(win));
27420          } else if (mouseY - mouseRangeToTriggerScrollInsideEditor <= 0) {
27421            state.intervalId.set(scrollUp(win));
27422          } else if (mouseX + mouseRangeToTriggerScrollInsideEditor >= clientWidth) {
27423            state.intervalId.set(scrollRight(win));
27424          } else if (mouseX - mouseRangeToTriggerScrollInsideEditor <= 0) {
27425            state.intervalId.set(scrollLeft(win));
27426          } else if (outerMouseY + mouseRangeToTriggerScrollOutsideEditor >= window.innerHeight) {
27427            state.intervalId.set(scrollDown(window));
27428          } else if (outerMouseY - mouseRangeToTriggerScrollOutsideEditor <= 0) {
27429            state.intervalId.set(scrollUp(window));
27430          } else if (outerMouseX + mouseRangeToTriggerScrollOutsideEditor >= window.innerWidth) {
27431            state.intervalId.set(scrollRight(window));
27432          } else if (outerMouseX - mouseRangeToTriggerScrollOutsideEditor <= 0) {
27433            state.intervalId.set(scrollLeft(window));
27434          }
27435        }
27436      });
27437    };
27438    const removeElement = elm => {
27439      if (elm && elm.parentNode) {
27440        elm.parentNode.removeChild(elm);
27441      }
27442    };
27443    const removeElementWithPadding = (dom, elm) => {
27444      const parentBlock = dom.getParent(elm.parentNode, dom.isBlock);
27445      removeElement(elm);
27446      if (parentBlock && parentBlock !== dom.getRoot() && dom.isEmpty(parentBlock)) {
27447        fillWithPaddingBr(SugarElement.fromDom(parentBlock));
27448      }
27449    };
27450    const isLeftMouseButtonPressed = e => e.button === 0;
27451    const applyRelPos = (state, position) => ({
27452      pageX: position.pageX - state.relX,
27453      pageY: position.pageY + 5
27454    });
27455    const start = (state, editor) => e => {
27456      if (isLeftMouseButtonPressed(e)) {
27457        const ceElm = find$2(editor.dom.getParents(e.target), isContentEditable).getOr(null);
27458        if (isNonNullable(ceElm) && isDraggable(editor.dom, editor.getBody(), ceElm)) {
27459          const elmPos = editor.dom.getPos(ceElm);
27460          const bodyElm = editor.getBody();
27461          const docElm = editor.getDoc().documentElement;
27462          state.set({
27463            element: ceElm,
27464            dataTransfer: createDataTransfer(),
27465            dragging: false,
27466            screenX: e.screenX,
27467            screenY: e.screenY,
27468            maxX: (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2,
27469            maxY: (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2,
27470            relX: e.pageX - elmPos.x,
27471            relY: e.pageY - elmPos.y,
27472            width: ceElm.offsetWidth,
27473            height: ceElm.offsetHeight,
27474            ghost: createGhost(editor, ceElm, ceElm.offsetWidth, ceElm.offsetHeight),
27475            intervalId: repeatable(scrollIntervalValue)
27476          });
27477        }
27478      }
27479    };
27480    const placeCaretAt = (editor, clientX, clientY) => {
27481      editor._selectionOverrides.hideFakeCaret();
27482      closestFakeCaretCandidate(editor.getBody(), clientX, clientY).fold(() => editor.selection.placeCaretAt(clientX, clientY), caretInfo => {
27483        const range = editor._selectionOverrides.showCaret(1, caretInfo.node, caretInfo.position === FakeCaretPosition.Before, false);
27484        if (range) {
27485          editor.selection.setRng(range);
27486        } else {
vendor: 13,997 bytes, lines 27487-27835
27487          editor.selection.placeCaretAt(clientX, clientY);
27488        }
27489      });
27490    };
27491    const dispatchDragEvent = (editor, type, target, dataTransfer, mouseEvent) => {
27492      if (type === 'dragstart') {
27493        setHtmlData(dataTransfer, editor.dom.getOuterHTML(target));
27494      }
27495      const event = makeDragEvent(type, target, dataTransfer, mouseEvent);
27496      const args = editor.dispatch(type, event);
27497      return args;
27498    };
27499    const move = (state, editor) => {
27500      const throttledPlaceCaretAt = first$1((clientX, clientY) => placeCaretAt(editor, clientX, clientY), 0);
27501      editor.on('remove', throttledPlaceCaretAt.cancel);
27502      const state_ = state;
27503      return e => state.on(state => {
27504        const movement = Math.max(Math.abs(e.screenX - state.screenX), Math.abs(e.screenY - state.screenY));
27505        if (!state.dragging && movement > 10) {
27506          const args = dispatchDragEvent(editor, 'dragstart', state.element, state.dataTransfer, e);
27507          if (isNonNullable(args.dataTransfer)) {
27508            state.dataTransfer = args.dataTransfer;
27509          }
27510          if (args.isDefaultPrevented()) {
27511            return;
27512          }
27513          state.dragging = true;
27514          editor.focus();
27515        }
27516        if (state.dragging) {
27517          const mouseEventOriginatedFromWithinTheEditor = e.currentTarget === editor.getDoc().documentElement;
27518          const targetPos = applyRelPos(state, calc(editor, e));
27519          appendGhostToBody(state.ghost, editor.getBody());
27520          moveGhost(state.ghost, targetPos, state.width, state.height, state.maxX, state.maxY, e.clientY, e.clientX, editor.getContentAreaContainer(), editor.getWin(), state_, mouseEventOriginatedFromWithinTheEditor);
27521          throttledPlaceCaretAt.throttle(e.clientX, e.clientY);
27522        }
27523      });
27524    };
27525    const getRawTarget = selection => {
27526      const sel = selection.getSel();
27527      if (isNonNullable(sel)) {
27528        const rng = sel.getRangeAt(0);
27529        const startContainer = rng.startContainer;
27530        return isText$b(startContainer) ? startContainer.parentNode : startContainer;
27531      } else {
27532        return null;
27533      }
27534    };
27535    const drop = (state, editor) => e => {
27536      state.on(state => {
27537        var _a;
27538        state.intervalId.clear();
27539        if (state.dragging) {
27540          if (isValidDropTarget(editor, getRawTarget(editor.selection), state.element)) {
27541            const dropTarget = (_a = editor.getDoc().elementFromPoint(e.clientX, e.clientY)) !== null && _a !== void 0 ? _a : editor.getBody();
27542            const args = dispatchDragEvent(editor, 'drop', dropTarget, state.dataTransfer, e);
27543            if (!args.isDefaultPrevented()) {
27544              editor.undoManager.transact(() => {
27545                removeElementWithPadding(editor.dom, state.element);
27546                getHtmlData(state.dataTransfer).each(content => editor.insertContent(content));
27547                editor._selectionOverrides.hideFakeCaret();
27548              });
27549            }
27550          }
27551          dispatchDragEvent(editor, 'dragend', editor.getBody(), state.dataTransfer, e);
27552        }
27553      });
27554      removeDragState(state);
27555    };
27556    const stopDragging = (state, editor, e) => {
27557      state.on(state => {
27558        state.intervalId.clear();
27559        if (state.dragging) {
27560          e.fold(() => dispatchDragEvent(editor, 'dragend', state.element, state.dataTransfer), mouseEvent => dispatchDragEvent(editor, 'dragend', state.element, state.dataTransfer, mouseEvent));
27561        }
27562      });
27563      removeDragState(state);
27564    };
27565    const stop = (state, editor) => e => stopDragging(state, editor, Optional.some(e));
27566    const removeDragState = state => {
27567      state.on(state => {
27568        state.intervalId.clear();
27569        removeElement(state.ghost);
27570      });
27571      state.clear();
27572    };
27573    const bindFakeDragEvents = editor => {
27574      const state = value$2();
27575      const pageDom = DOMUtils.DOM;
27576      const rootDocument = document;
27577      const dragStartHandler = start(state, editor);
27578      const dragHandler = move(state, editor);
27579      const dropHandler = drop(state, editor);
27580      const dragEndHandler = stop(state, editor);
27581      editor.on('mousedown', dragStartHandler);
27582      editor.on('mousemove', dragHandler);
27583      editor.on('mouseup', dropHandler);
27584      pageDom.bind(rootDocument, 'mousemove', dragHandler);
27585      pageDom.bind(rootDocument, 'mouseup', dragEndHandler);
27586      editor.on('remove', () => {
27587        pageDom.unbind(rootDocument, 'mousemove', dragHandler);
27588        pageDom.unbind(rootDocument, 'mouseup', dragEndHandler);
27589      });
27590      editor.on('keydown', e => {
27591        if (e.keyCode === VK.ESC) {
27592          stopDragging(state, editor, Optional.none());
27593        }
27594      });
27595    };
27596    const blockUnsupportedFileDrop = editor => {
27597      const preventFileDrop = e => {
27598        if (!e.isDefaultPrevented()) {
27599          const dataTransfer = e.dataTransfer;
27600          if (dataTransfer && (contains$2(dataTransfer.types, 'Files') || dataTransfer.files.length > 0)) {
27601            e.preventDefault();
27602            if (e.type === 'drop') {
27603              displayError(editor, 'Dropped file type is not supported');
27604            }
27605          }
27606        }
27607      };
27608      const preventFileDropIfUIElement = e => {
27609        if (isUIElement(editor, e.target)) {
27610          preventFileDrop(e);
27611        }
27612      };
27613      const setup = () => {
27614        const pageDom = DOMUtils.DOM;
27615        const dom = editor.dom;
27616        const doc = document;
27617        const editorRoot = editor.inline ? editor.getBody() : editor.getDoc();
27618        const eventNames = [
27619          'drop',
27620          'dragover'
27621        ];
27622        each$e(eventNames, name => {
27623          pageDom.bind(doc, name, preventFileDropIfUIElement);
27624          dom.bind(editorRoot, name, preventFileDrop);
27625        });
27626        editor.on('remove', () => {
27627          each$e(eventNames, name => {
27628            pageDom.unbind(doc, name, preventFileDropIfUIElement);
27629            dom.unbind(editorRoot, name, preventFileDrop);
27630          });
27631        });
27632      };
27633      editor.on('init', () => {
27634        Delay.setEditorTimeout(editor, setup, 0);
27635      });
27636    };
27637    const init$2 = editor => {
27638      bindFakeDragEvents(editor);
27639      if (shouldBlockUnsupportedDrop(editor)) {
27640        blockUnsupportedFileDrop(editor);
27641      }
27642    };
27643
27644    const setup$4 = editor => {
27645      const renderFocusCaret = first$1(() => {
27646        if (!editor.removed && editor.getBody().contains(document.activeElement)) {
27647          const rng = editor.selection.getRng();
27648          if (rng.collapsed) {
27649            const caretRange = renderRangeCaret(editor, rng, false);
27650            editor.selection.setRng(caretRange);
27651          }
27652        }
27653      }, 0);
27654      editor.on('focus', () => {
27655        renderFocusCaret.throttle();
27656      });
27657      editor.on('blur', () => {
27658        renderFocusCaret.cancel();
27659      });
27660    };
27661
27662    const setup$3 = editor => {
27663      editor.on('init', () => {
27664        editor.on('focusin', e => {
27665          const target = e.target;
27666          if (isMedia$2(target)) {
27667            const ceRoot = getContentEditableRoot$1(editor.getBody(), target);
27668            const node = isContentEditableFalse$b(ceRoot) ? ceRoot : target;
27669            if (editor.selection.getNode() !== node) {
27670              selectNode(editor, node).each(rng => editor.selection.setRng(rng));
27671            }
27672          }
27673        });
27674      });
27675    };
27676
27677    const isContentEditableFalse = isContentEditableFalse$b;
27678    const getContentEditableRoot = (editor, node) => getContentEditableRoot$1(editor.getBody(), node);
27679    const SelectionOverrides = editor => {
27680      const selection = editor.selection, dom = editor.dom;
27681      const rootNode = editor.getBody();
27682      const fakeCaret = FakeCaret(editor, rootNode, dom.isBlock, () => hasFocus(editor));
27683      const realSelectionId = 'sel-' + dom.uniqueId();
27684      const elementSelectionAttr = 'data-mce-selected';
27685      let selectedElement;
27686      const isFakeSelectionElement = node => isNonNullable(node) && dom.hasClass(node, 'mce-offscreen-selection');
27687      const isFakeSelectionTargetElement = node => node !== rootNode && (isContentEditableFalse(node) || isMedia$2(node)) && dom.isChildOf(node, rootNode) && dom.isEditable(node.parentNode);
27688      const setRange = range => {
27689        if (range) {
27690          selection.setRng(range);
27691        }
27692      };
27693      const showCaret = (direction, node, before, scrollIntoView = true) => {
27694        const e = editor.dispatch('ShowCaret', {
27695          target: node,
27696          direction,
27697          before
27698        });
27699        if (e.isDefaultPrevented()) {
27700          return null;
27701        }
27702        if (scrollIntoView) {
27703          selection.scrollIntoView(node, direction === -1);
27704        }
27705        return fakeCaret.show(before, node);
27706      };
27707      const showBlockCaretContainer = blockCaretContainer => {
27708        if (blockCaretContainer.hasAttribute('data-mce-caret')) {
27709          showCaretContainerBlock(blockCaretContainer);
27710          selection.scrollIntoView(blockCaretContainer);
27711        }
27712      };
27713      const registerEvents = () => {
27714        editor.on('click', e => {
27715          if (!dom.isEditable(e.target)) {
27716            e.preventDefault();
27717            editor.focus();
27718          }
27719        });
27720        editor.on('blur NewBlock', removeElementSelection);
27721        editor.on('ResizeWindow FullscreenStateChanged', fakeCaret.reposition);
27722        editor.on('tap', e => {
27723          const targetElm = e.target;
27724          const contentEditableRoot = getContentEditableRoot(editor, targetElm);
27725          if (isContentEditableFalse(contentEditableRoot)) {
27726            e.preventDefault();
27727            selectNode(editor, contentEditableRoot).each(setElementSelection);
27728          } else if (isFakeSelectionTargetElement(targetElm)) {
27729            selectNode(editor, targetElm).each(setElementSelection);
27730          }
27731        }, true);
27732        editor.on('mousedown', e => {
27733          const targetElm = e.target;
27734          if (targetElm !== rootNode && targetElm.nodeName !== 'HTML' && !dom.isChildOf(targetElm, rootNode)) {
27735            return;
27736          }
27737          if (!isXYInContentArea(editor, e.clientX, e.clientY)) {
27738            return;
27739          }
27740          removeElementSelection();
27741          hideFakeCaret();
27742          const closestContentEditable = getContentEditableRoot(editor, targetElm);
27743          if (isContentEditableFalse(closestContentEditable)) {
27744            e.preventDefault();
27745            selectNode(editor, closestContentEditable).each(setElementSelection);
27746          } else {
27747            closestFakeCaretCandidate(rootNode, e.clientX, e.clientY).each(caretInfo => {
27748              e.preventDefault();
27749              const range = showCaret(1, caretInfo.node, caretInfo.position === FakeCaretPosition.Before, false);
27750              setRange(range);
27751              if (isHTMLElement(closestContentEditable)) {
27752                closestContentEditable.focus();
27753              } else {
27754                editor.getBody().focus();
27755              }
27756            });
27757          }
27758        });
27759        editor.on('keypress', e => {
27760          if (VK.modifierPressed(e)) {
27761            return;
27762          }
27763          if (isContentEditableFalse(selection.getNode())) {
27764            e.preventDefault();
27765          }
27766        });
27767        editor.on('GetSelectionRange', e => {
27768          let rng = e.range;
27769          if (selectedElement) {
27770            if (!selectedElement.parentNode) {
27771              selectedElement = null;
27772              return;
27773            }
27774            rng = rng.cloneRange();
27775            rng.selectNode(selectedElement);
27776            e.range = rng;
27777          }
27778        });
27779        editor.on('SetSelectionRange', e => {
27780          e.range = normalizeVoidElementSelection(e.range);
27781          const rng = setElementSelection(e.range, e.forward);
27782          if (rng) {
27783            e.range = rng;
27784          }
27785        });
27786        const isPasteBin = node => isElement$6(node) && node.id === 'mcepastebin';
27787        editor.on('AfterSetSelectionRange', e => {
27788          const rng = e.range;
27789          const parent = rng.startContainer.parentElement;
27790          if (!isRangeInCaretContainer(rng) && !isPasteBin(parent)) {
27791            hideFakeCaret();
27792          }
27793          if (!isFakeSelectionElement(parent)) {
27794            removeElementSelection();
27795          }
27796        });
27797        init$2(editor);
27798        setup$4(editor);
27799        setup$3(editor);
27800      };
27801      const isWithinCaretContainer = node => isCaretContainer$2(node) || startsWithCaretContainer$1(node) || endsWithCaretContainer$1(node);
27802      const isRangeInCaretContainer = rng => isWithinCaretContainer(rng.startContainer) || isWithinCaretContainer(rng.endContainer);
27803      const normalizeVoidElementSelection = rng => {
27804        const voidElements = editor.schema.getVoidElements();
27805        const newRng = dom.createRng();
27806        const startContainer = rng.startContainer;
27807        const startOffset = rng.startOffset;
27808        const endContainer = rng.endContainer;
27809        const endOffset = rng.endOffset;
27810        if (has$2(voidElements, startContainer.nodeName.toLowerCase())) {
27811          if (startOffset === 0) {
27812            newRng.setStartBefore(startContainer);
27813          } else {
27814            newRng.setStartAfter(startContainer);
27815          }
27816        } else {
27817          newRng.setStart(startContainer, startOffset);
27818        }
27819        if (has$2(voidElements, endContainer.nodeName.toLowerCase())) {
27820          if (endOffset === 0) {
27821            newRng.setEndBefore(endContainer);
27822          } else {
27823            newRng.setEndAfter(endContainer);
27824          }
27825        } else {
27826          newRng.setEnd(endContainer, endOffset);
27827        }
27828        return newRng;
27829      };
27830      const setupOffscreenSelection = (node, targetClone) => {
27831        const body = SugarElement.fromDom(editor.getBody());
27832        const doc = editor.getDoc();
27833        const realSelectionContainer = descendant$1(body, '#' + realSelectionId).getOrThunk(() => {
27834          const newContainer = SugarElement.fromHtml('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>', doc);
27835          set$
278354
vendor: 27,222 bytes, lines 27835-28482
27835(newContainer, 'id', realSelectionId);
27836          append$1(body, newContainer);
27837          return newContainer;
27838        });
27839        const newRange = dom.createRng();
27840        empty(realSelectionContainer);
27841        append(realSelectionContainer, [
27842          SugarElement.fromText(nbsp, doc),
27843          SugarElement.fromDom(targetClone),
27844          SugarElement.fromText(nbsp, doc)
27845        ]);
27846        newRange.setStart(realSelectionContainer.dom.firstChild, 1);
27847        newRange.setEnd(realSelectionContainer.dom.lastChild, 0);
27848        setAll(realSelectionContainer, { top: dom.getPos(node, editor.getBody()).y + 'px' });
27849        focus$1(realSelectionContainer);
27850        const sel = selection.getSel();
27851        if (sel) {
27852          sel.removeAllRanges();
27853          sel.addRange(newRange);
27854        }
27855        return newRange;
27856      };
27857      const selectElement = elm => {
27858        const targetClone = elm.cloneNode(true);
27859        const e = editor.dispatch('ObjectSelected', {
27860          target: elm,
27861          targetClone
27862        });
27863        if (e.isDefaultPrevented()) {
27864          return null;
27865        }
27866        const range = setupOffscreenSelection(elm, e.targetClone);
27867        const nodeElm = SugarElement.fromDom(elm);
27868        each$e(descendants(SugarElement.fromDom(editor.getBody()), `*[${ elementSelectionAttr }]`), elm => {
27869          if (!eq(nodeElm, elm)) {
27870            remove$9(elm, elementSelectionAttr);
27871          }
27872        });
27873        if (!dom.getAttrib(elm, elementSelectionAttr)) {
27874          elm.setAttribute(elementSelectionAttr, '1');
27875        }
27876        selectedElement = elm;
27877        hideFakeCaret();
27878        return range;
27879      };
27880      const setElementSelection = (range, forward) => {
27881        if (!range) {
27882          return null;
27883        }
27884        if (range.collapsed) {
27885          if (!isRangeInCaretContainer(range)) {
27886            const dir = forward ? 1 : -1;
27887            const caretPosition = getNormalizedRangeEndPoint(dir, rootNode, range);
27888            const beforeNode = caretPosition.getNode(!forward);
27889            if (isNonNullable(beforeNode)) {
27890              if (isFakeCaretTarget(beforeNode)) {
27891                return showCaret(dir, beforeNode, forward ? !caretPosition.isAtEnd() : false, false);
27892              }
27893              if (isCaretContainerInline(beforeNode) && isContentEditableFalse$b(beforeNode.nextSibling)) {
27894                const rng = dom.createRng();
27895                rng.setStart(beforeNode, 0);
27896                rng.setEnd(beforeNode, 0);
27897                return rng;
27898              }
27899            }
27900            const afterNode = caretPosition.getNode(forward);
27901            if (isNonNullable(afterNode)) {
27902              if (isFakeCaretTarget(afterNode)) {
27903                return showCaret(dir, afterNode, forward ? false : !caretPosition.isAtEnd(), false);
27904              }
27905              if (isCaretContainerInline(afterNode) && isContentEditableFalse$b(afterNode.previousSibling)) {
27906                const rng = dom.createRng();
27907                rng.setStart(afterNode, 1);
27908                rng.setEnd(afterNode, 1);
27909                return rng;
27910              }
27911            }
27912          }
27913          return null;
27914        }
27915        let startContainer = range.startContainer;
27916        let startOffset = range.startOffset;
27917        const endOffset = range.endOffset;
27918        if (isText$b(startContainer) && startOffset === 0 && isContentEditableFalse(startContainer.parentNode)) {
27919          startContainer = startContainer.parentNode;
27920          startOffset = dom.nodeIndex(startContainer);
27921          startContainer = startContainer.parentNode;
27922        }
27923        if (!isElement$6(startContainer)) {
27924          return null;
27925        }
27926        if (endOffset === startOffset + 1 && startContainer === range.endContainer) {
27927          const node = startContainer.childNodes[startOffset];
27928          if (isFakeSelectionTargetElement(node)) {
27929            return selectElement(node);
27930          }
27931        }
27932        return null;
27933      };
27934      const removeElementSelection = () => {
27935        if (selectedElement) {
27936          selectedElement.removeAttribute(elementSelectionAttr);
27937        }
27938        descendant$1(SugarElement.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$4);
27939        selectedElement = null;
27940      };
27941      const destroy = () => {
27942        fakeCaret.destroy();
27943        selectedElement = null;
27944      };
27945      const hideFakeCaret = () => {
27946        fakeCaret.hide();
27947      };
27948      if (!isRtc(editor)) {
27949        registerEvents();
27950      }
27951      return {
27952        showCaret,
27953        showBlockCaretContainer,
27954        hideFakeCaret,
27955        destroy
27956      };
27957    };
27958
27959    const getNormalizedTextOffset = (container, offset) => {
27960      let normalizedOffset = offset;
27961      for (let node = container.previousSibling; isText$b(node); node = node.previousSibling) {
27962        normalizedOffset += node.data.length;
27963      }
27964      return normalizedOffset;
27965    };
27966    const generatePath = (dom, root, node, offset, normalized) => {
27967      if (isText$b(node) && (offset < 0 || offset > node.data.length)) {
27968        return [];
27969      }
27970      const p = normalized && isText$b(node) ? [getNormalizedTextOffset(node, offset)] : [offset];
27971      let current = node;
27972      while (current !== root && current.parentNode) {
27973        p.push(dom.nodeIndex(current, normalized));
27974        current = current.parentNode;
27975      }
27976      return current === root ? p.reverse() : [];
27977    };
27978    const generatePathRange = (dom, root, startNode, startOffset, endNode, endOffset, normalized = false) => {
27979      const start = generatePath(dom, root, startNode, startOffset, normalized);
27980      const end = generatePath(dom, root, endNode, endOffset, normalized);
27981      return {
27982        start,
27983        end
27984      };
27985    };
27986    const resolvePath = (root, path) => {
27987      const nodePath = path.slice();
27988      const offset = nodePath.pop();
27989      if (!isNumber(offset)) {
27990        return Optional.none();
27991      } else {
27992        const resolvedNode = foldl(nodePath, (optNode, index) => optNode.bind(node => Optional.from(node.childNodes[index])), Optional.some(root));
27993        return resolvedNode.bind(node => {
27994          if (isText$b(node) && (offset < 0 || offset > node.data.length)) {
27995            return Optional.none();
27996          } else {
27997            return Optional.some({
27998              node,
27999              offset
28000            });
28001          }
28002        });
28003      }
28004    };
28005    const resolvePathRange = (root, range) => resolvePath(root, range.start).bind(({
28006      node: startNode,
28007      offset: startOffset
28008    }) => resolvePath(root, range.end).map(({
28009      node: endNode,
28010      offset: endOffset
28011    }) => {
28012      const rng = document.createRange();
28013      rng.setStart(startNode, startOffset);
28014      rng.setEnd(endNode, endOffset);
28015      return rng;
28016    }));
28017    const generatePathRangeFromRange = (dom, root, range, normalized = false) => generatePathRange(dom, root, range.startContainer, range.startOffset, range.endContainer, range.endOffset, normalized);
28018
28019    const cleanEmptyNodes = (dom, node, isRoot) => {
28020      if (node && dom.isEmpty(node) && !isRoot(node)) {
28021        const parent = node.parentNode;
28022        dom.remove(node, isText$b(node.firstChild) && isWhitespaceText(node.firstChild.data));
28023        cleanEmptyNodes(dom, parent, isRoot);
28024      }
28025    };
28026    const deleteRng = (dom, rng, isRoot, clean = true) => {
28027      const startParent = rng.startContainer.parentNode;
28028      const endParent = rng.endContainer.parentNode;
28029      rng.deleteContents();
28030      if (clean && !isRoot(rng.startContainer)) {
28031        if (isText$b(rng.startContainer) && rng.startContainer.data.length === 0) {
28032          dom.remove(rng.startContainer);
28033        }
28034        if (isText$b(rng.endContainer) && rng.endContainer.data.length === 0) {
28035          dom.remove(rng.endContainer);
28036        }
28037        cleanEmptyNodes(dom, startParent, isRoot);
28038        if (startParent !== endParent) {
28039          cleanEmptyNodes(dom, endParent, isRoot);
28040        }
28041      }
28042    };
28043    const getParentBlock = (editor, rng) => Optional.from(editor.dom.getParent(rng.startContainer, editor.dom.isBlock));
28044    const resolveFromDynamicPatterns = (patternSet, block, beforeText) => {
28045      const dynamicPatterns = patternSet.dynamicPatternsLookup({
28046        text: beforeText,
28047        block
28048      });
28049      return {
28050        ...patternSet,
28051        blockPatterns: getBlockPatterns(dynamicPatterns).concat(patternSet.blockPatterns),
28052        inlinePatterns: getInlinePatterns(dynamicPatterns).concat(patternSet.inlinePatterns)
28053      };
28054    };
28055    const getBeforeText = (dom, block, node, offset) => {
28056      const rng = dom.createRng();
28057      rng.setStart(block, 0);
28058      rng.setEnd(node, offset);
28059      return rng.toString();
28060    };
28061
28062    const newMarker = (dom, id) => dom.create('span', {
28063      'data-mce-type': 'bookmark',
28064      id
28065    });
28066    const rangeFromMarker = (dom, marker) => {
28067      const rng = dom.createRng();
28068      rng.setStartAfter(marker.start);
28069      rng.setEndBefore(marker.end);
28070      return rng;
28071    };
28072    const createMarker = (dom, markerPrefix, pathRange) => {
28073      const rng = resolvePathRange(dom.getRoot(), pathRange).getOrDie('Unable to resolve path range');
28074      const startNode = rng.startContainer;
28075      const endNode = rng.endContainer;
28076      const textEnd = rng.endOffset === 0 ? endNode : endNode.splitText(rng.endOffset);
28077      const textStart = rng.startOffset === 0 ? startNode : startNode.splitText(rng.startOffset);
28078      const startParentNode = textStart.parentNode;
28079      const endParentNode = textEnd.parentNode;
28080      return {
28081        prefix: markerPrefix,
28082        end: endParentNode.insertBefore(newMarker(dom, markerPrefix + '-end'), textEnd),
28083        start: startParentNode.insertBefore(newMarker(dom, markerPrefix + '-start'), textStart)
28084      };
28085    };
28086    const removeMarker = (dom, marker, isRoot) => {
28087      cleanEmptyNodes(dom, dom.get(marker.prefix + '-end'), isRoot);
28088      cleanEmptyNodes(dom, dom.get(marker.prefix + '-start'), isRoot);
28089    };
28090
28091    const isReplacementPattern = pattern => pattern.start.length === 0;
28092    const matchesPattern = patternContent => (element, offset) => {
28093      const text = element.data;
28094      const searchText = text.substring(0, offset);
28095      const startEndIndex = searchText.lastIndexOf(patternContent.charAt(patternContent.length - 1));
28096      const startIndex = searchText.lastIndexOf(patternContent);
28097      if (startIndex !== -1) {
28098        return startIndex + patternContent.length;
28099      } else if (startEndIndex !== -1) {
28100        return startEndIndex + 1;
28101      } else {
28102        return -1;
28103      }
28104    };
28105    const findPatternStartFromSpot = (dom, pattern, block, spot) => {
28106      const startPattern = pattern.start;
28107      const startSpot = repeatLeft(dom, spot.container, spot.offset, matchesPattern(startPattern), block);
28108      return startSpot.bind(spot => {
28109        var _a, _b;
28110        const startPatternIndex = (_b = (_a = block.textContent) === null || _a === void 0 ? void 0 : _a.indexOf(startPattern)) !== null && _b !== void 0 ? _b : -1;
28111        const isCompleteMatch = startPatternIndex !== -1 && spot.offset >= startPatternIndex + startPattern.length;
28112        if (isCompleteMatch) {
28113          const rng = dom.createRng();
28114          rng.setStart(spot.container, spot.offset - startPattern.length);
28115          rng.setEnd(spot.container, spot.offset);
28116          return Optional.some(rng);
28117        } else {
28118          const offset = spot.offset - startPattern.length;
28119          return scanLeft(spot.container, offset, block).map(nextSpot => {
28120            const rng = dom.createRng();
28121            rng.setStart(nextSpot.container, nextSpot.offset);
28122            rng.setEnd(spot.container, spot.offset);
28123            return rng;
28124          }).filter(rng => rng.toString() === startPattern).orThunk(() => findPatternStartFromSpot(dom, pattern, block, point(spot.container, 0)));
28125        }
28126      });
28127    };
28128    const findPatternStart = (dom, pattern, node, offset, block, requireGap = false) => {
28129      if (pattern.start.length === 0 && !requireGap) {
28130        const rng = dom.createRng();
28131        rng.setStart(node, offset);
28132        rng.setEnd(node, offset);
28133        return Optional.some(rng);
28134      }
28135      return textBefore(node, offset, block).bind(spot => {
28136        const start = findPatternStartFromSpot(dom, pattern, block, spot);
28137        return start.bind(startRange => {
28138          var _a;
28139          if (requireGap) {
28140            if (startRange.endContainer === spot.container && startRange.endOffset === spot.offset) {
28141              return Optional.none();
28142            } else if (spot.offset === 0 && ((_a = startRange.endContainer.textContent) === null || _a === void 0 ? void 0 : _a.length) === startRange.endOffset) {
28143              return Optional.none();
28144            }
28145          }
28146          return Optional.some(startRange);
28147        });
28148      });
28149    };
28150    const findPattern$3 = (editor, block, details, normalizedMatches) => {
28151      const dom = editor.dom;
28152      const root = dom.getRoot();
28153      const pattern = details.pattern;
28154      const endNode = details.position.container;
28155      const endOffset = details.position.offset;
28156      return scanLeft(endNode, endOffset - details.pattern.end.length, block).bind(spot => {
28157        const endPathRng = generatePathRange(dom, root, spot.container, spot.offset, endNode, endOffset, normalizedMatches);
28158        if (isReplacementPattern(pattern)) {
28159          return Optional.some({
28160            matches: [{
28161                pattern,
28162                startRng: endPathRng,
28163                endRng: endPathRng
28164              }],
28165            position: spot
28166          });
28167        } else {
28168          const resultsOpt = findPatternsRec(editor, details.remainingPatterns, spot.container, spot.offset, block, normalizedMatches);
28169          const results = resultsOpt.getOr({
28170            matches: [],
28171            position: spot
28172          });
28173          const pos = results.position;
28174          const start = findPatternStart(dom, pattern, pos.container, pos.offset, block, resultsOpt.isNone());
28175          return start.map(startRng => {
28176            const startPathRng = generatePathRangeFromRange(dom, root, startRng, normalizedMatches);
28177            return {
28178              matches: results.matches.concat([{
28179                  pattern,
28180                  startRng: startPathRng,
28181                  endRng: endPathRng
28182                }]),
28183              position: point(startRng.startContainer, startRng.startOffset)
28184            };
28185          });
28186        }
28187      });
28188    };
28189    const findPatternsRec = (editor, patterns, node, offset, block, normalizedMatches) => {
28190      const dom = editor.dom;
28191      return textBefore(node, offset, dom.getRoot()).bind(endSpot => {
28192        const text = getBeforeText(dom, block, node, offset);
28193        for (let i = 0; i < patterns.length; i++) {
28194          const pattern = patterns[i];
28195          if (!endsWith(text, pattern.end)) {
28196            continue;
28197          }
28198          const patternsWithoutCurrent = patterns.slice();
28199          patternsWithoutCurrent.splice(i, 1);
28200          const result = findPattern$3(editor, block, {
28201            pattern,
28202            remainingPatterns: patternsWithoutCurrent,
28203            position: endSpot
28204          }, normalizedMatches);
28205          if (result.isNone() && offset > 0) {
28206            return findPatternsRec(editor, patterns, node, offset - 1, block, normalizedMatches);
28207          }
28208          if (result.isSome()) {
28209            return result;
28210          }
28211        }
28212        return Optional.none();
28213      });
28214    };
28215    const applyPattern$2 = (editor, pattern, patternRange) => {
28216      editor.selection.setRng(patternRange);
28217      if (pattern.type === 'inline-format') {
28218        each$e(pattern.format, format => {
28219          editor.formatter.apply(format);
28220        });
28221      } else {
28222        editor.execCommand(pattern.cmd, false, pattern.value);
28223      }
28224    };
28225    const applyReplacementPattern = (editor, pattern, marker, isRoot) => {
28226      const markerRange = rangeFromMarker(editor.dom, marker);
28227      deleteRng(editor.dom, markerRange, isRoot);
28228      applyPattern$2(editor, pattern, markerRange);
28229    };
28230    const applyPatternWithContent = (editor, pattern, startMarker, endMarker, isRoot) => {
28231      const dom = editor.dom;
28232      const markerEndRange = rangeFromMarker(dom, endMarker);
28233      const markerStartRange = rangeFromMarker(dom, startMarker);
28234      deleteRng(dom, markerStartRange, isRoot);
28235      deleteRng(dom, markerEndRange, isRoot);
28236      const patternMarker = {
28237        prefix: startMarker.prefix,
28238        start: startMarker.end,
28239        end: endMarker.start
28240      };
28241      const patternRange = rangeFromMarker(dom, patternMarker);
28242      applyPattern$2(editor, pattern, patternRange);
28243    };
28244    const addMarkers = (dom, matches) => {
28245      const markerPrefix = generate$1('mce_textpattern');
28246      const matchesWithEnds = foldr(matches, (acc, match) => {
28247        const endMarker = createMarker(dom, markerPrefix + `_end${ acc.length }`, match.endRng);
28248        return acc.concat([{
28249            ...match,
28250            endMarker
28251          }]);
28252      }, []);
28253      return foldr(matchesWithEnds, (acc, match) => {
28254        const idx = matchesWithEnds.length - acc.length - 1;
28255        const startMarker = isReplacementPattern(match.pattern) ? match.endMarker : createMarker(dom, markerPrefix + `_start${ idx }`, match.startRng);
28256        return acc.concat([{
28257            ...match,
28258            startMarker
28259          }]);
28260      }, []);
28261    };
28262    const sortPatterns$1 = patterns => sort(patterns, (a, b) => b.end.length - a.end.length);
28263    const getBestMatches = (matches, matchesWithSortedPatterns) => {
28264      const hasSameMatches = forall(matches, match => exists(matchesWithSortedPatterns, sortedMatch => match.pattern.start === sortedMatch.pattern.start && match.pattern.end === sortedMatch.pattern.end));
28265      if (matches.length === matchesWithSortedPatterns.length) {
28266        if (hasSameMatches) {
28267          return matches;
28268        } else {
28269          return matchesWithSortedPatterns;
28270        }
28271      }
28272      return matches.length > matchesWithSortedPatterns.length ? matches : matchesWithSortedPatterns;
28273    };
28274    const findPatterns$2 = (editor, block, node, offset, patternSet, normalizedMatches) => {
28275      const matches = findPatternsRec(editor, patternSet.inlinePatterns, node, offset, block, normalizedMatches).fold(() => [], result => result.matches);
28276      const matchesWithSortedPatterns = findPatternsRec(editor, sortPatterns$1(patternSet.inlinePatterns), node, offset, block, normalizedMatches).fold(() => [], result => result.matches);
28277      return getBestMatches(matches, matchesWithSortedPatterns);
28278    };
28279    const applyMatches$2 = (editor, matches) => {
28280      if (matches.length === 0) {
28281        return;
28282      }
28283      const dom = editor.dom;
28284      const bookmark = editor.selection.getBookmark();
28285      const matchesWithMarkers = addMarkers(dom, matches);
28286      each$e(matchesWithMarkers, match => {
28287        const block = dom.getParent(match.startMarker.start, dom.isBlock);
28288        const isRoot = node => node === block;
28289        if (isReplacementPattern(match.pattern)) {
28290          applyReplacementPattern(editor, match.pattern, match.endMarker, isRoot);
28291        } else {
28292          applyPatternWithContent(editor, match.pattern, match.startMarker, match.endMarker, isRoot);
28293        }
28294        removeMarker(dom, match.endMarker, isRoot);
28295        removeMarker(dom, match.startMarker, isRoot);
28296      });
28297      editor.selection.moveToBookmark(bookmark);
28298    };
28299
28300    const stripPattern$1 = (dom, block, pattern) => {
28301      return textAfter(block, 0, block).map(spot => {
28302        const node = spot.container;
28303        scanRight(node, pattern.start.length, block).each(end => {
28304          const rng = dom.createRng();
28305          rng.setStart(node, 0);
28306          rng.setEnd(end.container, end.offset);
28307          deleteRng(dom, rng, e => e === block);
28308        });
28309        return node;
28310      });
28311    };
28312    const createApplyPattern = stripPattern => (editor, match) => {
28313      const dom = editor.dom;
28314      const pattern = match.pattern;
28315      const rng = resolvePathRange(dom.getRoot(), match.range).getOrDie('Unable to resolve path range');
28316      const isBlockFormatName = (name, formatter) => {
28317        const formatSet = formatter.get(name);
28318        return isArray$1(formatSet) && head(formatSet).exists(format => has$2(format, 'block'));
28319      };
28320      getParentBlock(editor, rng).each(block => {
28321        if (pattern.type === 'block-format') {
28322          if (isBlockFormatName(pattern.format, editor.formatter)) {
28323            editor.undoManager.transact(() => {
28324              stripPattern(editor.dom, block, pattern);
28325              editor.formatter.apply(pattern.format);
28326            });
28327          }
28328        } else if (pattern.type === 'block-command') {
28329          editor.undoManager.transact(() => {
28330            stripPattern(editor.dom, block, pattern);
28331            editor.execCommand(pattern.cmd, false, pattern.value);
28332          });
28333        }
28334      });
28335      return true;
28336    };
28337    const sortPatterns = patterns => sort(patterns, (a, b) => b.start.length - a.start.length);
28338    const findPattern$2 = predicate => (patterns, text) => {
28339      const sortedPatterns = sortPatterns(patterns);
28340      const nuText = text.replace(nbsp, ' ');
28341      return find$2(sortedPatterns, pattern => predicate(pattern, text, nuText));
28342    };
28343    const createFindPatterns = (findPattern, skipFullMatch) => (editor, block, patternSet, normalizedMatches, text) => {
28344      var _a;
28345      if (text === void 0) {
28346        text = (_a = block.textContent) !== null && _a !== void 0 ? _a : '';
28347      }
28348      const dom = editor.dom;
28349      const forcedRootBlock = getForcedRootBlock(editor);
28350      if (!dom.is(block, forcedRootBlock)) {
28351        return [];
28352      }
28353      return findPattern(patternSet.blockPatterns, text).map(pattern => {
28354        if (skipFullMatch && Tools.trim(text).length === pattern.start.length) {
28355          return [];
28356        }
28357        return [{
28358            pattern,
28359            range: generatePathRange(dom, dom.getRoot(), block, 0, block, 0, normalizedMatches)
28360          }];
28361      }).getOr([]);
28362    };
28363
28364    const startsWithSingleSpace = s => /^\s[^\s]/.test(s);
28365    const stripPattern = (dom, block, pattern) => {
28366      stripPattern$1(dom, block, pattern).each(node => {
28367        const text = SugarElement.fromDom(node);
28368        const textContent = get$3(text);
28369        if (startsWithSingleSpace(textContent)) {
28370          set(text, textContent.slice(1));
28371        }
28372      });
28373    };
28374    const applyPattern$1 = createApplyPattern(stripPattern);
28375    const findPattern$1 = findPattern$2((pattern, text, nuText) => text.indexOf(pattern.start) === 0 || nuText.indexOf(pattern.start) === 0);
28376    const findPatterns$1 = createFindPatterns(findPattern$1, true);
28377    const getMatches$1 = (editor, patternSet) => {
28378      const rng = editor.selection.getRng();
28379      return getParentBlock(editor, rng).map(block => {
28380        var _a;
28381        const offset = Math.max(0, rng.startOffset);
28382        const dynamicPatternSet = resolveFromDynamicPatterns(patternSet, block, (_a = block.textContent) !== null && _a !== void 0 ? _a : '');
28383        const inlineMatches = findPatterns$2(editor, block, rng.startContainer, offset, dynamicPatternSet, true);
28384        const blockMatches = findPatterns$1(editor, block, dynamicPatternSet, true);
28385        return {
28386          inlineMatches,
28387          blockMatches
28388        };
28389      }).filter(({inlineMatches, blockMatches}) => blockMatches.length > 0 || inlineMatches.length > 0);
28390    };
28391    const applyMatches$1 = (editor, matches) => {
28392      if (matches.length === 0) {
28393        return;
28394      }
28395      const bookmark = editor.selection.getBookmark();
28396      each$e(matches, match => applyPattern$1(editor, match));
28397      editor.selection.moveToBookmark(bookmark);
28398    };
28399
28400    const applyPattern = createApplyPattern(stripPattern$1);
28401    const findPattern = findPattern$2((pattern, text, nuText) => text === pattern.start || nuText === pattern.start);
28402    const findPatterns = createFindPatterns(findPattern, false);
28403    const getMatches = (editor, patternSet) => {
28404      const rng = editor.selection.getRng();
28405      return getParentBlock(editor, rng).map(block => {
28406        const offset = Math.max(0, rng.startOffset);
28407        const beforeText = getBeforeText(editor.dom, block, rng.startContainer, offset);
28408        const dynamicPatternSet = resolveFromDynamicPatterns(patternSet, block, beforeText);
28409        return findPatterns(editor, block, dynamicPatternSet, false, beforeText);
28410      }).filter(matches => matches.length > 0);
28411    };
28412    const applyMatches = (editor, matches) => {
28413      each$e(matches, match => applyPattern(editor, match));
28414    };
28415
28416    const handleEnter = (editor, patternSet) => getMatches$1(editor, patternSet).fold(never, ({inlineMatches, blockMatches}) => {
28417      editor.undoManager.add();
28418      editor.undoManager.extra(() => {
28419        editor.execCommand('mceInsertNewLine');
28420      }, () => {
28421        insert$5(editor);
28422        applyMatches$2(editor, inlineMatches);
28423        applyMatches$1(editor, blockMatches);
28424        const range = editor.selection.getRng();
28425        const spot = textBefore(range.startContainer, range.startOffset, editor.dom.getRoot());
28426        editor.execCommand('mceInsertNewLine');
28427        spot.each(s => {
28428          const node = s.container;
28429          if (node.data.charAt(s.offset - 1) === zeroWidth) {
28430            node.deleteData(s.offset - 1, 1);
28431            cleanEmptyNodes(editor.dom, node.parentNode, e => e === editor.dom.getRoot());
28432          }
28433        });
28434      });
28435      return true;
28436    });
28437    const handleInlineKey = (editor, patternSet) => {
28438      const rng = editor.selection.getRng();
28439      getParentBlock(editor, rng).map(block => {
28440        const offset = Math.max(0, rng.startOffset - 1);
28441        const beforeText = getBeforeText(editor.dom, block, rng.startContainer, offset);
28442        const dynamicPatternSet = resolveFromDynamicPatterns(patternSet, block, beforeText);
28443        const inlineMatches = findPatterns$2(editor, block, rng.startContainer, offset, dynamicPatternSet, false);
28444        if (inlineMatches.length > 0) {
28445          editor.undoManager.transact(() => {
28446            applyMatches$2(editor, inlineMatches);
28447          });
28448        }
28449      });
28450    };
28451    const handleBlockPatternOnSpace = (editor, patternSet) => getMatches(editor, patternSet).fold(never, matches => {
28452      editor.undoManager.transact(() => {
28453        applyMatches(editor, matches);
28454      });
28455      return true;
28456    });
28457    const checkKeyEvent = (codes, event, predicate) => {
28458      for (let i = 0; i < codes.length; i++) {
28459        if (predicate(codes[i], event)) {
28460          return true;
28461        }
28462      }
28463      return false;
28464    };
28465    const checkKeyCode = (codes, event) => checkKeyEvent(codes, event, (code, event) => {
28466      return code === event.keyCode && !VK.modifierPressed(event);
28467    });
28468    const checkCharCode = (chars, event) => checkKeyEvent(chars, event, (chr, event) => {
28469      return chr.charCodeAt(0) === event.charCode;
28470    });
28471
28472    const setup$2 = editor => {
28473      const charCodes = [
28474        ',',
28475        '.',
28476        ';',
28477        ':',
28478        '!',
28479        '?'
28480      ];
28481      const keyCodes = [32];
28482      const getPatternSet = () => createPatternSet(getTextPatterns(editor)
vendor: 2,621 bytes, lines 28482-28543
28482.filter(pattern => {
28483        if (pattern.type === 'inline-command' || pattern.type === 'block-command') {
28484          return editor.queryCommandSupported(pattern.cmd);
28485        }
28486        return true;
28487      }), getTextPatternsLookup(editor));
28488      const hasDynamicPatterns = () => hasTextPatternsLookup(editor);
28489      editor.on('keydown', e => {
28490        if (e.keyCode === 13 && !VK.modifierPressed(e) && editor.selection.isCollapsed() && editor.selection.isEditable()) {
28491          const patternSet = filterByTrigger(getPatternSet(), 'enter');
28492          const hasPatterns = patternSet.inlinePatterns.length > 0 || patternSet.blockPatterns.length > 0 || hasDynamicPatterns();
28493          if (hasPatterns && handleEnter(editor, patternSet)) {
28494            e.preventDefault();
28495          }
28496        }
28497      }, true);
28498      editor.on('keydown', e => {
28499        if (e.keyCode === 32 && editor.selection.isCollapsed() && editor.selection.isEditable()) {
28500          const patternSet = filterByTrigger(getPatternSet(), 'space');
28501          const hasPatterns = patternSet.blockPatterns.length > 0 || hasDynamicPatterns();
28502          if (hasPatterns && handleBlockPatternOnSpace(editor, patternSet)) {
28503            e.preventDefault();
28504          }
28505        }
28506      }, true);
28507      const handleInlineTrigger = () => {
28508        if (editor.selection.isCollapsed() && editor.selection.isEditable()) {
28509          const patternSet = filterByTrigger(getPatternSet(), 'space');
28510          const hasPatterns = patternSet.inlinePatterns.length > 0 || hasDynamicPatterns();
28511          if (hasPatterns) {
28512            handleInlineKey(editor, patternSet);
28513          }
28514        }
28515      };
28516      editor.on('keyup', e => {
28517        if (checkKeyCode(keyCodes, e)) {
28518          handleInlineTrigger();
28519        }
28520      });
28521      editor.on('keypress', e => {
28522        if (checkCharCode(charCodes, e)) {
28523          Delay.setEditorTimeout(editor, handleInlineTrigger);
28524        }
28525      });
28526    };
28527
28528    const setup$1 = editor => {
28529      setup$2(editor);
28530    };
28531
28532    const Quirks = editor => {
28533      const each = Tools.each;
28534      const BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, parser = editor.parser;
28535      const browser = Env.browser;
28536      const isGecko = browser.isFirefox();
28537      const isWebKit = browser.isChromium() || browser.isSafari();
28538      const isiOS = Env.deviceType.isiPhone() || Env.deviceType.isiPad();
28539      const isMac = Env.os.isMacOS() || Env.os.isiOS();
28540      const setEditorCommandState = (cmd, state) => {
28541        try {
28542          editor.getDoc().execCommand(cmd, false, String(state));
28543        } catch (_a
vendor: 13,582 bytes, lines 28543-28922
28543) {
28544        }
28545      };
28546      const isDefaultPrevented = e => {
28547        return e.isDefaultPrevented();
28548      };
28549      const emptyEditorWhenDeleting = () => {
28550        const serializeRng = rng => {
28551          const body = dom.create('body');
28552          const contents = rng.cloneContents();
28553          body.appendChild(contents);
28554          return selection.serializer.serialize(body, { format: 'html' });
28555        };
28556        const allContentsSelected = rng => {
28557          const selection = serializeRng(rng);
28558          const allRng = dom.createRng();
28559          allRng.selectNode(editor.getBody());
28560          const allSelection = serializeRng(allRng);
28561          return selection === allSelection;
28562        };
28563        editor.on('keydown', e => {
28564          const keyCode = e.keyCode;
28565          if (!isDefaultPrevented(e) && (keyCode === DELETE || keyCode === BACKSPACE) && editor.selection.isEditable()) {
28566            const isCollapsed = editor.selection.isCollapsed();
28567            const body = editor.getBody();
28568            if (isCollapsed && !isEmptyNode(editor.schema, body)) {
28569              return;
28570            }
28571            if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
28572              return;
28573            }
28574            e.preventDefault();
28575            editor.setContent('');
28576            if (body.firstChild && dom.isBlock(body.firstChild)) {
28577              editor.selection.setCursorLocation(body.firstChild, 0);
28578            } else {
28579              editor.selection.setCursorLocation(body, 0);
28580            }
28581            editor.nodeChanged();
28582          }
28583        });
28584      };
28585      const selectAll = () => {
28586        editor.shortcuts.add('meta+a', null, 'SelectAll');
28587      };
28588      const documentElementEditingFocus = () => {
28589        if (!editor.inline) {
28590          dom.bind(editor.getDoc(), 'mousedown mouseup', e => {
28591            let rng;
28592            if (e.target === editor.getDoc().documentElement) {
28593              rng = selection.getRng();
28594              editor.getBody().focus();
28595              if (e.type === 'mousedown') {
28596                if (isCaretContainer$2(rng.startContainer)) {
28597                  return;
28598                }
28599                selection.placeCaretAt(e.clientX, e.clientY);
28600              } else {
28601                selection.setRng(rng);
28602              }
28603            }
28604          });
28605        }
28606      };
28607      const removeHrOnBackspace = () => {
28608        editor.on('keydown', e => {
28609          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
28610            if (!editor.getBody().getElementsByTagName('hr').length) {
28611              return;
28612            }
28613            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
28614              const node = selection.getNode();
28615              const previousSibling = node.previousSibling;
28616              if (node.nodeName === 'HR') {
28617                dom.remove(node);
28618                e.preventDefault();
28619                return;
28620              }
28621              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'hr') {
28622                dom.remove(previousSibling);
28623                e.preventDefault();
28624              }
28625            }
28626          }
28627        });
28628      };
28629      const focusBody = () => {
28630        if (!Range.prototype.getClientRects) {
28631          editor.on('mousedown', e => {
28632            if (!isDefaultPrevented(e) && e.target.nodeName === 'HTML') {
28633              const body = editor.getBody();
28634              body.blur();
28635              Delay.setEditorTimeout(editor, () => {
28636                body.focus();
28637              });
28638            }
28639          });
28640        }
28641      };
28642      const selectControlElements = () => {
28643        const visualAidsAnchorClass = getVisualAidsAnchorClass(editor);
28644        editor.on('click', e => {
28645          const target = e.target;
28646          if (/^(IMG|HR)$/.test(target.nodeName) && dom.isEditable(target)) {
28647            e.preventDefault();
28648            editor.selection.select(target);
28649            editor.nodeChanged();
28650          }
28651          if (target.nodeName === 'A' && dom.hasClass(target, visualAidsAnchorClass) && target.childNodes.length === 0 && dom.isEditable(target.parentNode)) {
28652            e.preventDefault();
28653            selection.select(target);
28654          }
28655        });
28656      };
28657      const removeStylesWhenDeletingAcrossBlockElements = () => {
28658        const getAttributeApplyFunction = () => {
28659          const template = dom.getAttribs(selection.getStart().cloneNode(false));
28660          return () => {
28661            const target = selection.getStart();
28662            if (target !== editor.getBody()) {
28663              dom.setAttrib(target, 'style', null);
28664              each(template, attr => {
28665                target.setAttributeNode(attr.cloneNode(true));
28666              });
28667            }
28668          };
28669        };
28670        const isSelectionAcrossElements = () => {
28671          return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) !== dom.getParent(selection.getEnd(), dom.isBlock);
28672        };
28673        editor.on('keypress', e => {
28674          let applyAttributes;
28675          if (!isDefaultPrevented(e) && (e.keyCode === 8 || e.keyCode === 46) && isSelectionAcrossElements()) {
28676            applyAttributes = getAttributeApplyFunction();
28677            editor.getDoc().execCommand('delete', false);
28678            applyAttributes();
28679            e.preventDefault();
28680            return false;
28681          } else {
28682            return true;
28683          }
28684        });
28685        dom.bind(editor.getDoc(), 'cut', e => {
28686          if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
28687            const applyAttributes = getAttributeApplyFunction();
28688            Delay.setEditorTimeout(editor, () => {
28689              applyAttributes();
28690            });
28691          }
28692        });
28693      };
28694      const disableBackspaceIntoATable = () => {
28695        editor.on('keydown', e => {
28696          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
28697            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
28698              const previousSibling = selection.getNode().previousSibling;
28699              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'table') {
28700                e.preventDefault();
28701                return false;
28702              }
28703            }
28704          }
28705          return true;
28706        });
28707      };
28708      const removeBlockQuoteOnBackSpace = () => {
28709        editor.on('keydown', e => {
28710          if (isDefaultPrevented(e) || e.keyCode !== VK.BACKSPACE) {
28711            return;
28712          }
28713          let rng = selection.getRng();
28714          const container = rng.startContainer;
28715          const offset = rng.startOffset;
28716          const root = dom.getRoot();
28717          let parent = container;
28718          if (!rng.collapsed || offset !== 0) {
28719            return;
28720          }
28721          while (parent.parentNode && parent.parentNode.firstChild === parent && parent.parentNode !== root) {
28722            parent = parent.parentNode;
28723          }
28724          if (parent.nodeName === 'BLOCKQUOTE') {
28725            editor.formatter.toggle('blockquote', undefined, parent);
28726            rng = dom.createRng();
28727            rng.setStart(container, 0);
28728            rng.setEnd(container, 0);
28729            selection.setRng(rng);
28730          }
28731        });
28732      };
28733      const setGeckoEditingOptions = () => {
28734        const setOpts = () => {
28735          setEditorCommandState('StyleWithCSS', false);
28736          setEditorCommandState('enableInlineTableEditing', false);
28737          if (!getObjectResizing(editor)) {
28738            setEditorCommandState('enableObjectResizing', false);
28739          }
28740        };
28741        if (!isReadOnly$1(editor)) {
28742          editor.on('BeforeExecCommand mousedown', setOpts);
28743        }
28744      };
28745      const addBrAfterLastLinks = () => {
28746        const fixLinks = () => {
28747          each(dom.select('a:not([data-mce-block])'), node => {
28748            var _a;
28749            let parentNode = node.parentNode;
28750            const root = dom.getRoot();
28751            if ((parentNode === null || parentNode === void 0 ? void 0 : parentNode.lastChild) === node) {
28752              while (parentNode && !dom.isBlock(parentNode)) {
28753                if (((_a = parentNode.parentNode) === null || _a === void 0 ? void 0 : _a.lastChild) !== parentNode || parentNode === root) {
28754                  return;
28755                }
28756                parentNode = parentNode.parentNode;
28757              }
28758              dom.add(parentNode, 'br', { 'data-mce-bogus': 1 });
28759            }
28760          });
28761        };
28762        editor.on('SetContent ExecCommand', e => {
28763          if (e.type === 'setcontent' || e.command === 'mceInsertLink') {
28764            fixLinks();
28765          }
28766        });
28767      };
28768      const setDefaultBlockType = () => {
28769        editor.on('init', () => {
28770          setEditorCommandState('DefaultParagraphSeparator', getForcedRootBlock(editor));
28771        });
28772      };
28773      const isAllContentSelected = editor => {
28774        const body = editor.getBody();
28775        const rng = editor.selection.getRng();
28776        return rng.startContainer === rng.endContainer && rng.startContainer === body && rng.startOffset === 0 && rng.endOffset === body.childNodes.length;
28777      };
28778      const normalizeSelection = () => {
28779        editor.on('keyup focusin mouseup', e => {
28780          if (!VK.modifierPressed(e) && !isAllContentSelected(editor)) {
28781            selection.normalize();
28782          }
28783        }, true);
28784      };
28785      const showBrokenImageIcon = () => {
28786        editor.contentStyles.push('img:-moz-broken {' + '-moz-force-broken-image-icon:1;' + 'min-width:24px;' + 'min-height:24px' + '}');
28787      };
28788      const restoreFocusOnKeyDown = () => {
28789        if (!editor.inline) {
28790          editor.on('keydown', () => {
28791            if (document.activeElement === document.body) {
28792              editor.getWin().focus();
28793            }
28794          });
28795        }
28796      };
28797      const bodyHeight = () => {
28798        if (!editor.inline) {
28799          editor.contentStyles.push('body {min-height: 150px}');
28800          editor.on('click', e => {
28801            let rng;
28802            if (e.target.nodeName === 'HTML') {
28803              rng = editor.selection.getRng();
28804              editor.getBody().focus();
28805              editor.selection.setRng(rng);
28806              editor.selection.normalize();
28807              editor.nodeChanged();
28808            }
28809          });
28810        }
28811      };
28812      const blockCmdArrowNavigation = () => {
28813        if (isMac) {
28814          editor.on('keydown', e => {
28815            if (VK.metaKeyPressed(e) && !e.shiftKey && (e.keyCode === 37 || e.keyCode === 39)) {
28816              e.preventDefault();
28817              const selection = editor.selection.getSel();
28818              selection.modify('move', e.keyCode === 37 ? 'backward' : 'forward', 'lineboundary');
28819            }
28820          });
28821        }
28822      };
28823      const tapLinksAndImages = () => {
28824        editor.on('click', e => {
28825          let elm = e.target;
28826          do {
28827            if (elm.tagName === 'A') {
28828              e.preventDefault();
28829              return;
28830            }
28831          } while (elm = elm.parentNode);
28832        });
28833        editor.contentStyles.push('.mce-content-body {-webkit-touch-callout: none}');
28834      };
28835      const blockFormSubmitInsideEditor = () => {
28836        editor.on('init', () => {
28837          editor.dom.bind(editor.getBody(), 'submit', e => {
28838            e.preventDefault();
28839          });
28840        });
28841      };
28842      const removeAppleInterchangeBrs = () => {
28843        parser.addNodeFilter('br', nodes => {
28844          let i = nodes.length;
28845          while (i--) {
28846            if (nodes[i].attr('class') === 'Apple-interchange-newline') {
28847              nodes[i].remove();
28848            }
28849          }
28850        });
28851      };
28852      const refreshContentEditable = noop;
28853      const isHidden = () => {
28854        if (!isGecko || editor.removed) {
28855          return false;
28856        }
28857        const sel = editor.selection.getSel();
28858        return !sel || !sel.rangeCount || sel.rangeCount === 0;
28859      };
28860      const setupRtc = () => {
28861        if (isWebKit) {
28862          documentElementEditingFocus();
28863          selectControlElements();
28864          blockFormSubmitInsideEditor();
28865          selectAll();
28866          if (isiOS) {
28867            restoreFocusOnKeyDown();
28868            bodyHeight();
28869            tapLinksAndImages();
28870          }
28871        }
28872        if (isGecko) {
28873          focusBody();
28874          setGeckoEditingOptions();
28875          showBrokenImageIcon();
28876          blockCmdArrowNavigation();
28877        }
28878      };
28879      const setup = () => {
28880        removeBlockQuoteOnBackSpace();
28881        emptyEditorWhenDeleting();
28882        if (!Env.windowsPhone) {
28883          normalizeSelection();
28884        }
28885        if (isWebKit) {
28886          documentElementEditingFocus();
28887          selectControlElements();
28888          setDefaultBlockType();
28889          blockFormSubmitInsideEditor();
28890          disableBackspaceIntoATable();
28891          removeAppleInterchangeBrs();
28892          if (isiOS) {
28893            restoreFocusOnKeyDown();
28894            bodyHeight();
28895            tapLinksAndImages();
28896          } else {
28897            selectAll();
28898          }
28899        }
28900        if (isGecko) {
28901          removeHrOnBackspace();
28902          focusBody();
28903          removeStylesWhenDeletingAcrossBlockElements();
28904          setGeckoEditingOptions();
28905          addBrAfterLastLinks();
28906          showBrokenImageIcon();
28907          blockCmdArrowNavigation();
28908          disableBackspaceIntoATable();
28909        }
28910      };
28911      if (isRtc(editor)) {
28912        setupRtc();
28913      } else {
28914        setup();
28915      }
28916      return {
28917        refreshContentEditable,
28918        isHidden
28919      };
28920    };
28921
28922    const 
vendor: 15,561 bytes, lines 28922-29330
28922isGplKey = key => key.toLowerCase() === 'gpl';
28923    const isValidGeneratedKey = key => key.length >= 64 && key.length <= 255;
28924    const validateLicenseKey = key => isGplKey(key) || isValidGeneratedKey(key) ? 'VALID' : 'INVALID';
28925    const validateEditorLicenseKey = editor => {
28926      const licenseKey = getLicenseKey(editor);
28927      const hasApiKey = isString(getApiKey(editor));
28928      if (!hasApiKey && (isUndefined(licenseKey) || validateLicenseKey(licenseKey) === 'INVALID')) {
28929        console.warn(`TinyMCE is running in evaluation mode. Provide a valid license key or add license_key: 'gpl' to the init config to agree to the open source license terms. Read more at https://www.tiny.cloud/license-key/`);
28930      }
28931    };
28932
28933    const DOM$6 = DOMUtils.DOM;
28934    const appendStyle = (editor, text) => {
28935      const body = SugarElement.fromDom(editor.getBody());
28936      const container = getStyleContainer(getRootNode(body));
28937      const style = SugarElement.fromTag('style');
28938      set$4(style, 'type', 'text/css');
28939      append$1(style, SugarElement.fromText(text));
28940      append$1(container, style);
28941      editor.on('remove', () => {
28942        remove$4(style);
28943      });
28944    };
28945    const getRootName = editor => editor.inline ? editor.getElement().nodeName.toLowerCase() : undefined;
28946    const removeUndefined = obj => filter$4(obj, v => isUndefined(v) === false);
28947    const mkParserSettings = editor => {
28948      const getOption = editor.options.get;
28949      const blobCache = editor.editorUpload.blobCache;
28950      return removeUndefined({
28951        allow_conditional_comments: getOption('allow_conditional_comments'),
28952        allow_html_data_urls: getOption('allow_html_data_urls'),
28953        allow_svg_data_urls: getOption('allow_svg_data_urls'),
28954        allow_html_in_named_anchor: getOption('allow_html_in_named_anchor'),
28955        allow_script_urls: getOption('allow_script_urls'),
28956        allow_mathml_annotation_encodings: getOption('allow_mathml_annotation_encodings'),
28957        allow_unsafe_link_target: getOption('allow_unsafe_link_target'),
28958        convert_unsafe_embeds: getOption('convert_unsafe_embeds'),
28959        convert_fonts_to_spans: getOption('convert_fonts_to_spans'),
28960        fix_list_elements: getOption('fix_list_elements'),
28961        font_size_legacy_values: getOption('font_size_legacy_values'),
28962        forced_root_block: getOption('forced_root_block'),
28963        forced_root_block_attrs: getOption('forced_root_block_attrs'),
28964        preserve_cdata: getOption('preserve_cdata'),
28965        inline_styles: getOption('inline_styles'),
28966        root_name: getRootName(editor),
28967        sandbox_iframes: getOption('sandbox_iframes'),
28968        sandbox_iframes_exclusions: getSandboxIframesExclusions(editor),
28969        sanitize: getOption('xss_sanitization'),
28970        validate: true,
28971        blob_cache: blobCache,
28972        document: editor.getDoc()
28973      });
28974    };
28975    const mkSchemaSettings = editor => {
28976      const getOption = editor.options.get;
28977      return removeUndefined({
28978        custom_elements: getOption('custom_elements'),
28979        extended_valid_elements: getOption('extended_valid_elements'),
28980        invalid_elements: getOption('invalid_elements'),
28981        invalid_styles: getOption('invalid_styles'),
28982        schema: getOption('schema'),
28983        valid_children: getOption('valid_children'),
28984        valid_classes: getOption('valid_classes'),
28985        valid_elements: getOption('valid_elements'),
28986        valid_styles: getOption('valid_styles'),
28987        verify_html: getOption('verify_html'),
28988        padd_empty_block_inline_children: getOption('format_empty_lines')
28989      });
28990    };
28991    const mkSerializerSettings = editor => {
28992      const getOption = editor.options.get;
28993      return {
28994        ...mkParserSettings(editor),
28995        ...mkSchemaSettings(editor),
28996        ...removeUndefined({
28997          remove_trailing_brs: getOption('remove_trailing_brs'),
28998          pad_empty_with_br: getOption('pad_empty_with_br'),
28999          url_converter: getOption('url_converter'),
29000          url_converter_scope: getOption('url_converter_scope'),
29001          element_format: getOption('element_format'),
29002          entities: getOption('entities'),
29003          entity_encoding: getOption('entity_encoding'),
29004          indent: getOption('indent'),
29005          indent_after: getOption('indent_after'),
29006          indent_before: getOption('indent_before')
29007        })
29008      };
29009    };
29010    const createParser = editor => {
29011      const parser = DomParser(mkParserSettings(editor), editor.schema);
29012      parser.addAttributeFilter('src,href,style,tabindex', (nodes, name) => {
29013        const dom = editor.dom;
29014        const internalName = 'data-mce-' + name;
29015        let i = nodes.length;
29016        while (i--) {
29017          const node = nodes[i];
29018          let value = node.attr(name);
29019          if (value && !node.attr(internalName)) {
29020            if (value.indexOf('data:') === 0 || value.indexOf('blob:') === 0) {
29021              continue;
29022            }
29023            if (name === 'style') {
29024              value = dom.serializeStyle(dom.parseStyle(value), node.name);
29025              if (!value.length) {
29026                value = null;
29027              }
29028              node.attr(internalName, value);
29029              node.attr(name, value);
29030            } else if (name === 'tabindex') {
29031              node.attr(internalName, value);
29032              node.attr(name, null);
29033            } else {
29034              node.attr(internalName, editor.convertURL(value, name, node.name));
29035            }
29036          }
29037        }
29038      });
29039      parser.addNodeFilter('script', nodes => {
29040        let i = nodes.length;
29041        while (i--) {
29042          const node = nodes[i];
29043          const type = node.attr('type') || 'no/type';
29044          if (type.indexOf('mce-') !== 0) {
29045            node.attr('type', 'mce-' + type);
29046          }
29047        }
29048      });
29049      if (shouldPreserveCData(editor)) {
29050        parser.addNodeFilter('#cdata', nodes => {
29051          var _a;
29052          let i = nodes.length;
29053          while (i--) {
29054            const node = nodes[i];
29055            node.type = 8;
29056            node.name = '#comment';
29057            node.value = '[CDATA[' + editor.dom.encode((_a = node.value) !== null && _a !== void 0 ? _a : '') + ']]';
29058          }
29059        });
29060      }
29061      parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', nodes => {
29062        let i = nodes.length;
29063        const nonEmptyElements = editor.schema.getNonEmptyElements();
29064        while (i--) {
29065          const node = nodes[i];
29066          if (node.isEmpty(nonEmptyElements) && node.getAll('br').length === 0) {
29067            node.append(new AstNode('br', 1));
29068          }
29069        }
29070      });
29071      return parser;
29072    };
29073    const autoFocus = editor => {
29074      const autoFocus = getAutoFocus(editor);
29075      if (autoFocus) {
29076        Delay.setEditorTimeout(editor, () => {
29077          let focusEditor;
29078          if (autoFocus === true) {
29079            focusEditor = editor;
29080          } else {
29081            focusEditor = editor.editorManager.get(autoFocus);
29082          }
29083          if (focusEditor && !focusEditor.destroyed) {
29084            focusEditor.focus();
29085            focusEditor.selection.scrollIntoView();
29086          }
29087        }, 100);
29088      }
29089    };
29090    const moveSelectionToFirstCaretPosition = editor => {
29091      const root = editor.dom.getRoot();
29092      if (!editor.inline && (!hasAnyRanges(editor) || editor.selection.getStart(true) === root)) {
29093        firstPositionIn(root).each(pos => {
29094          const node = pos.getNode();
29095          const caretPos = isTable$2(node) ? firstPositionIn(node).getOr(pos) : pos;
29096          editor.selection.setRng(caretPos.toRange());
29097        });
29098      }
29099    };
29100    const initEditor = editor => {
29101      editor.bindPendingEventDelegates();
29102      editor.initialized = true;
29103      fireInit(editor);
29104      editor.focus(true);
29105      moveSelectionToFirstCaretPosition(editor);
29106      editor.nodeChanged({ initial: true });
29107      const initInstanceCallback = getInitInstanceCallback(editor);
29108      if (isFunction(initInstanceCallback)) {
29109        initInstanceCallback.call(editor, editor);
29110      }
29111      autoFocus(editor);
29112      if (isDisabled(editor)) {
29113        toggleDisabled(editor, true);
29114      }
29115    };
29116    const getStyleSheetLoader$1 = editor => editor.inline ? editor.ui.styleSheetLoader : editor.dom.styleSheetLoader;
29117    const makeStylesheetLoadingPromises = (editor, css, framedFonts) => {
29118      const {
29119        pass: bundledCss,
29120        fail: normalCss
29121      } = partition$2(css, name => tinymce.Resource.has(toContentSkinResourceName(name)));
29122      const bundledPromises = bundledCss.map(url => {
29123        const css = tinymce.Resource.get(toContentSkinResourceName(url));
29124        if (isString(css)) {
29125          return Promise.resolve(getStyleSheetLoader$1(editor).loadRawCss(url, css));
29126        }
29127        return Promise.resolve();
29128      });
29129      const promises = [
29130        ...bundledPromises,
29131        getStyleSheetLoader$1(editor).loadAll(normalCss)
29132      ];
29133      if (editor.inline) {
29134        return promises;
29135      } else {
29136        return promises.concat([editor.ui.styleSheetLoader.loadAll(framedFonts)]);
29137      }
29138    };
29139    const loadContentCss = editor => {
29140      const styleSheetLoader = getStyleSheetLoader$1(editor);
29141      const fontCss = getFontCss(editor);
29142      const css = editor.contentCSS;
29143      const removeCss = () => {
29144        styleSheetLoader.unloadAll(css);
29145        if (!editor.inline) {
29146          editor.ui.styleSheetLoader.unloadAll(fontCss);
29147        }
29148      };
29149      const loaded = () => {
29150        if (editor.removed) {
29151          removeCss();
29152        } else {
29153          editor.on('remove', removeCss);
29154        }
29155      };
29156      if (editor.contentStyles.length > 0) {
29157        let contentCssText = '';
29158        Tools.each(editor.contentStyles, style => {
29159          contentCssText += style + '\r\n';
29160        });
29161        editor.dom.addStyle(contentCssText);
29162      }
29163      const allStylesheets = Promise.all(makeStylesheetLoadingPromises(editor, css, fontCss)).then(loaded).catch(loaded);
29164      const contentStyle = getContentStyle(editor);
29165      if (contentStyle) {
29166        appendStyle(editor, contentStyle);
29167      }
29168      return allStylesheets;
29169    };
29170    const preInit = editor => {
29171      const doc = editor.getDoc(), body = editor.getBody();
29172      firePreInit(editor);
29173      if (!shouldBrowserSpellcheck(editor)) {
29174        doc.body.spellcheck = false;
29175        DOM$6.setAttrib(body, 'spellcheck', 'false');
29176      }
29177      editor.quirks = Quirks(editor);
29178      firePostRender(editor);
29179      const directionality = getDirectionality(editor);
29180      if (directionality !== undefined) {
29181        body.dir = directionality;
29182      }
29183      const protect = getProtect(editor);
29184      if (protect) {
29185        editor.on('BeforeSetContent', e => {
29186          Tools.each(protect, pattern => {
29187            e.content = e.content.replace(pattern, str => {
29188              return '<!--mce:protected ' + escape(str) + '-->';
29189            });
29190          });
29191        });
29192      }
29193      editor.on('SetContent', () => {
29194        editor.addVisual(editor.getBody());
29195      });
29196      editor.on('compositionstart compositionend', e => {
29197        editor.composing = e.type === 'compositionstart';
29198      });
29199    };
29200    const loadInitialContent = editor => {
29201      if (!isRtc(editor)) {
29202        editor.load({
29203          initial: true,
29204          format: 'html'
29205        });
29206      }
29207      editor.startContent = editor.getContent({ format: 'raw' });
29208    };
29209    const initEditorWithInitialContent = editor => {
29210      if (editor.removed !== true) {
29211        loadInitialContent(editor);
29212        initEditor(editor);
29213      }
29214    };
29215    const startProgress = editor => {
29216      let canceled = false;
29217      const progressTimeout = setTimeout(() => {
29218        if (!canceled) {
29219          editor.setProgressState(true);
29220        }
29221      }, 500);
29222      return () => {
29223        clearTimeout(progressTimeout);
29224        canceled = true;
29225        editor.setProgressState(false);
29226      };
29227    };
29228    const contentBodyLoaded = editor => {
29229      const targetElm = editor.getElement();
29230      let doc = editor.getDoc();
29231      if (editor.inline) {
29232        DOM$6.addClass(targetElm, 'mce-content-body');
29233        editor.contentDocument = doc = document;
29234        editor.contentWindow = window;
29235        editor.bodyElement = targetElm;
29236        editor.contentAreaContainer = targetElm;
29237      }
29238      const body = editor.getBody();
29239      body.disabled = true;
29240      editor.readonly = isReadOnly$1(editor);
29241      editor._editableRoot = hasEditableRoot$1(editor);
29242      if (!isDisabled$1(editor) && editor.hasEditableRoot()) {
29243        if (editor.inline && DOM$6.getStyle(body, 'position', true) === 'static') {
29244          body.style.position = 'relative';
29245        }
29246        body.contentEditable = 'true';
29247      }
29248      body.disabled = false;
29249      editor.editorUpload = EditorUpload(editor);
29250      editor.schema = Schema(mkSchemaSettings(editor));
29251      editor.dom = DOMUtils(doc, {
29252        keep_values: true,
29253        url_converter: editor.convertURL,
29254        url_converter_scope: editor,
29255        update_styles: true,
29256        root_element: editor.inline ? editor.getBody() : null,
29257        collect: editor.inline,
29258        schema: editor.schema,
29259        contentCssCors: shouldUseContentCssCors(editor),
29260        referrerPolicy: getReferrerPolicy(editor),
29261        onSetAttrib: e => {
29262          editor.dispatch('SetAttrib', e);
29263        }
29264      });
29265      editor.parser = createParser(editor);
29266      editor.serializer = DomSerializer(mkSerializerSettings(editor), editor);
29267      editor.selection = EditorSelection(editor.dom, editor.getWin(), editor.serializer, editor);
29268      editor.annotator = Annotator(editor);
29269      editor.formatter = Formatter(editor);
29270      editor.undoManager = UndoManager(editor);
29271      editor._nodeChangeDispatcher = new NodeChange(editor);
29272      editor._selectionOverrides = SelectionOverrides(editor);
29273      setup$p(editor);
29274      setup$6(editor);
29275      setup$n(editor);
29276      if (!isRtc(editor)) {
29277        setup$5(editor);
29278        setup$1(editor);
29279      }
29280      const caret = setup$b(editor);
29281      setup$q(editor, caret);
29282      setup$o(editor);
29283      setup$r(editor);
29284      setup$7(editor);
29285      const setupRtcThunk = setup$t(editor);
29286      preInit(editor);
29287      validateEditorLicenseKey(editor);
29288      setupRtcThunk.fold(() => {
29289        const cancelProgress = startProgress(editor);
29290        loadContentCss(editor).then(() => {
29291          initEditorWithInitialContent(editor);
29292          cancelProgress();
29293        });
29294      }, setupRtc => {
29295        editor.setProgressState(true);
29296        loadContentCss(editor).then(() => {
29297          setupRtc().then(_rtcMode => {
29298            editor.setProgressState(false);
29299            initEditorWithInitialContent(editor);
29300            bindEvents(editor);
29301          }, err => {
29302            editor.notificationManager.open({
29303              type: 'error',
29304              text: String(err)
29305            });
29306            initEditorWithInitialContent(editor);
29307            bindEvents(editor);
29308          });
29309        });
29310      });
29311    };
29312
29313    const filter = always;
29314    const bind = (element, event, handler) => bind$2(element, event, filter, handler);
29315
29316    const DOM$5 = DOMUtils.DOM;
29317    const createIframeElement = (id, title, customAttrs, tabindex) => {
29318      const iframe = SugarElement.fromTag('iframe');
29319      tabindex.each(t => set$4(iframe, 'tabindex', t));
29320      setAll$1(iframe, customAttrs);
29321      setAll$1(iframe, {
29322        id: id + '_ifr',
29323        frameBorder: '0',
29324        allowTransparency: 'true',
29325        title
29326      });
29327      add$2(iframe, 'tox-edit-area__iframe');
29328      return iframe;
29329    };
29330    const getIframeHtml = editor => {
vendor: 5,279 bytes, lines 29331-29461
29331      let iframeHTML = getDocType(editor) + '<html><head>';
29332      if (getDocumentBaseUrl(editor) !== editor.documentBaseUrl) {
29333        iframeHTML += '<base href="' + editor.documentBaseURI.getURI() + '" />';
29334      }
29335      iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
29336      const bodyId = getBodyId(editor);
29337      const bodyClass = getBodyClass(editor);
29338      const translatedAriaText = editor.translate(getIframeAriaText(editor));
29339      if (getContentSecurityPolicy(editor)) {
29340        iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + getContentSecurityPolicy(editor) + '" />';
29341      }
29342      iframeHTML += '</head>' + `<body id="${ bodyId }" class="mce-content-body ${ bodyClass }" data-id="${ editor.id }" aria-label="${ translatedAriaText }">` + '<br>' + '</body></html>';
29343      return iframeHTML;
29344    };
29345    const createIframe = (editor, boxInfo) => {
29346      const iframeTitle = Env.browser.isFirefox() ? getIframeAriaText(editor) : 'Rich Text Area';
29347      const translatedTitle = editor.translate(iframeTitle);
29348      const tabindex = getOpt(SugarElement.fromDom(editor.getElement()), 'tabindex').bind(toInt);
29349      const ifr = createIframeElement(editor.id, translatedTitle, getIframeAttrs(editor), tabindex).dom;
29350      ifr.onload = () => {
29351        ifr.onload = null;
29352        editor.dispatch('load');
29353      };
29354      editor.contentAreaContainer = boxInfo.iframeContainer;
29355      editor.iframeElement = ifr;
29356      editor.iframeHTML = getIframeHtml(editor);
29357      DOM$5.add(boxInfo.iframeContainer, ifr);
29358    };
29359    const setupIframeBody = editor => {
29360      const iframe = editor.iframeElement;
29361      const ready = () => {
29362        editor.contentDocument = iframe.contentDocument;
29363        contentBodyLoaded(editor);
29364      };
29365      if (shouldUseDocumentWrite(editor) || Env.browser.isFirefox()) {
29366        const doc = editor.getDoc();
29367        doc.open();
29368        doc.write(editor.iframeHTML);
29369        doc.close();
29370        ready();
29371      } else {
29372        const binder = bind(SugarElement.fromDom(iframe), 'load', () => {
29373          binder.unbind();
29374          ready();
29375        });
29376        iframe.srcdoc = editor.iframeHTML;
29377      }
29378    };
29379    const init$1 = (editor, boxInfo) => {
29380      createIframe(editor, boxInfo);
29381      if (boxInfo.editorContainer) {
29382        boxInfo.editorContainer.style.display = editor.orgDisplay;
29383        editor.hidden = DOM$5.isHidden(boxInfo.editorContainer);
29384      }
29385      editor.getElement().style.display = 'none';
29386      DOM$5.setAttrib(editor.id, 'aria-hidden', 'true');
29387      editor.getElement().style.visibility = editor.orgVisibility;
29388      setupIframeBody(editor);
29389    };
29390
29391    const DOM$4 = DOMUtils.DOM;
29392    const initPlugin = (editor, initializedPlugins, plugin) => {
29393      const Plugin = PluginManager.get(plugin);
29394      const pluginUrl = PluginManager.urls[plugin] || editor.documentBaseUrl.replace(/\/$/, '');
29395      plugin = Tools.trim(plugin);
29396      if (Plugin && Tools.inArray(initializedPlugins, plugin) === -1) {
29397        if (editor.plugins[plugin]) {
29398          return;
29399        }
29400        try {
29401          const pluginInstance = Plugin(editor, pluginUrl) || {};
29402          editor.plugins[plugin] = pluginInstance;
29403          if (isFunction(pluginInstance.init)) {
29404            pluginInstance.init(editor, pluginUrl);
29405            initializedPlugins.push(plugin);
29406          }
29407        } catch (e) {
29408          pluginInitError(editor, plugin, e);
29409        }
29410      }
29411    };
29412    const trimLegacyPrefix = name => {
29413      return name.replace(/^\-/, '');
29414    };
29415    const initPlugins = editor => {
29416      const initializedPlugins = [];
29417      each$e(getPlugins(editor), name => {
29418        initPlugin(editor, initializedPlugins, trimLegacyPrefix(name));
29419      });
29420    };
29421    const initIcons = editor => {
29422      const iconPackName = Tools.trim(getIconPackName(editor));
29423      const currentIcons = editor.ui.registry.getAll().icons;
29424      const loadIcons = {
29425        ...IconManager.get('default').icons,
29426        ...IconManager.get(iconPackName).icons
29427      };
29428      each$d(loadIcons, (svgData, icon) => {
29429        if (!has$2(currentIcons, icon)) {
29430          editor.ui.registry.addIcon(icon, svgData);
29431        }
29432      });
29433    };
29434    const initTheme = editor => {
29435      const theme = getTheme(editor);
29436      if (isString(theme)) {
29437        const Theme = ThemeManager.get(theme);
29438        editor.theme = Theme(editor, ThemeManager.urls[theme]) || {};
29439        if (isFunction(editor.theme.init)) {
29440          editor.theme.init(editor, ThemeManager.urls[theme] || editor.documentBaseUrl.replace(/\/$/, ''));
29441        }
29442      } else {
29443        editor.theme = {};
29444      }
29445    };
29446    const initModel = editor => {
29447      const model = getModel(editor);
29448      const Model = ModelManager.get(model);
29449      editor.model = Model(editor, ModelManager.urls[model]);
29450    };
29451    const renderFromLoadedTheme = editor => {
29452      const render = editor.theme.renderUI;
29453      return render ? render() : renderThemeFalse(editor);
29454    };
29455    const renderFromThemeFunc = editor => {
29456      const elm = editor.getElement();
29457      const theme = getTheme(editor);
29458      const info = theme(editor, elm);
29459      if (info.editorContainer.nodeType) {
29460        info.editorContainer.id = info.editorContainer.id || editor.id + '_parent';
29461      }
29462      if (info.iframeContainer && info.iframeContainer.nodeType) {
29463        info.iframeContainer.id = info.iframeContainer.id || editor.id + '_iframecontainer';
29464      }
29465      info.height = info.iframeHeight ? info.iframeHeight : elm.offsetHeight;
29466      return info;
29467    };
29468    const createThemeFalseResult = (element, iframe) => {
29469      return {
29470        editorContainer: element,
29471        iframeContainer: iframe,
29472        api: {}
29473      };
29474    };
29475    const renderThemeFalseIframe = targetElement => {
29476      const iframeContainer = DOM$4.create('div');
29477      DOM$4.insertAfter(iframeContainer, targetElement);
29478      return createThemeFalseResult(iframeContainer, iframeContainer);
29479    };
29480    const renderThemeFalse = editor => {
29481      const targetElement = editor.getElement();
29482      return editor.inline ? createThemeFalseResult(null) : renderThemeFalseIframe(targetElement);
29483    };
29484    const renderThemeUi = editor => {
29485      const elm = editor.getElement();
29486      editor.orgDisplay = elm.style.display;
29487      if (isString(getTheme(editor))) {
29488        return renderFromLoadedTheme(editor);
29489      } else if (isFunction(getTheme(editor))) {
29490        return renderFromThemeFunc(editor);
29491      } else {
29492        return renderThemeFalse(editor);
29493      }
29494    };
29495    const augmentEditorUiApi = (editor, api) => {
29496      const uiApiFacade = {
29497        show: Optional.from(api.show).getOr(noop),
29498        hide: Optional.from(api.hide).getOr(noop),
29499        isEnabled: Optional.from(api.isEnabled).getOr(always),
29500        setEnabled: state => {
29501          const shouldSkip = state && (editor.mode.get() === 'readonly' || isDisabled(editor));
29502          if (!shouldSkip
vendor: 5,510 bytes, lines 29502-29644
29502) {
29503            Optional.from(api.setEnabled).each(f => f(state));
29504          }
29505        }
29506      };
29507      editor.ui = {
29508        ...editor.ui,
29509        ...uiApiFacade
29510      };
29511    };
29512    const init = async editor => {
29513      editor.dispatch('ScriptsLoaded');
29514      initIcons(editor);
29515      initTheme(editor);
29516      initModel(editor);
29517      initPlugins(editor);
29518      const renderInfo = await renderThemeUi(editor);
29519      augmentEditorUiApi(editor, Optional.from(renderInfo.api).getOr({}));
29520      editor.editorContainer = renderInfo.editorContainer;
29521      appendContentCssFromSettings(editor);
29522      if (editor.inline) {
29523        contentBodyLoaded(editor);
29524      } else {
29525        init$1(editor, {
29526          editorContainer: renderInfo.editorContainer,
29527          iframeContainer: renderInfo.iframeContainer
29528        });
29529      }
29530    };
29531
29532    const DOM$3 = DOMUtils.DOM;
29533    const hasSkipLoadPrefix = name => name.charAt(0) === '-';
29534    const loadLanguage = (scriptLoader, editor) => {
29535      const languageCode = getLanguageCode(editor);
29536      const languageUrl = getLanguageUrl(editor);
29537      if (!I18n.hasCode(languageCode) && languageCode !== 'en') {
29538        const url = isNotEmpty(languageUrl) ? languageUrl : `${ editor.editorManager.baseURL }/langs/${ languageCode }.js`;
29539        scriptLoader.add(url).catch(() => {
29540          languageLoadError(editor, url, languageCode);
29541        });
29542      }
29543    };
29544    const loadTheme = (editor, suffix) => {
29545      const theme = getTheme(editor);
29546      if (isString(theme) && !hasSkipLoadPrefix(theme) && !has$2(ThemeManager.urls, theme)) {
29547        const themeUrl = getThemeUrl(editor);
29548        const url = themeUrl ? editor.documentBaseURI.toAbsolute(themeUrl) : `themes/${ theme }/theme${ suffix }.js`;
29549        ThemeManager.load(theme, url).catch(() => {
29550          themeLoadError(editor, url, theme);
29551        });
29552      }
29553    };
29554    const loadModel = (editor, suffix) => {
29555      const model = getModel(editor);
29556      if (model !== 'plugin' && !has$2(ModelManager.urls, model)) {
29557        const modelUrl = getModelUrl(editor);
29558        const url = isString(modelUrl) ? editor.documentBaseURI.toAbsolute(modelUrl) : `models/${ model }/model${ suffix }.js`;
29559        ModelManager.load(model, url).catch(() => {
29560          modelLoadError(editor, url, model);
29561        });
29562      }
29563    };
29564    const getIconsUrlMetaFromUrl = editor => Optional.from(getIconsUrl(editor)).filter(isNotEmpty).map(url => ({
29565      url,
29566      name: Optional.none()
29567    }));
29568    const getIconsUrlMetaFromName = (editor, name, suffix) => Optional.from(name).filter(name => isNotEmpty(name) && !IconManager.has(name)).map(name => ({
29569      url: `${ editor.editorManager.baseURL }/icons/${ name }/icons${ suffix }.js`,
29570      name: Optional.some(name)
29571    }));
29572    const loadIcons = (scriptLoader, editor, suffix) => {
29573      const defaultIconsUrl = getIconsUrlMetaFromName(editor, 'default', suffix);
29574      const customIconsUrl = getIconsUrlMetaFromUrl(editor).orThunk(() => getIconsUrlMetaFromName(editor, getIconPackName(editor), ''));
29575      each$e(cat([
29576        defaultIconsUrl,
29577        customIconsUrl
29578      ]), urlMeta => {
29579        scriptLoader.add(urlMeta.url).catch(() => {
29580          iconsLoadError(editor, urlMeta.url, urlMeta.name.getOrUndefined());
29581        });
29582      });
29583    };
29584    const loadPlugins = (editor, suffix) => {
29585      const loadPlugin = (name, url) => {
29586        PluginManager.load(name, url).catch(() => {
29587          pluginLoadError(editor, url, name);
29588        });
29589      };
29590      each$d(getExternalPlugins$1(editor), (url, name) => {
29591        loadPlugin(name, url);
29592        editor.options.set('plugins', getPlugins(editor).concat(name));
29593      });
29594      each$e(getPlugins(editor), plugin => {
29595        plugin = Tools.trim(plugin);
29596        if (plugin && !PluginManager.urls[plugin] && !hasSkipLoadPrefix(plugin)) {
29597          loadPlugin(plugin, `plugins/${ plugin }/plugin${ suffix }.js`);
29598        }
29599      });
29600    };
29601    const isThemeLoaded = editor => {
29602      const theme = getTheme(editor);
29603      return !isString(theme) || isNonNullable(ThemeManager.get(theme));
29604    };
29605    const isModelLoaded = editor => {
29606      const model = getModel(editor);
29607      return isNonNullable(ModelManager.get(model));
29608    };
29609    const loadScripts = (editor, suffix) => {
29610      const scriptLoader = ScriptLoader.ScriptLoader;
29611      const initEditor = () => {
29612        if (!editor.removed && isThemeLoaded(editor) && isModelLoaded(editor)) {
29613          init(editor);
29614        }
29615      };
29616      loadTheme(editor, suffix);
29617      loadModel(editor, suffix);
29618      loadLanguage(scriptLoader, editor);
29619      loadIcons(scriptLoader, editor, suffix);
29620      loadPlugins(editor, suffix);
29621      scriptLoader.loadQueue().then(initEditor, initEditor);
29622    };
29623    const getStyleSheetLoader = (element, editor) => instance.forElement(element, {
29624      contentCssCors: hasContentCssCors(editor),
29625      referrerPolicy: getReferrerPolicy(editor)
29626    });
29627    const render = editor => {
29628      const id = editor.id;
29629      I18n.setCode(getLanguageCode(editor));
29630      const readyHandler = () => {
29631        DOM$3.unbind(window, 'ready', readyHandler);
29632        editor.render();
29633      };
29634      if (!EventUtils.Event.domLoaded) {
29635        DOM$3.bind(window, 'ready', readyHandler);
29636        return;
29637      }
29638      if (!editor.getElement()) {
29639        return;
29640      }
29641      const element = SugarElement.fromDom(editor.getElement());
29642      const snapshot = clone$4(element);
29643      editor.on('remove', () => {
29644        eachr(element.dom.attributes, attr => remove$
vendor: 13,333 bytes, lines 29644-29993
296449(element, attr.name));
29645        setAll$1(element, snapshot);
29646      });
29647      editor.ui.styleSheetLoader = getStyleSheetLoader(element, editor);
29648      if (!isInline$1(editor)) {
29649        editor.orgVisibility = editor.getElement().style.visibility;
29650        editor.getElement().style.visibility = 'hidden';
29651      } else {
29652        editor.inline = true;
29653      }
29654      const form = editor.getElement().form || DOM$3.getParent(id, 'form');
29655      if (form) {
29656        editor.formElement = form;
29657        if (hasHiddenInput(editor) && !isTextareaOrInput(editor.getElement())) {
29658          DOM$3.insertAfter(DOM$3.create('input', {
29659            type: 'hidden',
29660            name: id
29661          }), id);
29662          editor.hasHiddenInput = true;
29663        }
29664        editor.formEventDelegate = e => {
29665          editor.dispatch(e.type, e);
29666        };
29667        DOM$3.bind(form, 'submit reset', editor.formEventDelegate);
29668        editor.on('reset', () => {
29669          editor.resetContent();
29670        });
29671        if (shouldPatchSubmit(editor) && !form.submit.nodeType && !form.submit.length && !form._mceOldSubmit) {
29672          form._mceOldSubmit = form.submit;
29673          form.submit = () => {
29674            editor.editorManager.triggerSave();
29675            editor.setDirty(false);
29676            return form._mceOldSubmit(form);
29677          };
29678        }
29679      }
29680      editor.windowManager = WindowManager(editor);
29681      editor.notificationManager = NotificationManager(editor);
29682      if (isEncodingXml(editor)) {
29683        editor.on('GetContent', e => {
29684          if (e.save) {
29685            e.content = DOM$3.encode(e.content);
29686          }
29687        });
29688      }
29689      if (shouldAddFormSubmitTrigger(editor)) {
29690        editor.on('submit', () => {
29691          if (editor.initialized) {
29692            editor.save();
29693          }
29694        });
29695      }
29696      if (shouldAddUnloadTrigger(editor)) {
29697        editor._beforeUnload = () => {
29698          if (editor.initialized && !editor.destroyed && !editor.isHidden()) {
29699            editor.save({
29700              format: 'raw',
29701              no_events: true,
29702              set_dirty: false
29703            });
29704          }
29705        };
29706        editor.editorManager.on('BeforeUnload', editor._beforeUnload);
29707      }
29708      editor.editorManager.add(editor);
29709      loadScripts(editor, editor.suffix);
29710    };
29711
29712    const setEditableRoot = (editor, state) => {
29713      if (editor._editableRoot !== state) {
29714        editor._editableRoot = state;
29715        if (!isDisabled(editor)) {
29716          editor.getBody().contentEditable = String(editor.hasEditableRoot());
29717          editor.nodeChanged();
29718        }
29719        fireEditableRootStateChange(editor, state);
29720      }
29721    };
29722    const hasEditableRoot = editor => editor._editableRoot;
29723
29724    const sectionResult = (sections, settings) => ({
29725      sections: constant(sections),
29726      options: constant(settings)
29727    });
29728    const deviceDetection = detect$1().deviceType;
29729    const isPhone = deviceDetection.isPhone();
29730    const isTablet = deviceDetection.isTablet();
29731    const normalizePlugins = plugins => {
29732      if (isNullable(plugins)) {
29733        return [];
29734      } else {
29735        const pluginNames = isArray$1(plugins) ? plugins : plugins.split(/[ ,]/);
29736        const trimmedPlugins = map$3(pluginNames, trim$4);
29737        return filter$5(trimmedPlugins, isNotEmpty);
29738      }
29739    };
29740    const extractSections = (keys, options) => {
29741      const result = bifilter(options, (value, key) => {
29742        return contains$2(keys, key);
29743      });
29744      return sectionResult(result.t, result.f);
29745    };
29746    const getSection = (sectionResult, name, defaults = {}) => {
29747      const sections = sectionResult.sections();
29748      const sectionOptions = get$a(sections, name).getOr({});
29749      return Tools.extend({}, defaults, sectionOptions);
29750    };
29751    const hasSection = (sectionResult, name) => {
29752      return has$2(sectionResult.sections(), name);
29753    };
29754    const getSectionConfig = (sectionResult, name) => {
29755      return hasSection(sectionResult, name) ? sectionResult.sections()[name] : {};
29756    };
29757    const getMobileOverrideOptions = (mobileOptions, isPhone) => {
29758      const defaultMobileOptions = {
29759        table_grid: false,
29760        object_resizing: false,
29761        resize: false,
29762        toolbar_mode: get$a(mobileOptions, 'toolbar_mode').getOr('scrolling'),
29763        toolbar_sticky: false
29764      };
29765      const defaultPhoneOptions = { menubar: false };
29766      return {
29767        ...defaultMobileOptions,
29768        ...isPhone ? defaultPhoneOptions : {}
29769      };
29770    };
29771    const getExternalPlugins = (overrideOptions, options) => {
29772      var _a;
29773      const userDefinedExternalPlugins = (_a = options.external_plugins) !== null && _a !== void 0 ? _a : {};
29774      if (overrideOptions && overrideOptions.external_plugins) {
29775        return Tools.extend({}, overrideOptions.external_plugins, userDefinedExternalPlugins);
29776      } else {
29777        return userDefinedExternalPlugins;
29778      }
29779    };
29780    const combinePlugins = (forcedPlugins, plugins) => [
29781      ...normalizePlugins(forcedPlugins),
29782      ...normalizePlugins(plugins)
29783    ];
29784    const getPlatformPlugins = (isMobileDevice, sectionResult, desktopPlugins, mobilePlugins) => {
29785      if (isMobileDevice && hasSection(sectionResult, 'mobile')) {
29786        return mobilePlugins;
29787      } else {
29788        return desktopPlugins;
29789      }
29790    };
29791    const processPlugins = (isMobileDevice, sectionResult, defaultOverrideOptions, options) => {
29792      const forcedPlugins = normalizePlugins(defaultOverrideOptions.forced_plugins);
29793      const desktopPlugins = normalizePlugins(options.plugins);
29794      const mobileConfig = getSectionConfig(sectionResult, 'mobile');
29795      const mobilePlugins = mobileConfig.plugins ? normalizePlugins(mobileConfig.plugins) : desktopPlugins;
29796      const platformPlugins = getPlatformPlugins(isMobileDevice, sectionResult, desktopPlugins, mobilePlugins);
29797      const combinedPlugins = combinePlugins(forcedPlugins, platformPlugins);
29798      return Tools.extend(options, {
29799        forced_plugins: forcedPlugins,
29800        plugins: combinedPlugins
29801      });
29802    };
29803    const isOnMobile = (isMobileDevice, sectionResult) => {
29804      return isMobileDevice && hasSection(sectionResult, 'mobile');
29805    };
29806    const combineOptions = (isMobileDevice, isPhone, defaultOptions, defaultOverrideOptions, options) => {
29807      var _a;
29808      const deviceOverrideOptions = isMobileDevice ? { mobile: getMobileOverrideOptions((_a = options.mobile) !== null && _a !== void 0 ? _a : {}, isPhone) } : {};
29809      const sectionResult = extractSections(['mobile'], deepMerge(deviceOverrideOptions, options));
29810      const extendedOptions = Tools.extend(defaultOptions, defaultOverrideOptions, sectionResult.options(), isOnMobile(isMobileDevice, sectionResult) ? getSection(sectionResult, 'mobile') : {}, { external_plugins: getExternalPlugins(defaultOverrideOptions, sectionResult.options()) });
29811      return processPlugins(isMobileDevice, sectionResult, defaultOverrideOptions, extendedOptions);
29812    };
29813    const normalizeOptions = (defaultOverrideOptions, options) => {
29814      const copiedOptions = merge(options);
29815      return combineOptions(isPhone || isTablet, isPhone, copiedOptions, defaultOverrideOptions, copiedOptions);
29816    };
29817
29818    const addVisual = (editor, elm) => addVisual$1(editor, elm);
29819
29820    const registerExecCommands$2 = editor => {
29821      const toggleFormat = (name, value) => {
29822        editor.formatter.toggle(name, value);
29823        editor.nodeChanged();
29824      };
29825      const toggleAlign = align => () => {
29826        each$e('left,center,right,justify'.split(','), name => {
29827          if (align !== name) {
29828            editor.formatter.remove('align' + name);
29829          }
29830        });
29831        if (align !== 'none') {
29832          toggleFormat('align' + align);
29833        }
29834      };
29835      editor.editorCommands.addCommands({
29836        JustifyLeft: toggleAlign('left'),
29837        JustifyCenter: toggleAlign('center'),
29838        JustifyRight: toggleAlign('right'),
29839        JustifyFull: toggleAlign('justify'),
29840        JustifyNone: toggleAlign('none')
29841      });
29842    };
29843    const registerQueryStateCommands = editor => {
29844      const alignStates = name => () => {
29845        const selection = editor.selection;
29846        const nodes = selection.isCollapsed() ? [editor.dom.getParent(selection.getNode(), editor.dom.isBlock)] : selection.getSelectedBlocks();
29847        return exists(nodes, node => isNonNullable(editor.formatter.matchNode(node, name)));
29848      };
29849      editor.editorCommands.addCommands({
29850        JustifyLeft: alignStates('alignleft'),
29851        JustifyCenter: alignStates('aligncenter'),
29852        JustifyRight: alignStates('alignright'),
29853        JustifyFull: alignStates('alignjustify')
29854      }, 'state');
29855    };
29856    const registerCommands$a = editor => {
29857      registerExecCommands$2(editor);
29858      registerQueryStateCommands(editor);
29859    };
29860
29861    const registerCommands$9 = editor => {
29862      editor.editorCommands.addCommands({
29863        'Cut,Copy,Paste': command => {
29864          const doc = editor.getDoc();
29865          let failed;
29866          try {
29867            doc.execCommand(command);
29868          } catch (_a) {
29869            failed = true;
29870          }
29871          if (command === 'paste' && !doc.queryCommandEnabled(command)) {
29872            failed = true;
29873          }
29874          if (failed || !doc.queryCommandSupported(command)) {
29875            let msg = editor.translate(`Your browser doesn't support direct access to the clipboard. ` + 'Please use the Ctrl+X/C/V keyboard shortcuts instead.');
29876            if (Env.os.isMacOS() || Env.os.isiOS()) {
29877              msg = msg.replace(/Ctrl\+/g, '\u2318+');
29878            }
29879            editor.notificationManager.open({
29880              text: msg,
29881              type: 'error'
29882            });
29883          }
29884        }
29885      });
29886    };
29887
29888    const trimOrPadLeftRight = (dom, rng, html, schema) => {
29889      const root = SugarElement.fromDom(dom.getRoot());
29890      if (needsToBeNbspLeft(root, CaretPosition.fromRangeStart(rng), schema)) {
29891        html = html.replace(/^ /, '&nbsp;');
29892      } else {
29893        html = html.replace(/^&nbsp;/, ' ');
29894      }
29895      if (needsToBeNbspRight(root, CaretPosition.fromRangeEnd(rng), schema)) {
29896        html = html.replace(/(&nbsp;| )(<br( \/)>)?$/, '&nbsp;');
29897      } else {
29898        html = html.replace(/&nbsp;(<br( \/)?>)?$/, ' ');
29899      }
29900      return html;
29901    };
29902
29903    const processValue$1 = value => {
29904      if (typeof value !== 'string') {
29905        const details = Tools.extend({
29906          paste: value.paste,
29907          data: { paste: value.paste }
29908        }, value);
29909        return {
29910          content: value.content,
29911          details
29912        };
29913      }
29914      return {
29915        content: value,
29916        details: {}
29917      };
29918    };
29919    const trimOrPad = (editor, value) => {
29920      const selection = editor.selection;
29921      const dom = editor.dom;
29922      if (/^ | $/.test(value)) {
29923        return trimOrPadLeftRight(dom, selection.getRng(), value, editor.schema);
29924      } else {
29925        return value;
29926      }
29927    };
29928    const insertAtCaret = (editor, value) => {
29929      if (editor.selection.isEditable()) {
29930        const {content, details} = processValue$1(value);
29931        preProcessSetContent(editor, {
29932          ...details,
29933          content: trimOrPad(editor, content),
29934          format: 'html',
29935          set: false,
29936          selection: true
29937        }).each(args => {
29938          const insertedContent = insertContent$1(editor, args.content, details);
29939          postProcessSetContent(editor, insertedContent, args);
29940          editor.addVisual();
29941        });
29942      }
29943    };
29944
29945    const registerCommands$8 = editor => {
29946      editor.editorCommands.addCommands({
29947        mceCleanup: () => {
29948          const bm = editor.selection.getBookmark();
29949          editor.setContent(editor.getContent());
29950          editor.selection.moveToBookmark(bm);
29951        },
29952        insertImage: (_command, _ui, value) => {
29953          insertAtCaret(editor, editor.dom.createHTML('img', { src: value }));
29954        },
29955        insertHorizontalRule: () => {
29956          editor.execCommand('mceInsertContent', false, '<hr>');
29957        },
29958        insertText: (_command, _ui, value) => {
29959          insertAtCaret(editor, editor.dom.encode(value));
29960        },
29961        insertHTML: (_command, _ui, value) => {
29962          insertAtCaret(editor, value);
29963        },
29964        mceInsertContent: (_command, _ui, value) => {
29965          insertAtCaret(editor, value);
29966        },
29967        mceSetContent: (_command, _ui, value) => {
29968          editor.setContent(value);
29969        },
29970        mceReplaceContent: (_command, _ui, value) => {
29971          editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, editor.selection.getContent({ format: 'text' })));
29972        },
29973        mceNewDocument: () => {
29974          editor.setContent(getNewDocumentContent(editor));
29975        }
29976      });
29977    };
29978
29979    const legacyPropNames = {
29980      'font-size': 'size',
29981      'font-family': 'face'
29982    };
29983    const isFont = isTag('font');
29984    const getSpecifiedFontProp = (propName, rootElm, elm) => {
29985      const getProperty = elm => getRaw(elm, propName).orThunk(() => {
29986        if (isFont(elm)) {
29987          return get$a(legacyPropNames, propName).bind(legacyPropName => getOpt(elm, legacyPropName));
29988        } else {
29989          return Optional.none();
29990        }
29991      });
29992      const isRoot = elm => eq(SugarElement.fromDom(rootElm), elm);
29993      return closest$1(SugarElement.fromDom(elm), elm =>
vendor: 6,507 bytes, lines 29993-30150
29993 getProperty(elm), isRoot);
29994    };
29995    const normalizeFontFamily = fontFamily => fontFamily.replace(/[\'\"\\]/g, '').replace(/,\s+/g, ',');
29996    const getComputedFontProp = (propName, elm) => Optional.from(DOMUtils.DOM.getStyle(elm, propName, true));
29997    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('');
29998    const getFontSize = getFontProp('font-size');
29999    const getFontFamily = compose(normalizeFontFamily, getFontProp('font-family'));
30000
30001    const findFirstCaretElement = editor => firstPositionIn(editor.getBody()).bind(caret => {
30002      const container = caret.container();
30003      return Optional.from(isText$b(container) ? container.parentNode : container);
30004    });
30005    const getCaretElement = editor => Optional.from(editor.selection.getRng()).bind(rng => {
30006      const root = editor.getBody();
30007      const atStartOfNode = rng.startContainer === root && rng.startOffset === 0;
30008      return atStartOfNode ? Optional.none() : Optional.from(editor.selection.getStart(true));
30009    });
30010    const bindRange = (editor, binder) => getCaretElement(editor).orThunk(curry(findFirstCaretElement, editor)).map(SugarElement.fromDom).filter(isElement$7).bind(binder);
30011    const mapRange = (editor, mapper) => bindRange(editor, compose1(Optional.some, mapper));
30012
30013    const fromFontSizeNumber = (editor, value) => {
30014      if (/^[0-9.]+$/.test(value)) {
30015        const fontSizeNumber = parseInt(value, 10);
30016        if (fontSizeNumber >= 1 && fontSizeNumber <= 7) {
30017          const fontSizes = getFontStyleValues(editor);
30018          const fontClasses = getFontSizeClasses(editor);
30019          if (fontClasses.length > 0) {
30020            return fontClasses[fontSizeNumber - 1] || value;
30021          } else {
30022            return fontSizes[fontSizeNumber - 1] || value;
30023          }
30024        } else {
30025          return value;
30026        }
30027      } else {
30028        return value;
30029      }
30030    };
30031    const normalizeFontNames = font => {
30032      const fonts = font.split(/\s*,\s*/);
30033      return map$3(fonts, font => {
30034        if (font.indexOf(' ') !== -1 && !(startsWith(font, '"') || startsWith(font, `'`))) {
30035          return `'${ font }'`;
30036        } else {
30037          return font;
30038        }
30039      }).join(',');
30040    };
30041    const fontNameAction = (editor, value) => {
30042      const font = fromFontSizeNumber(editor, value);
30043      editor.formatter.toggle('fontname', { value: normalizeFontNames(font) });
30044      editor.nodeChanged();
30045    };
30046    const fontNameQuery = editor => mapRange(editor, elm => getFontFamily(editor.getBody(), elm.dom)).getOr('');
30047    const fontSizeAction = (editor, value) => {
30048      editor.formatter.toggle('fontsize', { value: fromFontSizeNumber(editor, value) });
30049      editor.nodeChanged();
30050    };
30051    const fontSizeQuery = editor => mapRange(editor, elm => getFontSize(editor.getBody(), elm.dom)).getOr('');
30052
30053    const lineHeightQuery = editor => mapRange(editor, elm => {
30054      const root = SugarElement.fromDom(editor.getBody());
30055      const specifiedStyle = closest$1(elm, elm => getRaw(elm, 'line-height'), curry(eq, root));
30056      const computedStyle = () => {
30057        const lineHeight = parseFloat(get$7(elm, 'line-height'));
30058        const fontSize = parseFloat(get$7(elm, 'font-size'));
30059        return String(lineHeight / fontSize);
30060      };
30061      return specifiedStyle.getOrThunk(computedStyle);
30062    }).getOr('');
30063    const lineHeightAction = (editor, lineHeight) => {
30064      editor.formatter.toggle('lineheight', { value: String(lineHeight) });
30065      editor.nodeChanged();
30066    };
30067
30068    const registerExecCommands$1 = editor => {
30069      const toggleFormat = (name, value) => {
30070        editor.formatter.toggle(name, value);
30071        editor.nodeChanged();
30072      };
30073      editor.editorCommands.addCommands({
30074        'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': command => {
30075          toggleFormat(command);
30076        },
30077        'ForeColor,HiliteColor': (command, _ui, value) => {
30078          toggleFormat(command, { value });
30079        },
30080        'BackColor': (_command, _ui, value) => {
30081          toggleFormat('hilitecolor', { value });
30082        },
30083        'FontName': (_command, _ui, value) => {
30084          fontNameAction(editor, value);
30085        },
30086        'FontSize': (_command, _ui, value) => {
30087          fontSizeAction(editor, value);
30088        },
30089        'LineHeight': (_command, _ui, value) => {
30090          lineHeightAction(editor, value);
30091        },
30092        'Lang': (command, _ui, lang) => {
30093          var _a;
30094          toggleFormat(command, {
30095            value: lang.code,
30096            customValue: (_a = lang.customCode) !== null && _a !== void 0 ? _a : null
30097          });
30098        },
30099        'RemoveFormat': command => {
30100          editor.formatter.remove(command);
30101        },
30102        'mceBlockQuote': () => {
30103          toggleFormat('blockquote');
30104        },
30105        'FormatBlock': (_command, _ui, value) => {
30106          toggleFormat(isString(value) ? value : 'p');
30107        },
30108        'mceToggleFormat': (_command, _ui, value) => {
30109          toggleFormat(value);
30110        }
30111      });
30112    };
30113    const registerQueryValueCommands = editor => {
30114      const isFormatMatch = name => editor.formatter.match(name);
30115      editor.editorCommands.addCommands({
30116        'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': command => isFormatMatch(command),
30117        'mceBlockQuote': () => isFormatMatch('blockquote')
30118      }, 'state');
30119      editor.editorCommands.addQueryValueHandler('FontName', () => fontNameQuery(editor));
30120      editor.editorCommands.addQueryValueHandler('FontSize', () => fontSizeQuery(editor));
30121      editor.editorCommands.addQueryValueHandler('LineHeight', () => lineHeightQuery(editor));
30122    };
30123    const registerCommands$7 = editor => {
30124      registerExecCommands$1(editor);
30125      registerQueryValueCommands(editor);
30126    };
30127
30128    const registerCommands$6 = editor => {
30129      editor.editorCommands.addCommands({
30130        mceAddUndoLevel: () => {
30131          editor.undoManager.add();
30132        },
30133        mceEndUndoLevel: () => {
30134          editor.undoManager.add();
30135        },
30136        Undo: () => {
30137          editor.undoManager.undo();
30138        },
30139        Redo: () => {
30140          editor.undoManager.redo();
30141        }
30142      });
30143    };
30144
30145    const registerCommands$5 = editor => {
30146      editor.editorCommands.addCommands({
30147        Indent: () => {
30148          indent(editor);
30149        },
30150        Outdent: () => {
vendor: 21,745 bytes, lines 30151-30790
30151          outdent(editor);
30152        }
30153      });
30154      editor.editorCommands.addCommands({ Outdent: () => canOutdent(editor) }, 'state');
30155    };
30156
30157    const registerCommands$4 = editor => {
30158      const applyLinkToSelection = (_command, _ui, value) => {
30159        if (editor.mode.isReadOnly()) {
30160          return;
30161        }
30162        const linkDetails = isString(value) ? { href: value } : value;
30163        const anchor = editor.dom.getParent(editor.selection.getNode(), 'a');
30164        if (isObject(linkDetails) && isString(linkDetails.href)) {
30165          linkDetails.href = linkDetails.href.replace(/ /g, '%20');
30166          if (!anchor || !linkDetails.href) {
30167            editor.formatter.remove('link');
30168          }
30169          if (linkDetails.href) {
30170            editor.formatter.apply('link', linkDetails, anchor);
30171          }
30172        }
30173      };
30174      editor.editorCommands.addCommands({
30175        unlink: () => {
30176          if (editor.selection.isEditable()) {
30177            if (editor.selection.isCollapsed()) {
30178              const elm = editor.dom.getParent(editor.selection.getStart(), 'a');
30179              if (elm) {
30180                editor.dom.remove(elm, true);
30181              }
30182              return;
30183            }
30184            editor.formatter.remove('link');
30185          }
30186        },
30187        mceInsertLink: applyLinkToSelection,
30188        createLink: applyLinkToSelection
30189      });
30190    };
30191
30192    const getTopParentBlock = (editor, node, root, container) => {
30193      const dom = editor.dom;
30194      const selector = node => dom.isBlock(node) && node.parentElement === root;
30195      const topParentBlock = selector(node) ? node : dom.getParent(container, selector, root);
30196      return Optional.from(topParentBlock).map(SugarElement.fromDom);
30197    };
30198    const insert = (editor, before) => {
30199      if (editor.mode.isReadOnly()) {
30200        return;
30201      }
30202      const dom = editor.dom;
30203      const rng = editor.selection.getRng();
30204      const node = before ? editor.selection.getStart() : editor.selection.getEnd();
30205      const container = before ? rng.startContainer : rng.endContainer;
30206      const root = getEditableRoot(dom, container);
30207      if (!root || !root.isContentEditable) {
30208        return;
30209      }
30210      const insertFn = before ? before$3 : after$4;
30211      const newBlockName = getForcedRootBlock(editor);
30212      getTopParentBlock(editor, node, root, container).each(parentBlock => {
30213        const newBlock = createNewBlock(editor, container, parentBlock.dom, root, false, newBlockName);
30214        insertFn(parentBlock, SugarElement.fromDom(newBlock));
30215        editor.selection.setCursorLocation(newBlock, 0);
30216        editor.dispatch('NewBlock', { newBlock });
30217        fireInputEvent(editor, 'insertParagraph');
30218      });
30219    };
30220    const insertBefore = editor => insert(editor, true);
30221    const insertAfter = editor => insert(editor, false);
30222
30223    const registerCommands$3 = editor => {
30224      editor.editorCommands.addCommands({
30225        InsertNewBlockBefore: () => {
30226          insertBefore(editor);
30227        },
30228        InsertNewBlockAfter: () => {
30229          insertAfter(editor);
30230        }
30231      });
30232    };
30233
30234    const registerCommands$2 = editor => {
30235      editor.editorCommands.addCommands({
30236        insertParagraph: () => {
30237          insertBreak(blockbreak, editor);
30238        },
30239        mceInsertNewLine: (_command, _ui, value) => {
30240          insert$1(editor, value);
30241        },
30242        InsertLineBreak: (_command, _ui, _value) => {
30243          insertBreak(linebreak, editor);
30244        }
30245      });
30246    };
30247
30248    const registerCommands$1 = editor => {
30249      editor.editorCommands.addCommands({
30250        mceSelectNodeDepth: (_command, _ui, value) => {
30251          let counter = 0;
30252          editor.dom.getParent(editor.selection.getNode(), node => {
30253            if (isElement$6(node) && counter++ === value) {
30254              editor.selection.select(node);
30255              return false;
30256            } else {
30257              return true;
30258            }
30259          }, editor.getBody());
30260        },
30261        mceSelectNode: (_command, _ui, value) => {
30262          editor.selection.select(value);
30263        },
30264        selectAll: () => {
30265          const editingHost = editor.dom.getParent(editor.selection.getStart(), isContentEditableTrue$3);
30266          if (editingHost) {
30267            const rng = editor.dom.createRng();
30268            rng.selectNodeContents(editingHost);
30269            editor.selection.setRng(rng);
30270          }
30271        }
30272      });
30273    };
30274
30275    const registerExecCommands = editor => {
30276      editor.editorCommands.addCommands({
30277        mceRemoveNode: (_command, _ui, value) => {
30278          const node = value !== null && value !== void 0 ? value : editor.selection.getNode();
30279          if (node !== editor.getBody()) {
30280            const bm = editor.selection.getBookmark();
30281            editor.dom.remove(node, true);
30282            editor.selection.moveToBookmark(bm);
30283          }
30284        },
30285        mcePrint: () => {
30286          editor.getWin().print();
30287        },
30288        mceFocus: (_command, _ui, value) => {
30289          focus(editor, value === true);
30290        },
30291        mceToggleVisualAid: () => {
30292          editor.hasVisual = !editor.hasVisual;
30293          editor.addVisual();
30294        }
30295      });
30296    };
30297    const registerCommands = editor => {
30298      registerCommands$a(editor);
30299      registerCommands$9(editor);
30300      registerCommands$6(editor);
30301      registerCommands$1(editor);
30302      registerCommands$8(editor);
30303      registerCommands$4(editor);
30304      registerCommands$5(editor);
30305      registerCommands$3(editor);
30306      registerCommands$2(editor);
30307      registerCommands$7(editor);
30308      registerExecCommands(editor);
30309    };
30310
30311    const selectionSafeCommands = ['toggleview'];
30312    const isSelectionSafeCommand = command => contains$2(selectionSafeCommands, command.toLowerCase());
30313    class EditorCommands {
30314      constructor(editor) {
30315        this.commands = {
30316          state: {},
30317          exec: {},
30318          value: {}
30319        };
30320        this.editor = editor;
30321      }
30322      execCommand(command, ui = false, value, args) {
30323        const editor = this.editor;
30324        const lowerCaseCommand = command.toLowerCase();
30325        const skipFocus = args === null || args === void 0 ? void 0 : args.skip_focus;
30326        if (editor.removed) {
30327          return false;
30328        }
30329        if (lowerCaseCommand !== 'mcefocus') {
30330          if (!/^(mceAddUndoLevel|mceEndUndoLevel)$/i.test(lowerCaseCommand) && !skipFocus) {
30331            editor.focus();
30332          } else {
30333            restore(editor);
30334          }
30335        }
30336        const eventArgs = editor.dispatch('BeforeExecCommand', {
30337          command,
30338          ui,
30339          value
30340        });
30341        if (eventArgs.isDefaultPrevented()) {
30342          return false;
30343        }
30344        const func = this.commands.exec[lowerCaseCommand];
30345        if (isFunction(func)) {
30346          func(lowerCaseCommand, ui, value);
30347          editor.dispatch('ExecCommand', {
30348            command,
30349            ui,
30350            value
30351          });
30352          return true;
30353        }
30354        return false;
30355      }
30356      queryCommandState(command) {
30357        if (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden() || this.editor.removed) {
30358          return false;
30359        }
30360        const lowerCaseCommand = command.toLowerCase();
30361        const func = this.commands.state[lowerCaseCommand];
30362        if (isFunction(func)) {
30363          return func(lowerCaseCommand);
30364        }
30365        return false;
30366      }
30367      queryCommandValue(command) {
30368        if (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden() || this.editor.removed) {
30369          return '';
30370        }
30371        const lowerCaseCommand = command.toLowerCase();
30372        const func = this.commands.value[lowerCaseCommand];
30373        if (isFunction(func)) {
30374          return func(lowerCaseCommand);
30375        }
30376        return '';
30377      }
30378      addCommands(commandList, type = 'exec') {
30379        const commands = this.commands;
30380        each$d(commandList, (callback, command) => {
30381          each$e(command.toLowerCase().split(','), command => {
30382            commands[type][command] = callback;
30383          });
30384        });
30385      }
30386      addCommand(command, callback, scope) {
30387        const lowerCaseCommand = command.toLowerCase();
30388        this.commands.exec[lowerCaseCommand] = (_command, ui, value) => callback.call(scope !== null && scope !== void 0 ? scope : this.editor, ui, value);
30389      }
30390      queryCommandSupported(command) {
30391        const lowerCaseCommand = command.toLowerCase();
30392        if (this.commands.exec[lowerCaseCommand]) {
30393          return true;
30394        } else {
30395          return false;
30396        }
30397      }
30398      addQueryStateHandler(command, callback, scope) {
30399        this.commands.state[command.toLowerCase()] = () => callback.call(scope !== null && scope !== void 0 ? scope : this.editor);
30400      }
30401      addQueryValueHandler(command, callback, scope) {
30402        this.commands.value[command.toLowerCase()] = () => callback.call(scope !== null && scope !== void 0 ? scope : this.editor);
30403      }
30404    }
30405
30406    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', ' ');
30407    class EventDispatcher {
30408      static isNative(name) {
30409        return !!nativeEvents[name.toLowerCase()];
30410      }
30411      constructor(settings) {
30412        this.bindings = {};
30413        this.settings = settings || {};
30414        this.scope = this.settings.scope || this;
30415        this.toggleEvent = this.settings.toggleEvent || never;
30416      }
30417      fire(name, args) {
30418        return this.dispatch(name, args);
30419      }
30420      dispatch(name, args) {
30421        const lcName = name.toLowerCase();
30422        const event = normalize$3(lcName, args !== null && args !== void 0 ? args : {}, this.scope);
30423        if (this.settings.beforeFire) {
30424          this.settings.beforeFire(event);
30425        }
30426        const handlers = this.bindings[lcName];
30427        if (handlers) {
30428          for (let i = 0, l = handlers.length; i < l; i++) {
30429            const callback = handlers[i];
30430            if (callback.removed) {
30431              continue;
30432            }
30433            if (callback.once) {
30434              this.off(lcName, callback.func);
30435            }
30436            if (event.isImmediatePropagationStopped()) {
30437              return event;
30438            }
30439            if (callback.func.call(this.scope, event) === false) {
30440              event.preventDefault();
30441              return event;
30442            }
30443          }
30444        }
30445        return event;
30446      }
30447      on(name, callback, prepend, extra) {
30448        if (callback === false) {
30449          callback = never;
30450        }
30451        if (callback) {
30452          const wrappedCallback = {
30453            func: callback,
30454            removed: false
30455          };
30456          if (extra) {
30457            Tools.extend(wrappedCallback, extra);
30458          }
30459          const names = name.toLowerCase().split(' ');
30460          let i = names.length;
30461          while (i--) {
30462            const currentName = names[i];
30463            let handlers = this.bindings[currentName];
30464            if (!handlers) {
30465              handlers = [];
30466              this.toggleEvent(currentName, true);
30467            }
30468            if (prepend) {
30469              handlers = [
30470                wrappedCallback,
30471                ...handlers
30472              ];
30473            } else {
30474              handlers = [
30475                ...handlers,
30476                wrappedCallback
30477              ];
30478            }
30479            this.bindings[currentName] = handlers;
30480          }
30481        }
30482        return this;
30483      }
30484      off(name, callback) {
30485        if (name) {
30486          const names = name.toLowerCase().split(' ');
30487          let i = names.length;
30488          while (i--) {
30489            const currentName = names[i];
30490            let handlers = this.bindings[currentName];
30491            if (!currentName) {
30492              each$d(this.bindings, (_value, bindingName) => {
30493                this.toggleEvent(bindingName, false);
30494                delete this.bindings[bindingName];
30495              });
30496              return this;
30497            }
30498            if (handlers) {
30499              if (!callback) {
30500                handlers.length = 0;
30501              } else {
30502                const filteredHandlers = partition$2(handlers, handler => handler.func === callback);
30503                handlers = filteredHandlers.fail;
30504                this.bindings[currentName] = handlers;
30505                each$e(filteredHandlers.pass, handler => {
30506                  handler.removed = true;
30507                });
30508              }
30509              if (!handlers.length) {
30510                this.toggleEvent(name, false);
30511                delete this.bindings[currentName];
30512              }
30513            }
30514          }
30515        } else {
30516          each$d(this.bindings, (_value, name) => {
30517            this.toggleEvent(name, false);
30518          });
30519          this.bindings = {};
30520        }
30521        return this;
30522      }
30523      once(name, callback, prepend) {
30524        return this.on(name, callback, prepend, { once: true });
30525      }
30526      has(name) {
30527        name = name.toLowerCase();
30528        const binding = this.bindings[name];
30529        return !(!binding || binding.length === 0);
30530      }
30531    }
30532
30533    const getEventDispatcher = obj => {
30534      if (!obj._eventDispatcher) {
30535        obj._eventDispatcher = new EventDispatcher({
30536          scope: obj,
30537          toggleEvent: (name, state) => {
30538            if (EventDispatcher.isNative(name) && obj.toggleNativeEvent) {
30539              obj.toggleNativeEvent(name, state);
30540            }
30541          }
30542        });
30543      }
30544      return obj._eventDispatcher;
30545    };
30546    const Observable = {
30547      fire(name, args, bubble) {
30548        return this.dispatch(name, args, bubble);
30549      },
30550      dispatch(name, args, bubble) {
30551        const self = this;
30552        if (self.removed && name !== 'remove' && name !== 'detach') {
30553          return normalize$3(name.toLowerCase(), args !== null && args !== void 0 ? args : {}, self);
30554        }
30555        const dispatcherArgs = getEventDispatcher(self).dispatch(name, args);
30556        if (bubble !== false && self.parent) {
30557          let parent = self.parent();
30558          while (parent && !dispatcherArgs.isPropagationStopped()) {
30559            parent.dispatch(name, dispatcherArgs, false);
30560            parent = parent.parent ? parent.parent() : undefined;
30561          }
30562        }
30563        return dispatcherArgs;
30564      },
30565      on(name, callback, prepend) {
30566        return getEventDispatcher(this).on(name, callback, prepend);
30567      },
30568      off(name, callback) {
30569        return getEventDispatcher(this).off(name, callback);
30570      },
30571      once(name, callback) {
30572        return getEventDispatcher(this).once(name, callback);
30573      },
30574      hasEventListeners(name) {
30575        return getEventDispatcher(this).has(name);
30576      }
30577    };
30578
30579    const DOM$2 = DOMUtils.DOM;
30580    let customEventRootDelegates;
30581    const getEventTarget = (editor, eventName) => {
30582      if (eventName === 'selectionchange') {
30583        return editor.getDoc();
30584      }
30585      if (!editor.inline && /^(?:mouse|touch|click|contextmenu|drop|dragover|dragend)/.test(eventName)) {
30586        return editor.getDoc().documentElement;
30587      }
30588      const eventRoot = getEventRoot(editor);
30589      if (eventRoot) {
30590        if (!editor.eventRoot) {
30591          editor.eventRoot = DOM$2.select(eventRoot)[0];
30592        }
30593        return editor.eventRoot;
30594      }
30595      return editor.getBody();
30596    };
30597    const isListening = editor => !editor.hidden && !isDisabled(editor);
30598    const fireEvent = (editor, eventName, e) => {
30599      if (isListening(editor)) {
30600        editor.dispatch(eventName, e);
30601      } else if (isDisabled(editor)) {
30602        processDisabledEvents(editor, e);
30603      }
30604    };
30605    const bindEventDelegate = (editor, eventName) => {
30606      if (!editor.delegates) {
30607        editor.delegates = {};
30608      }
30609      if (editor.delegates[eventName] || editor.removed) {
30610        return;
30611      }
30612      const eventRootElm = getEventTarget(editor, eventName);
30613      if (getEventRoot(editor)) {
30614        if (!customEventRootDelegates) {
30615          customEventRootDelegates = {};
30616          editor.editorManager.on('removeEditor', () => {
30617            if (!editor.editorManager.activeEditor) {
30618              if (customEventRootDelegates) {
30619                each$d(customEventRootDelegates, (_value, name) => {
30620                  editor.dom.unbind(getEventTarget(editor, name));
30621                });
30622                customEventRootDelegates = null;
30623              }
30624            }
30625          });
30626        }
30627        if (customEventRootDelegates[eventName]) {
30628          return;
30629        }
30630        const delegate = e => {
30631          const target = e.target;
30632          const editors = editor.editorManager.get();
30633          let i = editors.length;
30634          while (i--) {
30635            const body = editors[i].getBody();
30636            if (body === target || DOM$2.isChildOf(target, body)) {
30637              fireEvent(editors[i], eventName, e);
30638            }
30639          }
30640        };
30641        customEventRootDelegates[eventName] = delegate;
30642        DOM$2.bind(eventRootElm, eventName, delegate);
30643      } else {
30644        const delegate = e => {
30645          fireEvent(editor, eventName, e);
30646        };
30647        DOM$2.bind(eventRootElm, eventName, delegate);
30648        editor.delegates[eventName] = delegate;
30649      }
30650    };
30651    const EditorObservable = {
30652      ...Observable,
30653      bindPendingEventDelegates() {
30654        const self = this;
30655        Tools.each(self._pendingNativeEvents, name => {
30656          bindEventDelegate(self, name);
30657        });
30658      },
30659      toggleNativeEvent(name, state) {
30660        const self = this;
30661        if (name === 'focus' || name === 'blur') {
30662          return;
30663        }
30664        if (self.removed) {
30665          return;
30666        }
30667        if (state) {
30668          if (self.initialized) {
30669            bindEventDelegate(self, name);
30670          } else {
30671            if (!self._pendingNativeEvents) {
30672              self._pendingNativeEvents = [name];
30673            } else {
30674              self._pendingNativeEvents.push(name);
30675            }
30676          }
30677        } else if (self.initialized && self.delegates) {
30678          self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
30679          delete self.delegates[name];
30680        }
30681      },
30682      unbindAllNativeEvents() {
30683        const self = this;
30684        const body = self.getBody();
30685        const dom = self.dom;
30686        if (self.delegates) {
30687          each$d(self.delegates, (value, name) => {
30688            self.dom.unbind(getEventTarget(self, name), name, value);
30689          });
30690          delete self.delegates;
30691        }
30692        if (!self.inline && body && dom) {
30693          body.onload = null;
30694          dom.unbind(self.getWin());
30695          dom.unbind(self.getDoc());
30696        }
30697        if (dom) {
30698          dom.unbind(body);
30699          dom.unbind(self.getContainer());
30700        }
30701      }
30702    };
30703
30704    const stringListProcessor = value => {
30705      if (isString(value)) {
30706        return {
30707          value: value.split(/[ ,]/),
30708          valid: true
30709        };
30710      } else if (isArrayOf(value, isString)) {
30711        return {
30712          value,
30713          valid: true
30714        };
30715      } else {
30716        return {
30717          valid: false,
30718          message: `The value must be a string[] or a comma/space separated string.`
30719        };
30720      }
30721    };
30722    const getBuiltInProcessor = type => {
30723      const validator = (() => {
30724        switch (type) {
30725        case 'array':
30726          return isArray$1;
30727        case 'boolean':
30728          return isBoolean;
30729        case 'function':
30730          return isFunction;
30731        case 'number':
30732          return isNumber;
30733        case 'object':
30734          return isObject;
30735        case 'string':
30736          return isString;
30737        case 'string[]':
30738          return stringListProcessor;
30739        case 'object[]':
30740          return val => isArrayOf(val, isObject);
30741        case 'regexp':
30742          return val => is$4(val, RegExp);
30743        default:
30744          return always;
30745        }
30746      })();
30747      return value => processValue(value, validator, `The value must be a ${ type }.`);
30748    };
30749    const isBuiltInSpec = spec => isString(spec.processor);
30750    const getErrorMessage = (message, result) => {
30751      const additionalText = isEmpty$3(result.message) ? '' : `. ${ result.message }`;
30752      return message + additionalText;
30753    };
30754    const isValidResult = result => result.valid;
30755    const processValue = (value, processor, message = '') => {
30756      const result = processor(value);
30757      if (isBoolean(result)) {
30758        return result ? {
30759          value: value,
30760          valid: true
30761        } : {
30762          valid: false,
30763          message
30764        };
30765      } else {
30766        return result;
30767      }
30768    };
30769    const processDefaultValue = (name, defaultValue, processor) => {
30770      if (!isUndefined(defaultValue)) {
30771        const result = processValue(defaultValue, processor);
30772        if (isValidResult(result)) {
30773          return result.value;
30774        } else {
30775          console.error(getErrorMessage(`Invalid default value passed for the "${ name }" option`, result));
30776        }
30777      }
30778      return undefined;
30779    };
30780    const create$5 = (editor, initialOptions, rawInitialOptions = initialOptions) => {
30781      const registry = {};
30782      const values = {};
30783      const setValue = (name, value, processor) => {
30784        const result = processValue(value, processor);
30785        if (isValidResult(result)) {
30786          values[name] = result.value;
30787          return true;
30788        } else {
30789          console.warn(getErrorMessage(`Invalid value passed for the ${ name } option`, result));
30790          return false;
30791        }
30792      };
30793      const register = (name, spec) => {
30794        const processor = isBuiltInSpec(spec) ? getBuiltInProcessor(spec.processor) : spec.processor;
30795        const defaultValue = processDefaultValue(name, spec.default, processor);
30796        registry[name] = {
30797          ...spec,
30798          default: defaultValue,
30799          processor
30800        };
30801        const initValue = get$a(values, name).orThunk(() => get$a(initialOptions, name));
30802        initValue.each(value => setValue(name, value, processor));
30803      };
30804      const isRegistered = name => has$2(registry, name);
30805      const get = name => get$a(values, name).orThunk(() => get$a(registry, name).map(spec => spec.default)).getOrUndefined();
30806      const set = (name, value) => {
30807        if (!isRegistered(name)) {
30808          console.warn(`"${ name }" is not a registered option. Ensure the option has been registered before setting a value.`);
30809          return false;
30810        } else {
30811          const spec = registry[name];
30812          if (spec.immutable) {
30813            console.error(`"${ name }" is an immutable option and cannot be updated`);
30814            return false;
30815          } else {
30816            return setValue(name, value, spec.processor);
30817          }
30818        }
30819      };
30820      const unset = name => {
30821        const registered = isRegistered(name);
30822        if (registered) {
30823          delete values[name];
30824        }
30825        return registered;
30826      };
30827      const isSet = name => has$2(values, name);
30828      const debug = () => {
30829        try {
30830          console.log(JSON.parse(JSON.stringify(rawInitialOptions, (_key, value) => {
30831            if (isBoolean(value) || isNumber(value) || isString(value) || isNull(value) || isArray$1(value) || isPlainObject(value)) {
30832              return value;
30833            }
30834            return Object.prototype.toString.call(value);
30835          })));
30836        } catch (error) {
30837          console.error(error);
30838        }
30839      };
30840      return {
30841        register,
30842        isRegistered,
30843        get,
30844        set,
30845        unset,
30846        isSet,
30847        debug
30848      };
30849    };
30850
30851    const setContentEditable = (elm, state) => {
30852      elm.dom.contentEditable = state ? 'true' : 'false';
30853    };
30854    const toggleReadOnly = (editor, state) => {
30855      const body = SugarElement.fromDom(editor.getBody());
30856      if (state) {
30857        editor.readonly = true;
30858        if (editor.hasEditableRoot()) {
30859          setContentEditable(body, true);
30860        }
30861        disableEditor(editor);
30862      } else {
30863        editor.readonly = false;
30864        enableEditor(editor);
30865      }
30866    };
30867    const isReadOnly = editor => editor.readonly;
30868    const registerReadOnlyInputBlockers = editor => {
30869      editor.on('beforeinput paste cut dragend dragover draggesture dragdrop drop drag', e => {
30870        if (isReadOnly(editor)) {
30871          e.preventDefault();
30872        }
30873      });
30874      editor.on('BeforeExecCommand', e => {
30875        if ((e.command === 'Undo' || e.command === 'Redo') && isReadOnly(editor)) {
30876          e.preventDefault();
30877        }
30878      });
30879      editor.on('input', e => {
30880        if (!e.isComposing && isReadOnly(editor)) {
30881          const undoLevel = editor.undoManager.add();
30882          if (isNonNullable(undoLevel)) {
30883            editor.undoManager.undo();
30884          }
30885        }
30886      });
30887      editor.on('compositionend', () => {
30888        if (isReadOnly(editor)) {
30889          const undoLevel = editor.undoManager.add();
30890          if (isNonNullable(undoLevel)) {
30891            editor.undoManager.undo();
30892          }
30893        }
30894      });
30895    };
30896
30897    const defaultModes = [
30898      'design',
30899      'readonly'
30900    ];
30901    const switchToMode = (editor, activeMode, availableModes, mode) => {
30902      const oldMode = availableModes[activeMode.get()];
30903      const newMode = availableModes[mode];
vendor: 5,293 bytes, lines 30904-31076
30904      try {
30905        newMode.activate();
30906      } catch (e) {
30907        console.error(`problem while activating editor mode ${ mode }:`, e);
30908        return;
30909      }
30910      oldMode.deactivate();
30911      if (oldMode.editorReadOnly !== newMode.editorReadOnly) {
30912        toggleReadOnly(editor, newMode.editorReadOnly);
30913      }
30914      activeMode.set(mode);
30915      fireSwitchMode(editor, mode);
30916    };
30917    const setMode = (editor, availableModes, activeMode, mode) => {
30918      if (mode === activeMode.get() || editor.initialized && isDisabled(editor)) {
30919        return;
30920      } else if (!has$2(availableModes, mode)) {
30921        throw new Error(`Editor mode '${ mode }' is invalid`);
30922      }
30923      if (editor.initialized) {
30924        switchToMode(editor, activeMode, availableModes, mode);
30925      } else {
30926        editor.on('init', () => switchToMode(editor, activeMode, availableModes, mode));
30927      }
30928    };
30929    const registerMode = (availableModes, mode, api) => {
30930      if (contains$2(defaultModes, mode)) {
30931        throw new Error(`Cannot override default mode ${ mode }`);
30932      }
30933      return {
30934        ...availableModes,
30935        [mode]: {
30936          ...api,
30937          deactivate: () => {
30938            try {
30939              api.deactivate();
30940            } catch (e) {
30941              console.error(`problem while deactivating editor mode ${ mode }:`, e);
30942            }
30943          }
30944        }
30945      };
30946    };
30947
30948    const create$4 = editor => {
30949      const activeMode = Cell('design');
30950      const availableModes = Cell({
30951        design: {
30952          activate: noop,
30953          deactivate: noop,
30954          editorReadOnly: false
30955        },
30956        readonly: {
30957          activate: noop,
30958          deactivate: noop,
30959          editorReadOnly: true
30960        }
30961      });
30962      registerReadOnlyInputBlockers(editor);
30963      registerEventsAndFilters$1(editor);
30964      return {
30965        isReadOnly: () => isReadOnly(editor),
30966        set: mode => setMode(editor, availableModes.get(), activeMode, mode),
30967        get: () => activeMode.get(),
30968        register: (mode, api) => {
30969          availableModes.set(registerMode(availableModes.get(), mode, api));
30970        }
30971      };
30972    };
30973
30974    const each$2 = Tools.each, explode = Tools.explode;
30975    const keyCodeLookup = {
30976      f1: 112,
30977      f2: 113,
30978      f3: 114,
30979      f4: 115,
30980      f5: 116,
30981      f6: 117,
30982      f7: 118,
30983      f8: 119,
30984      f9: 120,
30985      f10: 121,
30986      f11: 122,
30987      f12: 123
30988    };
30989    const modifierNames = Tools.makeMap('alt,ctrl,shift,meta,access');
30990    const isModifier = key => key in modifierNames;
30991    const parseShortcut = pattern => {
30992      const shortcut = {};
30993      const isMac = Env.os.isMacOS() || Env.os.isiOS();
30994      each$2(explode(pattern.toLowerCase(), '+'), value => {
30995        if (isModifier(value)) {
30996          shortcut[value] = true;
30997        } else {
30998          if (/^[0-9]{2,}$/.test(value)) {
30999            shortcut.keyCode = parseInt(value, 10);
31000          } else {
31001            shortcut.charCode = value.charCodeAt(0);
31002            shortcut.keyCode = keyCodeLookup[value] || value.toUpperCase().charCodeAt(0);
31003          }
31004        }
31005      });
31006      const id = [shortcut.keyCode];
31007      let key;
31008      for (key in modifierNames) {
31009        if (shortcut[key]) {
31010          id.push(key);
31011        } else {
31012          shortcut[key] = false;
31013        }
31014      }
31015      shortcut.id = id.join(',');
31016      if (shortcut.access) {
31017        shortcut.alt = true;
31018        if (isMac) {
31019          shortcut.ctrl = true;
31020        } else {
31021          shortcut.shift = true;
31022        }
31023      }
31024      if (shortcut.meta) {
31025        if (isMac) {
31026          shortcut.meta = true;
31027        } else {
31028          shortcut.ctrl = true;
31029          shortcut.meta = false;
31030        }
31031      }
31032      return shortcut;
31033    };
31034    class Shortcuts {
31035      constructor(editor) {
31036        this.shortcuts = {};
31037        this.pendingPatterns = [];
31038        this.editor = editor;
31039        const self = this;
31040        editor.on('keyup keypress keydown', e => {
31041          if ((self.hasModifier(e) || self.isFunctionKey(e)) && !e.isDefaultPrevented()) {
31042            each$2(self.shortcuts, shortcut => {
31043              if (self.matchShortcut(e, shortcut)) {
31044                self.pendingPatterns = shortcut.subpatterns.slice(0);
31045                if (e.type === 'keydown') {
31046                  self.executeShortcutAction(shortcut);
31047                }
31048              }
31049            });
31050            if (self.matchShortcut(e, self.pendingPatterns[0])) {
31051              if (self.pendingPatterns.length === 1) {
31052                if (e.type === 'keydown') {
31053                  self.executeShortcutAction(self.pendingPatterns[0]);
31054                }
31055              }
31056              self.pendingPatterns.shift();
31057            }
31058          }
31059        });
31060      }
31061      add(pattern, desc, cmdFunc, scope) {
31062        const self = this;
31063        const func = self.normalizeCommandFunc(cmdFunc);
31064        each$2(explode(Tools.trim(pattern)), pattern => {
31065          const shortcut = self.createShortcut(pattern, desc, func, scope);
31066          self.shortcuts[shortcut.id] = shortcut;
31067        });
31068        return true;
31069      }
31070      remove(pattern) {
31071        const shortcut = this.createShortcut(pattern);
31072        if (this.shortcuts[shortcut.id]) {
31073          delete this.shortcuts[shortcut.id];
31074          return true;
31075        }
31076        return false;
vendor: 4,665 bytes, lines 31077-31217
31077      }
31078      normalizeCommandFunc(cmdFunc) {
31079        const self = this;
31080        const cmd = cmdFunc;
31081        if (typeof cmd === 'string') {
31082          return () => {
31083            self.editor.execCommand(cmd, false, null);
31084          };
31085        } else if (Tools.isArray(cmd)) {
31086          return () => {
31087            self.editor.execCommand(cmd[0], cmd[1], cmd[2]);
31088          };
31089        } else {
31090          return cmd;
31091        }
31092      }
31093      createShortcut(pattern, desc, cmdFunc, scope) {
31094        const shortcuts = Tools.map(explode(pattern, '>'), parseShortcut);
31095        shortcuts[shortcuts.length - 1] = Tools.extend(shortcuts[shortcuts.length - 1], {
31096          func: cmdFunc,
31097          scope: scope || this.editor
31098        });
31099        return Tools.extend(shortcuts[0], {
31100          desc: this.editor.translate(desc),
31101          subpatterns: shortcuts.slice(1)
31102        });
31103      }
31104      hasModifier(e) {
31105        return e.altKey || e.ctrlKey || e.metaKey;
31106      }
31107      isFunctionKey(e) {
31108        return e.type === 'keydown' && e.keyCode >= 112 && e.keyCode <= 123;
31109      }
31110      matchShortcut(e, shortcut) {
31111        if (!shortcut) {
31112          return false;
31113        }
31114        if (shortcut.ctrl !== e.ctrlKey || shortcut.meta !== e.metaKey) {
31115          return false;
31116        }
31117        if (shortcut.alt !== e.altKey || shortcut.shift !== e.shiftKey) {
31118          return false;
31119        }
31120        if (e.keyCode === shortcut.keyCode || e.charCode && e.charCode === shortcut.charCode) {
31121          e.preventDefault();
31122          return true;
31123        }
31124        return false;
31125      }
31126      executeShortcutAction(shortcut) {
31127        return shortcut.func ? shortcut.func.call(shortcut.scope) : null;
31128      }
31129    }
31130
31131    const create$3 = () => {
31132      const buttons = {};
31133      const menuItems = {};
31134      const popups = {};
31135      const icons = {};
31136      const contextMenus = {};
31137      const contextToolbars = {};
31138      const contexts = {};
31139      const sidebars = {};
31140      const views = {};
31141      const add = (collection, type) => (name, spec) => {
31142        collection[name.toLowerCase()] = {
31143          ...spec,
31144          type
31145        };
31146      };
31147      const addDefaulted = (collection, type) => (name, spec) => {
31148        collection[name.toLowerCase()] = {
31149          type,
31150          ...spec
31151        };
31152      };
31153      const addIcon = (name, svgData) => icons[name.toLowerCase()] = svgData;
31154      const addContext = (name, pred) => contexts[name.toLowerCase()] = pred;
31155      return {
31156        addButton: add(buttons, 'button'),
31157        addGroupToolbarButton: add(buttons, 'grouptoolbarbutton'),
31158        addToggleButton: add(buttons, 'togglebutton'),
31159        addMenuButton: add(buttons, 'menubutton'),
31160        addSplitButton: add(buttons, 'splitbutton'),
31161        addMenuItem: add(menuItems, 'menuitem'),
31162        addNestedMenuItem: add(menuItems, 'nestedmenuitem'),
31163        addToggleMenuItem: add(menuItems, 'togglemenuitem'),
31164        addAutocompleter: add(popups, 'autocompleter'),
31165        addContextMenu: add(contextMenus, 'contextmenu'),
31166        addContextToolbar: add(contextToolbars, 'contexttoolbar'),
31167        addContextForm: addDefaulted(contextToolbars, 'contextform'),
31168        addSidebar: add(sidebars, 'sidebar'),
31169        addView: add(views, 'views'),
31170        addIcon,
31171        addContext,
31172        getAll: () => ({
31173          buttons,
31174          menuItems,
31175          icons,
31176          popups,
31177          contextMenus,
31178          contextToolbars,
31179          sidebars,
31180          views,
31181          contexts
31182        })
31183      };
31184    };
31185
31186    const registry = () => {
31187      const bridge = create$3();
31188      return {
31189        addAutocompleter: bridge.addAutocompleter,
31190        addButton: bridge.addButton,
31191        addContextForm: bridge.addContextForm,
31192        addContextMenu: bridge.addContextMenu,
31193        addContextToolbar: bridge.addContextToolbar,
31194        addIcon: bridge.addIcon,
31195        addMenuButton: bridge.addMenuButton,
31196        addMenuItem: bridge.addMenuItem,
31197        addNestedMenuItem: bridge.addNestedMenuItem,
31198        addSidebar: bridge.addSidebar,
31199        addSplitButton: bridge.addSplitButton,
31200        addToggleButton: bridge.addToggleButton,
31201        addGroupToolbarButton: bridge.addGroupToolbarButton,
31202        addToggleMenuItem: bridge.addToggleMenuItem,
31203        addView: bridge.addView,
31204        addContext: bridge.addContext,
31205        getAll: bridge.getAll
31206      };
31207    };
31208
31209    const DOM$1 = DOMUtils.DOM;
31210    const extend = Tools.extend, each$1 = Tools.each;
31211    class Editor {
31212      constructor(id, options, editorManager) {
31213        this.plugins = {};
31214        this.contentCSS = [];
31215        this.contentStyles = [];
31216        this.loadedCSS = {};
31217        this.isNotDirty = false;
vendor: 2,009 bytes, lines 31218-31266
31218        this.composing = false;
31219        this.destroyed = false;
31220        this.hasHiddenInput = false;
31221        this.iframeElement = null;
31222        this.initialized = false;
31223        this.readonly = false;
31224        this.removed = false;
31225        this.startContent = '';
31226        this._pendingNativeEvents = [];
31227        this._skinLoaded = false;
31228        this._editableRoot = true;
31229        this.editorManager = editorManager;
31230        this.documentBaseUrl = editorManager.documentBaseURL;
31231        extend(this, EditorObservable);
31232        const self = this;
31233        this.id = id;
31234        this.hidden = false;
31235        const normalizedOptions = normalizeOptions(editorManager.defaultOptions, options);
31236        this.options = create$5(self, normalizedOptions, options);
31237        register$7(self);
31238        const getOption = this.options.get;
31239        if (getOption('deprecation_warnings')) {
31240          logWarnings(options, normalizedOptions);
31241        }
31242        const suffix = getOption('suffix');
31243        if (suffix) {
31244          editorManager.suffix = suffix;
31245        }
31246        this.suffix = editorManager.suffix;
31247        const baseUrl = getOption('base_url');
31248        if (baseUrl) {
31249          editorManager._setBaseUrl(baseUrl);
31250        }
31251        this.baseUri = editorManager.baseURI;
31252        const referrerPolicy = getReferrerPolicy(self);
31253        if (referrerPolicy) {
31254          ScriptLoader.ScriptLoader._setReferrerPolicy(referrerPolicy);
31255          DOMUtils.DOM.styleSheetLoader._setReferrerPolicy(referrerPolicy);
31256        }
31257        const contentCssCors = hasContentCssCors(self);
31258        if (isNonNullable(contentCssCors)) {
31259          DOMUtils.DOM.styleSheetLoader._setContentCssCors(contentCssCors);
31260        }
31261        AddOnManager.languageLoad = getOption('language_load');
31262        AddOnManager.baseURL = editorManager.baseURL;
31263        this.setDirty(false);
31264        this.documentBaseURI = new URI(getDocumentBaseUrl(self), { base_uri: this.baseUri });
31265        this.baseURI = this.baseUri;
31266        this.inline = isInline$1
vendor: 8,516 bytes, lines 31266-31547
31266(self);
31267        this.hasVisual = isVisualAidsEnabled(self);
31268        this.shortcuts = new Shortcuts(this);
31269        this.editorCommands = new EditorCommands(this);
31270        registerCommands(this);
31271        const cacheSuffix = getOption('cache_suffix');
31272        if (cacheSuffix) {
31273          Env.cacheSuffix = cacheSuffix.replace(/^[\?\&]+/, '');
31274        }
31275        this.ui = {
31276          registry: registry(),
31277          styleSheetLoader: undefined,
31278          show: noop,
31279          hide: noop,
31280          setEnabled: noop,
31281          isEnabled: always
31282        };
31283        this.mode = create$4(self);
31284        editorManager.dispatch('SetupEditor', { editor: this });
31285        const setupCallback = getSetupCallback(self);
31286        if (isFunction(setupCallback)) {
31287          setupCallback.call(self, self);
31288        }
31289      }
31290      render() {
31291        render(this);
31292      }
31293      focus(skipFocus) {
31294        this.execCommand('mceFocus', false, skipFocus);
31295      }
31296      hasFocus() {
31297        return hasFocus(this);
31298      }
31299      translate(text) {
31300        return I18n.translate(text);
31301      }
31302      getParam(name, defaultVal, type) {
31303        const options = this.options;
31304        if (!options.isRegistered(name)) {
31305          if (isNonNullable(type)) {
31306            options.register(name, {
31307              processor: type,
31308              default: defaultVal
31309            });
31310          } else {
31311            options.register(name, {
31312              processor: always,
31313              default: defaultVal
31314            });
31315          }
31316        }
31317        return !options.isSet(name) && !isUndefined(defaultVal) ? defaultVal : options.get(name);
31318      }
31319      hasPlugin(name, loaded) {
31320        const hasPlugin = contains$2(getPlugins(this), name);
31321        if (hasPlugin) {
31322          return loaded ? PluginManager.get(name) !== undefined : true;
31323        } else {
31324          return false;
31325        }
31326      }
31327      nodeChanged(args) {
31328        this._nodeChangeDispatcher.nodeChanged(args);
31329      }
31330      addCommand(name, callback, scope) {
31331        this.editorCommands.addCommand(name, callback, scope);
31332      }
31333      addQueryStateHandler(name, callback, scope) {
31334        this.editorCommands.addQueryStateHandler(name, callback, scope);
31335      }
31336      addQueryValueHandler(name, callback, scope) {
31337        this.editorCommands.addQueryValueHandler(name, callback, scope);
31338      }
31339      addShortcut(pattern, desc, cmdFunc, scope) {
31340        this.shortcuts.add(pattern, desc, cmdFunc, scope);
31341      }
31342      execCommand(cmd, ui, value, args) {
31343        return this.editorCommands.execCommand(cmd, ui, value, args);
31344      }
31345      queryCommandState(cmd) {
31346        return this.editorCommands.queryCommandState(cmd);
31347      }
31348      queryCommandValue(cmd) {
31349        return this.editorCommands.queryCommandValue(cmd);
31350      }
31351      queryCommandSupported(cmd) {
31352        return this.editorCommands.queryCommandSupported(cmd);
31353      }
31354      show() {
31355        const self = this;
31356        if (self.hidden) {
31357          self.hidden = false;
31358          if (self.inline) {
31359            self.getBody().contentEditable = 'true';
31360          } else {
31361            DOM$1.show(self.getContainer());
31362            DOM$1.hide(self.id);
31363          }
31364          self.load();
31365          self.dispatch('show');
31366        }
31367      }
31368      hide() {
31369        const self = this;
31370        if (!self.hidden) {
31371          self.save();
31372          if (self.inline) {
31373            self.getBody().contentEditable = 'false';
31374            if (self === self.editorManager.focusedEditor) {
31375              self.editorManager.focusedEditor = null;
31376            }
31377          } else {
31378            DOM$1.hide(self.getContainer());
31379            DOM$1.setStyle(self.id, 'display', self.orgDisplay);
31380          }
31381          self.hidden = true;
31382          self.dispatch('hide');
31383        }
31384      }
31385      isHidden() {
31386        return this.hidden;
31387      }
31388      setProgressState(state, time) {
31389        this.dispatch('ProgressState', {
31390          state,
31391          time
31392        });
31393      }
31394      load(args = {}) {
31395        const self = this;
31396        const elm = self.getElement();
31397        if (self.removed) {
31398          return '';
31399        }
31400        if (elm) {
31401          const loadArgs = {
31402            ...args,
31403            load: true
31404          };
31405          const value = isTextareaOrInput(elm) ? elm.value : elm.innerHTML;
31406          const html = self.setContent(value, loadArgs);
31407          if (!loadArgs.no_events) {
31408            self.dispatch('LoadContent', {
31409              ...loadArgs,
31410              element: elm
31411            });
31412          }
31413          return html;
31414        } else {
31415          return '';
31416        }
31417      }
31418      save(args = {}) {
31419        const self = this;
31420        let elm = self.getElement();
31421        if (!elm || !self.initialized || self.removed) {
31422          return '';
31423        }
31424        const getArgs = {
31425          ...args,
31426          save: true,
31427          element: elm
31428        };
31429        let html = self.getContent(getArgs);
31430        const saveArgs = {
31431          ...getArgs,
31432          content: html
31433        };
31434        if (!saveArgs.no_events) {
31435          self.dispatch('SaveContent', saveArgs);
31436        }
31437        if (saveArgs.format === 'raw') {
31438          self.dispatch('RawSaveContent', saveArgs);
31439        }
31440        html = saveArgs.content;
31441        if (!isTextareaOrInput(elm)) {
31442          if (args.is_removing || !self.inline) {
31443            elm.innerHTML = html;
31444          }
31445          const form = DOM$1.getParent(self.id, 'form');
31446          if (form) {
31447            each$1(form.elements, elm => {
31448              if (elm.name === self.id) {
31449                elm.value = html;
31450                return false;
31451              } else {
31452                return true;
31453              }
31454            });
31455          }
31456        } else {
31457          elm.value = html;
31458        }
31459        saveArgs.element = getArgs.element = elm = null;
31460        if (saveArgs.set_dirty !== false) {
31461          self.setDirty(false);
31462        }
31463        return html;
31464      }
31465      setContent(content, args) {
31466        return setContent(this, content, args);
31467      }
31468      getContent(args) {
31469        return getContent(this, args);
31470      }
31471      insertContent(content, args) {
31472        if (args) {
31473          content = extend({ content }, args);
31474        }
31475        this.execCommand('mceInsertContent', false, content);
31476      }
31477      resetContent(initialContent) {
31478        if (initialContent === undefined) {
31479          setContent(this, this.startContent, { format: 'raw' });
31480        } else {
31481          setContent(this, initialContent);
31482        }
31483        this.undoManager.reset();
31484        this.setDirty(false);
31485        this.nodeChanged();
31486      }
31487      isDirty() {
31488        return !this.isNotDirty;
31489      }
31490      setDirty(state) {
31491        const oldState = !this.isNotDirty;
31492        this.isNotDirty = !state;
31493        if (state && state !== oldState) {
31494          this.dispatch('dirty');
31495        }
31496      }
31497      getContainer() {
31498        const self = this;
31499        if (!self.container) {
31500          self.container = self.editorContainer || DOM$1.get(self.id + '_parent');
31501        }
31502        return self.container;
31503      }
31504      getContentAreaContainer() {
31505        return this.contentAreaContainer;
31506      }
31507      getElement() {
31508        if (!this.targetElm) {
31509          this.targetElm = DOM$1.get(this.id);
31510        }
31511        return this.targetElm;
31512      }
31513      getWin() {
31514        const self = this;
31515        if (!self.contentWindow) {
31516          const elm = self.iframeElement;
31517          if (elm) {
31518            self.contentWindow = elm.contentWindow;
31519          }
31520        }
31521        return self.contentWindow;
31522      }
31523      getDoc() {
31524        const self = this;
31525        if (!self.contentDocument) {
31526          const win = self.getWin();
31527          if (win) {
31528            self.contentDocument = win.document;
31529          }
31530        }
31531        return self.contentDocument;
31532      }
31533      getBody() {
31534        var _a, _b;
31535        const doc = this.getDoc();
31536        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;
31537      }
31538      convertURL(url, name, elm) {
31539        const self = this, getOption = self.options.get;
31540        const urlConverterCallback = getUrlConverterCallback(self);
31541        if (isFunction(urlConverterCallback)) {
31542          return urlConverterCallback.call(self, url, elm, true, name);
31543        }
31544        if (!getOption('convert_urls') || elm === 'link' || isObject(elm) && elm.nodeName === 'LINK' || url.indexOf('file:') === 0 || url.length === 0) {
31545          return url;
31546        }
31547        
vendor: 6,496 bytes, lines 31547-31730
31547const urlObject = new URI(url);
31548        if (urlObject.protocol !== 'http' && urlObject.protocol !== 'https' && urlObject.protocol !== '') {
31549          return url;
31550        }
31551        if (getOption('relative_urls')) {
31552          return self.documentBaseURI.toRelative(url);
31553        }
31554        url = self.documentBaseURI.toAbsolute(url, getOption('remove_script_host'));
31555        return url;
31556      }
31557      addVisual(elm) {
31558        addVisual(this, elm);
31559      }
31560      setEditableRoot(state) {
31561        setEditableRoot(this, state);
31562      }
31563      hasEditableRoot() {
31564        return hasEditableRoot(this);
31565      }
31566      remove() {
31567        remove$1(this);
31568      }
31569      destroy(automatic) {
31570        destroy(this, automatic);
31571      }
31572      uploadImages() {
31573        return this.editorUpload.uploadImages();
31574      }
31575      _scanForImages() {
31576        return this.editorUpload.scanForImages();
31577      }
31578    }
31579
31580    const DOM = DOMUtils.DOM;
31581    const each = Tools.each;
31582    let boundGlobalEvents = false;
31583    let beforeUnloadDelegate;
31584    let editors = [];
31585    const globalEventDelegate = e => {
31586      const type = e.type;
31587      each(EditorManager.get(), editor => {
31588        switch (type) {
31589        case 'scroll':
31590          editor.dispatch('ScrollWindow', e);
31591          break;
31592        case 'resize':
31593          editor.dispatch('ResizeWindow', e);
31594          break;
31595        }
31596      });
31597    };
31598    const toggleGlobalEvents = state => {
31599      if (state !== boundGlobalEvents) {
31600        const DOM = DOMUtils.DOM;
31601        if (state) {
31602          DOM.bind(window, 'resize', globalEventDelegate);
31603          DOM.bind(window, 'scroll', globalEventDelegate);
31604        } else {
31605          DOM.unbind(window, 'resize', globalEventDelegate);
31606          DOM.unbind(window, 'scroll', globalEventDelegate);
31607        }
31608        boundGlobalEvents = state;
31609      }
31610    };
31611    const removeEditorFromList = targetEditor => {
31612      const oldEditors = editors;
31613      editors = filter$5(editors, editor => {
31614        return targetEditor !== editor;
31615      });
31616      if (EditorManager.activeEditor === targetEditor) {
31617        EditorManager.activeEditor = editors.length > 0 ? editors[0] : null;
31618      }
31619      if (EditorManager.focusedEditor === targetEditor) {
31620        EditorManager.focusedEditor = null;
31621      }
31622      return oldEditors.length !== editors.length;
31623    };
31624    const purgeDestroyedEditor = editor => {
31625      if (editor && editor.initialized && !(editor.getContainer() || editor.getBody()).parentNode) {
31626        removeEditorFromList(editor);
31627        editor.unbindAllNativeEvents();
31628        editor.destroy(true);
31629        editor.removed = true;
31630      }
31631    };
31632    const isQuirksMode = document.compatMode !== 'CSS1Compat';
31633    const EditorManager = {
31634      ...Observable,
31635      baseURI: null,
31636      baseURL: null,
31637      defaultOptions: {},
31638      documentBaseURL: null,
31639      suffix: null,
31640      majorVersion: '7',
31641      minorVersion: '7.1',
31642      releaseDate: '2025-03-05',
31643      i18n: I18n,
31644      activeEditor: null,
31645      focusedEditor: null,
31646      setup() {
31647        const self = this;
31648        let baseURL = '';
31649        let suffix = '';
31650        let documentBaseURL = URI.getDocumentBaseUrl(document.location);
31651        if (/^[^:]+:\/\/\/?[^\/]+\//.test(documentBaseURL)) {
31652          documentBaseURL = documentBaseURL.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
31653          if (!/[\/\\]$/.test(documentBaseURL)) {
31654            documentBaseURL += '/';
31655          }
31656        }
31657        const preInit = window.tinymce || window.tinyMCEPreInit;
31658        if (preInit) {
31659          baseURL = preInit.base || preInit.baseURL;
31660          suffix = preInit.suffix;
31661        } else {
31662          const scripts = document.getElementsByTagName('script');
31663          for (let i = 0; i < scripts.length; i++) {
31664            const src = scripts[i].src || '';
31665            if (src === '') {
31666              continue;
31667            }
31668            const srcScript = src.substring(src.lastIndexOf('/'));
31669            if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
31670              if (srcScript.indexOf('.min') !== -1) {
31671                suffix = '.min';
31672              }
31673              baseURL = src.substring(0, src.lastIndexOf('/'));
31674              break;
31675            }
31676          }
31677          if (!baseURL && document.currentScript) {
31678            const src = document.currentScript.src;
31679            if (src.indexOf('.min') !== -1) {
31680              suffix = '.min';
31681            }
31682            baseURL = src.substring(0, src.lastIndexOf('/'));
31683          }
31684        }
31685        self.baseURL = new URI(documentBaseURL).toAbsolute(baseURL);
31686        self.documentBaseURL = documentBaseURL;
31687        self.baseURI = new URI(self.baseURL);
31688        self.suffix = suffix;
31689        setup$w(self);
31690      },
31691      overrideDefaults(defaultOptions) {
31692        const baseUrl = defaultOptions.base_url;
31693        if (baseUrl) {
31694          this._setBaseUrl(baseUrl);
31695        }
31696        const suffix = defaultOptions.suffix;
31697        if (suffix) {
31698          this.suffix = suffix;
31699        }
31700        this.defaultOptions = defaultOptions;
31701        const pluginBaseUrls = defaultOptions.plugin_base_urls;
31702        if (pluginBaseUrls !== undefined) {
31703          each$d(pluginBaseUrls, (pluginBaseUrl, pluginName) => {
31704            AddOnManager.PluginManager.urls[pluginName] = pluginBaseUrl;
31705          });
31706        }
31707      },
31708      init(options) {
31709        const self = this;
31710        let result;
31711        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', ' ');
31712        const isInvalidInlineTarget = (options, elm) => options.inline && elm.tagName.toLowerCase() in invalidInlineTargets;
31713        const createId = elm => {
31714          let id = elm.id;
31715          if (!id) {
31716            id = get$a(elm, 'name').filter(name => !DOM.get(name)).getOrThunk(DOM.uniqueId);
31717            elm.setAttribute('id', id);
31718          }
31719          return id;
31720        };
31721        const execCallback = name => {
31722          const callback = options[name];
31723          if (!callback) {
31724            return;
31725          }
31726          return callback.apply(self, []);
31727        };
31728        const findTargets = options => {
31729          if (Env.browser.isIE() || Env.browser.isEdge()) {
31730            initError('TinyMCE does not support the browser you are using. For a list of supported' + ' browsers please see: https://www.tiny.cloud/docs/tinymce/7
vendor: 10,689 bytes, lines 31730-32083
31730/support/#supportedwebbrowsers');
31731            return [];
31732          } else if (isQuirksMode) {
31733            initError('Failed to initialize the editor as the document is not in standards mode. ' + 'TinyMCE requires standards mode.');
31734            return [];
31735          } else if (isString(options.selector)) {
31736            return DOM.select(options.selector);
31737          } else if (isNonNullable(options.target)) {
31738            return [options.target];
31739          } else {
31740            return [];
31741          }
31742        };
31743        let provideResults = editors => {
31744          result = editors;
31745        };
31746        const initEditors = () => {
31747          let initCount = 0;
31748          const editors = [];
31749          let targets;
31750          const createEditor = (id, options, targetElm) => {
31751            const editor = new Editor(id, options, self);
31752            editors.push(editor);
31753            editor.on('init', () => {
31754              if (++initCount === targets.length) {
31755                provideResults(editors);
31756              }
31757            });
31758            editor.targetElm = editor.targetElm || targetElm;
31759            editor.render();
31760          };
31761          DOM.unbind(window, 'ready', initEditors);
31762          execCallback('onpageload');
31763          targets = unique$1(findTargets(options));
31764          Tools.each(targets, elm => {
31765            purgeDestroyedEditor(self.get(elm.id));
31766          });
31767          targets = Tools.grep(targets, elm => {
31768            return !self.get(elm.id);
31769          });
31770          if (targets.length === 0) {
31771            provideResults([]);
31772          } else {
31773            each(targets, elm => {
31774              if (isInvalidInlineTarget(options, elm)) {
31775                initError('Could not initialize inline editor on invalid inline target element', elm);
31776              } else {
31777                createEditor(createId(elm), options, elm);
31778              }
31779            });
31780          }
31781        };
31782        DOM.bind(window, 'ready', initEditors);
31783        return new Promise(resolve => {
31784          if (result) {
31785            resolve(result);
31786          } else {
31787            provideResults = editors => {
31788              resolve(editors);
31789            };
31790          }
31791        });
31792      },
31793      get(id) {
31794        if (arguments.length === 0) {
31795          return editors.slice(0);
31796        } else if (isString(id)) {
31797          return find$2(editors, editor => {
31798            return editor.id === id;
31799          }).getOr(null);
31800        } else if (isNumber(id)) {
31801          return editors[id] ? editors[id] : null;
31802        } else {
31803          return null;
31804        }
31805      },
31806      add(editor) {
31807        const self = this;
31808        const existingEditor = self.get(editor.id);
31809        if (existingEditor === editor) {
31810          return editor;
31811        }
31812        if (existingEditor === null) {
31813          editors.push(editor);
31814        }
31815        toggleGlobalEvents(true);
31816        self.activeEditor = editor;
31817        self.dispatch('AddEditor', { editor });
31818        if (!beforeUnloadDelegate) {
31819          beforeUnloadDelegate = e => {
31820            const event = self.dispatch('BeforeUnload');
31821            if (event.returnValue) {
31822              e.preventDefault();
31823              e.returnValue = event.returnValue;
31824              return event.returnValue;
31825            }
31826          };
31827          window.addEventListener('beforeunload', beforeUnloadDelegate);
31828        }
31829        return editor;
31830      },
31831      createEditor(id, options) {
31832        return this.add(new Editor(id, options, this));
31833      },
31834      remove(selector) {
31835        const self = this;
31836        let editor;
31837        if (!selector) {
31838          for (let i = editors.length - 1; i >= 0; i--) {
31839            self.remove(editors[i]);
31840          }
31841          return;
31842        }
31843        if (isString(selector)) {
31844          each(DOM.select(selector), elm => {
31845            editor = self.get(elm.id);
31846            if (editor) {
31847              self.remove(editor);
31848            }
31849          });
31850          return;
31851        }
31852        editor = selector;
31853        if (isNull(self.get(editor.id))) {
31854          return null;
31855        }
31856        if (removeEditorFromList(editor)) {
31857          self.dispatch('RemoveEditor', { editor });
31858        }
31859        if (editors.length === 0) {
31860          window.removeEventListener('beforeunload', beforeUnloadDelegate);
31861        }
31862        editor.remove();
31863        toggleGlobalEvents(editors.length > 0);
31864        return editor;
31865      },
31866      execCommand(cmd, ui, value) {
31867        var _a;
31868        const self = this;
31869        const editorId = isObject(value) ? (_a = value.id) !== null && _a !== void 0 ? _a : value.index : value;
31870        switch (cmd) {
31871        case 'mceAddEditor': {
31872            if (!self.get(editorId)) {
31873              const editorOptions = value.options;
31874              new Editor(editorId, editorOptions, self).render();
31875            }
31876            return true;
31877          }
31878        case 'mceRemoveEditor': {
31879            const editor = self.get(editorId);
31880            if (editor) {
31881              editor.remove();
31882            }
31883            return true;
31884          }
31885        case 'mceToggleEditor': {
31886            const editor = self.get(editorId);
31887            if (!editor) {
31888              self.execCommand('mceAddEditor', false, value);
31889              return true;
31890            }
31891            if (editor.isHidden()) {
31892              editor.show();
31893            } else {
31894              editor.hide();
31895            }
31896            return true;
31897          }
31898        }
31899        if (self.activeEditor) {
31900          return self.activeEditor.execCommand(cmd, ui, value);
31901        }
31902        return false;
31903      },
31904      triggerSave: () => {
31905        each(editors, editor => {
31906          editor.save();
31907        });
31908      },
31909      addI18n: (code, items) => {
31910        I18n.add(code, items);
31911      },
31912      translate: text => {
31913        return I18n.translate(text);
31914      },
31915      setActive(editor) {
31916        const activeEditor = this.activeEditor;
31917        if (this.activeEditor !== editor) {
31918          if (activeEditor) {
31919            activeEditor.dispatch('deactivate', { relatedTarget: editor });
31920          }
31921          editor.dispatch('activate', { relatedTarget: activeEditor });
31922        }
31923        this.activeEditor = editor;
31924      },
31925      _setBaseUrl(baseUrl) {
31926        this.baseURL = new URI(this.documentBaseURL).toAbsolute(baseUrl.replace(/\/+$/, ''));
31927        this.baseURI = new URI(this.baseURL);
31928      }
31929    };
31930    EditorManager.setup();
31931
31932    const setup = () => {
31933      const dataValue = value$2();
31934      const FakeClipboardItem = items => ({
31935        items,
31936        types: keys(items),
31937        getType: type => get$a(items, type).getOrUndefined()
31938      });
31939      const write = data => {
31940        dataValue.set(data);
31941      };
31942      const read = () => dataValue.get().getOrUndefined();
31943      const clear = dataValue.clear;
31944      return {
31945        FakeClipboardItem,
31946        write,
31947        read,
31948        clear
31949      };
31950    };
31951    const FakeClipboard = setup();
31952
31953    const min = Math.min, max = Math.max, round = Math.round;
31954    const relativePosition = (rect, targetRect, rel) => {
31955      let x = targetRect.x;
31956      let y = targetRect.y;
31957      const w = rect.w;
31958      const h = rect.h;
31959      const targetW = targetRect.w;
31960      const targetH = targetRect.h;
31961      const relChars = (rel || '').split('');
31962      if (relChars[0] === 'b') {
31963        y += targetH;
31964      }
31965      if (relChars[1] === 'r') {
31966        x += targetW;
31967      }
31968      if (relChars[0] === 'c') {
31969        y += round(targetH / 2);
31970      }
31971      if (relChars[1] === 'c') {
31972        x += round(targetW / 2);
31973      }
31974      if (relChars[3] === 'b') {
31975        y -= h;
31976      }
31977      if (relChars[4] === 'r') {
31978        x -= w;
31979      }
31980      if (relChars[3] === 'c') {
31981        y -= round(h / 2);
31982      }
31983      if (relChars[4] === 'c') {
31984        x -= round(w / 2);
31985      }
31986      return create$2(x, y, w, h);
31987    };
31988    const findBestRelativePosition = (rect, targetRect, constrainRect, rels) => {
31989      for (let i = 0; i < rels.length; i++) {
31990        const pos = relativePosition(rect, targetRect, rels[i]);
31991        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) {
31992          return rels[i];
31993        }
31994      }
31995      return null;
31996    };
31997    const inflate = (rect, w, h) => {
31998      return create$2(rect.x - w, rect.y - h, rect.w + w * 2, rect.h + h * 2);
31999    };
32000    const intersect = (rect, cropRect) => {
32001      const x1 = max(rect.x, cropRect.x);
32002      const y1 = max(rect.y, cropRect.y);
32003      const x2 = min(rect.x + rect.w, cropRect.x + cropRect.w);
32004      const y2 = min(rect.y + rect.h, cropRect.y + cropRect.h);
32005      if (x2 - x1 < 0 || y2 - y1 < 0) {
32006        return null;
32007      }
32008      return create$2(x1, y1, x2 - x1, y2 - y1);
32009    };
32010    const clamp = (rect, clampRect, fixedSize) => {
32011      let x1 = rect.x;
32012      let y1 = rect.y;
32013      let x2 = rect.x + rect.w;
32014      let y2 = rect.y + rect.h;
32015      const cx2 = clampRect.x + clampRect.w;
32016      const cy2 = clampRect.y + clampRect.h;
32017      const underflowX1 = max(0, clampRect.x - x1);
32018      const underflowY1 = max(0, clampRect.y - y1);
32019      const overflowX2 = max(0, x2 - cx2);
32020      const overflowY2 = max(0, y2 - cy2);
32021      x1 += underflowX1;
32022      y1 += underflowY1;
32023      if (fixedSize) {
32024        x2 += underflowX1;
32025        y2 += underflowY1;
32026        x1 -= overflowX2;
32027        y1 -= overflowY2;
32028      }
32029      x2 -= overflowX2;
32030      y2 -= overflowY2;
32031      return create$2(x1, y1, x2 - x1, y2 - y1);
32032    };
32033    const create$2 = (x, y, w, h) => {
32034      return {
32035        x,
32036        y,
32037        w,
32038        h
32039      };
32040    };
32041    const fromClientRect = clientRect => {
32042      return create$2(clientRect.left, clientRect.top, clientRect.width, clientRect.height);
32043    };
32044    const Rect = {
32045      inflate,
32046      relativePosition,
32047      findBestRelativePosition,
32048      intersect,
32049      clamp,
32050      create: create$2,
32051      fromClientRect
32052    };
32053
32054    const awaiter = (resolveCb, rejectCb, timeout = 1000) => {
32055      let done = false;
32056      let timer = null;
32057      const complete = completer => (...args) => {
32058        if (!done) {
32059          done = true;
32060          if (timer !== null) {
32061            clearTimeout(timer);
32062            timer = null;
32063          }
32064          completer.apply(null, args);
32065        }
32066      };
32067      const resolve = complete(resolveCb);
32068      const reject = complete(rejectCb);
32069      const start = (...args) => {
32070        if (!done && timer === null) {
32071          timer = setTimeout(() => reject.apply(null, args), timeout);
32072        }
32073      };
32074      return {
32075        start,
32076        resolve,
32077        reject
32078      };
32079    };
32080    const create$1 = () => {
32081      const tasks = {};
32082      const resultFns = {};
32083      const 
vendor: 4,333 bytes, lines 32083-32258
32083resources = {};
32084      const load = (id, url) => {
32085        const loadErrMsg = `Script at URL "${ url }" failed to load`;
32086        const runErrMsg = `Script at URL "${ url }" did not call \`tinymce.Resource.add('${ id }', data)\` within 1 second`;
32087        if (tasks[id] !== undefined) {
32088          return tasks[id];
32089        } else {
32090          const task = new Promise((resolve, reject) => {
32091            const waiter = awaiter(resolve, reject);
32092            resultFns[id] = waiter.resolve;
32093            ScriptLoader.ScriptLoader.loadScript(url).then(() => waiter.start(runErrMsg), () => waiter.reject(loadErrMsg));
32094          });
32095          tasks[id] = task;
32096          return task;
32097        }
32098      };
32099      const add = (id, data) => {
32100        if (resultFns[id] !== undefined) {
32101          resultFns[id](data);
32102          delete resultFns[id];
32103        }
32104        tasks[id] = Promise.resolve(data);
32105        resources[id] = data;
32106      };
32107      const has = id => {
32108        return id in resources;
32109      };
32110      const unload = id => {
32111        delete tasks[id];
32112        delete resources[id];
32113      };
32114      const get = id => resources[id];
32115      return {
32116        load,
32117        add,
32118        has,
32119        get,
32120        unload
32121      };
32122    };
32123    const Resource = create$1();
32124
32125    const create = () => (() => {
32126      let data = {};
32127      let keys = [];
32128      const storage = {
32129        getItem: key => {
32130          const item = data[key];
32131          return item ? item : null;
32132        },
32133        setItem: (key, value) => {
32134          keys.push(key);
32135          data[key] = String(value);
32136        },
32137        key: index => {
32138          return keys[index];
32139        },
32140        removeItem: key => {
32141          keys = keys.filter(k => k === key);
32142          delete data[key];
32143        },
32144        clear: () => {
32145          keys = [];
32146          data = {};
32147        },
32148        length: 0
32149      };
32150      Object.defineProperty(storage, 'length', {
32151        get: () => keys.length,
32152        configurable: false,
32153        enumerable: false
32154      });
32155      return storage;
32156    })();
32157
32158    let localStorage;
32159    try {
32160      const test = '__storage_test__';
32161      localStorage = window.localStorage;
32162      localStorage.setItem(test, test);
32163      localStorage.removeItem(test);
32164    } catch (_a) {
32165      localStorage = create();
32166    }
32167    var LocalStorage = localStorage;
32168
32169    const publicApi = {
32170      geom: { Rect },
32171      util: {
32172        Delay,
32173        Tools,
32174        VK,
32175        URI,
32176        EventDispatcher,
32177        Observable,
32178        I18n,
32179        LocalStorage,
32180        ImageUploader
32181      },
32182      dom: {
32183        EventUtils,
32184        TreeWalker: DomTreeWalker,
32185        TextSeeker,
32186        DOMUtils,
32187        ScriptLoader,
32188        RangeUtils,
32189        Serializer: DomSerializer,
32190        StyleSheetLoader,
32191        ControlSelection,
32192        BookmarkManager,
32193        Selection: EditorSelection,
32194        Event: EventUtils.Event
32195      },
32196      html: {
32197        Styles,
32198        Entities,
32199        Node: AstNode,
32200        Schema,
32201        DomParser,
32202        Writer,
32203        Serializer: HtmlSerializer
32204      },
32205      Env,
32206      AddOnManager,
32207      Annotator,
32208      Formatter,
32209      UndoManager,
32210      EditorCommands,
32211      WindowManager,
32212      NotificationManager,
32213      EditorObservable,
32214      Shortcuts,
32215      Editor,
32216      FocusManager,
32217      EditorManager,
32218      DOM: DOMUtils.DOM,
32219      ScriptLoader: ScriptLoader.ScriptLoader,
32220      PluginManager,
32221      ThemeManager,
32222      ModelManager,
32223      IconManager,
32224      Resource,
32225      FakeClipboard,
32226      trim: Tools.trim,
32227      isArray: Tools.isArray,
32228      is: Tools.is,
32229      toArray: Tools.toArray,
32230      makeMap: Tools.makeMap,
32231      each: Tools.each,
32232      map: Tools.map,
32233      grep: Tools.grep,
32234      inArray: Tools.inArray,
32235      extend: Tools.extend,
32236      walk: Tools.walk,
32237      resolve: Tools.resolve,
32238      explode: Tools.explode,
32239      _addCacheSuffix: Tools._addCacheSuffix
32240    };
32241    const tinymce$1 = Tools.extend(EditorManager, publicApi);
32242
32243    const exportToModuleLoaders = tinymce => {
32244      if (typeof module === 'object') {
32245        try {
32246          module.exports = tinymce;
32247        } catch (_a) {
32248        }
32249      }
32250    };
32251    const exportToWindowGlobal = tinymce => {
32252      window.tinymce = tinymce;
32253      window.tinyMCE = tinymce;
32254    };
32255    exportToWindowGlobal(tinymce$1);
32256    exportToModuleLoaders(tinymce$1);
32257
32258})();

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.